Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use jquery to generate an arbitrarily deep list

In javascript, I have an array of objects that represents an arbitrarily deep list...

data =
[
 { title, depth },
 { title, depth },
 { title, depth }, 
 { title, depth }, 
]

...where depth is how deep in the list the element is.

I want to convert this data into html.

For example:

[
 { title: "one", depth : 1 },
 { title: "two", depth : 1 },
 { title: "three", depth : 2 }, 
 { title: "four", depth : 3 }, 
 { title: "five", depth : 1 }, 
]

becomes...

<ul>
  <li><p>one</p></li>
  <li>
    <p>two</p>
    <ul>
      <li>
        <p>three</p>
        <ul>
          <li><p>four</p></li> 
        </ul>
      </li>
    </ul>
  </li>
  <li><p>five</p></li>
</ul>

What is the simplest way to do this, using jQuery?

Thanks

like image 715
trev Avatar asked Mar 11 '11 19:03

trev


3 Answers

Here is one way you could do it:

(function($) {
  $.listify = function(items) {
    var container = $('<div></div>'), root = container;
    var depth = 0;
    for (var i = 0; i < items.length; ++i) {
      var item = items[i];
      if (item.depth > depth) {
        while (item.depth > depth) {
          var ul = $('<ul></ul>').appendTo(container);
          var li = $('<li></li>').appendTo(ul);
          container = li;
          ++depth;
        }
      } else if (item.depth <= depth) {
        while (item.depth < depth) {
          container = container.parent().parent();
          --depth;
        }
        container = $('<li></li>').insertAfter(container);
      }
      container.append('<p>' + item.title + '</p>');
    }
    return root.children();
  }
})(jQuery);

I admit, I just wanted to name something listify. Here is a jsFiddle. You would call it like so:

$.listify([
  { title: "one", depth : 1 },
  { title: "two", depth : 1 },
  { title: "three", depth : 2 }, 
  { title: "four", depth : 3 }, 
  { title: "five", depth : 1 }, 
]).appendTo(document.body);
like image 147
Nathan Ostgard Avatar answered Oct 30 '22 02:10

Nathan Ostgard


Works with multiple levels and correctly nests the tags:

(function ($) {
    $.makelist = function (arr) {  
    var currentdepth = 1;
    var root = $('<ul>');
    var el = root;
    var idx = 0;

    while (idx < arr.length) {
      if (arr[idx].depth == currentdepth) {
         el.append($('<li>').html($('<p>').text(arr[idx].title)));
         idx++;
      }
      else if (arr[idx].depth > currentdepth) {
        newel = $('<ul>');
        el.append(newel);
        el = newel;
        currentdepth++;
      }
      else {
        el = el.parent('ul');
        currentdepth--;
      }
    }
    return root;
  }
})(jQuery);

        $(document).ready(function () {
            arr = [
                     { title: "one", depth: 1 },
                     { title: "two", depth: 1 },
                     { title: "three", depth: 2 },
                     { title: "four", depth: 3 },
                     { title: "five", depth: 1 },
                    ];

            $('body').append($.makelist(arr));
        });
like image 35
Samg Avatar answered Oct 30 '22 00:10

Samg


This one is dynamic:

http://jsfiddle.net/wq8QY/

no matter how many levels you go down it will still be created all the way.

 var json = [
 { title: "one", depth : 1 },
 { title: "two", depth : 10 },
 { title: "three", depth : 20 }, 
 { title: "four", depth : 25 }, 
 { title: "five", depth : 11 }, 
]
    var dom = $('body') ;
    dom.append($('<ul>'))
    //console.log(json.length)
    for( var i = 0; i < json.length; i++){
    //console.log(json[i])
        var appendTo = $('body')
        for(var j = 1; j <= json[i].depth; j++){
            console.log(appendTo, json[i], json[i].depth, '1st')
            if(appendTo.children('ul').length <= 0){
                console.log('no ul', j)
                appendTo.append($('<ul>'))
            }
           appendTo = $(appendTo.children('ul'))
            console.log(appendTo, json[i], '2nd')
        }
       console.log(appendTo, json[i], 'appending')
       appendTo.append($('<li><p>'+json[i].title+'</p></li>'))
    }
like image 20
Naftali Avatar answered Oct 30 '22 01:10

Naftali