When accessing an array, when is it appropriate to use the .eq() function?
For example, I have...
slides.eq(slidesLength-1).css("z-index", (slidesLength-1));
and later I have...
for(i=0; i<slidesLength-1; i++) {
$(slides[i]).css("left", "-100%");
}
In the first piece of code, the slideshow stops functioning if I don's use the .eq() function. However, the second piece seems to function whether I use the .eq() function or not. Why is this?
slides is not an array. It's a jQuery object. The .eq() method returns you the element at the specified index as a jQuery object.
While jQuery objects may not be arrays, they can pretend to be by having a length property as well as properties corresponding to the indexes. (Since they are not arrays, you can't call methods like .pop(), .forEach(), etc. on them.)
When you do slides[i], you are actually getting the DOM element, not a jQuery object. The $() function turns the DOM element into a jQuery object.
So, when you do slides.eq(1), internally jQuery is doing $(slides[i]).
P.S. Objects, like jQuery objects, that pretend to be arrays are called "array-like objects". If you console.log(slides), it may look like an array. This is just your console trying to make things convenient for you. (See this question for more info: Creating array-like objects in JavaScript)
.eq() is a jQuery method which returns a jQuery object, while accessing by index returns plain DOM element. You should use eq() when you want to use jQuery methods (css() in this case) on the returned selection.
The reason $(slides[i]) works is because you're constructing a jQuery object by passing the plain element to $() constructor.
Your slides variable is not an Array, but a jQuery object.
.eq() returns a jQuery object, eventually empty if index is out of bounds, and a negative index is counted from the end.
.get() returns a DOM Element, or undefined if index is out of bounds, and a negative index is counted from the end.
[] returns a DOM Element, or throw an Error if index is out of bounds.
...
Additionally, jQuery methods let you interact with a set of elements as it was alone. So you if you do:
slides.css("left", "-100%");
It is applied on every matched elements contained in the jQuery object. It is unnecessary to loop over them.
...
Also the preferred way to loop over matched elements is using the each() method:
slides.each(function (i, el) {
var $el = $(el);
});
...
Also it is an established convention to prefix jQuery variables with a $ sign; it let you to easily differentiate DOM elements from jQuery objects. But that's only a matter of taste.
Related
I'm trying to get the children of the nth element returned by a jquery call. For example:
var kids = $('div')[7].children();
However, I keep getting this error with respect to children():
Uncaught TypeError: object is not a function
Can someone explain why this happens? children() works fine as long as I'm not calling it on an indexed element.
It's because it is no longer a jQuery object after you specify an index [7]. Thus, you are calling a jQuery method on a DOM element (which doesn't work).
You could use the .eq() method instead:
$('div').eq(7).children();
You could also use:
$($('div')[7]).children();
It's worth pointing out that this would work because the DOM element is wrapped in $() - thus turning it into a jQuery object.
You're using children method in javascript object i.e. $('div')[7]. To work with jquery method you need to use jquery object instead of javascript object.
Use eq method:
var kids = $('div').eq(7).children();
When you use array syntax with a jquery list you get back a document node, not a jquery element. Use $('div').eq(7).children() instead.
Is there a way to have get() returning a jQuery object instead of "just" the DOM element?
Example:
$("div").get(0) returns [<div></div>] instad of <div></div>.
I'd like to prevent overwrapping like $($("div).get(0)) because the query will get a little bit longer than the example and I fear the readability gets lost. I'd rather not use variables to save unnecessary DOM elements in the RAM, either.
Use eq() to return the jquery object instead of get()
$("div").eq(0)
Given a jQuery object that represents a set of DOM elements, the .eq()
method constructs a new jQuery object from one element within that
set. The supplied index identifies the position of this element in the
set, jQuery doc
You would use eq:
$("div").eq(0)
Use eq() instead , which will return jQuery object
$("div").eq(0)
Also try this also:
$('div:first')
I'm writing a general purpose helper function in JavaScript. It accesses the className property of the element.
But since I'm using jQuery, it turns out that sometimes the element passed as an argument is actually an array (a jQuery set).
What is the simplest way to use an argument if it's an element or get the first element from the set if the argument is a set? Does jQuery have a tool for this?
You can test if the object is a jQuery object by using instanceof:
if (myObject instanceof jQuery) {
// use $.each to loop over myObject and get class names of all
// or just use myObject[0].className to return only the first
} else {
// it's not a jQuery object
}
You always want a native element? Each jQuery object has a property jquery (containing the jQuery version) so you can use it to check if the element you got is likely to be a jQuery object:
obj = obj.jquery ? obj[0] : obj;
If you are not into ducktyping:
obj = (obj instanceof jQuery) ? obj[0] : obj;
In case you want to pass a single element, an array of elements or a jQuery object to the same method, do the following:
function stuff(element) {
element = [].concat(element)[0];
}
If you have to deal with both jQuery objects and non-jQuery elements, this is a bit tougher. Keep in mind that the jQuery collection can possibly have different classNames for each element, i.e. the first and others may not be the same.
It's slightly inefficient, but this will work:
function (obj) {
var className = $(obj).get(0).className;
}
Wrapping a jQuery object in jQuery() does nothing, but wrapping the element allows you to access it again via .get. It's inefficient because you may have an extra $() call.
If that's no good, you could check obj.hasOwnProperty('className') since a jQuery object usually should not have it, but I think that is riskier.
Is a jQuery Object an Element or an Array of Elements?
Strictly, neither.
A jQuery object is a Javascript object that has some of the Array capabilities. In most aspects you can use it as an array of elements.
If the jQuery object may contain several elements, and you only want the first, you can use the first method to get that:
elements = elements.first();
If the parameter can be either an element, an array of elements, or a jQuery object, you can wrap it in a jQuery object to handle all the cases:
elements = $(elements).first();
I've created an array of elements called $images (all the elements in the hidden class.) Then when I try to apply any method to just one element in the array, I get a $images[1].attr is not a function error. However, when I try $images.attr('id') for example without specifying the index of the array, it works but gives me the result for the first element in the array only.
$images = $(".hidden");
alert($images[1].attr('id'));
What's going here and how can I apply methods to single elements in an array? By the way, I'm certain there are at least two elements in the array as I tested it for this.
If you want still to have a jQuery object, rather than retrieving a native DOM element object, you need to use the eq function. This gets an element at a position in the array and returns it wrapped in the jQuery object, so you can do jQuery operations on it.
So:
$images.eq(1).attr('id');
If you only want the DOM element, you can use the square bracket notation or the get method. You can then look up a DOM property directly:
$images[1].id; // is the same as
$images.get(1).id;
Use .eq, like so:
$images = $(".hidden");
alert($images.eq(1).attr('id'));
Hope this helps!
$images[1] does not return a jQuery object, it is returning a dom element.
you want $($images[1]).attr('id')
The extra methods jQuery decorates the result array with are not present in the elements themselves. To get a specific element, you can use the eq selector or method:
$images = $(".hidden");
alert($images.eq(1).attr('id'));
or
$image = $(".hidden:eq(1)");
alert($image.attr('id'));
What does jQuery .find() method return? a object OR a array list of objects?
If it returns an object which contain all the matched elements. How to convert this object to an array?
If it returns a array of elements, why $(xml).find("DATE").sort(mySortFunc); does not work, it seems the jQuery .find() returns an object which can not apply Javascript sort() method which is supposed to be applied on array.
Generally, I need to sort the objects find by $(xml).find("DATE") , but when I use sort function, it raised an error that the object can not be resolved.
The majority of jQuery methods returns a jQuery object, which can be accessed like it is an array (e.g. it has a .length attribute, elements can be accessed using the square bracket notation ([0]), and it supports some array methods (slice())).
jQuery has a method called toArray() which can be used to convert the jQuery object to a real array.
You can also use get() with no arguments to achieve the same effect (and save you a few key presses).
In future, you can checkout the jQuery API, and the return type for all jQuery methods is listed in the relevant documentation (e.g. for find(), the return type is "jQuery")
If you call .get() on a jQuery object without a parameter, it will return a regular array of DOM elements.
jQuery already acts like an array, and thus you can apply array like functionality to it.
Try to change
$(xml).find("DATE").sort(mySortFunc);
with
Array.prototype.sort.apply($(xml).find("DATE"), mySortFunc);
and you should get what you need