0

I have a multidimensional object array like this.

var categories = [{ 
    text: "engine",
    children: [1,2,3, { 
        text: "piston",
        children: [4,5,6]
    }]   
}, {
    text: "tire",
    children: [7,8,9]
}];

Everytime the index of the categories array equals an array there must be a dropdown menu with the contents of the array in it and it can be endless. If the index of the array is not equal to an array it should just be an a tag.

I am trying to achieve something like this:

https://www.w3schools.com/bootstrap/tryit.asp?filename=trybs_ref_js_dropdown_multilevel_css&stacked=h

I have tried altering this code below to make it suit my needs I did this in combination with a self made dropdown menu in html and css, but at this point it does not make sense anymore.

function menuToElement(menu) {
    const ul = document.createElement("ul");
    for (const item of menu) {
        const li = document.createElement("li");
        if (Object(item) === item) {
            li.textContent = item.text;
            li.appendChild(menuToElement(item.children));
        } else {
            li.textContent = item;
        }
        ul.appendChild(li);
    }
    return ul;
}
const ul = menuToElement(categories);
document.getElementById("menu").appendChild(ul);

The result I was getting is that I was only able to show the names engine and tire, but couldn't get a dropdown with the children in it to work. What I want to ask is if someone can explain what the code above does exactly and whether I approach this in the right way.

This is how I tried making the dropdown menu it is not fully working anymore because I was trying to make it append using the other code.

<div class="popup" onclick="togglePopup2()">
<div class="sel popuptext" id="myPopup2">
      <div class='txt'>Select</div>    
      <div id="Select" class="options hide">
           <div>Option 1</div>
           <div>Option 2</div>
           <div>Option 3</div>
      </div>           
    </div>
  <img src="~/images/circle.png" class="category" id="1">
</div>


var txt = $('.txt'),
    options = $('.options');

txt.click(function (e) {

    e.stopPropagation();
    var content = $(e.target).text();
    console.log(content);
    $('#'+ content).show(); 
});


$('body').click(function (e) {
    options.hide();
});
}
2
  • Can you post the self made dropdown code? Commented Dec 19, 2018 at 22:06
  • The dropdown code is now in the question. Commented Dec 19, 2018 at 22:17

2 Answers 2

2

Your code seems to work ok. At first it creates an unordered list (<ul>). Then goes through all elements of the input parameter and for each item create a list item element (<li>). If an element is an object then set its text to .text property of the item and recursively calls the same function with children of this item (.children) as parameters and append the result to previously created <li> element. Otherwise it just renders list item element with text being the same as the item.

Here is one simple fiddle using your code and some simple css (you should do it with click instead of hover): https://jsfiddle.net/zyuhqo3k/1/

function menuToElement(menu) {
    const ul = document.createElement("ul");
    for (const item of menu) {
        const li = document.createElement("li");
        if (Object(item) === item) {
            li.textContent = item.text + ' \u25BD';
            li.appendChild(menuToElement(item.children));
        } else {
            li.textContent = item;
        }
        ul.appendChild(li);
    }
    return ul;
}

var categories = [{ 
    text: "engine",
    children: [1,2,3, { 
        text: "piston",
        children: [4,5,6]
    }]   
}, {
    text: "tire",
    children: [7,8,9]
}];
const ul = menuToElement(categories);
document.getElementById("menu").appendChild(ul);
li > ul {
  display: none;
}

li:hover > ul {
  display: block;
}
<div id="menu">
</div>

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

Comments

2

Adapted Answer JS/jQuery based on code provided

HTML

<div id='myMenu' class="dropdown">

</div>

CSS

.dropdown-submenu {
  position: relative;
}

.dropdown-submenu .dropdown-menu {
  top: 0;
  left: 100%;
  margin-top: -1px;
}

jQuery

var categories = [{
  text: "engine",
  children: [1, 2, 3, {
    text: "piston",
    children: [4, 5, 6]
  }]
}, {
  text: "tire",
  children: [7, 8, 9]
}];

function menuToElement(menu) {
  const ul = document.createElement("ul");
  ul.className = 'dropdown-menu';
  for (const item of menu) {
    const li = document.createElement("li");
      if (Object(item) === item) {
        li.textContent = item.text;
        li.appendChild(menuToElement(item.children));
        li.className = "dropdown-submenu";
      } else {
        li.textContent = item;
      }
      ul.className = 'dropdown-menu';
      ul.appendChild(li);
    }
    return ul;
}

  $(document).ready(function() {

  var menu = menuToElement(categories);
  document.getElementById('myMenu').innerHTML = "<button class='btn btn-default dropdown-toggle' type='button' data-toggle='dropdown'>Categories<span class='caret'></span></button>";
  document.getElementById('myMenu').appendChild(menu);

  liList = document.getElementsByTagName('li');
  for (var i = 0; i < liList.length; i++) {
    items = liList[i].childNodes;
    if (items.length > 1)
    {
            liList[i].innerHTML = "<a class='test' tabindex='-1' href='#'>" + items[0].textContent+ "<span class='caret'></span></a>" + "<ul class='dropdown-menu'>" + items[1].innerHTML + "</ul>";
    }
    else if (items.length == 1){
            liList[i].innerHTML = "<a class='test' tabindex='-1' href='#'>" + items[0].textContent + "</a>";    
        }
  }

    $('#myMenu a').on("click", function(e) {
      $(this).next('ul').toggle();
      e.stopPropagation();
      e.preventDefault();
    });
  });

Working JS Fiddle https://jsfiddle.net/2h8adqut/10/

Comments

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.