General Info
Working on an online syntax highlighter with operational transformation for collaboration. The idea is that a single project has a filetree (pure html / css) on the left and the editor on the right. Users can create new files / directories as much as they want and obviously nest them.
The Problem
The files and directories are returned by the server as an object:
{
"files": ["index.html","panel.html"]
"directory1": {
"files": ["foo.html"]
"subdir1": {
"files": ["somefile.txt"]
}
"subdir2": {
"files": ["somefile.php","other.php"]
}
}
"directory2": {
"subdir1": {
"files": ["you_get_the_idea.txt"]
}
}
}
The object is correct. Each object within contains an array with the files for that directory and a nested object representing nested directories.
The problem is that I want to list the directories alphabetically on top and the files alphabetically within, just like any filebrowser does by default. For some reason, I can't get it done correctly.
What I've tried myself
// Containing the object above
const fileData = {};
let iterations = 0;
const iterate = (fileData) => {
Object.keys(fileData).forEach(key => {
// It's a directory
if (typeof fileData[key] === 'object' && fileData[key] !== null && key != 'files') {
html = '<li><input type="checkbox"/><span>' key '</span><ul>';
iterations ;
iterate(fileData[key]);
last = false;
}
// It's a file
else
{
for(let i = 0; i < fileData[key].length; i )
{
html = '<li><span>' fileData[key][i] '</span></li>';
}
for(let i = 0; i < iterations; i )
{
html = '</ul></li>';
}
iterations--;
}
});
}
In the above example, this would result in:
- index.html
- panel.html
- directory1
-- foo.html
-- subdir1
--- somefile.txt
--- subdir2
---- somefile.php
---- other.php
---- directory2
----- subdir1
------ you_get_the_idea.txt
Running example here: https://jsfiddle.net/jbvhyzu6/ (didn't put it here because the CSS code is way too long).
While it should result in:
- directory1
-- foo.html
-- subdir1
--- somefile.txt
-- subdir2
--- somefile.php
--- other.php
-- subdir2
--- subdir1
---- you_get_the_idea.txt
- index.html
- panel.html
So my question is: How can I fix this?
CodePudding user response:
You need to treat the nested parts before you process the rest.
const
fileData = { files: ["index.html", "panel.html"], directory1: { files: ["foo.html"], subdir1: { files: ["somefile.txt"] }, subdir2: { files: ["somefile.php", "other.php"] } }, directory2: { subdir1: { files: ["you_get_the_idea.txt"] } } },
iterate = data => Object
.entries(data)
.reduce((r, [k, v]) => r (
k === 'files'
? v.map(s => `<li><span>${s}</span></li>`).join('')
: `<li><input type="checkbox"/><span>${k}${iterate(v)}</li>`
), '<ul>'
) '</ul>';
document.body.innerHTML = iterate(fileData);