简体   繁体   中英

Generating a nodes path from an unordered list

I have the following list of data:

在此处输入图片说明

Which is set up with this HTML:

<ul id='tree'>
    <li data-id="1" data-parent="0">
        Home
        <ul>
            <li data-id="2" data-parent="1">
                About
                <ul>
                    <li data-id="4" data-parent="2">
                        What we do
                    </li>
                </ul>
            </li>

            <li data-id="3" data-parent="1">
                Contact
                <ul>
                    <li data-id="5" data-parent="3">
                        Employees
                        <ul>
                            <li data-id="6" data-parent="5">
                                Full-time
                            </li>

                            <li data-id="7" data-parent="5">
                                Part-time
                            </li>
                        </ul>
                    </li>
                </ul>
            </li>
        </ul>
    </li>
</ul>

Upon clicking a button, I want to generate the node path for each list item and add it to a string of data I can format.

I have started with this:

$('button').on('click', function(){ 

    var output = "";

    $("ul#tree li").each(function(){
         var id = $(this).data("id");
         var parent = $(this).data("parent");
         output = output + "id=" + id + "&parent=" + parent + "$"; 
    });

    $("section").html(output);

});

Which generates:

id=1&parent=0
id=2&parent=1
id=4&parent=2
id=3&parent=1
id=5&parent=3
id=6&parent=5
id=7&parent=5

However, I want to add the node path of each line (the path of parent ID's to the current list item). So, for example, it would look like this:

id=1&parent=0&node_path=.0.
id=2&parent=1&node_path=.0.1.
id=4&parent=2&node_path=.0.1.2.
id=3&parent=1&node_path=.0.1.
id=5&parent=3&node_path=.0.1.3.
id=6&parent=5&node_path=.0.1.3.5.
id=7&parent=5&node_path=.0.1.3.5.

I'm not sure how to create a function that would combine parent ID's in the path of ul > li's...

Something like this? This sample pulls node7 and walks up the tree building the path of data-ids.

 var node7 = document.getElementById('node7'); alert( pathToNode(node7) ); function pathToNode(node) { var path = []; var parent = node.parentElement; while(parent && parent.id !== 'tree') { if( parent.dataset.id ){ path.unshift(parent.dataset.id); } parent = parent.parentElement; } return path.join('.'); } 
 <ul id='tree'> <li data-id="1" data-parent="0"> Home <ul> <li data-id="2" data-parent="1"> About <ul> <li data-id="4" data-parent="2"> What we do </li> </ul> </li> <li data-id="3" data-parent="1"> Contact <ul> <li data-id="5" data-parent="3"> Employees <ul> <li data-id="6" data-parent="5"> Full-time </li> <li data-id="7" id="node7" data-parent="5"> Part-time </li> </ul> </li> </ul> </li> </ul> </li> </ul> 

You could just look for all the list items and start building up by going up a step and keep repeating until you hit the ul#tree . Heres how I would do it:

 var all = {}; $('#tree li').each(function(){ // Define a general i, a path variable, and the first parent var id = $(this).data('id') || false; var path = id; var parent = $(this).parent(); // This will ignore any list items without an id. if(id){ // While the parent is not ul#tree, keep going up. while(parent.attr('id') !== 'tree'){ var t = parent.data('id') || false; // There are many ways to output your data. // I decided to wrap them in objects, that you can use in JS. // But you could off course build a string. Just rememeber that `t` // is the value that should _before_ the previous value, // as its higher up the chain. if(t){ var temp = {}; temp[t] = path; path = temp } //path = t ? { + path : path; parent = parent.parent(); } all[id] = path; } }); console.log(all) 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.0/jquery.min.js"></script> <ul id="tree"> <li data-id="1">1</li> <li data-id="2"> <ul> <li data-id="5">1</li> <li data-id="6"> <ul> <li data-id="9">1</li> <li data-id="10"></li> </ul> </li> </ul> </li> <li data-id="3">1</li> <li data-id="4"> <ul> <li data-id="7">1</li> <li data-id="8">1</li> </ul> </li> </ul> 

You can write a recursive function to trace up the parent until no parent can be found, and return the path. And Dynamic programming can further save the trace time.

  1. Check its parent li has been traced or not.

  2. If parent is traced, get the parent's path, if not keep trace up until root is met.

  3. Put parent's id to the result path, and store it for further use.

 $('button').on('click', function(){ var output = ""; // Keep the traced record, so we can reuse it, rather than tracing with the same route again. var store = {}; var traceUp = function(id, pid) { var path = []; // If parent has already construct a path, just use it. if (typeof store[pid] !== 'undefined') { path = store[pid].slice(); } else { // Otherwise, find the parent li, and keep traceup. var pLi = $('li[data-id="' + pid +'"]'); if (pLi.length !== 0) { path = path.concat(traceUp(pid, pLi.data('parent'))); } } path.push(pid); store[id] = path; return path; }; $("ul#tree li").each(function(){ var id = $(this).data("id"); var parent = $(this).data("parent"); // Get the trace result in an array. var path = traceUp(id, parent); // use .join to convert array to string with desired format. output = output + "id=" + id + "&parent=" + parent + "&path=." + path.join('.') + '<br/>'; }); $("section").html(output); }); 
 <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script> <ul id='tree'> <li data-id="1" data-parent="0"> Home <ul> <li data-id="2" data-parent="1"> About <ul> <li data-id="4" data-parent="2"> What we do </li> </ul> </li> <li data-id="3" data-parent="1"> Contact <ul> <li data-id="5" data-parent="3"> Employees <ul> <li data-id="6" data-parent="5"> Full-time </li> <li data-id="7" data-parent="5"> Part-time </li> </ul> </li> </ul> </li> </ul> </li> </ul> <button>click</button> <section></section> 

You could use parents(), to get the list of parents. You could take this further and get rid of the parent data attribute all together, which would simplify the following code.

$('#mybutton').on('click', function () {

     var output = "";

     $("ul#tree li").each(function () {
         var id = $(this).data("id");
         var parent = $(this).data("parent");
         output = output + "id=" + id + "&parent=" + parent  + "&node_path=";

         var node_path = parent + ".";
         $(this).parents('li').each(function() {
             node_path +=  $(this).data("parent") + ".";
         });
         output += node_path.split('').reverse().join('')
         output += "<br/>";
     });

     $("#mysection").html(output);

 });

http://jsfiddle.net/4t6jgzhu/

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