In the previous part of this series I discussed how HTML DOM can be manipulated using jQuery. Now let's proceed with one of the most common task you do in JavaScript - handling events. jQuery streamlines the JavaScript event handling mechanism by providing you a uniform and easy way to wire events with their handlers without bothering about the cross browser issues. The following table lists some frequently used jQuery events :
Event |
Description |
click |
Occurs when you click on an element |
dblclick |
Occurs when you double click on an element |
hover |
Allows you to trap mouse entry and exit from an element |
mousedown |
Occurs when a mouse button is pressed but not yet released |
mouseup |
Occurs when a pressed mouse button is released |
keydown |
Occurs when a keyboard key is pressed but is yet to be released |
keyup |
Occurs when a keyboard key is released |
keypress |
Occurs when any of the input key is pressed. Normally used when you are only interested in data entered and not in state of Shift or Ctrl keys. |
blur |
Occurs when focus leaves an element |
focus |
Occurs when an element receives focus |
change |
Occurs when value of <input>, <textarea> and <select> changes. |
select |
Occurs when text is selected from <input> or <textarea> |
submit |
Occurs when a form is being submitted. Valid only on <form> element. |
resize |
Occurs when browser windows is resized |
ready |
Occurs when DOM tree is completely loaded |
One nice feature about jQuery event handling is the event object that gets passed to the handlers in a standard way. The event object passed to the event handlers contain several pieces of information about the event such as :
Event object property / method |
Description |
target |
The DOM element that triggered the event |
data |
User specific data passed to the event handler. This is optional. |
pageX |
X coordinate of mouse within the document |
pageY |
Y coordinate of mouse within the document |
preventDefault() |
Allows you to cancel the default action on an event (say form submission when clicked on Submit buttons) |
which |
Indicates the key code of the keyboard key that was pressed |
type |
Type of the event such as click or keydown |
altKey |
Returns true/false depending on whether ALT key is pressed on not |
shiftKey |
Returns true/false depending on whether SHIFT key is pressed on not |
ctrlKey |
Returns true/false depending on whether CTRL key is pressed on not |
To understand how event handling as described above works let's develop an example. In this example we will create a custom context menu (shortcut menu or right click menu) that displays some options specific to our website instead of the normal context menu of the browser. See below for an example :
Begin by adding a new web form and add script reference to jQuery library as before. Then add a <DIV> somewhere in the HTML body as shown below :
<div id="menuContainer"></div>
Our custom context menu will be a DIV with ID menuContainer. We won't store menu options statically. Rather we will put them in an XML file and then retrieve them from jQuery code. The XML file that contains the menu options has the following structure :
<menu>
<menuitem id="item1" text="Home Page" navigateUrl="url1.aspx"></menuitem>
<menuitem id="item2" text="--"></menuitem>
<menuitem id="item3" text="Login"></menuitem>
<menuitem id="item4" text="Administer Users" navigateUrl="url3.aspx"></menuitem>
<menuitem id="item5" text="Check Email" navigateUrl="url4.aspx"></menuitem>
<menuitem id="item6" text="--"></menuitem>
<menuitem id="item7" text="View Orders" navigateUrl="url6.aspx"></menuitem>
</menu>
The root tag is <menu>. In this example we won't go into nested menus. Each menu item is represented by <menuitem> element. The three possible attributes of <menuitem> element are id, text and navigateUrl. The id attribute uniquely identifies a menu item and is used on client side to determine which menu option was clicked by the user. The text attribute indicates the menu item text and the navigateUrl attribute attribute indicates the target URL. If navigateUrl attribute is missing then the menu item becomes clickable one. If text attribute is -- then a menu separator (<HR>) is added.
Now switch to the HTML source view of the web form and define two CSS classes as shown below :
.Hover
{
background-color:silver;
cursor:hand;
}
.MenuPad
{
background-color:whitesmoke;
border:solid 1px gray;
width:200px;
position:absolute;
}
The Hover CSS class defines the appearance of a menu item under the mouse pointer. The MenuPad CSS class defines the overall appearance of the context menu. Notice that MenuPad class sets the position attribute to absolute because we want to display the context menu at the place where user right clicks.
Add a <script> block in the head section of the web form and set ready event handler as shown below :
$(document).ready(OnReady);
The OnReady function looks like this :
function OnReady() {
$.get("Menu.xml", OnSuccess);
$(document)[0].oncontextmenu = function() { return false; }
$(document).mousedown(function(event) {
if (event.which == 3) {
$("#menuContainer").css("left", event.pageX)
.css("top", event.pageY)
.show();
}
})
,
$(document).keydown(function(event) {
if (event.which == 27) {
$("#menuContainer").hide();
}
})
}
The OnReady event handler essentially does four things. Firstly, it retrieves the menu definition file Menu.xml residing on the server. It does so using get() method you learnt in the previous part. The OnSuccess() function will be called upon successfully retrieving Menu.xml. OnSuccess() function is discussed later. Secondly, it suppresses the browser's default context menu from popping up. It is done by handling oncontextmenu event and then returning false from the event handler so that the event is cancelled. Then it handles mousedown and keydown events of document object.
Notice how the event object is passed to the event handler. The mousedown event handler checks the which property of the event object to determine which mouse button was clicked. The value of 3 indicates right click. It then sets the left and top properties using css() method. The event.pageX and event.pageY will give you the mouse pointer coordinates within the document. The show() method makes the menuContainer visible. You could have also set visible attribute to visible but using show() is easier.
The displayed context menu can be discarded by pressing Escape key. The keydown event handler again checks which property and if it is 27 (key code for Esc key) then it hides the menuContainer using hide() method.
The OnSuccess function receives XML menu definition and is shown below :
function OnSuccess(menuData) {
$(menuData).find("menuitem").each(ProcessMenuItem);
$("#menuContainer").addClass("MenuPad")
.hide();
$("#menuContainer div").hover(OnMouseOver, OnMouseOut)
.css("padding", "5px");
}
For each <menuitem> element it calls ProcessMenuItem function. The ProcessMenuItem function add individual menu items to the menuContainer. Initially when the page loads the menuContainer is invisible. So after adding all the menu items we hide the menuContainer. We also handle hover() event for each menu item <DIV> element. The hover event takes two functions one that is called when mouse enters the element and another that is called when mouse leaves the element. The OnMouseOver and OnMouseOut functions are shown below :
function OnMouseOver(event) {
$(this).addClass("Hover");
}
function OnMouseOut(event) {
$(this).removeClass("Hover");
}
The OnMouseOver function adds Hover CSS class to the current menu item using addClass() method. Similarly, OnMouseOut function removes the Hover CSS class using removeClass() method.
function ProcessMenuItem(index) {
var item = $(this);
var text = item.attr("text");
var url = item.attr("navigateUrl");
var menuItemHtml = "";
if (text == "--") {
menuItemHtml = "<hr />";
}
else if(url==null) {
menuItemHtml = "<div>" + text + "</div>";
}
else {
menuItemHtml = "<div>" +
"<a href='" + url + "'>" + text + "</a>" +
"</div>";
}
$("#menuContainer").append(menuItemHtml);
if (url == null) {
$("#menuContainer div:last-child")
.click({ menuItemId: text }, OnMenuItemClick);
}
}
The ProcessMenuItem function is an important one because menu items are added along with their handlers in this function. The ProcessMenuItem function first retrieves the text and navigateUrl attribute values. If text property is -- we wish to add a menu separator in the form of <HR> element. If the URL is specified we wish to display a hyperlink otherwise we simple display menu item text. The new menu item is appended to the menuContainer using append() method (you learnt about append() method in the previous part). Notice the last line carefully. Here, we handle click event of the last menu item. This way click event handler will be attached only to the recently added menu item. Note the first parameter of click event i.e. the one in { and }. This is how you can pass custom data to the event handler (OnMenuItemClick in our case). The first part i.e. menuItemId will appear as a property of event.data object and the later is its value. You can pass multiple pieces of information by separating them with a comma (,) e.g. { piece1:val1,piece2:val2 }.
function OnMenuItemClick(event) {
alert("You clicked : " + event.data.menuItemId);
$("#menuContainer").hide();
}
The OnMouseClick function is called when user clicks on a menu item that doesn't have navigateUrl attribute. Notice how we access the custom event data (event.data.menuItemId ). You can use this menuItemId to have a if...else or switch...case statements and perform different actions depending on the menu item clicked. Once the menu item action is performed we hide the menuContainer.
In the next part I will discuss some of the effects that can jazz up your HTML elements. Stay tuned!