﻿//-----------------------------------------------------------------------------
// XDOM
//
// Copyright 2005-2010 - Xcential Group LLC.
//
//-----------------------------------------------------------------------------

//=============================================================================
// Constructor

function XDOM()
{

   //--------------------------------------------------------------------------
   // Private Interface

   //--------------------------------------------------------------------------
   // Privileged Interface

   //--------------------------------------------------------------------------
   // Initialization

   var oMode = null;

}

XDOM.objectClass = "XDOM";

//=============================================================================
// Static Interface

 XDOM.FREE_THREADED = true;

 XDOM.ACTIVEX_DOC_VERSIONS = [
    ".6.0",
    ".4.0",
    ".3.0",
    ""
 ];

 XDOM.activeXDocClsId = null;

//-----------------------------------------------------------------------------

// Note: The following method produces a DOM document, based on the IE model
//       that is compatible with both IE and Mozilla.

XDOM.createDocument = function(
   freeThreaded
)
{
   freeThreaded = (freeThreaded == null) ? false : freeThreaded;

   //--------------------------------------------------------------------------

   function changeReadyState(
      doc,
      readyState
   )
   {

      if (typeof(doc.readyState) == typeof(readyState))
         doc.readyState = readyState;

      // If there is an onreadystatechange event handler, run it
      if (doc.onreadystatechange != null && typeof objDOMDocument.onreadystatechange == "function")
         doc.onreadystatechange();

   }

   //--------------------------------------------------------------------------

   function _Result_getLength()
   {

      return this.snapshotLength;
   }


   //--------------------------------------------------------------------------

   function _Result_getItem(
      index
   )
   {

      return this.snapshotItem(index);
   }

   //--------------------------------------------------------------------------

   function _Node_toXML()
   {

       var xmlSerializer = new XMLSerializer();
       var xml = xmlSerializer.serializeToString(this);

       return xml;
   }

   //--------------------------------------------------------------------------

   function _Node_resolveNamespace(
      prefix
   )
   {

      // Note: Although this method is attached to the node object, when it
      //       gets called by the evaluate method, it has lost its node context
      //       and 'this' points to this function rather than the node. As a
      //       hack, the node context is added to the method before calling the
      //       evaluate method.

      var document = (this.node.nodeType == this.node.DOCUMENT_NODE) ? this.node : this.node.ownerDocument;

      var selectionNamespaces = document.getProperty("SelectionNamespaces");

      if (XString(selectionNamespaces).isSomething())
      {
         if (XMatch(selectionNamespaces, "xmlns:" + prefix + "=[\'\"]([^\'\"]+)[\'\"]"))
         {
            var namespaceURI = XMatch.matches[1];
            return namespaceURI;
         }
      }

      return null;
   }

   //--------------------------------------------------------------------------

   function _Node_selectNodes(
      xPath
   )
   {

      var document = (this.nodeType == this.DOCUMENT_NODE) ? this : this.ownerDocument;

      var ORDERED_NODE_SNAPSHOT_TYPE = 7;

      this.resolveNamespace.node = this;
      var result = document.evaluate(xPath, this, this.resolveNamespace, ORDERED_NODE_SNAPSHOT_TYPE, null);

      result.item = _Result_getItem;
      result.__defineGetter__("length", _Result_getLength);

      return result;
   }

   //--------------------------------------------------------------------------

   function _Node_selectSingleNode(
      xPath
   )
   {

      var document = (this.nodeType == this.DOCUMENT_NODE) ? this : this.ownerDocument;

      var FIRST_ORDERED_NODE_TYPE  = 9;

      this.resolveNamespace.node = this;
      var result = document.evaluate(xPath, this, this.resolveNamespace, FIRST_ORDERED_NODE_TYPE, null);

      return result.singleNodeValue;
   }

   //--------------------------------------------------------------------------

   function _Document_getURL()
   {

      return this.documentURI;
   }

   //--------------------------------------------------------------------------

   function _Document_load(
      url
   )
   {

      this.parseError = 0;

      changeReadyState(this, 1);

      // Call the original load after changing the ready state

      // Watch for errors
      try
      {

         // Call the original load method
         this.__load__(url);

      }
      catch (error)
      {
         this.parseError = -9999999;
         changeReadyState(this, 4); // Finished, but with an error
      }

   }

   //--------------------------------------------------------------------------

   function _Document_onload()
   {

      // Check for a parsing error
      if (!this.documentElement || this.documentElement.tagName == "parsererror")
         this.parseError = -9999999;

      changeReadyState(this, 4);

   }

   //--------------------------------------------------------------------------

   function _Document_loadXML(
      xml
   )
   {

      this.parseError = 0;

      changeReadyState(this, 1);

      var domParser = new DOMParser();

      var doc = domParser.parseFromString(xml, "text/xml");

      // Replace any existing nodes with the new document
      while (this.hasChildNodes())
         this.removeChild(this.lastChild);

      for (var i=0; i < doc.childNodes.length; i++)
      {
         var importedNode = this.importNode(doc.childNodes[i], true);
         this.appendChild(importedNode);
      }

      // Check for a parsing error
      if (!this.documentElement || this.documentElement.tagName == "parsererror")
         this.parseError = -9999999;

      changeReadyState(this, 4);

   }

   //--------------------------------------------------------------------------

   function _Document_setProperty(
      name,
      value
   )
   {

      if (this.properties == null)
         this.properties = new Array();

      this.properties[name] = value;

   }

   //--------------------------------------------------------------------------

   function _Document_getProperty(
      name,
      value
   )
   {

      if (this.properties != null)
         return this.properties[name];

      return null;
   }

   //--------------------------------------------------------------------------

   var doc = null;

   if (XApp.getMode() == XApp.MODE_CLIENT)
   {
      if (document.implementation.createDocument && !(/microsoft/i).test(window.navigator.appName))
      {
         var doc = document.implementation.createDocument("", "", null);

         Node.prototype.__defineGetter__("xml", _Node_toXML);
         Node.prototype.resolveNamespace = _Node_resolveNamespace;
         Node.prototype.selectNodes = _Node_selectNodes;
         Node.prototype.selectSingleNode = _Node_selectSingleNode;

         Document.prototype.__defineGetter__("url", _Document_getURL);
         Document.prototype.__load__ = Document.prototype.load;
         Document.prototype.load = _Document_load;
         Document.prototype.loadXML = _Document_loadXML;
         Document.prototype.validateOnParse = false;
         Document.prototype.resolveExternals = false;
         Document.prototype.parseError = 0;
         Document.prototype.readyState = "0";
         Document.prototype.onreadystatechange = null;
         Document.prototype.setProperty = _Document_setProperty;
         Document.prototype.getProperty = _Document_getProperty;

         doc.addEventListener("load", _Document_onload, false);
      }
      else // Internet Explorer
      {
         var documentType = (freeThreaded) ? "FreeThreadedDOMDocument" : "DOMDocument";
         if (XDOM.activeXDocClsId == null)
         {
            for (var i=0; i < XDOM.ACTIVEX_DOC_VERSIONS.length; i++)
            {
               try
               {
                  var doc = new ActiveXObject("MSXML2." + documentType + XDOM.ACTIVEX_DOC_VERSIONS[i]);

                  //if it gets to this point, the string worked, so save it
                  XDOM.activeXDocClsId = XDOM.ACTIVEX_DOC_VERSIONS[i];
                  break;

               }
               catch (error)
               {}
            }
            if (XDOM.activeXDocClsId == null)
               throw XMsg("Microsoft's MSXML application could not be found on your computer. Please install the latest version.");
         }
         else
            var doc = new ActiveXObject("MSXML2." + documentType + XDOM.activeXDocClsId);
      }
   }
   else
   {
      var documentType = (freeThreaded) ? "FreeThreadedDOMDocument" : "DOMDocument";
      var doc = new ActiveXObject("MSXML2." + documentType);
      XDOM.activeXDocClsId = ""; // Default MSXML
   }

   return doc;
}

//-----------------------------------------------------------------------------

XDOM.createTemplate = function()
{

   //--------------------------------------------------------------------------

   function _Processor_addParameter(
      name,
      value
   )
   {

      this.setParameter(null, name, value);

   }

   //--------------------------------------------------------------------------

   function _Processor_transform()
   {

      if (!this.input)
         throw XMsg("Cannot transform without first specifying an input document.");

      var result = this.transformToDocument(this.input);

      var xmlSerializer = new XMLSerializer();

      this.output = xmlSerializer.serializeToString(result);

   }

   //--------------------------------------------------------------------------

   function _Template_createProcessor()
   {

      var processor = new XSLTProcessor();

      if (this.stylesheet != null)
         processor.importStylesheet(this.stylesheet);

      processor.input = null;
      processor.output = null;
      processor.addParameter = _Processor_addParameter;
      processor.transform = _Processor_transform;

      return processor;
   }

   //--------------------------------------------------------------------------

   if (XApp.getMode() == XApp.MODE_CLIENT)
   {
      if (document.implementation.createDocument && !(/microsoft/i).test(window.navigator.appName))
      {
         var template = new Array();
         template.stylesheet = null;
         template.createProcessor = _Template_createProcessor;
      }
      else
      {
         var template = new ActiveXObject("MSXML2.XSLTemplate" + XDOM.activeXDocClsId)
      }
   }
   else
      var template = new ActiveXObject("MSXML2.XSLTemplate")

   return template;
}

//=============================================================================
