Swap a class of an <li> on click - javascript

I am trying to swap the selected class from tab to tab to display which one is current
Sample Code
$("li.selected").idTabs(function(id,list,set){
$("a",set).removeClass("selected")
.filter("[#href='"+id+"']",set).addClass("selected");
for(i in list)
$(list[i]).hide();
$(id).fadeIn();
return false;
});
so on click I am trying to remove and load the selected class with no luck, tried this
<ul class="idTabs">
<li class="selected">Request more information</li>
<li>Request a test drive</li>
<li>Make an offer</li>
<li>Get a quote</li>
</ul>
$('.idTabs li').click(function(){
$('.idTabs li').removeClass('selected');
$(this).addClass('selected');
return false;
});

Aaron, your second example seems like it should work, but only works on the first two list items for some reason. I added classes to the li's to make the selector more specific and it works fine now.
<ul class="idTabs">
<li class="navTab selected">Request more information</li>
<li class="navTab">Request a test drive</li>
<li class="navTab">Make an offer</li>
<li class="navTab">Get a quote</li>
</ul>
$('.navTab').click(function(){
$('.navTab').removeClass('selected');
$(this).addClass('selected');
return false;
});
Regarding your comment below:
It works every time when you click on an li... does not work when clicking on the anchor text because the click handler is not attached to that. You should add "display: block;" to your anchor within your li to expand the click area to the entire li (you will need to remove the padding from your li and in turn pad your 'a' so that the entire li is clickable). then... move the click handler to the anchor and have it change the parent's (li) class. I'm thinking it should go something like this (I'm not able to test it out right now):
$('.navTab a').click(function(){
$('.navTab').removeClass('selected');
$(this).parent().addClass('selected');
return false;
});

Give all your tabs a class like 'tab', then try something along the lines of this:
$('li.tab').click(function(){
$('.tab').removeClass('slected');
$(this).addClass('selected');
return false;
});

You haven't really said what the problem is, but I'm guessing your selectors aren't quite right. You seem to be passing in the "set" class as a second argument, rather than as part of the selector string.
Try:
$("a," + set).removeClass("selected")
and
.filter("[#href='"+id+"']" + set)

Related

How do I make the eventListener to listen only for that particular element?

$ul.on("mouseenter", 'li', function() {
$("li button").slideDown();
});
So I have a li with a button adjacent to it like this:
<ul>
<li>Buy Robes<button>Delete</button></li>
<li>Go shopping<button>Delete</button></li>
<li>Buy noodles<button>Delete</button></li>
</ul>
But when I hover over any particular li, buttons for all lis is shown. But I want for that particular li I hover on. Like using the this keyword.
$ul.on("mouseenter", 'li', function() {
$(this).$("li button").slideDown();
});
Obviously the above code is wrong, but I want that to work something like this.
As pointed out in comments, your HTML is invalid. buttons are adjecent to the lis, but the selector you use focuses on finding the buttons inside the lis.
Correct your HTML; put the buttons inside the lis:
<ul>
<li>Buy Robes <button>Delete</button></li>
<li>Go shopping <button>Delete</button></li>
<li>Buy noodles <button>Delete</button></li>
</ul>
Now your selector $("li button") targets the correct elements. But still, there is one more issue. You're showing all the buttons, irrespective of which li was hovered. To correct this, scope your selector with this:
$ul.on("mouseenter", 'li', function() {
$(this).find("> button").slideDown();
});
This way, only the button, whose li was hovered, will be shown.

How to select a child ul and not the parent ul?

I have a 'tree' of information that's displayed in many nested lists (ul li ul li ....). Two problems:
When I click a <li>, the parent ul is toggled as well as the child.
If I click on an <li> in a nested list that does not have a ul in it (say, Blue under Cranberry below) the parent ul is toggle, even though this shouldn't be matching 'li.has(ul)'.
I've tried various JQuery selectors, next(ul), children().first(), etc with the same results. No luck - though I'm sure I'm just missing something simple here.
On JSFiddle.
$('li.has(ul)').click(function() {
$(this).children('ul').toggle();
});
And the html:
<ul class="unstyled" id="full_ontology">
<li>Apple</li>
<li>Banana</li>
<li>Cranberry
<ul>
<li>Blue</li>
<li>Red
<ul>
<li>Round</li>
<li>Square</li>
<li>Circular</li>
</ul>
</li>
<li>Purple</li>
</ul>
</li>
<li>Date</li>
<li>Elderberry
<ul>
<li>Yellow</li>
<li>Pink</li>
<li>Black</li>
</ul>
</li>
<li>Fig</li>
</ul>
The problem is event propagation, prevent it
$('li:has(ul)').click(function (e) {
$(this).children('ul').addClass('thisOne').toggle();
});
$('li').click(function (e) {
e.stopPropagation();
});
Demo: Fiddle
It's all about propagation.
Here is the working JavaScript:
$('li').click(function(e) {
if ($(this).has('ul')) {
$(this).children('ul').addClass('thisOne').toggle();
}
e.stopPropagation();
});
JSFiddle: http://jsfiddle.net/zkFGU/3/
Basically, first you want this event on all of the list items, not just the ones that have the ul. The reason is because if you don't, you can't stop propagation. For example, "Blue" under "Cranberry" has no list, so it wouldn't call the event. However, because "Blue" is actually in Cranberry, which is a list item and does trigger the event, clicking Blue counts as clicking Cranberry, so Cranberry retracts. By giving Blue a change to chance to stop propagation, it prevents Cranberry from erroneously collapsing.
The other part of stopping propagation is simply to stop parents. We want only the element we directly clicked on (which is triggered first) and no other element to (attempt) to toggle.

Detect class inside ul list, if not found delete li:first-child

I have this structure:
<ul id="#my-list">
<li><a class="class-1" href="#">Link</a></li>
<li><a class="class-2" href="#">Link</a></li>
<li><a class="class-3" href="#">Link</a></li>
</ul>
I want jquery to check if .class-1 inside #my-list exists, if not then it should delete .li (just the first one).
Basically, when the first link is deleted, the first li element should be removed as well.
$('#my-list:has(.class-1) li:first').remove()
That would of course require an ID like:
<ul id="my-list">
FIDDLE
According to your question, you'd like to do the opposite for some strange reason, and that would be :
$('#my-list:not(:has(.class-1)) li:first').remove()
but the question is, how are you deleting the anchor, and why not just delete the list item instead ?
Basically, when the first link is deleted, the first li element should be removed as well.
Sounds like you want:
$('#my-list > li').first().filter(function() {
return $(this).find('a').length === 0;
}).remove();
If you want to apply this to all li elements, not just the first one, simply omit .first().

Add return false to parent link only with jQuery

I have a list inside a toggled div...
<li>
Link
<ul stlye="display:none;">
<li>Child Link</li>
</ul>
</li>
Ive written a piece of jQuery to toggle the display of the child UL only when a child link is clicked it no longer works (It doesnt go through to google), can anybody see where im going wrong?
// Dropdown
$('.archives ul li a').click(function(){
$(this).parent().find('ul').slideToggle();
return false;
});
STYLE is spelled wrong.
stlye=
From your post's title it appears you want something like this...
$('.archives ul li a').click(function(){
var $children = $(this).parent().find('ul');
$children.slideToggle();
return $children.length > 0 ? false : true;
});
Return will be false only when child ULs are found.
Assuming what you've shown is inside a ul which is in turn inside an element with class archives, then the selector .archives ul li a matches both the parent and child anchors, because you've used a descendant selector, and so your handler gets called for the child, and the return false; prevents it from doing its default action (following the link).
If your goal is to have the handler triggered only for the earlier link and not for the child link, then you may need to be more specific. You haven't shown enough of your markup for us to help you be more specific, though. If I assume your markup looks something like this:
<div class="archives">
<ul>
<li>
Link
<ul style="display:none;">
<li>Child Link</li>
</ul>
</li>
</ul>
</div>
...then the selector to match only the "Link" anchor and not the "Child Link" anchor would be .archives > ul > li > a (e.g., using direct child selectors).
Also note that you had stlye rather than style, but I assume that's just a typo in the question. (Why don't people use copy and paste?! ;-) )
The ChildLink is also matched by your selector, and in the click handler you're preventing the default action (which would be "navigate to Google").
So you should adapt your selector to only get the toggle Link, or you use this:
$('.archives ul li a').click(function(e){
if ($(this).siblings('ul').slideToggle().length) // if we found a list to toggle
e.preventDefault(); // or return false
});
Since your return false statement is cancelling the default link action, you need to be more specific so that you don't target the links that want to allow to continue to function.
Try this:
$('.archives > li > a').click(function () {
$(this).parent().find('ul').slideToggle();
return false;
});
jsFiddle example
By using the > child selector and changing the target to only the immediate child links of the outermost list, the sublinks won't be selected and will continue to work. In your code your $('.archives ul li a') will apply to any child links, not just the top level.

Jquery select all children within children

I'm sure this will be a simple question but I still struggle with DOM selectors in Jquery so here is a model of my html code:
<fieldset class="product-options" id="product-options-wrapper">
<ul class="options-list">
<li><a href>Item1.1</a></li>
<li><a href>Item1.2</a></li>
<li><a href>Item1.3</a></li>
</ul>
...other html items here
<ul class="options-list">
<li><a href>Item2.1</a></li>
<li><a href>Item2.2</a></li>
<li><a href>Item2.3</a></li>
</ul>
</fieldset>
Now how do I select all of the 'li a' items in both lists (or X number of lists) with class name .options-list and bind them with a click function.
Currently I have:
$('fieldset#product-options-wrapper ul.options-list > li a').bind('click', function(e) {
//code here
});
And it only gets the first options-list.
Thanks, greatly appreciated!
EDIT: If i click on a Item2.X list item first, then it will grab that options list. But as soon as I click on the Item1.x list items it disregards the second .options-list
If you are going to bind to each li element, you should bind it to the ul element instead (helps greatly with performance when there are a lot of events).
$('.options-list', '#product-options-wrapper').bind('click', function(e)
{
e.preventDefault();//In case you don't want to go to a different page
var clicked = e.target;//The href that was clicked
/* If you only want this to happen if the a tag was clicked, add the following line
if(clicked.tagName == 'A')*/
//Rest here
});
How about $('.options-list a').bind('click', function(e) { });?
You can use delegate in this case to make it even simpler. Try this
$('#product-options-wrapper ul.options-list').delegate('li > a', 'click', function(e) {
//code here
});
Your method seems sound to me. I created a test fiddle using your HTML (and an extra anchor to prove that it won't get the click added) and your JS (with minor modifications).
http://jsfiddle.net/chrisvenus/esZxH/1/
The selector you had did work but since you said you wanted the a to be a direct child of the li (or at least I read it that way) I slightly tweaked it in my version above. ARe you sure its not just your function is not doing quite what you want while executing or can you confirm that your click function isn't being run at all?

Categories