SEARCH
INSIDE Current Issue Columns Offline Newsletters Archives
TRACKS Web Authors Designers Developers Strategists
GUIDES Style
Sheets Web
Browsers Web
Tools Ranking
System
ABOUT WebReview.com Write for
Us Advertising Staff Contact
NETWORK WebTechniques.com WEB2000 Show Site WebCoder.com
|
 |
 |
June
18, 1999 Issue > Browsers
JavaScript for the MVC example
By Mitch
Gould
The DOM
in Version 5 Browsers
Let's look at the JavaScript that runs our example. In studying
mvctable.js, a veteran DHTML coder will find some surprises due to its use
of the new DOM.
/*
mvctable.js v0.3 Monday, May 31, 1999
Mitch Gould - humanfact@generalpicture.com
by Mitch Gould, humanfact@generalpicture.com
This script demonstrates dynamic documents in Netscape Navigator and Internet Explorer 5 in the following ways:
(a) it exercises W3C's standard Document Object Model API.
(b) it creates, modifies, and destroys a table.
(c) it partially illustrates the concept of model-view-controller.
(To fully illustrate the MVC concept, modifications made to the
data view would need to be propagated back to the data model.)
*/
// A. Data initialization.
var datacount = 0
model = new Array()
// Allocate the first dataset, a set of quotations, from this array.
arrayquotes = new Array(
"Oh dear! I shall be too late.",
"Curiouser and curiouser!",
"Who are -you-?",
"We're all mad here.",
"Twinkle, twinkle, little bat.",
"Off with her head!",
"I make you a present of everything I've said...",
"Once, I was a real Turtle.",
"Sentence first—verdict afterwards.")
// When a link is clicked, the quotations' sources will be revealed
// from this array.
arraysources = new Array(
"White Rabbit",
"Alice",
"Caterpillar",
"Cheshire Cat",
"Dormouse",
"Red Queen",
"Dutchess",
"Mock Turtle",
"Red Queen")
// B. MVC-DOM methods.
// Establish a new data model and assign it to a new view.
function startController() {
// Populate the model with initial data.
datamodel = refreshModel(arrayquotes)
// Get the document body element.
var docbod = getBody()
/*
Create a view in the body of the document and fill it
with the initial data.
*/
createView(docbod, model)
}
// Copy the specified dataset into the model.
function refreshModel(arraycurrent) {
// Populate the model with the current datastore.
for(var i=0; i < arraycurrent.length; i = i + 1)
{
model[i] = arraycurrent[i]
}
return model
}
/*
this could be generalized to provide alternatives to a
a table view, such as a select object, a tree, or even
a textarea. this sample produces a one-column table.
Multi-column tables are more complex.
*/
function createView(bodyelement, themodel) {
table = document.createelement("TABLE")
table.border = 1
table.id = "viewtable"
tablebody = document.createelement("TBODY")
for(var i=0; i < model.length; i++)
{
currentrow = document.createelement("TR")
currentcell = document.createelement("TD")
currentcell.appendchild(document.createtextnode(model[i]))
currentrow.appendchild(currentcell)
tablebody.appendchild(currentrow)
}
table.appendchild(tablebody)
bodyelement.appendchild(table)
return table
}
// refresh the model first, then the view.
function refreshview(dataset) {
// populate the model with new data.
refreshmodel(dataset)
tablebody = document.getelementsbytagname("TBODY").item(0)
var count = 0
replacealltext(tablebody)
}
// One can also destroy HTML objects using the DOM.
function destroyView() {
objecttodestroy = document.getelementbyid("viewtable")
body = getbody()
body.removechild(objecttodestroy)
// now destroy the buttons.
objecttodestroy = document.getelementbyid("whosaid")
body.removechild(objecttodestroy)
objecttodestroy = document.getelementbyid("goaway")
body.removechild(objecttodestroy)
}
// c. dom tree-navigation and utilities.
/*
One must climb the trunk, branches, and twigs to get
(or set!) the fruit. The recursive nature of this
algorithm reflects an essential fractal nature of
documents.
*/
function replaceAllText(startelem) {
// Climb the object tree, replacing its text nodes with
// new data.
for (var i=0; i < startelem.childnodes.length; i = i + 1) {
switch (startelem.childnodes.item(i).nodetype) {
case 1: // element nodetype
replacealltext(startelem.childnodes.item(i))
break;
case 3: // text nodetype
if (datacount < model.length) {
settext(startelem.childnodes.item(i), model[datacount])
datacount = datacount + 1
} else {
settext(startelem.childnodes.item(i)," - ? - ")
}
break;
} //endswitch
} //endfor
} //endfunction
/*
many operations on dynamic documents require one to start
from the document's body element.
*/
function getBody()
{
if(navigator.appName != "Netscape") {
resultelement = document.body;
} else {
resultelement = document.getelementsbytagname("body").item(0);
}
return resultelement;
}
// utility function to overwrite text nodes.
function settext(tagtoset, valuetoset) {
tagtoset.nodevalue = valuetoset
}
// d. this can't start until the page loads.
window.onload = startcontroller
| Listing 2. The JavaScript
source for mvctable.js.
For the sake of clarity, mvctable.js is divided into four parts:
-
- A. data initialization,
- B. MVC-DOM methods,
- C. DOM tree-navigation and utilities, and
- D. load-event handler.
Section A is simply expected in a script of any size. Here, it sets up
the string arrays that contain the Alice quotations and their sources.
The code in the B section provides a way to implement a
model-view-controller design pattern using the Document Object Model. This
section acts as the controller, initializing the model and view,
refreshing the model and view with updated values, and destroying the view
upon request.
Section C provides support routines that encapsulate lower-level
details of access to document objects. It's a bit disappointing that the
DOM doesn't provide standardized access to the document at this level of
encapsulation, but once these utility methods are written, they can be
reused endlessly. These methods are responsible for navigating the
document tree to touch the desired objects, notably in this case, text
content that must be replaced.
The D section is required to start the controller as soon as the
browser finishes loading the page.
With this background, we're ready to examine the code example. As the
page is loading, the browser processes the data initialization section,
executing the constructor
model = new Array()
to create an empty model, and creating two more arrays:
arrayquotes and arraysources.
Initializing the controller
Once the page has finished loading, the controller starts.
// This can't start until the page loads entirely.
window.onload = startController
The controller transfers the quotes to the model, and creates a new
table in the document to act as a view, as shown in Listing 3.
// B. MVC-DOM methods.
// Establish a new data model and assign it to a new view.
function startController() {
// Populate the model with initial data.
datamodel = refreshModel(arrayquotes)
// Get the document body element.
var docbod = getBody()
/*
Create a view in the body of the document and fill it
with the initial data.
*/
createView(docbod, model)
}
| Listing
3. The startController() function.
To understand the functions called by startController(),
we must turn to a description of the DOM, which we'll cover in the next
section.
JavaScript for the MVC example Understanding
the Document Object Model
| .gif) |
.gif) |
.gif) |
|