Changing structure of html menu using javascript - javascript

CMS, that I am using, generates such a code for menu:
<ul>
<li>second level menu</li>
<li>third level menu</li>
<li>third level menu</li>
</ul>
<ul>
<li>second level menu</li>
<li>third level menu</li>
</ul>
...
I would like to change the way of displaying the third level menu. Is it possible to change this code using javascript into:
<ul>
<li>second level menu
<ul>
<li>third level menu</li>
<li>third level menu</li>
</ul>
</li>
</ul>
<ul>
<li>second level menu
<ul>
<li>third level menu</li>
</ul>
</li>
</ul>
...

You need to differentiate li elements, so you can identify then, which should be first or next level elements. Setting data-attributes, I think is a not "so much bad solution".
Btw, below is only a boilerplate code, and will work verily for given structure. You need to grasp the logic - so you can apply it to other problems.
<!DOCTYPE html>
<html>
<head>
<title></title>
</head>
<body>
<ul>
<li data-level="2">second level menu</li>
<li data-level="3">third level menu</li>
<li data-level="3">third level menu</li>
</ul>
<ul>
<li data-level="2">second level menu</li>
<li data-level="3">third level menu</li>
</ul>
<script type="text/javascript">
var uls = document.querySelectorAll('ul');
for(var i=0; i<uls.length; i++) {
var children = uls[i].querySelectorAll("li");
var _children = Array.from(children).filter(e=> e.dataset.level == "3");
if (_children.length > 0) {
var newul = document.createElement("ul");
_children.map(e=>newul.appendChild(e));
uls[i].appendChild(newul);
}
}
</script>
</body>
</html>

Related

Get Element with most children of specific class

I have a navigation that looks like this:
<div class="sub_navigation">
<ul>
<li>First Level
<ul>
<li>Second Level</li>
<li>Second Level
<ul>
<li>Third Level</li>
</ul>
</li>
</ul>
</li>
<li>First Level
<ul>
<li>Second Level</li>
<li>Second Level
<ul>
<li>Third Level
<ul>
<li>Fourth Level</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
Basically, everly li can have an infinite amount of children uls. I need to get the number of the highest level
For example, right now I'd be looking for the number 4 as the second li has 4 Levels.
I tried two different methods:
First, my own attempt that failed miserably:
$count = 1;
$('.sub_navigation > .menu > li').each(function() {
countChildren($count);
});
function countChildren() {
$(this).children('ul').each(function() {
$count++;
console.log($count);
});
return($count);
}
Second, a way I took from stack overflow but that didn't work out for me either, only returning 0 everytime:
var arr = []; //populate the length of children into this array.
$('.sub_navigation ul').map(function (i) {
arr[i] = $(this).children('ul').length;
});
var maxValue = Math.max.apply(Math, arr); //get the max value from the array
console.log(maxValue);
Could someone please point me in the right direction? I sadly have no idea how to acieve this at all anymore.
Thanks a lot!
You can use parentsUntil() like
var temp = $('.sub_navigation li').map(function() {
return $(this).parentsUntil('.sub_navigation', 'ul').length;
}).get();
var max = Math.max.apply(Math, temp);
snippet.log('Count: ' + max)
<!-- Provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="sub_navigation">
<ul>
<li>First Level
<ul>
<li>Second Level</li>
<li>Second Level
<ul>
<li>Third Level</li>
</ul>
</li>
</ul>
</li>
<li>First Level
<ul>
<li>Second Level</li>
<li>Second Level
<ul>
<li>Third Level
<ul>
<li>Fourth Level
<ul>
<li>Fifth Level</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
Instead of going from top to bottom level you could do it the other way.
Check for each li how many ul ancestors it has
var ulAncestorsPerLi = $( '.sub_navigation li' ).map(function(){
return $(this).parentsUntil( '.sub_navigation', 'ul' ).length;
}).get(),
deepestLevel = Math.max.apply( Math, ulAncestorsPerLi );
alert( deepestLevel );
var ulAncestorsPerLi = $('.sub_navigation li').map(function() {
return $(this).parentsUntil('.sub_navigation', 'ul').length;
}).get(),
deepestLevel = Math.max.apply(Math, ulAncestorsPerLi);
alert(deepestLevel);
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="sub_navigation">
<ul>
<li>First Level
<ul>
<li>Second Level</li>
<li>Second Level
<ul>
<li>Third Level</li>
</ul>
</li>
</ul>
</li>
<li>First Level
<ul>
<li>Second Level</li>
<li>Second Level
<ul>
<li>Third Level
<ul>
<li>Fourth Level</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</div>

Disable scrollable event on a specified id

I have a responsive navigation on my website. And, this js code is for smooth scrolling within my webpage.
$(function(){$("a[href*=#]:not([href=#])").click(function() {
if(location.pathname.replace(/^\//,"")==this.pathname.replace(/^\//,"")
&&location.hostname==this.hostname){
var target=$(this.hash);
target=target.length?target:$("[name="+this.hash.slice(1)+"]");
if(target.length){
$("html,body").animate({scrollTop:target.offset().top},1000);return false}}})});
When i create a link Scroll to Topwrapper, i can scroll it smoothly to the div as long as the div name is #topWrapper or #whatever. I have also an id name navi in my navigation. I would like to ask that, is there anyway i can disable the id in this js code so that it doesn't scroll when i click on the hamburger icon to open the menu? Thank you!
Hope you understand what i am asking as English is not my primary language. Thank you!
Update:
<nav class="menu" id="navi">
<ul>
<li class="has-sub-menu">About
<ul class="sub-menu">
<li>Our Vision</li>
<li>Our Services</li>
<li>Latest New</li>
<li>Our Blog</li>
</ul>
</li>
<li class="has-sub-menu">Gallery
<ul class="sub-menu">
<li class="has-sub-menu">Kitchen Cabinet
<ul class="sub-menu">
<li>Melamine ABS Kitchen Cabinet</li>
<li>Acrylic Door Kitchen Cabinet</li>
<li>3G Glass Door Kitchen Cabinet</li>
<li>4G Glass Door Kitchen Cabinet</li>
</ul>
</li>
<li class="has-sub-menu">Wardrobe Design
<ul class="sub-menu">
<li>Swing Door Wardrobe</li>
<li>Sliding Door Wardrobe</li>
<li>Walk In Closet</li>
</ul>
</li>
<li>TV Cabinet</li>
<li>Study Table Design</li>
<li>3D Cabinet Design</li>
<li>Others Cabinet Design</li>
</ul>
</li>
<li class="has-sub-menu">Materials
<ul class="sub-menu">
<li class="has-sub-menu">Doors
<ul>
<li>Melamine ABS Door</li>
<li>3G Glass Door</li>
<li>Acrylic Door</li>
<li>4G Glass Door</li>
<li>Membrane Pressed</li>
<li>Multi-Layer Ply Laminated</li>
</ul>
</li>
<li class="has-sub-menu">Carcass
<ul>
<li>Compressed Wood</li>
<li>Blockboard</li>
<li>Solid Wood</li>
<li>Aluminium</li>
</ul>
</li>
<li class="has-sub-menu">Worktop
<ul>
<li>HPL Worktop</li>
<li>Solid Surface</li>
<li>Granite Stone</li>
<li>Quartz Stone</li>
</ul>
</li>
</ul>
</li>
<li class="has-sub-menu">Promotion
<ul class="sub-menu">
<li>Kitchen Cabinet</li>
<li>Wardrobe</li>
<li>Appliances</li>
<li>Extended Promotion</li>
</ul>
</li>
<li class="has-sub-menu">Contact
<ul class="sub-menu">
<li>Contact Information</li>
<li>Enquiry Form</li>
<li>Meet Our Designers</li>
<li>Facebook</li>
<li>Twitter</li>
<li class="share">Whatsapp</li>
</ul>
</li>
</ul>
</nav>
Js Code for navigation:
$(document).ready(function(e){
var t=$("#navi"),a=$(".menu-link"),l=$(".has-sub-menu > a");
a.click(function(e){e.preventDefault(),a.toggleClass("active"),t.toggleClass("active")}),l.click(function(e){e.preventDefault();
var t=$(this);t.toggleClass("active").next("ul").toggleClass("active")}),e.preventDefault()});
Do:
document.getElementById("desired-id-name").addEventListener('click', function(){
return false; // does nothing
});
EDIT 1:
Since you are using jQuery, here is a jQuery version:
$("#desired-id-name").click(function(){
return false;
});
Make sure to add this inside:
$(function(){ ... };
EDIT 2:
$("#desired-id-name").scroll(function(){
return false;
});
Docs: https://api.jquery.com/scroll/

Get the size of the parent LI inside an UL?

How can I modify the below code so that I get only the parent li within the first ul and then with another variable get the sub li of the given sub ul?
$(function () {
var vULSize = $("ul li").size();
console.log(vULSize);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<ul>
<li>First</li>
<li>Second
<ul>
<li>Second Sub 1</li>
<li>Second Sub 2</li>
</ul>
</li>
<li>Third</li>
<li>Third
<ul>
<li>Third Sub 1</li>
<li>Third Sub 2</li>
</ul>
</li>
</ul>
Fiddle: http://jsfiddle.net/0sp9pohr/
You can ignore all li's that are descendants of an li like
$(function() {
var vULSize = $("ul li:not(li li)").size();
snippet.log(vULSize);
});
<!-- Provides the `snippet` object, see http://meta.stackexchange.com/a/242144/134069 -->
<script src="http://tjcrowder.github.io/simple-snippets-console/snippet.js"></script>
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul>
<li>First</li>
<li>Second
<ul>
<li>Second Sub 1</li>
<li>Second Sub 2</li>
</ul>
</li>
<li>Third</li>
<li>Third
<ul>
<li>Third Sub 1</li>
<li>Third Sub 2</li>
</ul>
</li>
</ul>
First you need to wrap it all in something, say for instance a div with the id container. Then you can do something like this:
var vULSize = $("#container > ul > li").length;
The > selector gives you only the direct descendants.
If you want to count the number of list elements one level down, this will give you an array with the result:
var counts = $("#container > ul > li").map(function() {
return $(this).find("li").length
}).get();
As pointed out in comments, you should use .length instead of .size().

Hide parent UL using jQuery at the same time show the nested child UL which was previously hidden with css

Ive got a <ul> list that is nested inside of a parent <ul> the child is hidden, i want to show it when a link is clicked in its parent. At the same time i want the parent <ul> content to be hidden (without hiding the child).
I know i could work around this by having two separate <ul> lists that were un nested but Ive been trying to keep them nested following the W3 guidelines on nested lists.
The issue Im having at the moment is that when the main list is hidden it also hides the child and does not allow it to be shown.
Ive made a jsfiddle of the issue here - http://jsfiddle.net/xc0g770z/
The HTML Im using is
<ul id="main-list">
<li>ONE</li>
<li>TWO</li>
<li>THREE</li>
<li>FOUR</li>
<li>FIVE</li>
<li>SIX
<ul id="sub-nav">
<li>SIX - ONE</li>
<li>SIX - TWO</li>
<li>SIX - THREE</li>
<li>SIX - FOUR</li>
<li>RETRUN</li>
</ul>
</li>
<li>SEVEN</li>
<li>EIGHT</li>
</ul>
The jQuery Im using is
$("#open-submenu").click(function () {
$("#main-list").hide();
$("#sub-nav").show();
});
Any ideas how i could get this to work whilst still using the nested ?
DEMO: http://jsfiddle.net/murid/xc0g770z/1/
$("#sub-nav").hide();
$("#open-submenu a").click(function () {
$("#main-list li").hide();
$("#open-submenu").show();
$("#sub-nav").show();
$("#sub-nav li").show();
});
One way to do this would be to use class
<ul>
<li class="main-list">ONE</li>
<li class="main-list">TWO</li>
<li class="main-list">THREE</li>
<li class="main-list">FOUR</li>
<li class="main-list">FIVE</li>
<li class="main-list" id="open-submenu">SIX<li></a>
<li class="six-sub">SIX - ONE</li>
<li class="six-sub">SIX - TWO</li>
<li class="six-sub">SIX - THREE</li>
<li class="six-sub">SIX - FOUR</li>
<li class="six-sub">RETRUN</li>
<li class="main-list">SEVEN</li>
<li class="main-list">EIGHT</li>
</ul>
The in the jquery
$("#open-submenu").click(function () {
$(".main-list").hide();
$(".six-sub").show();
});

Creating a menu from a list using Jquery to just show the parent ul and current Level

I've been trying to create a Menu from an list when the current link is identified with a span and I with to display the parent level and the current level on all branches as I navigate through the site. I am fairly new to scripting, any help found be greatly appreciated
Example
If the list was:
A
A b
A b c
A b
And the currentbranch span was on c.
I would want the list to be:
b
b c
b
-HTML List -
<ul>
<li><span class="currentbranch0">Home</span>
<ul class="multilevel-linkul-0">
<li>News
<ul class="multilevel-linkul-1">
<li>Internal
<ul class="multilevel-linkul-2">
<li>Archive</li>
</ul>
</li>
<li>External
<ul class="multilevel-linkul-2">
<li>Archive</li>
</ul>
</li>
<li>News Poll</li>
<li>All News</li>
</ul>
</li>
<li><span class="currentbranch1">Locations</span>
<ul class="multilevel-linkul-1">
<li>a</li>
<li>b</li>
<li>c</li>
<li><span class="currentbranch2">Menu Test</span>
<ul class="multilevel-linkul-2">
<li>test</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
Script
(document).ready(function() { var output = '<ul>';
output += $("#side_nav span").last().parent().parent().parent().parent().html();
output += '</ul>';
document.getElementById('side_nav').innerHTML = output;
});$("#side_nav li").ready(function() {
var count = [];
$("#side_nav ul[class^='multilevel-']").each(function(){
var item = $(this).attr('class')
count.push(item);
count.sort();
});
$('#side_nav li').each(function(){
if($(this).parent('ul').hasClass(count[count.length-1])){
$(this).remove();
};
});
});

Categories

Resources