Here is a selection of the events that occur in the browser while you are browsing the web. Any of these events can be used to trigger a function in your JavaScript code.
UI EVENTS Occur when a user interacts with the browser's user interface (UI) rather than the web page
EVENT | DESCRIPTION |
load | Web page has finished loading |
unload | Web page is unloading (usually because a new page was requested) |
error | Browser encounters a JavaScript error or an asset doesn't exist |
resize | Browser window has been resized |
scroll | User has scrolled up or down the page |
KEYBOARD EVENTS | Occur when a user interacts with the keyboard (see also input event) |
EVENT | DESCRIPTION |
keydown | User first presses a key (repeats while key is depressed) |
keyup | User releases a key |
keypress | Character is being inserted (repeats while key is depressed) |
MOUSE EVENTS | Occur when a user interacts with a mouse, trackpad, or touchscreen |
EVENT | DESCRIPTION |
click | User presses and releases a button over the same element |
dblclick | User presses and releases a button twice over the same element |
mousedown | User presses a mouse button while over an element |
mouseup | User releases a mouse button while over an element |
mousemove | User moves the mouse (not on a touchscreen) |
mouseover | User moves the mouse over an element (not on a touchscreen) |
mouseout | User moves the mouse off an element (not on a touchscreen) |
When an event has occurred, it is often described as having fired or been raised. In the diagram on the right, if the user is tapping on a link, a click event would fire in the browser.
Events are said to trigger a function or script. When the click event fires on the element in this diagram, it could trigger a script that enlarges the selected item.
FOCUS EVENTS | Occur when an element (e.g., a link or form field) gains or loses focus |
EVENT | DESCRIPTION |
focus / focusin | Element gains focus |
blur / focusout | Element loses focus |
FORM EVENTS | Occur when a user interacts with a form element |
EVENT | DESCRIPTION |
input | Value in any <input> or <textarea> element has changed (IE9+) or any element with the contenteditable attribute |
change | Value in select box, checkbox, or radio button changes (IE9+) |
submit | User submits a form (using a button or a key) |
reset | User clicks on a form's reset button (rarely used these days) |
cut | User cuts content from a form field |
copy | User copies content from a form field |
paste | User pastes content into a form field |
select | User selects some text in a form field |
MUTATION EVENTS* | Occur when the DOM structure has been changed by a script * To be replaced by mutation observers (see p284) |
EVENT | DESCRIPTION |
DOMSubtreeModified | Change has been made to document |
DOMNodeInserted | Node has been inserted as a direct child of another node |
DOMNodeRemoved | Node has been removed from another node |
DOMNodeInsertedIntoDocument | Node has been inserted as a descendant of another node |
DOMNodeRemovedFromDocument | Node has been removed as a descendant of another node |
When the user interacts with the HTML on a web page, there are three steps involved in getting it to trigger some JavaScript code. Together these steps are known as event handling.
1
Select the element node(s) you want the script to respond to.
For example, if you want to trigger a function when a user clicks on a specific link, you need to get the DOM node for that link element. You do this using a DOM query (see Chapter 5).
The UI events that relate to the browser window (rather than the HTML page loaded in it) work with the window object rather than an element node. Examples include the events that occur when a requested page has finished loading, or when the user scrolls. You will learn about using these on p272.
2
Indicate which event on the selected node(s) will trigger the response.
Programmers call this binding an event to a DOM node.
The previous two pages showed a selection of the popular events that you can monitor for.
Some events work with most element nodes, such as the mouseover event, which is triggered when the user rolls over any element. Other events only work with specific element nodes, such as the submit event, which only works with a form.
3
State the code you want to run when the event occurs.
When the event occurs, on a specified element, it will trigger a function. This may be a named or an anonymous function.
Here you can see how event handling can be used to provide feedback to users filling in a registration form. It will show an error message if their username is too short.
1
SELECT ELEMENT
The element that users are interacting with is the text input where they enter the username.
2
SPECIFY EVENT
When users move out of the text input, it loses focus, and the blur event fires on this element.
3
CALL CODE
When the blur event fires on the username input, it will trigger a function called checkUsername(). This function checks if the username is less than 5 characters.
If there are not enough characters, it shows an error message that prompts the user to enter a longer username.
If there are enough characters, the element that holds the error message should be cleared.
This is because an error message may have been shown to the user already and they subsequently corrected their mistake. (If the error message was still visible when they had filled in the form correctly, it would be confusing.)
Event handlers let you indicate which event you are waiting for on any particular element. There are three types of event handlers.
See p251
This is bad practice, but you need to be aware of it because you may see it in older code.
Early versions of HTML included a set of attributes that could respond to events on the element they were added to. The attribute names matched the event names. Their values called the function that was to run when that event occurred.
For example, the following: <a onclick=“hide()”> indicated that when a user clicked on this <a> element, the hide() function would be called.
This method of event handling is no longer used because it is better to separate the JavaScript from the HTML. You should use one of the other approaches shown on this page instead.
See p252
DOM event handlers were introduced in the original specification for the DOM. They are considered better than HTML event handlers because they let you separate the JavaScript from the HTML.
Support in all major browsers is very strong for this approach. The main drawback is that you can only attach a single function to any event. For example, the submit event of a form cannot trigger one function that checks the contents of a form, and a second to submit the form data if it passes the checks.
As a result of this limitation, if more than one script is used on the same page, and both scripts respond to the same event, then one or both of the scripts may not work as intended.
See p254
Event listeners were introduced in an update to the DOM specification (DOM level 2, released in the year 2000). They are now the favored way of handling events.
The syntax is quite different and, unlike traditional event handlers, these newer event listeners allow one event to trigger multiple functions. As a result, there are less likely to be conflicts between different scripts that run on the same page.
This approach does not work with IE8 (or earlier versions of IE) but you meet a workaround on p258. Differences in browser support for the DOM and events helped speed adoption of jQuery (but you need to know how events work to understand how jQuery uses them).
Please note: This approach is now considered bad practice; however, you need to be aware of it because you may see it if you are looking at older code. (See previous page.)
In the HTML, the first <input> element has an attribute called onblur (triggered when the user leaves the element). The value of the attribute is the name of the function that it should trigger.
The value of the event handler attributes would be JavaScript. Often it would call a function that was written either in the <head> element or a separate JavaScript file (as shown below).
The names of the HTML event handler attributes are identical to the event names shown on p246 - p247, preceded by the word “on.”
For example:
All modern browsers understand this way of creating an event handler, but you can only attach one function to each event handler.
Here is the syntax to bind an event to an element using an event handler, and to indicate which function should execute when that event fires:
Below, the event handler is on the last line (after the function has been defined and the DOM element node(s) selected).
When a function is called, the parentheses that follow its name tell the JavaScript interpreter to “run this code now.”
We don't want the code to run until the event fires, so the parentheses are omitted from the event handler on the last line.
An example of an anonymous function and a function with parameters is shown on p256.
In this example, the event handler appears on the last line of the JavaScript. Before the DOM event handler, two things are put in place:
1. If you use a named function when the event fires on your chosen DOM node, write that function first. (You could also use an anonymous function.)
2. The DOM element node is stored in a variable. Here the text input (whose id attribute has a value of username) is placed into a variable called elUsername.
When using event handlers, the event name is preceded by the word “on” (onsubmit, onchange, onfocus, onblur, onmouseover, onmouseout, etc).
3. On the last line of the code sample above, the event handler elUsername.onblur indicates that the code is waiting for the blur event to fire on the element stored in the variable called elUsername.
This is followed by an equal sign, then the name of the function that will run when the event fires on that element. Note that there are no parentheses on the function name. This means you cannot pass arguments to this function. (If you want to pass arguments to a function in an event handler, see p256.)
The HTML is the same as that shown on p251 but without the onblur event attribute. This means that the event handler is in the JavaScript, not the HTML.
Browser support: On line 3, the checkUsername() function uses the this keyword in the conditional statement to check the number of characters the user entered. It works in most browsers because they know this refers to the element the event happened on.
However, in Internet Explorer 8 or earlier, IE would treat this as the window object. As a result, it would not know which element the event occurred on and there would be no value that it checked the length of, so it would raise an error. You will learn a solution for this issue on p264.
Event listeners are a more recent approach to handling events. They can deal with more than one function at a time but they are not supported in older browsers.
Here is the syntax to bind an event to an element using an event listener, and to indicate which function should execute when that event fires:
An example of an anonymous function and a function with parameters is shown on p256.
In this example, the event listener appears on the last line of the JavaScript. Before you write an event listener, two things are put in place:
1. If you use a named function when the event fires on your chosen DOM node, write that function first. (You could also use an anonymous function.)
2. The DOM element node(s) is stored in a variable. Here the text input (whose id attribute has a value of username) is placed into a variable called elUsername.
The addEventListener() method takes three properties:
i) The event you want it to listen for. In this case, the blur event.
ii) The code that you want it to run when the event fires. In this example, it is the checkUsername() function. Note that the parentheses are omitted where the function is called because they would indicate that the function should run as the page loads (rather than when the event fires).
iii) A Boolean indicating how events flow, see p260. (This is usually set to false.)
Internet Explorer 8 and earlier versions of IE do not support the addEventListener() method, but they do support a method called attachEvent() and you will see how to use this on p258.
Also, as with the previous example, IE8 and older versions of IE would not know what this referred to in the conditional statement. An alternative approach for dealing with it is shown on p270.
Unlike the HTML and traditional DOM event handlers, when you specify the name of the event that you want to react to, the event name is not preceded by the word “on”.
If you need to remove an event listener, there is a function called removeEventListener() which removes the event listener from the specified element (it has the same parameters).
Because you cannot have parentheses after the function names in event handlers or listeners, passing arguments requires a workaround.
Usually, when a function needs some information to do its job, you pass arguments within the parentheses that follow the function name.
When the interpreter sees the parentheses after a function call, it runs the code straight away. In an event handler, you want it to wait until the event triggers it.
Therefore, if you need to pass arguments to a function that is called by an event handler or listener, you wrap the function call in an anonymous function.
The named function that requires the arguments lives inside the anonymous function.
Although the anonymous function has parentheses, it only runs when the event is triggered.
The named function can use arguments as it only runs if the anonymous function is called.
The first line of this example shows the updated checkUsername() function. The minLength parameter specifies the minimum number of characters that the username should be.
The value that is passed into the checkUsername() function is used in the conditional statement to check if the name is long enough, and provide feedback if the username name is too short.
The event listener on the last three lines is longer than the previous example because the call to the checkUsername() function needs to include the value for the minLength parameter.
To receive this information, the event listener uses an anonymous function, which acts like a wrapper. Inside that wrapper the checkUsername() function is called, and passed an argument.
Browser support: On the next page you also see how to deal with the lack of support for event listeners in IE8 and earlier.
IE5-8 had a different event model and did not support addEventListener() but you can provide fallback code to make event listeners work with older versions of IE.
IE5-IE8 did not support the addEventListener() method. Instead, it used its own method called attachEvent() which did the same job, but was only available in Internet Explorer. If you want to use event listeners and need to support Internet Explorer 8 or earlier, you can use a conditional statement as illustrated below.
Using an if…else statement, you can check if the browser supports the addEventListener() method. The condition in the if statement will return true if the browser supports the addEventListener() method, and you can use it. If the browser does not support that method, it returns false, and the code will try to use the attachEvent() method.
When attachEvent() is used, the event name should be preceded by the word “on” (e.g., blur becomes onblur). You will see another approach to supporting the older IE event model in Chapter 13 (using a utility file).
The event handling code builds on the last example, but it is a lot longer this time because it contains the fallback for Internet Explorer 5-8.
After the checkUsername() function, an if statement checks whether addEventListener() is supported or not; it returns true if the element node supports this method, and false if it does not.
If the browser supports the addEventListener() method, the code inside the first set of curly braces is run using addEventListener().
If it is not supported, then the browser will use the attachEvent() method that older versions of IE will understand. In the IE version, note that the event name must be preceded by the word “on.”
If you need to support IE8 (or older), instead of writing this fallback code for every event you are responding to, it is better to write your own function (known as a helper function) that creates the appropriate event handler for you. You will see a demonstration of this in Chapter 13, which covers form enhancement and validation.
It is, however, important to understand this syntax, used by IE8 (and older) so that you know why the helper function is used and what it is doing.
As you will see in the next chapter, this is another type of cross-browser inconsistency that jQuery can take care of for you.
HTML elements nest inside other elements. If you hover or click on a link, you will also be hovering or clicking on its parent elements.
Imagine a list item contains a link. When you hover over the link or click on it, JavaScript can trigger events on the <a> element, and also any elements the <a> element sits inside.
The event starts at the most specific node and flows outwards to the least specific one. This is the default type of event flow with very wide browser support.
Event handlers/listeners can be bound to the containing <li>, <ul>, <body>, and <html> elements, plus the document object, and the window object. The order in which the events fire is known as event flow, and events flow in two directions.
The event starts at the least specific node and flows inwards to the most specific one. This is not supported in Internet Explorer 8 and earlier.
The flow of events only really matters when your code has event handlers on an element and one of its ancestor or descendant elements.
The example below has event listeners that respond to the click event on each of the following elements:
The event will show the HTML content of that element in an alert box, and event flow will tell you which element the click is registered upon first.
For traditional DOM event handlers (and HTML event attributes), all modern browsers default to using event bubbling rather than capturing. With event listeners, the final parameter in the addEventListener() method lets you choose the direction to trigger events:
The event-flow.js file (shown on the left, and available in the download code) demonstrates the difference between bubbling and capturing. In this example, the event handlers have a value of false for their last parameter indicating events should be followed in bubbling phase. So the first alert box shows the content of the innermost <a> element, and works its way out. You can also see the capturing version in the download code.
When an event occurs, the event object tells you information about the event, and the element it happened upon.
Every time an event fires, the event object contains helpful data about the event, such as:
The event object is passed to any function that is the event handler or listener.
If you need to pass arguments to a named function, the event object will first be passed to the anonymous wrapper function (this happens automatically); then you must specify it as a parameter of the named function (as shown on the next page).
When the event object is passed into a function, it is often given the parameter name e (for event). It is a widely used shorthand (and you see it adopted throughout this book).
Note, however, that some programmers also use the parameter name e to refer to the error object; so e may mean event or error in some scripts.
Not only did IE8 have a different syntax for event listeners (as shown on p258), the event object in IE5-8 also had different names for the properties and methods shown in the tables below, and the example on p265.
EVENT LISTENER WITH NO PARAMETERS
1. Without you doing anything, a reference to the event object is automatically passed from the number 1, where the event listener calls the function…
2. To here, where the function is defined. At this point, the parameter must be named. It Is often given the name e for event.
3. This name can then be used inside the function as a reference to the event object. You can now use the properties and methods of the event object.
EVENT LISTENER WITH PARAMETERS
1. The reference to the event object is automatically passed to the anonymous function, but it must be named in the parentheses.
2. The reference to the event object can then be passed onto the named function. It is given as the first parameter of the named function.
3. The named function receives the reference to the event object as the first parameter of the method. 4. It can now be used by this name in the named function.
Below you can see how you get the event object in IE5-8. It is not passed automatically to event handler/listener functions; but it is available as a child of the window object.
On the right, an if statement checks if the event object has been passed into the function. As you saw on p168, the existence of an object is treated as a truthy value, so the condition here is saying “if the event object does not exist…”
In IE8 and less, e will not hold an object, so the following code block runs and e is set to be the event object that is a child of the window object.
Once you have a reference to the event object, you can get its properties using the technique on the right. This works on short circuit evaluation (see p169).
If you need to assign event listeners to several elements, here is a function that will return a reference to the element the event happened on.
Here is the example that has been used throughout the chapter so far with some modifications:
1. The function is called checkLength() rather than checkUsername(). It can be used on any text input.
2. The event object is passed to the event listener. The code includes fallbacks for IE5-8 (Chapter 13 demonstrates using helper functions to do this).
3. In order to determine which element the user was interacting with, the function uses the event object's target property (and for IE5-8 it uses the equivalent srcElement property).
This function is now far more flexible than the previous code you have seen in this chapter because:
1. It can be used to check the length of any text input so long as that input is directly followed by an empty element that can hold a feedback message for the user. (There should not be space or carriage returns between the two elements; otherwise, some browsers might return a whitespace node.)
2. The code will work with IE5-8 because it tests whether the browser supports the latest features (or whether it needs to fallback to use older techniques).
Creating event listeners for a lot of elements can slow down a page, but event flow allows you to listen for an event on a parent element.
If users can interact with a lot of elements on the page, such as:
adding event listeners to each element can use a lot of memory and slow down performance.
Because events affect containing (or ancestor) elements (due to event flow - p260), you can place event handlers on a containing element and use the event object's target property to find which of its children the event happened on.
By attaching an event listener to a containing element, you are only responding to one element (rather than having an event handler for each child element).
You are delegating the job of the event listener to a parent of the elements. In the list shown here, if you place the event listener on the <ul> element rather than on links in each <li> element, you only need one event listener. This gives better performance, and if you add or remove items from the list it would still work the same. (The code for this example is shown on p269.)
ADDITIONAL BENEFITS OF EVENT DELEGATION
If you add new elements to the DOM tree, you do not have to add event handlers to the new elements because the job has been delegated to an ancestor.
Earlier in the chapter, the this keyword was used to identify an event's target, but that technique did not work in IE8, or when a function needed parameters.
It requires fewer functions to be written, and there are fewer ties between the DOM and your code, which helps maintainability.
The event object has methods that change: the default behavior of an element and how the element's ancestors respond to the event.
preventDefault()
Some events, such as clicking on links and submitting forms, take the user to another page.
To prevent the default behavior of such elements (e.g., to keep the user on the same page rather than following a link or being taken to a new page after submitting a form), you can use the event object's preventDefault() method.
IE5-8 have an equivalent property called returnValue which can be set to false. A conditional statement can check if the preventDefault() method is supported, and use IE8's approach if it isn't:
if (event.preventDefault) {
event.preventDefault();
} else {
event.returnValue = false;
}
stopPropagation()
Once you have handled an event using one element, you may want to stop that event from bubbling up to its ancestor elements (especially if there are separate event handlers responding to the same events on the containing elements).
To stop the event bubbling up, you can use the event object's stopPropogation() method.
The equivalent in IE8 and earlier is the cancelBubble property which can be set to true. Again, a conditional statement can check if the stopPropogation() method is supported and use IE8's approach if not:
if (event.stopPropogation) {
event.stopPropogation();
} else {
event.cancelBubble = true;
}
You will sometimes see the following used in similar situations that are in a function: return false;
It prevents the default behavior of the element, and prevents the event from bubbling up or capturing further. It also works in all browsers, so it is popular.
Note, however, when the interpreter comes across the return false statement, it stops processing any subsequent code within that function and moves to the next statement after the function was called.
Since this blocks any further code within the function, it is often better to use the preventDefault() method of the event object rather than return false.
This example will put together a lot of what you have learned in the chapter so far. Each list item contains a link. When the user clicks on that link (to indicate they have completed that task), the item will be removed from the list.
1. The event listener will be added to the <ul> element, so this needs to be selected.
2. Check whether or not the browser supports addEventListener().
3. If so, use it to call the itemDone() function when the user clicks anywhere on that list.
4. If not, use the attachEvent() method.
5. The itemDone() function will remove the item from the list. It requires three pieces of information.
6. Three variables are declared to hold the info.
7. target holds the element the user clicked on. To obtain this, the getTarget() function is called. This is created at the start of the script, and shown at the bottom of the flowchart.
8. elParent holds that element's parent (the <li>)
9. elGrandparent holds that element's grandparent
10. The <li> element is removed from the <ul> element.
11. Check if the browser supports preventDefault() to prevent the link taking the user to a new page.
12. If so, use it.
13. If not, use the older IE returnValue property.
In the HTML, the links would take you to itemDone.php if the browser did not support JavaScript. (The PHP file is not supplied with the code download because server-side languages are beyond the scope of this book.)
When calling a function, the event object's target property is the best way to determine which element the event occurred on. But you may see the approach below used; it relies on the this keyword.
The this keyword refers to the owner of a function. On the right, this refers to the element that the event is on.
This works when no parameters are being passed to the function (and therefore it is not called from an anonymous function).
function checkUsername(el, minLength) { var elMsg = document.getElementById(‘feedback’); if (el.value.length < minLength) { elMsg.innerHTML = ‘Not long enough’; } else { elMsg.innerHTML = ‘’; } } var el = document.getElementById(‘username’); el.addEventListener(‘blur’, function() { checkUsername(el, 5); }, false);
If you pass parameters to the function, the this keyword no longer works because the owner of the function is no longer the element that the event listener was bound to, it is an anonymous function.
You could pass the element the event was called on as another parameter of the function.
In both cases, the event object is the preferred approach.
In the rest of the chapter, you learn about the different types of events you can respond to.
Events are defined in:
The DOM events specification is managed by the W3C (who also look after other specifications including HTML, CSS, and XML). Most of the events you will meet in this chapter are part of this DOM events specification.
Browsers implement all the events using the same event object that you already met. It also provides feedback such as which element the event occurred on, which key a user pressed, or where the cursor is positioned).
There are, however, some events that are not covered in the DOM event model - in particular those that deal with form elements. (They used to be part of the DOM, but got moved to the HTML5 specification.)
Most are a result of the user interacting with the HTML, but there are a few that react to the browser or other DOM events.
The HTML5 specification (that is still being developed) details events that browsers are expected to support that are specifically used with HTML. For example, events that are fired when a form is submitted or form elements are changed (which you will meet on p282):
submit
input
change
There are also new events introduced with the HTML5 specification that are only supported by more recent browsers. Here are a few (which you will meet on p286):
readystatechange
DOMContentLoaded
hashchange
We do not show every event, but the examples you see should teach you enough so that you can work with all types of events.
Browser manufacturers also implement some events as part of their Browser Object Model (or BOM). Typically these are events not (yet) covered by W3C specifications (although some will be added to W3C specifications in the future). Several of these events dealt with touchscreen devices:
touchstart
touchend
touchmove
orientationchange
Other events are being added to capture gestures and take advantage of accelerometers. Care is needed using such features, as different browsers often create different implementations of similar functionality.
User interface (UI) events occur as a result of interaction with the browser window rather than the HTML page contained within it, e.g., a page having loaded or the browser window being resized.
The event handler / listener for UI events should be attached to the browser window.
In old HTML code, you may see these events used as attributes on the opening <body> tag. (For example, older code used the onload attribute to trigger code that would run when the page had loaded.)
The load event is commonly used to trigger scripts that access the contents of the page. In this example, a function called setup() gives focus to the text input when the page has loaded.
The event is automatically raised by the window object when a page has finished loading the HTML and all of its resources: images, CSS, scripts (even third party content e.g., banner ads).
The setup() function would not work before the page has loaded because it relies on finding the element whose id attribute has a value of username, in order to give it focus.
Note that the event listener is attached to the window object (not the document object - as this can cause cross-browser compatibility issues).
If the <script> element is at the end of the HTML page, then the DOM would have loaded the form elements before the script runs, and there would be no need to wait for the load event. (See also: the DOMContentLoaded event on p286 and jQuery's document.ready() method on p312.)
Because the load event only fires when everything else on the page has loaded (images, scripts, even ads), the user already have started to use the page before the script has started to run.
Users particularly notice when a script changes the appearance of the page, changes focus, or selects form elements after they have started to use it. (It can make a site look slower to load.)
Imagine this form had more inputs; the user may be filling in the second or third box when the script fires - moving focus back to the first box too late and interrupting the user.
The HTML elements you can interact with, such as links and form elements, can gain focus. These events fire when they gain or lose focus.
If you can interact with an HTML element, then it can gain (and lose) focus. You can also tab between the elements that can gain focus (a technique often used by those with visual impairments).
In older scripts, the focus and blur events were often used to change the appearance of an element as it gained focus, but now the CSS :focus pseudoclass is a better solution (unless you need to affect an element other than the one that gained focus).
The focus and blur events are most commonly used on forms. They can be particularly helpful when:
In this example, as the text input gains and loses focus, feedback is shown to the user in the <div> element under the text input. The feedback is given using two functions.
tipUsername() is triggered when the text input gains focus. It changes the class attribute of the element containing the message, and updates the contents of the element.
checkUsername() is triggered when the text input loses focus. It adds a message and changes the class if the username is less than 5 characters; otherwise, it clears the message.
The mouse events are fired when the mouse is moved and also when its buttons are clicked.
All of the elements on a page support the mouse events, and all of these bubble. Note that actions are different on touchscreen devices.
Preventing a default behavior can have unexpected results. E.g., a click event only fires when both the mousedown and mouseup event have fired.
The mouseover and mouseout events were often used to change the appearance of boxes or to switch images as the user rolls over them. To change the appearance of the element, a preferable technique would be to use the CSS :hover pseudo-class.
The mousedown and mouseup events separate out the press and release of a mouse button. They are commonly used for adding drag and drop functionality, or to add controls in game development.
The aim of this example is to use the click event to remove the big note that has been added to the middle of the page. But first, the script has to create that note.
Because the note is over the top of the page, we only want to show it to users who have JavaScript enabled (otherwise they could not hide it).
When the click event fires on the close link the dismissNote() function is called. This function will remove the note that was added by the same script.
The click event can be applied to any element, but it is better to only use it on items that are usually clicked or it will not be accessible to people who rely upon keyboard navigation.
You may also be tempted to use the click event to run a script when a user clicks on a form element, but it is better to use the focus event because that fires when the user accesses that control using the tab key.
The event object can tell you where the cursor was positioned when an event was triggered.
The screenX and screenY properties indicate the position of the cursor within the entire screen on your monitor, measuring from the top left corner of the screen (rather than the browser).
The pageX and pageY properties indicate the position of the cursor within the entire page. The top of the page may be outside of the viewport so even if the cursor is in the same position, page and client coordinates can be different.
The clientX and clientY properties indicate the position of the cursor within the browser's viewport. If the user has scrolled down and the top of the page is no longer in view, it will not affect the client coordinates.
In this example, as you move your mouse around the screen, the text inputs across the top of the page are updated with the current mouse position.
This demonstrates the three different positions you can retrieve when the mouse is moved or when one of the buttons is clicked.
Note how showPosition() is passed event as a parameter, which refers to the event object. The positions are all properties of this event object.
The keyboard events are fired when a user interacts with the keyboard (they fire on any kind of device with a keyboard).
EVENT | TRIGGER |
input | Fires when the value of an <input> or <textarea> element changes. First supported in IE9 (although it does not fire when deleting text in IE9). For older browsers, you can use keydown as a fallback. |
keydown | Fires when the user presses any key on the keyboard. If the user holds down a key, the event continues to fire repeatedly. This is important because it mimics what would happen in a text input if the user holds down a key (the same character would be added repeatedly while the key is held down). |
keypress | Fires when the user presses a key that would result in a character being shown on the screen. For example, this event would not fire when the user presses the arrow keys, whereas the keydown event would. If the user holds down a key, the event continues to fire repeatedly. |
keyup | Fires when the user releases a key on the keyboard. The keydown and keypress events fire before a character shows on screen, whereas keyup fires after it appears. |
The three events that begin key… fire in this order:
1. keydown - user presses key down
2. keypress - user has pressed or is holding a key that adds a character into the page
3. keyup - user releases key
When you use the keydown or keypress events, the event object has a property called keyCode, which can be used to tell which key was pressed. However, it does not return the letter for that key (as you might expect); it returns an ASCII code that represents the lowercase character for that key. You can see a table of the characters and their ASCII codes in an online extra on the website accompanying this book.
If you want to get the letter or number as it would be displayed on the keyboard (rather than an ASCII equivalent), the String object has a built-in method called fromCharCode() which will do the conversion for you: String.fromCharCode(event.keycode);
In this example, the <textarea> element should only have 180 characters. When the user enters text, the script will show them how many characters they have left available to use.
The event listener checks for the keypress event on the <textarea> element. Each time it fires, the charCount() function updates the character count and shows the last character used.
The input event would work well to update the count when the user pastes in text or uses keys like backspace, but it does not tell you which key was the last to be pressed.
There are two events that are commonly used with forms. In particular you are likely to see submit used in form validation.
EVENT | TRIGGER |
submit | When a form is submitted, the submit event fires on the node representing the <form> element. It is most commonly used when checking the values a user has entered into a form before sending it to the server. |
change | Fires when the status of several form elements change. For example, when:
It is often better to use the change event rather than the click event because clicking is not the only way users interact with form elements (for example, they might use the tab, arrow, or Enter keys). |
input | The input event, which you saw on the previous page is commonly used with <input> and <textarea> elements. |
The focus and blur events (which you met on p274) are often used with forms, but they can also be used in conjunction with other elements, such as links (so they are not specifically related to forms).
Checking form values is known as validation. If users miss required information or enter incorrect information, checking it using JavaScript is faster than sending the data to the server for it to be checked. Validation is covered in Chapter 13.
When a user interacts with the drop-down select box, the change event will trigger the packageHint() function. This shows messages below the select box that reflect the choice.
When the form is submitted, the checkTerms() function is called. This tests to see if the user has checked the box that indicates they agree to the terms and conditions.
If not, the script will prevent the default behavior of the form element (and stop it from submitting the form data to the server) and it will show an error message to the user.
Whenever elements are added to or removed from the DOM, its structure changes. This change triggers a mutation event.
When your script adds or removes content from a page it is updating the DOM tree. There are many reasons why you might want to respond to the DOM tree being updated, for example, you might want to tell the user that the page had changed.
Below are some events that are triggered when the DOM changes. These mutation events were introduced in Firefox 3, IE9, Safari 3, and all versions of Chrome. But they are already scheduled to be replaced by an alternative called mutation observers.
EVENT | TRIGGER |
DOMNodeInserted | Fires when a node is inserted into the DOM tree. e.g. using appendChild(), replaceChild(), or insertBefore(). |
DOMNodeRemoved | Fires when a node is removed from the DOM tree. e.g. using removeChild() or replaceChild(). |
DOMSubtreeModified | Fires when the DOM structure changes. It fires after the two events listed above occur. |
DOMNodeInsertedIntoDocument | Fires when a node is inserted into the DOM tree as a descendant of another node that is already in the document. |
DOMNodeRemovedFromDocument | Fires when a node is removed from the DOM tree as a descendant of another node that is already in the document. |
If your script makes a lot of changes to a page, you end up with a lot of mutation events firing. This can make a page feel slow or unresponsive. They can also trigger other event listeners as they propagate through the DOM, which modify other parts of the DOM, triggering more mutation events. Therefore they are being replaced by mutation observers.
Browser support: Chrome, Firefox 3, IE 9, Opera 9, Safari 3
Mutation observers are designed to wait until a script has finished its task before reacting, then report the changes as a batch (rather than one at a time). You can also specify the type of changes to the DOM that you want them to react to. But at the time of writing, the browser support was not widespread enough to use them on public websites.
Browser support: IE 11, Firefox 14, Chrome 27 (or 18 with webkit prefix), Safari 6.1, Opera 15 On mobile: Android 4.4, Safari on iOS 7.
In this example, two event listeners each trigger their own function. The first is on the last but one line, and it listens for when the user clicks the link to add a new list item. It then uses DOM manipulation events to add a new element (changing the DOM structure and triggering mutation events).
The second event listener waits for the DOM tree within the <ul> element to change. When the DOMNodeInserted event fires, it calls a function called updateCount(). This function counts how many items there are in the list, and then updates the list count at the top of the page accordingly.
Here are three page-level events that have been included in versions of the HTML5 spec that have become popular very quickly.
There are also several other events that are being introduced to support more recent devices (such as phones and tablets). They respond to events such as gestures and movements that are based upon an accelerometer (which detects the angle at which a device is being held).
In this example, as soon as the DOM tree has been formed, focus is given to the text input with an id of username.
The DOMContentLoaded event fires before the load event (because the latter waits for all of the page's resources to load).
If users try to leave the page before they press the submit button, the beforeunload event checks that they want to leave.
On the left, you can see the dialog box that is shown when you try to navigate away from the page.
The text before your message and on the buttons may change from browser to browser (you have no control over this).
This example shows an interface for a user to record voice notes. The user can enter a name which is displayed in the heading, and they can press record (which changes the image that is shown).
When the user starts typing a name into the text box, the keyup event will trigger a function called writeLabel() which copies the text from the form input and writes it into the main heading under the logo for List King, replacing the words ‘AUDIO NOTE’.
The record / pause button is a bit more interesting. The button has an attribute called data-state. When the page loads, its value is record. When the user presses the button, the value of this attribute changes to pause (this triggers a new CSS rule to indicate that it is now recording).
If you have not used HTML5's data- attributes, they allow you to store custom data on any HTML element. (The name of the attribute can be anything starting with data- as long as the name is lowercase.)
This demonstrates a new technique based upon event delegation. The event listener is placed upon the containing element whose id is buttons. The event object is used to determine the value of the id attribute on the element that was used. The value from that id attribute is then used in a switch statement to decide which function to call (depending on whether the button is in record state or pause state).
This is a good way to handle many buttons because it reduces the number of event listeners in your code.
The event listeners are written at the bottom of the page, and they have fallbacks for users who are running IE8 or less (which has a different event model).
The script starts by defining the variables that it will need to use, and then collecting the element nodes that are needed.
The player functions (shown on the right-hand page) would appear next, and at the bottom of this page you can see the event listeners.
The event listeners live inside a conditional statement so that the attachEvent() method can be used for visitors who have IE8 or less.
The recorderControls() function is automatically passed the event object. Not only does this offer code to support older versions of IE, but also stops the link from performing its default behavior (of taking the user to a new page).
The switch statement is used to indicate which function to run depending on whether the user is trying to record or stop the audio note. This technique of delegation is a good way to cope with multiple buttons in the UI.
SUMMARY
EVENTS
18.223.170.223