I find my self doing this a lot:
$(document).on("click","li",function(){
$(".selected").removeClass("selected"); // Remove any old selected
$(this).addClass("selected"); // Apply selected to this element
});
Is there a better and less repetitive way of doing a task like this? Like toggle a class. Btw, only one element can be selected at a given time.
Thanks.
A more efficient way is to keep track of the last selected item:
var $selected = null;
$(document).on("click", "li", function() {
if ($selected) {
$selected.removeClass('selected');
}
$selected = $(this).addClass('selected');
});
Of course, this should work as long as that particular function is the only one that will ever add / remove the selected class.
This could optionally be wrapped inside a closure to remove the $selected variable.
Btw, using document as the anchor for your delegation isn't best practice. It's better to choose the nearest node that will not get removed from the document.
Update
As Kevin B has mentioned, you could eliminate the branch like so:
var $selected = $();
$(document).on("click", "li", function() {
$selected.removeClass('selected');
$selected = $(this).addClass('selected');
});
The ability to use $() was introduced in 1.4; before that you would use $([]).
You can do this:
<script>
$(document).ready(function(){
$(this).on("click", "li", function() {
$(this).addClass('selected').siblings().removeClass('selected');
});
});
</script>
After debating with Jack I propose mine.
Assuming your list is here :
var $myList = $('#list');
Then:
$myList.on("click","li",function(){
$(".selected",$myList).removeClass("selected"); // Remove any old selected
$(this).addClass("selected"); // Apply selected to this element
});
or
$myList.on("click","li",function(){
$(this).siblings(".selected").removeClass("selected"); // Remove any old selected
$(this).addClass("selected"); // Apply selected to this element
});
Your way of doing it is good enough for me but Jack's is faster and mine is in between both.
I like this one because you don't need to assume there will only be one selected element. And searching is faster when we provide context as far as I know
Thinking about this, you could keep your list elements in a variable, such as:
var $liElements = $('#yourContainer > li');
$(document).on("click","li",function(){
$liElements.not($(this)).removeClass("selected");
$(this).addClass("selected");
});
The notion of keeping track of the current element is the same as the other answers, but you can wrap this logic up cleanly in a function such as
function class_swapper=function(cls){
var cur;
return function(elt){
if (cur) { cur.classList.remove(cls); }
elt.classList.add(cls);
cur=elt;
};
};
A call to class_swapper returns a function used to actually apply the specified class to a particular element (and remove it from the previous one, which is remembered inside the function). You can use this as follows:
var swapper=class_swapper("selected");
swapper(elt1);
swapper(elt2);
or in terms of your example
$(document).on("click","li",function(){swapper(this);});
I've used classList.add and classList.remove, which is a classy way (ouch) of manipulating classes in modern browsers, but of course these could be replaced by jQuery's addClass etc. as necessary.
Related
Currently, I have this code:
$(document).ready(function(){
// #filtertab-00 replace this with your element id
$('#filtertab-00 .box-content .es-nav .elastislide-next, #filtertab-00 .box-content .es-nav .elastislide-prev').click(function() {
// trigger lazy load
$("#filtertab-00 img.lazy").each(function(i) {
$(this).delay(150*i).fadeIn(1000, function() {
var src = $(this).attr("data-original");
$(this).attr('src',src);
});
});
});
});
and i want to use this function to target object names (id) as below:
filtertab-00
filtertab-10
filtertab-20
filtertab-30
filtertab-40
filtertab-50
filtertab-60
....
filtertab-90
Does anyone know how to use the loop function to get it work?
i just want this:
when i click pre or next button after i select a tab(name varies from filtertab-00 to filtertab-90),it will activate lazyloading for images at current selected tab.
any idea is welcome!
Perhaps you could use jQuery's attribute-starts-with selector. You can then just select all IDs that begin with filtertab- using jQuery like this:
$('div[id^="filtertab-"]').each( //magic goes here );
Note: This method is slow because it has to search the DOM for elements with IDs that meet the criteria, but it does the job. I've never noticed an appreciable latency.
This is solved through selector magic as filoxo described but since you want the images, here's another version involving find() to get your actual images.
$('div[id^="filtertab-"]').find("img.lazy").each(function(i) {
$(this).delay(150*i).fadeIn(1000, function() {
var src = $(this).attr("data-original");
$(this).attr('src',src);
});
});
In addition to that, check out the impressive list of jQuery selectors. They cover a lot of ground :)
I am storing a div which gets selected
var selectedCell = null;
$(".selectableBox").on('click', function (event) {
selectedCell = $(this);
}
Later I want to hide one of selectableCell's children name selectableCellChild
$('#deleteConfirmed').on('click', function (event) {
selectedCellList.($'selectableCellChild').hide();
});
How can I correctly hide this child div? I know the syntax of the above example isn't right, and I have tried it many ways including using children() and next() methods of selectedCellList
selectedCellList.find('{selectableCellChild}').hide();
Where selectableCellChild is a placeholder for the real selector of the cell.
I have tried it many ways including using children() and next()
children - traverse only one level deep.
find - traverse the all the DOM levels deep.
next select the next immediate sibling.
For the second part, this is what you want:
$('#deleteConfirmed').on('click', function (event) {
$(selectedCellList).find('.selectableCellChild').hide();
});
If I understood correctly, you are trying to hide the children of clicked div. Try like below,
var selectedCell = null;
$(".selectableBox").on('click', function (event) {
selectedCell = $(this);
}); //Your missed );
$('#deleteConfirmed').on('click', function (event) {
//v-- Changed from selectedCellList to selectedCell as this is the clicked div.
selectedCell.find('.selectableCellChild').hide();
//assuming selectableCellChild-^ is class of child elements in the clicked div
});
Use .find.
selectedCellList.find('selectableCellChild').hide(); // I hope selectableCellChild isn't your real selector, it won't work
Also, when declaring your variable, make it a jQuery object since you intend to store a jquery object in it to avoid undefined method errors.
var selectedCell = $();
I am trying and failing to add datepicker to inputs that are created dynamically.
They have different id's and I am specifically targeting the new input and calling datepicker.
In the jsFiddle example below it only works for the 2nd input (first one datepicker is called on) and does not work for any others after that.
Here is the jsFiddle: http://jsfiddle.net/TJfbc/1/ Press the plus sign to add more.
Note: I am aware the first element will not have the datepicker.
Here's a cleaner alternative
$(function() {
//append one handler to the parent to detect append actions
$('.action_items').on('click', '.expand', function() {
var $el = $(this);
$el.parent()
.clone()
.appendTo($el.closest('.action_items'))
.find('input')
.removeClass('hasDatepicker')
.each(function () {
newName = this.name.slice(0,6) + (parseInt(this.name.slice(6)) + 1);
this.name = newName;
this.id = newName;
})
.datepicker();
//change text, remove original handler, add the remove handler
$el.text('-').off('click').on('click',function(){
$(this).parent().remove();
});
})
});
http://jsfiddle.net/TJfbc/27/
You need to "refresh" the previous textfield that has already class of 'hasDatepicker' before you can initialize a new one
new_action_item.find('.dpDate').removeClass('hasDatepicker').datepicker()
An improvement on readability:
No need to repeatedly call $() on new_action_item since clone() returns an already jQuery object
I have have the following
<div id="dualList"></div>
And I have written a plugin but for the sake of testing I have stripped it away. I am having problems with the plugin displaying the id of the div.
<script>
(function($) {
$.fn.DualList = function() {
var thisControl = $(this);
alert(thisControl.attr('id'));
}
})(jQuery);
</script>
And its bound on document on ready using
$("#dualList").DualList();
Any ideas why the ID isnt echoing out?
First off, as far as I can tell, it does work.
However, there are a couple of things that are not optimal in your code. You can't be sure that there's just one onject selected (it could be a class selector, for all you know). You should therefore iterate through all the members of the selection. Second, you don't need the jQuery constructor to get the id property. You can do it just with this.id:
$.fn.DualList = function() {
return this.each(function() {
alert (this.id);
});
};
Working example of this style of code
Widget is a collection wherever invoked, so
$(this.element[0]).attr("id")
will get you the id of the first element and so on..
is there a way to make a toggle function that first of all toggles only one css style element, such as background-color or something like that. and that selects an id instead of a class, for i know of the toggleClass, but im just wondering if it's possible with ids instead?
$("#gallery").load('http://localhost/index.php/site/gallerys_avalible/ #gallerys_avalible');
$('li').live('click', function(e) {
e.preventDefault();
if(!clickCount >=1) {
$(this).css("background-color","#CC0000");
clickCount++;
}
console.log("I have been clicked!");
return false;
});
You really should use classes for that. IDs are unique within a page and should be used as points where you catch events ( via $.live() or some other method which uses event delegation ). Besides , if you think of using IDs because they have higher specificity in CSS rules , then you are going the wrong way.
In short: bad idea, stick to toggling classes.
EDIT:
After reading OP's comment - I believe this is what he is looking for a way to highlight an "active" link on click. And Yes, teresko is definitely right that you should be toggling the classes, not the ID's.
This is the essence of a jQuery snippet that you may be looking for:
$("li").bind('click', function(){
// remove the active class if it's there
if($("li.active").length) $("li.active").removeClass('active');
// add teh active class to the clicked element
$(this).addClass('active');
});
Demo
Check out the jQuery toggle api.
It's a little confusing because a simple google search on jQuery toggle brings you to the show/hide toggle documentation. But, .toggle() can be used to alternate functions - you can even add more than two.
like so...
$("el").toggle(
function(){
$(this).css('background-color', 'red');
},
function(){
$(this).css('background-color, ''); // sets the bg-color to nothing
});
jQuery doesnt has toggleId() function . But you can create your own id toggle function .
function toggleId(className,id)
{
var tag = document.querySelector('.'+className);
tag.id = tag.getAttribute("id") ? '' : id;
}
toggleId("myClass","id");
this will toggle id ( id and NULL ) of myClass element .
another example for toggling between two id
suppose you want to toggle between two id ( id1 and id2 ) of an element then
function toggleId(className,id1,id2)
{
var tag = document.querySelector('.'+className);
tag.id = tag.getAttribute("id") ? id2 : id1;
}
toggleId("myClass","id1","id2");
$("click-element").bind('click', function(){
if($("your-element").is('#yourIdValue')){
$('your-element').removeAttr('id');
}else{
$('your-element').attr('id', 'yourIdValue');
}
});
});