// mozXPath [http://km0ti0n.blunted.co.uk/mozxpath/] km0ti0n@gmail.com
// Code licensed under Creative Commons Attribution-ShareAlike License 
// http://creativecommons.org/licenses/by-sa/2.5/


//-- Expand the dom model in firefox etc to mimic selectnodes and selectsinglenode functions

if( document.implementation.hasFeature("XPath", "3.0") )
{
	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;
	}
	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;
		}
	}

	Element.prototype.selectNodes = function(cXPathString)
	{
		if(this.ownerDocument.selectNodes)
		{
			return this.ownerDocument.selectNodes(cXPathString, this);
		}
		else{throw "For XML Elements Only";}
	}

	Element.prototype.selectSingleNode = function(cXPathString)
	{	
		if(this.ownerDocument.selectSingleNode)
		{
			return this.ownerDocument.selectSingleNode(cXPathString, this);
		}
		else{throw "For XML Elements Only";}
	}

}

function replaceDOMChildren(xmlNodeList, parent)
{
    removeChildren(parent);
    copyXMLNodeListToDom(xmlNodeList, parent);
}

function removeChildren(parent)
{
    var children = getChildren(parent);
    if (children)
    {
        var childIdx = children.length - 1;
        while (childIdx>=0)
        {
            parent.removeChild(children[childIdx]);
            childIdx--;
        }
    }
}

function copyXMLNodeListToDom(xmlNodeList, parent)
{
    if (xmlNodeList) {
        var fragment = document.createDocumentFragment();
        for (Idx=0; Idx < xmlNodeList.length; Idx++) {
            copyXMLNodeToDocumentFragment(xmlNodeList[Idx], fragment);
        }
        parent.appendChild(fragment);
    }
}

function copyXMLNodeToDocumentFragment(xmlNode, fragment)
{
    if (xmlNode)
    {
        var element = copyXMLNodeToDomElement(xmlNode);
        fragment.appendChild(element);
    }
}

function copyXMLNodeToDomElement(xmlNode)
{
        var element = null;

         //RN - This now works for IE, but not FireFox.  According to various articles, the code within the catch is supposed to be for FireFox, but when I debugged,
         //Firefox appeared to be using the first method and not throwing an error!

        //try{
        //  element = document.createElement(xmlNode.xml);
        //}catch(err){
        //  element = document.createElement(xmlNode.tagName);
        //}
        
        //DA - Use object detection instead of the try catch method above to determine what to use for which browser if = IE else = firefox etc.
        if (xmlNode.xml) {
            element = document.createElement(xmlNode.xml);
        } else {
            element = document.createElement(xmlNode.tagName);
        }
              
        var attributes = xmlNode.attributes;
        if (attributes)
        {
            var attributeIdx = 0;
            for (attributeIdx=0; attributeIdx < attributes.length; attributeIdx++)
            {
                var attribute = attributes[attributeIdx];

                switch (attribute.name.toLowerCase())
                {
                    case "id":              {       element.id = attribute.value;                       }   break;
                    case "class":           {       element.className = attribute.value;                }   break;
                    case "style":           {       populateElementStyle(element, attribute.value);     }   break;
                    case "name":            {       element.setAttribute('name',attribute.value);       }   break;
                    //case "type":            {       element.setAttribute('type',attribute.value);       }   break;
                    case "type": 
                        {
                            try {
                                element.setAttribute('type', attribute.value);  //Rest of the browsers
                            } catch (err) {
                                element.type = attribute.value;     // IE8 doesnt allow 'type' to be get or set via getAttribute or setAttribute, but can be set like this fine.
                            }
                        } break;                     
                    default:
                    {
                        if (!populateElementEvent(element, attribute.name, attribute.value))
                        {
                            element.setAttribute(attribute.name, attribute.value);
                        }
                    }              
                }
            }
        }
        
        var children = getChildren(xmlNode);
        if (children)
        {
            var childIdx;
            for (childIdx=0; childIdx<children.length; childIdx++)
            {
                var nextChild = children[childIdx];
			    if(nextChild.nodeType == 3) //(nextChild.nodeName=='#text')
			    {
//			        element.innerText = nextChild.nodeValue;
			        element.appendChild(document.createTextNode(nextChild.nodeValue));
                }
                else
                {
                    element.appendChild(copyXMLNodeToDomElement(nextChild));
                }
            }
        }
        return element;
}

/*
function Evaluate(code)
{
    eval(code);
}
*/
function populateElementEvent(element, name, value)
{
    var handled = true;
    switch (name.toLowerCase())
    {
        case "onabort":                 {   element.onabort = getFunction(value);              } break;
        case "onactivate":              {   element.onactivate = getFunction(value);           } break;
        case "onafterprint":            {   element.onafterprint = getFunction(value);         } break;
        case "onafterupdate":           {   element.onafterupdate = getFunction(value);        } break;
        case "onbeforeactivate":        {   element.onbeforeactivate = getFunction(value);     } break;
        case "onbeforecopy":            {   element.onbeforecopy = getFunction(value);         } break;
        case "onbeforecut":             {   element.onbeforecut = getFunction(value);          } break;
        case "onbeforedeactivate":      {   element.onbeforedeactivate = getFunction(value);   } break;
        case "onbeforeeditfocus":       {   element.onbeforeeditfocus = getFunction(value);    } break;
        case "onbeforepaste":           {   element.onbeforepaste = getFunction(value);        } break;
        case "onbeforeprint":           {   element.onbeforeprint = getFunction(value);        } break;
        case "onbeforeunload":          {   element.onbeforeunload = getFunction(value);       } break;
        case "onbeforeupdate":          {   element.onbeforeupdate = getFunction(value);       } break;
        case "onblur":                  {   element.onblur = getFunction(value);               } break;
        case "onbounce":                {   element.onbounce = getFunction(value);             } break;
        case "oncellchange":            {   element.oncellchange = getFunction(value);         } break;
        case "onchange":                {   element.onchange = getFunction(value);             } break;
        case "onclick":                 {   element.onclick = getFunction(value);              } break;
        case "oncontextmenu":           {   element.oncontextmenu = getFunction(value);        } break;
        case "oncontrolselect":         {   element.oncontrolselect = getFunction(value);      } break;
        case "oncopy":                  {   element.oncopy = getFunction(value);               } break;
        case "oncut":                   {   element.oncut = getFunction(value);                } break;
        case "ondataavailable":         {   element.ondataavailable = getFunction(value);      } break;
        case "ondatasetchanged":        {   element.ondatasetchanged = getFunction(value);     } break;
        case "ondatasetcomplete":       {   element.ondatasetcomplete = getFunction(value);    } break;
        case "ondblclick":              {   element.ondblclick = getFunction(value);           } break;
        case "ondeactivate":            {   element.ondeactivate = getFunction(value);         } break;
        case "ondrag":                  {   element.ondrag = getFunction(value);               } break;
        case "ondragend":               {   element.ondragend = getFunction(value);            } break;
        case "ondragenter":             {   element.ondragenter = getFunction(value);          } break;
        case "ondragleave":             {   element.ondragleave = getFunction(value);          } break;
        case "ondragover":              {   element.ondragover = getFunction(value);           } break;
        case "ondragstart":             {   element.ondragstart = getFunction(value);          } break;
        case "ondrop":                  {   element.ondrop = getFunction(value);               } break;
        case "onerror":                 {   element.onerror = getFunction(value);              } break;
        case "onerrorupdate":           {   element.onerrorupdate = getFunction(value);        } break;
        case "onfilterchange":          {   element.onfilterchange = getFunction(value);       } break;
        case "onfinish":                {   element.onfinish = getFunction(value);             } break;
        case "onfocus":                 {   element.onfocus = getFunction(value);              } break;
        case "onfocusin":               {   element.onfocusin = getFunction(value);            } break;
        case "onfocusout":              {   element.onfocusout = getFunction(value);           } break;
        case "onhelp":                  {   element.onhelp = getFunction(value);               } break;
        case "onkeydown":               {   element.onkeydown = getFunction(value);            } break;
        case "onkeypress":              {   element.onkeypress = getFunction(value);           } break;
        case "onkeyup":                 {   element.onkeyup = getFunction(value);              } break;
        case "onlayoutcomplete":        {   element.onlayoutcomplete = getFunction(value);     } break;
        case "onload":                  {   element.onload = getFunction(value);               } break;
        case "onlosecapture":           {   element.onlosecapture = getFunction(value);        } break;
        case "onmousedown":             {   element.onmousedown = getFunction(value);          } break;
        case "onmouseenter":            {   element.onmouseenter = getFunction(value);         } break;
        case "onmouseleave":            {   element.onmouseleave = getFunction(value);         } break;
        case "onmousemove":             {   element.onmousemove = getFunction(value);          } break;
        case "onmouseout":              {   element.onmouseout = getFunction(value);           } break;
        case "onmouseover":             {   element.onmouseover = getFunction(value);          } break;
        case "onmouseup":               {   element.onmouseup = getFunction(value);            } break;
        case "onmousewheel":            {   element.onmousewheel = getFunction(value);         } break;
        case "onmove":                  {   element.onmove = getFunction(value);               } break;
        case "onmoveend":               {   element.onmoveend = getFunction(value);            } break;
        case "onmovestart":             {   element.onmovestart = getFunction(value);          } break;
        case "onpaste":                 {   element.onpaste = getFunction(value);              } break;
        case "onpropertychange":        {   element.onpropertychange = getFunction(value);     } break;
        case "onreadystatechange":      {   element.onreadystatechange = getFunction(value);   } break;
        case "onreset":                 {   element.onreset = getFunction(value);              } break;
        case "onresize":                {   element.onresize = getFunction(value);             } break;
        case "onresizeend":             {   element.onresizeend = getFunction(value);          } break;
        case "onresizestart":           {   element.onresizestart = getFunction(value);        } break;
        case "onrowenter":              {   element.onrowenter = getFunction(value);           } break;
        case "onrowexit":               {   element.onrowexit = getFunction(value);            } break;
        case "onrowsdelete":            {   element.onrowsdelete = getFunction(value);         } break;
        case "onrowsinserted":          {   element.onrowsinserted = getFunction(value);       } break;
        case "onscroll":                {   element.onscroll = getFunction(value);             } break;
        case "onselect":                {   element.onselect = getFunction(value);             } break;
        case "onselectionchange":       {   element.onselectionchange = getFunction(value);    } break;
        case "onselectstart":           {   element.onselectstart = getFunction(value);        } break;
        case "onstart":                 {   element.onstart = getFunction(value);              } break;
        case "onstop":                  {   element.onstop = getFunction(value);               } break;
        case "onsubmit":                {   element.onsubmit = getFunction(value);             } break;
        case "onunload":                {   element.onunload = getFunction(value);             } break;
        
        default:                        {   handled = false;                                    } break;
    }
    return handled;
}

var dynamicFunctionCache;
function getFunction(value)
{
    var Result;
    if (!dynamicFunctionCache)
    {
        dynamicFunctionCache = new Object();
    }
    Result = dynamicFunctionCache[value];
    if (!Result)
    {
        Result = new Function(value);
        dynamicFunctionCache[value] = Result;
    }
    return Result;
}

function populateElementStyle(element, styleValue)
{
    var styleComponents = styleValue.split(";");
    var numStyleComponents = styleComponents.length;
    var styleComponentIdx;
    
    for (styleComponentIdx = 0; styleComponentIdx < numStyleComponents; styleComponentIdx++)
    {
        var styleComponent = styleComponents[styleComponentIdx];
        if (styleComponent)
        {
            var parts = styleComponent.split(":");
            if (parts && parts.length == 2)
            {
                var name = trim(parts[0]);
                var value = trim(parts[1]);
                if (name.length > 0)
                {
                    switch (name.toLowerCase())
                    {
                        case "background":                  {   element.style.background = value;                       } break;
                        case "background-attachment":       {   element.style.backgroundAttachment = value;             } break;
                        case "background-color":            {   element.style.backgroundColor = value;                  } break;
                        case "background-image":            {   element.style.backgroundImage = value;                  } break;
                        case "background-position":         {   element.style.backgroundPosition = value;               } break;
                        case "background-position-x":       {   element.style.backgroundPositionX = value;              } break;
                        case "background-position-y":       {   element.style.backgroundPositionY = value;              } break;
                        case "background-repeat":           {   element.style.backgroundRepeat = value;                 } break;
                        case "behaviour":                   {   element.style.behaviour = value;                        } break;
                        case "border":                      {   element.style.border = value;                           } break;
                        case "border-bottom":               {   element.style.borderBottom = value;                     } break;
                        case "border-bottom-color":         {   element.style.borderBottomColor = value;                } break;
                        case "border-bottom-style":         {   element.style.borderBottomStyle = value;                } break;
                        case "border-bottom-width":         {   element.style.borderBottomWidth = value;                } break;
                        case "border-color":                {   element.style.borderColor = value;                      } break;
                        case "border-left":                 {   element.style.borderBottom = value;                     } break;
                        case "border-left-color":           {   element.style.borderLeftColor = value;                  } break;
                        case "border-left-style":           {   element.style.borderLeftStyle = value;                  } break;
                        case "border-left-width":           {   element.style.borderLeftWidth = value;                  } break;
                        case "border-right":                {   element.style.borderBottom = value;                     } break;
                        case "border-right-color":          {   element.style.borderRightColor = value;                 } break;
                        case "border-right-style":          {   element.style.borderRightStyle = value;                 } break;
                        case "border-right-width":          {   element.style.borderRightWidth = value;                 } break;
                        case "border-style":                {   element.style.borderStyle = value;                      } break;
                        case "border-top":                  {   element.style.borderBottom = value;                     } break;
                        case "border-top-color":            {   element.style.borderTopColor = value;                   } break;
                        case "border-top-style":            {   element.style.borderTopStyle = value;                   } break;
                        case "border-top-width":            {   element.style.borderTopWidth = value;                   } break;
                        case "bottom":                      {   element.style.bottom = value;                           } break;
                        case "clear":                       {   element.style.clear = value;                            } break;
                        case "clip":                        {   element.style.clip = value;                             } break;
                        case "color":                       {   element.style.color = value;                            } break;
                        case "cursor":                      {   element.style.cursor = value;                           } break;
                        case "direction":                   {   element.style.direction = value;                        } break;
                        case "display":                     {   element.style.display = value;                          } break;
                        case "filter":                      {   element.style.filter = value;                           } break;
                        case "font":                        {   element.style.font = value;                             } break;
                        case "font-family":                 {   element.style.fontFamily = value;                       } break;
                        case "font-size":                   {   element.style.fontSize = value;                         } break;
                        case "font-style":                  {   element.style.fontStyle = value;                        } break;
                        case "font-variant":                {   element.style.fontVariant = value;                      } break;
                        case "font-weight":                 {   element.style.fontWeight = value;                       } break;
                        case "height":                      {   element.style.height = value;                           } break;
                        case "layout-flow":                 {   element.style.layoutFlow = value;                       } break;
                        case "layout-grid":                 {   element.style.layoutGrid = value;                       } break;
                        case "layout-grid-char":            {   element.style.layoutGridChar = value;                   } break;
                        case "layout-grid-line":            {   element.style.layoutGridLine = value;                   } break;
                        case "layout-grid-mode":            {   element.style.layoutGridMode = value;                   } break;
                        case "layout-grid-type":            {   element.style.layoutGridType = value;                   } break;
                        case "left":                        {   element.style.left = value;                             } break;
                        case "letter-spacing":              {   element.style.letterSpacing = value;                    } break;
                        case "line-break":                  {   element.style.lineBreak = value;                        } break;
                        case "margin":                      {   element.style.margin = value;                           } break;
                        case "margin-left":                 {   element.style.marginLeft = value;                       } break;
                        case "margin-bottom":               {   element.style.marginBottom = value;                     } break;
                        case "margin-right":                {   element.style.marginRight = value;                      } break;
                        case "margin-top":                  {   element.style.marginTop = value;                        } break;
                        case "max-height":                  {   element.style.maxHeight = value;                        } break;
                        case "max-width":                   {   element.style.maxWidth = value;                         } break;
                        case "min-height":                  {   element.style.minHeight = value;                        } break;
                        case "min-width":                   {   element.style.minWidth = value;                         } break;
                        case "overflow":                    {   element.style.overflow = value;                         } break;
                        case "overflow-x":                  {   element.style.overflowX = value;                        } break;
                        case "overflow-y":                  {   element.style.overflowY = value;                        } break;
                        case "padding":                     {   element.style.padding = value;                          } break;
                        case "padding-left":                {   element.style.paddingLeft = value;                      } break;
                        case "padding-bottom":              {   element.style.paddingBottom = value;                    } break;
                        case "padding-right":               {   element.style.paddingRight = value;                     } break;
                        case "padding-top":                 {   element.style.paddingTop = value;                       } break;
                        case "page-break-after":            {   element.style.pageBreakAfter = value;                   } break;
                        case "page-break-before":           {   element.style.pageBreakBefore = value;                  } break;
                        case "position":                    {   element.style.position = value;                         } break; 
                        case "right":                       {   element.style.right = value;                            } break; 
                        case "scrollbar-3dlight-color":     {   element.style.scrollbar3dLightColor = value;            } break; 
                        case "scrollbar-arrow-color":       {   element.style.scrollbarArrowColor = value;              } break; 
                        case "scrollbar-base-color":        {   element.style.scrollbarBaseColor = value;               } break; 
                        case "scrollbar-darkshadow-color":  {   element.style.scrollbarDarkShadowColor = value;         } break; 
                        case "scrollbar-face-color":        {   element.style.scrollbarFaceColor = value;               } break; 
                        case "scrollbar-highlight-color":   {   element.style.scrollbarHighlightColor = value;          } break; 
                        case "scrollbar-shadow-color":      {   element.style.scrollbarShadowColor = value;             } break; 
                        case "scrollbar-track-color":       {   element.style.scrollbarTrackColor = value;              } break; 
                        case "float":                       {   element.style.styleFloat = value;                       } break; 
                        case "text-align":                  {   element.style.textAlign = value;                        } break; 
                        case "text-align-last":             {   element.style.textAlignLast = value;                    } break; 
                        case "text-autospace":              {   element.style.textAutospace = value;                    } break; 
                        case "text-decoration":             {   element.style.textDecoration = value;                   } break; 
                        case "text-indent":                 {   element.style.textIndent = value;                       } break; 
                        case "text-justify":                {   element.style.textJustify = value;                      } break; 
                        case "text-kashida-space":          {   element.style.textKashidaSpace = value;                 } break; 
                        case "text-overflow":               {   element.style.textOverflow = value;                     } break; 
                        case "text-transform":              {   element.style.textTransform = value;                    } break; 
                        case "text-underline-position":     {   element.style.textUnderlinePosition = value;            } break; 
                        case "top":                         {   element.style.top = value;                              } break;
                        case "unicode-bidi":                {   element.style.unicodeBidi = value;                      } break; 
                        case "visibility":                  {   element.style.visibility = value;                       } break; 
                        case "whiteSpace":                  {   element.style.whiteSpace = value;                       } break; 
                        case "width":                       {   element.style.width = value;                            } break;
                        case "word-break":                  {   element.style.wordBreak = value;                        } break;
                        case "word-spacing":                {   element.style.wordSpacing = value;                      } break;
                        case "word-wrap":                   {   element.style.wordWrap = value;                         } break;
                        case "writing-mode":                {   element.style.writingMode = value;                      } break;
                        case "z-index":                     {   element.style.zIndex = value;                           } break;
                        case "zoom":                        {   element.style.zoom = value;                             } break;
                    }
                }
            }
        }
    }
}

function trim(strInput)
{
	var strResult;
	var objRegex = new RegExp("(^\\s+)|(\\s+$)");
	strResult = strInput.replace(objRegex, "");
	return strResult;
}



function getXMLNodeListSerialisation(xmlNodeList) {
    var result = "";
    if (xmlNodeList) {
        for (Idx=0; Idx < xmlNodeList.length; Idx++) {
            xmlNode = xmlNodeList[Idx];
            result = result+getXMLNodeSerialisation(xmlNode);
        }
    }
    return result;
}

function getXMLNodeSerialisation(xmlNode) {
 
  var text = "hello";
  try {
    // Gecko-based browsers, Safari, Opera.
    var serializer = new XMLSerializer();
    text = serializer.serializeToString(xmlNode);
  }
  catch (e) {
    try {
      // Internet Explorer.
      text = xmlNode.xml;
    }
    catch (e) {}
  }
  return text;
}

//function getXmlNodeValue(xmlNode){
//    return try.these(
//        function() {return xmlNode.text;},
//        function() {return xmlNode.textContent;}
//        );
//}

function setSelectInnerHTML(selectObject, xmlNodeList)
{
    try {
        for (optionIdx = selectObject.options.length-1; optionIdx>=0; optionIdx--)
        {
            selectObject.options[optionIdx] = null;
//            selectObject.options.remove(optionIdx);
        }
        for (nodeIdx = 0; nodeIdx<xmlNodeList.length; nodeIdx++) {
            xmlNode = xmlNodeList[nodeIdx];
            if (xmlNode.nodeType != 3) {            //-- not text node
                newOption = new Option();
                var ValueAttribute = xmlNode.getAttribute("value");          // get this from attributes
                var SelectedAttribute = xmlNode.getAttribute("selected");
                newOptionValue = ValueAttribute;
                newOptionSelected = false;
                if (SelectedAttribute) {
                    newOptionSelected = true;
                }

                if (xmlNode.text)
                {
                    newOptionText = xmlNode.text;
                }
                else
                {
                    newOptionText = xmlNode.textContent;
                }
                
                selectObject.options.add( new Option(newOptionText, newOptionValue, newOptionSelected), nodeIdx );
                
                if (newOptionSelected)
                {
                    selectObject.options.selectedIndex = nodeIdx;
                }
            }           
        }
    } catch (e) {
        alert(e.message);
        selectObject.innerHTML = getXMLNodeListSerialisation(xmlNodeList)
    }
}

function getParent(node)
{
    var Parent = null;
    if (node.parentElement)
    {
        Parent = node.parentElement;
    }
    else 
    {
        Parent = node.parentNode;
    }
    return Parent;
}

function getChildren(node)
{
    var children = null;
    if (node.children)
    {
        children = node.children;
    }
    else if (node.childNodes)
    {
        children = node.childNodes;
    }
    return children;
}

function isTextNode(node)
{
    return node.nodeType==3;
}

function addEventHandler(element, type, handler)
{    
    if (element.addEventListener) 
    {        
        element.addEventListener(type, handler, false);    
    } 
    else if (element.attachEvent) 
    {        
        element.attachEvent("on" + type, handler);    
    }
};


function getMouseX(e)
{ 
    var mouseX = 0;
    if (!e) e = window.event;
    if (!e) e = event;
    if (e)
    { 
        mouseX = document.all ? (e.clientX + document.body.scrollLeft) : e.pageX;
    }
    return mouseX;
};

function resolveEvent(e)
{
    if (!e) e = window.event;
    if (!e) e = event;
    return e;
};

function resolveEventTarget(ev)
{
	var target   = ev.target || ev.srcElement;
	return target;
};

function submitForm(element)
{
    if (element)
    {
        var pagerForm = findEnclosingForm(element);
        if (pagerForm)
        {
            pagerForm.submit();
        }
    }
}

function setInformationElementValue(informationElementID, value)
{
   var informationElement = document.getElementById(informationElementID);
    if (informationElement)
    {
        informationElement.value = value;
    }
}


function findEnclosingForm(eventElement)
{
    return findEnclosingElement(eventElement, "FORM");
}

function findEnclosingElement(element, tagName)
{
    var result;
    var parent = getParent(element)
    if (parent)
    {
        if (parent.tagName == tagName)
        {
            result = parent;
        } 
        else
        {
            result = findEnclosingElement(parent, tagName);
        }
    }
    return result;
}


