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

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.

Related

Is There a Way to Implement EventTarget with Plain JS?

I'm trying (perhaps in vain) to come up with a way to use the publish-subscribe pattern while a) using no libraries and b) minimizing boilerplate code in modules that use it. So far the best I've come up with is this:
var handle = document.createElement();
var unsubscribe = AwesomeModule.subscribe(handle);
handle.addEventListener('awesome', function() {
console.log('awesome');
});
This will work pretty well, except that people using AwesomeModule might be confused by having to provide a random DOM element that isn't used as an element.
I tried the following and it doesn't work too well:
var handle = Object.create(EventTarget);
var unsubscribe = AwesomeModule.subscribe(handle);
handle.addEventListener('awesome', function(){
console.log('awesome')
});
I get TypeError: Object [object Object] has no method 'addEventListener'. Interestingly enough, it doesn't seem to look in the prototype chain even though handle has EventTarget as its prototype.
Why doesn't this work? Is there a way implement EventTarget with pure JS? Can it be done in a single line of code that won't horrify users of AwesomeModule?
EDIT: I don't know why it didn't occur to me last night, but I suppose EventTarget being an interface means that it doesn't have implemented code. What's confusing is that in the Chrome debugger console Object.create(EventTarget) makes an object that appears to have addEventListener in is prototype chain. Maybe its lying. Can anyone explain this behavior? Can anyone explain why W3 chose not to make EventTarget a concrete "class"?
It looks like the answer to my original question is "yes." Since JavaScript doesn't have an inheritance model like Java which does compile-time checks for legal implementation, I suppose any Object can implement an interface merely by having methods with the same name. However, doing this would constitute making a library since the addEventListener code isn't implemented in EventTarget (I had previously assumed it was). Since there seems to be no cross-browser way to get a vanilla EventTarget, I will probably use window.addEventListener in conjunction with custom events.
The source is located here: https://code.google.com/p/chromium/codesearch#chromium/src/third_party/trace-viewer/src/base/event_target.js&sq=package:chromium&type=cs&l=18
If you can't modify it, you can always replicate it.
Here's a simple set of routines that works well.
with a small polyfill for IE9 and 10, support is decent.
you can incorporate these functions into your project as needed, i don't think it constitutes a library, or i wouldn't post this.
var on = addEventListener.bind(window),
off = removeEventListener.bind(window),
emit = function(name, val) {
dispatchEvent(new CustomEvent(name, {
detail: val
}));
};
// demo:
on("test", function(e){ alert(e.detail);});
emit("test", "Number is " + Math.random());
i don't think it can get much simpler (~180 chars) without sacrificing speed or library compatibility.

Javascript closures (I think)

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)"

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