janModel.js

by Jan Verhoeven, October 3, 2003

The janModel.js script library contains functions to build a W3C DOM Core tree model in javascript, allowing for structured data storage. The model itself can be used for many purposes and works in recent versions of Internet Explorer, Mozilla, Netscape Navigator and Opera. The library can serialize a model into a text string, allowing for client-server exchange of a model. Have a look at the Quiz example. Dynamic loading of external models (defined in a javascript *.js file) is possible in IE and Mozilla, but not in Opera.

If you want you can download the demo files.

The Node object

Every model consists of a single root node object that can have any number of child nodes. Because every node can have any number of child nodes, and so on, you can build a tree structure of any complexity.

You create a new Node object with:

n= new Node(id,data)

The id parameter is required and must be a unique string identifier within the model.

The data parameter is optional and consist of one or more name:value pairs seperated by a semi-colon.

x = new Node("x100","label:BackEdit;size:567kb")

Please note that the value part of a name:value pair is unescaped when parsed. This means that you must escape special characters in the value part. You must at least escape new line, tab, : and ;. Other special characters (like spaces) can be left unescaped, but they will be escaped when you serialize a node. When you generate the model string in e.g. an ASP page from database data you should always escape the value part.

The data is parsed into the attributes of the node. An attribute can be retrieved in three different ways:

size=x.attributes["size"]
size=x.a("size")
size=x.getAttribute("size")
The getAttribute method is the standard W3C DOM Core method, but you may prefer x.a as a shortcut.

Instead of using new Node you can also use the shortcut function: x=n(id,data)

Adding a child node

You can add a child node in two different ways:

x= new Node("x100","label:software")
xx=new Node("x101","label:BackEdit")
x.appendChild(xx)
This is the DOM Core way of adding a child node. There is also a shortcut method available
x= new Node("x100","label:software")
xx= x.c("x101","label:BackEdit")
The c(id,data) is a method of the node object. It creates a new node and appends it as a child to itself.

Building a model

You build a model in a model creation function:
function createModel() {
  x= n("x000","label:software")
  xx= x.c("x100","label:Editors")
  xxx= xx.c("x101","label:BackEdit")
  xxx= xx.c("x101","label:EasyXML")
  xx= x.c("x200","label:Databases")
  xxx= xx.c("x201","label:EasySQLite")
  return x
}
In the onload event of the document you call a main() function:
<body onload="main()">
Within the main() function we initialize the model:
var model

function main() {
  model=createModel()
}
And next we do something with the model.

Because the serialize() method creates a function name createModel() you are advised to always use that name, even if you do not use the serialize()

Dynamic loading of a model

In Internet Explorer and Mozilla (including Netscape Communicator), but not in Opera, it is possible to load a model dynamically by creating a new SCRIPT element, setting the source of the element and appending the element to the document.

function loadQuiz(pSrc) {
var se
  se=document.createElement("SCRIPT")
  se.src=pSrc
  document.firstChild.firstChild.appendChild(se)
}
The pSrc is a reference to a javascript file (*.js) that contains a unique model create function name, e.g. softwareModel. After the model create function you must include the initialization code:
nodeIndex.length=0
model=softwareModel()
You can see a working example in the janModelQuiz.html and quiz_software.js files.

Getting a node by id

You can retrieve a node by id using nodeIndex:
mynode=nodeIndex[id]

Node methods and properties

A node has several methods and properties.

id
Returns the unique identifier used when creating the node. You can change it at any time but this is not recommended.

parentNode
Returns the parent node. For the root node null is returned.

childNodes
Returns the collection of child nodes. You can retrieve the length with:

L= mynode.childNodes.length
And iterate over the child node collection with:
L= mynode.childNodes.length
  for (i=0;i<L;i++) {
    mychildnode=mynode.childNodes[i]
  }

attributes
Returns the attributes collection:

price=mynode.attributes["price"]

getAtrribute(name)
Returns the value of a named attribute:

price=mynode.getAttribute("price")
If the named attribute does not exist then null is returned.

setAtrribute(name, value)
Sets the value of a named attribute:

mynode.setAttribute("price",123)
If the attribute does not exist it is automatically added.

appendChild(pNode)
Appends pNode as child node:

mychild= new Node("x345","label:car")
mynode.appendchild(mychild)

removeChild(pNode)
Removes the child node pNode:

mynode.removeChild(mychild)

hasChildNodes()
Returns true when the node has child nodes, otherwise returns false:

if (mynode.hasChildNodes() ) {
}

firstChild()
Returns the first child if any otherwise returns null:

mychild=mynode.firstChild()

lastChild()
Returns the last child if any otherwise returns null:

mychild=mynode.lastChild()

previousSibling()
Returns the previous sibling of the node if any, otherwise returns null.:

mynode=mynode.previousSibling()

nextSibling()
Returns the next sibling of the node if any, otherwise returns null.:

mynode=mynode.nextSibling()

serialize()
Serializes a node to a function createModel() definition.
This allows for client-server exchange of a model. Server side you serialize the model and insert it into a page.
Client side you serialize the model and assign it to e.g. a hidden form field in escaped form. Although you can serialize any node, you most likely will serialize the root node to obtain the complete model.

document.jan.model.value=escape(model.serialize())

With Server side ASP you unescape:

modelString=unescape(request.form("model"))
buildModel(modelString)

In the javascript section of your ASP page you can use the javascript eval() function:


<script language="javascript" runat="server">
var model
  function buildModel(pString) {
    eval(modelString)
    model=CreateModel()
  }
</script>