/*
 * DOMユーティリティ
 * DOMをJavascriptで使用する際に、便利なユーティリティと定数定義
 * ある程度のWebブラウザ間の違いは、この中で吸収する。
 *
 * このソース内で定義されている変数とメソッドは、全てクラス変数・
 * クラスメソッドです。オブジェクトのインスタンスを作成する必要はありません。
 *
 * AppUtil.applcationInit()が、既に正常終了していることを前提にしています。
 * 必ずbodyエレメントに、onload="AppUtil.applcationInit();"を記述するか、
 * 又は他の方法で、必ず呼び出しが終了しているようにしてください。
 *
 * このファイルの利用について
 * このファイルの内容は、個人利用・商用利用に関わらず、一部または全部を、
 * 自由に利用していただいてかまいません。
 * 但し、引用元の表示か、著作者が（有）ワイシステムクリエイトであることを
 * 示す、著作権表示を必ず行ってください。
 * また、このファイルの内容を利用した事により、何らかの不利益を被った場合
 * でも、（有）ワイシステムクリエイトは、一切保証できませんので、利用者ご
 * 自身の責任において、ご利用くださるようお願いします。
 *
 * Copyright (C) 2003-2005 Y System Create Corporation. All Rights Reserved.
 *
 * $Date: 2005/04/30 01:32:21 $
 * $Revision: 1.6 $
 */

/*
 * コンストラクタ
 */
function DomUtil() {}

DomUtil.ELEMENT_NODE= document.ELEMENT_NODE;                                // 1
if (! DomUtil.ELEMENT_NODE) {
    DomUtil.ELEMENT_NODE = 1;
}
DomUtil.ATTRIBUTE_NODE= document.ATTRIBUTE_NODE;                            // 2
if (! DomUtil.ATTRIBUTE_NODE) {
    DomUtil.ATTRIBUTE_NODE = 2;
}
DomUtil.TEXT_NODE= document.TEXT_NODE;                                      // 3
if (! DomUtil.TEXT_NODE) {
    DomUtil.TEXT_NODE = 3;
}
DomUtil.CDATA_SECTION_NODE= document.CDATA_SECTION_NODE;                    // 4
if (! DomUtil.CDATA_SECTION_NODE) {
    DomUtil.CDATA_SECTION_NODE = 4;
}
DomUtil.ENTITY_REFERENCE_NODE= document.ENTITY_REFERENCE_NODE;              // 5
if (! DomUtil.ENTITY_REFERENCE_NODE) {
    DomUtil.ENTITY_REFERENCE_NODE = 5;
}
DomUtil.ENTITY_NODE= document.ENTITY_NODE;                                  // 6
if (! DomUtil.ENTITY_NODE) {
    DomUtil.ENTITY_NODE = 6;
}
DomUtil.PROCESSING_INSTRUCTION_NODE= document.PROCESSING_INSTRUCTION_NODE;  // 7
if (! DomUtil.PROCESSING_INSTRUCTION_NODE) {
    DomUtil.PROCESSING_INSTRUCTION_NODE = 7;
}
DomUtil.COMMENT_NODE= document.COMMENT_NODE;                                // 8
if (! DomUtil.COMMENT_NODE) {
    DomUtil.COMMENT_NODE = 8;
}
DomUtil.DOCUMENT_NODE= document.DOCUMENT_NODE;                              // 9
if (! DomUtil.DOCUMENT_NODE) {
    DomUtil.DOCUMENT_NODE = 9;
}
DomUtil.DOCUMENT_TYPE_NODE= document.DOCUMENT_TYPE_NODE;                    // 10
if (! DomUtil.DOCUMENT_TYPE_NODE) {
    DomUtil.DOCUMENT_TYPE_NODE = 10;
}
DomUtil.DOCUMENT_FRAGMENT_NODE= document.DOCUMENT_FRAGMENT_NODE;            // 11
if (! DomUtil.DOCUMENT_FRAGMENT_NODE) {
    DomUtil.DOCUMENT_FRAGMENT_NODE = 11;
}
DomUtil.NOTATION_NODE= document.NOTATION_NODE;                              // 12
if (! DomUtil.NOTATION_NODE) {
    DomUtil.NOTATION_NODE = 12;
}

/*
 * ターゲットノードの子供をすべて削除する。
 */
DomUtil.removeAllChild = function (targetNode) {

    while (targetNode.hasChildNodes()) {

        targetNode.removeChild(targetNode.firstChild);
    }
}


/*
 * targetNodeの子孫から、指定のidを持つElementを取得する。
 */
DomUtil.getElementByIdFromNode = function (targetNode, targetId) {
    /*
     * ターゲットが子供を持たない場合は、処理終了。
     */
    if (targetNode.hasChildNodes()) {
        var childList = targetNode.childNodes;
        var count = childList.length;
        for (var i = 0; i < count; i ++) {
            var elementItem = childList.item(i);
            if (elementItem.nodeType == DomUtil.ELEMENT_NODE) {
                /*
                 * エレメントノードの場合、idをチェックし、
                 * 該当しなければ、リカーシブ
                 */
                if (elementItem.id == targetId) {
                    return elementItem;
                }
                var rtnElement =
                    DomUtil.getElementByIdFromNode(elementItem, targetId);
                if (rtnElement) {
                    return rtnElement;
                }
            }
        }
    }
    return null;
}


/**
 * 指定要素の子孫要素から、指定の属性が指定の値となっている要素を取得する。
 * 該当する要素が複数存在する場合でも、最初に発見した要素を返す。
 * 該当する要素が、指定要素の子孫に存在しない場合、nullを返す。
 * @param 要素 : 指定要素。この子孫の中から、該当する要素を検索する。
 * @param 文字列 : 指定属性。
 * @param 文字列 : 値
 * @reutrn 要素 : 発見した要素。該当する要素が存在しない場合、null。
 */
DomUtil.getElementByAttributeValue =
    function (targetNode, attributeKey, attributeValue) {

    if ("class" == attributeKey) {

        attributeKey = "className";
    }

    /*
     * ターゲットが子供を持たない場合は、処理終了。
     */
    if (targetNode.hasChildNodes()) {

        var childList = targetNode.childNodes;
        var count = childList.length;
        for (var i = 0; i < count; i ++) {

            var elementItem = childList.item(i);
            if (elementItem.nodeType == DomUtil.ELEMENT_NODE) {

                /*
                 * エレメントノードの場合、属性値をチェックし、
                 * 該当しなければ、リカーシブ
                 * 属性周りは、DOM Level 1程度のものも、IE5.5は
                 * まともにサポートしていないので、早く捨てたい。
                 */
                //var value = elementItem.getAttribute(attributeKey);
                var value = elementItem[attributeKey];
                if (value) {

                    var valueList = value.split(" ");

                    for (var j = 0; j < valueList.length; j ++) {

                        if (valueList[j] == attributeValue) {

                            return elementItem;
                        }
                    }
                }

                var rtnElement =
                    DomUtil.getElementByAttributeValue(elementItem,
                                                       attributeKey,
                                                       attributeValue);
                if (rtnElement) {

                    return rtnElement;
                }
            }
        }
    }
    return null;
}


/*
 * ドキュメントとidを指定して、該当するノードの先頭にある
 * テキストノードから、テキストを取得する。
 * ドキュメントが指定されない場合は、documentを使用する。
 */
DomUtil.getTextValue = function (targetId, targetDoc) {

    if (null == targetDoc) {

        targetDoc = document;
    }

    var targetElement = targetDoc.getElementById(targetId);
    if (targetElement == null) {
        throw 'DomUtil@getTextValue:' +
              'no element applicable to a targerId.' +
              ' targetId('+targetId+')';
    }
    return DomUtil.getTextValueByNode(targetElement);
}


/*
 * 指定エレメントの先頭にあるテキストノードから、
 * テキストを取得する。
 */
DomUtil.getTextValueByNode = function (targetNode) {

    if (targetNode.hasChildNodes()) {
        /*
         * 子ノードがある場合、先頭の子ノードがテキストノードかをチェックし、
         * テキストノードの場合は、そのvalueを返す。
         */
        if (targetNode.firstChild.nodeType == DomUtil.TEXT_NODE) {
            return targetNode.firstChild.nodeValue;
        }
    }
    /*
     * 子ノードを持たない場合や、先頭の子ノードがテキストノード以外の場合は、
     * サイズ０の文字列を返す。
     */
    return '';
}


/*
 * 指定のエレメントに、テキストノード追加し、指定のテキストをセットする。
 * targetNode : element
 * textValue  : String
 * viewDoc    : document : nullの場合は、documentを使用する。
 */
DomUtil.setTextValue = function (targetElement, textValue, viewDoc) {

    if (null == viewDoc) {

        viewDoc = document;
    }

    if (targetElement.nodeType != DomUtil.ELEMENT_NODE) {
//        throw 'ComYscjpDomUtilities.setTextValue:Not ELEMENT_NODE'+targetElement;
AppUtil.printLog("DomUtil.setTextValue:No ELEMENT_NODE", AppUtil.DEBUGLOG);
AppUtil.printLog("nodeType("+targetElement.nodeType+")("+targetElement.nodeValue+")", AppUtil.DEBUGLOG);
//throw "DomUtil.setTextValue:No ELEMENT_NODE";
return;
    }
    DomUtil.removeAllChild(targetElement);
    var textValueNode = viewDoc.createTextNode(textValue);
    targetElement.appendChild(textValueNode);
}


/*
 * ディープクローン
 * valueTag配下のxml(html)の構造を、targetTag配下にコピーする。
 * targetTag コピー先のタグ
 * valueTag コピー元となるタグ
 */
DomUtil.deepClone = function (targetTag, valueTag) {

  /*
   * コピー元に子ノードが存在する場合のみ、処理を行う。
   */
  if (valueTag.hasChildNodes()) {

    var targetDoc = targetTag.ownerDocument;
    if (! targetDoc) {
      targetDoc = document;
    }

    for (var i = 0; i < valueTag.childNodes.length; i ++) {

      var valueChild = valueTag.childNodes.item(i);

      if (valueChild.nodeType == DomUtil.ELEMENT_NODE) {

        /**
         * エレメントノードの場合は、タグ名でノードを作成し、
         * アトリビュートをコピーする。
         * その後、まだ子が有る場合は、リカーシブ。
         */
        var targetEleNode = targetDoc.createElement(valueChild.tagName);
        targetEleNode = targetTag.appendChild(targetEleNode);
        var valueAtts = valueChild.attributes;
        targetEleNode.className = valueChild.className;

//        for (var j = 0; j < valueAtts.length; j ++) {

//          var attNode = valueAtts.item(j);
          /**
           * 本来のDOMの仕様であれば、下のコメントとなっているコードで、
           * 正しく動作するはずだが、IE5.5がサポートしていないので、
           * やむなく、変更する。
           */
//          targetEleNode.setAttribute(attNode.name, attNode.value);
//          targetAtts.setNamedItem(attNode);
//        }

        /*
         * この次の処理は、イメージの読み込みを正しく行わない
         * Webブラウザが存在するために、しょうがなく行う。
         */
        if (valueChild.tagName == 'IMG') {

          var srcurl = valueChild.getAttribute('src');
          targetEleNode.src = srcurl;
        }
        DomUtil.deepClone(targetEleNode, valueChild);
      }
      else if (valueChild.nodeType == DomUtil.TEXT_NODE) {

        /**
         * テキストノードの場合は、テキストでノードを作成し、
         * 子として追加する。
         */
        var textNode = targetDoc.createTextNode(valueChild.nodeValue);
        targetTag.appendChild(textNode);
      }
    }
  }
}


/*
 * ディープクローン
 * sourceNode配下のxml(html)の構造を、targetNode配下にコピーする。
 * コピーの対象となるのは、エレメントノードとテキストノードのみで、
 * コメントなどは、コピーされない。
 * エレメントノードの属性は、デフォルトの状態では、
 * 設定されている全ての属性をコピーするが、
 * DomUtil.cloneAttributes(nodeTo, nodeFrom, isUnImp)
 * メソッドを適当なメソッドで上書きすることにより、
 * 指定の属性のみコピーするように、変更することが出来る。
 *
 * targetNode コピー先のタグ
 * sourceNode コピー元となるタグ
 * isUnImp 属性を全てコピーするかを指定するフラグ
 *         null以外が指定された場合、全ての属性をコピーする。
 */
DomUtil.deepClone2 = function (targetNode, sourceNode, isUnImp) {

    /*
     * コピー元に子ノードが存在する場合のみ、処理を行う。
     */
    if (! sourceNode.hasChildNodes()) {

        return;
    }

    var targetDocument = targetNode.ownerDocument;

    if (! targetDocument) {

        targetDocument = document;
    }

    for (var i = 0; i < sourceNode.childNodes.length; i ++) {

        var sourceChild = sourceNode.childNodes.item(i);

        if (sourceChild.nodeType == DomUtil.ELEMENT_NODE) {

            /*
             * エレメントノードの場合は、タグ名でノードを作成し、
             * アトリビュートをコピーする。
             * その後、まだ子が有る場合は、リカーシブ。
             */
            var targetEleNode = targetDocument.createElement(sourceChild.tagName);
            targetEleNode = targetNode.appendChild(targetEleNode);
            DomUtil.cloneAttributes(targetEleNode, sourceChild, isUnImp);
//            targetEleNode.className = sourceChild.className;

            DomUtil.deepClone(targetEleNode, sourceChild);
        }
        else if (sourceChild.nodeType == DomUtil.TEXT_NODE) {

            /**
             * テキストノードの場合は、テキストでノードを作成し、
             * 子として追加する。
             */
            var textNode = targetDocument.createTextNode(sourceChild.nodeValue);
            targetNode.appendChild(textNode);
        }
    }
}


DomUtil.cloneAttributes = function (nodeTo, nodeFrom, isUnImp) {

    var fromAttributes = nodeFrom.attributes;

    for (var j = 0; j < fromAttributes.length; j ++) {

        var fromAttribute = fromAttributes.item(j);

        /**
         * 本来のDOMの仕様であれば、下のコメントとなっているコードで、
         * 正しく動作するはずだが、IE5.5がサポートしていないので、
         * やむなく、変更する。
         */
        nodeTo.setAttribute(fromAttribute.name, fromAttribute.value);
//        targetAtts.setNamedItem(fromAttribute);   // IE5.5 not supported
    }
}
