parse data with event listener? - javascript

Is there a way to parse data to a function from the event listener ?
I have this:
div.addEventListener('mousedown',run(id),false);
function run(e,id){
console.log(id);
}
Thing is it executes straight away. The other problem is - if i want to parse the variable id, and the run function recieves e for the event, how do you parse any thing else =/ It's a bit confusing to work out what order e is (before or after your designated variables that you want to parse)
The current work around so far was to assign id to window so its basically a global... but i'm wondering if parsing via the event is possible at all ?

One way is to create a new listener function in which the id variable is already bound to the value that you want, like this:
function newListener(id) {
var listener = function(e) {
console.log(id);
}
return listener;
}
div.addEventListener('mousedown',newListener(id),false);
newListener(id) defines a new function, in which the value that the id variable had at the time is available inside that function. Then the javascript environment will call that function when the mouse button is pressed.

An event handler does not take arguments directly, you are calling the function run(id), not passing a handler, here is how you pass it (using anonymous function)
https://developer.mozilla.org/en/docs/DOM/element.addEventListener
div.addEventListener('mousedown',function(e){
doSomething(id);
},false);
function doSomething(id){
console.log(id);
}

Related

How does addEventListener() receive the event object param automatically?

Consider this code below:
element.addEventListener('click', function(event) { ... })
The addEventListener method works in such a way that its second param is a function into which the event object is automatically passed as a first parameter.
How does addEventListener do this? Is there a programming pattern involved?
Its called a callback where in you call the function parameter inside the function you are running
var success = function(event){
console.log(event);
}
function sample(data, callback){
//peform data manipulation here
var json = JSON.parse(data);
callback(json);
}
var json = localStorage.getItem('user_data');
sample(json, success);
What you see there as event is just the name of the variable that will be used later when the event is triggered, it's not that the event is already being passed as a parameter. You are passing a function that, when the event is triggered, will be called with the actual event.
You could an object that implements EventListener that has a method handleEvent which will receive the event as the first parameter.
Maybe it's easier to understand if you use pass a variable with the function:
myCallback = function(event) {
// do something with event
}
element.addEventListener('click', myCallback);
Iternally (really simplified), it saves a reference to that function and calls it with the actual event (something like myCallback(event)) when the user clicks the element to actually run the function.
https://developer.mozilla.org/en-US/docs/Web/API/EventTarget/addEventListener

Event function declaration

Im trying to understand the declaration of the event handler and the function declaration in this post: https://stackoverflow.com/a/46418688/7727532
Im pretty new to Javascript and jQuery and trying to understand. What I do know is that you declare like the following
$('#clickMe').on('click', doSomeThing(e));
function doSomeThing(e){
console.log(e);
}
The first part I dont understand is
(e) => this._handleScaling(e)
What is happening here? We catch the current object and sending it to function _handleScaling()? But why do we have "(e) =>" before?
Second part is
_handleScaling(e) {
Which if Im right is a local function inside another? Because of the underline start. So maybe the code in the link isnt telling the whole picture?
You need to give function reference rather than function's return value
Replace
$('#clickMe').on('click', doSomeThing(e));
with
$('#clickMe').on('click', doSomeThing); //e is the event object will be automatically passed on to the event handler
The first part I dont understand is
(e) => this._handleScaling(e) What is happening here? We catch the
current object and sending it to function _handleScaling()? But why do
we have "(e) =>" before?
No, _handleScaling is only passed e (event object) so that it can get access to element on which this event has been triggered using e.target since with arrow function this will refer to scope in which this arrow function is defined.

How to pass extra parameter to event handling callback?

I have a button on which I want to attach an event listener. I also need to pass a extra parameter url to this function. I read about apply and I'm doing the following:
$('#list-button').on('click',postListing.apply([url]));
My problem is that as soon as this script is loaded postListing is called. I am not calling the function anywhere else. I need it to be called only on click.
The difference between bind and call/apply is that bind doesn't call the function immediately much like it loads the data with the variable when needed
You can reformat your code so it looks like this
$('#list-button').on('click', postListing.bind(this, url));
Found a way. It can be done using a closure:
var postListing = function(event, url){
return function(){
//Main functionality wrapped here
};
};
And the event listener setting remains the same:
$('#list-button').on('click',postListing.apply([url]));

How to add parameter to bound function created through .bind(this)?

I have added an event listener that points to a method of the current object. Because the context of this was lost, I binded the method. From what I understand, .bind(this) creates a new bound function, which means to remove the event listener, I have to keep the bound function in a variable for future use.
MyObject.prototype.addListener = function () {
var checkAnchorBound = this.checkAnchor.bind(this);
//anAnchorElement points to an anchor tag on the page
this.anAnchorElement.addEventListener("click", checkAnchorBound);
}
Now, whenever I click that anchor, checkAnchor runs and everything works perfectly. The problem is removing the event listener because that event listener needs to be removed inside this.removeListener which is called by this.checkAnchor. That means I cannot pass the bound function as a parameter.
MyObject.prototype.removeListener = function (event) {
//I cannot pass checkAnchorBound from MyObject.addListener as parameter
this.anAnchorElement.removeEventListener("click", checkAnchorBound);
}
I tried storing checkAnchorBound in the object so I would not have to pass the variable as a parameter like so:
MyObject.prototype.addListener = function () {
this.checkAnchorBound = this.checkAnchor.bind(this);
//anAnchorElement points to an anchor tag on the page
this.anAnchorElement.addEventListener("click", this.checkAnchorBound);
}
However, addEventListener no longer works. Is there a way to pass checkAnchorBound as a parameter even though my listener is a bound function? If not, is there a way I can store the bound function inside of MyObject?

What exactly is the parameter e (event) and why pass it to JavaScript functions?

Well, when I learned JavaScript, all the books and Internet articles I read showed code passing a parameter e to functions that handle JavaScript events, such as the code block below:
function myEvent(e) {
var evtType = e.type
alert(evtType)
// displays click, or whatever the event type was
}
I've always accepted that as being the way it is, but now I have some questions (this is very confusing to me):
Where does this e come from? When I look at the entire JavaScript file, e does not seem to exist at all.
Why pass this parameter e to functions? Will functions stop working if I do not pass e to them?
Consider the code block below. There is an event variable (e) passed to an anonymous inner function. Let's say I want to use an event object outside of the anonymous function (maybe in a line above/below the element.onkeypress line). How can I do this?
element.onkeypress = function(e) {
if(e.keyCode) {
element.keyCode = e.keyCode;
} else {
element.keyCode = e.charCode;
}
};
The e is short for event
The simplest way to create an event is to click somewhere on the page.
When you click, a click event is triggered. This event is actually an object containing information about the action that just happened. In this example's case, the event would have info such as the coordinates of the click (event.screenX for example), the element on which you clicked (event.target), and much more.
Now, events happen all the time, however you are not interested in all the events that happen. When you are interested in some event however, it's when you add an event listener to the element you know will create events[1]. For example you are interested in knowing when the user clicks on a 'Subscribe' button and you want to do something when this event happens.
In order to do something about this event you bind an event handler to the button you are interested in. The way to bind the handler to the element is by doing element.addEventListener(eventName, handler).
eventName is a string and it's the name of the event you are interested in, in this case that would be 'click' (for the "click" event).
The handler is simply a function which does something (it's executed) when the event happens. The handler function, by default, when executed is passed the event object (that was created when the event/action you are interested in happened) as an argument.
Defining the event as a parameter of your handler function is optional but, sometimes (most times), it is useful for the handler function to know about the event that happened. When you do define it this is the e you see in the functions like the ones you mentioned. Remember, the event is just a regular javascript object, with lots of properties on it.
Hope that helped.
For more info read Creating and Triggering Events
As for your 3rd question, now you should know you cannot do that, because e only exists when an event happens. You could have the handler function, which has access to the e object when it gets executed, to store it in some global variable and work on that.
[1] That is not exactly correct, but it's simpler to understand. The more correct thing to say there is "add an event listener to the element you know will have events flow through it". See this for more information
The parameter e that you are asking about is an Event object, and it
represents the event being fired which caused your function to be executed. It doesnt really have to be e, you can name it anything you want just like all other function parameters.
Where does this e come from? When I look at the entire javascript file, e
does not seem to exist at all.
You won't be able to find this e variable in your javascript file because
it's really not there at all, but comes from the javascript engine executing
your callback function.
When you give a callback function for some event
(e.g. element.onkeypress = function(e) { ... }), you are giving the
javascript engine a function to execute/call when that event fires, and when
it executes/calls your callback function it passes along an Event object
representing the event that just happened. Javascript could be doing something
like this to call your callback function:
var e = new Event();
callbackFunction(e);
and that's where the Event object e comes from.
Why pass this parameter e to functions? Will the function stop working if
I do not pass e to it?
The function will not stop working if you don't have the e parameter in it.
But if you need to access some details about the event that caused your
function to be executed, you are going to need the e parameter to get them.
Consider the code block below, there is an event variable(e) passed to an
anonymous inner function. Lets say I want to use event object outside of the
anonymous function(maybe in a line above/below the element.onkeypress line),
how can I do this?
I dont think you can do this, even if you store it in a variable outside the
scope of your callback function. This is because your function is not executed
right away when you declare it, but instead only when the event is fired
(e.g. a key is pressed, firing the 'keypress' event).
var event;
element.onkeypress = function(e) {
event = e;
...
};
console.log(event); // => undefined
The only way this could work is when the code that uses the event variable
also gets executed later, specifically after the anonymous function given to
onkeypress gets executed. So the code below could work:
var event;
element.onkeypress = function(e) {
event = e;
...
};
setTimeout(function() {
console.log(event); // => the event object, if the `keypress` event
// fired before `setTimeout` calls this function
}, 100000); // <= set to very large value so that it gets run way way later
I will try my best to explain in the most abstract way possible. The real implementation is probably a lot more complex. Therefore, the names that I am about to use are hypothetical but they do serve a good purpose for explaining things, I hope ;)
Every node in the browser is an implementation of EventEmitter class. This class maintains an object events that contains key:value pairs of eventType (the key) : an Array containing listener functions (the value).
The two functions defined in the EventEmitter class are addEventListener and fire.
class EventEmitter {
constructor(id) {
this.events = {};
this.id = id;
}
addEventListener(eventType, listener) {
if (!this.events[eventType]) {
this.events[eventType] = [];
}
this.events[eventType].push(listener);
}
fire(eventType, eventProperties) {
if (this.events[eventType]) {
this.events[eventType].forEach(listener => listener(eventProperties));
}
}
}
addEventListener is used by the programmer to register their desired listener functions to be fired upon the execution of their desired eventType.
Note that for each distinct eventType, there is a distinct array. This array can hold multiple listener functions for the same eventType.
fire is invoked by the browser in response to user interactions. The browser knows what kind of interaction has been performed and on what node it has been performed. It uses that knowledge to invoke fire on the appropriate node with the appropriate parameters which are eventType and eventProperties.
fire loops through the array associated with the specific eventType. Going through the array, it invokes every listener function inside the array while passing eventProperties to it.
This is how the listener functions, registered only with the particular eventType, are invoked once fire is called.
Following is a demonstration. There are 3 Actors in this demonstration. Programmer, Browser and the User.
let button = document.getElementById("myButton"); // Done by the Programmer
let button = new EventEmitter("myButton"); // Done by the Browser somewhere in the background.
button.addEventListener("click", () =>
console.log("This is one of the listeners for the click event. But it DOES NOT need the event details.")
); // Done By the Programmer
button.addEventListener("click", e => {
console.log(
"This is another listener for the click event! However this DOES need the event details."
);
console.log(e);
}); // Done By the Programmer
//User clicks the button
button.fire("click", {
type: "click",
clientX: 47,
clientY: 18,
bubbles: true,
manyOthers: "etc"
}); // Done By the Browser in the background
After the user clicks on button, Browser invokes fire on button passing "click" as an eventType and the object holding eventProperties. This causes all the registered listener functions under "click" eventType to be invoked.
As you can see, the Browser ALWAYS puts eventProperties on fire. As a programmer, you may or may not use those properties in your listener functions.
Some answers that I found helpful on stackoveflow:
Where is an event registered with addEventListener stored?
Where are Javascript event handlers stored?
When a listener is added using addEventListener, the first argument passed to the function is an Event object, so it will be assigned to the e parameter (or whatever name is given to the function's first parameter).
It's just how JS works, you get event object in every event callback. It contains a lot of info about the event.
Function will not stop working if you do not pass it, it is optional. Go on and console.log the event (e) and see the event object and its properties. It will be more clear when you see what it has.
You can use it outside of that anonymous function by storing it, example:
var myEvent;
element.onkeypress = function(e) {
myEvent = e;
if(e.keyCode) {
element.keyCode = e.keyCode;
} else {
element.keyCode = e.charCode;
}
};
console.log(myEvent);
but you should know that the event object is relative only to that specific event that happened, and considering that you should decide if you really need to do that.

Categories