1

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?

1 Answer 1

1

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}</span>${iterate(v)}</li>`
            ), '<ul>'
        ) + '</ul>';

document.body.innerHTML += iterate(fileData);

Sign up to request clarification or add additional context in comments.

2 Comments

Amazing! Thank you so much! I can work with this ^^
I noticed you forgot to close the <span> element here: <li><input type="checkbox"/><span>${k}${iterate(v)}</li>, so I added it.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.