Javascript closures (I think) - javascript

I've got a piece of code I'm working with that was handed down to me by a previous developer. I am just trying to understand it better and not just use it naively. Here's the code:
slides.paginator.click(function (e) {
e.preventDefault();
interval.stop();
switchSlide($(this).index());
interval.start();
});
The part that I do not understand is the argument e that is being passed through this anonymous function. I have seen this before and I thought it had something to do with closures, but again, I am not sure. Can anyone give me a little insight into exactly how this parameter e works? I have seen it in other cases as well, such as with jQuery's AJAX methods.
Even pointing me in the right direction towards an article would be a great help. Thanks!

"e" comes from "event", check the jquery .click() docs http://api.jquery.com/click/
function(e){} replaces "handler(eventObject)"

Related

Can someone explain this code using the .bind() function to me?

I encountered this snippet (event handling) from the jQuery source code:
var events = ['click', 'focus', 'blur', …];
jQuery.each(event,function(i,name){
jQuery.prototype[name] = function(fn){
return this.bind(name,fn);
};
});
Can someone explain this to me? How does the this.bind(name,fn); work the same as element.addEventListener('event','callback()')?
I know the basics of JavaScript, but I do not know the more advanced parts of JavaScript. Since I taught myself, there are many holes in my JavaScript knowledge. If anyone knows of a good source I could learn more advanced JavaScript from I would like to hear that too.
it's quite simple we have all events in an array [click, focus ...] easily we apply a foreach on that array and next part of code assign a function to jQuery prototype $.fn.click() which will become $('#me').click(), and finally this click(); function calls $.fn.bind(); which will call addEventListener() later, that's it.
if you still wondering where is addEventListener() read about bind() in jQuery.

simple jquery widget

jQuery.widget("ui.test", {
_init: function(){
alert(this.element.innerHTML);
}
});
How do I make it so when I am attaching this to a HTML element
It will alert the innerHTML (I know it does nothing, it is just to understand the basics).
<div id="baba">ja jaj</div>
<script>
$('#baba').test();//will alert "ja jaj"
</script>
What am I missing here?
What I missed:
My code was actually perfectly fine, EXCEPT, I assumed that this.element is an HTML element, while in reality it is a jQuery object. Hence innerHTML did nothing while html(), in the answer below, worked.
You're missing the jQuery UI library. Simply attach it and yu're good to go - http://jsfiddle.net/jUm5H/
(function($) {
$.widget("ui.test", {
_init: function() {
alert( this.element.html() );
}
});
}(jQuery));
$('#baba').test();
UPDATE
"To make sure that your plugin doesn't collide with other libraries that might use the dollar sign, it's a best practice to pass jQuery to an IIFE (Immediately Invoked Function Expression) that maps it to the dollar sign so it can't be overwritten by another library in the scope of its execution." - source
So it's basically just a good practice. You can ignore it and it will work - http://jsfiddle.net/jUm5H/1/ But it's better to do it in a correct way from the beginning. It might save a lot of debugging time and frustration in the future projects :)

Unexpected JQuery awesomeness... But how does it work (method missing type syntax)?

Apologies for the vagueness of the title, I can't think of a succint way of summarising this question. I'm new to Javascript and JQuery and needed to respond to a checkbox being toggled, based on its value. Searching the site revealed lots of answers, mostly in the form:
$("input[type='checkbox']").click(function() {
if( $(this).is(':checked') ) {
//code here
}
})
In a flash of dynamic typing inspiration however, I tried typing this into my Javascript console:
$("input[type='checkbox']").click(function() {
if( this.checked ) {
//code here
}
})
...and to my surprise it worked! What's going on here behind the scenes? Is there a method defined called 'checked', or some kind of default property, or even a Ruby-style 'method missing' concept? Is this enabled by JQuery or is it intrinsic to Javascript?
It struck me as pretty awesome and I'd like to understand it better.
This basically boils down to the difference between this and $(this). (Read more here)
this is the DOM object for the current object where as $(this) is the jQuery wrapped version. This means you can do this.checked and is the same as calling normal Javascript.
What this does mean though is that, like #Val said you may run into cross browser issues as you are not relying on jQuery to solve these issues for you.
The reason it works is when the handler is called, its does something to the effect of:
callbackfn.call(<reference to event obj>, .. params .. )
If you go take a look at the JS reference, you'll see that the first parameter passed to .call is the context you want the function to run within. So in this case, since the object passed in is the clicked item, it will be the context.
I disagree with the other replies that this will cause you any trouble in xss browser compatibility, this is how you're supposed to do it and many many jQuery libraries rely on this.
See this stackoverflow article
$(this)[0] == this

Problem with "this.function" and Scope in my code

Hey I have this code right here:
http://pastie.org/534470
And on line 109 I get an error saying "TypeError: Result of expression 'this.allVarsDefined' [undefined] is not a function."
Scope in javascript is confusing to me. Can anybody see what my problem is? Also do you guys know of any articles that would help me learn about scope in javascript. This is my first time really using JS :)
This looks prototype-based. You probably need to set up your notification callback like this:
setTimeout(this.notify.bind(this), 5000, track);
so that the notify function is bound to the Scrobbler object and gets this set to the Scrobbler object instead of the event triggering the function when the timeout occurs.
If I'm wrong on you using prototype, you can probably achieve the same effect using
var that = this;
setTimeout( function() { that.notify(); }, 5000, track );
Try changing line 109 from
setTimeout(this.notify, 5000, track);
to
setTimeout(function(){this.notify()}, 5000, track);
What this will do is create "closure" (function(){this.notify()}) that includes the "this" variable in it, and "this" includes this.allVarsDefined, so you should stop getting that error.
I think the problem with your old code is that when you write "this.notify" you were just yanking the function out of the instance of the object and passing it to setTimeout, but you were not passing any information about the object itself. That would be okay if the notify function did not refer to "this", but since it does refer to "this", you need to use a closure.
You would benefit from reading more about Javascript closures. Here is a decent article. I also recommend the great book Java Script: The Definitive Guide 5th Edition by O'Reilly. It only costs like $50 but it is well-written and will help you immensely if you are trying to write a web-app in javascript.
If my solution does not work, then simplify your code down to the most basic thing that you think should work and does not work, and then post it here.

How to change onClick handler dynamically?

I'm sure there are a million posts about this out there, but surprisingly I'm having trouble finding something.
I have a simple script where I want to set the onClick handler for an <A> link on initialization of the page.
When I run this I immediately get a 'foo' alert box where I expected to only get an alert when I click on the link.
What stupid thing am I doing wrong? (I've tried click= and onClick=)...
<script language="javascript">
function init(){
document.getElementById("foo").click = new function() { alert('foo'); };
}
</script>
<body onload="init()">
<a id="foo" href=#>Click to run foo</a>
</body>
Edit: I changed my accepted answer to a jQuery answer. The answer by 'Már Örlygsson' is technically the correct answer to my original question (click should be onclick and new should be removed) but I strongly discourage anyone from using 'document.getElementById(...) directly in their code - and to use jQuery instead.
Try:
document.getElementById("foo").onclick = function (){alert('foo');};
Use .onclick (all lowercase). Like so:
document.getElementById("foo").onclick = function () {
alert('foo'); // do your stuff
return false; // <-- to suppress the default link behaviour
};
Actually, you'll probably find yourself way better off using some good library (I recommend jQuery for several reasons) to get you up and running, and writing clean javascript.
Cross-browser (in)compatibilities are a right hell to deal with for anyone - let alone someone who's just starting.
jQuery:
$('#foo').click(function() { alert('foo'); });
Or if you don't want it to follow the link href:
$('#foo').click(function() { alert('foo'); return false; });
I tried more or less all of the other solutions the other day, but none of them worked for me until I tried this one:
var submitButton = document.getElementById('submitButton');
submitButton.setAttribute('onclick', 'alert("hello");');
As far as I can tell, it works perfectly.
If you want to pass variables from the current function, another way to do this is, for example:
document.getElementById("space1").onclick = new Function("lrgWithInfo('"+myVar+"')");
If you don't need to pass information from this function, it's just:
document.getElementById("space1").onclick = new Function("lrgWithInfo('13')");
OMG... It's not only a problem of "jQuery Library" and "getElementById".
Sure, jQuery helps us to put cross-browser problems aside, but using the traditional way without libraries can still work well, if you really understand JavaScript ENOUGH!!!
Both #Már Örlygsson and #Darryl Hein gave you good ALTARNATIVES(I'd say, they're just altarnatives, not anwsers), where the former used the traditional way, and the latter jQuery way. But do you really know the answer to your problem? What is wrong with your code?
First, .click is a jQuery way. If you want to use traditional way, use .onclick instead. Or I recommend you concentrating on learning to use jQuery only, in case of confusing. jQuery is a good tool to use without knowing DOM enough.
The second problem, also the critical one, new function(){} is a very bad syntax, or say it is a wrong syntax.
No matter whether you want to go with jQuery or without it, you need to clarify it.
There are 3 basic ways declaring function:
function name () {code}
... = function() {code} // known as anonymous function or function literal
... = new Function("code") // Function Object
Note that javascript is case-sensitive, so new function() is not a standard syntax of javascript. Browsers may misunderstand the meaning.
Thus your code can be modified using the second way as
= function(){alert();}
Or using the third way as
= new Function("alert();");
Elaborating on it, the second way works almost the same as the third way, and the second way is very common, while the third is rare. Both of your best answers use the second way.
However, the third way can do something that the second can't do, because of "runtime" and "compile time". I just hope you know new Function() can be useful sometimes. One day you meet problems using function(){}, don't forget new Function().
To understand more, you are recommended read << JavaScript: The Definitive Guide, 6th Edition >>, O'Reilly.
I agree that using jQuery is the best option. You should also avoid using body's onload function and use jQuery's ready function instead. As for the event listeners, they should be functions that take one argument:
document.getElementById("foo").onclick = function (event){alert('foo');};
or in jQuery:
$('#foo').click(function(event) { alert('foo'); }
Here is the YUI counterpart to the jQuery posts above.
<script>
YAHOO.util.Event.onDOMReady(function() {
document.getElementById("foo").onclick = function (){alert('foo');};
});
</script>
I think you want to use jQuery's .bind and .unBind methods. In my testing, changing the click event using .click and .onclick actually called the newly assigned event, resulting in a never-ending loop.
For example, if the events you are toggling between are hide() and unHide(), and clicking one switches the click event to the other, you would end up in a continuous loop. A better way would be to do this:
$(element).unbind().bind( 'click' , function(){ alert('!') } );
Nobody addressed the actual problem which was happening, to explain why the alert was issued.
This code: document.getElementById("foo").click = new function() { alert('foo'); }; assigns the click property of the #foo element to an empty object. The anonymous function in here is meant to initialize the object. I like to think of this type of function as a constructor. You put the alert in there, so it gets called because the function gets called immediately.
See this question.
The YUI example above should really be:
<script>
YAHOO.util.Event.onDOMReady(function() {
Dom.get("foo").onclick = function (){alert('foo');};
});
</script>

Categories