简体   繁体   中英

Parsing a tree - Collecting data for each node, recursively (JavaScript)

I have a tree structure as follows which is rendered using jsTree:

Root
    Child 1
        Child 1 - 1
        Child 2 - 2
    Child 2
Root2
    Child 1

The tree is created dynamically by the user from the UI using a form and button clicks for adding nodes and attributes for each node. These attributes are collected using a form when the user clicks on a particular node. I am storing the node information in a list with node name and it's parent as follows:

<ul>
    <li data-node="Root 1" data-parent = ''>[Form to add attributes]</li>
    <li data-node="Child 1" data-parent="Root 1">[Form to add attributes]</li>
    <li data-node="Child 2" data-parent="Root 1">[Form to add attributes]</li>

... and so on.

I need to collect that data, in the following JSON format:

Root1: {
    formdata: {...}
    children: {
        Child 1: {
            formdata: {...}
            children: {
                Child 1 - 1: {
                    formdata: {...}
                }
                Child 1 - 2: {
                    formdata: {...}
                }
            }
        }
        Child 2: {
            formdata: {...}
            children: {
                Child 1 - 1: {
                    formdata: {...}
                }
            }
        }
    }
}

... and so on.

It could be N levels deep. I am only able to visualise collection going down one branch. If I dig into Root 1 > Child 1 > Child 1 - 1 , I am not able to figure out how to come back to the parent, while maintaining the collected data.

Any help would be appreciated.

After the edit to your question, it looks like that extra data are available as form inputs, or maybe the form is just the tool to end up with additional data- attributes on the li elements.

1. With FormData

I'll first assume these data are accessible via the standard FormData API. So for instance, if a form has <input name="country"> , its value will be available under the country key.

Here is how you could build a tree object from scanning the DOM:

 function collectTree(ul) { // Create the nodes & identify the root let nodes = {}; let root = null; for (let li of ul.children) { // Extract form data using the FormData API let formdata = Object.fromEntries(new FormData(li.querySelector("form")).entries()); nodes[li.dataset.node] = { formdata }; if (!li.dataset.parent) root = nodes[li.dataset.node]; } // Populate the children arrays for (let li of ul.children) { if (!li.dataset.parent) continue; let p = nodes[li.dataset.parent]; if (!p.children) p.children = {}; p.children[li.dataset.node] = nodes[li.dataset.node]; } return root; } const root = collectTree(document.querySelector("ul")); console.log(root);
 <ul> <li data-node="Root 1" data-parent=""> <form> <input name="address" value="Abbey Road 1"> <input name="country" value="UK"> </form> </li> <li data-node="Child 1" data-parent="Root 1"> <form> <input name="address" value="Champs-Elysées 9"> <input name="country" value="FR"> </form> </li> <li data-node="Child 1 1" data-parent="Child 1"> <form> <input name="address" value="Downing Street 10"> <input name="country" value="UK"> </form> </li> <li data-node="Child 2" data-parent="Root 1"> <form> <input name="address" value="Wall Street 1"> <input name="country" value="US"> </form> </li> </ul>

2. With additional data- attributes

If the extra data is not present in the form, but become additional data- attributes to the li elements (that was not clear to me), then it is similar:

 function collectTree(ul) { // Create the nodes & identify the root let nodes = {}; let root = null; for (let li of ul.children) { // Extract form data using the FormData API ({ node, parent, ...formdata} = li.dataset); nodes[node] = { formdata }; if (!parent) root = nodes[node]; } // Populate the children arrays for (let li of ul.children) { if (!li.dataset.parent) continue; let p = nodes[li.dataset.parent]; if (!p.children) p.children = {}; p.children[li.dataset.node] = nodes[li.dataset.node]; } return root; } const root = collectTree(document.querySelector("ul")); console.log(root);
 <ul> <li data-node="Root 1" data-parent="" data-address="Abbey Road 1" data-country="UK"></li> <li data-node="Child 1" data-parent="Root 1" data-address="Champs-Elysées 9" data-country="FR"></li> <li data-node="Child 1 1" data-parent="Child 1" data-address="Downing Street 10" data-country="UK"></li> <li data-node="Child 2" data-parent="Root 1" data-address="Wall Street 1" data-country="US"></li> </ul>

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM