Advanced DOM manipulation - Gavilan Collegehhh.gavilan.edu/llam/LectureNotes/AdvancedDOM.pdf ·...

Preview:

Citation preview

Advanced DOM manipulation

Objectives

Applied

Write code that uses the ready method of the jslib_dom_ready.js

library.

Write code that uses the walk and getElementsByClassName

methods of the jslib_dom.js library.

Write code that creates and clones DOM nodes.

Write code that adds and removes DOM nodes from the DOM

tree, including using a document fragment.

Objectives (continued)

Knowledge

Describe the problems associated with using the onload method

of the window object to detect when the DOM is ready.

Describe the createTextNode, createElement, and cloneNode

methods.

Describe the appendChild, insertBefore, removeChild, and

replaceChild methods.

Describe the createDocumentFragment method.

The XHTML page in a browser

The XHTML for the page <!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>DOM Ready Test</title>

<link rel="stylesheet" type="text/css"

href="ready_test.css"/>style>

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

</head>

The XHTML for the page (continued) <body>

<div id="content">

<h1 class="center">DOM Ready Test</h1>

<p>DOM Status: <span id="status">Not Ready</span></p>

<p><button id="btnTest">Test</button></p>

<p><!-- this script prevents the browser from caching

the image -->

<script type="text/javascript">

var ms = (new Date()).getTime();

var site = "http://solarsystem.nasa.gov";

var path =

"/multimedia/gallery/GPN-2001-000009.jpg";

var url = site + path + "?ms=" + ms;

document.write(

'<img src="' + url + '" width="600" />' );

</script>

</p>

</div>

</body>

</html>

The ready_test.js file var $ = function(id) { return document.getElementById(id); }

var testClick = function () {

alert("This button is ready!");

}

window.onload = function () {

$("btnTest").onclick = testClick;

$("status").firstChild.nodeValue = "READY";

}

The XHTML page in a browser

The XHTML that imports the library <script type="text/javascript"

src="jslib_dom_ready.js"></script>

A method of the jsLib.dom object ready( function )

An except from the ready_test.js file var domReady = function () {

$("btnTest").onclick = testClick;

$("status").firstChild.nodeValue = "READY";

}

jsLib.dom.ready( domReady );

The jslib_dom_ready.js file if ( ! jsLib ) { var jsLib = {}; }

if ( ! jsLib.dom ) { jsLib.dom = {}; }

jsLib.dom.readyList = [];

jsLib.dom.isReady = false;

jsLib.dom.ready = function ( fn ) {

if ( fn instanceof Function ) {

if ( jsLib.dom.isReady ) {

fn.call(document);

} else {

jsLib.dom.readyList.push( fn );

}

} else {

if ( jsLib.dom.isReady ) {

while ( jsLib.dom.readyList.length > 0 ) {

fn = jsLib.dom.readyList.pop();

fn.call(document);

}

}

}

}

The jslib_dom_ready.js file (continued) jsLib.dom.readyInit = function () {

if ( document.addEventListener ) {

document.addEventListener(

"DOMContentLoaded",

function () {

jsLib.dom.isReady = true;

jsLib.dom.ready();

},

false

);

The jslib_dom_ready.js file (continued) } else if ( document.attachEvent ) {

if ( document.documentElement.doScroll &&

window == window.top ) {

var doScrollPoll = function () {

if ( jsLib.dom.isReady ) return;

try {

document.documentElement.doScroll("left");

} catch( error ) {

setTimeout( doScrollPoll, 0 );

return;

}

jsLib.dom.isReady = true;

jsLib.dom.ready();

}

doScrollPoll();

The jslib_dom_ready.js file (continued) } else {

document.attachEvent(

"onreadystatechange", function () {

if (document.readyState === "complete"){

jsLib.dom.isReady = true;

jsLib.dom.ready();

}

}

);

}

if ( window.attachEvent ) {

window.attachEvent( "onload", function () {

jsLib.dom.isReady = true;

jsLib.dom.ready();

}

);

}

}

}

jsLib.dom.readyInit();

The DOM tree displayed in a dialog box

The XHTML file <!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>Image Gallery</title>

<link rel="stylesheet" type="text/css"

href="image_gallery.css"/>

<script type="text/javascript"

src="jslib_dom_ready.js"></script>

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

<script type="text/javascript"

src="show_dom_tree.js"></script>

</head>

The XHTML file (continued) <body>

<div id="content">

<h1 class="center">Fishing Image Gallery</h1>

<p class="center">Click one of the links below

to view the image.</p>

<ul class="center" id="imageList">

<li><a href="casting1.jpg" title="Casting 1">

Casting 1</a></li>

<li><a href="casting2.jpg" title="Casting 2">

Casting 2</a></li>

<li><a href="catchrelease.jpg"

title="Catch and Release">

Catch and Release</a></li>

<li><a href="fish.jpg" title="Fish">Fish</a></li>

<li><a href="lures.jpg" title="Lures">Lures</a></li>

</ul>

</div>

</body>

</html>

A method of the jsLib.dom object walk ( nodeFn, preFn, postFn, node )

The show_dom_tree.js file var domTree = "";

var indent = "";

var addNode = function (node) {

domTree += indent + node.tagName.toLowerCase();

if (node.hasAttributes()) {

domTree += " (";

for ( var i = 0; i < node.attributes.length; i++) {

domTree += node.attributes[i].name + "=\"";

domTree += node.attributes[i].value + "\"";

if ( i < node.attributes.length - 1) {

domTree += " ";

}

}

domTree += ")";

}

domTree += "\n";

}

var moreIndent = function () {

indent += " ";

}

The show_dom_tree.js file (continued) var lessIndent = function () {

if (indent.length >= 4) indent = indent.slice(0,-4);

}

var showDomTree = function () {

jsLib.dom.walk(addNode, moreIndent, lessIndent);

alert(domTree);

}

jsLib.dom.ready( showDomTree );

A method of the jsLib.dom object getElementsByClassName ( className )

The XHTML that imports the JavaScript files <script type="text/javascript"

src="jslib_dom_ready.js"></script>

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

<script type="text/javascript"

src="show_centered_elements.js"></script>

The show_centered_elements.js file var showCenteredElementCount = function () {

var centeredElements =

jsLib.dom.getElementsByClassName("center");

alert("Centered elements: " + centeredElements.length);

}

jsLib.dom.ready( showCenteredElementCount );

The resulting dialog box

The jslib_dom.js file if ( ! jsLib ) { var jsLib = {}; }

if ( ! jsLib.dom ) { jsLib.dom = {}; }

jsLib.dom.walk = function ( nodeFn, preFn, postFn, node ) {

if ( nodeFn == undefined ) return;

if ( node == undefined ) node =

document.documentElement;

if (node.nodeType == 1) {

nodeFn(node);

if ( node.hasChildNodes() ) {

if ( preFn !== undefined ) preFn(node);

for(var i=0; i < node.childNodes.length; i++) {

jsLib.dom.walk(

nodeFn, preFn, postFn,

node.childNodes[i]);

}

if ( postFn !== undefined ) postFn(node);

}

}

}

The jslib_dom.js file (continued) jsLib.dom.getElementsByClassName = function ( className ) {

var elements = [];

var nodeTest = function (node) {

if ( className == node.className ) {

elements.push( node );

}

}

jsLib.dom.walk(nodeTest);

return (elements.length > 0) ? elements : undefined;

}

Two methods of the document object createTextNode( text )

createElement( tagName )

How to create a Text node var textNode =

document.createTextNode("Lightweight Neoprene Waders");

How to create an Element node var liNode = document.createElement("li");

How to modify the attributes of a new node var imgNode = document.createElement("img");

imgNode.src = "lures.jpg";

A method of the document object cloneNode( deep )

How to copy an Element node var list = document.getElementById("headlines");

var newList = list.cloneNode();

How to copy an Element node and its child nodes var list = document.getElementById("headlines");

var newList = list.cloneNode(true);

Two methods of the document object appendChild( newNode )

insertBefore( newNode, childNode )

How to add one node as the last child node var liNode = document.createElement("li");

var textNode =

document.createTextNode("Lightweight Neoprene Waders");

liNode.appendChild( textNode );

How to add one node as the first child node var ulNode = document.getElementById("headline");

ulNode.insertBefore( liNode, ulNode.firstChild );

A method of the document object removeChild( childNode )

How to remove a child node var removedNode = ulNode.removeChild( ulNode.lastChild );

A method of the document object replaceChild( newNode, childNode )

How to replace a child node with another node var replacedNode =

ulNode.replaceChild( liNode, ulNode.firstChild );

A method of the document object createDocumentFragment()

How to create a document fragment var docFrag = document.createDocumentFragment();

How to append nodes to a document fragment

Create the nodes

var liText = document.createTextNode(

"Lightweight Neoprene Waders" );

var liNode = document.createElement("li");

liNode.appendChild( liText );

var ulNode = document.createElement("ul");

ulNode.appendChild( liNode );

var pText = document.createTextNode(

"Mike's Bait and Tackle Shop");

var pNode = document.createElement("p");

pNode.appendChild( pText );

Append the nodes to a document fragment

docFrag.appendChild( ulNode );

docFrag.appendChild( pNode );

Append the document fragment to the document

var contentDiv = document.getElementById("content");

contentDiv.appendChild( docFrag );

The Headlines application in the browser

The XHTML file <!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>Mike's Bait and Tackle Shop</title>

<style type="text/css">

@import "main.css";

</style>

<script type="text/javascript"

src="jslib_event.js"></script>

<script type="text/javascript"

src="jslib_dom_ready.js"></script>

<script type="text/javascript"

src="headlines_library.js"></script>

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

</head>

The XHTML file (continued) <body>

<div id="content">

<h1 class="center">Mike's Bait and Tackle Shop</h1>

<div id="new_products">

<p id="np_head">New Products

<img src="pause.gif" id="toggle" /></p>

<ul id="headlines">

<li><a href="#">Aqua Cam Camera Case</a></li>

<li><a href="#">Lightweight Boat Box for

Saltwater Flies</a></li>

<li><a href="#">Stretch Pants for

Wet Wading</a></li>

<li><a href="#">Microfleece Zip-Neck with

4-Way Stretch</a></li>

<li><a href="#">Best Drift Inflatable

Indicators</a></li>

<li><a href="#">Pin-On Floating Fly

Keeper Box</a></li>

The XHTML file (continued) <li><a href="#">Lightweight Neoprene Waders</a></li>

<li><a href="#">Compact High-Volume

Air Pump</a></li>

<li><a href="#">Hook Disgorger and

Sharpener</a></li>

<li><a href="#">Tailwaters XT Wading Jacket</a></li>

</ul>

</div>

<p>Welcome to Mike's Bait and Tackle Shop. We have all

the gear you'll need to make your next fishing trip a

great success!</p>

<p>Contact us by phone at 559-555-6624 to place your

order today.</p>

<p class="copyright">&copy; 2009 Mike's Bait and Tackle

Shop</p>

</body>

</html>

The headlines_library.js file var $ = function(id) { return document.getElementById(id); }

var Headlines = function ( ulId, imgId, headlineCount ) {

var headlines = this;

if ( arguments.length < 2 || arguments.length > 3) {

throw new Error(

"Headlines: wrong number of arguments.");

}

this.ulNode = $(ulId);

this.imgNode = $(imgId);

if (arguments.length == 2) {

headlineCount = 3;

} else {

headlineCount = parseInt(headlineCount);

}

if ( isNaN(headlineCount) || headlineCount < 1 ) {

throw new Error("Headlines: Headline count " +

"is not a valid number.");

}

The headlines_library.js file (continued) this.headlineCount = headlineCount;

this.items = [];

this.running = false;

var node;

while ( this.ulNode.hasChildNodes() ) {

node = this.ulNode.removeChild(

this.ulNode.firstChild );

if ( node.nodeType == 1 && node.tagName == "LI") {

this.items.push(node);

}

}

this.next = 0;

while ( this.next < this.headlineCount &&

this.next < this.items.length) {

this.ulNode.appendChild( this.items[this.next] );

this.next++;

}

this.next--;

this.imgClick = function () { headlines.toggle(); };

this.ulOver = function () { headlines.pause(); };

this.ulOut = function () { headlines.play(); };

The headlines_library.js file (continued) jsLib.event.add( this.imgNode, "click", this.imgClick );

jsLib.event.add(

this.ulNode, "mouseover", this.ulOver );

jsLib.event.add( this.ulNode, "mouseout", this.ulOut );

this.play();

}

Headlines.prototype.showNext = function () {

this.next++;

this.next = this.next % this.items.length;

this.ulNode.removeChild( this.ulNode.firstChild );

this.ulNode.appendChild( this.items[this.next] );

}

Headlines.prototype.pause = function () {

clearInterval( this.timer );

this.imgNode.src = "play.gif";

this.running = false;

}

The headlines_library.js file (continued) Headlines.prototype.play = function () {

var headlines = this;

this.timer = setInterval(

function() { headlines.showNext(); }, 3000

);

this.imgNode.src = "pause.gif";

this.running = true;

}

Headlines.prototype.toggle = function () {

if ( this.running ) {

this.pause();

} else {

this.play();

}

}

The headlines.js file var headlines;

var headlinesStart = function () {

headlines = new Headlines( "headlines", "toggle", 4);

}

jsLib.dom.ready( headlinesStart );

Recommended