This course will become read-only in the near future. Tell us at community.p2pu.org if that is a problem.

The DOM and Events


Week 3 -The DOM and Events



http://yuiblog.com/yuitheater/crockford-yuiconf2009-state.m4v  This Crockford address was in the run up to Ecmascript5, interesting and funny, see what he says about the DOM (and Html5).

Document Object Model (DOM) is a cross-platform and language-independent convention for representing and interacting with objects in HTML.  Browsers rely on a layout engine (Gecko/Firefox, Trident/IE, Presto/Opera, WebKit/Safari,Chrome and so on) to parse HTML into DOM.

The  DOM is a tree like representation of everything (all the objects) on your page (in the browser window, the document). Everything is between html tags so html is at the top, the stuff between head tags and body tags is sitting below that and so on.

[[--You will sometimes hear of the BOM or Browser Object Model which would also include methods of the window object, like window.open (popups), we won't be looking at those--]].

Because of this tree structure, we get a programmatic way of accessing any element (object) on the page. You can access the various element, attribute and text nodes as JavaScript objects (there are 12 node types in all, you will probably only use four, at least for the time being:- Element, Attr,Text and Document with nodeType 1,2,3 and 9).

This  allows you to read and alter the contents of nodes, as well as add new nodes to the tree or remove nodes from the tree. This is how a lot of fancy effects in Javascript are achieved.

[[--Diversion-- you may have heard of the Greasemonkey extension for Firefox; this extension won't do anything until you actually install a script, there are many here.  User scripts are written in javascript and manipulate the contents of a web page using the DOM, just like we are looking at this Week, the difference being that the user of a web page is authoring the changes rather than the developer. Maybe after you have completed the course, you might like to look into user scripts development or even Firefox extensions development, which is a fancier packaging of a user script--]]

All the elements in the sample picture can be accessed via the single Document object that represents the page. In fact, you can get around the DOM using the following members of the Node interface:-

childNodes, firstChild, lastChild ,nextSibling, previousSibling and parentNode

so document.body.childNodes; applied tor above example would have three children, h1,p and ul elements. 

The more usual and easier way is to give page elements an ID and access them by reference to that.:

var element = document.getElementById( elementId );

Let's give our above unordered list some id's:

    <ul>
      <li id="widget1">
      <li id="widget2">
      <li id="widget3">
    </ul>

and then we can, for example:

var widget2 = document.getElementById( "widget2" );

You can also get access to page elements with

var elements = document.getElementsByTagName(elementName)

which would give you access to an array of elements that have the specified name even if they have different IDs or...

New in Html5, getElementsByClassName...

allied with getAttribute and setAttribute....

http://www.quirksmode.org/dom/intro.html  has examples of how to get, change create and remove elements.

http://goo.gl/fnur     Basic Intro to the DOM


Firebug

Right, time to give Firebug a spin; remember the little alert program from back in Week 1? Well, change the "alert" bit to "console.log" so that it is console.log ("Hi, I'm a program"); in your html file and load it into the browser. Then open Firebug and click on Console/All and you should see the message "Hi, I'm a program" played back in there; this is a simpler way to put tests in your scripts than using alerts. More here: http://getfirebug.com/logging

Firebug helps us find DOM objects quickly and then edit them on the fly.  Firebug allows among other things :

  • Inspecting DOM
  • Filtering properties, functions, and constants
  • Modifying DOM on the fly
  • JavaScript code navigation

http://getfirebug.com/wiki/index.php/Firebug_Release_Notes

Go to http://www.w3.org/TR/html5/obsolete.html (this is a page of things that have been obsoleted or are on their way to being obsoleted by Html5) and open Firebug. Click on the Html tab and you will see the html/head/body tree there.

Close Firebug; it is quicker in Firefox to use the context menu, so scroll down a little to section titled
"11.1.1 Warnings for Obsolete but conforming features", right click on the title and select "Inspect element" in your context menu. Firebug should popopen automatically at the html panel with the relevant bit highlighted and showing the associated style in the right hand panel.

Now any changes you make in the panels are reflected "live" on the page (they will disappear when the page is reloaded). Click on the layout tab in the right panel, these aspects are also editable, try it.

You could write a whole book on using Firebug, it's such a good extension, it even has extensions for itself! Have fun.


 


Events

Well we have all these programming methods, how do we get them to do something on the page? Well, it's dynamic, user does something, page responds.

Responds to what? Events. There are also some events that aren’t directly caused by the user: the load event that fires when a page has been loaded, for instance.

Simplest example, familiar to everybody, a mouse click. You can also react to other mouseevents as in the following sample simple dropdown menu example (where for simplicity we have included the css and javascript between the head tags rather than as seperate files); copy paste it into a file and load it to see how it works, then read through the code and interpret it according to what you see, the interplay between the html and the functions as well as use of the DOM.

(Note that the Ul could easily be expanded to include further menus without having to change the style sheet.)

<!DOCTYPE html>
<html>
<head>
<title>Drop-Down Menu</title>

<style type ="text/css">
#sddm
{    margin: 0;
    padding: 0;
    z-index: 30}

#sddm li
{    margin: 0;
    padding: 0;
    list-style: none;
    float: left;
    font: bold 11px arial}

#sddm li a
{    display: block;
    margin: 0 1px 0 0;
    padding: 4px 10px;
    width: 60px;
    background: #5970B2;
    color: #FFF;
    text-align: center;
    text-decoration: none}

#sddm li a:hover
{    background: #49A3FF}

#sddm div
{    position: absolute;
    visibility: hidden;
    margin: 0;
    padding: 0;
    background: #EAEBD8;
    border: 1px solid #5970B2}

    #sddm div a
    {    position: relative;
        display: block;
        margin: 0;
        padding: 5px 10px;
        width: auto;
        white-space: nowrap;
        text-align: left;
        text-decoration: none;
        background: #EAEBD8;
        color: #2875DE;
        font: 11px arial}

    #sddm div a:hover
    {    background: #49A3FF;
        color: #FFF}
</style>

<!-- dd menu -->
<script type="text/javascript">
<!--
var timeout         = 500;
var closetimer        = 0;
var ddmenuitem      = 0;

// open hidden layer
function mopen(id)
{   
    // cancel close timer
    mcancelclosetime();

    // close old layer
    if(ddmenuitem) ddmenuitem.style.visibility = 'hidden';

    // get new layer and show it
    ddmenuitem = document.getElementById(id);
    ddmenuitem.style.visibility = 'visible';

}
// close showed layer
function mclose()
{
    if(ddmenuitem) ddmenuitem.style.visibility = 'hidden';
}

// go close timer
function mclosetime()
{
    closetimer = window.setTimeout(mclose, timeout);
}

// cancel close timer
function mcancelclosetime()
{
    if(closetimer)
    {
        window.clearTimeout(closetimer);
        closetimer = null;
    }
}

// close layer when click-out
document.onclick = mclose;
// -->
</script>

</head>

<body>

<h1>DropDown Menu</h1>

<p>This menu can be located anywhere on a page:</p>

<ul id="sddm">
    <li><a href="#" _cke_saved_href="#" onmouseover="mopen('m1')" onmouseout="mclosetime()">Home</a>
        <div id="m1" onmouseover="mcancelclosetime()" onmouseout="mclosetime()">
        <a href="#">HTML DropDown</a>
        <a href="#">DHTML DropDown menu</a>
        <a href="#">JavaScript DropDown</a>
        <a href="#">DropDown Menu</a>
        <a href="#">CSS DropDown</a>
        </div>
    </li>
</ul>

</body>
</html>

As alluded to previously, this code is not really the best way to do things, if you would like to look at a more polished version of drop down code, take a  look at http://www.scriptiny.com/2008/11/drop-down-menu/

Also, at http://www.quirksmode.org/book/examplescripts.html there is a set of example scripts used for the well known book, "ppk on Javascript"; all of these are worth examining.

Watch this video http://blip.tv/file/get/NETTUTS-JavaScriptFromNullChapter5Events852.mp4

Assignment



  1. What are the roles of 'name', 'id' and 'class' attributes in HTML tags? What is an appropriate use of these?
  2. Which pointers does each node in the DOM tree typically have?
  3. Given a node object from a DOM tree, how do we determine if it is a text node or a regular node?
  4. Download the source for the web page 'http://www.useit.com/about/nographics.html'. In the source page itself, write a Javascript function which counts the number of text nodes in the document and shows the count in an alert dialogue. You can choose how you want to trigger the function (through a button click, link click, or any other event).
  5. Change the example above, so that instead of displaying the count in an alert dialogue, it is displayed in a span tag in the HTML page itself.
  6. Add a link besides the button, such that when the link is click, it changes the style on the span tag to make it's contents bold.
  7. Post a link to your assignment and working code.


Task Discussion