// --------------------------------------------------------------------
// Author  : mashimonator
// Create  : 2009/02/26
// Update  : 2009/02/26
//         : 2009/10/19 JQueryを使用しない形式に修正
//         : 2009/10/20 アコーディオンの表示形式（uniqueOpen）を切り替え可能に修正
// Description : アコーディオンメニューを実装する
// --------------------------------------------------------------------

/*@cc_on 
var doc = document;
eval('var document = doc');
@*/
var accordion = {
	//-----------------------------------------
	// 設定値
	//-----------------------------------------
	conf : {
		targetClass : 'accordion',                      // 対象とするクラス名
		uniqueOpen : true,                              // 一度に開くメニューを1つにするか否か（true：1つ／false：複数）
		targetTag : 'dl',                               // 対象とする要素名
		buttonTag : 'dt',                               // ボタン部分の要素名
		menuTag : 'dd',                                 // メニュー部分の要素名
		defaultOpen : 'accordionOpen',                  // 初期オープン状態に指定するクラス名
		speed : 10,                                     // スクロールの速度
		slickness : 8,                                  // スクロールの滑らかさ
		rolloverClass : 'accordionOver',                // ロールオーバー時に付加されるクラス名
		activeClass : 'accordionActive',                // アクティブ時に付加されるクラス名
		// 以下 変更不可
		classNameBaseStr : 'accordion_###_Menu',
		menuHeight : [],
		animate : false,
		showMenu : null,
		showedMenu : null,
		count : 0
	},
	//-----------------------------------------
	// 初期処理
	//-----------------------------------------
	init : function() {
		var elements = accordion.getTargetElements(accordion.conf.targetTag, accordion.conf.targetClass);
		var len = elements.length;
		for (var i = 0; i < len; i++) {
			accordion.createMenu(elements[i]);
		}
	},
	//-----------------------------------------
	// アコーディオンメニュー作成
	//-----------------------------------------
	createMenu : function( element ) {
		// ボタン部分の要素を取得
		var buttons = element.getElementsByTagName(accordion.conf.buttonTag);
		// メニュー部分の要素を取得
		var menus = element.getElementsByTagName(accordion.conf.menuTag);
		// ボタン部分の数だけ繰り返し
		var btnLen = buttons.length;
		for (var i = 0; i < btnLen; i++) {
			// クラス名生成
			var clsName = accordion.conf.classNameBaseStr.replace( '###', accordion.conf.count );
			// *************************
			// ボタンの処理
			// *************************
			// ボタン要素にスタイルを設定
			buttons[i].style.cursor = 'pointer';
			buttons[i].className += ' ' + clsName;
			var img = accordion.isContainImg(buttons[i]);
			// 画像かテキストで分岐
			if ( img ) {
				//--- img要素が含まれる場合
				if ( (img.src.match(/_n\./)) || (img.style.filter) ) {
					// ロールオーバーのイベント付加
					try{
						img.addEventListener('mouseover',accordion.over,false);
						img.addEventListener('mouseout',accordion.out,false);
					}catch(e){
						img.attachEvent('onmouseover', (function(el){return function(){accordion.over.call(el);};})(img)); 
						img.attachEvent('onmouseout', (function(el){return function(){accordion.out.call(el);};})(img)); 
					}
				}
			} else {
				//--- img要素が含まれない場合
				var child =  accordion.isContainElements(buttons[i]);
				if ( !child ) { child = buttons[i]; }
				// ロールオーバーのイベント付加
				try{
					child.addEventListener('mouseover',accordion.over,false);
					child.addEventListener('mouseout',accordion.out,false);
				}catch(e){
					child.attachEvent('onmouseover', (function(el){return function(){accordion.over.call(el);};})(child)); 
					child.attachEvent('onmouseout', (function(el){return function(){accordion.out.call(el);};})(child)); 
				}
			}
			// メソッド登録 
			buttons[i].onclick = function() {
				var className = this.className.replace(accordion.conf.rolloverClass, '').replace(accordion.conf.activeClass, '').replace(/\s/g, '');
				var button = accordion.getTargetElements(accordion.conf.buttonTag, className);
				var menu = accordion.getTargetElements(accordion.conf.menuTag, className);
				if ( menu[0] && !accordion.conf.animate ) {
					if ( menu[0].style.visibility == 'hidden' ) {
						// ボタンアクティブ
						accordion.active(menu[0]);
						// アニメーション準備
						accordion.conf.animate = true;
						accordion.conf.showMenu = menu[0];
						var elm = accordion.getSameParentVisibleNode(menu[0]);
						if ( accordion.conf.uniqueOpen && elm ) {
							// ボタン非アクティブ
							accordion.nonactive(elm);
							accordion.conf.showedMenu = elm;
							// スライド
							accordion.slideUp();
						} else {
							// スライド
							accordion.slideDown();
						}
					} else {
						// ボタン非アクティブ
						accordion.nonactive(menu[0]);
						// アニメーション準備
						accordion.conf.animate = true;
						accordion.conf.showMenu = null;
						accordion.conf.showedMenu = menu[0];
						// スライド
						accordion.slideUp();
					}
				}
				return false;
			}
			// *************************
			// メニューの処理
			// *************************
			//メニュー要素にスタイルを設定
			menus[i].className += ' ' + clsName;
			menus[i].style.overflow = 'hidden';
			// 高さを取得
			accordion.conf.menuHeight[clsName] = menus[i].offsetHeight;
			// デフォルトオープン設定
			if ( menus[i].className && !menus[i].className.match(accordion.conf.defaultOpen) ) {
				// 非表示
				menus[i].style.visibility = 'hidden';
				menus[i].style.height = '0px';
			} else {
				// デフォルトオープンの場合は表示
				menus[i].className = menus[i].className.replace(accordion.conf.defaultOpen, '');
				accordion.active(menus[i]);
				menus[i].style.visibility = 'visible';
			}
			// カウントアップ
			accordion.conf.count = accordion.conf.count + 1;
		}
	},
	//-----------------------------------------
	// mouseover
	//-----------------------------------------
	over : function() {
		if ( !this.className || !this.className.match(accordion.conf.activeClass) ) {
			if ( this.nodeName.toUpperCase() != 'IMG' ) {
				this.className += ' ' + accordion.conf.rolloverClass;
			} else {
				if ( (this.style) && (this.style.filter) && (this.style.filter.match(/_n\.png/)) ) { //(IE5.5-6 && png)
					this.style.filter = this.style.filter.replace('_n.png', '_r.png');
				} else {
					this.src = this.src.replace('_n.', '_r.');
				}
			}
		}
	},
	//-----------------------------------------
	// mouseout
	//-----------------------------------------
	out : function() {
		if ( !this.className || !this.className.match(accordion.conf.activeClass) ) {
			if ( this.nodeName.toUpperCase() != 'IMG' ) {
				this.className = this.className.replace(accordion.conf.rolloverClass, '');
			} else {
				if ( (this.style) && (this.style.filter) && (this.style.filter.match(/_r\.png/)) ) { //(IE5.5-6 && png)
					this.style.filter = this.style.filter.replace('_r.png', '_n.png');
				} else {
					this.src = this.src.replace('_r.', '_n.');
				}
			}
		}
	},
	//-----------------------------------------
	// active設定
	//-----------------------------------------
	active : function( element ) {
		var button = accordion.getCorrespondingButtonFromMenu(element);
		var img = accordion.isContainImg(button);
		if ( img ) {
			if ( (img.style) && (img.style.filter) && (img.style.filter.match(/_r\.png/)) ) { //(IE5.5-6 && png)
				img.style.filter = img.style.filter.replace('_r.png', '_a.png');
				img.style.filter = img.style.filter.replace('_n.png', '_a.png');
			} else {
				img.src = img.src.replace('_r.', '_a.');
				img.src = img.src.replace('_n.', '_a.');
			}
			img.className += ' ' + accordion.conf.activeClass;
		} else {
			var child = accordion.isContainElements(button);
			if ( !child ) { child = button; }
			if ( child.className ) {
				child.className = child.className.replace(accordion.conf.rolloverClass, '');
			}
			child.className += ' ' + accordion.conf.activeClass;
		}
	},
	//-----------------------------------------
	// active解除
	//-----------------------------------------
	nonactive : function( element ) {
		var button = accordion.getCorrespondingButtonFromMenu(element);
		var img = accordion.isContainImg(button);
		if ( img ) {
			element = img;
			if ( (element.style) && (element.style.filter) && (element.style.filter.match(/_r\.png/)) ) { //(IE5.5-6 && png)
				element.style.filter = element.style.filter.replace('_a.png', '_n.png');
			} else {
				element.src = element.src.replace('_a.', '_n.');
			}
		} else {
			var child = accordion.isContainElements(button);
			if ( child ) { 
				element = child;
			} else {
				element = button;
			}
		}
		element.className = element.className.replace(accordion.conf.activeClass, '');
	},
	//-----------------------------------------
	// menu部をスライド（close）
	//-----------------------------------------
	slideUp : function() {
		var tmp = accordion.conf.showedMenu.offsetHeight;
		if ( tmp > 0 ) {
//			accordion.conf.showedMenu.style.visibility = 'visible';
//			accordion.conf.showedMenu.style.height = (tmp - accordion.conf.slickness)  + 'px';
//			window.setTimeout('accordion.slideUp()', accordion.conf.speed);
//		} else {
			accordion.conf.showedMenu.style.height = '0px';
			accordion.conf.showedMenu.style.visibility = 'hidden';
			if ( accordion.conf.showMenu && (accordion.conf.showMenu != accordion.conf.showedMenu) && (accordion.conf.showMenu.style.visibility == 'hidden') ) {
				accordion.conf.showedMenu = null;
				accordion.slideDown();
			} else {
				accordion.conf.animate = false;
			}
		}
	},
	//-----------------------------------------
	// menu部をスライド（open）
	//-----------------------------------------
	slideDown : function() {
		var className = accordion.conf.showMenu.className;
		var h = accordion.conf.menuHeight[className.replace(/^\s/g, '').replace(/\s$/g, '')];
		var tmp = accordion.conf.showMenu.offsetHeight;
		if ( tmp < h ) {
			accordion.conf.showMenu.style.visibility = 'visible';
			accordion.conf.showMenu.style.height = (tmp + accordion.conf.slickness)  + 'px';
			window.setTimeout('accordion.slideDown()', accordion.conf.speed);
		} else {
			accordion.conf.showMenu.style.height = h + 'px';
			accordion.conf.showMenu = null;
			accordion.conf.animate = false;
		}
	},
	//-----------------------------------------
	// メニューに対応するボタンを返す
	//-----------------------------------------
	getCorrespondingButtonFromMenu : function( element ) {
		var result = false;
		var reg1 = new RegExp(accordion.conf.rolloverClass, 'ig');
		var reg2 = new RegExp(accordion.conf.activeClass, 'ig');
		var className = element.className.replace(reg1, '').replace(reg2, '').replace(/\s/g, '');
		var button = accordion.getTargetElements(accordion.conf.buttonTag, className);
		if ( button[0] ) {
			result = button[0];
		}
		return result;
	},
	//-----------------------------------------
	// 同じ親要素内のナビで開いているメニューを返す
	//-----------------------------------------
	getSameParentVisibleNode : function( element ) {
		var result = false;
		var parent = element.parentNode;
		var dt = parent.getElementsByTagName(accordion.conf.buttonTag);
		var len = dt.length;
		var reg = new RegExp(accordion.conf.classNameBaseStr.replace('###','([0-9]+)'),'i');
		for (var i = 0; i < len; i++) {
			if ( dt[i].className ) {
				var className = dt[i].className.replace(accordion.conf.rolloverClass, '').replace(accordion.conf.activeClass, '').replace(/\s/g, '');
				if ( dt[i] != element && className.match(reg) ) {
					var dd = accordion.getTargetElements(accordion.conf.menuTag, className);
					if ( dd[0] && dd[0].style.visibility == 'visible' ) {
						result = dd[0];
						break;
					}
				}
			}
		}
		return result;
	},
	//-----------------------------------------
	// 対象要素が子要素を含むかを返す
	//-----------------------------------------
	isContainElements : function( element ) {
		if ( element ) {
			if ( element.hasChildNodes() ) {
				var len = element.childNodes.length;
				var elements = element.childNodes;
				var result = false;
				for (var i = 0; i < len; i++) {
					if ( elements[i].nodeType == '1' ) {
						result = elements[i];
						break;
					}
				}
				return result;
			} else {
				return false;
			}
		}
	},
	//-----------------------------------------
	// 対象要素がimg要素を含むかを返す
	//-----------------------------------------
	isContainImg : function( element ) {
		if ( element ) {
			var img = element.getElementsByTagName('IMG');
			if ( img[0] ) {
				return img[0];
			} else {
				return false;
			}
		}
	},
	//-----------------------------------------
	// ターゲットタグを取得する
	//-----------------------------------------
	getTargetElements : function( tag, cls ) {
		var elements = new Array();
		var targetElements = document.getElementsByTagName(tag.toUpperCase());
		var len = targetElements.length;
		for ( var i = 0; i < len; i++ ) {
			if ( targetElements[i].className.match(cls) ) {
				elements[elements.length] = targetElements[i];
			}
		}
		return elements;
	},
	//-----------------------------------------
	// イベントに関数を付加する
	//-----------------------------------------
	addEvent : function( target, event, func ) {
		try {
			target.addEventListener(event, func, false);
		} catch (e) {
			target.attachEvent('on' + event, func);
		}
	}
}
// Loadが終わるまで非表示にする
// ----------------------------------------
document.write('<style type="text/css">');
document.write('.'+accordion.conf.targetClass+' '+accordion.conf.menuTag+' {visibility:hidden;}');
document.write('</style>');
// ----------------------------------------
// 実行
accordion.addEvent( window, 'load', accordion.init );
