﻿/**
 * ess_dhtml.js V2.1
 * 此脚本为FF实现了一些IE特有的方法
 * 注意事项：本脚本似乎与prototype-1.6.0.2.js冲突，若需同时使用本脚本与prototype，则本脚本必须在prototype之前引用
 */

if (window.HTMLElement) {
	var _leafElems = ["IMG", "HR", "BR", "INPUT"];
	var leafElems = {};
	for (var i=0; i<_leafElems.length; i++) {
		leafElems[_leafElems[i]] = true;
	}
	
	function setInnerHTML(str) {
		var r = this.ownerDocument.createRange();
		r.selectNodeContents(this);
		r.deleteContents();
		var df = r.createContextualFragment(str);
		this.appendChild(df);
		
		return str;
	}
		
	function setOuterHTML(str) {
		var r = this.ownerDocument.createRange();
		r.setStartBefore(this);
		var df = r.createContextualFragment(str);
		this.parentNode.replaceChild(df, this);
		return str;
	}

	function getInnerHTML(node) {
		var str = "";
		for (var i=0; i<node.childNodes.length; i++)
			str += getOuterHTML(node.childNodes.item(i));
		return str;
	}

	function getOuterHTML(node) {
		var str = "";
		
		switch (node.nodeType) {
			case 1: // ELEMENT_NODE
				str += "<" + node.nodeName;
				for (var i=0; i<node.attributes.length; i++) {
					if (node.attributes.item(i).nodeValue != null) {
						str += " "
						str += node.attributes.item(i).nodeName;
						str += "=\"";
						str += node.attributes.item(i).nodeValue;
						str += "\"";
					}
				}

				if (node.childNodes.length == 0 && leafElems[node.nodeName])
					str += "/>";
				else {
					str += ">";
					str += getInnerHTML(node);
					str += "</" + node.nodeName + ">"
				}
				break;
					
			case 3:	//TEXT_NODE
				str += node.nodeValue;
				break;
				
			case 4: // CDATA_SECTION_NODE
				str += "<![CDATA[" + node.nodeValue + "]]>";
				break;
						
			case 5: // ENTITY_REFERENCE_NODE
				str += "&" + node.nodeName + ";"
				break;

			case 8: // COMMENT_NODE
				str += "<!--" + node.nodeValue + "-->"
				break;
		}

		return str;
	}
	
	HTMLElement.prototype.__defineSetter__("innerHTML", setInnerHTML);
	HTMLElement.prototype.__defineGetter__("innerHTML", function() {
		return getInnerHTML(this);
	});
	
	HTMLElement.prototype.__defineSetter__("outerHTML", setOuterHTML);
	HTMLElement.prototype.__defineGetter__("outerHTML", function() {
		return getOuterHTML(this);
	});
}

if (window.XMLDocument) {
	var ex;
	XMLDocument.prototype.__proto__.__defineGetter__("xml", function() {
		try {
			return new XMLSerializer().serializeToString(this);
		}
		catch (ex){
			var d = document.createElement("div");
			d.appendChild(this.cloneNode(true));
			return d.innerHTML;
		}
	});
	
	Element.prototype.__proto__.__defineGetter__("xml", function() {
		try {
			return new XMLSerializer().serializeToString(this);
		}
		catch (ex) {
			var d = document.createElement("div");
			d.appendChild(this.cloneNode(true));
			return d.innerHTML;
		}
	});
	
	XMLDocument.prototype.__proto__.__defineGetter__("text", function() {
		return this.firstChild.textContent; //用this.firstChild.nodeValue应该也可以
	});
	
	Element.prototype.__proto__.__defineGetter__("text", function() {
		return this.textContent;
	});
	
	XMLDocument.prototype.loadXML = function(xmlString) {
		var childNodes = this.childNodes;
		for (var i = childNodes.length - 1; i >= 0; i--)
			this.removeChild(childNodes[i]);

		var dp = new DOMParser();
		var newDOM = dp.parseFromString(xmlString, "text/xml");
		var newElt = this.importNode(newDOM.documentElement, true);
		this.appendChild(newElt);
	}
	
	
	if(document.implementation.hasFeature("XPath", "3.0")) {
		// prototying the XMLDocument
		XMLDocument.prototype.selectNodes = function(cXPathString, xNode)
		{
			if( !xNode ) { xNode = this; } 
			var oNSResolver = this.createNSResolver(this.documentElement)
			var aItems = this.evaluate(cXPathString, xNode, oNSResolver, XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
			var aResult = [];
			for(var i = 0; i < aItems.snapshotLength; i++)
			{
				aResult[i] = aItems.snapshotItem(i);
			}
			return aResult;
		}

		// prototying the Element
		Element.prototype.selectNodes = function(cXPathString)
		{
			if(this.ownerDocument.selectNodes)
			{
				return this.ownerDocument.selectNodes(cXPathString, this);
			}
			else
			{
				throw "selectNodes For XML Elements Only";
			}
		}
		
		// prototying the XMLDocument
		XMLDocument.prototype.selectSingleNode = function(cXPathString, xNode)
		{
			if( !xNode ) { xNode = this; } 
			var xItems = this.selectNodes(cXPathString, xNode);
			if( xItems.length > 0 )
			{
				return xItems[0];
			}
			else
			{
				return null;
			}
		}

		// prototying the Element
		Element.prototype.selectSingleNode = function(cXPathString)
		{		
			if(this.ownerDocument.selectSingleNode)
			{
				return this.ownerDocument.selectSingleNode(cXPathString, this);
			}
			else
			{
				throw "For XML Elements Only";
			}
		}
	}
}

