| home / programming / javascript / domwrapper | [previous] |
|
|
We've now come to the last part of our project, error handling. As I'm sure you can guess, IE
and Mozilla do it two different ways. IE's DOM Document has a parseError attribute that
is filled with an error code if an error occurs. However, an error in the DOM Document
does not throw a JavaScript error, so execution does not stop. In Mozilla, any error
inside the load() method is thrown as a JavaScript error, and execution stops cold. So
once again, we will make Mozilla more like IE and create a parseError attribute.
The parseError attribute starts out as 0, which indicates that there
is no error. Whenever someone wants to check if there has been an error, a simple check to see if
the parseError attribute is not equal to 0 does the trick. So let's start
out by adding our parseError attribute with a default value of 0:
Document.prototype.parseError = 0;
Next, we will add a try...catch block in our _Document_load() method.
Because it would be impossible to map all of the errors in Mozilla to their IE counterparts, we'll
just set the parseError attribute to –9999999 to indicate that there is
an error (we will also change the readyState attribute to indicate the loading action
is done). Important thing to note: we must set the parseError attribute to 0
every time the load() method is called, because it is essentially wiping the slate
clean for the Document object:
function _Document_load(strURL) {
//set the parseError to 0
this.parseError = 0;
//change the readyState
changeReadyState(this, 1)
//watch for errors
try (
//call the original load method
this.__load__(strURL);
} catch (objException) {
//set the parseError attribute
this.parseError = -9999999;
//set readyState to 4, we are done loading
changeReadyState(this, 4);
} // End: try...catch
}
And here's another interesting wrinkle: if an error is caused while parsing, Mozilla doesn't throw an exception. Instead, it creates an XML string containing the details of the error, for example:
<parsererror xmlns="http://www.w3.org/1999/xhtml">XML Parsing Error: mismatched tag. Expected: </root>. Location: file:///C:/DOCUME~1/Nicholas/MYDOCU~1/MYARTI~1/USINGT~1/Example/Invalid.xml Line Number 3, Column 37:<sourcetext> <root image="root.gif">My Root</boot> ------------------------------------^</sourcetext></parsererror>
So, we actually need to check for an error after the XML is loaded to see if one of these
XML error strings has been generated (or if there is no documentElement for some
reason). Because we have incredible foresight, we will create a
function called handleOnLoad() to encapsulate this process. The handleOnLoad()
function will take one parameter, the Document to check. It will also set the readyState
attribute to 4 (regardless of any errors, the loading is over):
function handleOnLoad(objDOMDocument) {
//check for a parsing error
if (!objDOMDocument.documentElement || objDOMDocument.documentElement.tagName == "parsererror")
objDOMDocument.parseError = -9999999;
//change the readyState
changeReadyState(objDOMDocument, 4);
}
Now, we need to add this into two places, the _Document_onload() function and the
loadXML() method (note that we aren't adding it to the _Document_load()
function, because we can only determine parsing errors after the XML has been loaded):
function _Document_onload() {
//handle the onload event
handleOnLoad(this);
}
//add the loadXML() method to the Document class
Document.prototype.loadXML = function(strXML) {
//change the readystate
changeReadyState(this, 1);
//create a DOMParser
var objDOMParser = new DOMParser();
//create new document from string
var objDoc = objDOMParser.parseFromString(strXML, "text/xml");
//make sure to remove all nodes from the document
while (this.hasChildNodes())
this.removeChild(this.lastChild);
//add the nodes from the new document
for (var i=0; i < objDoc.childNodes.length; i++) {
//import the node
var objImportedNode = this.importNode(objDoc.childNodes[i], true);
//append the child to the current document
this.appendChild(objImportedNode);
} //End: for
//we can't fire the onload event, so we fake it
handleOnLoad(this);
} //End: function
Now the parseError attribute should be fairly accurate for Mozilla.
After a somewhat lengthy trek, we have created our cross-browser (IE5/NS6) DOM Document wrapper. To review, you can now create a DOM Document object by doing the following:
var objDOMDocument = jsXML.createDOMDocument(strNamespaceURI, strRootTagName);
You can load an XML string into the DOM Document by doing:
objDOMDocument.loadXML("<myroot />");
You can retrieve the XML string by doing:
var strXML = objDOMDocument.xml;
To load an external XML file, we do the following:
objDOMDocument.async = false;
objDOMDocument.load("myfile.xml");
To load it asynchronously:
objDOMDocument.async = true;
objDOMDocument.load("myfile.xml");
You can set an event handler to determine when an XML file has been fully loaded by doing:
objDOMDocument.onreadystatechange = myFunction;
function myFunction() {
if (this.readyState == 4)
alert("Loaded");
}
And to check for errors, you can do the following:
if (objDOMDocument.parseError != 0)
alert("Error");
We are now ready to use a DOM Document the same way across Internet Explorer 5.0+ (Windows) and Mozilla (Mozilla or Netscape 6.1+). This example illustrates all of these uses. I ask that you try it in both browsers. There are slight differences, but the overall functionality is the same.
Nicholas C. Zakas is a user interface designer for web applications at MatrixOne, Inc. in Massachusetts. Nicholas works primarily as a client-side developer using JavaScript, DHTML, XML and XSLT. He can be reached via e-mail at nicholas@nczonline.net or at his Web site, http://www.nczonline.net.
| home / programming / javascript / domwrapper | [previous] |
Created: June 13, 2002
Revised: June 13, 2002
URL: http://webreference.com/programming/javascript/domwrapper/5.html