Creating a "selected item" javascript code for navigation menu? - javascript

I have a navigation menu with about 10 items, and I put together this code to update the links for which is selected and which is not. It manually updates classes. The problem is, as you can probably tell, its inefficient and its a pain to update. Is there a better way of doing it?
$('#Button1').click(function(){
$('#Button1').addClass("selectedItem");
$('#Button2').removeClass("selectedItem");
$('#Button3').removeClass("selectedItem");
$('#Button4').removeClass("selectedItem");
$('#Button5').removeClass("selectedItem");
$('#Button6').removeClass("selectedItem");
$('#Button7').removeClass("selectedItem");
$('#Button8').removeClass("selectedItem");
$('#Button9').removeClass("selectedItem");
$('#Button10').removeClass("selectedItem");
});

You could try something like this -
$("[id^='Button']").removeClass("selectedItem");
$('#Button1').addClass("selectedItem");
This will first remove all the selectedItem classes from any element which has an id attribute starting with "button". The second command then adds the class to Button1
You could also simply bind all the elements with the same handler like this -
var $buttons = $("[id^='Button']");
$buttons.on('click', function ()
{
$buttons.removeClass("selectedItem");
$(this).addClass("selectedItem");
});
For each element, when clicked, the class will be removed - the element that was clicked with then have the class added.
Checkout the Attribute Starts With Selector [name^="value"] selector.

I would suggest using classes because this is exactly what they are for - to denote groups of elements. While you can easily select your buttons using the method proposed by Lix (and you should use this method if you can't modify HTML), using class is a more unobtrusive:
var $buttons = $('.button').on('click', function() {
$buttons.removeClass('selectedItem');
$(this).addClass('selectedItem');
});
Meta example: http://jsfiddle.net/88JR2/

You could have a class .button and apply it to all your buttons then
$('#Button1').click(function(){
$('.button').removeClass("selectedItem");
$('#Button1').addClass("selectedItem");
});

Related

Store jQuery in a variable

I've got an FAQ page I'm building. Next to the question, there is a plus sign to expand the content. On click, I've added the class active, but there are many questions, and I don't want to repeat the same jQuery snippet for each question. I've figured out how to find the parent ID but I'm having trouble storing it in an variable to reuse in the jQuery script.
What I want to be able to do:
var element = $(this).parent().parent().attr('id')
$('.expand').click(function(){
$('element .expand').toggleClass('active')
})
Is there a way to do this? I get undefined when I do this:
$('.expand').click(function(){
console.log(element)
});
You can use the find() function to locate children of a selected element:
var element = $(this).parent().parent().attr('id')
$('.expand').click(function(){
$("#" + element).find('.expand').toggleClass('active')
});
However, looking at your code, it seems like you just want to toggle the "active" class of the clicked element. If that is the case, you can do this much more simply without a variable at all:
$('.expand').click(function(){
$(this).toggleClass('active')
});

How to change button class in a div while just the last one can keep the change?

I'm using this code to change my buttons's class:
$('button').on('click', function(){
var btn=$(this);
if(btn.attr('class')=='tct-button'){
btn.removeClass('tct-button').addClass('tct-button2');
}
else{
btn.removeClass('tct-button2').addClass('tct-button');
}
});
The problem is that I have multiple div's with multiple buttons in each. I need to change this so that every time I click on a button in a div the others which were changed by a previous click (in that same div) change back to the default class which is 'tct-button', and just the last clicked button turns to 'tct-button2'. Would you please help me.
use toggleClass in jquery ,there is no need to check hasClass()
$(this).toggleClass("tct-button2 tct-button");
DEMO
Use hasClass()
Determine whether any of the matched elements are assigned the given class.
Code
$('button').on('click', function(){
var btn=$(this);
if(btn.hasClass('tct-button')){
btn.removeClass('tct-button').addClass('tct-button2');
}
else{
btn.removeClass('tct-button2').addClass('tct-button');
}
});
However I think you need
$('button').on('click', function(){
$('.tct-button2').removeClass('tct-button2'); //Remove all class
$(this).addClass('tct-button2'); //Add the class to current element
});
If you want to add an additional class to your buttons (tct-button2) whilst keeping tct-button on every button you could do what Satpal suggested.
However, from the sounds of it and I may be wrong, if you want to change the classes so that each button only has one class at a time on it (either tct-button or tct-button2) you can do similar to what Satpal suggested and use:
$('button').on('click', function(){
$('.tct-button2').addClass('tct-button').removeClass('tct-button2'); //Add original class and Remove tct-button2 class
$(this).removeClass('tct-button').addClass('tct-button2'); //Add the class to current element
});
Here is the example http://jsfiddle.net/lee_gladding/xao46uzs/
to only affect buttons in the div the clicked one belongs to, use a similar method to:
$('button').on('click', function(){
$(this).parent('div').find('.tct-button2').addClass('tct-button').removeClass('tct-button2'); //Remove all class in that div
$(this).removeClass('tct-button').addClass('tct-button2'); //Add the class to current element
});
(You might want to use a better selector for the parent, possibly a class or what ever your actual html uses)
Example:
http://jsfiddle.net/lee_gladding/xao46uzs/3/

Element not reacting to JQuery Click

I have added Elements using Jquery inside PHP after loading them from the database. Each button has two classes, one controlling the GUI and another controlling the Click for particular button. The code is as under
echo "<script type='text/javascript'>$('.main').append('<button class=b_ui b$index>Change</button>'); </script>";
Now if I check the classes from Inspect Element perspective of the browser, it shows 2 classes. But when I click on it and get class of element using this code
$('.b_ui').click(function()
{
cls = $(this).attr('class');
alert('no. '+cls);
}
It shows only first class (GUI) and not the other which I want to use for handling click.
Any help ?
Put quotes around the class attribute. <button class=\"b_ui b$index\">Change</button>
You should use "on" method:
$(document).on('click', '.b_ui', function() {
cls = $(this).attr('class');
alert('no. '+cls);
});
When adding elements dynamically to the DOM, they are not accessible by jQuery like an element which was there at page load. say you have this div:
<div id="div"></div>
and you add some content with jQuery so it now looks like this:
<div id="div"><span id="span"></span></div>
you cannot refer directly to the span using jQuery with $('span[id=span]'), you have to target a containing element then filter which contained element you want:
$('#id').on('click','span',function(){});

Dynamically adding onchange function to drop down with jQuery

I have a couple of drop down boxes with ids country1, country2, ... When the country is changed in a drop down the value of the country shoudl be displayed in an alert box.
if I add the onchange handler for one box like this it works fine:
$('#country1') .live('change', function(e){
var selectedCountry = e.target.options[e.target.selectedIndex].value;
alert(selectedCountry);
});
But I need to do this dynamically for all drop down boxes so I tried:
$(document).ready(function() {
$('[id^=country]') .each(function(key,element){
$(this).live('change', function(e){
var selectedCountry = e.target.options[e.target.selectedIndex].value;
alert(selectedCountry);
});
});
});
This doesn't work. No syntax error but just nothing happens when the seleted country is changed. I am sure that the each loop is performed a couple of times and the array contains the select boxes.
Any idea on that?
Thanks,
Paul
The reason .live() existed was to account for elements not present when you call the selector.
$('[id^=country]') .each(function(key,element){ iterates over elements that have an id that starts with country, but only those that exist when you run the selector. It won't work for elements that you create after you call .each(), so using .live() wouldn't do you much good.
Use the new style event delegation syntax with that selector and it should work:
$(document).on('change', '[id^=country]', function(e) {
// ...
});
Replace document with the closest parent that doesn't get dynamically generated.
Also, consider adding a class to those elements along with the id attribute.
Instead of incremental ids I'd use a class. Then the live method is deprecated but you may use on with delegation on the closest static parent or on document otherwise.
$('#closestStaticParent').on('change', '.country', function() {
// this applies to all current and future .country elements
});
You don't need an each loop this way; plus events are attached to all the elements in the jQuery collection, in this case all .country elements.

Remove all classes except one

Well, I know that with some jQuery actions, we can add a lot of classes to a particular div:
<div class="cleanstate"></div>
Let's say that with some clicks and other things, the div gets a lot of classes
<div class="cleanstate bgred paddingleft allcaptions ..."></div>
So, how I can remove all the classes except one? The only idea I have come up is with this:
$('#container div.cleanstate').removeClass().addClass('cleanstate');
While removeClass() kills all the classes, the div get screwed up, but adding just after that addClass('cleanstate') it goes back to normal. The other solution is to put an ID attribute with the base CSS properties so they don't get deleted, what also improves performance, but i just want to know another solution to get rid of all except ".cleanstate"
I'm asking this because, in the real script, the div suffers various changes of classes.
Instead of doing it in 2 steps, you could just reset the entire value at once with attr by overwriting all of the class values with the class you want:
jQuery('#container div.cleanstate').attr('class', 'cleanstate');
Sample: http://jsfiddle.net/jtmKK/1/
Use attr to directly set the class attribute to the specific value you want:
$('#container div.cleanstate').attr('class','cleanstate');
With plain old JavaScript, not JQuery:
document.getElementById("container").className = "cleanstate";
Sometimes you need to keep some of the classes due to CSS animation, because as soon as you remove all classes, animation may not work. Instead, you can keep some classes and remove the rest like this:
$('#container div.cleanstate').removeClass('removethis removethat').addClass('cleanstate');
regarding to robs answer and for and for the sake of completeness you can also use querySelector with vanilla
document.querySelector('#container div.cleanstate').className = "cleanstate";
What if if you want to keep one or more than one classes and want classes except these. These solution would not work where you don't want to remove all classes add that perticular class again.
Using attr and removeClass() resets all classes in first instance and then attach that perticular class again. If you using some animation on classes which are being reset again, it will fail.
If you want to simply remove all classes except some class then this is for you.
My solution is for: removeAllExceptThese
Array.prototype.diff = function(a) {
return this.filter(function(i) {return a.indexOf(i) < 0;});
};
$.fn.removeClassesExceptThese = function(classList) {
/* pass mutliple class name in array like ["first", "second"] */
var $elem = $(this);
if($elem.length > 0) {
var existingClassList = $elem.attr("class").split(' ');
var classListToRemove = existingClassList.diff(classList);
$elem
.removeClass(classListToRemove.join(" "))
.addClass(classList.join(" "));
}
return $elem;
};
This will not reset all classes, it will remove only necessary.
I needed it in my project where I needed to remove only not matching classes.
You can use it $(".third").removeClassesExceptThese(["first", "second"]);

Categories