var MSIE, Netscape, Opera, Safari, Firefox;

if(window.navigator.appName.indexOf("Internet Explorer") >= 0){
	MSIE = true;
}else if(window.navigator.appName == "Opera"){
	Opera = true;
}else if(window.navigator.userAgent.indexOf("Safari") >= 0){
	Safari = true;
}else if(window.navigator.userAgent.indexOf("Firefox") >= 0){
	Firefox = true;
	Netscape = true;
}else{
    Netscape = true;
}


/*------------------------------------------------------------*/
// 表示・非表示を切り替えたときのアニメーション
//
// ANIMATION_NONE       : アニメーションなし
// ANIMATION_VERTICAL   : 垂直方向に広がるアニメーション
// ANIMATION_HORIZONTAL : 水平方向に広がるアニメーション
// ANIMATION_OPACITY    : 透明度を変えていくアニメーション
/*------------------------------------------------------------*/
var ANIMATION_NONE       = 0;
var ANIMATION_VERTICAL   = 1 << 1;
var ANIMATION_HORIZONTAL = 1 << 2;
var ANIMATION_OPACITY    = 1 << 3;


/*------------------------------------------------------------*/
////////////////////////////////////////////////////////////////
// レイヤ操作関連メソッド
////////////////////////////////////////////////////////////////
//
// レイヤの作成
//   var layer = new Component(id);
//
// レイヤの背景色設定
//   layer.backgroundColor("#000000");
//
// レイヤの透明度設定
//   layer.opacity(50);
//
// レイヤのサイズ設定
//   layer.size(width, height);
//      or
//   layer.width(width);
//   layer.height(height);
//
// レイヤの移動
//   layer.move(x, y);
//      or
//   layer.x(x);
//   layer.y(y);
//
// レイヤの表示・非表示
//   layer.visible(true or false);
//
// レイヤの表示・非表示のアニメーション設定
//   layer.animation(mode);
//     ANIMATION_NONE       : アニメーションなし
//     ANIMATION_VERTICAL   : 垂直方向に広がるアニメーション
//     ANIMATION_HORIZONTAL : 水平方向に広がるアニメーション
//     ANIMATION_OPACITY    : 透明度を変えていくアニメーション
//
////////////////////////////////////////////////////////////////
// ブラウザの情報を取得するための関数郡
////////////////////////////////////////////////////////////////
//
// ブラウザの表示領域のサイズを取得する
//   getBrowserInnerWidth()
//   getBrowserInnerHeigth()
//
// ページスクロール時の表示開始位置を取得する
//   getPageXOffset()
//   getPageYOffset()
//
// マウスの位置情報を取得する
//   getCurrentMouseX()
//   getCurrentMouseY()
//
////////////////////////////////////////////////////////////////
// イベントハンドラ関連の関数郡
////////////////////////////////////////////////////////////////
//
// ウィンドウリサイズイベントのハンドラ登録
//   addWindowResizeEventHandler(func);
//
// ウィンドウスクロールイベントのハンドラ登録
//   addWindowScrollEventHandler(func);
//
// マウス移動イベントのハンドラ登録
//   addDocumentMouseMoveEventHandler(func);
//
/*------------------------------------------------------------*/

//-------------------------------------------------------------
// コンストラクタ
//-------------------------------------------------------------
function Component(id)
{
	this._component = document.getElementById(id);
	this._opacity_change_interval = 1;
	this._animation = ANIMATION_NONE;
	
	var opc = this._component.style.opacity;
	if(opc == "")
	{
		opc = 1;
	}
	this._opacity = opc * 100;
}


//-------------------------------------------------------------
// レイヤのidを取得するメソッド
//-------------------------------------------------------------
Component.prototype.id = function()
{
	return this._component.id;
}


//-------------------------------------------------------------
// レイヤに表示するテキストのフォントサイズを設定するメソッド。
// 引数を指定しない場合は現在のフォントサイズを返す。
//-------------------------------------------------------------
Component.prototype.fontSize = function(size)
{
	if(_defined(size))
	{
		this._component.style.fontSize = size + "px";
	}
	else
	{
		return this._component.style.fontSize;
	}
}


//--------------------------------------------------------------
// 表示・非表示の時に徐々に透明度を変えていく間隔（時間）を
// 設定する。値が小さいほど速く変化する。
//--------------------------------------------------------------
Component.prototype.opacityChangeInterval = function(interval)
{
	if(typeof(interval) == "undefined")
	{
		return this._opacity_change_interval;
	}
	else
	{
		this._opacity_change_interval = interval;
	}
}


//--------------------------------------------------------------
// 内部に表示するHTMLを変更するメソッド
//--------------------------------------------------------------
Component.prototype.html = function(html)
{
	var component = this._component;
	
	if(typeof(html) == "undefined")
	{
		return component.innerHTML;
	}
	else
	{
		component.innerHTML = html;
	}
}


//----------------------------------------------------------
// 背景色変更メソッド
//----------------------------------------------------------
Component.prototype.backgroundColor = function(color)
{
	this._component.style.backgroundColor = color;
}


//----------------------------------------------------------
// 上のボーダーのスタイル設定をする。
//----------------------------------------------------------
Component.prototype.borderTop = function(border)
{
	if(_defined(border)){
		var comp = this._component;
		if(MSIE)
		{
			//comp.style.borderTop = border.color();
			//comp.style.border-top-style = border.style();
			//comp.style.border-top-width = border.width();
		}
		else
		{
			comp.style.borderTopColor = border.color();
			comp.style.borderTopStyle = border.style();
			comp.style.borderTopWidth = border.width() + "px";
		}
	}
}


//----------------------------------------------------------
// 下のボーダーのスタイル設定をする。
//----------------------------------------------------------
Component.prototype.borderBottom = function(border)
{
	if(_defined(border)){
		var comp = this._component;
		if(MSIE)
		{
		}
		else
		{
			comp.style.borderBottomColor = border.color();
			comp.style.borderBottomStyle = border.style();
			comp.style.borderBottomWidth = border.width() + "px";
		}
	}
}


//----------------------------------------------------------
// 左のボーダーのスタイル設定をする。
//----------------------------------------------------------
Component.prototype.borderLeft = function(border)
{
	if(_defined(border)){
		var comp = this._component;
		if(MSIE)
		{
		}
		else
		{
			comp.style.borderLeftColor = border.color();
			comp.style.borderLeftStyle = border.style();
			comp.style.borderLeftWidth = border.width() + "px";
		}
	}
}


//----------------------------------------------------------
// 右のボーダーのスタイル設定をする。
//----------------------------------------------------------
Component.prototype.borderRight = function(border)
{
	if(_defined(border)){
		var comp = this._component;
		if(MSIE)
		{
		}
		else
		{
			comp.style.borderRightColor = border.color();
			comp.style.borderRightStyle = border.style();
			comp.style.borderRightWidth = border.width() + "px";
		}
	}
}


//----------------------------------------------------------
// 上下左右のボーダースタイルを一括で設定する。
// 引数の個数で設定する箇所が変わる。
//
// 引数1個：上下左右同じ設定
// 引数2個：指定した順に "上下" "左右" を設定
// 引数3個：指定した順に "上" "左右" "下" を設定
// 引数4個：指定した順に "上" "右" "下" "左" を設定
//----------------------------------------------------------
Component.prototype.border = function()
{
	var arg = this.border.arguments;
	
	if(arg.length == 1)
	{
		this.borderTop(arg[0]);
		this.borderBottom(arg[0]);
		this.borderLeft(arg[0]);
		this.borderRight(arg[0]);
		
	}
	else if(arg.length == 2)
	{
		this.borderTop(arg[0]);
		this.borderBottom(arg[0]);
		this.borderLeft(arg[1]);
		this.borderRight(arg[1]);
		
	}else if(arg.length == 3)
	{
		this.borderTop(arg[0]);
		this.borderLeft(arg[1]);
		this.borderRight(arg[1]);
		this.borderBottom(arg[2]);
		
	}
	else if(arg.length == 4)
	{
		this.borderTop(arg[0]);
		this.borderRight(arg[1]);
		this.borderBottom(arg[2]);
		this.borderLeft(arg[3]);
	}
}


//----------------------------------------------------------
// X軸方向の座標指定メソッド
// 引数を渡さなければX軸方向の座標を返す。
//----------------------------------------------------------
Component.prototype.x = function(x)
{
	var component = this._component;
	
	if(typeof(x) == "undefined")
	{
		var ret = (MSIE) ? component.style.pixelLeft : parseInt(component.style.left);
		return ret;
	}
	else
	{
		if(MSIE)
		{
			component.style.pixelLeft = x; // + document.body.scrollLeft;
		}
		else if(Opera)
		{
			component.style.left = x;
		}
		else
		{
			component.style.left = x + "px";
		}
	}
}


//-------------------------------------------------------------
// Y軸方向の座標指定メソッド
// 引数を渡さなければY軸方向の座標を返す。
//-------------------------------------------------------------
Component.prototype.y = function(y)
{
	var component = this._component;
	
	if(typeof(y) == "undefined")
	{
		var ret = (MSIE) ? component.style.pixelTop : parseInt(component.style.top);
		return ret;
	}else
	{
		if(MSIE)
		{
			component.style.pixelTop = y; // + document.body.scrollTop;
		}
		else if(Opera)
		{
			component.style.top = y;
		}
		else
		{
			component.style.top = y + "px";
		}
	}
}


//-------------------------------------------------------------
// レイヤの移動メソッド
// 以下の方法と意味は同じ。
//
//   var component = new Component(id);
//   component.x(x);
//   component.y(y);
//-------------------------------------------------------------
Component.prototype.move = function(x, y)
{
	this.x(x);
	this.y(y);
}


//-------------------------------------------------------------
// レイヤの z-index を変更する。
// 引数を指定しなければ現在の z-index の設定値を返す。
//-------------------------------------------------------------
Component.prototype.zIndex = function(index)
{
	var component = this._component;
	
	if(_defined(index))
	{
		component.style.zIndex = index;
	}
	else
	{
		var index = component.style.zIndex;
		if(index == ""){
			index = 0;
		}
		return index;
	}
}

//-------------------------------------------------------------
// レイヤの幅指定メソッド。
// 引数を指定しなければ現在の幅を返す。
//-------------------------------------------------------------
Component.prototype.width = function(width)
{
	var component = this._component;
	
	if(typeof(width) == "undefined")
	{
		var ret = (MSIE) ? component.style.pixelWidth : parseInt(component.style.width);
		return ret;
	}
	else
	{
		if(MSIE)
		{
			component.style.pixelWidth = width;
		}
		else if(Opera)
		{
			component.style.width = width;
		}
		else
		{
			component.style.width = width + "px";
		}
	}
}


//-------------------------------------------------------------
// レイヤの高さ指定メソッド。
// 引数を指定しなければ現在の高さを返す。
//-------------------------------------------------------------
Component.prototype.height = function(height)
{
	var component = this._component;
	
	if(!_defined(height))
	{
		var ret = (MSIE) ? component.style.pixelHeight : parseInt(component.style.height);
		return ret;
	}
	else
	{
		if(MSIE)
		{
			component.style.pixelHeight = height;
		}
		else if(Opera)
		{
			component.style.height = height;
		}
		else
		{
			component.style.height = height + "px";
		}
	}
}


//-------------------------------------------------------------
// サイズ変更メソッド。
// 以下と同じ。
//
//   var component = new Component(id)
//   component.width(width);
//   component.height(height);
//-------------------------------------------------------------
Component.prototype.size = function(width, height)
{
	this.width(width);
	this.height(height);
}


//-------------------------------------------------------------
// レイヤの表示、非表示を切り替える時のアニメーションを
// 設定する。引数を指定しなかった場合は現在の設定を返す。
//
// 引数 :
//   mode : アニメーションの種類
//-------------------------------------------------------------
Component.prototype.animation = function(mode)
{
	if(_defined(mode))
	{
		this._animation = mode;
	}
	else
	{
		return this._animation;
	}
}


//-------------------------------------------------------------
// レイヤの表示、非表示を切り替える。
// 引数を指定しなかった場合は、現在の表示状態を返す。
//
// 引数 :
//   visible : 表示、非表示の指定 (boolean)
//-------------------------------------------------------------
Component.prototype.visible = function(visible)
{
	var component = this._component;
	
	if(!_defined(visible))
	{
		return (component.style.visibility == "visible") ? true : false;
	}
	else
	{
		if(this.visible() == visible)
		{
			//return;
		}
		
		// アニメーション設定がなければすぐに表示・非表示を切替る。
		if(this.animation() == ANIMATION_NONE)
		{
			component.style.visibility = (visible) ? "visible" : "hidden";
			return;
		}
		
		
		if(MSIE || Safari || Firefox || Opera)
		{
			if(visible)
			{
				component.style.visibility = "visible";
				
				if(this.animation() == ANIMATION_OPACITY)
				{
					// 初期透明度と変更度合いの設定
					this._changeStep = 10;
					this._maxOpacity = this.opacity();
					this._opacity = 0;
				}
				else if(this.animation() == ANIMATION_VERTICAL)
				{
					this._maxHeight = this.height();
					this._changeStep = this.height() / 20;
					this.height(0);
				}
				else if(this.animation() == ANIMATION_HORIZONTAL)
				{
					this._changeStep = this.height() / 20;
					this._maxWidth = this.width();
					this.width(0);
				}
			}
			else
			{
				if(this.animation() == ANIMATION_OPACITY)
				{
					// 初期透明度と変更度合いの設定
					this._changeStep = -10;
					this._opacity = this.opacity();
				}
				else if(this.animation() == ANIMATION_VERTICAL)
				{
					this._changeStep = -1 * this.height() / 20;
					this._maxHeight = this.height();
				}
				else if(this.animation() == ANIMATION_HORIZONTAL)
				{
					this._changeStep = -1 * this.height() / 20;
					this._maxWidth = this.width();
				}
			}
			
			__addComponent(this);
			
			this._changeLooks();
		}
		else
		{
			component.style.visibility = (visible) ? "visible" : "hidden";
		}
	}
}


//-------------------------------------------------------------
// コンポーネントの表示形式を切り返る。
// 引数を指定しない場合は現在の設定値を返す。
//-------------------------------------------------------------
Component.prototype.display = function(display)
{
    var component = this._component;
            
    if(!_defined(display))
    {
        return component.style.display;
    }
    else
    {
        component.style.display = display;
    }
}


//-------------------------------------------------------------
// レイヤの表示、非表示のアニメーションを制御する。
//-------------------------------------------------------------
Component.prototype._changeLooks = function()
{
	var ret = 0;
	if(this.animation() == ANIMATION_OPACITY)
	{
		// 透明度変更のアニメーション
		ret = this.changeOpacity();
	}
	else if(this.animation() == ANIMATION_VERTICAL)
	{
		ret = this.changeVertical();
	}
	else if(this.animation() == ANIMATION_HORIZONTAL)
	{
		ret = this.changeHorizontal();
	}
	else
	{
		return;
	}
	
	if(ret == 0){
		var interval = this._opacity_change_interval;
		setTimeout("__triggerChangeLooks('" + this.id() + "')", interval);
	}
}


//-------------------------------------------------------------
// レイヤの透明度を徐々に変更するメソッド。
//
// 戻り値：
//   1 : 透明度が0または100
//   0 : 透明度が1〜99（透明度の変更が可能）
//-------------------------------------------------------------
Component.prototype.changeOpacity = function()
{
	var opacity = this._opacity + this._changeStep;
	
	this.opacity(opacity);
	
	var ret = 0;
	if(opacity >= this._maxOpacity)
	{
		ret = 1;
	}
	else if(opacity <= 0)
	{
		this._component.style.visibility = "hidden";
		ret = 1;
	}
	
	return ret;
}


//-------------------------------------------------------------
// レイヤのサイズを縦方向に徐々に変更するメソッド。
//
// 戻り値：
//   1 : サイズが設定した値になる又は0
//   0 : サイズの変更が可能
//-------------------------------------------------------------
Component.prototype.changeVertical = function()
{
	var height = this.height() + this._changeStep;
	if(height > this._maxHeight)
	{
		height = this._maxHeight;
	}
	else if(height < 0)
	{
		height = 0;
	}
	
	this.height(height);
	
	var ret = 0;
	if(height >= this._maxHeight)
	{
		ret = 1;
	}
	else if(height <= 0)
	{
		this._component.style.visibility = "hidden";
		ret = 1;
	}
	
	return ret;
}


//-------------------------------------------------------------
// レイヤのサイズを横方向に徐々に変更するメソッド。
//
// 戻り値：
//   1 : サイズが設定した値になる又は0
//   0 : サイズの変更が可能
//-------------------------------------------------------------
Component.prototype.changeHorizontal = function()
{
	var width = this.width() + this._changeStep;
	if(width > this._maxWidth)
	{
		width = this._maxWidth;
	}
	else if(width < 0)
	{
		width = 0;
	}
	
	this.width(width);
	
	var ret = 0;
	if(width >= this._maxWidth)
	{
		ret = 1;
	}
	else if(width <= 0)
	{
		this._component.style.visibility = "hidden";
		ret = 1;
	}
	
	return ret;
}


//-------------------------------------------------------------
// レイヤの透明度を指定した値に変更するメソッド。
//-------------------------------------------------------------
Component.prototype.opacity = function(opacity)
{
	if(!_defined(opacity))
	{
		return this._opacity;
	}
	else
	{
		this._opacity = opacity;
		
		var component = this._component;
		component.style.opacity = opacity / 100;
		component.style.mozOpacity = opacity / 100;
		component.style.filter = "alpha(opacity=" + opacity + ")";
	}
}


//----------------------------------------------------------
// レイヤをそれぞれのidをキーにして保存する。
//----------------------------------------------------------
var _component_list = new Array();

function __addComponent(component)
{
	var id = component.id();
	_component_list[id] = component;
}


//----------------------------------------------------------
// レイヤの透明度を変更していく過程でタイマから呼ばれる関数。
// 引数で指定されたレイヤの透明度変更メソッドをコールする。
//----------------------------------------------------------
function __triggerChangeLooks(id)
{
	var component = _component_list[id];
	component._changeLooks();
}


//----------------------------------------------------------
// 引数で渡された変数が初期化済みの変数かを判定する。
//----------------------------------------------------------
function _defined(val)
{
	return (typeof(val) != "undefined") ? true : false;
}



/*==================================================================*/
// ボーダークラスの定義
// デフォルトの設定は "1px solid #000000"
/*==================================================================*/
function Border()
{
	this._width = 1;
	this._style = "solid";
	this._color = "#000000";
}


//----------------------------------------------------------
// ボーダーの色の設定、取得を行うメソッド。
//
// var boder = new Border();
// boder.color("#ffffcc");
// alert(boder.color());
//----------------------------------------------------------
Border.prototype.color = function(color)
{
	if(!_defined(color)){
		return this._color;
	}else{
		this._color = color;
	}
}


//----------------------------------------------------------
// ボーダーのスタイルの設定、取得を行うメソッド。
// スタイルは以下の値を設定する。
//   none, hidden, solid, double, groove,
//   ridge, inset, outset, dashed, dotted
//
// var boder = new Border();
// boder.style("dashed");
// alert(boder.style());
//----------------------------------------------------------
Border.prototype.style = function(style)
{
	if(!_defined(style)){
		return this._style;
	}else{
		this._style = style;
	}
}


//----------------------------------------------------------
// ボーダーの幅の設定、取得を行うメソッド。
//
// var boder = new Border();
// boder.width(10);
// alert(boder.width());
//----------------------------------------------------------
Border.prototype.width = function(width)
{
	if(!_defined(width)){
		return this._width;
	}else{
		this._width = width;
	}
}


/*==================================================================*/
// ブラウザ上のマウスの位置を捕捉するための関数郡
// マウスの位置情報を取得するには以下の2つの関数を使用する。
//
//   getCurrentMouseX()
//   getCurrentMouseY()
//
/*==================================================================*/
var __mousePosX = 0;
var __mousePosY = 0;


function __getEventX(evt)
{
	var ret;
	if(Netscape)
	{
		ret = evt.pageX;
	}
	else if(MSIE)
	{
		ret = event.x + getPageXOffset();
	}
	else
	{
		ret = event.x;
	}
	
	return ret;
}

function __getEventY(evt)
{
	var ret;
	if(Netscape)
	{
		ret = evt.pageY;
	}
	else if(MSIE)
	{
		ret = event.y + getPageYOffset()
	}
	else
	{
		ret = event.y;
	}
	
	return ret;
}

//----------------------------------------------------------
// ブラウザ上のマウスポインタのX座標を返す。
//----------------------------------------------------------
function getCurrentMouseX()
{
	return __mousePosX;
}

//----------------------------------------------------------
// ブラウザ上のマウスポインタのY座標を返す。
//----------------------------------------------------------
function getCurrentMouseY()
{
	return __mousePosY
}



/*==================================================================*/
// ブラウザの情報を取得するための関数郡
//
// ブラウザの表示領域のサイズを取得する
//   getBrowserInnerWidth()
//   getBrowserInnerHeigth()
//
// ページスクロール時の表示開始位置
//   getPageXOffset()
//   getPageYOffset()
//
/*==================================================================*/
//----------------------------------------------------------
// ブラウザの表示領域の幅を返す。
//----------------------------------------------------------
function getBrowserInnerWidth()
{
	return (MSIE) ? document.body.clientWidth : window.innerWidth;
}


//----------------------------------------------------------
// ブラウザの表示領域の高さを返す。
//----------------------------------------------------------
function getBrowserInnerHeight()
{
	return (MSIE) ? document.body.clientHeight : window.innerHeight;
}


//----------------------------------------------------------
// スクロールされている時の表示開始位置（X軸）を返す。
//----------------------------------------------------------
function getPageXOffset()
{
	return (MSIE) ? document.body.scrollLeft : window.pageXOffset;
}


//----------------------------------------------------------
// スクロールされている時の表示開始位置（Y軸）を返す。
//----------------------------------------------------------
function getPageYOffset()
{
	return (MSIE) ? document.body.scrollTop : window.pageYOffset;
}


/*==================================================================*/
// イベントハンドラ系の関数郡
//
// ウィンドウリサイズイベントのハンドラ登録
//   addWindowResizeEventHandler(func)
//
/*==================================================================*/

// ウィンドウリサイズイベントハンドラを登録する配列
var __windowResizeEventHandler = new Array();

// マウスの移動イベントハンドラを登録する配列
var __documentMouseMoveEventHandler = new Array();

// ウィンドウスクロールイベントハンドラを登録する配列
var __windowScrollEventHandler = new Array();

//----------------------------------------------------------
// ウィンドウリサイズ時のイベントハンドラを登録する。
//----------------------------------------------------------
function addWindowResizeEventHandler(func)
{
	__windowResizeEventHandler.push(func);
}


//----------------------------------------------------------
// マウス移動時のイベントハンドラを登録する。
// イベント発生時にイベントハンドラへはマウスの
// X座標、Y座標が引数で渡される。
//----------------------------------------------------------
function addDocumentMouseMoveEventHandler(func)
{
	__documentMouseMoveEventHandler.push(func);
}


// マウス位置の自動取得用のハンドラ登録
// getCurrentMouseX(), getCurrentMouseY() 用のデータを取得する。
function __baseDocumentMouseMoveEventHandler(x, y)
{
	__mousePosX = x;
	__mousePosY = y;
}
addDocumentMouseMoveEventHandler(__baseDocumentMouseMoveEventHandler);


//----------------------------------------------------------
// ウィンドウスクロール時のイベントハンドラを登録する。
//----------------------------------------------------------
function addWindowScrollEventHandler(func)
{
	__windowScrollEventHandler.push(func);
}


//----------------------------------------------------------
// ウィンドウリサイズ時のイベント処理
// 登録されているイベントハンドラを実行する。
//----------------------------------------------------------
window.onresize = function()
{
	for(var i=0; i<__windowResizeEventHandler.length; i++)
	{
		__windowResizeEventHandler[i].call();
	}
}


//----------------------------------------------------------
// マウス移動時のイベント処理
// 登録されているイベントハンドラを実行する。
//----------------------------------------------------------
document.onmousemove = function(evt)
{
	var x = __getEventX(evt);
	var y = __getEventY(evt);
	
	for(var i=0; i<__documentMouseMoveEventHandler.length; i++)
	{
		__documentMouseMoveEventHandler[i].call(null, x, y);
	}
}


//----------------------------------------------------------
// ウィンドウスクロール時のイベント処理
// 登録されているイベントハンドラを実行する。
//----------------------------------------------------------
window.onscroll = function()
{
	for(var i=0; i<__windowScrollEventHandler.length; i++)
	{
		__windowScrollEventHandler[i].call();
	}
}




