In majority of JavaScript method(iterator) callback first argument is element and second is index. But in case of jQuery always second argument is element and first one is index. Why they formatted differently? Is that for avoiding confusion between them, since both contains methods like map, filter, etc. Is there any special meaning behind that? I'm just curious to know.
This is because jQuery relies on this; it doesn't need an element iterator.
$('selector').each(function(){
// 'this' refers to unwrapped jQuery selector element; no need for arguments == cleaner code
var $this = $(this);
});
In Vanilla JS, iterators rely on the parameters:
[].forEach(function(el, index){
// 'this' refers to Window object; use the argument
el.querySelector('foo')
});
Because jQuery can utilize the scoped element using this, it doesn't really need the arguments. I'd have to look up the history of the library to even see if the element existed as the second argument in earlier versions.
Related
I am creating a few DOM elements dynamically like,
var anchorElement = jQuery('<a />',{text:property.text});
var liElement = jQuery('<li />',{"class":"navlink_"+i,id:"navlink_"+i});
anchorElement.on('click',property.fnctn);
liElement.append(anchorElement);
parentID.append(liElement);
Where property is a JSON object.
property.text is the text that I want to put into anchor element. (Works fine)
I want to attach a click event handler to that anchor element.
The function that needs to be bound to that element is specified in JSON and we can access it like
property.fnctn
The following line should bind the event handler to the anchor element.
anchorElement.on('click',property.fnctn);
This was not working so I tried converting it into string like,
anchorElement.on('click',property.fnctn.toString());
No Success...
When I click on this link, the error is logged in the console
The object has no method 'apply'.
What is the reason...???
I am able to get it working with a slight work around like
anchorElement.attr('onclick',property.fnctn+"()");
Above statement works, but I want to know why .on() API is not working.
Thanks :)
AÐitya.
Update:
Youve said that property.actfn is a string, "paySomeoneClick". It's best not to use strings for event handlers, use functions instead. If you want the function paySomeoneClick, defined in the string, to be called, and if that function is global, you can do this:
anchorElement.on('click',function(event) {
return window[property.fnctn](event);
});
That works because global functions are properties of the global object, which is available via window on browsers, and because of the bracketed notation described below.
If the function is on an object you have a reference to, then:
anchorElement.on('click',function(event) {
return theObject[property.fnctn](event);
});
That works because in JavaScript, you can access properties of objects in two ways: Dotted notation with a literal property name (foo.bar accesses the bar propety on foo) and bracketed notation with a string property name (foo["bar"]). They're equivalent, except of course in the bracketed notation, the string can be the result of an expression, including coming from a property value like property.fnctn.
But I would recommend stepping back and refactoring a bit so you're not passing function names around in strings. Sometimes it's the right answer, but in my experience, not often. :-)
Original answer:
(This assumed that property.fnctn was a function, not a string. But may be of some use to someone...)
The code
anchorElement.on('click',property.fnctn);
will attach the function to the event, but during the call to the function, this will refer to the DOM element, not to your property object.
To get around that, use jQuery's $.proxy:
anchorElement.on('click',$.proxy(property.fnctn, property));
...or ES5's Function#bind:
anchorElement.on('click',property.fnctn.bind(property));
...or a closure:
anchorElement.on('click',function(event) {
return property.fnctn(event);
});
More reading (on my blog):
Mythical methods
You must remember this
Closures are not complicated
I used this selector in a function and I don't even know exactly what it means, but it worked - here is my piece of code:
else if($(this).hasClass('list')) {
listItem.stop(true,true).fadeOut(333, function(){
var $this = $(this);
if(listItem.hasClass('grid')) {
$this.find('h1', this).insertBefore($this.children());
}
The ".find()" method only pays attention to one argument, so it means exactly the same thing as
$this.find('h1')
JavaScript doesn't care if you pass too many arguments to a function; in fact there's no such concept as "too many arguments".
You can use a context in the $() function, like this:
$('element', this)
It will then only search among the decendants of the element that this referens to.
It's equivalent to using the find method:
$(this).find('element')
Using find with two parameters is pointless, though. It will only ignore the second parameter.
It is an alternative selector context to be used instead of the document root for the jQuery constructor.
The .find() method will ignore any other arguments than the selector. Its search context node is given as the context of the function call.
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)
I'm trying to understand the format of the Javascript functions that jQuery, among other people, use.
For instance jQuery(arg).hide() or $("#obj").hide
I'd like to write similar format functions but I don't understand how.
I know how to write
function myFunc(args) {
}
but I don't understand the second part ie the .hide()
is that a function within a function?
thanks for any help
It's called method chaining. The way to achieve this is for your first function to return an object, so the second function can be called as a method on that object.
The standard way to do this style of programming is to always return the same type of object, so for example, jQuery always returns a jQuery object representing a collection of HTML nodes. If one of the calls modifies the collection then the next call will be on that collection. That's how you can do something like $('#myid').parent().hide();. $('#myid') returns a jQuery object representing the #myid element and .parent() returns a jQuery object representing the parent element of #myid. .hide() returns the same object, so you could then call another method on the same object if you wanted.
This is called method chaining. I highly recommend picking up Crockford's "JavaScript: The Good Parts". This is a very quick read but wonderfully explains OOP in JavaScript and identifies good versus bad language features. Highly recommend it.
As Skilldrick pointed out, this is called method chaining.
The most straightforward example for this is an object that returns itself when you call any of its methods:
var world = {
'hello': function() {
alert('Hello');
return this;
},
'goodbye': function() {
alert('Goodbye');
return this;
}
};
world.hello().goodbye();
This is identical to world.hello(); world.goodbye();.
jQuery does a little more than that. Calling the jQuery or $ function on a valid selector string will return a jQuery object representing the matched elements (it's not actually an array, though you could think of it as one). Most of its methods will return the object itself after modifying the object (e.g. $("a").css({...}) will apply changes to the styling of the matched elements and then return the set of matched elements again).
But some jQuery methods allow modifying the set you're working with (e.g. $("a").parent() will return a jQuery object representing the parents of the matched elements). That is, they don't return the same object, but an object that behaves identically.
You have to be careful if you decide to use this style, though, as the flow will break if you need a method that has a return value of its own (e.g. if you want calculations or getter methods). This can be avoided by passing a callback function to the method, but the resulting coding style may be terribly convoluted.
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).