1

I have the following HTML

<ol data-level="0">
    <li class="active">This is the data1</li>
</ol>
<ol data-level="1">
    <li class="active">This is the data2</li>
</ol>
<ol data-level="2">
    <li class="active">This is the data3</li>
</ol>
<ol data-level="3">
    <li class="active">This is the data4</li>
</ol>
<ol data-level="2">
    <li class="active">This is the data5</li>
</ol>
<ol data-level="2">
    <li class="active">This is the data6</li>
</ol>
<ol data-level="0">
    <li class="active">This is the data7</li>
</ol>

Below you can see the outcome of the above HTML (I stripped out some html tags for better readability!). Indents

I have to create a valid unordered list from this outcome. I've searched around stackoverflow and I came across multiple solutions. E.g. making use of a recursive function. The problem with this is that I don't know how to pass in the objects that belong to the 'root' object (see: How can I recursively create a UL/LI's from JSON data - multiple layers deep).

At the moment I'm stuck with this code:

var $root = $items.first();
var rootLvl = $root.data('level');
var prevLvl = rootLvl;

function recursiveCheck($next) {
    prevLvl = $next.data('level');
    var nextItem = $next.next();

    if (nextItem.data('level') > prevLvl) {
        console.log('check');
        recursiveCheck(nextItem);
    } else {
        console.log('break');
    }
}

recursiveCheck($root);

At the 'break' I don't know how to go back to the previous root element.. Can someone pull me in the right direction?

Thanks in advance!

Edit: My desired outcome is like this:

    <ul>
        <li>Data 1
            <ul>
                <li> Data 2
                    <ul>
                        <li> Data 3
                            <ul>
                                <li>
                                    Data 4
                                </li>
                            </ul>
                        </li>
                        <li>Data 5
                        </li>
                        <li>Data 6
                        </li>
                    </ul>
                </li>
            </ul>
        </li>
        <li>Data 7
        </li>
    </ul>

More information

- level 1 
- - level 2 // this belongs to the first level 1
- - - level 3 // this belongs to level 2
- - - level 3 // this belongs to level 2
- - - level 3 // this belongs to level 2
- - level 2 // this belongs to the first level 1
- level 1 
- - level 2 // this belongs to the second level 1

in this example the first level 1 has two level 2 subitems, but one of them also has three level 3 subitems. So I have to find out how to get the next items with a higher level. I'm able to produce above string with '- - -'. I just can't convert this to an unordered list.

Solved, final code:

edu.saveSummary = function() {
    var dataLevel = 'edu-draggable-level';
    var node = $('[data-edu-draggable]').first();

    function parseUL() {
        var level = node.data(dataLevel);
        var ul = document.createElement("ul");

        while (node && node.data(dataLevel) === level) {
            var li = document.createElement("li");
            li.textContent = node.text();
            ul.appendChild(li);
            node = node.next();
            if (node && +node.data(dataLevel) > level) {
                li.appendChild(parseUL());
            }
        }

        return ul;
    }

    return parseUL();
};
4
  • 1
    What is the actual output you want to achieve? "I have to create a valid unordered list from this outcome" is kinda ambiguous. Commented Dec 4, 2013 at 8:19
  • Added, sorry you are right :-) Commented Dec 4, 2013 at 8:23
  • Maybe I didn't get the point, but can you just show different indentations, e.g. give padding:30px for level 3... Commented Dec 4, 2013 at 8:24
  • For remembering elements in the tree-like structure while you're "traversing" them, you use stack structure. That might help. Commented Dec 4, 2013 at 8:25

1 Answer 1

3

Something along these lines should work:

var node = first_ol_node;

function parseUL() {
    var level = +node.children().first().data('level');
    var ul = document.createElement("ul");
    while (node && +node.children().first().data('level') === level) {
        var li = document.createElement("li");
        li.textContent = node.text();
        ul.appendChild(li);
        node = node.next();
        if (node && +node.children().first().data(level) > level) {
            li.appendChild(parseUL());
        }
    }
    return ul;
}

var ul = parseUL();

One problem is that you need both to return the parsed ul node from the function and you also need to advance the parsing pointer over the source items (and in Javascript there's no way to pass a variable by reference, you can only pass by value).

In this solution I'm using an external variable instead of a parameter to keep the current pointer in the source items (advanced in node = node.next()) and the return value is the parsed UL.

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

3 Comments

If I use your code my browser crashes, I think it's in an endless loop. I changed a bit to your code e.g. +node.children().first().data, I changed this to +node.data(), the data is in the OL tag not in the LI tag? Or do I miss something here? Thanks for your answer though, I'll keep trying and trying..
I solved my problem, I removed the '+' sign and now it works. @6502 can you tell me what's the '+' sign used for?
@DieterGoetelen: Sorry... I didn't test the code at all, I added the + to force a numeric conversion and avoid surprises with comparison. Just double check if it works with level "2" not being considered bigger than level "12".

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.