This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
jQuery attribute selector for multiple values
I have this
$('input:radio[name=foo]').change(function() {
blah();
});
$('input:radio[name=bar]').change(function() {
blah();
});
Can I do something like this?
$('input:radio[name=foo||bar]').change(function() {
blah();
});
what If I had another one?
$('input:radio[name=foo||bar||foobar]').change(function() {
blah();
});
I can't use class which would be ideal as this is a custom framework (not mine) that
generates the HTML which is overriding my class. Also there is no id selector available
just the name attribute. I think I'm stuck doing separate functions but wanted to pose the question to see if anyone can think outside the box on this one.
Note: this project uses jQuery 1.3.2 and I can't upgrade just yet. And before you say anything, yeah I'm with you on upgrading...
There is no 'or' character, but you can use multiple selectors - you just separate them by commas:
$('input:radio[name=foo], input:radio[name=bar]').change(function() {
blah();
});
Or better yet, use a class selector as this is exactly what they were designed for.
Unfortunately there isn't a simple selector for or within [attr] selectors. You can use a comma (,) to separate your selections:
$('input:radio[name=foo], input:radio[name=bar]').change(...);
Or if your selection happens to be longer, you can use $.fn.filter:
$('#foo #bar #baz .fizz .buzz input:radio').filter('[name=foo], [name=bar]').change(...);
I recommend reviewing the entire list of jQuery selectors.
jQuery's $() function uses CSS selectors (nearly all of CSS3 plus a few of its own). Their syntax has nothing whatsoever to do with JavaScript's logical operators.
Neither CSS3 nor jQuery offer a "match any of these", so you use a selector group instead:
$('input:radio[name=foo], input:radio[name=bar], input:radio[name=foobar]').change(function() {
blah();
});
Another alternative is adding a new filter for regex:
http://james.padolsey.com/javascript/regex-selector-for-jquery/
Then you can do something like
$('input:radio:regex(name, ^(foo|bar|baz)$)')
Your proposed solution does work on newer versions of jQuery. You can chain filter onto your query, though ...
$('input:radio').filter("[name=foo],[name=bar]").change(function() {
blah();
});
View and play with the jsfiddle here
http://jsfiddle.net/NAgv5/1/
Related
I was recently assigned a very small but complex task in jQuery, the requirement was quite simple, given the following HTML :
<div>
<span id="myid2151511" class="myclass23462362">....foobar....</span>
<span id="myid2151512" class="myclass23462362">....YoLO....</span>
<span id="myid2151513" class="myclass23462362">....lalal....</span>
<span id="myid2151514" class="myclass23462362">....foobar....</span>
</div>
What i have to do i recursively go through all the span under div, With a certain id and check if the values contained in the spans is foobar, So i can up with the following jQuery code:
$(function(){
$('div [id^="myid"]:contains("foobar"):last').css({'background' : 'rgb(227, 216, 22)' })
});
FIDDLE HERE
Its quite a complex bit of code by itself, but the jQuery documentation made it a cakewalk for me as for as understanding the code is concerned.
By now i am comfortable writing code like so in jQuery:
$('some-Element').somemethod().anothermethod().yetanothermethod();
Every function returns a value in the above jQuery statement, so chain ability becomes a reality.
but when i see code like so.
$('div [id^="myid"]:contains("foobar"):last').css({'background' : 'rgb(227, 216, 22)' });
I am thrown a bit off the hook(although i managed to write the above line myself), notice how alot of the filtering is done by a selector :last and :contains, to me they appear to be working much like some kind of a jQuery method. So my question is, how do these selectors in jQuery work in comparison to jQuery methods ?
If anybody could explain or give me a vague idea, it would be Fantastic.
EDIT ::
well to clarify my question in one line, to me $(".someClass").eq('10'); makes sense, but somehow $(".someClass:eq(10)") does't , i mean it works, but how on earth is it implemented internally ?(I wrote this edit after reading the answers below, and well this question has been thoroughly answered by now, but this edit is just to clarify my question.).
That's an interesting question. The short answer is they both accomplish the same thing. Of course though, there's always more to the story. In general:
$('div [id^="myid"]:contains("foobar"):last').css({'background' : 'rgb(227, 216, 22)' });
Is equivalent to:
$("div").find("[id^='myid']").filter(":contains('foobar')").last().css({'background' : 'rgb(227, 216, 22)' });
Most of the time when you call $(), jQuery is calling document.querySelectorAll(). This is a browser implemented function that grabs elements based on a selector. That complex string you create is passed to this method and the elements are returned.
Naturally, things implemented by the browser are faster than JavaScript so the less JavaScript and more C++, the better. As a result, your example passing everything as a selector is likely to be faster as it just sends it all to the browser as one call and tells it "do it." Calling $(), contains(), last() on the other hand is going to call querySelectorAll multiple times and therefore it will likely be slower since we're doing more JavaScript as opposed to letting the browser do the heavy lifting in one shot. There are exceptions though. JQuery generally calls querySelectorAll. However, there are times when it doesn't. This is because jQuery extends what querySelectorAll is capable of.
For example, if you do something like $(".someClass:eq(10)") per the jQuery documentation:
jQuery has extended the CSS3 selectors with the following selectors. Because these selectors are jQuery extension and not part of the CSS specification, queries using them cannot take advantage of the performance boost provided by the native DOM querySelectorAll() method. To achieve the best performance when using these selectors, first select some elements using a pure CSS selector, then use .filter().
So in that case, while $(".someClass:eq(10)") might seem to be faster, in reality $(".someClass").eq(10) or $(".someClass").filter(":eq(10)") is going to be faster since the first call will be executed as JavaScript code. The latter two will first call querySelectorAll to select by class, then only use JavaScript to find the 10th element. When jQuery has to do the selection in pure JavaScript, it does it using the Sizzle engine which is fast, very fast, but not faster than native code in the browser. So again, the short answer is, they're the same thing, the long answer is, it depends. If you're interested in all the extensions that fall into that category, the link to the jQuery documentation I included lists them.
First of all, yes nikhil was right. ID is unique identifier and can be only used once. If you are willing to apply same styles to several elements, or you to use it to select several elements together use class attribute. But however, i couldn't understand your question. But maybe this could help
there is function in javascript which is widely supported by almost all major browsers
document.querySelectorAll("div [id^=myId]");
in fact you could write your own library (well not as advanced one like jquery but)
var $ = function(selector){
return document.querySelectorAll(selector);
}
// and then you could use it like this
var elementsWithMyId = $("div [id^=myId]");
// where elementsWithMyId will contain array of all divs which's id start with myId
so as i understood your question, No. there is no magic happening behind jQuery selections it's just browser built in function which is kinda shortened by jquery. of course they added tons of new features, which would work like this:
var $ = function(selector){
var elementsArray = document.querySelectorAll(selector);
elementsArray.makeBlue = function(){
for(var i = 0; i < elementsArray.length; i++){
elementsArray[i].style.backgroundColor = "blue";
}
// so elementsArray will now have function to make all of its
// div blues. but if you want to have chain like that, we have to return this array not just make all of it blue
return elementsArray;
}
elementsArray.makeRed = function(){
for(var i = 0; i < elementsArray.length; i++){
elementsArray[i].style.backgroundColor = "red";
}
return elementsArray;
}
return elementsArray;
}
// so now you can use it like this
// this returns array which has options make blue, and make red so lets use make blue first
// makeBlue then returns itself, meaning it returns array which has again options of making itself red and blue so we can use makeRed now
$("div [id^=myId]").makeBlue().makeRed();
and thats it!
I am trying to solve a question.
I wrote the following code, and it works fine:
(function () {
if($('#target:contains("bold")')) {
$('#target span:first').css('font-weight','bold');
}
if($('#target:contains("strike")')) {
$('#target span').eq(1).css('text-decoration','line-through');
}
if($('#target:contains("blink")')) {
$('#target span:last').css('text-decoration','blink');
}
}) ();
Their solution is as follows:
(function () {
var target = $('#target');
var html = target.html();
html = html.replace('blink',"$&".blink());
html = html.replace('bold',"$&".bold());
html = html.replace('strike',"$&".strike());
target.html(html);
}) ();
I have the following questions:
I do not understand what is "$&" in "$&".blink(), "$&".bold() and "$&".strike(),
Are blink, bold and strike jQuery UI methods?
These are not jQuery methods. Everything in jQuery is either a function that of the form $.funcName() or a method that operates on a jQuery object, e.g. $(something).methodName().
These are regular Javascript methods of the String class: String.prototype.blink
, String.prototype.bold, String.prototype.strike. They just wrap their argument with the appropriate HTML element. However, they have been deprecated, because CSS is preferred these days rather than the old tags like <blink>, so you shouldn't use them.
"$&" is a feature of the .replace() method, it's automatically replaced with the original matching element. It's mostly useful when using a regular expression, since you don't know the exact string that will match the pattern.
Your solution to the problem doesn't look like it will work properly. It assumes that each word is in its own span, and also that bold is in the first span, strike is in the second span, and blink is in the third span. The objective of the exercise is to find the words wherever they are in the DIV, and put the appropriate style around just that word.
The JavaScript replace() method uses regular expressions. The $& syntax is shorthand for the matched expression; so it will represent blink, bold, and strike respectively.
As #Daniel A. White mentions in his answer, blink(), bold(), and strike() are deprecated methods from string.prototype for wrapping the source string in markup. The exact markup used will vary by browser; for instance, one may return <b>bold</b>, another <strong>bold</strong> and yet another <span style="font-weight: bold">bold</span>.
For what it's worth, while #Barmr's accepted answer is shorter, I find yours more elegant in that it's easy to understand, consistent in its results, and standards-based. That said, #Barmar raises valid concerns regarding the assumptions it makes and, therefore, its usefulness in a general context.
Those are deprecated methods for wrapping a string in a certain element.
String.prototype.blink reveals it to be a native method.
You can view those here:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/blink
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/bold
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/String/strike
I saw some code around the web that uses the following statement
if ($($(this)).hasClass("footer_default")) {
$('#abc')
.appendTo($(this))
.toolbar({position: "fixed"});
}
What is the use of $($(this)) and why is that necessary here?
Yes, $($(this)) is the same as $(this), the jQuery() or $() function is wonderfully idempotent. There is no reason for that particular construction (double wrapping of this), however, something I use as a shortcut for grabbing the first element only from a group, which involves similar double wrapping, is
$($('selector')[0])
Which amounts to, grab every element that matches selector, (which returns a jQuery object), then use [0] to grab the first one on the list (which returns a DOM object), then wrap it in $() again to turn it back into a jQuery object, which this time only contains a single element instead of a collection. It is roughly equivalent to
document.querySelectorAll('selector')[0];, which is pretty much
document.querySelector('selector');
You can wrap $ as many times as you want, it won't change anything.
If foo is a DOM element, $(foo) will return the corresponding jQuery object.
If foo is a jQuery object, $(foo) will return the same object.
That's why $($(this)) will return exactly the same as $(this).
There is no specific need for double-wrapping and $($(this)) is exactly the same as $(this).
That said, I once found this double-wrapping in one file in my project, committed by another developer. Tracking the changes through revision, turned out that it started as $($(this).find('selector').first()) - that is, the result of some selector was wrapped to create a new object. Then for whatever reasons, the selector was removed and only the double-wrapping of this remained. Needless to say, on the next commit it was changed to $(this).
As explained before me, $($(this)) and $(this) are absolutely identical. jQuery returns the same jQuery object if you try to wrap it more than once.
Additionally, for performance considerations it is a good practice to reuse jQuery objects - it is quite expensive to create jQuery objects, especially the ones with complex selectors. Example:
var $this = $(this);
if ($this.hasClass("footer_default")) {
$('#abc')
.appendTo($this)
.toolbar({position: "fixed"});
}
Just google for 'jQuery best practices' - it will take a 30 min for you to learn these basics and you will use jQuery way more effectively.
There is no meainig of doing that.
The following code return the same:
console.log($($(this)).hasClass("footer_default"))
console.log($(this).hasClass("footer_default"))
a boolean value depenging on if the selected element has or not the class footer_default:
.hasClass( className )Returns: Boolean
Demo: http://jsfiddle.net/IrvinDominin/aSzFn/
$(this) and $($(this)) both return jquery object.
There is no difference between these two.
I was just poking around with jQuery, and I stumbled upon the Find function.
I tested like this:
$(document).ready(function(){
$('button').click(function(){
$('div').find('div').fadeOut(2000);
});
});
And this
$(document).ready(function(){
$('button').click(function(){
$('div div').fadeOut(2000);
});
});
And both produce the exact same result.
Whats the difference? :)
In your example there is no difference but there are cases that you can not use the first one, for example let't say you have an element as the parameter of a function and you want to find divs inside it, then you have to use the "Find" method.
function foo(index, el)
{
$(el).find("div")...
}
But when you know the exact path, obviously the second approach is more robus.
There is no difference.
If you already have a jQuery object, the find method is useful.
Otherwise, a single selector is simpler.
Most selectors have method equivalents (.children(), .first(), .not()) for this reason.
The method versions also allow you to call .end() to go back to the previous object.
They both do exactly the same thing, but in older browsers where document.querySelectorAll() is not available (Old IEs) $("div").find("div"); is quicker, as Paul Irish confirms in this comment here.
Another thing to note is that in jQuery you can also do this:
$("div", "#some-element")
Which would search for div inside of #some-element. jQuery actually converts this into:
$("#some-element").find("div")
So it's always suggested to use .find() rather than pass in a context.
In this specific case, they do the same thing. Note that find() will traverse all the descendants of the matched elements.
We're considering switching our site from Prototype to jQuery. Being all-too-familiar with Prototype, I'm well aware of the things about Prototype that I find limiting or annoying.
My question for jQuery users is: After working with jQuery for a while, what do you find frustrating? Are there things about jQuery that make you think about switching (back) to Prototype?
I think the only that gets me is that when I do a selection query for a single element I have to remember that it returns an array of elements even though I know there is only one. Normally, this doesn't make any difference unless you want to interact with the element directly instead of through jQuery methods.
Probably the only real issue I've ever ran into is $(this) scope problems. For example, if you're doing a nested for loop over elements and sub elements using the built in JQuery .each() function, what does $(this) refer to? In that case it refers to the inner-most scope, as it should be, but its not always expected.
The simple solution is to just cache $(this) to a variable before drilling further into a chain:
$("li").each(function() {
// cache this
var list_item = $(this);
// get all child a tags
list_item.find("a").each(function() {
// scope of this now relates to a tags
$(this).hide("slow");
});
});
My two pain points have been the bracket hell, can get very confusing
$('.myDiv').append($('<ul />').append($('<li />').text('content')));
My other common issue has to do with the use of JSON in jQuery, I always miss the last comma,
$('.myDiv').tabs({ option1:true, options2:false(, woops)});
Finally, I've been using jQuery for about 6 months now and I don't think I'll ever go back to prototypes. I absolutely love jQuery, and a lot of the tricks they use have helped me learn a lot. one cool trick that I like is using string literals for method calls, I never really did that too much with prototypes.
$('.myDiv')[(add ? 'add' : 'remove') + 'Class']('redText');
(The only thing I can think of is that this is the element instead of a jQuery object in $("...").each(function)-calls, as $(element) is more often used then just the element. And that extremly minor thing is just about it.
Example of the above (simplified and I know that there are other much better ways to do this, I just couldn't think of a better example now):
// Make all divs that has foo=bar pink.
$("div").each(function(){
if($(this).attr("foo") == "bar"){
$(this).css("background", "pink");
}
});
each is a function that takes a function as parameter, that function is called once for each matching element. In the function passed, this refers to the actual browser DOM-element, but I find that you often will want to use some jQuery function on each element, thus having to use $(this). If this had been set to what $(this) is, you'd get shorter code, and you could still access the DOM element object using this.get(0). Now I see the reason for things being as they are, namely that writing $(this) instead of this, is hardly that cumbersome, and in case you can do what you want to do with the DOM element the way it is is faster than the way it could have been, and the other way wouldn't be faster in the case you want $(this).)
I don't think there are any real gotchas, or even any lingering annoyances. The other answers here seem to confirm this - issues are caused simply by the slightly different API and different JavaScript coding style that jQuery encourages.
I started using Prototype a couple of years ago and found it a revelation. So powerful, so elegant. After a few months I tried out jQuery and discovered what power and elegance really are. I don't remember any annoyances. Now I am back working on a project using Prototype and it feels like a step back (to be fair, we're using Prototype 1.5.1).
If you reversed the question - "What Prototype annoyances should I be aware of as a jQuery user?" - you would get a lot more answers.
Nope. Nada. Nyet.
.each:
jQuery (you need Index, even if you're not using it):
$.each(collection, function(index, item) {
item.hide();
});
Prototype (you're usually using the item, so you can omit the index):
collection.each(function(item) {
item.hide();
});
This is really only an annoyance if you're doing a lot of DOM manipulation. PrototypeJs automatically adds its API to DOM Elements, so this works in prototypejs (jQuery of course doesn't do this):
var el = document.createElement("div");
el.addClassName("hello"); // addClassName is a prototypejs method implemented on the native HTMLElement
Even without running the native element through the $() function.
PS: Should note that this doesn't work in IE.