DHTML
<pageby nominor="false" comments="false"/>
Introduction to Dynamic HTML
Prerequisites
- HTML and XHTML (background information and links)
- HTML and XHTML elements and attributes
- HTML and XHTML validation and repair
- CSS tutorial
- Javascript tutorial - basics
- 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
- 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:
- HTML or XHTML
- CSS, the Cascading Style Sheet language
- JavaScript, i.e. the ECMA-script programming language
- 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
- X3D, ....
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
- Comparison of layout engines (DOM) (wikipedia)
- http://www.quirksmode.org/dom/w3c_html.html (Quirksmode)
- http://www.quirksmode.org/dom/w3c_core.html
- 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).
Tools for DOM inspection
Most navigators have some built-in DOM tools. For some, extensions must be installed.
Examples of spring 2011 browsers.
- IE 9: 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: 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: Firebug is an alternative. It it includes more features of interest to JS 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:
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 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 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. “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 is a brief list of common APIs 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.
document.getElementById(id)
element. getElementsByTagName (name)
document.createElement (name)
parentNode. appendChild (node)
element.innerHTML
element.style.left
element.setAttribute
element.getAttribute
element.addEventListener
window.content
window.onload
window.dump
window.scrollTo
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:
(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, then write a little function that does some modification.
- 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
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
<?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 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.
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.
- Gecko DOM CSS Properties
- W3C Document Object Model CSS from the Document Object Model (DOM) Level 2 Style Specification
Most of the time it's easy to guess the DOM name of a CSS property
- remove the "-"
- 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 PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN">
<html>
<head>
<title>Manipulating Styles</title>
<script type="text/javascript">
var flag = 1;
function changeText() {
var p = document.getElementById("pid");
if (flag==1) {
p.style.color = "blue";
p.style.fontSize = "16pt";
flag=2;
}
else if (flag==2) {
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" onclick="changeText();"></p>
</form>
<hr>
<!-- Created: Mon Jan 23 18:03:44 CET 2006 -->
</body>
</html>
File: change-style-2.html
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();
<?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
(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:
<pclass="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:
<p class="important"></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:
<pre><input type=button onClick="do_document('cool','red');" value="Highlight important stuff"></pre>
</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>
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:
<p class="important"></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:
<input type=button onClick="do_document('cool','red','color');" value="Highlight important stuff">
</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>
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>
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)
Exercise
- Create an HTML page that includes some elements (tags) some of which you consider important.
- 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
- http://www.w3.org/TR/DOM-Level-2-Core/
- http://www.w3.org/TR/DOM-Level-2-HTML/
- http://www.w3.org/TR/DOM-Level-2-Events/
- http://www.w3.org/TR/DOM-Level-2-Style/