JQuery insertBefore() duplicating insert - javascript

I have the following markup:
<div class="mobile-menu">
<ul>
<li class="product">
Link
<ul>
<li>Link</li>
<li>Link</li>
<li class="item-has-children">
Link has submenu
<ul>
<li>submenu link</li>
<li>submenu link</li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
What I'm trying to do is move the submenu (li.item-has-children) as the first li item under .product. So my markup looks like this:
<div class="mobile-menu">
<ul>
<li class="product">
Link
<ul>
<li class="item-has-children">
Link has submenu
<ul>
<li>submenu link</li>
<li>submenu link</li>
</ul>
</li>
<li>Link</li>
<li>Link</li>
</ul>
</li>
</ul>
</div>
I have managed to move the li item to the top, but it's duplicating. As in my rendered markup with my JQuery below looks something like this:
<div class="mobile-menu">
<ul>
<li class="product">
Link
<ul>
<li>
Link has submenu
<ul>
<li>submenu link</li>
<li>submenu link</li>
<li>
<ul>
<li>Link has submenu</li>
<li>
<ul>
<li>submenu link</li>
<li>submenu link</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
The submenu is basically duplicating within each other and aI think it's to do with the way I'm using insertBefore(). I think it's targeting nested li elements too:
$('.mobile-menu ul li.product ul li.item-has-children').insertBefore($('.mobile-menu ul > li.product ul:first-of-type li:first-child'));
I simply want to move li.item-has-children as the first item in the li.product ul

Related

Find ul with a specific li item in a collection of ul and than add class to it

I have a collection of unordered lists. I would like to iterate through this list and than find an specific li item and than add a class to the ul containing that li.
I hope I was clear enough for you guys. Let me show you my code for better understanding.
This is a fiddle I created to help you understand my problem.
https://jsfiddle.net/wdwn9swu/
This is what I tried to target the ul I need but it didn't work.
if ($('ul.sub-tab').find('ul.sub-tab > li.super-active')) {
$('ul.sub-tab').find('li.super-active').addClass('super-active');
}
I would like that on of the lists that corresponds with the id, to always be open.
Any idea guys ?? Thanks!!
I think the easiest and simplest way is:
$("li.super-active").parent().addClass("super-active");
According the fact you are using valid html <li> element parent must be <ul> element in that case (can also be <ol>).
$('.main-tab>li a').click(function() {
$(this).siblings('.sub-tab').slideToggle(200);
$(this).parent().siblings('li').children('.sub-tab').slideUp(200);
});
$('.main-tab li').each(function() {
id = '10';
$links = $(".main-tab li[data-id =" + id + "]");
$links.addClass("super-active");
//console.log("1234");
});
$("li.super-active").parent().addClass("super-active");
console.log($(".super-active"));
.main-tab ul {
padding-left: 10px;
}
.sub-tab {
display: none;
}
.super-active img {
display: block !important;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<div class="center">
<ul class="main-tab">
<li data-id="5">
Main 1
<ul class="sub-tab">
<li data-id="7">
Main 1 Sub 1
<ul class="sub-tab">
<li data-id="10">Sub 2</li>
<li data-id="11">Sub 2</li>
</ul>
</li>
<li>
Main 1 Sub 2
<ul class="sub-tab">
<li data-id="12">Sub 2</li>
<li data-id="13">Sub 2</li>
</ul>
</li>
</ul>
</li>
<li data-id="8">
Main 2
<ul class="sub-tab">
<li data-id="9">
Main 2 Sub 1
<ul class="sub-tab">
<li data-id="14">Sub 2</li>
<li data-id="15">Sub 2</li>
</ul>
</li>
</ul>
</li>
<li data-id="3">
Main 3
<ul class="sub-tab">
<li data-id="25">
Main 3 Sub 1
<ul class="sub-tab">
<li data-id="17">Sub 2</li>
<li data-id="18">Sub 2</li>
</ul>
</li>
</ul>
</li>
</ul>
Use jQuery's :has selector:
Selects elements which contain at least one element that matches the
specified selector.
Find ul.sub-tab that has a list item with .super-active class, and add the class .super-active to the ul as well:
$('ul.sub-tab:has(li.super-active)').addClass('super-active');
Example:
$('ul.sub-tab:has(li.super-active)').addClass('super-active');
.sub-tab.super-active {
background: gold;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="center">
<ul class="main-tab">
<li data-id="5">
Main 1
<ul class="sub-tab"> <!-- this will be removed -->
<li data-id="7" class="super-active">
Main 1 Sub 1
<ul class="sub-tab">
<li data-id="10">Sub 2</li>
<li data-id="11">Sub 2</li>
</ul>
</li>
<li>
Main 1 Sub 2
<ul class="sub-tab">
<li data-id="12">Sub 2</li>
<li data-id="13">Sub 2</li>
</ul>
</li>
</ul>
</li>
<li data-id="8">
Main 2
<ul class="sub-tab">
<li data-id="9">
Main 2 Sub 1
<ul class="sub-tab">
<li data-id="14">Sub 2</li>
<li data-id="15">Sub 2</li>
</ul>
</li>
</ul>
</li>
<li data-id="3">
Main 3
<ul class="sub-tab">
<li data-id="25">
Main 3 Sub 1
<ul class="sub-tab">
<li data-id="17">Sub 2</li>
<li data-id="18">Sub 2</li>
</ul>
</li>
</ul>
</li>
</ul>

DOM traversal from a span element inside an anchor to list

I can't figure how to travers the DOM, starting from <span class = "open-menu-link">, I want to reach <ul class="sub-menu"> .
The script
<script> $('.open-menu-link').click(function(e){
alert(e.currentTarget);
});
</script>
return a Object HTMLSpanElement, but if I code e.currentTarget.parentNode; it returns http://localhost/mysite/home.php. Doing e.currentTarget.children; I get Object HTMLCollection, but if I try e.currentTarget.children[1] I get undefined... so how can I reach <ul class="sub-menu">?
The snippet is the follow:
<ul class="menu">
<li>Work</li>
<li class="menu-item-has-children">Haschildren <span class = "open-menu-link">+</span>
<ul class="sub-menu">
<li>Child 1</li>
<li>Child 2</li>
<li>Child 3</li>
</ul>
</li>
<li>Careers</li>
<li>Contact</li>
</ul>
$(function() {
$('.open-menu-link').click(function(e){
console.log(e.target.parentNode.nextElementSibling);
console.log(e.target.parentNode.parentNode.children[1]);
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="menu">
<li>Work</li>
<li class="menu-item-has-children">
Haschildren <span class="open-menu-link">+</span>
<ul class="sub-menu">
<li>Child 1</li>
<li>Child 2</li>
<li>Child 3</li>
</ul>
</li>
<li>Careers</li>
<li>Contact</li>
</ul>
There are couple of options:
$('.open-menu-link').click(function(e){
console.log(e.target.parentNode.nextElementSibling);
console.log(e.target.parentNode.parentNode.children[1]);
});
The <span class = "open-menu-link"> in your code has only one child i.e text node + this is the reason why e.currentTarget.children[1] is giving you undefined.
Coming to the dom traversal, you should start with node <li class="menu-item-has-children"> . Well that is what I can infer from your question.
You need to use preventDefault() because you'r class is a link. By clicking, it'll redirect you to the link.
$('.open-menu-link').click(function(e) {
console.log($(this).parent().next())
e.preventDefault()
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<ul class="menu">
<li>Work
</li>
<li class="menu-item-has-children">
Haschildren <span class = "open-menu-link">+</span>
<ul class="sub-menu">
<li>Child 1
</li>
<li>Child 2
</li>
<li>Child 3
</li>
</ul>
</li>
<li>Careers
</li>
<li>Contact
</li>
</ul>

Hide and show list items of divs after nth item of direct child only

Say I have an unordered list, like so:
Demo
HTML Code :
<ul>
<li>One
<ul>
<li>on 1.1</li>
<li>on 1.2</li>
<li>on 1.3</li>
</ul>
</li>
<li>Two</li>
<li>Three</li>
<li>Four</li>
<li>Five</li>
<li>One 1</li>
<li>Two 2</li>
<li>Three 3</li>
<li>Four 4</li>
<li>Five 5</li>
<li>One 11</li>
<li>Two 22</li>
<li>Three 33</li>
<li>Four 44</li>
<li>Five 55</li>
</ul>
<span class="show_more">see more</span>
Script File :
$('.nav_accordian').each(function(){
var max = 4
if ($(this).find('li').length > max) {
$(this).find('li:gt('+max+')').hide().end().append('<li class="sub_accordian"><span class="show_more">(see more)</span></li>');
$('.sub_accordian').click( function(){
$(this).siblings(':gt('+max+')').toggle();
if ( $('.show_more').length ) {
$(this).html('<span class="showMore">show More</span>');
}
else {
$(this).html('<span class="showMore">less More</span>');
};
});
};
});
i did for when i click on 'show more' it should be visible next five results of list items . Once every results loaded 'show more' text would be changed on 'less more'.
and when i clicked upon the 'less more' button first results result items should be visible other items would be hide.
The issue is the script is consider child list of li also
Giving a class to the list element you want to count on should resolve your problem :
<ul>
<li class="list__element">One
<ul>
<li>on 1.1</li>
<li>on 1.2</li>
<li>on 1.3</li>
</ul>
</li>
<li class="list__element">Two</li>
<li class="list__element">Three</li>
<li class="list__element">Four</li>
<li class="list__element">Five</li>
<li class="list__element">One 1</li>
<li class="list__element">Two 2</li>
<li class="list__element">Three 3</li>
<li class="list__element">Four 4</li>
<li class="list__element">Five 5</li>
<li class="list__element">One 11</li>
<li class="list__element">Two 22</li>
<li class="list__element">Three 33</li>
<li class="list__element">Four 44</li>
<li class="list__element">Five 55</li>
</ul>
<span class="show_more">see more</span>
And in your JS you would count then ".list__element", like so :
if ($(this).find('.list__element').length > max) {
...
}

Hide li item if content matches another div

I currently have content inside the div "company-name", I also have a whole list of items which has the div "item-name". If the content inside 'item-name' matches the content inside 'company-name' (WORD FOR WORD), then I want to display:block; that li, otherwise the li should be HIDDEN.
Also if the "item-name" div is empty/blank, it should also be hidden.
<div id="company-name">ABC Corporation</div>
<ul>
<li>Content for this item - this list item should display:block; because the item-name matches the company-name
<ul>
<li class="location">Australia</li>
<li class="industry">Pharmaceuticals</li>
<li class="item-name">ABC Corporation</li>
</ul>
</li>
<li>Content for this item - this list item should be HIDDEN - display:block;
<ul>
<li class="location">Australia</li>
<li class="industry">Pharmaceuticals</li>
<li class="item-name">XYZ Company</li>
</ul>
</li>
<li>Content for this item - this list item should be HIDDEN - display:block;
<ul>
<li class="location">Australia</li>
<li class="industry">Pharmaceuticals</li>
<li class="item-name">LMN Hardware</li>
</ul>
</li>
</ul>
You can iterate over the item-name elements and see whether its content is matching that of the company-name, if so show it like
var cn = $('#company-name').text().trim();
$('li:has(li.item-name)').hide();
$('li.item-name').filter(function() {
return $(this).text().trim() == cn;
}).parent().closest('li').show()
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js"></script>
<div id="company-name">ABC Corporation</div>
<ul>
<li>Content for this item - this list item should display:block; because the item-name matches the company-name
<ul>
<li class="location">Australia</li>
<li class="industry">Pharmaceuticals</li>
<li class="item-name">ABC Corporation</li>
</ul>
</li>
<li>Content for this item - this list item should be HIDDEN - display:block;
<ul>
<li class="location">Australia</li>
<li class="industry">Pharmaceuticals</li>
<li class="item-name">XYZ Company</li>
</ul>
</li>
<li>Content for this item - this list item should be HIDDEN - display:block;
<ul>
<li class="location">Australia</li>
<li class="industry">Pharmaceuticals</li>
<li class="item-name">LMN Hardware</li>
</ul>
</li>
</ul>

Don't slideToggle all

I have a vertical sliding menu, that looks like this:
<ul class="menu">
<li>link</li>
<li>link</li>
<li class="more">link with submenu</li>
<ul class="submenu">
<li>sub link 1</li>
<li>sub link 2</li>
</ul>
<li class="more">link with submenu</li>
<ul class="submenu">
<li>sub link 1</li>
<li>sub link 2</li>
</ul>
<li>link</li>
<li>link</li>
</ul>
the jQuery is like this:
jQuery(document).ready(function($) {
$(".more").click(function() {
$(this).parent().children(".submenu").slideToggle(500); });
});
My problem is, when I click on a ".more", every ".submenu" is being slideToggle (Both opens)
How can I do, so it is only the correct submenu that is being slidetoggled?
Thank you.
Remove the call to .parent(). Also, your .submenu should be nested within the <li> to which it belongs, leaving you with the following jQuery:
$("li.more").on("click", function() {
$("ul.submenu", this).slideToggle(500);
});
And this markup:
<ul class="menu">
<li>link</li>
<li>link</li>
<li class="more">
link with submenu
<ul class="submenu">
<li>sub link 1</li>
<li>sub link 2</li>
</ul>
</li>
<li class="more">
link with submenu
<ul class="submenu">
<li>sub link 1</li>
<li>sub link 2</li>
</ul>
</li>
<li>link</li>
<li>link</li>
</ul>
this one?
$(this).next().eq(0).slideToggle(500); });

Categories

Resources