-3

var allmenus = $('.dragger-menu').map(function() {
  var li = {};
  $(this).children('li').each(function() {
    switch ($(this).data("menu")) {
      case "page":
        li.page = {
          id: $(this).data("menu-id")
        };
        break;
      case "external-link":
        li["external-link"] = {
          title: $(this).text().trim(),
          url: $(this).data("menu-link"),
          icon: $(this).children("i").attr("class")
        }
        break;
      case "dropdown":
        li.dropdown = {};
        li.dropdown.title = $(this).contents().filter(function() {
          return this.nodeType == Node.TEXT_NODE;
        }).text().trim();
        li.dropdown.data = $(this).children("ol").map(function() {
          var data = {};
          $(this).children("li").each(function() {
            switch ($(this).data("menu")) {
              case "page":
                data.page = {
                  id: $(this).data("menu-id")
                };
                break;
              case "external-link":
                data["external-link"] = {
                  title: $(this).text().trim(),
                  url: $(this).data("menu-link"),
                  icon: $(this).children("i").attr("class")
                }
                break;
            }
          });
          return data;
        }).get();
        break;
    }
  });
  return li;
}).get();

var obj = {
  menu: allmenus
};
var jsondata = JSON.stringify(obj, null, 2);
console.log(jsondata);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ol class="dragger-menu">
   <li class="list-group-item" data-menu="page" data-menu-id="24">Online Register</li>
   <li class="list-group-item" data-menu="page" data-menu-id="26">Secondly Page</li>
   <li class="list-group-item" data-menu="dropdown">
      <i class="fa fa-caret-square-o-down"></i> Dropdown Menu 
      <ol class="">
         <li class="list-group-item" data-menu="page" data-menu-id="25">Contact Us</li>
         <li class="list-group-item" data-menu="external-link" data-menu-link="https://twitter.com/your-page"><i class="fa fa-Twitter"></i> Twitter</li>
         <li class="list-group-item" data-menu="external-link" data-menu-link="https://facebook.com/your-page"><i class="fa fa-Facebook"></i> Facebook</li>
      </ol>
   </li>
</ol>
<ol class="dragger-menu">
   <li class="list-group-item" data-menu="page" data-menu-id="28">Ahmet Deneme</li>
   <li class="list-group-item" data-menu="page" data-menu-id="21">Secondly Page</li>
</ol>

The above javascript code does not pass the same type element to json. Example: If you are run the code, you see only page 26, not 24. This code only get last elem in same elem. I want the all elements in json data. What should i do in javascript code ? Sorry for my bad englısh . Thanks for all.

2 Answers2

0

Don't build JSON by concatenating strings. Create an object and then use JSON.stringify.

And use jQuery's .each() and .map() methods to loop through the DOM, rather than for loops.

var allmenus = $('.dragger-menu').map(function() {
  var li = {};
  $(this).children('li').each(function() {
    switch ($(this).data("menu")) {
      case "page":
        li.page = {
          id: $(this).data("menu-id")
        };
        break;
      case "external-link":
        li["external-link"] = {
          title: $(this).text().trim(),
          url: $(this).data("menu-link"),
          icon: $(this).children("i").attr("class")
        }
        break;
      case "dropdown":
        li.dropdown = {};
        li.dropdown.title = $(this).contents().filter(function() {
          return this.nodeType == Node.TEXT_NODE;
        }).text().trim();
        li.dropdown.data = $(this).children("ol").map(function() {
          var data = {};
          $(this).children("li").each(function() {
            switch ($(this).data("menu")) {
              case "page":
                data.page = {
                  id: $(this).data("menu-id")
                };
                break;
              case "external-link":
                data["external-link"] = {
                  title: $(this).text().trim(),
                  url: $(this).data("menu-link"),
                  icon: $(this).children("i").attr("class")
                }
                break;
            }
          });
          return data;
        }).get();
        break;
    }
  });
  return li;
}).get();

var obj = {
  menu: allmenus
};
var jsondata = JSON.stringify(obj, null, 2);
console.log(jsondata);
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<ol class="dragger-menu">
  <li class="list-group-item" data-menu="page" data-menu-id="24">Online Register</li>
  <li class="list-group-item" data-menu="external-link" data-menu-link="https://facebook.com/your-page"><i class="fa fa-facebook"></i> Facebook</li>
  <li class="list-group-item" data-menu="dropdown">
    <i class="fa fa-caret-square-o-down"></i> Dropdown Menu
    <ol class="">
      <li class="list-group-item" data-menu="page" data-menu-id="25">Contact Us</li>
      <li class="list-group-item" data-menu="external-link" data-menu-link="https://twitter.com/your-page"><i class="fa fa-Twitter"></i> Twitter</li>
    </ol>
  </li>
</ol>
<ol class="dragger-menu">
  <li class="list-group-item" data-menu="page" data-menu-id="28">Ahmet Deneme</li>
</ol>

The code to get the title of the dropdown came from How to get the text node of an element?. It would be easier if you put that text inside a <span> so you can write a selector for it.

Barmar
  • 741,623
  • 53
  • 500
  • 612
  • What do you mean? I have page 25 and page 28, that's all the elements. – Barmar Dec 21 '18 at 08:15
  • I should have used `.children()`, it was selecting `li` nested further down in the HTML. – Barmar Dec 21 '18 at 08:20
  • You commented out the `dropdown` part of your code, so I didn't put it in my answer. But you should get the general idea and be able to add that yourself. It's similar to this. – Barmar Dec 21 '18 at 08:21
  • I don't know how make it for dropdown. Should I use nested function ? – Yavuz Selim Özmen Dec 21 '18 at 08:28
  • No, just add a loop like `$(this).children("ol").children("li").each()` to create the `data:` property. – Barmar Dec 21 '18 at 08:31
  • Just like the way I processed the `li` in `.dragger-menu`. – Barmar Dec 21 '18 at 08:32
  • Do you really need everything done for you? You need to learn to generalize, you can't expect to find the exact code you need. – Barmar Dec 21 '18 at 08:33
  • The code for processing the dropdown menu items is basically the same as the `dragger-menu` items. You might want to pull that out into a separate function to avoid repeating it. That will be especially useful if you allow multiple levels of nesting, since it can recurse as many times as necessary. – Barmar Dec 21 '18 at 08:56
  • I get duplicate key error now. dublicate key "page". Should I put a number on the top of the keys after the menu? How can i do this? – Yavuz Selim Özmen Dec 21 '18 at 12:52
  • That's a database error, what does it have to do with this HTML? I don't know what you mean by a number on top of the keys. The page IDs seem to be unique, one is id 24, another is ID 25, the last is ID 28. If these are duplicating something that's already in the database, you should probably fix that. – Barmar Dec 21 '18 at 17:16
  • must be: "0": { "page": { "id": {} } }, ... I want to count 0,1,2 before the key – Yavuz Selim Özmen Dec 24 '18 at 06:21
  • Online Register
  • Page another
  • When two pages, it doesn't read it all. – Yavuz Selim Özmen Dec 24 '18 at 07:19
  • Where is `"0":` in the desired result in the question? – Barmar Dec 24 '18 at 15:18
  • Please update the question. The sample input never has multiple pages inside the same `
      `. And it doesn't say the result must begin with `"0":`. I can only answer the question you ask, not the question you meant to ask.
    – Barmar Dec 24 '18 at 15:20
  • You left out the expected result that goes with the new HTML. – Barmar Dec 25 '18 at 16:11
  • You also got rid of your original, broken code. Readers of the question need to see what I was correcting, otherwise the answer makes less sense. Remember, this is a teaching tool for all users of the site, not just a way to get someone to write code for you personally. – Barmar Dec 25 '18 at 16:12