0

I'm trying to use a recursive function to show/hide multiple nested UL/LI elements on the DOM.

I have a function which works for single nested, but I am trying to use a recursive function to control an x amount of nested elements.

Here is what I currently have:

HTML

<section data-range="true">
  <input type="range">
  <ul>
    <li>Item one</li>
    <li>Item two</li>
    <ul>
      <li>Nestd two-one</li>
      <li>Nestd two-two</li>
      <ul>
        <li>Double-nested one</li>
      </ul>
    </ul>
    <li>Item three</li>
  </ul>
</section>

JS:

/*  eventListener
 *  Attach an event listener to this element
 *
 *  @param Object - Event object
*/
function eventListener(el) {
  el.addEventListener('change', function(e) {
      // List
      else if (el.parentNode.children[1].nodeName == "UL" || el.parentNode.children[1].nodeName == "OL") {
          updateList(e, el.value);
      }
  });
}

/*  updateList
 *
 *  @param Object - Event object
 *  @param Real - Range value (i.e. 3.2)
*/
function updateList(e, range) {
    var target = e.srcElement || e.target;
    var list = target.nextSibling.nextElementSibling;
    var listNumber = list.childElementCount;

    displayChildren(list, listNumber);
}

/*  displayChildren
 *
 *  @param Object - Event object
*/
function displayChildren(list, listNumber) {

    for (var i = 0; i < listNumber; i++) {
        if (list.children[i].nodeName != 'UL') {
            list.children[i].style.display = (list.children[i].getAttribute('data-position') <= range) ? "":"none";
        }
        if (list.children[i].children.length > 0) {
            displayChildren(list.children[i], list.children[i].childElementCount);
        }
    }
}

Here are some live examples:

  • JSbin with recursive function on nested elements.
  • JSbin with working nested elements.

Any helpful tips are appreciated.

Kyle
  • 1,153
  • 5
  • 28
  • 56
  • 1
    Please describe in more detail what you are trying to accomplish. Please show or describe before/after results so we can see exactly what you start with and what you want to end with. – jfriend00 Jun 02 '16 at 16:42

1 Answers1

1

Well, you just omit some parameters. :)

Check it JsBin

function updateList(e, range) {
  ...
  displayChildren(list, listNumber, range); // add range param.
}

function displayChildren(list, listNumber, range) { // and here
  ...
  displayChildren(list.children[i], list.children[i].childElementCount, range); // and here.

Why don't use jQuery? anyway, It's cool script you've made, good luck :)

---- EDIT

Your data-position and input range's values are not 'Number', they are 'String'.

So, If more then 10 'UL' elements it compares like '10' with '4' (and '4' is bigger value')

JsBin (working demo)

to fix it, convert to number type before compare them at

function eventListener(el) {
  ...
  updateList(e, parseInt(el.value));


function displayChildren(list, listNumber, range) {
  ...
  // Now range is Number. (and LHS will converted with number)
  list.children[i].style.display = (list.children[i].getAttribute('data-position') <= range) ? "":"none";

I think you already got it, check it out :) Javascript string/integer comparisons

---- Edit again

And.. If you just want to show and hide 'LI' elements how about this?

var Range = function(step) {
  var rangeElements = document.querySelectorAll("[data-range]");

  for(var i = 0; i < rangeElements.length; i++) {
    var el = rangeElements[i];
    var inputRange = el.children[0]; // input type="range"
    var sectionRange = el.children[1]; // root UL

    inputRange.min = 0;
    inputRange.max = inputRange.value = sectionRange.getElementsByTagName('LI').length;
    inputRange.step = Number(step) || 1;

    // for better UX use oninput event.
    inputRange.addEventListener('input', function(e) {
      var el = e.target;
      var rangeItems = el.parentNode.children[1].getElementsByTagName('LI');
      var range = Number(el.value);
      for(var i = 0; i < rangeItems.length; i++) { rangeItems[i].style.display = i < range ? '' : 'none'; }
    });
  }
  return rangeElements;
}
Community
  • 1
  • 1
Yourim Yi
  • 198
  • 1
  • 5