/**
 *	@filename		height_controller.js
 *	@charset		utf-8
 *	@created		October 8, 2009
 *	@lastmodified	November 2, 2009
 *	@description	高さ調整用
 */
 
/**
 *	@class HeightController
 *	@param {Element/ElementList/Array} elements
 */
var HeightController = function(elements){
	
	var self = this;
	
	//ブラウザ判定
	this.isIE = document.all && !window.opera;
	this.isFX = navigator.userAgent.indexOf("Firefox") > -1;
	
	this.head = document.getElementsByTagName("head")[0];
	this.elementSet = [];
	
	//スタイルシート作成
	if(this.isIE){
		this.styleSheet = document.createStyleSheet();
	}else{
		this.styleSheet = document.createElement("style");
		this.head.appendChild(this.styleSheet);
	}
	
	//引数が指定されていた場合
	if(elements){
		this.addElements(elements);
	}
	
	//フォントサイズ変更時にイベント登録
	(new OnFontSizeChange()).addEventListener("change", function(){
		self.setHeight();
	});
};

HeightController.CLASS_NAME_PREFIX = "height_controller_";

/**
 *	@param {ElementList/Array} elements
 *
 *	高さを揃えたい要素群を追加ます。
 *	それら要素群の中で最も高さが大きい要素に高さを合わせます。
 *	フォントサイズ変化時にも同様の処理が行われます。
 */
HeightController.prototype.addElements = function(elements){
	
	//任意のクラス名を作成
	var className = HeightController.CLASS_NAME_PREFIX + this.elementSet.length;
	
	//リストに追加
	this.elementSet.push({
		elements : elements,
		className : className
	});
	
	//クラス名を付与
	var i=0, len=elements.length;
	while(i<len){
		elements[i].className += (" " + className);
		i++;
	}
	
	this.setHeight();
};

/**
 *	@param {ElementList/Array} elements
 *	@param {Number} 何個ずつ揃えるか
 */
HeightController.prototype.addElementsWithPairing = function(elements, pairNum){
	var pair;
	for(var i=0, len=elements.length; i<len; i += pairNum){
		pair = [];
		for(var j=i, len2 = i + pairNum; j<len2; j++){
			if(elements[j]){
				pair.push(elements[j]);
			}
		}
		this.addElements(pair);
		pair = null;
	}
};

/**
 *	@return {void}
 *
 *	要素の高さを設定します。
 */
HeightController.prototype.setHeight = function(){
	//高さをリセット
	this.resetHeight();
	
	//最大高さを計算しcssルールを作成
	var rules = [];
	var maxHeight, _h;
	var i=0, len=this.elementSet.length;
	while(i<len){
		maxHeight = _h = 0;
		var j=0, len2=this.elementSet[i].elements.length;
		while(j<len2){
			//_h= this.elementSet[i].elements[j].offsetHeight;
			_h= this.calcHeight(this.elementSet[i].elements[j]);
			maxHeight = maxHeight < _h ? _h : maxHeight;
			j++;
		}
		rules.push("." + this.elementSet[i].className + "{height:" + maxHeight + "px!important;}");
		i++;
	}
	
	//cssを適応
	if(this.isIE){
		this.styleSheet.cssText = rules.join("");
	}else if(this.isFX){
		this.styleSheet.innerHTML = rules.join("");
	}else{
		var k = 0;
		var len3 = rules.length;
		while(k < len3){
			this.styleSheet.sheet.insertRule(rules[k], k);
			k++;
		}
	}
};

/**
 *	@param {Element} obj
 *	@return {Number}
 *
 *	各要素のパッディング・ボーダーを計算します。
 *	この処理はパフォーマンス向上のため一度しか行われません。
 *	パッディング・ボーダーが動的に変化する場合には対応していません。
 */
HeightController.prototype.calcAttributes = function(obj){
	var padding=0, border=0, borderTop=0, borderBottom=0, style;
	if(this.isIE){
		style = obj.currentStyle;
		if(typeof XMLHttpRequest !== "undefined"){//IE7 or later
			padding = parseInt(style.getAttribute("paddingTop"), 10) + parseInt(style.getAttribute("paddingBottom"), 10);
		}else{
			borderTop = parseInt(style.getAttribute("borderTopWidth"), 10);
			borderTop = isNaN(borderTop) ? 0 : borderTop;
			
			borderBottom = parseInt(style.getAttribute("borderBottomWidth"), 10);
			borderBottom = isNaN(borderBottom) ? 0 : borderBottom;
			
			border = borderTop + borderBottom;
			//alert(border);
		}
	}else{
		style = document.defaultView.getComputedStyle(obj, null);
		padding = parseInt(style.getPropertyValue("padding-top"), 10) + parseInt(style.getPropertyValue("padding-bottom"), 10);
	}
	obj.__heightControllerAttributes = (padding + border);
	return obj.__heightControllerAttributes;
};

/**
 *	@param {Element} obj
 *	@return {Number}
 *
 *	各要素の高さを計算します。
 */
HeightController.prototype.calcHeight = function(obj){
	var height=0, attr=0;
	if(!isNaN(obj.__heightControllerAttributes)){
		attr = obj.__heightControllerAttributes;
	}else{
		attr = this.calcAttributes(obj);
	}
	height = obj.offsetHeight;
	return height - attr;
};

/**
 *	@retrun {void}
 *
 *	スタイル―シートをリセットし高さ指定を解除します。
 */
HeightController.prototype.resetHeight = function(){
	if(this.isIE){
		this.styleSheet.cssText = "";
	}else if(this.isFX){
		this.styleSheet.innerHTML = "";
	}else{
		this.head.removeChild(this.styleSheet);
		this.styleSheet = document.createElement("style");
		this.head.appendChild(this.styleSheet);
	}
};