Basic DOM manipulation with JQuery – II

This was originally published on Oct-31-2013

In my Basic DOM manipulation with JQuery – I post here, we discussed how to select elements from the DOM and do stuff with them. In this post, we will take that a bit further with how to discover elements through events and actions performed by the end-user or the system.

As before, let us use a real example to guide us. Let’s say we wanted to pop up a small “information” box next to an element when the user hovers over the element with the mouse pointer.

In order to do this, what I did was

  1. Create a standard layout template with all three links
  2. Create CSS classes for enabling and disabling,
  3. Identify the link that needs to be disabled (maybe by passing in a variable from the controller)
  4. Identify the link in the DOM using Jscript
  5. Set the appropriate Class using Jscript.

Of these steps, the common theme is

  1. Identify an entity in the DOM using Jscript
  2. Do something with that entity using Jscript.

It is these 2 last steps that I wish to document in this post.

1. Get Ready

First things, first. You need a reference to the latest Jscript library and a good way to do this is to reference the one on the cloud provided by Google.

//ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js

Let us ensure that the entire document object model (DOM) has been loaded by JQuery. You will typically want to put this at the end of your document.

$(document).Ready();

Simple functionality

If what you want to do is a few steps, you can just include it in one big inline function within the Ready();

$(document).Ready(function(){ …… do your stuff here …… });

2. Handling events

There are many different events that can get triggered on the browser. User mouse clicks, hovers, selections, button clicks and so on. We will specifically look at how we will be handling events and then bind to those events. We will also see some hierarchical behavior of events as they bubble up from the children to the parent, etc. So, let’s take a concrete example. Let’s say we wanted to handle a click event on a submit button,
<input id=”submitform” type=”button” /> in order to do this, we will have to

  1. Handling Events: jquery supports many event handlers such as click(), focus(), mousedown(), keypress(), etc. An exhaustive list can be found here: http://api.jquery.com/category/events

In this case, we will be handling the click() event for the button. If you look at the specifications, it describes it as .click( handler(eventObject) ) where eventObject is the the jquery event object which is the target of our click event. So, the flow will be something like, in a script, first find a DOM object, then attach to a specific event for that object and pass it a handler function that will handle that event. So  in this case,

var inp = $(“#submitform”);  // find the object
inp.click(handlerFunction(){alert(“The element, submitform was clicked.“;});  // attach to the click event and handle with the handlerFunction()

  1. Triggering additional events: In addition to handling events as shown above, we may also choose to trigger additional events. So, for instance, we may choose to trigger an event to click another input button, lets say <input id=”anothersubmitbutton” type=”button” /> when the submitform button gets clicked by doing this:

    var inp = $(“#submitform”);  // find the object
    click(handlerFunction(){
    alert(“The element, submitform was clicked.“;  // attach to the click event and handle with the handlerFunction()
    var secondbutton = $(“#anothersubmitbutton”);
    secondbutton.click(); // trigger the click event for the anothersubmitbutton.
    });

Other than the click() function, the change() function is also very useful to track changes to user input in things like text boxes, text areas, input and others.

  1. Passing the event object: When an event triggers, we can also simply pass in the event object to the handler for that event trigger. Therefore, we instead of just click(function(){//do something…}); we could myvar.click(function(e){ // notice we passed in the event object, e }); With the event object, we could grab the target of the event object by doing e.target(); Once you get the target, you can get to other properties by using the attr function after you wrap the target() into a jquery object like this: $(e.target()).attr(‘id’) will return the id.
  2. The .on() function: The .on() function will let you bind a handler to an event for any DOM element such as, $(‘#myid’).on(‘click’, ‘clickHandler(eventObject));
  3. The .off() function: The .off() function will turn off any events associated with a jquery element. So, for instance if $(‘#myid’) had an event click() bound to it, doing $(‘#myid’).off() will disable it. Or we could also disable specific events by passing the event in the off function like, .off(‘click’);
  4. Binding multiple events to a trigger with .on(): You can also bind multiple events to a trigger and any handler you then define will handle both events. This is great for toggling css class between multiple events like,
    $(‘myid’).on(‘mouseenter mouseleave’, ‘myHandler’);
    function myHandler( $(this).toggleClass(‘cssclass’));
  5. What if you wanted to handle events for many, many, many elements? For instance, what if you wanted to capture the click event within a table with thousands or rows and determine which row (tr) was clicked? Here we really need to attach an event (the click on a particular row) to an event handler (whatever you wish to do with that row). This is where you will use the live(), and delegate() with the on() This allows the children of a parent to be attached to be handled by a parent’s event handler. Let’s look at this at more detail.
    1. .live(): The .live() will attach an event and its handler function all the way to the document level and fire at the document level. Therefore if we attached .live() to many elements with a class of myclass and had it’s click event handled by myhandler() function, like so: $(‘.myclass’).live(‘click’, myhandler); then any clicks on any of the elements with that class will fire the myhandler() function at the document level. You kill this behavior by calling the .die() function like $(‘.myclass’).die(‘click’);
    2. .delegate(): The delegate() function will delegate the other way round, so the following will read like: $(‘#myid’).delegate(‘div’, ‘mouseenter’, myhandler); means, For the element identified by myid, I wish to handle the mouseenter event for any of it’s DIV children by calling the myhandler() function. You can also disable this behavior by calling the .undelegate() function like so, $(‘#myid’).undelegate();
    3. .on() to the rescue!! Instead of determining when to use .live() and .delegate() we can simply use .on(). Here is how to use it for instance,
      $(‘#mytable’).on(‘click’, ‘tr’, myhandler); will read like, for the table identified by mytable, capture the click event for any of its children that is a table row (tr) and handle that at the mytable level by firing the function, myhandler(). THIS IS NOW THE PREFERRED WAY TO DO THIS IF YOU ARE ON JQUERY 1.7 OR HIGHER.
    4. .on() with a Map: Consider doing what we did in 7c. above but with different events like this.
      $(‘#mytable tr’).on({
      click: function(){// handle click;},
      dblclick: function(){//handle double click;)
      });
    5. .on() with a bubble up: Consider a large table of many rows or a large catalog of pictures and let’s say you wish to capture the html() from the click event. If you attach it, let’s say using the .on() function then the event handler gets attached to every single row or picture, quite inefficient. However, there is another way of accomplishing this behavior in a more efficient way. To do this,
      1. First select the parent, in the case of the table rows (td), select the table, maybe by using an identifier selector. Now, we can do this:
      2. $(‘#mytableid’).on(‘click’, ‘tr’, eventHandlerFunction({ alert($(this).html()); }); You could also, similarly get the text() for a td element in the same fashion.
  • Notice the tr after the click. The statement above loosely translates to: after you find my table, on the click event, for any tr children, attach the eventHandlerFunction to that event. Notice that the event is attached to the parent (table) and not each of the many children (tr).
  1. Binding to the hover() event: The usage pattern is very straight-forward. For a given selector, on the hover event, define a handler when the mouse enters the selector and another for when the mouse leaves the selector. Sort of like (some selector).hover(eventHandlerMouseIn, eventHandlerMouseleave)
    You can also simplify this by passing a single event handler for both when the mouse enters and when the mouse leaves (let’s say with a css toggle class function). So something like, (some selector).hover(function(){ toggleClass(‘changeBackgroundColorClass’); });

Conclusion

Going back to my original example of showing a box when hovering over an element, here is how I did it.

  1. Define a class that will describe the box.
    .boxy {

border-bottom-color: purple;

border-width: medium;

border-style: solid;

border-radius: 10px;

width: 50px;

height: 50px;

margin: 7px;

padding: 10px;

font-family: ‘Stoke’, serif;

color: purple;

background-color: lightgray;

}

  1. Wire up the selector to show the box when I hover over a specific label and another to remove the box when I hover away from the label
    $(‘#contentArea .lb’).hover(function () {

// var pos = el.position();

$(this).append(“

hover

“).fadeIn(‘2’);

}, function () {

$(‘#xyz’).remove().fadeOut(‘2’);

});
References

http://api.jquery.com

https://developers.google.com/speed/libraries/ – Google Hosted Libraries, including that for JScript

Leave a Reply

Fill in your details below or click an icon to log in:

WordPress.com Logo

You are commenting using your WordPress.com account. Log Out / Change )

Twitter picture

You are commenting using your Twitter account. Log Out / Change )

Facebook photo

You are commenting using your Facebook account. Log Out / Change )

Google+ photo

You are commenting using your Google+ account. Log Out / Change )

Connecting to %s