JQuery 3 - Reinventing Events
Written by Ian Elliot   
Monday, 03 April 2017
Article Index
JQuery 3 - Reinventing Events
Bubbling & Capture
Event Data
Bubbling & Delegation
  • Finally there are some properties that relate to mouse and keyboard:

event.pageX

The mouse position relative the top left edge of the document

event.pageY

The mouse position relative the top left edge of the document

event.which

The key or mouse button that was pressed when the event occurred. This is a replacement for event.keyCode and event.charCode provided by jQuery to make working with mouse and keyboard easier. For a mouse event 1= left button, 2=middle and 3=right button. Note that scroll wheel is usually a middle button.

event.metaKey

True if a meta key - the Windows or Mac Command Key was pressed when the event occurred.

Many events have a default action. For example clicking on a link loads that page into the browser. You can stop default actions using:

event.preventDefault();

You can discover if some other event handler had prevented the default action using:

event.isDefaultPrevented();

You can also stop bubbling, see later using either:

event.stopPropagation()

or:

event.stopImmediatePropagation();

and you can test to see if bubbling has been stopped using:

event.isPropagationStopped();

See the section on bubbling and delegation for more information. 

Event Data

Perhaps the most useful addition that jQuery makes to the event handling mechanism is the ability to pass custom data to an event handler. If you include an object of data as the second or third parameter in on or one, then that object will be passed to the event handler in the data property of the event object. 

The key point is that the link to the object is live. The object is set at the time that the event handler is attached, but what matters is the state of the object when the event happens. 

For example:

 

mydata={};
mydata.value=10;

$("button").on("click",mydata,function(event){
                         alert(event.data.value);
              });
mydata.value=20;


What value do you see when the button is clicked?

The answer is that the event is almost certain to happen well after the code shown has completed and hence the value stored in the object is 20. 

Notice that this implies that the mydata object still exists even though the code that created it came to an end well before the event handler was called. The reason that mydata still exists is that a closure is formed because the event handling function persists after the code has completed. This is an important general point and applies to all event handlers. As they persist for the time that they are attached to an element, they are always associated with a closure that provides them with access to all of the variables that were in scope when they were defined. 

For example, suppose we create a function to attach the event handler:

mydata={};
mydata.value=10;
setEvent=function(){        
  $("button").on("click",mydata,function(event){
                    alert(event.data.value);
                 });
         };
setEvent();
mydata.value=20;

In this case the result is exactly the same in that mydata.value is set to 20 before the event handling function is called. However is we move the definition of mydata into the setEvent function:

setEvent=function(){  
  var mydata={};       
  mydata.value=10;
  $("button").on("click",mydata,function(event){
                             alert(event.data.value); 
                 });
         };
setEvent();
mydata.value=20;

Then the value passed to the event handler is 10 because the mydata outside of the setEvent function is a different object i.e. it is not local to the function. In fact is mydata is defined outside of the function as well the attempt to set value causes a runtime error. This emphasises the fact the a closure is in operation. 

In fact because of the closure we don't really need the data parameter to pass data to the event handler. For example:

setEvent = function () {
  var mydata = {};
  mydata.value = 10;
  $("button").on("click", function (event) {
                      alert(mydata.value);
                 });
};
setEvent();

Notice that we don't need the event object at all as mydata in the closure. 

You might at this point thing that there is no advantage to using event.data but this overlook one difference between it and simply using the closure. The object reference is stored and if you change the object reference later the event handler still gets the original object. For example:

setEvent = function () {
 var mydata = {};
 mydata.value = 10;
 $("button").on("click", mydata,function (event) {
                           alert(event.data.value);
              });
  mydata={};
};
setEvent();

Notice now that mydata is an empty object at the time the event handler is called but the event handler still gets the original object with value set to 10. This wouldn't work if you just used the closure. 

This may seem to be a slight difference but sometimes it can be important. For example a standard demonstration of how things can go wrong with a closure is to try to capture each of the values in a for loop:

for(i=0;i<5;i++){  $("button").on("click",i,function(event){
                     alert(event.data);
              });
}

In this case the index i is the object, remember nearly everything in JavaScript is an object. If you run this and click the button the five event handlers will be called in order and you will see 0, 1, 2, 3, 4 displayed. Compare this to:

for(i=0;i<5;i++){
 $("button").on("click",function(event){
                     alert(i);
              });
}

where the closure is used to access the variable i which is 5 when the loop ends and this is what each of the event handlers access. 

A subtle difference that probably needs some thinking about to get straight in your mind. 

Custom Events

jQuery makes it very easy for you to fire an existing event or implement your own custom event. The trigger function will execute all event handlers attached to an element.

trigger(event,parameters)

where event is the name of the event you want to trigger or an event object specifying the event. The second parameter is optional, but if used it provides additional parameters to pass to the event handler. Notice these have nothing to do with the data passed in the on function and retrieved via the event.data property. These really are additional parameters to be passed to the handler. If parameters is an object then it is passed as a single extra parameter. If parameters is an array then each element is passed as a parameter. 

For example to fire a click event on a button you would use:

$("button").trigger("click");

In this case the event handlers are executed in their standard order and passed the data object specified in the on function when they were attached to the button. 

You can specify additional parameters as part of a standard event handler like click but notice that when the event is fired in the usual way i.e. not via trigger these additional parameters will be undefined. 

For example:

$("button").on("click",function(event,param1,param2){
                                alert(param1 + param2);
             });

$("button").trigger("click",["first","second"]);

In this case param1 is set to "first" and param2 is set to "second" but if you click on the button then they are undefined. Notice that the extra parameters always come after the default event parameter. 

You can use trigger to implement your own events. All you have to do is decide on a name for your event and use on to attach an event handler for it. For example, to attach myevent you would use:

$("button").on("myevent",function(event,param1,param2){
                                 alert(param1 + param2);
             });

Which also passes two additional parameters as in the previous click example. Now you can trigger your custom event using:

$("button").trigger("myevent",["first","second"]);

I is usually a good idea to use a name space to make clear that your event belongs to you. A name space is just a dot separated name. For example 

myevent.mycompany

You can have multiple name spaces but these are not hierarchical.

For example:

myevent.myname.mycompany

creates two name spaces myname and mycompany and you can refer to the event as:

myevent.myname 

or:

myevent.mycompany

If you add an event with a name space you can also make use of the name space removal feature in the off function. So: 

.off("myevent.myname") 

would remove all myevents attached using the myname namespace. 

This works even with standard events such as click. 

<ASIN:1871962501>



Last Updated ( Thursday, 05 May 2022 )