﻿/*@cc_on@*/

/**
 *	1) [new] XMLDocument([strXML]);
 *	
 *	creates and returns an XML document parsed from strXML
 *	if strXML is omitted, creates and returns an empty XML document
 *	strXML must be a string starting with "<";
 *		otherwise, it is considered a URI and uses the second constructor
 *	
 *	2) [new] XMLDocument(uri[, onload]);
 *	
 *	imports and returns an XML document from specified URI
 *	if onload is a function, document is imported async;
 *		once XML document is imported, onload is called with the this keyword
 *		referring to the document
 *	if onload is anything else or unspecified, document is imported sync
 */
 //note: doesn't work with Opera since Opera uses DOM3 L/S and doesn't support load()
(function () {
	//Gecko: XMLDocument is a native interface and completely overriding causes
	//	weird problems, so when overriding it, set the new XMLDocument's prototype
	//	to the old one's (happens at the end of this function)
	var $XMLDocument;
	if (window.XMLDocument) {
		$XMLDocument = XMLDocument;
	}
	//XMLDocument is already taken (by Gecko) and stored in $XMLDocument,
	//	so put the browser-specific XMLDocument creation code in $newXMLDocument
	var $newXMLDocument;
	if (document.implementation && document.implementation.createDocument) {
		$newXMLDocument = function() {
			return document.implementation.createDocument(null, null, null);
		}
	} else {
		$newXMLDocument = function() {
			return new ActiveXObject('Msxml2.DOMDocument');
		}
	}
	//Gecko's DOMParser for loading xml strings
	if (window.DOMParser)
		var dp = new DOMParser();
	//IE mem leak fix:
	//	objects that form circular references are stored in a registry,
	//	and onunload, those references are broken
	/*@
	var registry = [];
	//new Function() returns closure-less function
	var empty = new Function();
	window.attachEvent('onunload', function() {
		for (var i = 0; i < registry.length; i++) {
			var xmlDoc = registry[i];
			//onreadystatechange is set to empty closure-less function, because:
			//1) abort() calls onreadystatechange()
			//2) prevent closure-related mem leak
			xmlDoc.onreadystatechange = empty;
			//if xmlDoc is still being processed, abort() it to prevent mem leak
			if (xmlDoc.readyState != 4) {
				xmlDoc.abort();
			}
		}
	});
	@*/
	window.XMLDocument = function(uri, onload) {
		var xmlDoc;
		//if uri is not specified or null or an empty string,
		//	just return an empty XML document
		if (!uri) {
			xmlDoc = $newXMLDocument();
		//else if uri starts with '<', it is treated as a string of XML
		//	and parsed into an XML document
		} else if (uri.charAt(0) == '<') {
			//(dp is defined in the code after this function)
			if (dp) {
				//bypass loadXML() since that requires copying a document
				return dp.parseFromString(uri, 'text/xml');
			} else {
				xmlDoc = $newXMLDocument();
				xmlDoc.loadXML(uri);
				return xmlDoc;
			}
		//else uri is treated as a URI to an XML resource
		} else {
			xmlDoc = $newXMLDocument();
			//if onload is a function, load XML async,
			//	then call onload once XML is loaded
			if (onload instanceof Function) {
				//IE uses onreadystatechange, while Gecko uses onload
				/*@
				@if (1)
					xmlDoc.onreadystatechange = function() {
						if (xmlDoc.readyState != 4)
							return;
				@else
					@*/
					xmlDoc.onload = function() {
					/*@
				@end
				@*/
						if (xmlDoc.documentElement == null)
							throw new Error('"' + uri + '" does not contain a valid XML document');
						onload.call(xmlDoc);
					}
				/*@
				//IE mem leak fix
				registry.push(xmlDoc);
				@*/
			//else if onload is not specified or null, load XML sync
			} else {
				xmlDoc.async = false;
			}
			if (!xmlDoc.load(uri))
				throw new Error('"' + uri + '" does not contain a valid XML document');
		}
		return xmlDoc;
	}
	//makes the new XMLDocument the "same" as the old one
	if ($XMLDocument && $XMLDocument.prototype) {
		XMLDocument.prototype = $XMLDocument.prototype;
	}
	
	//loadXML method is NOT added to Gecko, due to inefficiency
	//use XMLDocument("xmlstring") instead
})();
