最新消息:雨落星辰是一个专注网站SEO优化、网站SEO诊断、搜索引擎研究、网络营销推广、网站策划运营及站长类的自媒体原创博客

javascript - Build nested folder structure from path strings - Stack Overflow

programmeradmin2浏览0评论

How can I build a nested UL structure from an object of paths using JavaScript?

For example given the following array of paths:

var paths = [
  "d1/d2/d3/file1.txt",
  "d1/d2/d3/file2.txt",
];

I would like to build the following UL

<ul class="base-UL">
  <li class="folder">d1
    <ul>
      <li class="folder">d2
        <ul>
          <li class="folder">d3
            <ul>
              <li class="file" data-url="d1/d2/d3/file1.text">file1.text</li>
              <li class="file" data-url="d1/d2/d3/file2.text">file2.text</li>
            </ul>
          </li>
        </ul>
      </li>
    </ul>
  </li>
</ul>

How should I build a recursive function that does this?

Edit I was able to succefully write a function which does this however, I can't figure out how to get the full path as the data attribute in the file elements: See below:

function buildFromPathList(paths) {
  for (var i = 0, path; path = paths[i]; ++i) {
    var pathParts = path.split("/");
    var subObj = tree_;

    for (var j = 0, folderName; folderName = pathParts[j]; ++j) {
      if (!subObj[folderName]) {
        subObj[folderName] = j < pathParts.length - 1 ? {} : null;
      }

      subObj = subObj[folderName];
    }
  }

  return tree_;
}

function render(object) {
  for (var folder in object) {
    if (!object[folder]) {
      var name = folder.trim();
      html_ += '<li class="file>' + folder + '</li>';
    } else {
      html_ += '<li class="folder">' + folder + '<ul>';
      render(object[folder]);
      html_ += "</ul>";
    }
  }
}

var html_ = [];
render(buildFromPathList(paths));

How can I build a nested UL structure from an object of paths using JavaScript?

For example given the following array of paths:

var paths = [
  "d1/d2/d3/file1.txt",
  "d1/d2/d3/file2.txt",
];

I would like to build the following UL

<ul class="base-UL">
  <li class="folder">d1
    <ul>
      <li class="folder">d2
        <ul>
          <li class="folder">d3
            <ul>
              <li class="file" data-url="d1/d2/d3/file1.text">file1.text</li>
              <li class="file" data-url="d1/d2/d3/file2.text">file2.text</li>
            </ul>
          </li>
        </ul>
      </li>
    </ul>
  </li>
</ul>

How should I build a recursive function that does this?

Edit I was able to succefully write a function which does this however, I can't figure out how to get the full path as the data attribute in the file elements: See below:

function buildFromPathList(paths) {
  for (var i = 0, path; path = paths[i]; ++i) {
    var pathParts = path.split("/");
    var subObj = tree_;

    for (var j = 0, folderName; folderName = pathParts[j]; ++j) {
      if (!subObj[folderName]) {
        subObj[folderName] = j < pathParts.length - 1 ? {} : null;
      }

      subObj = subObj[folderName];
    }
  }

  return tree_;
}

function render(object) {
  for (var folder in object) {
    if (!object[folder]) {
      var name = folder.trim();
      html_ += '<li class="file>' + folder + '</li>';
    } else {
      html_ += '<li class="folder">' + folder + '<ul>';
      render(object[folder]);
      html_ += "</ul>";
    }
  }
}

var html_ = [];
render(buildFromPathList(paths));
Share Improve this question edited Oct 10, 2017 at 11:53 stevenferrer 2,6121 gold badge23 silver badges34 bronze badges asked Oct 30, 2014 at 4:44 user3143218user3143218 1,8165 gold badges34 silver badges48 bronze badges 3
  • so, what's your problem now? – Oki Erie Rinaldi Commented Oct 30, 2014 at 5:07
  • I can't get the full path of the file as a data-attribute. e.g "html + = "<li class="file" data-path="'+full_path+' – user3143218 Commented Oct 30, 2014 at 5:08
  • 1 I've replaced my example after I saw your edit. It should be more than enough to get you started. Enjoy! – istos Commented Oct 30, 2014 at 6:06
Add a comment  | 

2 Answers 2

Reset to default 14
var paths = [
    "d1/d2/d3/file1.txt",
    "d1/d2/d3/file2.txt",
];

I'd build a better data structure first:

var hierarchy = paths.reduce(function(hier,path){
    var x = hier;
    path.split('/').forEach(function(item){
        if(!x[item]){
            x[item] = {};
        }
        x = x[item];
    });
    x.path = path;
    return hier;
}, {});

And then use that to build the HTML (without indentation):

var makeul = function(hierarchy, classname){
    var dirs = Object.keys(hierarchy);
    var ul = '<ul';
    if(classname){
        ul += ' class="' + classname + '"';
    }
    ul += '>\n';
    dirs.forEach(function(dir){
        var path = hierarchy[dir].path;
        if(path){ // file
            ul += '<li class="file" data-url="' + path + '">' + dir + '</li>\n';
        }else{
            ul += '<li class="folder">' + dir + '\n';
            ul += makeul(hierarchy[dir]);
            ul += '</li>\n';
        }
    });
    ul += '</ul>\n';
    return ul;
};

makeul(hierarchy, 'base-UL');

I will start you with an example and see if you can figure out the HTML generation yourself.

You can also find this on Github: https://github.com/vasilionjea/treepath


The paths:

var paths = [
  "d1/d2/d3/file1.txt",
  "d1/d2/d3/file2.txt",
  "d2/d3/file3.txt",
  "d3/file4.txt",

  "d1/d2/first.png",
  "d2/second.png",

  "d1/photo1.jpg",
  "d1/photo2.jpg",

  "animate.gif"
];


Code to build a tree:

var tree = {
  // Represents the "root" directory, like in a filesystem.
  root: {
    absolute_path: '',
    files: []
  }
};

function buildTree(parts) {
  var lastDir = 'root';
  var abs_path = '';

  parts.forEach(function(name) {
    // It's a directory
    if (name.indexOf('.') === -1) {
      lastDir = name;
      abs_path += lastDir + '/';

      if (!tree[name]) {
        tree[name] = {
          absolute_path: abs_path,
          files: []
        };
      }
    } else {
      tree[lastDir].files.push(name);
    }
  });
}

paths.forEach(function(path, index, array) {
  buildTree(path.split('/'));
});


Now log the constructed tree:

console.log(tree);

// Output:
{
  "root": {
    "absolute_path": "",
    "files": [
      "animate.gif"
    ]
  },

  "d1": {
    "absolute_path": "d1/",
    "files": [
      "photo1.jpg",
      "photo2.jpg"
    ]
  },

  "d2": {
    "absolute_path": "d1/d2/",
    "files": [
      "first.png",
      "second.png"
    ]
  },

  "d3": {
    "absolute_path": "d1/d2/d3/",
    "files": [
      "file1.txt",
      "file2.txt",
      "file3.txt",
      "file4.txt"
    ]
  }
}
发布评论

评论列表(0)

  1. 暂无评论