/*  http://www.hesperus.net/javascript/treemenu.js  Copyright (C) 2000, KAIGO */

////////////////////////////////////////////////////////////////////////////////
//
//  詳細は http://www.hesperus.net/javascript/treemenu/ を参照してください。
//
//  変更履歴
//
//  Date		Ver.	Editor	Description
//  --------	----	------	----------------------------------------
//  00/11/03	0.01	KAIGO	テストバージョン。
//  01/01/12	0.02	KAIGO	パスを変更。TreeRoot.asStringを廃止。
//
//
//  注意
//
//  「アイテム」というときは「class="TreeItem"」という属性を持ったDIVエレメント
//  を指します。TreeItemオブジェクトと区別してください。
//

////////////////////////////////////////////////////////////////////////////////
// メイン（初期化）

// グローバル変数 $hesperus は Hesperus が提供する他のJavaScriptでも使用する可能
// 性があるので、常に作成してよいわけではありません。
if (window.$hesperus) ; else {
	$hesperus = new Object();
}

// すでに初期化されていれば、余計なことはしません。
if ($hesperus.treeParam) ; else {
	$hesperus.treeParam = new TreeParam('http://www.formula-fan.com/images/window/');
	// 引数には画像ファイルへのパスを指定します。
}

////////////////////////////////////////////////////////////////////////////////
//  関数

// IE5.0以降かどうかを返す
function isIe5After()
{
	if (navigator.appName != 'Microsoft Internet Explorer') {
		return false;
	}

	var index = navigator.appVersion.indexOf('MSIE ');
	if (index < 0) {
		return false;
	}

	var separator = navigator.appVersion.indexOf(';', index += 5);
	if (separator < 0) {
		return false;
	}

	return parseFloat(navigator.appVersion.substring(index, separator)) >= 5.0;
}

// アイテムを展開する
function ExpandTreeItem(treeItem)
{
	with (treeItem) {
		var _depth = parseInt(depth);
		if (expanded = !expanded) {
			children[_depth + 0].src = $hesperus.treeParam.images[hasSibling ? 8 : 5];
			children[_depth + 1].children[0].src = $hesperus.treeParam.images[opened ? 11 : 11];
			children[_depth + 2].style.display = 'block';
		} else {
			if (OpenTreeItem.lastClicked && isGroundchild(treeItem, OpenTreeItem.lastClicked)) {
				if (href) {
					children[_depth + 1].click();
				}
			}
			children[_depth + 0].src = $hesperus.treeParam.images[hasSibling ? 7 : 4];
			children[_depth + 1].children[0].src = $hesperus.treeParam.images[opened ? 12 : 9];
			children[_depth + 2].style.display = 'none';
		}
	}
}

// アイテムを開く（排他制御）
function OpenTreeItem(treeItem)
{
	// lastClickedは最後にこの関数を通ったアイテム

	if (OpenTreeItem.lastClicked) {
		with (OpenTreeItem.lastClicked) {
			children[parseInt(depth) + 1].children[0].src = $hesperus.treeParam.images[expanded ? 10 : 9];
			opened = false;
		}
	}

	if (treeItem) {
		with (treeItem) {
			children[parseInt(depth) + 1].children[0].src = $hesperus.treeParam.images[expanded ? 11 : 12];
			opened = true;
		}
	}

	OpenTreeItem.lastClicked = treeItem;
}

// エレメントの親をさかのぼってアイテムを探す
function findTreeItem(element)
{
	while ((element = element.parentElement) && (element.className != 'TreeItem'));

	return element;
}

// ２つのエレメントが直系であるかどうかを返す。
function isGroundchild(mother, child)
{
	if (mother && child) {
		while (child = child.parentElement) {
			if (child == mother) {
				return true;
			}
		}
	}

	return false;
}

// 親のアイテムをさかのぼって探しつつ、展開されていなければそれを展開する
function CaseExpandParent(treeItem)
{
	if (treeItem) {
		while (treeItem = findTreeItem(treeItem)) {
			if (!treeItem.expanded) {
				ExpandTreeItem(treeItem);
			}
		}
	}
}

// アイテムを開く（この関数は同期を図るために使う）
function ClickItem(href)
{
	if (!$hesperus.treeParam.ie) {
		return false;
	}

	var _href = href.toLowerCase();
	for (var i = 0; i < document.links.length; i++) {
		if (_href == document.links[i].href.toLowerCase()) {
			var treeItem = findTreeItem(document.links[i]);
			CaseExpandParent(treeItem);
			OpenTreeItem(treeItem);
			return true;
		}
	}

	OpenTreeItem(null);
	return false;
}

////////////////////////////////////////////////////////////////////////////////
// イベントハンドラ

// 「＋」または「−」ボタンが押されたときにコールされる
function TreeItemOnExpand()
{
	ExpandTreeItem(findTreeItem(event.srcElement));
}

// アイテムのタイトルかフォルダのようなアイコンがクリックされたときにコールされる
function TreeItemOnOpen()
{
	var treeItem = findTreeItem(event.srcElement);

	if (treeItem.func) {
		eval(unescape(treeItem.func));
	}

	if (treeItem.href) {
		OpenTreeItem(treeItem);
	}
}

////////////////////////////////////////////////////////////////////////////////
//  TreeParam

// コンストラクタ
function TreeParam(imagePath)
{
	this.images = new Array(13);
	this.caseValues = new Array(6);

	with (this) {
		// 画像ファイルのURLを作成して保存しておきます。
		for (var i = 0; i < images.length; i++) {
			images[i] = imagePath + 'treemenu-' + (((i < 10) ? '0' : '') + i) + '.gif';
		}

		// IEのときとそうでないときで切り分ける文字列
		// こんなふうにするとメンテナンスは大変かもしれない・・・
		caseValues[0] = '';
		caseValues[1] = ' src="' + images[5] + '"';
		caseValues[2] = ' src="' + images[8] + '"';
		caseValues[3] = '';
		caseValues[4] = ' src="' + images[10] + '"';
		caseValues[5] = '<div>';
		if (this.ie = isIe5After()) {
			caseValues[0] = ' onClick="OpenTreeItem(null)"';
			caseValues[1] = ' src="' + images[4] + '" onClick="TreeItemOnExpand()"';
			caseValues[2] = ' src="' + images[7] + '" onClick="TreeItemOnExpand()"';
			caseValues[3] = ' onClick="TreeItemOnOpen()"';
			caseValues[4] = ' src="' + images[9] + '"';
			caseValues[5] = '<div style="display:none">';
		}
	}
}

////////////////////////////////////////////////////////////////////////////////
//  TreeRoot

// コンストラクタ
function TreeRoot()
{
	// TreeItemを継承
	this.inherited = TreeItem;
	this.inherited(null, null, arguments);

	// メソッドの調整
	this.addSibling = null;
	this.insertSibling = null;
	this.findLastSibling = null;
	this.toString = _tree_root_to_string;
}

// TreeRoot.toString
function _tree_root_to_string()
{
	var str = '<nobr><div class="TreeRoot" style="font-size:13"><a';
	if (this.href) {
		str += ' href="' + this.href + '"';
		if (this.target) {
			str += ' target="' + this.target + '" STYLE="TEXT-DECORATION:NONE"';
		}
		str += $hesperus.treeParam.caseValues[0];
	}
	str += '>';
	str += '<img width="21" height="16" border="0" align="absmiddle" src="' + $hesperus.treeParam.images[0] + '">';

	if (this.title) {
		str += this.title;
	}

	str += '</a><div>';

	if (this.child) {
		str += this.child.asString(0, new Array(0));
	}

	str += '</div></div></nobr>';

	return str;
}


////////////////////////////////////////////////////////////////////////////////
//  TreeItem

// コンストラクタ
function TreeItem(sibling, child, argv)
{
	// プロパティ
	this.sibling = sibling;
	this.child = child;
	this.title = null;
	this.href = null;
	this.target = null;
	this.func = null;

	// argvがあり、長さがあり、文字列でない。
	if (argv && argv.length && typeof(argv) != 'string') {
		switch (argv.length) {
		default: // これは一番上に持ってこないとダメ
		case 4:
			this.func = argv[3];
		case 3:
			this.target = argv[2];
		case 2:
			this.href = argv[1];
		case 1:
			this.title = argv[0];
		case 0: // 冗長？
			break;
		}
	}

	// メソッド
	this.addChild = _tree_item_add_child;
	this.addSibling = _tree_item_add_sibling;
	this.insertChild = _tree_item_insert_child;
	this.insertSibling = _tree_item_insert_sibling;
	this.findLastSibling = _tree_item_find_last_sibling;
	this.asString = _tree_item_as_string;
	this.toString = _tree_item_to_string;
}

// 子供を追加
function _tree_item_add_child()
{
	if (this.child) {
		var lastChild = this.child.findLastSibling();
		return lastChild.sibling = new TreeItem(null, null, arguments);
	}

	return this.child = new TreeItem(null, null, arguments);
}

// 弟を追加
function _tree_item_add_sibling()
{
	var sibling = this.findLastSibling();
	return sibling.sibling = new TreeItem(null, null, arguments);
}

// 子供を挿入
function _tree_item_insert_child()
{
	return this.child = new TreeItem(this.child, null, arguments);
}

// 兄弟を挿入
function _tree_item_insert_sibling()
{
	return this.sibling = new TreeItem(this.sibling, null, arguments);
}

// 末っ子を探す
function _tree_item_find_last_sibling()
{
	for (var element = this; element.sibling; element = element.sibling);
	return element;
}

// TreeItem.asString
function _tree_item_as_string(depth, array)
{
	// プロパティをタグへ保存する。保存しておけば、あとであるかないかを調べる必
	// 要はない。名前だけの属性を参照するとfalseとして認識できる。
	var str = '<div class="TreeItem" expanded opened depth="' + depth + '" ';

	// 弟がいるかどうかを保存
	str += 'hasSibling';
	if (this.sibling) {
		str += '="true"';
	}

	// リンク先を保存
	str += ' href';
	if (this.href) {
		str += '="' + this.href + '"';
	}

	// 関数を保存
	str += ' func';
	if (this.func) {
		str += '="' + escape(this.func) + '"';
	}

	str += '>';

	// 左側にラインまたは空白を子供としての深さの数だけ置く。
	for (var i = 0; i < depth; i++) {
		str += '<img width="19" height="16" align="absmiddle" src="'



			+ $hesperus.treeParam.images[array[i] ? 1 : 2] + '">';
	}

	// 「＋」「−」「└」「├」などを置く
	var hasSibling = this.sibling ? 2 : 0;
	var hasChild = this.child ? 1 : 0;
	switch (hasSibling + hasChild) {
	case 0:
		str += '<img width="19" height="16" align="absmiddle" src="' + $hesperus.treeParam.images[3] + '">';
		break;
	case 1:
		str += '<img width="19" height="16" align="absmiddle"' + $hesperus.treeParam.caseValues[1] + '>';
		break;
	case 2:
		str += '<img width="19" height="16" align="absmiddle" src="' + $hesperus.treeParam.images[6] + '">';
		break;
	case 3:
		str += '<img width="19" height="16" align="absmiddle"' + $hesperus.treeParam.caseValues[2] + '>';
		break;
	}

	// この位置の img は常に a の子供であるようにすると、あとでエレメントが img
	// なのか a なのかを調べる必要がないので都合が良い。
	str += '<a';
	if (this.href) {
		str += ' href="' + this.href + '"';
		if (this.target) {
			str += ' target="' + this.target + '" STYLE="TEXT-DECORATION:NONE"';
		}
	}
	if (this.href || this.func) {
		str += $hesperus.treeParam.caseValues[3];
	}
	str += '><img width="21" height="16" border="0" align="absmiddle"';
	// フォルダアイコンを置く
	if (this.child) {
		str += $hesperus.treeParam.caseValues[4];
	} else {
		str += ' src="' + $hesperus.treeParam.images[12] + '"';
	}
	str += '>' + this.title + '</a>' + $hesperus.treeParam.caseValues[5];

	// 子供のasStringを呼ぶ
	if (this.child) {
		array[depth] = (this.sibling != null); // この位置に弟がいるか否かを保存
		// 弟がいればラインを引かなければならない。
		str += this.child.asString(depth + 1, array);
	}

	str += '</div></div>';

	// 弟のasStringを呼ぶ
	if (this.sibling) {
		str += this.sibling.asString(depth, array);
	}

	return str;
}

// TreeItem.toString
function _tree_item_to_string()
{
	return '[object TreeItem]';
}