/*
 * tree.js -- DHTML でツリー表示をするための JavaScript
 *
 * 注意：prototype.js が必要。
 *
 * 2006/08/07 by Shigeru Hagiwara
 */

var HtmlTree = {
    /** 開いている状態を示す画像 */
    NODE_MINUS_IMG :  "imgs/node_minus.gif",
    /** 閉じている状態を示す画像 */
    NODE_PLUS_IMG : "imgs/node_plus.gif",

    semicolonPattern : /\s*;\s*/,
    treeNodeClassPat : new RegExp("(^|\\s)treeNode(\\s|$)"),
    nodeLeafClassPat : new RegExp("(^|\\s)(treeNode|treeLeaf)(\\s|$)"),

    treeStatus : {}
}

HtmlTree.minusImgPat = new RegExp(HtmlTree.NODE_MINUS_IMG + "$");
HtmlTree.plusImgPat = new RegExp(HtmlTree.NODE_PLUS_IMG + "$");


/**
 * ツリーの状態を初期化する
 */
HtmlTree.initTree = function() {
    /* クッキー中のツリーの状態を取得する */
    HtmlTree.loadTreeStatus();
    var isFirstTime = false;
    if (HtmlTree.treeStatus.keys().length == 0) {
	HtmlTree.treeStatus = {};
	isFirstTime = true;
    }

    var counter = 0;
    var root = $('treeRoot');
    if (root == undefined) {
	return;
    }
    for (var i = 0; i < root.childNodes.length; i++) {
	/* child の div の表示状態をトグルする */
	var child = root.childNodes[i];
	if (child.nodeName == "DIV" && child.className.match(HtmlTree.nodeLeafClassPat)) {
	    if (isFirstTime) {
		HtmlTree.treeStatus[counter] = true;
	    }
	    counter = HtmlTree.initNode(child, counter);
	}
    }
    if (isFirstTime) {
	HtmlTree.saveTreeStatus();
    }
}

HtmlTree.initNode = function(node, counter) {
    HtmlTree.setNodeVisible(node, HtmlTree.treeStatus[counter] || false);
    node.nodeNumber = counter;
    counter++;
    for (var i = 0; i < node.childNodes.length; i++) {
	var child = node.childNodes[i];
	if (child.nodeName == "DIV" && child.className.match(HtmlTree.nodeLeafClassPat)) {
	    counter = HtmlTree.initNode(child, counter);
	}
    }
    return counter;
}

/**
 * ツリーの状態をクッキーから取得する
 */
HtmlTree.loadTreeStatus = function() {
    var cookieList = document.cookie.split(HtmlTree.semicolonPattern);
    HtmlTree.treeStatus = $H({});
    for (var i = 0; i < cookieList.length; i++) {
	var pair = cookieList[i].split('=');	
	if (pair[0] == 'ts') {
	    HtmlTree.treeStatus = $H(decodeURI(pair[1]).parseJSON());
	    break;
	}
    }
}

/**
 * ツリーの状態をクッキーへ保存する
 */
HtmlTree.saveTreeStatus = function() {
    var ts = encodeURI(HtmlTree.treeStatus.toJSONString());
    document.cookie = 'ts=' + ts + "; expires=Tue, 1-Jan-2030 00:00:00 GMT;";
}

/**
 * ツリーを開閉するための画像が, クリックされたときに呼び出される関数
 */
HtmlTree.nodeButtonClicked = function(e) {
    var eTarget = (e.target || e.srcElement);    
    var imgSrc = eTarget.src || eTarget.parentNode.firstChild.src;
    if (imgSrc.match(HtmlTree.minusImgPat)) {
	HtmlTree.setNodeVisible(eTarget.parentNode, false);
    } else {
	HtmlTree.setNodeVisible(eTarget.parentNode, true);
    }
    HtmlTree.saveTreeStatus();
    // HtmlTree.setCursorClear(e);
}

HtmlTree.setCursorWait = function(e) {
    var eTarget = (e.target || e.srcElement);
    eTarget.style.cursor = "wait";
    document.body.style.cursor = "wait";
}

HtmlTree.setCursorClear = function(e) {
    var eTarget = (e.target || e.srcElement);
    eTarget.style.cursor = "default";
    document.body.style.cursor = "auto";
}

HtmlTree.displayUnderline = function(e) {
    var eTarget = (e.target || e.srcElement);
    if (eTarget.nodeName == 'IMG') {
	//eTarget.nextSibling.style.textDecoration = "underline";
	var sibling = HtmlTree.findNextSiblingElement(eTarget);
	if (sibling != null) {
	    sibling.style.textDecoration = "underline";
	}
    } else {
	eTarget.style.textDecoration = "underline";
    }
}

HtmlTree.hideUnderline = function(e) {
    var eTarget = (e.target || e.srcElement);
    if (eTarget.nodeName == 'IMG') {
	//eTarget.nextSibling.style.textDecoration = "none";	
	var sibling = HtmlTree.findNextSiblingElement(eTarget);
	if (sibling != null) {
	    sibling.style.textDecoration = "none";
	}
    } else {
	eTarget.style.textDecoration = "none";
    }
}

HtmlTree.findNextSiblingElement = function(element) {
    var sibling = element.nextSibling;
    if (sibling == null) {
	return null;
    }
    while (sibling.nodeType != 1) {
	sibling = sibling.nextSibling;
    }
    return sibling;
}

/**
 * ノードが開閉ボタン画像を持っていない場合、初期化する
 */
HtmlTree.initTreeNode = function(element) {
    var firstChildElement = element.firstChild;
    while (firstChildElement.nodeType != 1) { // nodeType が 1 というのは、 Node.ELEMENT_NODE ということ
	firstChildElement = firstChildElement.nextSibling;
	if (firstChildElement == null) {
	    return;
	}
    }
    
    var nodeImgElem = document.createElement("img");
    nodeImgElem.className = "nodeImg";
    // Event.observe(firstChildElement, 'mousedown', HtmlTree.setCursorWait, false);
    Event.observe(firstChildElement, 'mouseup', HtmlTree.nodeButtonClicked, false);
    if (firstChildElement.style) {
	firstChildElement.style.cursor = "default";
	// firstChildElement.style.marginBottom = "2px";
    }
	    
    Event.observe(firstChildElement, "mouseover", HtmlTree.displayUnderline, false);
    Event.observe(firstChildElement, "mouseout", HtmlTree.hideUnderline, false);
	    
    element.insertBefore(nodeImgElem, element.firstChild);
    // Event.observe(nodeImgElem, 'mousedown', HtmlTree.setCursorWait, false);
    Event.observe(nodeImgElem, 'mouseup', HtmlTree.nodeButtonClicked, false);
    Event.observe(nodeImgElem, "mouseover", HtmlTree.displayUnderline, false);
    Event.observe(nodeImgElem, "mouseout", HtmlTree.hideUnderline, false);
}

/**
 * ノードを開閉するための関数。
 *
 * 引数：
 *   element は treeNode クラスか treeLeaf クラスの div エレメント。
 *   visible は boolean
 */
HtmlTree.setNodeVisible = function(element, visible) {
    /* クッキー中のツリーの状態を更新する */
    HtmlTree.treeStatus[element.nodeNumber] = visible;

    if (element.nodeName == "DIV" && element.className.match(HtmlTree.treeNodeClassPat)) {
	/* leaf でなくて、途中の node だった場合 */
	if (element.firstChild.nodeName != "IMG"
	    || (! element.firstChild.src.match(HtmlTree.minusImgPat)
		&& ! element.firstChild.src.match(HtmlTree.plusImgPat))) {
	    HtmlTree.initTreeNode(element);
	}
	/* 開閉画像をトグルする */
	element.firstChild.src = visible ? HtmlTree.NODE_MINUS_IMG : HtmlTree.NODE_PLUS_IMG;
    }

    for (var i = 0; i < element.childNodes.length; i++) {
	/* child の div の表示状態をトグルする */
	var child = element.childNodes[i];
	if (child.nodeName == "DIV" && child.className.match(HtmlTree.nodeLeafClassPat)) {
	    child.style.display = visible ? "block" : "none";
	}
    }
   
}

/* ページがロードされたときに、ツリーの状態を初期化する */
Event.observe(window, 'load', HtmlTree.initTree, false);

// EOF

