Using this this in Jquery - javascript

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.

Related

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

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.

Using javascript "this" for jquery selector

In this code, we can obtain value of element id as 2 differnt way and both way return resultat
$("#my_div").on("click", function () {
alert( $(this).attr("id") );
alert( this.id );
});
But i interest, second way, is it proper in this case? I ask this, because in code we use jquery selector and for jquery selector, write clear javascript: this is justified and will it work always? or may be better use jquery $(this) for jquery selector? or not differnce?
this.id will give you the internal DOM element property while $(this).attr("id") returns the value of 'id' attribute.
The alternative to this.id in jQuery is using prop() method: $(this).prop("id"). However, using pure this.id construction will be easier and faster.
The main jQuery constructor can take a number of different types of argument.
In that context, this is not a selector, it is an HTMLElementNode (which jQuery calls an element).
This is perfectly OK and documented.
There is no need to spend the resources in wrapping an element in a jQuery object if you are just going to grab its ID. There aren't any compatibility problems between browsers for that.
Grabbing the id property of an HTMLElementNode takes less code and is faster then wrapping the whole thing in jQuery.
Yes, your second way is proper.
$("#my_div").on("click", function () {
// this is available within this function
alert( this.id );
});
this refers to an HTMLDOMElement within the function, and wrapping that this within $() will give you an jQuery object.
If you define another function within the click handler. Ex:
$("#my_div").on("click", function () {
// keep reference of this
var that = this;
function test() {
// this will not available here directly
// instead of that you can use reference
alert(that.id);
}
});
And $(this).attr('id'), this.id or $(this).prop('id') will give you the same result.
For choosing the best method is not always clear.
In this case you want the this.id, because the other solution requires much more calls behind the scenes (obvious calls to jQuery and attr).
If you need more information that mite differ from browser, you want the jQuery way.

Why do I need to wrap my JQuery code in a function literal?

I have following code that works -
$(function(){
$('#testbutton').click(function(){
var checkedValue = $('[name="someRadioGroup"]:radio:checked').val();
$('#result').html('The radio element with value <tt>' + checkedValue + '</tt> is checked');
});
});
I understand that $('#testbutton') fetches the HTML element with id testbutton and assigns an event handler to it.
But I don't understand why I need to put that code inside a function literal?
If I remove the $(function(){ (and the corresponding }); ) it does not work.
However other code can work without being wrapped in a function literal. Example -
alert('Hi there')
What is the difference? Why does alert work but the event assignment statement does not?
$(function(){...}); is shorthand for $(document).ready(function(){...});. The purpose of it is to not run your code until the elements that you intend to work with exist in the DOM (which generally is after the document is ready.)
It is not a requirement.
You are putting your code in an event handler that is invoked when the DOM is ready.
If you don't put your code in a DOM ready handler, and if your code performs DOM selection, you need to find some other way to to make sure the DOM is ready before it runs.
If your code doesn't perform DOM selection, then it's not needed. That's why your alert() works, because it doesn't need to fetch any elements.
An alternative is this.
<body>
<button id="testbutton">click</button>
<div id="result"></div>
<script type="text/javascript" src="/your/script.js"></script>
</body>
This places your code below all the elements on the page, so they are certain to be available when your code runs.
Another alternative is to use a window.onload handler.
window.onload = function() {
// your code
};
or using jQuery.
$(window).on("load", function() {
// your code
});
This is similar to the DOM ready handler, except that it waits for all resource, like images, to be loaded.
At the most basic level, something of the form (function(){...})() is a function literal that is executed immediately. What this means is that you have defined a function and you are calling it immediately.
This form is useful for information hiding and encapsulation since anything you define inside that function remains local to that function and inaccessible from the outside world (unless you specifically expose it - usually via a returned object literal).
A variation of this basic form is what you see in jQuery plugins (or in this module pattern in general). Since you are defining a function literal, it doesn't have access to anything from the outside world unless you explicitly pass in the information. Hence:
(function($) {
...
})(jQuery);
Which means you're passing in a reference to the actual jQuery object, but it's known as $ within the scope of the function literal.

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.

Categories