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

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

/*
 * 指定要素のクラスに、文字列を追加する。
 */
HtmlUtil.addClassValue = function (element, classValue) {

    var ptn = new RegExp("\\b"+classValue+"\\b");

    /*
     * 既に存在すれば、なにもしない。
     */
    if (-1 == element.className.search(ptn)) {

        element.className += " " + classValue;
    }
}

/*
 * 指定要素のクラスから、文字列を削除する。
 */
HtmlUtil.removeClassValue = function (element, classValue) {

    return HtmlUtil.replaceClassValue(element, classValue, "");
}

/*
 * 指定要素のクラスから、oldValueを削除し、newValueに変更する。
 */
HtmlUtil.replaceClassValue = function (element, oldValue, newValue) {

    var ptn = new RegExp("\\b"+oldValue+"\\b", "g");
    var className = element.className;
    element.className = className.replace(ptn, newValue);

    if (element.className == className) {

        /*
         * 変更なし
         */
        return false;
    }

    return true;
}

HtmlUtil.bufferIdTable = 1000;
HtmlUtil.listenerList = new Object();

HtmlUtil.saveFormListener = function (e) {

    var evnt = EventUtil.createEvent(e);
    var listener = HtmlUtil.listenerList[evnt.currentTarget.name];
    HtmlUtil.listenerList[evnt.currentTarget.name] = null;

    /*
     * ここで、フレーム内のドキュメントをコピーし、リスナーの渡す。
     * フレームは、削除する。
     */
    AppUtil.printLog("LOAD !");
    
    listener.saveFormAction(evnt.currentTarget);
}
HtmlUtil.saveFormErrorListener = function (e) {

    AppUtil.printLog("ERROR !");
}
HtmlUtil.saveFormAbortListener = function (e) {

    AppUtil.printLog("ABORT !");
}
/**
 * フォームセーブ
 * 指定されたformの内容を、uriに送信する。
 * 結果は、iframeに読み込む。
 */
HtmlUtil.saveFormToUri = function (form, listener, uri, method) {

    var appArea = document.getElementById(AppUtil.APPID_APPAREA);

    /*
     * サーバとの通信バッファ作成。
     */
    var buffer = document.createElement("iframe");
//    buffer.id = "id_" + HtmlUtil.bufferIdTable;
    buffer.name = "id_" + HtmlUtil.bufferIdTable;
    HtmlUtil.bufferIdTable ++;
    buffer.src = "";
//    buffer.style.display = "none";
    buffer = appArea.appendChild(buffer);

    /*
     * URIが指定されたいた場合は、formのactionを上書きする。
     */
    if (uri) {

        form.action = uri;
    }

    /*
     * メソッドが指定されたいた場合は、formのmethodを上書きする。
     */
    if (method) {

        form.method = method;
    }

    form.target = buffer.name;
//    form.target = AppUtil.APPID_COMMUBUF
    buffer.onload = HtmlUtil.saveFormListener;
    buffer.onerror = HtmlUtil.saveFormErrorListener;
    buffer.onabort = HtmlUtil.saveFormAbortListener;
    HtmlUtil.listenerList[buffer.name] = listener;

    form.submit();
}

/**
 * 指定要素までのスクロール
 * @param target : 要素 : スクロールさせたい要素。
 *                 この要素の上辺までスクロールさせる。
 * @param margin : 数値(px) : スクロール位置を、targetの上辺 - marginとする。
 */
HtmlUtil.scrollTo = function (target, margin) {

    if (null == margin) {

        margin = 0;
    }

    var top = target.offsetTop - margin;
    window.scrollTo(0, top);
}

/**
 * テーブルエレメントを、DOMで使いやすくするラッパクラス
 * コンストラクタ
 * @param table : 要素 : テーブルエレメント
 */
function JSTable(table) {

    if (table) {

        if (table.tagName) {

            if (table.tagName.toLowerCase() == "table") {

                this.table = table;
                return;
            }
        }
    }

    throw "JSTable:Illegal argment table is null";
}

/**
 * テーブルの総行数(ヘッダ・ボディ・フッタ含む)を返します。
 * @return テーブルの総行数(ヘッダ・ボディ・フッタ含む)
 */
JSTable.prototype.getRowCount = function() {

    return this.table.rows.length;
}

/**
 * テーブルのボディ部の合計行数を返します。
 * @return テーブルのボディ部の合計行数
 */
JSTable.prototype.getBodiesRowCount = function() {

    var bodies = this.table.tBodies;
    var length = bodies.length;
    var count = 0;
    for (var i = 0; i < length; i ++) {

        count += bodies.item(i).rows.length;
    }
    return count;
}

/**
 * 指定インデックスの行エレメントを、ボディ部から取得し返します。
 * @param rowIndex : 数値 : 取得したい行の0を先頭とする行数。
 *        テーブル全体の行数ではなく、ボディ部全体の行数を指定する。
 * @return 行エレメント。該当する行が存在しない場合、null。
 */
JSTable.prototype.getRowFromBodiesAt = function(rowIndex) {

    /*
     * 引数のインデックスが、0より小さい場合、返す行はない。
     */
    if (0 > rowIndex) {

        return null;
    }

    var index = rowIndex;
    var bodies = this.table.tBodies;
    var bodiesLength = bodies.length;
    for (var i = 0; i < bodiesLength; i ++) {

        var body = bodies.item(i);
        var rowLength = body.rows.length;
        if (index < rowLength) {
            /*
             * このボディに該当行あり
             */
            return body.rows.item(index);
        }
        else {
            /*
             * このボディには該当行なし
             */
            index -= rowLength;
        }
    }
    /*
     * ここへ来てしまったら、引数不正
     * ボディにある総行数よりも、引数の方が大きい
     */
    return null;
}

/**
 * 指定インデックスのセルを、ボディ部から取得し返します。
 * @param rowIndex : 数値 : 取得したいセルの0を先頭とする行数。
 *        テーブル全体の行数ではなく、ボディ部全体の行数を指定する。
 * @param columnIndex : 数値 : 取得したいセルの0を先頭とする列数。
 * @return 行インデックスと列インデックスに該当するセル要素。
 *         該当する行または列が存在しない場合、null。
 */
JSTable.prototype.getCellFromBodiesAt = function (rowIndex, columnIndex) {

    var row = this.getRowFromBodiesAt(rowIndex);

    if (! row || row.cells.length <= columnIndex) {

        return null;
    }

    return row.cells.item(columnIndex);
}

/**
 * 指定インデックスのセルを、フッタ部から取得し返します。
 * @param rowIndex : 数値 : 取得したいセルの0を先頭とする行数。
 *        テーブル全体の行数ではなく、フッタ部の行数を指定する。
 * @param columnIndex : 数値 : 取得したいセルの0を先頭とする列数。
 * @return 行インデックスと列インデックスに該当するセル要素。
 *         該当する行または列が存在しない場合、null。
 */
JSTable.prototype.getCellFromFootAt = function (rowIndex, columnIndex) {

    if (null == this.table.tFoot) {

        return null;
    }

    if (rowIndex >= this.table.tFoot.rows.length) {

        return null;
    }

    var row = this.table.tFoot.rows.item(rowIndex);

    if (! row || row.cells.length <= columnIndex) {

        return null;
    }

    return row.cells.item(columnIndex);
}

/**
 * 指定の行インデックスと列インッデクスが、有効かどうかをテストします。
 * 有効な場合true、無効な場合はfalseを返します。
 */
JSTable.prototype.isValidIndex = function(rowIndex, columnIndex) {

    try {

        if (rowIndex < 0 || columnIndex < 0) {

            throw "";
        }

        var rowItem = this.getBodiesRowAt(rowIndex);
        if (columnIndex < rowItem.cells.length) {

            return true;
        }
    }
    catch (e) {}

    return false;
}

/**
 * ボディ部の指定のインデックスに行を挿入する。
 * インデックスが0より小さい場合や、ボディ部の総行数より大きい場合は、
 * ボディ部の最期に追加する。
 * @param rowIndex : 数値 : 追加／挿入したい行の0を先頭とする行数。
 *        テーブル全体の行数ではなく、ボディ部全体の行数を指定する。
 * @return 追加／挿入した行要素。
 */
JSTable.prototype.insertRowAt = function(rowIndex) {

    var bodiesRowCount = this.getBodiesRowCount();

    /*
     * 引数のインデックスが、0より小さい場合や、ボディ部の総行数より
     * 大きい場合は、最期に追加する。
     */
    if (0 > rowIndex || bodiesRowCount <= rowIndex) {

        rowIndex = bodiesRowCount;
    }

    var body = null;
    var index = rowIndex;
    var bodies = this.table.tBodies;
    var bodiesLength = bodies.length;
    for (var i = 0; i < bodiesLength; i ++) {

        body = bodies.item(i);
        var rowLength = body.rows.length;
        if (index < rowLength) {
            /*
             * このボディに該当行あり
             */
            return body.insertRow(index);
        }
        else {
            /*
             * このボディには該当行なし
             */
            index -= rowLength;
        }
    }

    /*
     * 最期のボディ部に行を追加する。
     */
    if (null != body) {

        return body.insertRow(-1);
    }

    /*
     * ここへくることは、ロジック上あり得ない。
     */
    return null;
}


