DHTML: Difference between revisions

The educational technology and digital learning wiki
Jump to navigation Jump to search
 
(20 intermediate revisions by 2 users not shown)
Line 1: Line 1:
{{Incomplete}}
{{Incomplete}}
{{web technology tutorial|intermediate}}
{{web technology tutorial|intermediate}}
<pageby nominor="false" comments="false"/>
<!-- <pageby nominor="false" comments="false"/> -->


== Introduction to Dynamic HTML ==
== Introduction to Dynamic HTML ==
Line 24: Line 24:
; Disclaimer
; Disclaimer


* '''Contents were developed in 2009 for XHTML 1.0 / HTML4 and should be expanded/changed for HTML5'''
* There may be typos (sorry) and mistakes (sorry again)
* There may be typos (sorry) and mistakes (sorry again)
* Please also consult a recent manual or a textbook !
* Please also consult a recent manual or a textbook !
Line 48: Line 49:


Below, we recall the architecture of an example modern HTML/Javascript page:
Below, we recall the architecture of an example modern HTML/Javascript page:
* [http://tecfa.unige.ch/guides/js/ex/coap/week-1-2/1-6-dom-change-modern.html Simple JavaScript program]


(1) Part 1 - start
(1) Part 1 - start
Line 199: Line 202:
Most navigators have some built-in DOM tools. For some, extensions must be installed.
Most navigators have some built-in DOM tools. For some, extensions must be installed.


Examples of spring 2011 browsers.
Examples of spring 2011 to sprint 2013 browsers.


* IE 9: Hit F12. This will display the developer tools. You then can see the HTML structure (i.e. part of the DOM)
* IE 9 and later: Hit F12. This will display the developer tools. You then can see the HTML structure (i.e. part of the DOM)
* Chrome 11: Hit CTRL-SHIFT-i. This will get you a similar tool as in IE. However, in addition, in the right-hand panel you can inspect all DOM properties for a given element selected in the HTML tree to the left.
* Chrome 11: Hit CTRL-SHIFT-i. This will get you a similar tool as in IE. However, in addition, in the right-hand panel you can inspect all DOM properties for a given element selected in the HTML tree to the left.
* Firefox 4: You should install [https://addons.mozilla.org/en-US/firefox/addon/dom-inspector-6622/ DOM Inspector]. In addition you also might install [https://addons.mozilla.org/en-US/firefox/addon/web-developer/ Web Developer], since it can interact with DOM inspector.
* Firefox 4 and later: In order to get IE/Chrome like functionality, you should install [https://addons.mozilla.org/en-US/firefox/addon/dom-inspector-6622/ DOM Inspector]. In addition you also might install [https://addons.mozilla.org/en-US/firefox/addon/web-developer/ Web Developer], since it can interact with DOM inspector. You then see the HTML DOM tree. With little pull-down menu on top you also can have the "real" DOM Tree plus some other views.
* Firefox 4 and later: [http://www.getfirebug.com/ Firebug] is an alternative. It it includes similar features plus more that are of interest to JavaScript programmers.


== Referencing and changing objects ==
== Referencing and changing objects ==
Line 225: Line 229:
<table class="wikitable"> <tr> <td><code>document</code></td> <td>When a member returns an object of type <code>document</code> (e.g., the <strong><code>ownerDocument</code></strong> property of an element returns the <code>document</code> to which it belongs), this object is the root <code>document</code> object itself. The DOM <code>document</code> [https://developer.mozilla.org/en/DOM/document Reference chapter] describes the <code>document</code> object.</td> </tr> <tr> <td><code>element</code></td> <td><code>element</code> refers to an element or a node of type <code>element</code> returned by a member of the DOM API. Rather than saying, for example, that the <code>document.createElement()</code> method returns an object reference to a <code>node</code>, we just say that this method returns the <code>element</code> that has just been created in the DOM. <code>element</code> objects implement the DOM <code>Element</code> interface and also the more basic <code>Node</code> interface, both of which are included together in this reference.</td> </tr> <tr> <td><code>nodeList</code></td> <td>A <code>nodeList</code> is an array of elements, like the kind that is returned by the method <code>document.getElementsByTagName()</code>. Items in a <code>nodeList</code> are accessed by index in either of two ways: <ul> <li>list.item(1)</li> <li>list[1]</li> </ul> These two are equivalent. In the first, <strong><code>item()</code></strong> is the single method on the <code>nodeList</code> object. The latter uses the typical array syntax to fetch the second item in the list.</td> </tr> <tr> <td><code>attribute</code></td> <td>When an <code>attribute</code> is returned by a member (e.g., by the <strong><code>createAttribute()</code></strong> method), it is an object reference that exposes a special (albeit small) interface for attributes. Attributes are nodes in the DOM just like elements are, though you may rarely use them as such.</td> </tr> <tr> <td><code>namedNodeMap</code></td> <td>A <code>namedNodeMap</code> is like an array, but the items are accessed by name or index, though this latter case is merely a convenience for enumeration, as they are in no particular order in the list. A <code>namedNodeMap</code> has an item() method for this purpose, and you can also add and remove items from a <code>namedNodeMap</code>.</td> </tr> </table>
<table class="wikitable"> <tr> <td><code>document</code></td> <td>When a member returns an object of type <code>document</code> (e.g., the <strong><code>ownerDocument</code></strong> property of an element returns the <code>document</code> to which it belongs), this object is the root <code>document</code> object itself. The DOM <code>document</code> [https://developer.mozilla.org/en/DOM/document Reference chapter] describes the <code>document</code> object.</td> </tr> <tr> <td><code>element</code></td> <td><code>element</code> refers to an element or a node of type <code>element</code> returned by a member of the DOM API. Rather than saying, for example, that the <code>document.createElement()</code> method returns an object reference to a <code>node</code>, we just say that this method returns the <code>element</code> that has just been created in the DOM. <code>element</code> objects implement the DOM <code>Element</code> interface and also the more basic <code>Node</code> interface, both of which are included together in this reference.</td> </tr> <tr> <td><code>nodeList</code></td> <td>A <code>nodeList</code> is an array of elements, like the kind that is returned by the method <code>document.getElementsByTagName()</code>. Items in a <code>nodeList</code> are accessed by index in either of two ways: <ul> <li>list.item(1)</li> <li>list[1]</li> </ul> These two are equivalent. In the first, <strong><code>item()</code></strong> is the single method on the <code>nodeList</code> object. The latter uses the typical array syntax to fetch the second item in the list.</td> </tr> <tr> <td><code>attribute</code></td> <td>When an <code>attribute</code> is returned by a member (e.g., by the <strong><code>createAttribute()</code></strong> method), it is an object reference that exposes a special (albeit small) interface for attributes. Attributes are nodes in the DOM just like elements are, though you may rarely use them as such.</td> </tr> <tr> <td><code>namedNodeMap</code></td> <td>A <code>namedNodeMap</code> is like an array, but the items are accessed by name or index, though this latter case is merely a convenience for enumeration, as they are in no particular order in the list. A <code>namedNodeMap</code> has an item() method for this purpose, and you can also add and remove items from a <code>namedNodeMap</code>.</td> </tr> </table>


Now programmers could write ''tree-walking'' or ''tree extraction code'' to extract any sort of item (e.g. elements or attribute values) from the DOM tree. However, to make things easier, the DOM Level 1 HTML specification and various DOM level 2 specifications define a '''huge''' number of APIs to make this taks much easier. Again, according to [https://developer.mozilla.org/en/Gecko_DOM_Reference/Introduction#What_is_the_DOM.3F Introduction to the Gecko DOM Reference], one can identify a list the most commonly used interfaces of the DOM. As we explained above, Document and window objects are the objects whose interfaces you generally use most often in DOM programming. {{quotation|The window object represents something like the browser, and the document object is the root of the document itself. Element inherits from the generic Node interface, and together these two interfaces provide many of the methods and properties you use on individual elements. These elements may also have specific interfaces for dealing with the kind of data those elements hold, as in the table object example in the previous section.}}
Now, programmers could write so-called ''tree-walking'' or ''tree extraction code'' to extract any sort of item (e.g. elements or attribute values) from the DOM tree. However, to make things easier, the DOM Level 1 HTML specification and various DOM level 2 specifications define a '''huge''' number of APIs to make this taks much easier.


The following is a brief list of common APIs in web and XML page scripting using the DOM. Links point to the [https://developer.mozilla.org/en/Gecko_DOM_Reference Gecko DOM Reference] (Mozilla browsers) but this documentation ought to be useful for any kind of modern browser.
According to [https://developer.mozilla.org/en/Gecko_DOM_Reference/Introduction#What_is_the_DOM.3F Introduction to the Gecko DOM Reference], one can identify a list of the most commonly used interfaces of the DOM. As we explained above, ''document'' and ''window'' objects whose interfaces you one uses most often in DOM programming. {{quotation|The window object represents something like the browser, and the document object is the root of the document itself. Element inherits from the generic Node interface, and together these two interfaces provide many of the methods and properties you use on individual elements. These elements may also have specific interfaces for dealing with the kind of data those elements hold, as in the table object example in the previous section.}}
 
The following list includes common APIs (methods and properties) in web and XML page scripting using the DOM. Links point to the [https://developer.mozilla.org/en/Gecko_DOM_Reference Gecko DOM Reference] (Mozilla browsers) but this documentation ought to be useful for any kind of modern browser.


* <code> [https://developer.mozilla.org/en/DOM/document.getElementById document.getElementById](id)</code>  
* <code> [https://developer.mozilla.org/en/DOM/document.getElementById document.getElementById](id)</code>  
Line 238: Line 244:
* <code>element.[https://developer.mozilla.org/en/DOM/element.getAttribute getAttribute] </code>  
* <code>element.[https://developer.mozilla.org/en/DOM/element.getAttribute getAttribute] </code>  
* <code>element.[https://developer.mozilla.org/en/DOM/element.addEventListener addEventListener] </code>  
* <code>element.[https://developer.mozilla.org/en/DOM/element.addEventListener addEventListener] </code>  
* <code>element.createDocument </code>
* <code>[https://developer.mozilla.org/en/DOM/window.content window.content] </code>  
* <code>[https://developer.mozilla.org/en/DOM/window.content window.content] </code>  
* <code>[https://developer.mozilla.org/en/DOM/window.onload window.onload] </code>  
* <code>[https://developer.mozilla.org/en/DOM/window.onload window.onload] </code>  
Line 245: Line 252:
=== A simple introductory DOM example ===
=== A simple introductory DOM example ===


A simple DHTML page can by made by executing some JavaScript page after the page has loaded. Let's define the procedure step-by-step:
A simple DHTML page can be made by executing some JavaScript code after the page has loaded. Let's define the procedure step-by-step:


(1) Add ''id="....."'' attributes to your HTML elements you later want to use. E.g. to change a <code>p</code> element, use <code>&lt;p id="my_para"&gt;</code>
(1) Add ''id="....."'' attributes to your HTML elements you later want to use. E.g. to change a <code>p</code> element, use <code>&lt;p id="my_para"&gt;</code>
Line 258: Line 265:
:Means: tell the onload property of the window the name of the function it has to call once the page is loaded.
:Means: tell the onload property of the window the name of the function it has to call once the page is loaded.


(3) Retrieve a "handle" on an HTML element, then write a little function that does some modification.
(3) Retrieve a "handle" on an HTML element
* Use the '' document.getElementById("your_id")'' method to refer to an object
* Use the '' document.getElementById("your_id")'' method to refer to an object
* use the '' innerHTML'' method to change contents of an objects
* use the '' innerHTML'' method to change contents of an objects
Line 265: Line 272:
means: find the HTML with id=p1 in the page and put this object in the my_para variable
means: find the HTML with id=p1 in the page and put this object in the my_para variable


(4) Write a little function that does some modification.
  alert( "Paragraph contents : " + my_para.innerHTML);
  alert( "Paragraph contents : " + my_para.innerHTML);
means: ''create a little popup window that will display the "inside" of the referenced HTML element''.
means: ''create a little popup window that will display the "inside" of the referenced HTML element''.


=== Example: Simple object referencing ===
=== Example: Simple object referencing ===
DOM is the computer representation of an HTML page. In this example, Javascript is separated by <script> .... </ script>.


<source lang="xml">
<source lang="xml">
Line 305: Line 315:
Note: The "+" operation will just append the contents of the p to "Paragraph contents". It's called string concatenation.
Note: The "+" operation will just append the contents of the p to "Paragraph contents". It's called string concatenation.


Of course, this is a fairly useless thing to do. Let's now see how we can change a content. This is more interesting since it gives you an idea of how dangerous so-called http://en.wikipedia.org/wiki/Cross-site_scripting [cross-site XSS scripting] can be. E.g. you insert some external JavaScript widget which you don't understand in your page and it will change stuff in '''your page''', like sending account information to some other web site.
Of course, this is a fairly useless thing to do. Let's now see how we can change a content. This is more interesting since it gives you an idea of how dangerous so-called [http://en.wikipedia.org/wiki/Cross-site_scripting cross-site XSS scripting] can be. E.g. you insert some external JavaScript widget which you don't understand in your page and it will change stuff in '''your page''', like prompting and sending account information to some other web site.


=== Example: Simple object referencing and change ===
=== Example: Simple object referencing and change ===
Line 470: Line 480:


<source lang="xml">
<source lang="xml">
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<!DOCTYPE html>
<html>
<html>
   <head>
   <head>
     <title>Manipulating Styles</title>
     <title>Manipulating Styles</title>
 
   
     <script type="text/javascript">
     <script type="text/javascript">
       var flag = 1;
       window.onload = function () {
        document.getElementById("but").onclick=changeText;
      }


       function changeText() {
       function changeText() {
       var p = document.getElementById("pid");
       var p = document.getElementById("pid");
       if (flag==1) {
       if (p.style.color == "red") {
         p.style.color = "blue";
         p.style.color = "blue";
         p.style.fontSize = "16pt";
         p.style.fontSize = "16pt";
         flag=2;
         flag=2;
         }
         }
       else if (flag==2) {
       else {
         p.style.color = "red";
         p.style.color = "red";
         p.style.fontSize = "16pt";
         p.style.fontSize = "16pt";
Line 498: Line 510:
     <h1>Manipulating Styles</h1>
     <h1>Manipulating Styles</h1>
     <ul>
     <ul>
       <li>Inspired from <a href="http://developer.mozilla.org/en/docs/Gecko_DOM_Reference:Examples">
       <li>Inspired from <a href="http://developer.mozilla.org/en/docs/Gecko_DOM_Reference:Examples">http://developer.mozilla.org/en/docs/Gecko_DOM_Reference:Examples</a></li>
      http://developer.mozilla.org/en/docs/Gecko_DOM_Reference:Examples</a></li>
   </ul>
   </ul>
     <p id="pid"  
     <p id="pid"  
       onclick="window.location.href = 'http://www.cnn.com/';">News Link</p>
       onclick="window.location.href = 'http://www.cnn.com/';">News Link</p>
     <form>
     <form>
       <p><input value="Change style" type="button" onclick="changeText();"></p>
       <p><input value="Change style" type="button" id="but"></p>
     </form>
     </form>


     <hr>
     <hr>
  <!-- Created: Mon Jan 23 18:03:44 CET 2006 -->
  <!-- Created: Mon Jan 23 18:03:44 CET 2006, changed Dec 2014 -->
  </body>
  </body>
</html>
</html>
</source>
</source>
File: [http://tecfa.unige.ch/guides/js/ex/dhtml/change-style-2.html change-style-2.html]
* File: [http://tecfa.unige.ch/guides/js/ex/dhtml/change-style-3.html change-style-3.html] (HTML 5)
* File: [http://tecfa.unige.ch/guides/js/ex/dhtml/change-style-2.html change-style-2.html] (HTML 4, more verbose selection code)


== HTML Window and Navigator ==
== HTML Window and Navigator ==
Line 781: Line 794:
(2) Then, decide which elements in your HTML text you wish to highlight and add a class attribute to each of these, e.g. something like:
(2) Then, decide which elements in your HTML text you wish to highlight and add a class attribute to each of these, e.g. something like:


  &lt;p''class="important"''&gt;
  &lt;p'' class="important"''&gt;


(3) Change the class attribute value from "important" to whatever you wish, but don't forget to change the argument when calling the do_document function, e.g. if the CSS class you wish to highlight is "''cool''", change to:
(3) Change the class attribute value from "important" to whatever you wish, but don't forget to change the argument when calling the do_document function, e.g. if the CSS class you wish to highlight is "''cool''", change to:
Line 1,188: Line 1,201:
A slighly more complex version is:
A slighly more complex version is:
:File [http://tecfa.unige.ch/guides/js/ex/dhtml/dynamicposition2.html dynamicposition2.html] (it has a start/stop button, but the code should be ''improved'')
:File [http://tecfa.unige.ch/guides/js/ex/dhtml/dynamicposition2.html dynamicposition2.html] (it has a start/stop button, but the code should be ''improved'')
== Event handlers ==
This section needs be elaborated. In the meantime, see the Wikipedia [http://en.wikipedia.org/wiki/DOM_events DOM events articles] for more details about DOM level 2 events or the Gecko documentation, in particular the definitions for [https://developer.mozilla.org/en/DOM/element element] and [https://developer.mozilla.org/en/DOM/event event]
When two or more nested elements define an event handler for the same type of event, then there must be some rules to decide which event will be handled.
=== A simple example ===
Example: [http://tecfa.unige.ch/guides/js/ex/dhtml/examine-events-en.html examine-events-en.html]
<source lang="xml">
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>Gecko DOM addEventListener example</title>
    <style>
    #table2 { border: 1px solid blue; padding: 10px}
    td { border: 1px solid red }
    </style>
  <script>
      window.onload = load;
      var x_td;
      var y_td;
      // Event registration
      function touche (event) {
        x = event.pageX;
        y = event.pageY;
        obj = event.target;
        // alert ("positions x=" + x + ",y=" + y + "\n object= " + obj);
        x_td.innerHTML = x;
        y_td.innerHTML = y;
        obj_td.innerHTML = obj.innerHTML;
      }
      function load() {
        var el2 = document.getElementById("table2");
        if (el2.addEventListener) el2.addEventListener("mouseover", touche, false)
        // for those who can't use a real browser
            else alert ("Sorry you need a browser that understands DOM Level 2 Events");
        x_td = document.getElementById("x");
        y_td = document.getElementById("y");
        obj_td = document.getElementById("obj");
      }
  </script>
</head>
<body>
    <h1>Gecko DOM addEventListener example</h1>
This is an EventHandler demo that will deal with a mouseover event
<p>
Ceci est une démo d'un EventHandler pour l'événement mouseover, enregistré pour la table.
<p>
Move your mouse over the table please / Bougez la souris sur le tableau SVP:
    <table align="center" id="table2">
<tr><td>Ma tete</td></tr>
<tr><td>Ma poitrine</td></tr>
<tr><td>Mon ventre</td></tr>
<tr><td>Mes jambes</td></tr>
    </table>
   
<p>
J'été touché aux coordonnées / I was touched at coordinates:
    <table align="center" id="coordinates">
<tr><td>X = </td>  <td id="x"> </td></tr>
<tr><td>Y = </td>  <td id="y"> </td></tr>
<tr><td>Objet = </td>  <td id="obj"> </td></tr>
    </table>
    <hr>
    Testé avec Mozilla et Firefox (marche) et avec IE 6 (ne marche pas, car ne semble pas avoir implémenté addEventListener).
<p>
    Source: <a href="http://developer.mozilla.org/fr/docs/DOM:element.addEventListener">http://developer.mozilla.org/fr/docs/DOM:element.addEventListener</a>
  </body>
</html>
</source>
The crucial code is the following. It will define an event handler for a mouseover with the table (id="table2"). The function is mouseover is called whenever a user mouses over the table.
<source lang="javascript">
var el2 = document.getElementById("table2");
el2.addEventListener("mouseover", touche, false)
</source>


== Exercise ==
== Exercise ==
Line 1,213: Line 1,320:
* http://www.w3.org/TR/DOM-Level-2-Events/
* http://www.w3.org/TR/DOM-Level-2-Events/
* http://www.w3.org/TR/DOM-Level-2-Style/
* http://www.w3.org/TR/DOM-Level-2-Style/
; Tutorials
* [http://icant.co.uk/articles/from-dhtml-to-dom/from-dhtml-to-dom-scripting.html From DHTML to DOM scripting] by Christian Heilmann March 2006, [http://icant.co.uk/articles/from-dhtml-to-dom/FromDHTMLtoDOMscripting_March2006.pdf PDF version (202KB)]


== Acknowledgements and copyright modification ==
== Acknowledgements and copyright modification ==
Line 1,221: Line 1,331:
[[Category: Web authoring]]
[[Category: Web authoring]]
[[Category: JavaScript]]
[[Category: JavaScript]]
[[Category: CSS]]

Latest revision as of 21:30, 27 March 2018

Introduction to Dynamic HTML

Prerequisites

Objectives
  • Understand the principles of modern Dynamic HTML (DOM/CSS/JavaScript)
  • Reuse of some simple JavaScript functions
  • Understand basic Object Referencing and modification of contents
  • Be able to use Dynamic Font Styles
  • Be able to change Positioning
  • The concept of "tree walking"
Disclaimer
  • Contents were developed in 2009 for XHTML 1.0 / HTML4 and should be expanded/changed for HTML5
  • There may be typos (sorry) and mistakes (sorry again)
  • Please also consult a recent manual or a textbook !

HTML, XHTML, CSS and JavaScript

"DHTML" stands for "Dynamic HTML" and means that we use four different technologies together to create dynamic HTML pages:

  1. HTML or XHTML
  2. CSS, the Cascading Style Sheet language
  3. JavaScript, i.e. the ECMA-script programming language
  4. DOM JavaScript bindings. DOM means "Document Object Model" and refers to the data representation of a web content and all the methods that are defined to retrieve and modify elements of that content. DOM works with all XHTML versions and all more recent HTML versions (> 4).

Dynamic HTML (DHTML) does not exist as a standard. DHTML simply refers to the fact that we use these four techniques to create interactive and dynamic contents. The difficult part is understanding DOM and JavaScript programming ...

Let's first recall a few JavaScript principles from the Javascript tutorial - basics

  • JavaScript is a programming language that runs inside your navigator
  • JavaScript functions are usually defined in the head
    • Code is defined within the " script" tag.
    • The head may also include event handling code that assigns functions to event handling properties.
  • JavaScript functions can be called in various ways from the body of the document, but modern programming technique discourages this practice.
    • JavaScript instructions can be inserted within "' script " tags (as in the head)
    • JavaScript also can be found within "inline" event handler definitions

Below, we recall the architecture of an example modern HTML/Javascript page:

(1) Part 1 - start

<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
"http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 <html xmlns = "http://www.w3.org/1999/xhtml">

(2) Part 2 - head - includes all the JavaScript code

    <head>
       <title>Object Model</title>
       <script type = "text/javascript">
          window.onload = start;

          function start(){
             var p = document.getElementById("pText");
             alert( "Page contents : " + p.innerHTML );
             p.innerHTML = "Thanks for coming.";
             alert( "Page contents changed to : " + p.innerHTML );
             p.innerHTML = "Cool, isn't it ?";
          }
       </script>
    </head>

(2) Part 3 - the body - includes the web page contents

    <body>
       <p id = "pText">Welcome to our Web page!</p>
    </body>

(4) Part 4 - the end

 </html>
Note on standardization

The JavaScript language itself is fairly cross-browser compatible

  • However, event handling and DOM is not fully standard (e.g. the older Microsoft DHTML is not a standard and even IE 7 is still quite far from implementing the DOM level 2.)
  • Inline event management however is fairly cross-browser compatible, i.e. some of the old and never standardized stuff does work
  • More advanced old stuff is less compatiable.
Note on JavaScript and XHTML

Valid XHTML requires JavaScript to be inserted within a commented CDATA section

<script language="javascript">
// <![CDATA[
   alert ("hello I am alerting you from a valid XHTML Page");
// ]]>
</script>

An other, better solution is to put the javascript code into an external file. E.g.

<script type="text/javascript" src="external.js" >
</script>

Introduction to DOM

DHTML and DOM - some definitions

DOM = Document Object Model

A document object model (DOM) is an application programming interface (API) for representing a document (such as an HTML document) and accessing and manipulating the various elements (such as HTML tags and strings of text) that make up that document.

  • DOM allows Web authors to control and dynamically modify the presentation of their pages
  • DOM gives them access to all the elements on their pages
    • e.g. Headers, paragraphs, forms, styles
  • All information is represented in an object hierarchy and from which scripts can retrieve and modify properties and attributes
  • Non standard DOM extensions provide information about navigator and windows ...

History of DOM and DOM levels

Only recently, DHTML became standardized as essential through the DOM Javascript binding, i.e. JavaScript libraries that can deal with the DOM data structre. Before (in the 1990'), DHTML was a nightmare for web developers, i.e. there was total incompatibility between various browser brands and lesser incompatibilities between OS and navigator versions.

DOM is defined by levels and there exist several specifications per level.

Level 0

  • Non-standardized things, like Microsoft DHTML or Netscape DOM 4.x, etc.
  • Methods that concern window and navigator are still being used and implemented in most browsers. These are not standardized, but can be considered "industry standard", i.e. implemented by all browsers.

Level 1 (octobre 1998)

  • DOM Level 1 Core: defines how HTML and XML are represented in the machine and can be navigated
  • DOM Level 1 HTML: HTML-specific extensions

Level 2 (2001)

  • 6 specifications, adding XML namespace support, filtered views and events.
  • DOM Level 2 Core Specification (extension of DOM Level 1 Core)
  • DOM Level 2 Views Specification
  • DOM Level 2 Events Specification: standardizes management of user generated events
  • DOM Level 2 Style Specification: CSS
  • DOM Level 2 Traversal and Range Specification
  • DOM Level 2 HTML Specification: extensions for HTML

Level 3: contains 6 specifications

  • DOM Level 3 Core
  • DOM Level 3 Load and Save
  • DOM Level 3 XPath
  • DOM Level 3 Views and Formatting
  • DOM Level 3 Requirements
  • DOM Level 3 Validation

Other W3C languages that define DOM extensions

Non W3C languages also may support DOM

Implementations

  • Most modern browsers (2005 ) implement most of DOM level 1 specs.
  • Most modern browsers implement at least some of DOM level 2.
  • Some proprietary DOM 0 still is needed (e.g. navigator information). These are usually cross-browser compatible.
  • Other "old style" DHTML should be avoided if possible (e.g. "innnerHTML")
  • Other "old style" DHTML should be avoided in every case (e.g. the MS DHTML model).
Navigator comparison tables
Executive summary regarding DOM/DHTML variants
  • Plan for the future (use standards whenever possible)
  • Make sure to test your code with browsers your target population will use

DOM objects Overview

There are a few system variables that point to objects which allow you to access the current document, the current window and the navigator. The most important ones are:

  • document : to access and manipulate contents of a page
  • window : to access information about the window and to create new windows
  • navigator : to access information about the navigator (browser).

Dyn-html-5.png

Tools for DOM inspection

Most navigators have some built-in DOM tools. For some, extensions must be installed.

Examples of spring 2011 to sprint 2013 browsers.

  • IE 9 and later: Hit F12. This will display the developer tools. You then can see the HTML structure (i.e. part of the DOM)
  • Chrome 11: Hit CTRL-SHIFT-i. This will get you a similar tool as in IE. However, in addition, in the right-hand panel you can inspect all DOM properties for a given element selected in the HTML tree to the left.
  • Firefox 4 and later: In order to get IE/Chrome like functionality, you should install DOM Inspector. In addition you also might install Web Developer, since it can interact with DOM inspector. You then see the HTML DOM tree. With little pull-down menu on top you also can have the "real" DOM Tree plus some other views.
  • Firefox 4 and later: Firebug is an alternative. It it includes similar features plus more that are of interest to JavaScript programmers.

Referencing and changing objects

In order to do some DHTML your script must be able to refer to HTML elements and then change something. So you need to know 4 things:

  • how to refer to a specific object within a page (also called "document")
  • how to change the contents of an HTML element
  • how to define a JavaScript (JS) function that will do this.
  • how to launch (call) this JS function

How do we access the DOM from JavaScript

From JavaScript code you may use the API for the document or the non-standardized window object to access and manipulate the DOM.

Here is a simple example of the window API that you are already familiar with. The short-hand method for creating a little popup window is alert("HELLO ....");. In fact, "alert" is method of the window object and rather should be written:

window.alert("Hello, better solution !");

DOM Level 1 defines some basic data types that are available in any DOM, e.g. XML, HTML, and various XML languages like XHTML, SVG, etc. According to the Introduction to the Gecko DOM Reference, its most important data types can be described by the following table.

document When a member returns an object of type document (e.g., the ownerDocument property of an element returns the document to which it belongs), this object is the root document object itself. The DOM document Reference chapter describes the document object.
element element refers to an element or a node of type element returned by a member of the DOM API. Rather than saying, for example, that the document.createElement() method returns an object reference to a node, we just say that this method returns the element that has just been created in the DOM. element objects implement the DOM Element interface and also the more basic Node interface, both of which are included together in this reference.
nodeList A nodeList is an array of elements, like the kind that is returned by the method document.getElementsByTagName(). Items in a nodeList are accessed by index in either of two ways:
  • list.item(1)
  • list[1]
These two are equivalent. In the first, item() is the single method on the nodeList object. The latter uses the typical array syntax to fetch the second item in the list.
attribute When an attribute is returned by a member (e.g., by the createAttribute() method), it is an object reference that exposes a special (albeit small) interface for attributes. Attributes are nodes in the DOM just like elements are, though you may rarely use them as such.
namedNodeMap A namedNodeMap is like an array, but the items are accessed by name or index, though this latter case is merely a convenience for enumeration, as they are in no particular order in the list. A namedNodeMap has an item() method for this purpose, and you can also add and remove items from a namedNodeMap.

Now, programmers could write so-called tree-walking or tree extraction code to extract any sort of item (e.g. elements or attribute values) from the DOM tree. However, to make things easier, the DOM Level 1 HTML specification and various DOM level 2 specifications define a huge number of APIs to make this taks much easier.

According to Introduction to the Gecko DOM Reference, one can identify a list of the most commonly used interfaces of the DOM. As we explained above, document and window objects whose interfaces you one uses most often in DOM programming. “The window object represents something like the browser, and the document object is the root of the document itself. Element inherits from the generic Node interface, and together these two interfaces provide many of the methods and properties you use on individual elements. These elements may also have specific interfaces for dealing with the kind of data those elements hold, as in the table object example in the previous section.”

The following list includes common APIs (methods and properties) in web and XML page scripting using the DOM. Links point to the Gecko DOM Reference (Mozilla browsers) but this documentation ought to be useful for any kind of modern browser.

A simple introductory DOM example

A simple DHTML page can be made by executing some JavaScript code after the page has loaded. Let's define the procedure step-by-step:

(1) Add id="....." attributes to your HTML elements you later want to use. E.g. to change a p element, use <p id="my_para">

(2) Create code to trigger a JavaScript function just after the page is loaded.

  • Old Style: call the JavaScript function when the page will load
 <body onload = "start() ">
Means: when the page loads into the browser, launch the start() function
  • New Style: Give JavaScript a function name. This function will be called by JS when the page will load. Insert the following line in the JavaScript code (not in the HTML)
window.onload = start;
Means: tell the onload property of the window the name of the function it has to call once the page is loaded.

(3) Retrieve a "handle" on an HTML element

  • Use the document.getElementById("your_id") method to refer to an object
  • use the innerHTML method to change contents of an objects
var my_para = document.getElementById("p1");

means: find the HTML with id=p1 in the page and put this object in the my_para variable

(4) Write a little function that does some modification.

alert( "Paragraph contents : " + my_para.innerHTML);

means: create a little popup window that will display the "inside" of the referenced HTML element.

Example: Simple object referencing

DOM is the computer representation of an HTML page. In this example, Javascript is separated by <script> .... </ script>.

<?xml version = "1.0"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

<html xmlns = "http://www.w3.org/1999/xhtml">
   <head>
      <title>Object Model</title>
      <script type = "text/javascript">
         window.onload = start;
         function start() 
         {
            var my_para = document.getElementById("p1");
            alert( "Paragraph contents : " + my_para.innerHTML );
         }
      </script>
   </head>

   <body>
      <p id = "p1">Welcome to our Web page!</p>
   </body>
</html>

File: 1-6-dom-reference-modern.html

The start function will retrieve a handle to the p element that has identifier = p1.

document.getElementById("p1");

This handle is put into the my_para variable

var my_para = document.getElementById("p1");

You now can retrieve the contents of the p

my_para.innerHTML

And finally you can display it in popup.

alert( "Paragraph contents : " + my_para.innerHTML );

Note: The "+" operation will just append the contents of the p to "Paragraph contents". It's called string concatenation.

Of course, this is a fairly useless thing to do. Let's now see how we can change a content. This is more interesting since it gives you an idea of how dangerous so-called cross-site XSS scripting can be. E.g. you insert some external JavaScript widget which you don't understand in your page and it will change stuff in your page, like prompting and sending account information to some other web site.

Example: Simple object referencing and change

  • This example shows how to change the contents of an HTML element
  • Once we have a reference to the HTML element ("para") in this case we can change it
 <html xmlns = "http://www.w3.org/1999/xhtml">
    <head>
       <title>Object Model</title>
       <script type = "text/javascript">
          window.onload = start;

          function start(){
             var p = document.getElementById("pText");
             alert( "Page contents : " + p.innerHTML );
             p.innerHTML = "Do you really think we care that you came ?";
             alert( "Page contents changed to : " + p.innerHTML );
             p.innerHTML = "Cool, isn't it ?";
          }
       </script>
    </head>

    <body>
       <p id = "pText">Welcome to our Web page!</p>
    </body>

File: 1-6-dom-change-modern.html

See the Javascript tutorial - basics for an old style DOM version of this code.

Style

DHTML is often about about changing CSS properties. In order to do so, you must know that CSS properties in the DOM have slightly different names, because the "-" inside the CSS property names is not compatible with a programming language where "-" means substraction.

Therefore, warning (!!!): "CSS inside the DOM" has slightly different names than CSS properties. For a list see e.g.

Most of the time it's easy to guess the DOM name of a CSS property

  1. remove the "-"
  2. capitalize words (except the first one)

Example: CSS property "background-color" becomes DOM/CSS "backgroundColor".

Some examples:

DOM CSS

CSS property

background

background

backgroundColor

background-color

borderColor

border-color

fontFamily

font-family

fontSize

font-size

marginBottom

margin-bottom

marginLeft

margin-left

In order to change a style property of an element, use the syntax:

object.style.xxx = "yyy";

e.g.

para.style.fontFamily="Helvetica"

object here refers to a JavaScript variable that points to an HTML element in the DOM, i.e. the stuff we explained above under the label "object referencing".

Example: Changing style of background with a prompt

<?xml version = "1.0"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

<html xmlns = "http://www.w3.org/1999/xhtml">
   <head>
      <title>Object Model</title>

      <script type = "text/javascript">
         <!--
         function start() 
         {
            var inputColor = prompt(
               "Enter a color name for the " + 
               "background of this page", "" );
            document.body.style.backgroundColor = inputColor;  
         }
         // -->
      </script>
   </head>

   <body onload = "start()">
      <p>Welcome to our Web site!</p>
   </body>
</html>

File: change-background-style.html

Example: Change style with a push button

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>Manipulating Styles</title>

    <script type="text/javascript">
      function changeText() {
        var p = document.getElementById("pid");
	p.style.color = "blue"
	p.style.fontSize = "18pt"
      }
    </script>
  </head>
  <body>
    <h1>Manipulating Styles</h1>
    <ul>
      <li>Inspired from <a href="http://developer.mozilla.org/en/docs/Gecko_DOM_Reference:Examples">
          http://developer.mozilla.org/en/docs/Gecko_DOM_Reference:Examples</a></li>
    </ul>
    <p id="pid" 
      onclick="window.location.href = 'http://www.cnn.com/';">News Link</p>
    <form>
      <p><input value="Change style" type="button" onclick="changeText();"></p>
    </form>
    <hr>
 Last modified: Mon Jan 23 18:19:47 CET 2006
<!-- hhmts end -->
  </body>
</html>

File: change-style-1.html

Example: Change style forth and back with a push button

<!DOCTYPE html>
<html>
  <head>
    <title>Manipulating Styles</title>
    
    <script type="text/javascript">
      window.onload = function () {
         document.getElementById("but").onclick=changeText;
      }

      function changeText() {
      var p = document.getElementById("pid");
      if (p.style.color == "red") {
        p.style.color = "blue";
        p.style.fontSize = "16pt";
        flag=2;
        }
      else {
        p.style.color = "red";
        p.style.fontSize = "16pt";
        flag=1;
       }
      }
    </script>


  </head>
  <body>
    <h1>Manipulating Styles</h1>
    <ul>
      <li>Inspired from <a href="http://developer.mozilla.org/en/docs/Gecko_DOM_Reference:Examples">http://developer.mozilla.org/en/docs/Gecko_DOM_Reference:Examples</a></li>
   </ul>
    <p id="pid" 
      onclick="window.location.href = 'http://www.cnn.com/';">News Link</p>
    <form>
      <p><input value="Change style" type="button" id="but"></p>
    </form>

    <hr>
 <!-- Created: Mon Jan 23 18:03:44 CET 2006, changed Dec 2014 -->
 </body>
</html>

HTML Window and Navigator

Introducing some window and navigator properties

We firstly shall introduce some interesting properties. A complete example is presented in the next section.

  • The Window interface gives information about the window
  • It also includes a reference to the navigator
  • (Based on the AbstractView interface of DOM Level 2 Views Specification)
window.document

Returns the document object of a window (useful if you manipulate more than one window)

doc= window.document;
// print the title
window.dump(doc.title);
window.navigator

Returns the navigator object

nav = window.navigator;

You then can extract information from the navigator, e.g.

alert ("Language of your browser: " nav.language);

Navigator information is important for writing hairy cross-browser scripts. Here are a few properties of interest (there are more):

 navigator.appName
 navigator.appVersion
 navigator.userAgent
 navigator.appCodeName

On the Web, you can find good browser detection scripts, e.g.

window.history
h = window.history;
alert ("You have " h.items " item in your navigation history");
window.status

Can read or change the "status bar" (at bottom of window)

window.status = "cool website";

E.g. following code shows how to trigger status bar change when user moves the mouse over a link (by default most browsers will not allow this).

<a href="http://yoursite.org/"> onmouseover="status='Consult this';  
return true;">Your site</a>
window.print()

Sends content of window to printer

window.print();

Example: Information about the navigator

<?xml version = "1.0"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

<html xmlns = "http://www.w3.org/1999/xhtml">
 <head>
  <title>The navigator Object</title>
  <script type = "text/JavaScript">
    // <![CDATA[
    function start () {
      var output1 = "Hello, your " + navigator.appName + " navigator has the following properties <br/>";
      document.writeln(output1);
      
      var output2 = "<ul>";
      output2 += "<li>Navigator Application Name: " + navigator.appName + "</li>";
      output2 += "<li>Version = " + navigator.appVersion + "</li>";
      output2 += "<li>User agent = " + navigator.userAgent + "</li>";
      output2 += "<li>Code Name = " + navigator.appCodeName + "</li>";
      output2 += "</ul>";
      
      document.writeln(output2);
      
      if (navigator.javaEnabled()) document.write("<li>Java works (enabled)");
      else document.write("<li>Java doesn't work");
    }
    // ]]>
    </script>
  </head>
  <body onload = "start()"> </body>
</html>

File: navigator-props.html

Example: Redirect to page according to navigator

(This script is a bit too simple for real world use ...)

<?xml version = "1.0"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">

<html xmlns = "http://www.w3.org/1999/xhtml">
  <head>
    <title>The navigator Object</title>
    <script type = "text/javascript">
      <!--
      function start() {
      alert ("Your Navigator is " + navigator.appName + ", Version " +  navigator.appVersion.substring() );
      if ( navigator.appName == "Microsoft Internet Explorer" ) {
         if ( navigator.appVersion.substring( 1, 0 ) >= "4" )
            document.location = "newIEversion.html"; 
         else
            document.location = "oldIEversion.html";
         }
      else 
      document.location = "NSversion.html";  
      }

      // -->
    </script>
  </head>
  
  <body onload = "start()">
    <p>Redirecting your browser to the appropriate page, 
      please wait...</p>
  </body>
</html>

File: navigator.html and newIEversion.html and NSversion.html

Collections and creation of elements

To understand code in the following section you need some training in programming (which we don't provide here). Therefore, just try to grasp some very abstract principles and try to copy/paste this code and make some very minor modifications ....

Collections

Instead of dealing with just one single object, you may want to write a script that can deal with several objects at the same time. E.g:

  • all objects that have the same "name" attribute (only few HTML elements can have a name attribute)
  • all elements of list
  • all titles (h2) of a page

Example: Emphasize child elements

This code will hightlight contents of li elements within an ol or ul HTML element that has id="important"

<?xml version = "1.0"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">

<html xmlns = "http://www.w3.org/1999/xhtml">
   <head>
      <title>Collections</title>

      <script type = "text/javascript">
         function doit()
         {   
            var list = document.getElementById("important");
            var list_els = list.getElementsByTagName("li");
            // alert (list.innerHTML);
            for (var i = 0; i < list_els.length; i++) { 
                // if (list_els[i].nodeType == 1)
                list_els[i].style.color = "red";
             }
         }
      </script>
   </head>

   <body>
    <form>
      <p><input value="Highlight important things" type="button" onclick="doit();">
      </p>
    </form>

    <p>Welcome to our <strong>Web</strong> page!</p>
    <div></div>
    <p>Here we have list of important things:</p>
    <ul id="important">
      <li>This is important</li>
      <li>This is quite important</li>
      <li>This is also important</li>
    </ul>
    <p>Here we have list of less important things:</p>
    <ul>
      <li>This is less important</li>
      <li>This is not so important</li>
      <li>This ain't important either</li>
    </ul>
   </body>
</html>

File: emphasize-collection.html

Tree walking

Tree walking means to look at an element (for starters) and then examine its children, the children of children etc.

  • We start using "real" algorithms here which are not easy to understand. However, you may take this code and just change a few things in order to fit it to your purpose. Make sure to change only 1-2 things
  • We also introduce here the concept of functions that take arguments . Basically, we can call a function and give it information it has to deal with.

Example: Tree walking - Collect element names

This is fairly uninteresting code since it will only display HTML elements used in a document, but it will show the overall logic of tree walking. Just copy/paste all the javascript code and the input button if you want to see it in action in one of your pages. For programmers: Documentation is in the comments and the HTML page.

  • The code has two functions. When the user presses the button it launch the do_document function
  • This do_document function will extract the body element and then call the mark_tags function with the argument == body element
  • The mark_tags function will examine all children of body and if there are any, also the children of these children, etc.
  • Each time we find an element node, we will append its name to the node_list variable
  • Finally, we display the node_list in an alert popup window
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>Tree walking</title>
    <script>
    var node_list = "";

    function do_document () {
      mark_tags(document.body);
      alert ("This text has the following elements: " + node_list);
    }

    function mark_tags(node) {                     
      // Check if n is an Element Node
      if (node.nodeType == 1 /*Node.ELEMENT_NODE*/)  {
	// Append the node name to the list
	node_list += node.nodeName + " ";
	// Let's see if there are children
	if (node.hasChildNodes()) {
	    // Now get all children of n
	    var children = node.childNodes;               
	    // Loop through the children
	    for(var i=0; i < children.length; i++) {  
                mark_tags(children[i]);      // Recurse on each one
	    }
	}
      }
   }  
</script>
</head>

<body>
    <h1>Tree walking</h1>
    <form>
      <input type=button onClick="do_document();" value="Show body node names">
    </form>
    <p>Pressing the above <strong>button</strong> will:</p>
    <ul>
      <li>launch the do_document function</li>
      <li>The do_document function will extract the body element and then call the mark_tags function with argument == body element</li>
      <li>The mark_tags function will examine all children of body and if there are are, also the children of these children, etc.</li>
      <li>Each time we find an element node, we will append its name to the node_list variable</li>
      <li>Finally, we display node_list in an alert popup window</li>
    </ul>
    
    <hr>
<!-- Created: Tue Apr 17 15:28:55 Europe de l'Ouest 2007 -->
<!-- hhmts start -->
Last modified: Wed Apr 18 10:37:39 W. Europe Standard Time 2007
<!-- hhmts end -->
  </body>
</html>

File: tree-walking.html

Tree walking: Change color style

(1) Copy the whole script or save the [source. Then, have a look at this HTML page (tree-walking2.html). It's all in there for you to grab ...

(2) Then, decide which elements in your HTML text you wish to highlight and add a class attribute to each of these, e.g. something like:

<p class="important">

(3) Change the class attribute value from "important" to whatever you wish, but don't forget to change the argument when calling the do_document function, e.g. if the CSS class you wish to highlight is "cool", change to:

<input type=button onClick="do_document(cool,red);" value="Highlight">

(4) You may add as many input buttons you like, but of course there should be a corresponding css class and a color.

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>Tree walking</title>
    <script>

    function do_document (css_class,color) {
      mark_tags(document.body,css_class,color);
    }

    function mark_tags(node,css_class,color) {                
      // Check if n is an Element Node
      if (node.nodeType == 1 /*Node.ELEMENT_NODE*/)  {
	// Highlight if needed
        // IE has a bug, for IE we use the attributes['xx'].value
	  var class_attr = (navigator.appName == "Microsoft Internet Explorer") ? node.attributes['class'].value : (node.getAttribute("class"));
        if (class_attr == css_class)
          node.style.color = color;
	// Let's see if there are children
	if (node.hasChildNodes()) {
	    // Now get all children of node
	    var children = node.childNodes;               
	    // Loop through the children
	    for(var i=0; i < children.length; i++) {  
                // Recurse on each child
                mark_tags(children[i],css_class,color);      
	    }
	}
      }
   }  
</script>
</head>

<body>
    <h1>Tree walking</h1>
    <form>
      <input type=button onClick="do_document('important','red');" 
             value="Highlight important stuff">
      <input type=button onClick="do_document('boring','#ffff00');" 
             value="Highlight boring stuff">
    </form>
    <p>Pressing the above <strong>buttons</strong> will:</p>
    <ul>
      <li>launch the do_document function with 2 arguments: A name of a CSS class and a color</li>
      <li>The do_document function will extract the body and then call the mark_tags function with arguments body, css_class and color</li>
      <li class="important">The mark_tags function will examine all children of body and if there are are, also the children of these children, etc.</li>
      <li class="important">Each time we find an element node that has an attribute class="important", we will change its style to a given color</li>
    </ul>
    
    <p class="boring">Let's hope you enjoy this</p>
    <p class="important">If you want to reuse this code:</p>
    <ul>
      <li>Copy the whole script section in the head plus the lines with the input buttons. Just view the source of this page. It's all in there.</li>
      <li>Decide which elements in your HTML text you wish to highlight and add a class atttribute to each of these, e.g. something like:
      &lt;p class="important"&gt;</li>
      <li class="important">Change the class attribute value from "important" to whatever you wish, but don't forget to change the argumenst when calling the do_document function, e.g. if the CSS class you wish to highlight is "cool" and you want the color to be red:
 &lt;pre&gt;&lt;input type=button onClick="do_document('cool','red');" value="Highlight important stuff"&gt;&lt;/pre&gt;
      </li>
      <li>You may add as many input buttons you like, but of course there should be a corresponding css class and a color.</li>
      <li>Of course, you also can change the code to modify other style properties, but that will require some JavaScript and DOM knowledge....</li>
    </ul>

    <hr>
    Made by Daniel K. Schneider, TECFA. This is freeware.
 <!-- Created: Tue Apr 17 15:28:55 Europe de l'Ouest 2007 -->
  </body>
 </html>

tree-walking2.html

Example: Tree walking: Change any style

If you wish to change other style properties, you may look at this code. It implements a do_document(css_class,style_value,style_property) function. E.g.

do_document('boring','none','display')

would change the display property of elements with class="boring" to none (hide elements)

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>Tree walking</title>
    <script>

    function do_document (css_class,color,style_attr) {
      mark_tags(document.body,css_class,color,style_attr);
    }

    function mark_tags(node,css_class,color,style_attr) {                
      // Check if n is an Element Node
      if (node.nodeType == 1 /*Node.ELEMENT_NODE*/)  {
	// Highlight if needed
        // IE has a bug, for IE we use the attributes['xx'].value
	  var class_attr = (navigator.appName == "Microsoft Internet Explorer")
                           ? node.attributes['class'].value : (node.getAttribute("class"));
        if (class_attr == css_class)
          node.style[style_attr] = color;
	// Let's see if there are children
	if (node.hasChildNodes()) {
	    // Now get all children of node
	    var children = node.childNodes;               
	    // Loop through the children
	    for(var i=0; i < children.length; i++) {  
                // Recurse on each child
                mark_tags(children[i],css_class,color,style_attr);      
	    }
	}
      }
   }  
</script>
</head>

<body>
    <h1>Tree walking</h1>
    <form>
      <input type=button onClick="do_document('important','red','color');" 
             value="Highlight important stuff">
      <input type=button onClick="do_document('boring','none','display');" 
             value="Highlight boring stuff">
    </form>
    <p>Pressing the above <strong>buttons</strong> will:</p>
    <ul>
      <li>launch the do_document function with 2 arguments: A name of a CSS class and a color</li>
      <li>The do_document function will extract the body and then call the mark_tags function with arguments body, css_class and color</li>
      <li class="important">The mark_tags function will examine all children of body and if there are are, 
          also the children of these children, etc.</li>
      <li class="important">Each time we find an element node that has an attribute class="important",
          we will change its style to a given color</li>
    </ul>
    
    <p class="boring">Let's hope you enjoy this</p>
    <p class="important">If you want to reuse this code:</p>
    <ul>
      <li>Copy the whole script section in the head plus the lines with the input buttons. 
          Just view the source of this page. It's all in there.</li>
      <li>Decide which elements in your HTML text you wish to highlight and add a class atttribute to each of these,
          e.g. something like:
      &lt;p class="important"&gt;</li>
      <li class="important">Change the class attribute value from "important" to whatever you wish, 
          but don't forget to change the arguments when calling the do_document function,
          e.g. if the CSS class you wish to highlight is "cool" and you want the color to be red:
 &lt;input type=button onClick="do_document('cool','red','color');" value="Highlight important stuff"&gt;
      </li>
      <li>You may add as many input buttons you like,
          but of course there should be a corresponding css class and a property and a value.</li>
      <li>Of course, you also can change the code to modify more complex style properties,
          but that will require some JavaScript and DOM knowledge....</li>
    </ul>

    <hr>
    Made by Daniel K. Schneider, TECFA. This is freeware.
<!-- Created: Tue Apr 17 15:28:55 Europe de l'Ouest 2007 -->
<!-- hhmts start -->
Last modified: Wed Apr 18 10:38:59 W. Europe Standard Time 2007
<!-- hhmts end -->
  </body>
</html>

tree-walking3.html

Using getElementsByClassName instead of tree walking

As of 19:51, 10 October 2009 (UTC), works with Firefox.

<?xml version = "1.0"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN"
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd">
 
<html xmlns = "http://www.w3.org/1999/xhtml">
   <head>
      <title>Collections</title>
 
      <script type = "text/javascript">

      // This function will change a given class to a given color.
      // To make it work, there must be class attributes in the HTML code
      // and the function must be called like doit('class_name','color_name')

  function doit (myclass,color) {   
      var list_of_elements = document.getElementsByClassName(myclass);
      for (var i = 0; i < list_of_elements.length; i++) {
          var item = list_of_elements.item(i);
          if (item.nodeType == 1) {item.style.color = color;}
      }
   }
      </script>
   </head>
 
   <body>


  <form>
      <!-- invisible comment: note how we use single quotes for date and red -->
      <p><input value="Highlight dates" 
                type="button" onclick="doit('date','red');" />
	  <input value="Unhighlist dates"
	    type="button" onclick="doit('date','black');" />
      </p>
      <p><input value="Highlight events"
	  type="button" onclick="doit('event','green');" />
      </p>
 </form>
 
    <p>The late <i class="date">20th century</i> is 
      <span class="event">exciting</span></p>
    
    <p><span class="date">1999</span> was a turning point since
    a  <span class="event">millenium was coming up.</span></p>

   </body>
</html>

Source: http://tecfa.unige.ch/guides/js/ex/dhtml/get-elements-by-classname.html

Note: We also should try DOM event listener code instead of HTML embedded function calls... (sometimes later)

Creation of elements

  • Creation of new HTML elements is somewhat hairy (unless you use the innerHTML method which is less standard and doesn't give you the same power, since new elements will not really be in the DOM)
  • You have to create an element with the document.createElement "factory" method.
  • Then you have to fill in the element, e.g. by creating a TextNode with document.createTextNode
  • Then only you can insert it, e.g. append an element's children with heading.appendChild();

Example: Simple append

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>Simple text insertion into the DOM of an HTML page</title>
 
    <script type="text/JavaScript">

    function insert_things () {
      // heading will contain a new "h1" element (node)
      var heading = document.createElement("h1");
      // heading_text will contain a new "text" node
      var heading_text = document.createTextNode("I love pressing buttons !");
      // we can now ask the heading node to insert the heading_text
      heading.appendChild(heading_text);
      // Finally we can ask the body to insert this at the end.
      document.body.appendChild(heading);
      }
    </script>

 </head>

  <body>
    <h1>Simple text insertion into the DOM of an HTML page</h1>
    <p>
      Each time you click the DoIt button, some text will be inserted at the end of the HTML body.  See the source of this page.</p>

    <input type=button onClick="insert_things();" value="DoIt">

    <hr>
  </body>
</html>

insert3.html

Animation

Animation means changing some style properties (e.g. position, size, color). There are several sorts of animations, e.g.

  • automatic animations
  • animations that react to user input

Warning (again). This section requires some programming skills. If you don't have these, do not worry. The goal here is to demo that more sophisticated animation can be done with a little bit of scripting. Learning how to script takes several weeks ....

Example: User-driven object moving

In the body, we use href attributes to call a moveitBy javascript function

  • This function is called with 3 arguments: id , move_right , move_down
  • "id" is the value of and id attribute
  • move_right and move_down are positive or negative numbers (pixels to shift).
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>Move an object with JS and DOM</title>

    <script type="text/javascript">

      function moveitBy(img, x, y){
      var obj         =  document.getElementById(img);
      obj.style.left  =  parseInt(obj.style.left)+x+"px"
      obj.style.top   =  parseInt(obj.style.top)+y+"px"
      }
      
      function moveitTo(img, x, y){
      var obj         = document.getElementById(img);
      obj.style.left  = x+"px"
      obj.style.top   = y+"px"
      }
    </script>
  </head>

  <body>
    <h1>Move an object with JS and DOM</h1>
    <p></p>
    <div id="image" style="position: relative; left: 0px; top: 0px;">
      <img src="tecfa-affiche.gif" alt="logo">
    </div>
    <ul>
      <li><a href="javascript:moveitBy('image', 20, 0);">Move by 20px (right)</a></li>
      <li><a href="javascript:moveitBy('image', -20, 0);">Move by 20px (left)</a></li>
      <li><a href="javascript:moveitBy('image', 0, 10);">Move to 10px (down)</a></li>
      <li><a href="javascript:moveitBy('image', 0, -10);">Move to 10px (up)</a></li>
      <li><a href="javascript:moveitTo('image', 0, 0);">Move to original position</a></li>
    </ul>
    
View Source to see the code for this.

    <hr>
    <address>Daniel K. Schneider</address>
<!-- Created: Tue Apr 25 10:22:13 CEST 2006 -->
<!-- hhmts start -->
Last modified: Mon Apr 16 18:15:55 Europe de l'Ouest 2007
<!-- hhmts end -->
<!-- Inspired by <a href="http://wsabstract.com/javatutors/dom4.shtml">http://wsabstract.com/javatutors/dom4.shtml</a> by Timothy Francis Brady. -->
  </body>
</html>

File: move-object1.html

The moveitBy function

  • firstly takes the first argument (an id) and retrieves the div object within which we placed the image
  • it then modifies "left" and "top" values of this div by adding or substracting 20.
function moveitBy
(img, x, y){
  var obj         =  document.getElementById(img);
  obj.style.left  =  parseInt(obj.style.left) x "px"
  obj.style.top   =  parseInt(obj.style.top) y "px"
  }
  • The function moevitTo will reposition an object at given left/top coordinates
function moveitTo(img, x, y){
  var obj         = document.getElementById(img);
  obj.style.left  = x "px"
  obj.style.top   = y "px"
 }
</script>

Example: Automatic font, size and position animation

<?xml version = "1.0"?>
<!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Strict//EN"
   "http://www.w3.org/TR/xhtml1/DTD/xhtml1-strict.dtd">
 <!-- Dynamic Positioning, originally by Deitel & Associates, Inc: 
     Internet and World Wide Web, How To Program  -->
 <!-- adapted to more real DOM + simplified JS by Daniel K. Schneider 
     There may be copyright issues ... -->

<html xmlns = "http://www.w3.org/1999/xhtml">
   <head>
      <title>Dynamic Positioning</title>

      <script type = "text/javascript">
         var speed = 5;
         var count = 10;
         var firstLine = "Text growing";
         var pText;

         function start()  {
            pText = document.getElementById("pText");
            window.setInterval( "run()", 100 );
         }

         function run() {
            count += speed;

            if ( ( count % 200 ) == 0 ) {
               speed *= -1;
               pText.style.color = ( speed < 0 ) ? "red" : "blue" ;
               firstLine =         ( speed < 0 ) ? "Text shrinking" : "Text growing";
            }

            size = Math.round(count / 3) ;
            pText.style.fontSize = size + "px";
            pText.style.left = count + "px";
            pText.innerHTML = firstLine + "<br /> Font size: " + size + "px";
	}
      </script>
   </head>

   <body onload = "start()">
      <p id = "pText" 
         style = "position:absolute; left:0; font-family:serif; color:blue">
      Welcome!</p>
   </body>
</html>
File dynamicposition.html

A slighly more complex version is:

File dynamicposition2.html (it has a start/stop button, but the code should be improved)

Event handlers

This section needs be elaborated. In the meantime, see the Wikipedia DOM events articles for more details about DOM level 2 events or the Gecko documentation, in particular the definitions for element and event

When two or more nested elements define an event handler for the same type of event, then there must be some rules to decide which event will be handled.

A simple example

Example: examine-events-en.html

<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
  <head>
    <title>Gecko DOM addEventListener example</title>

    <style>
     #table2 { border: 1px solid blue; padding: 10px}
     td { border: 1px solid red }
    </style>

   <script>
      window.onload = load;

      var x_td;
      var y_td;

      // Event registration
      function touche (event) {
        x = event.pageX;
        y = event.pageY;
        obj = event.target;
        // alert ("positions x=" + x + ",y=" + y + "\n object= " + obj);
        x_td.innerHTML = x;
        y_td.innerHTML = y;
        obj_td.innerHTML = obj.innerHTML;
      }
 
      function load() { 
         var el2 = document.getElementById("table2"); 
         if (el2.addEventListener) el2.addEventListener("mouseover", touche, false)
         // for those who can't use a real browser
            else alert ("Sorry you need a browser that understands DOM Level 2 Events");
         x_td = document.getElementById("x"); 
         y_td = document.getElementById("y"); 
         obj_td = document.getElementById("obj"); 
      } 
   </script> 

 </head>

 <body> 
    <h1>Gecko DOM addEventListener example</h1>

This is an EventHandler demo that will deal with a mouseover event
<p>
Ceci est une démo d'un EventHandler pour l'événement mouseover, enregistré pour la table. 

<p>
Move your mouse over the table please / Bougez la souris sur le tableau SVP:


    <table align="center" id="table2"> 
	<tr><td>Ma tete</td></tr> 
	<tr><td>Ma poitrine</td></tr> 
	<tr><td>Mon ventre</td></tr> 
	<tr><td>Mes jambes</td></tr> 
    </table> 
    
<p>
J'été touché aux coordonnées / I was touched at coordinates:
    <table align="center" id="coordinates"> 
	<tr><td>X = </td>  <td id="x"> </td></tr> 
	<tr><td>Y = </td>  <td id="y"> </td></tr> 
	<tr><td>Objet = </td>  <td id="obj"> </td></tr> 
    </table> 
    <hr>

    Testé avec Mozilla et Firefox (marche) et avec IE 6 (ne marche pas, car ne semble pas avoir implémenté addEventListener).
<p>
    Source: <a href="http://developer.mozilla.org/fr/docs/DOM:element.addEventListener">http://developer.mozilla.org/fr/docs/DOM:element.addEventListener</a>

  </body>
</html>

The crucial code is the following. It will define an event handler for a mouseover with the table (id="table2"). The function is mouseover is called whenever a user mouses over the table.

 var el2 = document.getElementById("table2"); 
 el2.addEventListener("mouseover", touche, false)

Exercise

  1. Create an HTML page that includes some elements (tags) some of which you consider important.
  2. Add a class attribute to these with some value, e.g.
<ul class="important"> <li>Before you start, insert the key</li> </ul>
  • Implement at least one push button that will change styling of these elements
    • Optional: Implement other push buttons that highlight other elements
    • Look at the examples in this tutorials
  • For those with some programming skills:
    • Change other style elements, e.g. make elements visible or hidden, change position, etc.
    • Look at the examples in this tutorials

Links

W3C specifications
Tutorials

Acknowledgements and copyright modification