kekule
Version:
Open source JavaScript toolkit for chemoinformatics
354 lines (330 loc) • 11.2 kB
JavaScript
/**
* @fileoverview
* Utilities to handle XML and JSON data.
* @author Partridge Jiang
*/
(function($root){
;
var
/**
* Class to handle JSON file and data.
* @class JsonUtility
*/
JsonUtility = {
/** Parse JSON object from text, return object. */
parse: function(text)
{
return JSON.parse(text);
},
/** Serialize a object to JSON string.
* NOTE: this function only works in browser support JSON.stringify.
* @param {Object} srcObj Source JavaScript object.
* @param {Object} options Options for serializing:
* {
* prettyPrint: {Bool} whether format output JSON or use a compact one,
* indentSpaces: {Int} indent space count for formatting
* }
* @returns {String} JSON string.
*/
serializeToStr: function(srcObj, options)
{
//return Object.toJSON(srcObj);
if (options && options.prettyPrint)
return JSON.stringify(srcObj, null, options.indentSpaces || 2);
else
return JSON.stringify(srcObj);
}
};
var
/**
* Class to handle XML file and data.
* This part is partly borrowed from Javascript - The Definitive Guide, 5th Ed
* and add some code of myself, mainly for Safari (do not support xmldoc.load)
* and including file handle
* @class XmlUtility
*/
XmlUtility = {
// appoint explicit DOMParser/DOMImplementation/XMLSerializer classes
DOM_PARSER: null,
DOM_IMPLEMENTATION: null,
XML_SERIALIZER: null,
/** @private */
DEF_INCLUDE_TAG_NAME: 'include',
/** @private */
DEF_INCLUDE_SRC_ATTRIB: 'src',
/** @private */
DEF_LOAD_TIMEOUT: 20000,
/** @private */
DEF_BYPASS_ROOT_ELEM: true,
/** @private */
DEF_SERIALIZE_TO_JSCODE_VARNAME: '__xmlStr__',
/** @private */
FILE_EXT_XML: '.xml',
/** @private */
FILE_EXT_XML_JS_WRAPPER: '.xmljs',
/** Create a new XML document */
newDocument: function(rootTagName, namespaceURL)
{
if (!rootTagName) rootTagName = "";
if (!namespaceURL) namespaceURL = "";
if (XmlUtility.DOM_IMPLEMENTATION) // node enviroment
{
var doc = (new XmlUtility.DOM_IMPLEMENTATION()).createDocument(namespaceURL, rootTagName, null);
return doc;
}
else if (typeof(document) !== 'undefined') // is in web browser environment
{
if (document.implementation && document.implementation.createDocument)
{
// This is the W3C standard way to do it
var doc = document.implementation.createDocument(namespaceURL,
rootTagName, null);
//console.log('Here: ', doc);
return doc;
/*
if (doc.load)
return doc;
else // Safari adn Google Chrome do not support xmldoc.load
{
var xmlhttp = new XMLHttpRequest();
doc = xmlhttp;
return doc;
}
*/
}
else if (typeof(ActiveXObject) !== "undefined")
{ // This is the IE way to do it
// Create an empty document as an ActiveX object
// If there is no root element, this is all we have to do
var doc = new ActiveXObject("MSXML2.DOMDocument");
// If there is a root tag, initialize the document
if (rootTagName)
{
// Look for a namespace prefix
var prefix = "";
var tagname = rootTagName;
var p = rootTagName.indexOf(':');
if (p != -1)
{
prefix = rootTagName.substring(0, p);
tagname = rootTagName.substring(p + 1);
}
/*
// If we have a namespace, we must have a namespace prefix
// If we don't have a namespace, we discard any prefix
if (namespaceURL) {
if (!prefix) prefix = "a0"; // What Firefox uses
}
else prefix = "";
*/
// Create the root element (with optional namespace) as a
// string of text
var text = "<" + (prefix ? (prefix + ":") : "") + tagname +
(namespaceURL ?
((prefix ? " xmlns:" : " xmlns") + prefix + '="' + namespaceURL + '"')
: "") +
"/>";
// And parse that text into the empty document
doc.loadXML(text);
}
return doc;
}
}
},
/** parse Xml DOM from text, return XMLDocument */
parse: function(text)
{
if (XmlUtility.DOM_PARSER)
return (new XmlUtility.DOM_PARSER()).parseFromString(text, "application/xml");
else if (typeof(document) !== 'undefined') // is in web browser environment
{
if (typeof DOMParser != "undefined")
{
// Mozilla Firefox, Google Chrome and related browsers
return (new DOMParser()).parseFromString(text, "application/xml");
}
else if (typeof ActiveXObject != "undefined")
{
// Internet Explorer.
var doc = XmlUtility.newDocument(); // Create an empty document
doc.loadXML(text); // Parse text into it
return doc; // Return it
}
else
{
// As a last resort, try loading the document from a data: URL
// This is supposed to work in Safari. Thanks to Manos Batsis and
// his Sarissa library (sarissa.sourceforge.net) for this technique.
var url = "data:text/xml;charset=utf-8," + encodeURIComponent(text);
var request = new XMLHttpRequest();
request.open("GET", url, false);
request.send(null);
return request.responseXML;
}
}
},
/** load XML document from url. */
load: function(url, callback, options) // return XMLDocument
// options: object include fields:
// timeout: Integer, in ms
{
// check file ext first, if is a Xml-Js-Wrapper, call corresponding method
/*
if (url.lastIndexOf(XmlUtility.FILE_EXT_XML_JS_WRAPPER) === url.length - XmlUtility.FILE_EXT_XML_JS_WRAPPER.length) // end with this ext
return XmlUtility.loadHelper.loadJsWrapper(url, callback, options);
if (!options)
options = {disableInclude: false};
if (!options.disableInclude)
return XmlUtility.loadHelper.loadAndHandleIncludeElement(url, callback, options);
else
return XmlUtility.loadHelper.loadSimple(url, callback, options.timeout);
*/
return XmlUtility.loadHelper.loadSimple(url, callback, (options || {}).timeout);
},
/** @private */
loadHelper: {
// TODO: this method is unable to be used in Node.js environment
/////////////////////////////////////////////////////////////////////
// Internal method for load to use
///////////////
/** @private */
loadSimple: function(url, callback, loadTimeout)
// return XMLDocument, if assigned callback, it runs async
// callback(xmlDoc, isloadSuccess)
// this function will try use XHR method in IE,
// as IE can not load local XML file via XHR
{
var async = (callback != null);
if ((loadTimeout === null) || (loadTimeout === undefined))
loadTimeout = XmlUtility.DEF_LOAD_TIMEOUT;
if (!(document.implementation && document.implementation.createDocument)) // ie
{
return XmlUtility.loadHelper.loadSimpleViaDoc(url, callback);
}
else // other browse
{
var req = new XMLHttpRequest();
var timeoutHandle = null;
if (loadTimeout)
timeoutHandle = setTimeout(function() // timeout, load failed
{
runCallBack(null, false);
}, loadTimeout);
/** @ignore */
var runCallBack = function(xmldoc, isSuccess)
{
if (timeoutHandle) // clear timeout handler
clearTimeout(timeoutHandle);
if (callback)
callback(xmldoc, isSuccess);
};
if (async)
{
/** @ignore */
req.onreadystatechange = function(){
if (req.readyState == 4)
{
//if (req.status == 200)
var xmldoc = req.responseXML;
if (xmldoc && xmldoc.documentElement) // check documentElement, otherwise opera will cause error
{
runCallBack(xmldoc, true);
}
else
runCallBack(null, false);
}
};
}
try
{
//console.log('open request', req);
req.open('get', url, async);
req.send(null);
}
catch(e)
{
runCallBack(null, false); // load failed
}
var doc = req.responseXML;
if (doc && doc.documentElement)
return doc;
else
return null;
}
},
/** @private */
loadSimpleViaDoc: function(url, callback) // use for IE
{
var tagInitial = 'dummy_dummy_dummy_dummy';
var async = (callback != null);
// Create a new document with the previously defined function
var xmldoc = XmlUtility.newDocument(tagInitial);
xmldoc.async = async;
if (async)
{
/** @ignore */
xmldoc.onreadystatechange = function( ) {
if (xmldoc.readyState == 4)
{
if ((!xmldoc.documentElement) || (xmldoc.documentElement.tag == tagInitial))
callback(xmldoc, false);
else
callback(xmldoc, true);
}
};
}
xmldoc.load(url); // Load and parse
return xmldoc; // Return the document
}
},
/**
* Serialize a XML node content to string.
* @param {Object} node
* @param {Object} options Options for serializing:
* {
* prettyPrint: {Bool} whether format output JSON or use a compact one,
* }
*/
serializeNode: function(node, options)
{
if (options && options.prettyPrint)
{
return XmlUtility.serializeNodePretty(node);
}
if (XmlUtility.XML_SERIALIZER)
return (new XmlUtility.XML_SERIALIZER()).serializeToString(node);
else if (typeof XMLSerializer != "undefined")
return (new XMLSerializer( )).serializeToString(node);
else if (node.xml) return node.xml;
else throw "XML.serialize is not supported or can't serialize " + node;
},
/** Try serialize node content to string in pretty mode. Not always possible in some browser. */
serializeNodePretty: function(node)
{
try
{
if (XmlUtility.XML_SERIALIZER)
return (new XmlUtility.XML_SERIALIZER()).serializeToString(node).toXMLString();
else
return new XMLSerializer().serializeToString(node).toXMLString(); // firefox
// TODO: E4X is deprecated in firefox 21, so need other methods
}
catch(e)
{
return XmlUtility.serializeNode(node);
}
},
// utils functions
/** Get url of a XML document */
getXmlDocUrl: function(xmlDoc)
{
return xmlDoc.url // IE
|| xmlDoc.documentURI // firefox
|| xmlDoc.URL // Safari
|| xmlDoc.location; // Opera
}
};
// export those two util class to DataType namespace
DataType.JsonUtility = JsonUtility;
DataType.XmlUtility = XmlUtility;
})(this);