Jquery Selector - Multiple Items - javascript

Say I have two jquery selections:
var txtA = $('#txtA');
var txtB = $('#txtB');
In order to attach the same event function, is this the neatest way, or am I missing an obvious piece of syntax or jquery wizardness?
$(jQuery.merge(txtA , txtB )).click(function () { alert('hello'); });
Thanks.

.add() should do (provided that you have already populated txtA and txtB and want the reuse those selections.):
txtA.add(txtB).click(function () {
alert('hello');
});
Given a jQuery object that represents a set of DOM elements, the .add() method constructs a new jQuery object from the union of those elements and the ones passed into the method. The argument to .add() can be pretty much anything that $() accepts, including a jQuery selector expression, references to DOM elements, or an HTML snippet.

$('#txtA, #txtB').click(function () { alert('hello'); });
may work for you

Here is what I have done:
$()
.add(elementOne)
.add(elementTwo)
.add(elementThree)
.click(function() {
alert('hello');
});

You can just do:
$("#txtA, #txtB").click(function () { alert('hello'); });
The same as a CSS selector, cool huh! :-)

Related

How to refresh the jQuery .each() function?

Explaining by example:
$(selector).each(function () {
if (expression) {
$(this).next().remove();
}
....
});
Based on an expression I remove an element that also are a part of the selector, and in effect are removing the next element the .each() function will get.
The .each() function doesn't seem to care and are running it's code on the removed element breaking the iteration process on my code in the each function. Basically meaning a counter in the .each() function will count the deleted element even though it shouldn't.
Is there a way to refresh or update the .each() function so it skips elements that where removed after its initiation?
Better to filter your elements before:
$(selector).filter(function() {
if (expression) {
return false;
}
}).each(function() { .. });
I do not think you can modify the collection from inside the each call.
Even better, you can split this in two calls, since if you do all of it in one call only, the selector will be cached:
$(selector).filter(function() {
return expression;
}).next().remove();
// and then
$(selector).each(function() { ... }); // now *without* removed elements.
The first time you query the DOM with $(selector) you are given back a jQuery collection containing all the elements (specifically, references to the elements) that satisfy that selector. Any changes to the DOM do not affect that collection. If you happen to modify the DOM in such a way that the elements in the collection no longer satisfy the initial selector, this will not be reflected.
The correct solution to this problem is to not modify the DOM in the each loop, and basically find another way to solve your problem. But a simple (computationally expensive) solution is just to recheck the element on the initial selector upon iteration... you can use the .is method to achieve this:
$(selector).each(function () {
var $this = $(this);
if ($this.is(selector)) {
if (expression) {
$this.next().remove();
}
}
....
});

Filter the $(this) element in loop jquery

I am trying to perform an action to other elements than the $(this) item
$('.items').click(function(){
var myitem = $(this);
$(".items").each(function() {
if (myitem == $(this)){
break;
} else {
//perform action
}
});
});
Where did I go wrong? Is there any better method?
Try to use the .not() function to filter out the current element,
$('.items').click(function(){
$('.items').not(this).each(function(){
//perform action here.
});
});
What went wrong?
When using the jQuery method (a.k.a. $) a new instance of the jQuery object is created, containing a list of elements matching your selector along side with a rich prototype of jQuery's methods.
Your mistake was to try and compare two different instances.
What you could have done was to compare the elements themselves by making the following changes:
// change this:
var myitem = $(this);
// to this:
var myitem = this;
// change this:
if (myitem == $(this)){
// to this:
if (myitem == this){
Unless you intend to use the jQuery object functionality there's no reason to initiate a new instance. Simply use the element itself when possible. It's a best practice to avoid such use cases. Performance wise.
Best solution
But the best solution in your case is what was mentioned in all other answers, using jQuery's not method to exclude the element from the newly created instance.
Using.not() to avoid
Try this
$(".items").not($(this)).each(function() {
});
OR
As per your code
$(".items").not(myitem).each(function() {
});
you can use not() to ignore the element which is clicked:
$(".items").not(this).each(function() {
});

select html element id using jquery and .change()

I have several <select> boxes all using the same prefix and I would like to set up a recursive function to essentially do the work for me.
$('[id^="by_"]').change(function(e)
{
var elem = e;
console.log(e.value);
});
Based on this code is my intention pretty clear? Am I on the right track?
console prints out: undefined
I think you're on the right track - the selector you're using matches a prefix of "by_", and you're binding the change event to all of them. Make sure you put this in $(document).ready or similar. Are you having any problems with this code? Instead of using the e parameter, I would just use this inside of the function to refer to the element and $(this) to get the jQuery object of it. So to get the value, you'd use:
this.value
// or
$(this).val()
(ignore the e and elem stuff, although it wouldn't be a bad idea to store $(this) in something like elem so you can have a reference to it instead of re-creating the jQuery object every time you need it)
When using callbacks to events with jQuery, the (first) parameter of the callback is an event object that explains many things about the event that occurred ( http://api.jquery.com/category/events/event-object/ ) and does not hold the element - that's what this is for!
e in your code is the event object which has no value property, you should use this instead:
$('[id^="by_"]').change(function(e) {
var elem = this;
console.log(this.value);
});
Or if you want to use event object, you can use target property:
e.target.value
Since you're already using jQuery, why not something like this:
$('[id^="by_"]').change(function(e)
{
var $elem = $( this );
console.log( $elem.val() );
});
Isn't it more something like that:
$('[id^="by_"]').change(function()
{
console.log($('option:selected',this).val());
});
​
jsfiddle

Compare 'e.target' to a jQuery object

What I want to do:
( clickedObject === someDiv ) //returns true or false
What I tried
( $(e.target) === $('.selector') ); //returns a false negative.
My workaround
( $(e.target).attr('class') === $('.selector').attr('class') ); //works as intended, not so clean though.
What is the right way to compare the object I clicked to an object in the DOM?
To check if e.target has this class you can use the hasClass function.
if ($(e.target).hasClass("selector"))
Or, if you really want to compare objects, note that jQuery selectors return a collection of items, so I think you'll want
if (e.target === $('.selector')[0])
You're close. Use .is() instead:
if($(e.target).is('.selector')) {
// Your code
}
The trick here is that you wrap e.target in a jQuery object to allow it access to all the useful jQuery methods.
If you're just seeing whether e.target has a certain class, try using .hasClass() in place of .is():
if($(e.target).hasClass('selector')) {
// Your code
}
Either method works, although .hasClass() is a little clearer as to what the code does, and is faster than using .is()
If you want to match the element that the event is attached to you can use $(this), or if you want to find which element triggered the event use $(event.target).
Below is an example of both of these.
http://jsfiddle.net/Phunky/TbJef/
Unless you're using event delegation these will be the same though and if there the same element.
Obviously using .is() function is the best solution here.
If you find yourself doing such comparison, try to check if it is possible to use embedded jQuery mechanisms like this:
$(element).on("click", ".selector", function() {
alert("clicked");
});
Second argument in the .on() method is a target selector. When using this construction (read more: http://api.jquery.com/on/#direct-and-delegated-events) there will be no need to make any additional comparisons.
https://jsfiddle.net/m5zysufy/
$(document).click(function (e) {
e.stopPropagation();
var container = $('.dropdown-list').attr('class');
if ($(e.target).attr('class') == container) {
$('.dropdown-menu').slideToggle();
} else {
$('.header .header-elem .dropdown-nav .dropdown-menu').slideUp();
}
});

jQuery .wrap() question

i'm having some problems with jQuery
$(document).ready(function() {
var foo = $("<div><h1>Bar</h1><p>Hi</p><h1>Baz</h1><p>bye</p></div>");
foo.filter("h1,h2").map(function(id) {
$(this).wrap('<span color="red"/>');
});
alert(foo.html());
});
This code outputs
<h1>Bar</h1><p>Hi</p><h1>Baz</h2><p>bye</p>
The span's are nowhere to be seen. What am I doing wrong?
It doesn't have any effect because .filter() filters elements at that level, you could need .find() to get descendants like this:
$(document).ready(function() {
var foo = $("<div><h1>Bar</h1><p>Hi</p><h1>Baz</h1><p>bye</p></div>");
foo.find("h1,h2").wrap('<span color="red"/>');
alert(foo.html());
});
You can test it out here. Also note you should use .each() instead of .map() for looping...but there's no need here, since you can just call .wrap() directly.
You don't want to use filter here, you want to use find. Also, why are you using map?
$(document).ready(function() {
var foo = $("<div><h1>Bar</h1><p>Hi</p><h1>Baz</h2><p>bye</p></div>");
foo.find("h1,h2").wrap('<span color="red"/>');
alert(foo.html());
});
Live test
First off: your markup is invalid (Baz is wrapped by an opening h1 and a closing h2). But the .map reference says you need to return the value.
$(document).ready(function() {
var foo = $("<div><h1>Bar</h1><p>Hi</p><h1>Baz</h1><p>bye</p></div>");
var bar = foo.find("h1,h2").map(function(id) {
return $(this).wrap('<span color="red"/>');
});
});
You need .find() instead of .filter() since the heading elements are nested.
var foo = $("<div><h1>Bar</h1><p>Hi</p><h1>Baz</h1><p>bye</p></div>");
foo.find("h1,h2").wrap('<div color="red"/>');
Also, I changed it to wrap using a <div> instead of a <span> since I don't think it is valid to have a <span> wrapped around heading elements.

Categories

Resources