
/****************************************************/
/*           OpenPath PageBuilder                   */
/*       WRITTEN BY Richard, Chih-Shyang Chang      */
/*           2000/12/13                             */
/*      本程式受著作權法保護，侵權必究              */
/****************************************************/
// Purpose: The OpenPathXML component is designed to facilitate the manipulation of XML data
function OpenPathXML()
{
  // Attributes
  this.rootTag = "UniMSG";
  this.xmlDoc = new ActiveXObject("Microsoft.XMLDOM");
  this.xmlDoc.async = false;
  this.xmlDoc.loadXML('<' + this.rootTag + '></' + this.rootTag + '>');

  // Methods
  this.setRootTag = __setRootTag;
  this.loadXML = __loadXML;
  this.load = __load;
  this.getXML = __getXML;
  this.resetContent = __resetContent;
  this.generate = __generate;
  this.query = __query;
  this.generatePath = __generatePath;
  this.generateAttribute = __generateAttribute;
  this.queryAttribute = __queryAttribute;
  this.remove = __remove;
  this.getCount = __getCount;
  this.appendChild = __appendChild;
  this.appendSibling = __appendSibling;
  this.merge = __merge;
  this.extractPartialPath = __extractPartialPath;
  this.extractFullPath = __extractFullPath;
  this.clone = __clone;
  this.exist = __exist;
}


function __setRootTag(tag)
{
  if (tag.length == 0) return;
  this.rootTag = tag;
  this.xmlDoc.loadXML('<' + this.rootTag + '></' + this.rootTag + '>');
}


function __loadXML(strXML)
{
  try {
    var blnRet = this.xmlDoc.loadXML(strXML);
    if (blnRet == false)
      throw "[OpenPathXML Run-time Error]:\nloadXML(): parse error(XML not well-formed)!";
  } catch (e) {
    throw e;
  }
}


function __load(xmlSource)
{
  var blnRet = this.xmlDoc.load(xmlSource);
  if (blnRet == false)
    throw "[OpenPathXML Run-time Error]:\nloadXML(): parse error(XML not well-formed)!";
}


function __getXML()
{
  return this.xmlDoc.xml;
}


function __resetContent()
{
  this.xmlDoc.loadXML('<' + this.rootTag + '></' + this.rootTag + '>');
}


function __generate(strPattern, strContent)
{
  try
  {
    strContent += "";	  // Cast strContent to the string type

    var strParentPattern, strChildPattern;
    var strTag;
    var ndParent, ndChild, ndText;
    var ndx;

    if (strPattern.indexOf("/" + this.rootTag) == -1) strPattern = "/" + this.rootTag + "/" + strPattern;

    ndx = strPattern.lastIndexOf("/");  // find out the index of the last occurrence of '/'
    strParentPattern = strPattern.substring(0, ndx);
    strChildPattern = strPattern;
    strTag = strPattern.substr(ndx + 1);

    ndParent = this.xmlDoc.selectSingleNode(strParentPattern);
    if (ndParent == null)
      throw "[OpenPathXML Run-time Error]:\ngenerate(): invalid access pattern '" + strParentPattern + "'";

    ndChild = this.xmlDoc.selectSingleNode(strChildPattern);
    if (ndChild == null)  // the node doesn't exist, so create it.
    {
      //if (strContent == "") return false;

      ndChild = __createElementNode(this.xmlDoc, strTag);

      ndText = this.xmlDoc.createTextNode(strContent);
      ndChild.appendChild(ndText);
      ndParent.appendChild(ndChild);
    }
    else
    {
      ndChild.text = strContent;
    }

    return true;
  }
  catch (e)
  {
    throw e;
  }

}


function __query(strPattern)
{
  try
  {
    var nd;

    if (strPattern.indexOf("/" + this.rootTag) == -1)
      nd = this.xmlDoc.selectSingleNode("/" + this.rootTag + "/" + strPattern);
    else
      nd = this.xmlDoc.selectSingleNode(strPattern);

    if (nd == null)
      return "";

    return nd.text;
  }
  catch (e)
  {
    throw e;
  }
}


function __generatePath(strPattern, blnHasTextNode)
{
  try
  {
    var strParent;
    var nd;
    var ndText;
    var ndParent;
    var ndList;
    var strTags;
    var strTagName;
    var i, ndx;
    var leftPos, rightPos;


    if (strPattern == "") return false;

    if (blnHasTextNode == null) blnHasTextNode = false;

    if (strPattern.indexOf("/" + this.rootTag) != -1) strPattern = strPattern.substr(this.rootTag.length + 2);


    strTags = strPattern.split("/");
    strParent = "/" + this.rootTag;

    for (i=0; i<strTags.length; i++)
    {
      nd = this.xmlDoc.selectSingleNode(strParent + "/" + strTags[i]);
      if (nd == null)
      {
        leftPos = strTags[i].indexOf("[");
        if (leftPos > 0)
        {
          rightPos = strTags[i].indexOf("]", leftPos);
          ndx = strTags[i].substring(leftPos, rightPos);
          strTagName = strTags[i].substring(0, leftPos);

          ndList = this.xmlDoc.selectNodes(strParent + "/" + strTagName);
          if (ndx - ndList.length > 0)
            throw "[OpenPathXML Run-time Error]:\ngeneratePath(): invalid access pattern '" + strPattern + "'";
        }
        else
        {
          strTagName = strTags[i];
        }

        // the node doesn't already exist, so create it.
        nd = __createElementNode(this.xmlDoc, strTagName);

        if (blnHasTextNode == false)
        {
          ndParent = this.xmlDoc.selectSingleNode(strParent);
          ndParent.appendChild(nd);
        }
        else
        {
          ndText = this.xmlDoc.createTextNode("");
          nd.appendChild(ndText);
          ndParent = this.xmlDoc.selectSingleNode(strParent);
          ndParent.appendChild(nd);
        }

      }

      strParent = strParent + "/" + strTags[i];
    }

    return true;

  }
  catch (e)
  {
    throw e;
  }

}


function __remove(strPattern)
{
  try
  {
    var nd;

    if (strPattern.indexOf("/" + this.rootTag) == -1)
      nd = this.xmlDoc.selectSingleNode("/" + this.rootTag + "/" + strPattern);
    else
      nd = this.xmlDoc.selectSingleNode(strPattern);

    if (nd == null)
      throw "[OpenPathXML Run-time Error]:\nremove(): invalid access pattern '" + strPattern + "'";

    nd.parentNode.removeChild(nd);
  }
  catch (e)
  {
    throw e;
  }
}


function __getCount(strPattern)
{
  try
  {
    var ndList;

    if (strPattern.indexOf("/" + this.rootTag) == -1)
      ndList = this.xmlDoc.selectNodes("/" + this.rootTag + "/" + strPattern);
    else
      ndList = this.xmlDoc.selectNodes(strPattern);

    if (ndList == null)
      throw "[OpenPathXML Run-time Error]:\ngetCount(): invalid access pattern '" + strPattern + "'";

    return ndList.length;
  }
  catch (e)
  {
    throw e;
  }

}


function __generateAttribute(strPattern, strAttribute, strValue)
{
  try
  {
    var nd;
    var attr;

    strValue += "";   // Cast strValue to the string type

    if (strPattern.indexOf("/" + this.rootTag) == -1)
      nd = this.xmlDoc.selectSingleNode("/" + this.rootTag + "/" + strPattern);
    else
      nd = this.xmlDoc.selectSingleNode(strPattern);

    if (nd == null)
      throw "[OpenPathXML Run-time Error]:\ngenerateAttribute(): invalid access pattern '" + strPattern + "'";

    attr = nd.getAttributeNode(strAttribute);
    if (attr == null)
    {
      attr = this.xmlDoc.createAttribute(strAttribute);
      attr.value = strValue;
      nd.attributes.setNamedItem(attr);
    }
    else
    {
      attr.value = strValue;
    }

    return true;
  }
  catch (e)
  {
    throw e;
  }
}


function __queryAttribute(strPattern, strAttribute)
{
  try
  {
    var nd;
    var attr;

    if (strPattern.indexOf("/" + this.rootTag) == -1)  // If "/rootTag" doesn't appear in the pattern, then add one automatically
      nd = this.xmlDoc.selectSingleNode("/" + this.rootTag + "/" + strPattern);
    else
      nd = this.xmlDoc.selectSingleNode(strPattern);

    if (nd == null)
      throw "[OpenPathXML Run-time Error]:\nqueryAttribute(): invalid access pattern '" + strPattern + "'";

    attr = nd.getAttributeNode(strAttribute);
    if (attr == null)
        return "";

    return attr.value;
  }
  catch (e)
  {
    throw e;
  }
}


function __appendChild(strPattern, obj)
{
  try
  {
    var nd, nd2, ndList;

    if (strPattern.indexOf("/" + this.rootTag) == -1)  // If "/rootTag" doesn't appear in the pattern, then add one automatically
      nd = this.xmlDoc.selectSingleNode("/" + this.rootTag + "/" + strPattern);
    else
      nd = this.xmlDoc.selectSingleNode(strPattern);

    if (nd == null)
      throw "[OpenPathXML Run-time Error]:\nappendChild(): invalid access pattern '" + strPattern + "'";

    var doc = new ActiveXObject("Microsoft.XMLDOM");
    doc.async = false;
    doc.loadXML(obj.getXML());

    for (var i=0; i<doc.lastChild.childNodes.length; i++)
    {
      nd2 = doc.lastChild.childNodes.item(i).cloneNode(true);
      nd.appendChild(nd2);
    }

    return true;
  }
  catch (e)
  {
    throw e;
  }
}


function __appendSibling(strPattern, obj)
{
  try
  {
    var nd, nd2, ndParent = null, ndList;

    if (strPattern == "/" + this.rootTag)
      throw "[OpenPathXML Run-time Error]:\nappendSibling(): access pattern '" + strPattern + "' is illegal";

    if (strPattern.indexOf("/" + this.rootTag) == -1)  // If "/rootTag" doesn't appear in the pattern, then add one automatically
      nd = this.xmlDoc.selectSingleNode("/" + this.rootTag + "/" + strPattern);
    else
      nd = this.xmlDoc.selectSingleNode(strPattern);

    if (nd == null)
      throw "[OpenPathXML Run-time Error]:\nappendSibling(): invalid access pattern '" + strPattern + "'";

    ndParent = nd.parentNode;

    var doc = new ActiveXObject("Microsoft.XMLDOM");
    doc.async = false;
    doc.loadXML(obj.getXML());

    for (var i=0; i<doc.lastChild.childNodes.length; i++)
    {
      nd2 = doc.lastChild.childNodes.item(i).cloneNode(true);
      ndParent.appendChild(nd2);
    }

    return true;
  }
  catch (e)
  {
    throw e;
  }
}


function __merge(strPattern, strTag, obj)
{
  try
  {
    var nd, nd2, nd3, ndList;

    if (strPattern.indexOf("/" + this.rootTag) == -1)  // If "/rootTag" doesn't appear in the pattern, then add one automatically
      nd = this.xmlDoc.selectSingleNode("/" + this.rootTag + "/" + strPattern);
    else
      nd = this.xmlDoc.selectSingleNode(strPattern);

    if (nd == null)
      throw "[OpenPathXML Run-time]:\nmerge(): invalid access pattern '" + strPattern + "'";

    nd2 = __createElementNode(this.xmlDoc, strTag);
    nd.appendChild(nd2);

    var doc = new ActiveXObject("Microsoft.XMLDOM");
    doc.async = false;
    doc.loadXML(obj.getXML());

    for (var i=0; i<doc.lastChild.childNodes.length; i++)
    {
      nd3 = doc.lastChild.childNodes.item(i).cloneNode(true);
      nd2.appendChild(nd3);
    }

    return true;
  }
  catch (e)
  {
    throw e;
  }
}


function __extractPartialPath(strPattern)
{
  try
  {
    var nd, strXML, objNew;

    if (strPattern.indexOf("/" + this.rootTag) == -1)  // If "/rootTag" doesn't appear in the pattern, then add one automatically
      nd = this.xmlDoc.selectSingleNode("/" + this.rootTag + "/" + strPattern);
    else
      nd = this.xmlDoc.selectSingleNode(strPattern);

    if (nd == null)
      throw "[OpenPathXML Run-time Error]:\nextractPartialPath(): invalid access pattern '" + strPattern + "'";

    strXML = '<' + this.rootTag + '><' + nd.nodeName + '>';

    for (var i=0; i<nd.childNodes.length; i++)
      strXML += nd.childNodes.item(i).xml;

    strXML = strXML + '</' + nd.nodeName + '></' + this.rootTag + '>';

    objNew = new OpenPathXML();
    objNew.loadXML(strXML);

    return objNew;
  }
  catch (e)
  {
    throw e;
  }
}


function __extractFullPath(strPattern)
{
  try
  {
    var nd,strXML;
    var strHead, strTail, i;
    var strTag, objNew;

    if (strPattern.indexOf("/" + this.rootTag) == -1)  // If "/rootTag" doesn't appear in the pattern, then add one automatically
      nd = this.xmlDoc.selectSingleNode("/" + this.rootTag + "/" + strPattern);
    else
      nd = this.xmlDoc.selectSingleNode(strPattern);

    if (nd == null)
      throw "[OpenPathXML Run-time Error]:\nextractFullPath(): invalid access pattern '" + strPattern + "'";

    strXML = nd.xml;
    strHead = "";
    strTail = "";

    nd = nd.parentNode;
    strTag = nd.nodeName;
    while (strTag != this.rootTag)
    {
      strHead = "<" + strTag + ">" + strHead;
      strTail = strTail + "</" + strTag + ">";
      nd = nd.parentNode;
      strTag = nd.nodeName;
    }

    objNew = new OpenPathXML();
    objNew.loadXML("<" + this.rootTag + ">" + strHead + strXML + strTail + "</" + this.rootTag + ">");

    return objNew;
  }
  catch (e)
  {
    throw e;
  }
}

function __clone()
{
  var opxml = new OpenPathXML();
  opxml.loadXML(this.xmlDoc.xml);

  return opxml;
}

function __exist(strPattern)
{
  try
  {
    var nd;

    if (strPattern.indexOf("/" + this.rootTag) == -1)
      nd = this.xmlDoc.selectSingleNode("/" + this.rootTag + "/" + strPattern);
    else
      nd = this.xmlDoc.selectSingleNode(strPattern);

    if (nd == null)
      return 0;
    else
      return 1;
  }
  catch (e)
  {
    throw e;
  }
}

function fnResetControlValues(array)
{
  var opxml = new OpenPathXML();

  fnResetData(opxml, array);
  return opxml;
}

function fnResetData(opxml, array)
{
  if (opxml == null) return;

  var ary = null;
  if (array == null)
    ary = mVarControlList;
  else
    ary = array;

  var o = null;
  var val = null;
  var acckey = null;
  for (var i=0; i < ary.length && ary[i] != null; i++)
  {
    o = ary[i];
    switch (o.type) {
      case "select-one":
        if (o.options.length > 0) {
          if (o.size <= 1) {
            o.options[0].selected = true;
            val = o.options[0].value;
            acckey = o.accessKey;
          } else {
            o.selectedIndex = -1;
            continue;
          }
        } else {
          continue;
        }

        break;
      case "checkbox":
        var items = o.value.split(":");
        var yy,nn;

        if (items.length >= 2) {
          yy = items[0];
          nn = items[1];
        } else if (items.length >= 1) {
          yy = items[0];
          nn = "N";
        } else {
          yy = "Y";
          nn = "N";
        }

        if (o.V_DEFAULT != null) {
          if (o.V_DEFAULT=="CHECKED") {
            o.status = true;
            val = yy;
          } else {
            o.status = false;
            val = nn;
          }
        } else {
          if (o.status)
            val = yy;
          else
            val = nn;
        }
        break;
      case "radio":
        if (o.V_DEFAULT != null) {
          if (o.V_DEFAULT=="CHECKED") {
            o.status = true;
            val = o.value;
          } else {
            o.status = false;
            val = null;
          }
        } else {
          var obj = eval(o.name);
          val = obj.value;
        }
        break;
      case "text":
        if (o.V_DEFAULT != null) {
          val = o.V_DEFAULT;
          o.value = val;
        } else {
          val = null;
          o.value = "";
        }
        break;
      case "textarea":
        if (o.V_DEFAULT != null) {
          val = o.V_DEFAULT;
          o.value = val;
        } else {
          val = null;
          o.value = "";
        }
        break;
      default:
        continue;
        break;
    }
    if (val == null || val == "" || o.accessKey == null || o.accessKey == "")
      continue;

    fnGeneratePathValue(opxml, o.accessKey, val);
  }
}


function fnGeneratePathValue(opxml, acckey, strContent)
{
  try
  {
    var strParent;
    var nd;
    var attr;
    var ndAttr;
    var ndx;
    var ndText;
    var ndParent;
    var ndList;
    var strTags;
    var strTagName;
    var isAttr;
    var i, ndx;
    var leftPos, rightPos;


    if (acckey.substring(1, opxml.rootTag.length + 1) == opxml.rootTag)
      acckey = acckey.substr(opxml.rootTag.length + 2);  // remove the root tag

    strContent += '';
    strTags = acckey.split("/");
    strParent = "/" + opxml.rootTag;


    for (i=0; i<strTags.length; i++)
    {

      if (i == strTags.length - 1)
      {
        ndx = strTags[i].indexOf("@");
        if (ndx != -1)
        {
          isAttr = true;
          attr = strTags[i].substr(1);
        }
        else
        {
          isAttr = false;
        }
      }


      nd = opxml.xmlDoc.selectSingleNode(strParent + "/" + strTags[i]);

      if (nd == null)
      {
        leftPos = strTags[i].indexOf("[");
        if (leftPos > 0)
        {
          rightPos = strTags[i].indexOf("]", leftPos);
          ndx = strTags[i].substring(leftPos, rightPos);
          strTagName = strTags[i].substring(0, leftPos);

          ndList = opxml.xmlDoc.selectNodes(strParent + "/" + strTagName);
          if (ndx - ndList.length > 0)
            throw "[Err]: fnGeneratePathValue()\n Invalid access pattern '" + acckey + "'";
        }
        else
        {
          strTagName = strTags[i];
        }


        // the node doesn't already exist, so create it.
        if (i < strTags.length - 1)
        {
          nd = __createElementNode(opxml.xmlDoc, strTagName);
          ndParent = opxml.xmlDoc.selectSingleNode(strParent);
          ndParent.appendChild(nd);
        }
        else   // else  i == strTags.length - 1
        {
          if (isAttr == false)
          {
            nd = __createElementNode(opxml.xmlDoc, strTagName);
            ndText = opxml.xmlDoc.createTextNode(strContent);
            nd.appendChild(ndText);
            ndParent = opxml.xmlDoc.selectSingleNode(strParent);
            ndParent.appendChild(nd);
          }
          else
          {
            opxml.generateAttribute(strParent, attr, strContent);
            //alert('attr = ' + attr + '\n path = ' + strParent);
          }
        }

      }  // end of if

      strParent = strParent + "/" + strTags[i];
    }

    return true;

  }
  catch (e)
  {
    throw e;
  }
}

function fnCollectData(opxml, array)
{
  if (opxml == null) return;

  var ary = null;
  if (array == null)
    ary = mVarControlList;
  else
    ary = array;

  for (var i=0; i < ary.length && ary[i] != null; i++)
  {
    o = ary[i];
    switch (o.type) {
      case "select-one":
        if (o.selectedIndex >= 0)
        {
          val = o.options[o.selectedIndex].value;
          if (val == '') o.options[o.selectedIndex].text;
        }
        else
        {
          val = "";
        }
        break;
      case "checkbox":
        var items = o.value.split(":");
        var yy,nn;

        if (items.length == 2)
        {
          yy = items[0];
          nn = items[1];
        }
        else
        {
          yy = "Y";
          nn = "N";
        }

        if (o.status)
          val = yy;
        else
          val = nn;
        break;
      case "radio":
        var names = eval(o.name);
        for (var j=0; j<names.length; j++)
          if (names[j].checked == true)
          {
            val = names[j].value;
            break;
          }
        break;
      case "text":
      case "textarea":
        val = o.value;
        break;
      default:
        if (o.tagName == 'SPAN') {
          val = o.innerText;
          break;
        } else
          continue;
    }

    //if (val == null || val == "" || o.accessKey == null || o.accessKey == "")
    if (o.accessKey == null || o.accessKey == "")
      continue;

    fnGeneratePathValue(opxml, o.accessKey, val);
  }
}


function fnFillData(opxml, array)
{
  if (opxml == null) return;

  var ary = null;
  if (array == null)
    ary = mVarControlList;
  else
    ary = array;

  var o = null;
  var ndx;
  var val = null;
  var acckey = null;
  var attr;

  for (var i=0; i < ary.length && ary[i] != null; i++)
  {
    o = ary[i];
    acckey = o.accessKey;

    if (acckey == '' || acckey == null)
      continue;

    ndx = acckey.indexOf("@");
    if (ndx != -1)
    {
      attr = acckey.substr(ndx + 1);
      acckey = acckey.substring(0, ndx - 1);

      //alert('attr: ' + attr);
      //alert('acckey: ' + acckey);

      try {
        val = opxml.queryAttribute(acckey, attr);
      }
      catch (e) {}
    }
    else
    {
      val = opxml.query(acckey);
    }


    if (o.tagName == 'SPAN')
    {
      o.innerText = val;
      continue;
    }


    switch (o.type) {
      case "select-one":
        o.selectedIndex = -1;
        for (var j=0; j<o.options.length; j++)
          if (o.options[j].value == val)
          {
            o.selectedIndex = j;
            break;
          }
        break;

      case "checkbox":
        var items = o.value.split(":");
        if (val == items[0])  // Y
          o.checked = true;
        else
          o.checked = false;  // N
        break;

      case "radio":
        var names = eval(o.name);
        names[0].checked = true;
        for (var j=0; j<names.length; j++)
          if (names[j].value == val)
          {
            names[j].checked = true;
            break;
          }
        break;

      case "text":
        o.value = val;
        break;

      case "textarea":
        o.value = val;
        break;

      default:
        break;
    }  // end of switch block
  }  // end of for loop

}


function __createElementNode(xmlDoc, strTag)
{
  var pos;
  var ns; // name space
  var nd, ndChild;

  pos = strTag.indexOf(":");
  if (pos == -1)
  {
    ndChild = xmlDoc.createNode(1, strTag, "");
  }
  else
  {
    ns = "xmlns:" + strTag.substr(0, pos);
    nd = xmlDoc.selectSingleNode("//@" + ns);
    ndChild = xmlDoc.createNode(1, strTag, nd.value);
  }

  return ndChild;
}
	