Iterate over html elements with same class using .each - javascript

I have some div elements with the same class. I want to iterate through them. I am using jquery ".each" in order to do it. I also want to access each element individually and toogle its class so I need to get the index of the element within the class elements array. I currently have a code similar to this:
$('.the_div_class').each(function(i, obj) {
if("a certain condition") {
$('.the_div_class')[0].toggleClass('other_div_class'); // trying to access the index 0 of the array that contains the elements of that class;
}
}
However I receive an error saying "$(...)[0].toggleClass is not a function". If I don't specify an index I toogle all the elements of the array... I console.log the "$('.the_div_class')" array and get a structure similar to this:
[div.the_div_class, div.the_div_class, div.the_div_class, div.the_div_class, div.the_div_class, prevObject: r.fn.init[1]]
And if I console.log "$('.the_div_class')[0]" I get this:
<div class="the_div_class">
Why doesn't it work and what should I do in order to make it work?

The code $('.the_div_class')[0] will only get the first element that matches that selector in the DOM with that class naively, it doesn't work because it's no longer a jQuery object (hence it doesn't have the method .toggleClass()). Inside .each() you can use this to refer to the current element being iterated:
$('.the_div_class').each(function(i, obj) {
if("a certain condition") {
$(this).toggleClass('other_div_class');
}
}
Note: To get a item by it's index in jQuery you can use .get(). For example:
$('.the_div_class').get(0).toggleClass('other_div_class');

Change your code to:
var collection = $('.the_div_class');
collection.each(function(i, obj) {
if("a certain condition") {
$(collection[0]).toggleClass('other_div_class'); // trying to access the index 0 of the array that contains the elements of that class;
}
}
You need to recreate jQuery object by passing DOM element to $ again, i.e $($('.the_div_class')[0]) for your code.

When you specify the index, you're fetching the plain javascript element that was selected with jQuery, not a jQuery object. This is why the toggleClass() method is unavailable to you.
You can wrap it in jQuery like this $($(selector)[i]) to convert it back to a jQuery object. However, the arguments supplied with the each loop are your friend here. That is, you can access the current object in the loop with $(obj).

You need to change the code to get element by using this keyword:
$('.the_div_class').each(function(i, obj) {
if("a certain condition") {
$(this).toggleClass('other_div_class'); // trying to access the index 0 of the array that contains the elements of that class;
}
}

Related

array.eq() vs. array[] in Javascript and Jquery

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.

Setting jQuery plugin options from data attributes

Im having a problem setting options to an array value in a jQuery plugin using data attributes.
If I reference the data attribute using a class selector
$('.tm-input').tagsManager(
{
prefilled: $('.tm-input').data('load')
})
It works but all the elements get the same values.
If I reference using "this" it sets the correct values but it comes across as a string not an array.
$('.tm-input').tagsManager(
{
prefilled: $(this).data('load')
})
I've tried using JSON.parse() but I get an error about an unexpected character. Any help would be appreciated!
Have you tried each
$('.tm-input').each (function () {
$(this).tagsManager( { prefilled: $(this).data('load') });
});
Explanation:
When a selector has more than 1 element, applying a method to it will typically affect all of the elements, but retrieving a property will typically only return that property from the 1st element.
So when you use .tagsManager on your $('.tm-input') selector, you are applying .tagsManger to all of the elements. But when you set prefilled:$('.tm-input').data('load'), the data method is only grabbing the data from the first element in the list, every single time.
When you use each, it applies the logic inside of the each block to each element individually, rather than all of them at once, so when you use $(this).data('load'), it grabs the load attribute from each individual element as well.

Is a Function Argument a Native Element or a jQuery Set?

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();

What do [] brackets after a Jquery selector mean?

I'm using this code to play a preloaded mp3 file.
var shuffle = $("#shuffle")[0];
shuffle.play();
Shuffle is my id. I got the code off the net but I CANNOT figure out what the [0] after the jquery selector does. The sound does not play if I remove it.What does it do?
thanks
jQuery is an array-like object that contains all of your matched elements. Often times, jQuery will by default apply its changes to the first element in the collection:
$("li").css("display"); // display val of first element, not all elements.
Even though many li elements could have been found, the jQuery object tells us about the first implicitly. We could explicitly instruct it to do so by using the $.get method:
$("li").get(0); // Returns first DOM element
$("li")[0]; // Also returns first DOM element
We could check the nodeName to verify this:
$("li").get(0).nodeName; // LI
$("li")[0].nodeName; // LI
If we look under the covers, we can see how $.get() is implemented:
get: function(num) {
return num == null
? this.toArray()
: ( num < 0
? this[ this.length + num ]
: this[ num ] );
}
From this we can see that when no argument is provided, the entire collection of element is converted to an array, and then returned. When an argument is provided, for instance 2, we return the element as index 2. If -2 is provided, this is added to the length (suppose the length is 5, 5+(-2) is 3) and the resulting number is used as the index.
So with regards to your particular example:
var shuffle = $("#shuffle")[0];
shuffle.play();
jQuery is used to get any element that has the id value of shuffle. This returns the jQuery array-like object. But your play() method doesn't exist on the jQuery object, it exists on the #shuffle object. As such, you need to get the first element in the collection.
You could use $.get(0), however as we just saw, this would just be adding one more step. Internally, jQuery would perform the same code you're performing above, [0].
In the direct context of your question, $("#shuffle") is a selector of an id, which returns a jQuery object (not an array per-se, but it has an array-like structure), then the [0] part is actually returning a native DOMElement object of the element with id shuffle instead of the jQuery object returned by calling $('#shuffle') (without the []).
Essentially the same as doing document.getElementById('shuffle')
EDIT (as Matt pointed out)
this will then allow you to do your .play() call to start your audio stream.
The brackets after the $('#shuffle') get the first element of that selector provided.
$('div.test')[0];
<div class="test"></div> <-- this one would get returned
<div class="test"></div>
<div class="test"></div>
It returns the native javascript object containing the first element in the matched set of elements.
JQuery returns an array. [0] takes the first item in the array.
The nth element of the returned array. The same as in regular javascript or php and a good part of the programming languages which support arrays.
Its means the chronological order of object to be process always used on array [0],[1],[2]... you can check Here

applying methods to single elements in an array - jquery/javascript

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'));

Categories