Often I see javascript code where event handlers (like onmousemove) are assigned dynamically.
Example:
document.getElementById('foo').onmousemove = function(e)
{ /* do some stuff with event e */ }
Apparently this 'e' parameter is some kind of event object. Where does that come from, as in: who or what defines what this 'e' parameter is when the function is called, and can I also do this in static html?
I mean like this:
<div id='foo' onmousemove='Bla(e)'> ... </div>
What should I fill in for 'e' to get that same event thing? And can I also combine that with more parameters, like
<div id='foo' onmousemove='Bla(this,e,4)'> ... </div>
where e is, again, supposed to be the event object?
Event handlers are defined as callback methods. A callback is (hence the expression) called from another process at a later time. This is done by the environment (the browser in this case) at the time an event fires.
it calls your callback function and passes in the event object.
The event object is stored in window.event inside of any event handler, so you do not need to worry about your handler conforming to accepting it as a parameter.
In your second and third examples, the e parameter will be passed as undefined because no variable e exists in that scope (unless you have a global e).
This is what's known as a callback method. The event is initially created by the operating system, sent to the web browser, which then passes it off to you in javascript Event object.
I'm not sure, but I think the event is an object instance of ActionEvent. I don't think ActionEvent can be manually instantiated, so you can't do it in static HTML. Even if it would be possible, it certainly wouldn't be best practice.
Related
I am trying to pass function reference as event handler in jQuery. I would like to use a shorthand like in the simple example below...
$("a").click(console.debug.bind(undefined,this));
...rather than passing explicitly the whole function body:
$("a").click(function() {
console.debug(this)
});
Moreover, I would like to access elements selected by jQuery in my shorthand function (and pass them as a parameter). In other words: I expect to have a result of $("a") as a this (or any other code that will retrieve the result).
So far I've tried:
var a = function() {
console.debug(this);
};
var b = console.debug.bind(undefined,this);
$("a").click(function() {console.debug(this)}); // prints link
$("a").click(a); // prints link
b(); // prints Window
$("a").click(console.debug.bind(undefined,this)); // prints Window & jQuery.Event
Here is the fiddle:
https://jsfiddle.net/hbqw2z93/1/
My questions are:
Is it possible to use such construction and meet all requirements, without definition of additional variables - just one line as shown above?
Is it possible to access jQuery's selection result using described approach?
Why in the given scope this becomes 'merged' Window and jQuery.Event object?
You already using it, aren't you? :) It's limited, but it works in your own fiddle
jQuery will pass event object to your specified function. You can use function bind to pass that as an argument (you already have this working in your fiddle)
It doesn't. See what's happening:
jQuery passed one argument to click handler function - event object. You pass console.debug.bind(undefined, this) as a handler function so jQuery will call it with one argument.
Then, when you are binding you are asking to use 'undefined' as a 'this' object inside the function and sending an extra argument - 'this', which is a Window at this scope because you are binding at the highest level.
So when actual click happens, jQuery calls console.debug with two parameters - Window object that was bound during click() and jQuery event that is always passed to click handler. console.debug() can accept and display multiple objects, which is exactly what you see in the developer console.
The first parameter of bind is the new context to use for this. By passing undefined you are essentially not passing the first parameter.
The second and further parameters are passed into the function as the first values.
Note also that this when in the global scope, refers to the window object.
So here, b...
console.debug.bind(undefined,this);
is identical to...
function(){ console.debug(window); }
..since you're passing this (which is window) as the first parameter to debug.
By default, when you attach an event to the element, this will automatically point to the element which caught the event, so bind shouldn't even be necessary, which is why $("a").click(a); worked without using bind.
When I started learning javascript I thought that the browser would simply run the javascript in onclick attribute of elements as if it was inside a script tag. However I realize that is not the case because you can use certain parameters inside these attributes. For example onclick="foo(this, event)" passes the event triggered and the element that the event was triggered on to function foo.
I wonder what other parameters can be used inside these tags? The documentation on w3schools does not mention anything about this. I would also like to know how these attributes are implemented; how is the function called and in what scope (I know that foo will be called like element.foo() but this is not true for other javascript expressions). Is there a comprehensive documentation anywhere? my best guess at the moment is that the implementation looks like this:
element.onclickfunction = function(){
var event = new Event(...)
eval(element.onclick)
}
Edit:
none of the responses really answered my question. I was interested to know what other special parameters can be passed to the function specified in an event handler and how the parameter this is interpreted to be the Element. I am picking the best answer because he provided a link to mdn where EventHandler interface is described.
In JavaScript, you can register an event listener on any DOM element, the document itself, the context window, or any other objects that support events. There are a whole bunch of events that are defined in a whole bunch of web standards. A good resource that lists these out is the Mozilla Developer Network.
The EventListener that gets registered to the event only takes one parameter: the event. You can see that it only has one method, handleEvent, which takes only one parameter.
To pass other stuff into the event handler, you can take advantage of closures or bind(). I'm going to borrow from this answer to demonstrate how bind() works:
elem.addEventListener(function(a1, a2, e) {
// inside the event handler, you have access to both your arguments
// and the event object that the event handler passes
}.bind(elem, arg1, arg2));
Binding elem, arg1, and arg2 to the function means that the this of the function becomes elem, and the first two arguments of the function become arg1 and arg2. The e argument is still the event that triggered the function, just like always. Binding stuff like this is super useful when you want to pass stuff from outside the event handler to inside the handler. You can read more about bind() here.
With regards to your specific question about onclick(), the principle is basically the same except your registering a specific click event handler to an element. It too only takes one argument, and that is the MouseEvent object. But like with any function, you can still bind other arguments to it. See here for more info.
In a codebase I see bind used to make bound copies of functions on the prototype, used as callbacks for DOM events.
Why might this idiom be used, rather than, for example, using the methods on the prototype directly?
Does this offer some benefits in terms of memory consumption/the ability to free memory use when events are unbound from DOM events?
function F() {
var onFoo = this._onFoo.bind(this); // Why?
document.getElementById('foo').onClick(onFoo);
}
F.prototype._onFoo = function () { /*...*/ }
The issue is that event handlers set their own value for this when they call the callback. That value will typically be related to the event handler, not to the object that the method is bound to. For example, in your example:
document.getElementById('foo').onClick(myObj.myFunc);
The this pointer in myFunc will be set to the DOM element that had the event handler attached (in this case, the foo element). But that isn't myObj so myFunc in that case could not access any of it's own instance variables via the this pointer (the normal way that methods access their instance data).
So, if you have a method that wants to access it's own instance data when it is called directly by an event handler, you have to do something other than just pass the method to the event handler. There are a couple ways to work around this issue.
One way of doing so it so use .bind() which returns a new stub function who's function is to set this before calling your function like this:
document.getElementById('foo').addEventListener('click', myObj.myFunc.bind(myObj));
In this case .bind() actually returns a new stub function who's function is to set the value of this to myObj before it calls myFunc.
You could also do that manually yourself like this:
document.getElementById('foo').addEventListener('click', function(e) {
myObj.myFunc();
});
But, as you can see, .bind() provides a shortcut that takes less code (which is why it was invented).
A potential disadvantage to using .bind() in some cases is that you may no longer have access to the value of this that the caller of your callback would have set itself because .bind() threw that value away and replaced it with your own. In the event handler example above, this is not an issue because the original source of the event can be accesses via the e argument that is passed to the event handler so it is not lost if you need it.
I am aware of no meaningful difference in memory consumption or garbage collection between the two methods above. Both create a new function that is used to call the original and control the value of this when calling the original function. Both will have the same garbage collection lifetime.
It appears that one thing that is confusing you is that objects in Javascript are assigned or passed by pointer (some call it by reference, but that has some connotations that don't apply here so I'll use the phrase by pointer).
var x = {};
x.myFunc = function() {console.log("hello");};
x.myFunc(); // generates "hello" in the console
var t = x.myFunc; // save reference to the function that x.myFunc currently points to
delete x.myFunc; // remove property myfunc from the x object
t(); // generates "hello" in the console
t() still works event after x.myFunc has been removed because both t and x.myFunc had a reference (or pointer) to the same function. Doing a delete x.myFunc simply removed the myFunc property from the x object. The function that x.myFunc points to will only be "freed" by the GC when there are no other references to it. But, there is another reference to that function in t, so it is not freed and t() can use it for as long as t exists.
I don't know the meaning of the sentence 'function(event)'
Event.add(apple,'click',function(event) {
Event.stopPropagation(event);
});
Isn't the argument 'event' is the unique keyword of javascript?
Is keyword can be an argument of some function?
I understand the meaning of below code :
function(test) {
alert(test);
}
But I don't understand this one :
function(event)...
Can any one give an explanation about that to me?
The event object is always passed to the handler and contains a lot of useful information what has happened.
Different types of events provide different properties. For example, the onclick event object contains:
event.target - the reference to clicked element. IE uses event.srcElement instead.
event.clientX / event.clientY - coordinates of the pointer at the moment of click.
Information about which button was clicked and other properties.
Please visit this link.
It answers all your questions very simply
Source http://javascript.info/tutorial/obtaining-event-object
Example:
Like if in HTML you have assigned an event like this
<button onclick="alert(event)">See the event</button>
then
function alert(event) {
// event.type contains whether this event was invoked in the result of a click etc
// event.target would contain the reference to the element which invoked this method/event
}
It is an anonymous function, that is a function without name, that sends the event object. That object contains information about the event itself. It is always passed as first object/variable.
It is defining an anonymous function object. This code:
function foo(bar) { ... }
Is functionally similar to:
var foo = function (bar) { ... };
(Except that in the first case the name foo and the creation and assignment of the function object are hoisted to the top of the scope, while in the second case only the name foo is hoisted; foo won't hold the function until the assignment executes.)
Effectively, the code you posted is calling Event.add() and passing a function to it as the third argument, but rather than declaring the function ahead of time it is creating the function object inline.
Another way to write the code block in your question is:
function handler(event) {
Event.stopPropagation(event);
}
Event.add(apple, 'click', handler);
Except that the code in your question does not introduce the handler name.
Note that there is no such method Event.stopPropagation(). However, the event object will have a stopPropagation(), so the capital E was probably a typo. It's likely that the intent was to use function (event) { event.stopPropagation(); }.
event is just a variable that's passed to event listener functions such as Event.add, element.on. It's not reserved (although Event is, which is why you can use Event.add), and you can name it whatever you like.
The event argument is used to pass information about the event that has happened (the click on apple in this case), which can be used to retrieve data about the event or manipulate it.
function(){...} is an anonymous function, which means that you don't need to name it, you can just declare it inline, and the function will be passed as an argument, as if you said
function foo (event) {
...
}
Event.add(apple, "click", foo);
but you don't need to declare it before hand. It does come at the disadvantage of not being duplicable, for instance when clearing an event handler.
Look at the event variable and you will all understand :)
function (event) {
console.log({ event });
}
Sometimes I see functions with parameter like this:
$('#my_div').bind("mouseover mouseenter", function (e) {
console.log(e);
var el = $("#" + e.type);
var n = el.text();
el.text(++n);
});
I don't get what is being passed into the function. I would understand it if it is something like (function(e){ .... }(parameter); but it is not. Can someone shade some light
jQuery will actually call that function, since functions are first class citizen objects in JavaScript, so it can be passed as an argument. e is for event args which jQuery will provide.
This pattern is called "callback".
There's always a parameter being passed, it's just that you're not the one passing it directly. The browser is.
In this case, you're talking about the event handlers. Basically what happens is that when the event is triggered, the browser will pass an event object to the callback of the event listener (the callback you provided).
If you want to know what's inside the event object, look into this mozilla docs page https://developer.mozilla.org/en-US/docs/Web/API/Event
If you want to know how browsers handle the whole passing of event object, here's the specification: http://www.w3.org/html/wg/drafts/html/master/webappapis.html#the-event-handler-processing-algorithm look under 4) where it says "process the event E as follows"
The function isn't actually being called yet. This is telling the browser to call that function for you when the 'mouseover' or 'mouseenter' event happens. In this case, when the browser does that it will pass an event object which will get bound to the local variable e in side of the function.