//**************************************************
//**************************************************
// file:    transformClient01.js
// name:    transformXbrowserFromDocs
// purpose: this will transform in a cross browser environment and was
//          originally created after the transformXBrowser function 
//          which was hard coded to get xsl data islands via their elementId
// returns: XML Doc Fragment (mozilla) / XML Doc IE
// params:  
//          xslDoc: w3c DOM xsl or activeX (preferably w3c level 1 xslt)
//          xmlDoc: w3c DOM xml or activeX
// date:    2008-06-14
// dev:     mcd
// date     2008-06-16: modified to avoid returning anything too complex
//              as appendChild doesn't work for IE and namespace problems
//              emerge when you attempt to make appendChild work in IE
//              see http://www.alistapart.com/articles/crossbrowserscripting
function transformXbrowserFromDocs(xslDoc, xmlDoc){    
    var xmlFrag, outputXHtmlString;
    if (window.XSLTProcessor)
    {
	    // support Mozilla/Gecko based browsers, returns an xml doc fragment	    
	    xmlFrag = transformMozilla(xslDoc, xmlDoc);
	    var xmlSerializerObject = new XMLSerializer();
        var outputXHtmlString = xmlSerializerObject.serializeToString(xmlFrag);
    }
    else if(window.ActiveXObject)
    {
	    // support Windows/ActiveX enabled browsers
	    var outputXHtmlString = xmlDoc.transformNode(xslDoc);
    }
    else
    {
        // unsupported browser
        outputXHtmlString = 'Your browser does not support client-side XSL transformations.';
    }
    return outputXHtmlString;
}

//**************************************************
//**************************************************
// name:            clientTransformXML
// purpose:         transform an xml string with a document embedded xsl document
//                  in a cross-browser manner
// returns:         xml string
// params:
//                  sXml:           a xml string
//                  xslDoc:         a textarea or xml tag doc id containing a xsl document 
// dev:             mcd
// date:            2007
// dev:             mcd
// date:            2008-09-07
// modification:    changed this function such that if the xslDocId tagname is 'textarea' 
//                  then it is cross browser.  If it is 'xml' then
//                  it is implementing a data island and is IE only.
//                  this mod allows you to change all pages that use this function, such that
//                  if you convert the data islands to textareas the transformation will still work
//                  bug watch: if the xslDoc identified in the text area contains the document function
//                  then this will fail as it doesn't handle that case yet, for those you'll need to do 
//                  more than just put the xsl doc into a text area
function clientTransformXML(sXml, xslDocId){
    var myResultXmlString = "";
    var aNode = document.getElementById(xslDocId);
    inString = aNode.nodeName;
    if (inString.toLowerCase().indexOf("textarea") != -1) {    
        //cross-browser
        //alert(sXml)
        var myXmlDoc = loadXMLDoc(sXml);
        var myXslDoc = loadXMLDoc(aNode.value);
        myResultXmlString = transformXbrowserFromDocs(myXslDoc, myXmlDoc);
    } else {
        //IE DATAISLAND    
	    try {
		    //xslDocId = "finsights_to_depthchartmsg"; //postNflDepthChartMsg02.xsl
		    var XmlDoc = new ActiveXObject("MSXML2.DOMDocument.3.0");
		    var XslDoc = document.getElementById(xslDocId).XMLDocument;
		    XmlDoc.async=false;		
		    XmlDoc.loadXML(sXml);
	    } catch (e) {
		    e.description+='>clientTransformXML';throw e;
	    }
	    myResultXmlString = XmlDoc.transformNode(XslDoc);
    }    
    return myResultXmlString;
}

//2007/02/12- when you update the function above so it accepts a xsldoc (and not a docid) then you can just
//do the first line of this function and call its parent (assuming javascript allows overrides)
function transformXbrowserWithParam(xmlDoc, xslDoc, paramArray) {
    var XHtmlDocFrag; outputXHtmlString;
	//dude
	//alert('beforexsldocwparam');
    var xslDocWithParams = SetXSLParam(xslDoc, paramArray);
    //alert('xsldoc: ' + xslDocWithParams.xml);
    if (window.XSLTProcessor)
    {
	    // support Mozilla/Gecko based browsers
	    var xsltProcessor = new XSLTProcessor();	    
	    xsltProcessor.importStylesheet(xslDocWithParams);
	    XHtmlDocFrag = xsltProcessor.transformToFragment(xmlDoc, document);	
	    var xmls1 = new XMLSerializer();
        outputXHtmlString = xmls1.serializeToString(XHtmlDocFrag);        	    
    }
    else if(window.ActiveXObject)
    {
	    // support Windows/ActiveX enabled browsers
	    var outputXHtmlString = xmlDoc.transformNode(xslDocWithParams);	    
    }
    else
    {
        // unsupported browser
        outputXHtmlString = 'Your browser does not support client-side XSL transformations.';
    }    
    return outputXHtmlString;
}

//**************************************************
//**************************************************
function SetXSLParam(xslDoc, paramArray) {
    var i, oNode;
    //var xsl = document.getElementById(theXmlElementId);
    //alert(xslDoc.innerHTML);
	//2007/07/19 something happened and this worked for the teamselect after I added the alert below, apparently the xsldoc isn't ready and giving it a bit more time helps it load and parse?    
    //alert(xslDoc.documentElement);	
    var oNodeList = xslDoc.documentElement.childNodes;
    for(i=0;i<oNodeList.length;i++) {
        oNode = xmlNextNode(oNodeList,i);
        if(oNode.nodeName=='xsl:param') {
            for (x in paramArray)
            {	            
                if (oNode.getAttribute('name')==paramArray[x][0]){
                    oNode.setAttribute('select',paramArray[x][1]);
                    break;
                }
            }
        }
    }
    return xslDoc;
}

//**************************************************
//**************************************************
// purpose: this is a w3c DOM level 1 compliant way of getting the next node in a node list
// dev:     mcd
// params:  
//          oNodeList: a w3c DOM node list
//          i: the node position in the list you wish to return
// returns: an w3c DOM xml node
// notes:   http://www.experts-exchange.com/Web_Development/Web_Languages-Standards/XML/Q_21782737.html?qid=21782737
// original dev date: ?
// repurposed date:    2008-06-14 repurposed for cross-browser xslt with no changes 
function xmlNextNode(oNodeList,i) {
    var oNode;
    if(oNodeList.snapshotLength) {
        oNode = oNodeList.snapshotItem(i);
    } else {
        try {
            oNode = oNodeList.item(i);
        } catch(e) {
            alert('transformClient01.js: xmlNextNode() not succesful');
        }
    }
    return oNode;
}

//**************************************************
//**************************************************
// name MultiDimensialArray
// purpose:     m-d arrays are not javascript native and so
//              this function creates a multi-dimensional array object
// returns:     a multidimensional array, e.g., myArray[0][0]
// params: 
//              iRows: the number of rows you want
//              iCols: the number of columns you want
// dev:         mcd
// date:        ? (original dev date)
function MultiDimensionalArray(iRows,iCols) 
{ 
var i; 
var j; 
   var a = new Array(iRows); 
   for (i=0; i < iRows; i++) 
   { 
       a[i] = new Array(iCols); 
       for (j=0; j < iCols; j++) 
       { 
           a[i][j] = ""; 
       } 
   } 
   return(a); 
}

//**************************************************
//**************************************************
//file:         myjs/transformClient01.js
//function      loadXMLDoc
//purpose:      returns a xmlDoc in cross-browser environment
//returns:      an activeX xmlDoc or non-ie xmlDoc depending on user browser
//param:    
//              xmlString: a xml string
//dev:          mcd
//date:         2008-06-13
//dev:          mcd
//date:         2008-09-07
//note:         this function is deprecated.  use the xmlextras.js  XmlDocument.Create  / .loadXML instead
function loadXMLDoc(xmlString) {
    var xmlDoc;
    var dk;
    // code for IE
    if (window.ActiveXObject)
    {
        xmlDoc=new ActiveXObject("Microsoft.XMLDOM");
        xmlDoc.async=false;
        xmlDoc.loadXML(xmlString);
    }
    // code for Mozilla, Firefox, Opera, etc.
    else if (document.implementation && document.implementation.createDocument)
    {
        //xmlDoc=document.implementation.createDocument("","",null);
        parser = new DOMParser();
        xmlDoc = parser.parseFromString(xmlString, "text/xml");
    }
    else
    {
        alert('Your browser cannot handle this script');
    }        
    return(xmlDoc);
}

//**************************************************
//**************************************************
//file:     myjs/transformClient01.js
// name:    function transformMozilla
// purpose: this is the non-ie branch for the transformXBrowser function and will
//          xslt.  It was originally tested-created in firefox, thus the fucntion
//          name 
// results: a non-ie xml document fragment
// params:  
//          xslDoc: a non-ie xml DOM containing a w3c valid xsl stylesheet.  This
//                  function will work a broader array of browsers if the stylesheet
//                  uses the lowest (1.0) level w3c xslt version
//          xmlDoc: a non-ie xml DOM
// dev:     mcd
// date:    2008-06-14
//
function transformMozilla(xslDoc, xmlDoc) {
    //writeIt(xslDoc,false)
    //writeIt(xmlDoc,false)
    alert(xmlDoc.xml);
    var xsltProcessor = new XSLTProcessor();
    xsltProcessor.importStylesheet(xslDoc);
   
    //xsltProcessor.importStylesheet(xslRef);
    var resultFragmentXmlDocument = xsltProcessor.transformToFragment(xmlDoc, document);   
   
    //var resultDocument = xsltProcessor.transformToDocument(xmlDoc, document);   
    return resultFragmentXmlDocument;
}

//**************************************************
//**************************************************
// file:    /myjs/transformClient01.js
// name:    importedXmlNodeGet
// purpose: originally created for non-ie browser like firefox that couldn't 
//          use the document function to pull in non-doo xml documents.  To
//          workaround this limitation the xml doc is retrieved via another
//          javascript process (using the embedded iFrame workaround) and
//          that process retrieves xml documents that you may want to 
//          merge.  This functions assists the merge process by getting and
//          returning a xml node suitable for the DOM appendChild method.  Note,
//          this doesnt work in browsers that don't recognize wc3 dom 
//          level 2 importNode or ELEMENT_NODE -- note that IE is one such browser
//          and this will not work in IE, but it doesn't matter because
//          IE document function allows sub-domain and domain-port-specific 
//          xmlhttp documents.
// returns: level 2 xml DOM node suitable for the DOM appendChild method
// params:  
//          appendFromXmlDoc: non-IE xml DOM
// dev:     mcd
// date:    2008-06-14
//
//          2008-06-16: note: IE doesn't support DOM level 2 don't try this
function importedXmlNodeGet(appendFromXmlDoc) {
    var newXmlNode = null, importedXmlNode = null;
    //writeIt(appendToXmlDoc, false);
    //writeIt(appendFromXmlDoc, true);
    newXmlNode = appendFromXmlDoc.documentElement;//(appendFromNodeTagNameString)[0].childNodes[0];    
    if (newXmlNode.nodeType != document.ELEMENT_NODE){
        newXmlNode = newXmlNode.nextSibling;
    }
    
    if (newXmlNode){
        importedXmlNode = document.importNode(newXmlNode, true);
        //writeIt(importedXmlNode, false);
    } 
    return importedXmlNode;
}

//**************************************************
//**************************************************
//name:     replaceDocumentFunctionWithDocument
//dev:      mcd
//purpose:  mozilla browsers workaround for domain of origin restriction on document() function 
//returns:  non-activex xsl document string modified use node-set instead of document function and embed xml
//parameters: 
//          xslDoc: w3c compatible xml document containing the stylesheet 
//          variableNameString: the name of the variable currently containing the non-doo document() function
//          appendThisChildNode: the non-doo w3c compatible xml node (obtained with w3c compatible importNode() function)
//date:     2008-06-13
//notes:    this will not work in <firefox 3.0 as earlier versions don't support exsl node-set extension
//
function replaceDocumentFunctionWithDocument(xslDoc, variableNameString, appendThisChildNode) {
    //writeIt(appendThisChildNode,true);
    //writeIt(xslDoc,false);
    var i, oNode, oNodeSiblingBelow, oNodeClone;
    //get the root node
    var docRoot = xslDoc.documentElement;
    //writeIt(docRoot.nodeName, true, true);
    //assume the root is xsl:stylesheet and append exsl attributes necessary for node-set function
    //  to work in mozilla    
    var a = document.createAttribute("xmlns:exsl");
    a.nodeValue = "http://exslt.org/common";
    docRoot.setAttributeNode(a);
    a = document.createAttribute("extension-element-prefixes");
    a.nodeValue = "exsl";
    docRoot.setAttributeNode(a);    

    var oNodeList = docRoot.childNodes;
    for(i=0;i<oNodeList.length;i++) {
        oNode = xmlNextNode(oNodeList,i);
        if(oNode.nodeName=='xsl:variable') {
            if (oNode.getAttribute('name')==variableNameString){
                oNodeClone = oNode.cloneNode(true);
                oNode.setAttribute('name', variableNameString + "1");                
                oNode.removeAttribute('select');                
                oNode.appendChild(appendThisChildNode);
                oNodeSiblingBelow = xmlNextNode(oNodeList,i+1);
                oNodeClone.setAttribute('select', "exsl:node-set($" + variableNameString + "1)");
                docRoot.insertBefore(oNodeClone, oNodeSiblingBelow);
                break;
            }
        }         
    }
    //2008-06-13: couldn't get the exsl prefix recognized in the document w/o this 
    //little bit of serialize/deserialize.  This is a hack, but I spent >8 hours trying
    //to get the exsl namespace prefix to be created or preserved upon importStylesheet.  see
    //http://fgeorges.blogspot.com/2007/01/creating-namespace-nodes-in-xslt-10.html
    //http://episteme.arstechnica.com/eve/forums/a/tpc/f/6330927813/m/653008249631/inc/1
    //http://biglist.com/lists/xsl-list/archives/200102/msg00656.html
    //http://www.oreillynet.com/xml/blog/2007/01/limited_exslt_support_in_mozil.html
    //mydocs/ffd/dev/xslt_cross_browser.txt (this contains many related key words and code snippets)
    var xmls1 = new XMLSerializer();
    var resultXmlString = xmls1.serializeToString(xslDoc);
    //var xslDoc1 = loadXMLDoc(resultXmlString);
    return resultXmlString;
}

//**************************************************
//**************************************************
//name:     replaceDocumentFunctionActiveX
//purpose:  IE browsers workaround for domain of origin restriction on document() function 
//returns:  activex xsl document string modified touse node-set instead of document function and embed xml
//parameters: 
//          xslDocString: w3c compatible xml document string containing the stylesheet 
//          variableNameString: the name of the variable currently containing the non-doo document() function
//          appendThisChildXmlString: xml doc string pulled from non DOO subdomain
//dev:      mcd
//date:     2008-06-27
//notes:    note, when a site is trusted it can do non-DOO document function, but that
//          is not a viable solution for public facing site.  IE doesn't implement the appendChild
//          DOM functionality without a ton of namespace contortions that make cloneNode and importNode
//          impossible to use.  regexp is just as good.
//
function replaceDocumentFunctionActiveX(xslDocString, variableNameString, appendThisChildXmlString) {
    //re = /\<xsl:variable name=\"aliasLookupDoc\"[^\>]*?/;
    var variableNameTemp = variableNameString + "1";
    var newVariable = '<xsl:variable name="'+ variableNameString +'1">'+ appendThisChildXmlString +'</xsl:variable><xsl:variable name="' + variableNameString + '" select="msxsl:node-set($'+ variableNameTemp +')" />';
    var re = /<xsl\:variable[^>]+aliasLookupDoc[^>]+>/;
    var str1 = xslDocString.replace(re, newVariable);
    //remove any xml declaration
    var re2 = /<\?[^>]+>/
    var str2 = str1.replace(re2,'');
    
    //remove blank lines
    var re3 = /^[^<]*/;
    var str3 = str2.replace(re3,'');
    
    var re4 = /(<xsl\:stylesheet[^>]+)/;
    var str4 = str3.replace(re4, '$1 xmlns:msxsl="urn:schemas-microsoft-com:xslt"');
    return str4;
}

//**************************************************
//**************************************************
//2008-06-21
//purpose: this will convert an xmldoc to a string and optionally place it in a text area value property
//returns: an xml string
//params: crossbrowserXmlDoc: a document created in mozilla or IE
//      optionalElementIdString: teh document id of the textarea to persist the xml to.  leave null if you just want the string
//dev: mcd
function xmlPersistToString(crossBrowserXmlDoc, optionalElementIdString) {    
    var resultXmlString;
    if (!window.ActiveXObject) {
        var xmls1 = new XMLSerializer();
        resultXmlString = xmls1.serializeToString(crossBrowserXmlDoc);    
    } else {
        resultXmlString = crossBrowserXmlDoc.xml;
    }
    if(optionalElementIdString) {
        var persistXmlTextArea = document.getElementById(optionalElementIdString);
        persistXmlTextArea.value = resultXmlString;
    }
    return resultXmlString;
}



