Explanation for index and value inputs to anonymous function in javascript - javascript

I have a question on how anonymous functions work in Javascript.
I saw this beautiful piece of code to toggle "disabled" from an html element [from this post link to stack overflow ]:
$('#el').prop('disabled', function(i, v) { return !v; });
The inputs to the anonymous function i and v are the index and the value.
Why is that? Is it because of .prop() or is this somehow a property of the anonymous functions? Are there other inputs available?
Thanks
SOLUTION: The answer to my question is in the docs for .prop() api.jquery.com/prop/:

It's just how the jQuery .prop() method is implemented. If it sees that the second parameter is a function, it calls your function for each matched element, passing the element index and the attribute value.
Inventing an API in JavaScript involves making decisions like that for all situations involving a callback that the API clients will use. There are no hard-and-fast rules in general, though some contexts have conventions that should probably be followed when possible. An example is the Node world, where it's very common for callbacks to get passed two arguments, a (possibly null) error and the data relevant to the operation.

It is how the prop() function is defined in jQuery. Or more accurately, how the callback for prop() is defined.

Why is that? Is it because of .prop() or is this somehow a property of
the anonymous functions? Are there other inputs available?
No, not "properties" of anonymous function , parameters of anonymous callback function. Yes, additional parameters could possibly be defined for, passed to, called at function.
i : index is index of elements from selector #el passed ; v : value is value of disabled property of selected DOM element #el disabled

the anonymous function is passed as a paremeter to the jquery prop method (callback). jquery will do its magic behind and call that function passing those parameters to it in order to you be able to work with them.

Related

Why is JQuery messing with the params I want to bind to a click handler?

In short, I'm doing this:
function myHandler(a,b,c,d){
doStuffWithMyParams(a,b,c,d);
}
Then somewhere else:
jqueryElem.click(myHandler.bind(a,b,c,d));
When I do, some of the parameters passed (a,b) are read correctly. But the third (c) is a JQuery event object. I've also tried binding the args as an array. Then, the first param becomes the event object.
Totally perplexed here. Thanks in advance for any direction on this.
With the code myHandler.bind(a,b,c,d), the argument a is the context that bind() uses
So my handler is actually seeing this
function myHandler(b,c,d,event){
So I have a feeling you want
jqueryElem.click(myHandler.bind(this, a,b,c,d));
Building on what epascarello wrote, this should do the trick:
jqueryElem.click(myHandler.bind(this,[a,b,c,d]));
Not having the array might cause b to be treated as an eventHandler. Notice I used an array, but it could also be an object, for instance.

jQuery / JavaScript, why do I need to wrap variables in $() to use them?

Say I have a map on an array of elements. The callback function takes the index and the value at that position in the array.
If I wrap the array element that the callback receives in $(), it behaves as I expect. If I use it without wrapping it in $(), it gives an error.
var nonHiddenElements = $( "form :input" ).not(':hidden');
nonHiddenElements.map(function(index, element){
input_id = $(element).attr('id'); // this works
input_id = element.attr('id') ; // this gives an error
})
Can someone explain how this works.
Is this a jQuery quirk, or a JavScript thing?
What type of objects does my nonHiddenElements array contain exactly?
What is element that gets passed to the callback?
And mainly what is the $() doing?
You need to understand how jQuery actually works. I will try to explain it briefly.
$ is nothing but a normal javascript function. jQuery === $, is just a function with a fancy name. This function does a lot of different things, depending on what you pass in it. For example if you pass a string it will be treated as CSS selector and jQuery internals will try to find corresponding DOM elements. Or if you pass a string starting with < and ending with > jQuery will create a new DOM element by provided HTML string.
Now if you pass a DOM element or NodeCollection of DOM elements, it/they will be wrapped into jQuery instances so that they can have a jQuery prototype methods. There are many prototype methods jQuery offers. For example text, css, append, attr - those are all methods of jQuery prototype. They are defined basically like this (simplified):
jQuery.prototype.text = function() { ... }
Normal DOM elements don't have those convenient methods jQuery provides. And inside of methods like map or each if you check this value or element parameter like you do, you will see that they are actually not jQuery instances:
element instanceof jQuery // => false
and of course you can't use instance methods with not an instance.
So in order to use jQuery prototype methods you need have a jQuery instance, which you can obtain if you call jQuery function with DOM element passed in it:
$(element) instanceof jQuery // true
Javascript is a programming language.
jQuery is a JavaScript Library.
With jQuery:
$("some element")
In native JavaScript you would have to do something like this.
getElementById('elementByID')
Explained in detail here: https://developer.mozilla.org/en-US/docs/Web/API/document.getElementById
MDN is a great resource for beginners. https://developer.mozilla.org/en-US/docs/Web/JavaScript

Using this this in Jquery

I am having trouble with this in Jquery. When I do that on my website, it returns me the window.width. I just want to access the element from within. This is an example.
<div class="section " style="width:400px"></div>
$( ".section" ).html($(this).width());
or
<div class="section "><p></p></div>
$( ".section p" ).html($(this).parent().width());
also here is JSFiddle jsfiddle.net/XY66w/1
I'm going to assume that when you attempt to write this code:
<div class="section " style="width:400px"></div>
$( ".section" ).html($(this).width());
What you're trying to do is show 400px inside the div.section. If that is what you're trying to do, then here's what's happening:
This statement:
$( ".section" ).html($(this).width());
if Javascript, or most other languages I know, is syntactically equivalent to this:
var newHTML = $(this).width();
$( ".section" ).html(newHTML);
As you can see, this isn't a jQuery issue - but more a JavaSciprt / any programming language problem. You're telling the browser to pass in a value to the .html() method, so it must calculate that value first, in the scope of the function that you're calling the method from. In this case, you're calling the method from the window or global scope (or some other undefined scope, so you will never get what you expect.
The simple fix is this:
var section = $('.section');
section.html(section.width());
On the other hand, there are some jQuery methods that accept functions and these are the ones that you seem to be thinking of in this case. For instance, things would be slightly different in case you were using the each method, which accepts a function:
$('.section').each(function(index, element){
$(this).html($(this).width());
});
In this case, you're passing in a function that jQuery will then call in the scope of each element that is matched by your selector.
The big difference is to differentiate when you're passing in a value and when you're passing in a function that will be evaluated later.
You can do what you want this way, I think:
$(".section").each(function() {
$(this).html($(this).width());
});
JavaScript, like a lot of common languages, is not a "lazy" language. An expression statement like yours is evaluated such that all the function parameters are determined before anything's actually called. By using the jQuery .each() API, you can act on each element of the selected set.
jQuery only binds this when it's calling a function, such as an event handler, a callback function, a function supplied to something like $.each, etc.
In your examples, you're just supplying an argument to a jQuery method, and it's not inside a function that was called by jQuery. So this just contains whatever the browser's context is, which is window for top-level code. It's not the element(s) matched by the selector .section.

is there a difference between the jquery code here?

Here is the code block a
$('ul.filter li').each(function() {
$(this).click(function(e) { //do something });
});
Here is code block b
$('ul.filter li').click(function(e) { //do something });
Don't these do the same thing? is one better than the other? Which one is the better/faster method?
I would assume block b since it has less code but I want to confirm it here, thanks
The effect you see will be the same, but in the first case, every li element is assigned a new function, as you are creating the function object inside the each callback.
In the second case, there exists only one copy of the event handler, which means it uses less memory over all (although this is probably not measurable).
Internally, click calls on (in jQuery 1.7), which is iterating over the elements via each as well:
return this.each( function() {
jQuery.event.add( this, types, fn, data, selector );
});
This is the case with many jQuery methods (most often noted in the documentation), so you are saving characters and memory by letting jQuery implicitly do this.
They would both have the same effect.
I would prefer the second only because it is more concise and you're creating a single anonymous function to handle the click rather than an anonymous function per element.
For Jquery philosophy, the second is better because it is shorter.
Both are more or less same and give the same results. The second code snippet will also internally run each loop and assign the click handler to each li element.
But yes the second code snippet is very clear and simple.
The second usage is called "implicit iteration" and is one of the cornerstones of jQuery.
For example, in JavaScript Definitive Guide, 6th Ed, p.530 for jQuery Basics:
Despite the power of the each() method, it is not very commonly used,
since jQuery methods usually iterate implicitly over the set of
matched elements and operate on them all. You typically only need to
use each() if you need to manipulate the matched elements in
different ways. Even then, you may not need to call each(), since a
number of jQuery methods allow you to pass a callback function.
in http://jqfundamentals.com/chapter/jquery-basics
Implicit iteration means that jQuery automatically iterates over all
the elements in a selection when you call a setter method on that
selection. This means that, when you want to do something to all of
the elements in a selection, you don't have to call a setter method on
every item in your selection — you just call the method on the
selection itself, and jQuery iterates over the elements for you.
Typically, when the library has this built-in as the standard way of doing it, it will be in general better and faster, or else they wouldn't have built it in.

How does jQuery act on multiple selectors?

I've been wondering for a little while how jQuery acts on multiple selectors. For instance:
$("p").css({"border":"1px solid #000"});
Performs the subsequent function on all p tags. I've had a look through the jQuery source but to be honest it's an extensive read when you're trying to work out one specific bit of functionality. My assumption is that there's some kind of stack whereby css() and other functions merely act on the current stack, which is divined by the selector function.
Other than that, I can't work out how it could be replicated as, I think, there's no way in javascript to return multiple objects to execute a function on. E.g.
House.first_bedroom.size = "large"
House.second_bedroom.size = "small"
House.all_rooms().alertSize();
alertSize() would have to be a member function of some collection of objects rather than a member function of each room object that is returned by all_rooms()?
First, jQuery functions (generally) return a jQuery object, which acts like an array and keeps track of the current set of matched elements. Second, internally each jQuery function makes extensive use of the each() function to iterate over the matched objects, perform subsequent actions and construct the new jQuery object to return. Some functions do return something other than jQuery, like get(). These functions cannot be chained. Chaining is only possible when the function returns a jQuery object. Because the returned object is a jQuery object it has all the functions of jQuery available to it.
The jquery constructor ($(...)) always return a jquery object. You can think of it as a fancy array. The items selected are stored (looks like this is called context in the source).
So then on your object you're calling the function css... See jQuery.fn.css in the source. It basically calls a function which performs the delegate (setting or getting the css) on each item in the context.
Perhaps the DOM is parsed and all elements matching the criteria are added to an array? Or.. something more efficient? :)
Similarly, for event handling, a handler is assigned to each element in the array?
I'm just stabbing in the dark here.

Categories