Wrapping twice an HTML element with jQuery is a safe operation, since it returns an instance of the same DOM element:
var $a = $('#foo');
var $b = $($a);
alert($b.get(0) === $a.get(0)); // true
It allows a flexible setup of configuration objects, which may contain either selectors, or DOM elements, or jQuery instances.
I didn't know it, so in my personal library I extended jQuery with methods to safely wrap and unwrap objects.
Is there in the jQuery core a safe backward operation to unwrap DOM elements from their relative jQuery instances?
I mean something acting like that:
function unwrap(obj) {
return (obj instanceof jQuery) ? obj.get(0) : obj;
}
which is smart enough to allow avoiding that conditional check each time.
Detect DOM object vs. jQuery Object seems to contain the answer to this question.
Each jQuery object has a jquery property. Something like:
function unwrap(obj) {
return (obj.jquery) ? obj.get(0) : obj;
}
It would make more sense to wrap everything in jQuery then just grab the 0th element out of the resulting array:
jQuery( elem )[0];
If passed a jQuery object, jQuery( jQueryObject ) will return the same elements in the same order. If you pass an element this returns the element. If you pass a jQuery object, this will return the first element inside it. If you pass a selector, this returns the first match in the DOM.
We use a similar technique in jQuery UI to basically resolve whatever selector/element/jquery object you passed in the options to a widget.
Related
I have read the JQuery documentation, and while much attention is devoted to what you should pass the function, I don't see any information on what it actually returns.
In particular, does it always return an array, even if only one element is found? Does it return null when nothing is found? Where is this documented?
I understand that jquery methods can be applied to the return value, but what if I want to just use the return value directly?
From Rick Strahl's description:
The jQuery Object: The Wrapped Set:
Selectors return a jQuery object known
as the "wrapped set," which is an
array-like structure that contains all
the selected DOM elements. You can
iterate over the wrapped set like an
array or access individual elements
via the indexer ($(sel)[0] for
example). More importantly, you can
also apply jQuery functions against
all the selected elements.
About returning nothing:
Does it always return an array? Does it return null?
You always get the same thing back, whether or not it has any contents is the question. Typically you can check this by using .val() (e.g. $('.myElem').val())
It doesn't return an array, it returns a jQuery object. The jQuery object is what contains all the special jQuery methods.
It never returns null, or another type. If one element is found, the jQuery object will have only one child. If no elements are found, the jQuery object will be empty.
As another answerer mentioned, it always returns the jQuery object.
This object always contains an array of elements (even if it is an empty array, or an array with just one object).
If you'd like to use the returned object "directly", as in, as a plain element, you can do one of the following:
$('selector')[0] // element
$('selector').get(0) // element
$('selector').length // number of elements in the array
The jQuery function (i.e. "$") always returns a jQuery object in every instance.
From the jQuery documentation:
The jQuery object itself behaves much like an array; it has a length property and the elements in the object can be accessed by their numeric indices [0] to [length-1]. Note that a jQuery object is not actually a Javascript Array object, so it does not have all the methods of a true Array object such as join().
The fact that $() always returns the jQuery function lets you chain jQuery function calls judiciously.
Jquery selector mechnism
$("..") , the jquery selector, is used to select matched elements.
Return value
It always return an array-like jquery object, which has a length property,
Call method on returned jquery object
Methods of jquery could be called on the object, and apply to those selected elements,
Access original element by index
The selected elements, are store as property of the object, their property name are index numbers start from 0,
thus could be accessed by index, start from 0,
after get the original element, you can treat it as if get by document.getElementXxx().
Wrap an original element to a jquery object
After get the original element, you can wrap it to be a jquery object, by calling $(originalEle),
then you can call jquery methods on the wrapped object.
According to firebug, it returns an array of objects that match to your selector. But this array is a jQuery object, that more methods than a simple Array.
Their documentation lists a few of the core calls you can use with "$" and what they return
This is not actually a jQuery question, but jQuery does something I would like to be able to do with other objects.
I notice that jQuery returns the number of elements using the .length property. However, the jQuery object is not actually an array, so the number of elements is not naturally available that way.
I presume that the jQuery object uses numbered keys for the actual elements, since [n] returns one of them.
How is it possible to have a .length property of a non-array automatically updated when elements are added or removed? Or is that manually maintained when jQuery adds or removes elements?
Thanks
As you've observed, a jQuery object is not actually an array. Thus, the .length property is just maintained manually by any method that might actually change the internal contents of the array-like list of DOM objects.
This works fairly easily with a jQuery object because very few methods actually change the list of DOM objects in an existing jQuery object. Most jQuery methods such as .filter() that operate on the list of DOM element in a jQuery object actually return a new jQuery object and the original jQuery object is not modified.
Even a jQuery method like .add() or .slice() do not modify the existing jQuery object, but instead return a new jQuery object with the appropriate modification in it.
If you trace through the jQuery source and look at how a lot of jQuery objects are created, pretty much all the methods that operate on a given jQuery object go through .pushStack() which calls jQuery.merge() which manually sets the .length property on the new jQuery object.
If you look at the code for the main jQuery constructor $(someSelector), it does some sort of document query, builds the internal array-like list of DOM nodes, then manually sets the .length property.
It’s manually maintained. Compare:
var l = [];
console.log(l.length); // 0
l[0] = 0;
console.log(l.length); // 1
var l = $([]);
console.log(l.length); // 0
l[0] = 0;
console.log(l.length); // 0
I can't understand the difference between $("") and $.find(""). They behave differently when nothing is matched but you try to do something with the result (like call toggle()).
$("").toggle(); // No error
$.find("").toggle(); // An error
$("body").find("").toggle(); // No error!
$($.find("")).toggle(); // No error
Why? :-)
In my context I have a function that uses $ to search for elements globally and has no problems when nothing matches. Now I want to allow the function to search only inside specified element (wrapped in a jQuery object). But it still should work if I pass $ itself.
$.find("") returns an empty array so it throws an error when you use [].toggle() as array has no toggle method.
And wrapping it inside jQuery i.e. $ like $($.find("")) returns an empty object Object[] and using toggle() in jQuery object won't throw an error.
$.find is internal CSS selector engine (Sizzle) and the function returns just and array of found elements. It's not jQuery instance and hence doesn't have jQuery prototype methods like toggle. (Thanks #dfsq)
There's no shorthand method $.find for find in jquery
This is what the official jQuery doc has to say about .find method:
Get the descendants of each element in the current set of matched
elements, filtered by a selector, jQuery object, or element.
The difference between $.find("") and $("").find("") is:
$.find begins traversing the DOM from the very top of the DOM tree, whereas $("").find start traversing the DOM from the specified DOM element and tries to find it's children.
Actually, toggle is a jQuery function which is only available within a jQuery object BUT $.find() does not return a jQuery object instead it returns vanilla JavaScript object. Hence the error.
Whereas any jQuery selector will return a jQuery object hence, if you convert this $.find to jQuery object then it works.
You can try the following code to check if an object is jQuery object or not.
$("#mainbar") instanceof jQuery
//Output: true
$.find("#mainbar") instanceof jQuery
//Output: false
$($.find("#mainbar")) instanceof jQuery
//Output: true
See official jQuery documentation, which states:
Given a jQuery object that represents a set of DOM elements, the .find() method allows us to search through the descendants of these elements (…)
So in other words, .find() only works correctly when you want to find something inside already selected elements.
What's the jQuery equivalent for each():
$(".element").each(function(){
// do stuff
});
when attaching a function to a single element, like #element ?
You can always reference the jQuery object in a variable:
var $el = $('#element');
...then manipulate it.
$el.doSomething(); // call some jQuery methods from the cached object
$el.doSomethingElse();
If the reason you wanted .each() was to reference the DOM element as this, you don't really need the this keyword to do it, you can simply grab the DOM element out of the jQuery object.
var element = $('#element')[0]; // both of these give you the DOM element
var element = $('#element').get(0); // at index 0
The two of these are equivalent, and will retrieve the DOM element that would be referenced as this in the .each().
alert( element.tagName ); // alert the tagName property of the DOM element
alert( element.id ); // alert the ID property of the DOM element
I'd note that it isn't necessarily bad to use each to iterate over a single element.
The benefits are that you have easy access to the DOM element, and you can do so in a new scope so you don't clutter the surrounding namespace with variables.
There are other ways to accomplish this as well. Take this example:
(function( $ ) {
// Inside here, "this" will refer to the DOM element,
// and the "$" parameter, will reference the jQuery library.
alert( this.tagName );
// Any variables you create inside will not pollute the surrounding
// namespace.
var someVariable = 'somevalue'; // is local to this function
}).call( $('#element')[0], jQuery );
To directly answer your question, .each() operates normally on element sets of any size including 1.
You can also omit the .each() call completely and just call jQuery methods on $('#element'). Remember that you can chain most if not all jQuery method calls as they return the jQuery object. This even works on multiple elements for the matter, depending on what the methods do.
$('#element').doSomething().doSomethingElse();
If you need to reference the object multiple times, make a variable:
var $elm = $('#element');
$elm.doSomething();
doSomethingElse($elm);
Use first().
each() matches all elements, while first() matches only the first.
There are other selectors too. When you use the id in the selector, you will only get one element. This is the main difference between .element and #element. The first is a class that can be assigned to many elements, while the second is an id that belongs to only (at most) one element.
You can still use each if only one (or 0) element is returned. Also, you can skip each altogether if you want to link an event. You use each when you want to execute a specific function for each element in the list of elements.
If there is only 1 element, you can access it normally using the selector.
$('#your_element').your_event(function() {
});
Behind the scenes, each is just a for loop that iterates through each element in the map returned by jQuery.
It is essentially† the same as:
var i, map = $('...selector...');
for (i = 0; i < map.length; i++)
{
someFunction(i, map[i]);
}
† There's more to it than this, involving calling the function in the context of the map element etc.
It's implementation is to provide a convenient way to call a function on each element in the selection.
Do you mean like $('#element').children().each()
supposing you have something like a ul with an id and you want the li each inside it?
If the intention is to call a (non-jQuery) function in a new scope I think using "each" still is a valid (and probably the most elegant) way and it stays true to the jQuery syntax although I agree to Alex, it feels wrong since it might have some overhead.
If you can change the syntax use $('#element')[0] as replacement for this (as already mentioned in the accepted answer).
Btw could someone with enough reputation please correct the comment of "zzzzBov" about the accepted answer?
$('#element')[0] and $('#element').get(0) ARE! the same, if you want the jQuery object use $('#element').first() or $('#element').eq(0)
Is there a way to get JavaScript this from jQuery this?
this == this, whatever this is.
this is a not jquery it is a special, somewhat convoluted, javascript keyword that describes the current scope of execution.
your challenge may be determining or controlling what this is.
There is:
$('a').click(function(){
var jqueryobject = $(this);
var domelement = this;
});
Within such a closure, this always represent the native DOM element which must/can be wrapped into a jQuery object.
If you already got a jQuery object and need to get the DOM element either use
var DOMelement = $(this)[0];
or
var DOMelement = $(this).get(0);
Since jQuery objects are array like objects you can always grab them with standard array access [] notation. The jQuery method .get() will actually do the same. With both ways, you'll receive the DOM element at that array position.
General - what is this ?
this contains a reference to the object of invocation
this allows a method to know what object it is concerned with
this allows a single function object to service many functions
So this is the most important part of all protoypal inheritance things
I don't really understand what you're asking for here, but I'll give it a shot. Firstly, remember that jQuery is just a series of functions written in Javascript. The this keyword is literally the same in "both" contexts.
Perhaps you want to get the actual DOM element instead of the jQuery object? You can use .get():
// let's say there's a single paragraph element
var obj = $('p'); // obj is a jQuery object
var dom = obj.get(0); // dom is a DOM element
Try to access this (DOM element) instead of $(this) (jquery object).