Friends, I am working on JavaScript for collapse/Expand <UL> list.
here is my Code. I am wanted to work on it, in Nth Level, i can show Child, but its not hiding Children.
I hope you guys will help me..
Thanks in Advance...
This will do the trick:
event.stopPropagation();
Docs.
If you debug your code you'll see that the event is being called for each parent ul. Check this out:
$("#ExpList ul li:has(ul)").click(function(event) {
event.stopPropagation();
$(this).find('> ul')
.toggleClass("hiddenChild")
.toggleClass("displayChild");
});
And the HTML:
<div id='ExpList'>
<ul>
<li>Platform-1
<ul class='hiddenChild'>
<li>Child-1
<ul class='hiddenChild'>
<li>P-C-C-1</li>
</ul>
</li>
</ul>
</li>
</ul>
</div>
Fiddle.
HTML considerations:
I don't know if you can use a div wrapping the whole list, but I think it would make more sense doing it;
You're using the id ExpList for all ul. This is not how we use an id. Instead, for selecting many elements use its own tag or a common class;
I removed the onClick = openChild() which were present in all ul. It was throwin an error in your fiddle.
JavaScript considerations:
You don't have to mix a selector with a find this way $("#ExpList").find('li:has(ul)'). You can just use it on the same selector, as I did $("#ExpList ul li:has(ul)");
You don't need to search for all ul children($(this).children('ul')) since you'll have just one, I used this instead, which looks for just one: $(this).find('> ul');
As said before, the event.stopPropagation() does the trick. You don't need to trigger click event on all parent ul.
In CSS, I just changed #ExpList to this #ExpList ul to work in the new structure. I hope it helps.
Related
I am trying to highlight the current page link, like this...
Image Here
Thanks to the others before me who have asked this, I have been able to do so properly.
But, My Navigation Bar has a sub menu.
I am trying to highlight the parent of the sub menu whenever I am in it. But, whenever I am from a parent menu (example the "MAIN") and went to a sub menu from a different parent (example the "TRANSFEREES") this happens...Image Here
here is the html for the menu...
<ul id = "nav">
<li>MAIN</li>
<li>ABOUT US</li>
<li>ADMISSION
<ul class = "sub">
<li>FRESHMEN</li>
<li>TRANSFEREES</li>
</ul>
</li>
</ul>
Here is the Javascript code...
$('ul#nav li a').click(function(){
$(this).closest('ul#nav li').addClass('active').siblings().removeClass('active');
return false;
});
And the CSS...
ul#nav li.active{
background:#9993a6;}
I have tried looking for a solution for this everywhere, I am a newbie at Javascript so if any of you could help me... I would really appreciate it... Thanks in advance.
The way you are removing active class is wrong, because addClass does not return a jQuery object, so you cannot use siblings() on it.
I also think is better to use parents instead of closest, you should try something like this:
$('ul#nav li a').click(function(){
var listElement = $(this).parents('ul#nav li');
listElement.addClass('active');
listElement.siblings().removeClass('active');
return false;
});
Try removing the active class for every list item in the list and it's sublists, and then add the active class to the items you want, otherwise you'll have to control too many cases.
This is the code:
$('ul#nav li a').click(function(){
$('#nav li').removeClass('active');
$(this).addClass('active');
var possibleParent = $(this).parents('#nav li');
if (possibleParent) possibleParent.addClass('active');
});
And here a Codepen demostrating: http://codepen.io/anon/pen/jWORRG
I'm working on a menu that is designed using an unordered list, with each list element containing a link to another page. However, I would also like to be able to click on each bullet point to open more subcategories that will also link to other pages.
Essentially, I would like to be able to click once on a link and have it go to the correct page, but I would also like to click on the bullet point and have it expand into the subcategories. I've been researching how to separate the bullet from the content of the li, but it doesn't seem to be working in my case, likely because my li contains a lot of subcategories. Here's an example:
<li id="m2l1" class="child">
Y
<ul id="u11">
<li class="gchild">Y.1</li>
<li class="gchild">Y.2</li>
<li class="gchild">Y.3</li>
<li class="gchild">Y.4</li>
<li class="gchild">Y.5</li>
<li class="gchild">Y.6</li>
<li class="gchild">Y.7</li>
<li class="gchild">Y.8</li>
<li class="gchild">Y.9</li>
</ul>
</li>
Does anyone have any suggestions as to how to separate the bullet from the text in my case?
Here's the link: http://jsfiddle.net/stamblerre/XYp48/17/
Thank you!!!
Your HTML is invalid. You can't have div inside your ul. Moreover, you can greatly simplify your code by moving separate logic for each li into one generic handler.
Something like this:
Demo: http://jsfiddle.net/abhitalks/XYp48/18/
CSS:
ul {
display: none;
overflow: hidden;
}
ul:first-child {
display: block;
}
JS:
$("li").on("click", function () {
$(this).children("ul").slideToggle();
return false;
});
Edit:
I deliberately left out checking of a because clicking the a would navigate to the respective pages (as mentioned in your question), so expand/collapse wouldn't matter.
However, as per your comment if you really want to remove a altogether from the handler, then you can use the event target to handle li without a. Something like this:
Demo 2: http://jsfiddle.net/abhitalks/XYp48/22/
JS:
$("li").on("click", function (e) {
var $t = $(e.target); // get the event target as a jQuery object
if (!$t.is('a')) { // check if the target is not an anchor
$(this).children("ul").slideToggle();
return false;
}
// otherwise if target is anchor, then do nothing
});
Change your list still to hide bullets, then modify your html to :
<li class="gchild">•Y.1</li>
Should do the trick.
<li class="gchild">Y.1</li>
One way that worked for me: remove the bullet with li { list-style-type: none; } then add your own bullets with the character • (alt-8 on a mac). Add that character inside a elements like so:
• X
with the label now outside of the element.
Hope this works for you!
I am trying to remove the li's with conditon under Ul in multiple div's.
<div>
<ul>
<li class="sel">.....</li>
<li class="sel">.....</li>
............
<li>.....</li>
<li>.....</li>
...........
<!-- I have some 600 li's -->
</ul>
</div>
I have 200 li's with class='sel'. Now I need to remove the remaining 400 li's.
I am trying to remove in two ways, like,
$("ul", this).each(function(){
$("li", this).each(function(){
$(this).remove();
//Also tried with -- $(this).empty().remove();
});
});
other way like,
$("ul", this).each(function(){
$("li[class!=sel]", this).remove(); // Also tried with 'not'
});
Now the problem is, When I am trying to execute these ways In IE getting Script overloaded error.
Please help me out on other ways to remove unwanted li's.
Note: I don't want to keep the un-wanted li's to hide() state.
Thanks in advance...
If you're using the Attribute Not Equal Selector, you don't need to wrap it with .each() - simply call it like this:
$('li[class!="sel"]').remove();
The selector ('li[class!="sel"]') is grabbing all <li> elements that don't have class sel and then calling the remove() method on that entire set of elements.
Demo
Edit
If you only want to target the <ul> which contains the <li class="sel"></li> elements, you can set the context like this:
// Find the first <li> with class="sel" and get it's parent <ul>
var $ul = $('li.sel:first').parent('ul');
// Use $ul as the context for the removal of the <li> elements
$('li[class!="sel"]', $ul).remove();
For what it's worth, I ran into a similar problem just a couple of weeks ago, only in IE8, even calling .remove() on a single item selected by id. The problem only occurred when the element contained a great deal of content.
What I did was to call .html('') to clear the element just before calling .remove(). This reduced the time dramatically (sub-second).
Mine was obviously a different situation (one element vs. many, selected by id vs. contextual selectors, not sure what your li content is, etc.), but it might be worth a shot.
$("ul", this).each(function(){
$("li[class!=sel]", this).html('').remove();
});
Try detaching the ul, remove the li's, then reattach the ul.
$("ul", this).detach().find("li").not(".sel").remove().end().end().appendTo(this);
This prevents the browser from redrawing until all li's that need to be removed are removed.
I was making a menu today, and I stumbled on this curious case, with the following HTML:
<div id="list1">
<ul>
<li>1</li>
<li>2 - Here is a Submenu
<ul>
<li>3</li>
<li>4</li>
</ul>
</li>
</ul>
</div>
Then i used the following js:
$('#list1 li').click(function(){
$('.list-item').removeClass('list-item');
$(this).addClass('list-item');
});
When I do this the class would only be applied to the outer <li>, but I wanted it to be applied to both the parent and child LIs.
Now my question is, how can I handle this "returns" so I apply the classes to both the parent and child LIs?
How does js handle these type of selectors? Is the event really running twice and removing the last class that was set?
The issue is that $('#list1 li') can select both levels of li tags inside #list and apply a click handler to both. In addition, you are allowing the click to propagate up so it may be seen by more than just the one you click on.
If you only want the outer level, then you should use direct child specifications like this. and that will isolate what click handler is actually installed:
$("#list > ul > li")
This will only get the top level li tags. And, the whole code would look like this:
$('#list1 > ul > li').click(function(){
$('.list-item').removeClass('list-item');
$(this).addClass('list-item');
});
If you want to isolate the removeClass operation to just the other LI tags at the same level, not across the entire document, then you can use something like this:
$('#list1 > ul > li').click(function(){
$(this).addClass('list-item').siblings().removeClass('list-item');
});
Your comments have me a bit confused about this LI tags you want clickable. If you actually want the lower level to be clickable and then apply the list-item class to both the one that was clicked and the parent LI, then you can do that like this:
$('#list1 > ul > li > ul > li').click(function() {
$("#list1 .list-item").removeClass('list-item');
$(this).parents("li").add(this).addClass('list-item');
return(false); // stop event propagation
});
Whether or not jQuery applies a method to one element in a list of elements or all of them depends on the method.
.click() and .addClass() will both be applied to all jQuery objects in your selector.
In your case, a click handler is applied to all li elements in #list. $(this) applies to the specific li that was clicked on.
However, you have nested li elements, which means that multiple click handlers fire when you click on an inner nested li, both the nested li and it's parent li.
To prevent this event propagation through the dom tree, put a stopPropagation() call in your click handler:
$('#list1 li').click(function(e){
e.stopPropagation();
$('.list-item').removeClass('list-item');
$(this).addClass('list-item');
});
You can also return false from your handler, which stops propagation and prevents default actions. This is specific to jQuery.
if you are adding a "current" page style:
$('#list1 > ul > li').on('click',function(){
$(this).addClass('list-item') //adds class to clicked item
.siblings() //find the others of the same level
.removeClass('list-item'); //remove their styles
});
I have a list with links:
<li class="link-1">One</li>
<li class="link-2">Two</li>
<li class="link-3">Three</li>
..
user clicks on any link, then with jQuery I want to display the content of the link.. somthing like:
$(".link-??? a").click(function() {
alert($(".link-??? a").html());
})
something like this. I am not going to create X function (as the number of the links), so what can I do? I should replace the ??? in somtehing else..
You could do:
$('li[class^="link"] a').click(...
However this would only work if the li have only one class or if the link-X class is the first in the list.
Inside the handler you can use $(this) to refer to the a element:
alert($(this).text());
Much better would be to give the li elements a common class:
<li class="link">One</li>
<li class="link">Two</li>
<li class="link">Three</li>
$('.link a').click(... will be much more reliable.
Give each element the same class. Then in your javascript reference this within your function. Check out the link below to see a working example
http://jsfiddle.net/kprgr/2/
<li class="link">One</li>
<li class="link">Two</li>
<li class="link">Three</li>
$(".link").click(function() {
alert($(this).find("a").html());
});
Try..
$(".link-??? a").click(function() {
alert(this.innerHTML);
})
Inside the click event, this should refer to the element that was clicked.
You could also do..
alert($(this).html());
..but the first way is simpler, and faster.