Can't do anything with elements retrieved w/ class selectors [duplicate] - javascript

This question already has answers here:
Get an element by index in jQuery
(5 answers)
Closed 8 years ago.
I'm trying to set a .click function for the first element with a certain class - and each one will need separate code, incrementing my purchase function, with the first one using purchase(0,0,1); and the second using purchase(0,1,1); and so forth. While doing so with $(".generation:first") (with generation being said class) works, I want to be able to do this for all elements with this class, referring to them from an array, and for some reason
$(".generation")[0].click(function () { purchase(0,0,1); });
doesn't work - no errors or anything. It just doesn't seem to select it. Just the same later:
// Note: listings is an array of three different classes, 0 is .generation
// Therefore, 'listings[0][0]' should be identical to '$(".generation")[0]'
listings[0][0].find(".count").text(game.buildings[type][id].count+" bought");
The above won't work, stating undefined is not a function, if I use .children(".count") it instead says object is not a function.

You use .eq(0) to get the first element in a jQuery object. [0] just gets you the first DOM object which obviously doesn't support the jQuery .click() method of adding an event handler. So, you can do it like this:
$(".generation").eq(0).click(function () { purchase(0,0,1); });
If you want slightly different functionality for each .generation element as your comments now indicate, you can iterate with .each() and do something slightly different on each element.
$(".generation").each(function(index) {
$(this).click(function() {
purchase(0, index, 1);
});
});

You can just call the click function on the jQuery object to register the handler for all elements with the said class
$(".generation").click(function () { purchase(0,0,1); });
The problem is the .click() function is present in the jQuery object, but when you use $(".generation")[0] it returns a dom element reference which does not have the method thus you are getting the error.
In that case, you can find the index of the current element like
var $els = $(".generation").click(function () {
purchase(0, $els.index(this), 1);
});

Related

Proper use of bind and referencing objects values in a click handler [duplicate]

This question already has answers here:
Javascript call() & apply() vs bind()?
(24 answers)
Closed 5 years ago.
I'm having trouble wrapping my head around the proper use of bind and the reference to past links being opened in my on click handler.
This function receives an array of 4 links. I simply want to open the correct link on click.
Links 2 and 3 work because they are bound to the window object. Links 0 and 1 will work on the first array that is passed but when a new array of links is passed to the function, when clicked, it will open the previous link and not the one that was most recently passed to the function.
I know that adding values to the window object is bad practice so I've been trying to figure out a better way to implement it while gaining a better grasp on bind,apply, and call. (If even necessary here).
Why is it that the first 4 links passed are correct but any other time links are passed, it will continue to reference and open the initial set of links?
links = function(linksArr) {
var that = this;
this.linkArray = linksArr;
//Create an object from array in attempt to get correct link on event click
var linkReference = linksArr.reduce(function(all,item,index){
all[index] = item;
console.log(all);
return all;
},{});
//Does not work. Attempted use of bind
$('.link0').on("click", function () {
window.open(linkReference[0], '_blank');
}.bind(linkReference));
//Does not work. Trying to apply the proper links through the apply method
$('.link1').on("click", function () {
window.open(linksArr[1], '_blank');
}.apply(null,linksArr));
//Works
$('.link2').on("click", function () {
window.open(that.linkArray[2], '_blank');
});
//Works
$('.link3').on("click", function () {
window.open(that.linkArray[3], '_blank');
});
};`
bind() makes the element you bind with be the 'this' inside the method. You should use 'this' as the reference, not the name you used when you bound.
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Reference/Global_Objects/Function/bind

Iterate over html elements with same class using .each

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;
}
}

How to get 'this' in a function referring to jQuery object

Amongst other things, I have read:
what-does-this-mean
you-must-remember-this
mythical-methods
but they haven't solved 'this' problem I'm having with a piece of JavaScript.
I have a Section object that gets passed some XML which it uses to populate the section. In the Section object I append a div which has a specified index. The resulting jQuery object is pushed into a sections Array. The following code is from the Section object code:
sections.push($('#section' + p_sectionIndex));
this.showSection = function() {
this.show();
}
this.hideSection = function() {
this.hide();
}
sections[sections.length-1].on('show', this.showSection.call(sections[sections.length-1]));
sections[sections.length-1].on('hide', this.hideSection.call(sections[sections.length-1]));
Elsewhere I call sections[index].trigger('hide'); and sections[index].trigger('show');
The first of the links I mentioned above seemed to suggest this in a function depends on HOW it's called and that you could pass a reference to this into the function by using call. I know the showSection and hideSection function ARE being triggered - I just can't get the this in those functions to refer to the jQuery objects in the sections Array.
I have tried multiple variations of the above (excluding the call, using $(this) in the functions, adding the showSection and hideSection functions to the jQuery object - amongst others) but I'm kind of out of ideas.
Any help much appreciated!
this in an event handler is the element node that the event was bound to. If you want a jQuery object wrapping that node, use $(this)
Demo: http://jsfiddle.net/b36M6/
This of course assumes you revert back to the correct way of passing a function to the event binding.
When you use .call(), you're invoking the function immediately.
Since you want this to refer to the element, bound, just pas the function itself.
sections[sections.length-1].on('show', this.showSection);
sections[sections.length-1].on('hide', this.hideSection);
Now this in the showSection and hideSection methods will refer to the sections[] member to which it was bound.
I assume "show" and "hide" are some sort of custom events.

Doesn't jQuery('#id') do the same thing as document.getElementById('#id') in javascript? [duplicate]

This question already has answers here:
Closed 10 years ago.
Possible Duplicate:
document.getElementById vs jQuery
I have a function that will take all the spans with a certain class ("jobStatus") and remove an additional class from it ("orange"). I call the function from a SELECT onchange (onchange="chgJobstatus(this);"). It's working great.
However, I'm trying to get it to run on page load, based upon the selected value (this is server-side dynamically generated.)
This will work:
$(document).ready(function(){
chgJobstatus(document.getElementById("chgStatus"));
});
This will NOT work:
$(document).ready(function(){
chgJobstatus(jQuery('#chgStatus'));
});
Doesn't jQuery('#id') do the same thing as document.getElementById('#id') ??
Regarding selecting the element, yes, but jQuery selectors return jQuery objects and getElementById returns a DOM Element object, you can get the DOM Element using [index] or get(index) method:
chgJobstatus(jQuery('#chgStatus')[0]);
This will surely work. jQuery(selector) always return a jQuery object (jQuery(selector) instanceof jQuery is true ) . but you can get native dom element using .get or simply using array like syntax as below.
$(document).ready(function(){
chgJobstatus(jQuery('#chgStatus')[0]);
});
jQuery('#id') - returns a jQuery Object
document.getElementById('#id') - returns a HTML DOM Object
jQuery('#id').get(0); OR jQuery('#id')[0]; - returns a HTML DOM Object
By using jquery it will allows you to access jquery functions. if you read below links you will get an good idea.
document.getElementById vs jQuery
jQuery $() vs. document.getElementByID — differences
getelementbyid-vs-jquery-id
jquery-sharp-vs-getelementbyid
getelementbyid-vs-jquery-id
On more important thing you should know is that jQuery returns a reference to a jQuery object, not the object itself.
No, jQuery('#id') returns a jquery object, with additional functions and properties attached to it.
I'm not entirely sure what you're trying to do, but something like this could substitute all the javascript you've described.
$("#chgStatus")
.bind("change", function() {
$(".jobStatus").removeClass("orange");
}).trigger("change");

Why do I have to use $(this)? [duplicate]

This question already has answers here:
Closed 12 years ago.
Possible Duplicate:
jQuery $(this) vs this
In jquery sometimes I find that within a function I have to use $(this) because this won't work:
var listItems = $('li');
listItems.each(function(index) {
$(this).css({
})
})
Any ideas as to the reason why?
$() is the jQuery constructor function
this is a reference to the DOM element of invocation
So basically, you're turning a DOM reference into a jQuery object
In your example, you could also use
listItems.each(function(index, element){
$(element).css({
});
});
..since .each() will pass both, index + element in its callback.
I know I'm a bit late to this thread but I just wanted to bring up the fact that redundant wrapping of DOM objects is one of the most frequently committed crimes against jQuery. Taking care with your jQuery-instance constructing can have tremendous effects performance-wise and it's so easy to do that you have no excuse not to.
Typically, when people have a DOM object (whether it be referenced as this or element) they'll try to wrap it each time they need access to a jQuery method:
jQuery(this).css('a', 'b');
The problem is when you're doing this multiple times:
jQuery(this).css('a', 'b');
jQuery(this).find('span').attr(...);
jQuery(this)....
Every time jQuery() is called, a new jQuery instance is constructed. That kind of operation is expensive and should be avoided if at all possible -- especially in loops!
To avoid this, for one, you could utilise chaining with all methods that return a jQuery instance $(this).css(a,b).attr(a,b)...). The rest of the time you should have a locally declared variable that refers to the jQuery instance and then just use that:
var self = jQuery(this);
self.css(...);
self.attr(...);
If you're doing this within an .each() callback function, there is still a new jQuery object being constructed on every single iteration. You can avoid this by having one generic jQuery object which you continually mutate and then you can run jQuery methods off that single instance:
Look at this:
jQuery.single = function(a){
return function(b){
a[0] = b;
return a
}
}(jQuery([1]));
Now look at this:
$('a').each(function(i){
$.single(this).append('Anchor number ' + i);
});
Only one jQuery object is being used. You can make it even faster by avoiding the identifier resolution:
$_ = $.single;
$('a').each(function(i){
$_(this).append('Anchor number ' + i);
});
Food for thought. More info here: http://james.padolsey.com/javascript/76-bytes-for-faster-jquery/
this is the native DOM element. $(this) is a jQuery object that allows you to call functions such as .css() on it.
this is typically a DOM object by default, which means it only has the methods on normal DOM objects.
If you want to invoke a library-specific function (such as jQuery's .css function), you have to convert it to a full jQuery object first, which is what $() does by default if you pass it a DOM object.
(You can also pass other things to $(), such as an HTML string (to construct a new jQuery-wrapped DOM object) or a CSS selector (to get a set of jQuery objects that correspond to DOM objects matching the selector).
If you are using Firefox, try console.log($(this)) and console.log(this) to see the difference.

Categories