/**
 * フォームAjaxライブラリ
 *
 * 
 * @requires prototype.js (>1.4)
 * @requires prototype-helper.js (>0.1)
 * @package	Common
 * @version $Id: $
 * 
 * @requires	prototype.js
 * @requires	prototype-helper.js
 * 
 */


/**
 * Iframeの動的ロード
 */
function loadIframe( targetName, src ){
	$('iframe_'+targetName).src = src;
	Element.show('iframe_'+targetName );
	Element.show('indicator_'+targetName );
	$(targetName+'_uploadlink').remove();
}


/**
 * インジケーターの動的生成
 */
IndicatorDefaultParams = {
	'tagName' : 'span',
	'mesg' : '検索中...',
	'attributes' : { 
		'id' : 'indicator'
	},
	'imagePath' : 'image/',
	'imageFile' : 'spinner.gif',
	'OnLoadHide' : 'true'
}


function getIndicatorElement( params ){
	var setParams = Object.extend(IndicatorDefaultParams, params);
	span=$c(setParams.tagName,setParams.attributes);
	span.appendChild($c('img',{ 'src' : setParams.imagePath + setParams.imageFile } ));
	span.appendChild(document.createTextNode(setParams.mesg));
	if(setParams.OnLoadHide) Element.hide(span);
	return span;
}

var Indicator = Class.create();
Indicator.prototype = {
	initialize : function ( params ){	
		this.Ielem=getIndicatorElement( params );
	},
	show : function(){
		Element.show(this.Ielem);	
	},
	hide : function(){
		Element.hide(this.Ielem);	
	},
	append : function( elem ){
		if(elem){
			elem.appendChild(this.Ielem);
		}
	}
}

/**
 * ツールチップオブジェクトの生成
 */
var ToolTips = Class.create();
ToolTipsDefaultParams = {
	'innerHTML' : 'ツールチップです',
	'rel' : 'mouseover',	/* mouseover|click|relを指定 */
	'position' : 'right', /* (bottom|top|right)を指定 */
	'style' : {
		'position' : 'absolute',
		'display' : 'none',
		'background-color': '#DDDDDD',
		'border' : '1px solid #777777',
		'padding' : '2px'
	}
}
ToolTips.prototype = {
	initialize : function( params ){
		this.params = Object.extend( ToolTipsDefaultParams, params);
		this.RenderElement();
	},
	/**
	 * ツールチップしたい要素を登録する
	 */
	RegisterElement : function ( elems ){
		console.debug('RegisterElement',to_array(elems));
		to_array(elems).each(function(e){
			Event.observe(e,'mouseover',this.OnMouseOver.bindAsEventListener(this));
			Event.observe(e,'mouseout',this.OnMouseOut.bindAsEventListener(this));
		}.bind(this));
	},
	RenderElement : function (){
		this.tipElem=$c('div',{
				'class' : 'tooltip',
				'style' : this.params.style,
				'innerHTML' : this.params.innerHTML
			});
		console.debug('RenderElement',this.tipElem);
		document.body.appendChild( this.tipElem );
	},
	OnMouseOver : function (evt){
		console.debug('onMouseOver');
		var elem=Event.element(evt)
		switch (this.params.mode) {
			default:
			case 'mouseover':
				
				break;
			case 'click':
				
				break;
			case 'rel':
				if(elem.tagName.toLowerCase()=='a'){
					this.tipElem.innerHTML = elem.rel;
				} else {
					this.tipElem.innerHTML = parentNodeMatch(elem,'a').rel;
				}
				break;
		}
		pos=Position.cumulativeOffset( elem );
		Element.show(this.tipElem);
		h=0; w=0;
		switch (this.params.position) {
			default:
			case 'bottom':
				h=Element.getHeight(elem);
				break;
			case 'top':
				h=-(Element.getHeight(this.tipElem));
				console.debug('h',h);
				break;
			case 'right':
				w=elem.offsetWidth;
				break;
		}

		Element.setStyle( this.tipElem,{ top : (pos[1]+h)+'px', left : (pos[0]+w)+'px' } );
	},
	OnMouseOut : function ( evt ){
		Element.hide( this.tipElem );		
	}
}

/**
 * Ajaxでエレメントを更新するヘルパ
 */
var AjaxUpdater = Class.create();
AjaxUpdater.prototype = {
	initialize : function (button_id, url, form_id, target_id, indicator_id, confirm_novalue, eval_option){	
		this.url = url;
		this.form = $(form_id);
		this.target_id = target_id;
		this.eval_option = (eval_option!==undefined)?eval_option:true;
		if($(this.target_id).tagName.toLowerCase()=='tbody'){
			alert('TBODY要素に対してtargetは指定できません(IEバグ)');
			return false;
		}
		this.button = to_array(button_id);
		this.button.each(function(id){
			e=$(id);
			if(e.tagName.toLowerCase()=='input'){
				e.onclick = this.DoClick.bindAsEventListener(this);
			} else if(e.tagName.toLowerCase()=='select'){
				e.onchange = this.DoClick.bindAsEventListener(this);
			}
		}.bind(this));
		this.indicator =$(indicator_id);
		this.confirm_novalue = confirm_novalue;
	},
	DoClick : function ( evt ){
		if ( this.OnRequestBefore ) this.OnRequestBefore.apply(this,arguments);
		var values = Form.getElements(this.form);
		if ( this.confirm_novalue && values.find( function(e){
			if (e.type=='text') return e.value != '';
			if (e.type=='checkbox') return e.checked;
			return false;
		}) == null ) {
			if (!confirm('すべてのレコードを表示しますがよろしいですか?')) return false;
		}
		this.pars = Form.serialize(this.form);
		this.button.each( function(e){
			$(e).disabled=true;
		});
		this.DoRequest();
		//alert('url:'+this.url+decodeURI(pars)+"\n"+"target:"+this.target_id);
		return false;
	},
	DoRequest : function( appendQuery ){
		Element.show(this.indicator);
		if(appendQuery){
			this.pars+='&'+$H(appendQuery).toQueryString();
		}
		var Ajax_SeachResult = new Ajax.Updater(
			this.target_id, 
			this.url,
			{
				method: 'get', 
				parameters: this.pars,
				onComplete: this.OnComplete.bind(this),
				onFailure: this.OnError.bind(this),
				evalScripts: true
			});
		if ( this.OnRequestAfter ) this.OnRequestAfter.apply(this,arguments);
	},
	OnComplete : function () {
		Element.hide(this.indicator);
		this.button.each( function(e){
			$(e).disabled=false;
		});
		if ( this.OnCompleteAfter ) {
			this.OnCompleteAfter.apply(this,arguments);
		};
	},
	OnError : function(){
		//alert('onError');
		this.button.each( function(e){
			$(e).disabled=false;
		});
		Element.hide(this.indicator);
	}
}
/**
 * Ajaxでコミットクエリーを送る
 * 
 * @param	button_id	コミットボタン
 * @param	url			コミット先アクション
 * @param	form_id		フォームIDまたはエレメントの配列
 * @param	indicator_id インジケータのID
 * 
 * ex. 
 *   new AjaxCommiter( '{url_for action="ajax_zipcode"}', new Array('zipcode_1','zipcode_2') );
 */
var AjaxCommiter = Class.create();
AjaxCommiter.prototype = {
	initialize : function ( url, form_id, indicator_id ){	
		this.url = url;
		this.form = form_id;
		this.indicator = (indicator_id)?$(indicator_id):$('indicator');
	},
	DoRequest : function () {
		if(this.OnRequestBefore) this.OnRequestBefore();
		if(is_array(this.form)) {
			var d={};
			this.form.each(function(e){
				d[$(e).name]=$(e).value;
			});
			this.pars=$H(d).toQueryString();
		} else {
			this.pars=Form.serialize(this.form);
		}
		if(this.OnGetRequestParams) this.pars=this.OnGetRequestParams();
		Element.show(this.indicator);
		var Ajax_Comitter = new Ajax.Request(
			this.url,
			{
				method: 'post', 
				parameters: this.pars,
				onComplete: this.OnComplete.bind(this),
				onFailure: this.OnError.bind(this)
			});
		return false;
	},
	OnComplete : function ( originalRequest, json ) {
		Element.hide(this.indicator);
		this.result=originalRequest.responseText;
		this.json=eval(json);
		if(this.OnCompleteAfter) this.OnCompleteAfter.apply(this,arguments);
	},
	
	OnError : function(){
		Element.hide(this.indicator);
	}
}

/**
 * コントロールレイヤーウィンドウオブジェクト
 */
var ControlLayerWindow = Class.create();
ControlLayerWindow.prototype = {
	initialize : function ( id ){
		this.layerwindow = $(id);
		this.x_define = false;
		this.close_btn = $A(this.layerwindow.getElementsByTagName('input')).find( function(s){
			return s.name=='close';
		});
		if( this.close_btn ) this.close_btn.onclick = this.DoCloseWindow.bindAsEventListener(this);
	},
	/**
	 * javascript: DoShowWindow( this, id );等で呼び出す
	 * OnShowWindowコールバックをparamsをパラメータにコールする
	 */
	DoShowWindow : function ( elem, params ){
		if(this.OnBeforeShowWindow) this.OnBeforeShowWindow(this.layerwindow);
		pos=Position.cumulativeOffset( elem );
		h=Element.getHeight(elem);
		Element.show(this.layerwindow);
		if(this.x_define){
			w=this.layerwindow.offsetWidth-elem.offsetWidth;
		} else {
			w=0;
		}
		Element.setStyle( this.layerwindow,{ top : (pos[1]+h)+'px', left : (pos[0]-w)+'px' } );
		if($('result_'+this.layerwindow.id)) {
			$('result_'+this.layerwindow.id).innerHTML='';
		}
		if(this.OnShowWindow) this.OnShowWindow(params);
	},
	DoCloseWindow : function ( evt ){
		Element.hide(this.layerwindow);
		if(this.OnCloseWindow) this.OnCloseWindow();
	}
}

/**
 * コントロールレイヤーオブジェクト
 */
var ControlLayer = Class.create();
ControlLayer.prototype = {
	initialize : function ( layers ){
		this.layers=layers.collect( function(s){
			return $(s);
		});
	},
	OnBeforeShowWindow : function( elem ){
		this.layers.each( function(e){
			if ( e !== elem ){
				Element.hide(e);
			}
		});
	}
}

/**
 * 日付の範囲指定を行うボタンを作成する
 * 
 */
var DateRange = Class.create();
DateRange.prototype = {
	initialize : function (start_date_id, end_date_id){
		this.start_date = $(start_date_id);
		this.end_date = $(end_date_id);
		this.formatString = 'YY-MM-DD';
	},
	RenderLinks : function ( target, links ){
		links.collect( function(t,i){
			switch (t) {
				case 'ThisMonth':
					e=$c('a',{ 'href' : '#none','innerHTML' : '今月'});
					Event.observe( e, 'click',this.OnClickThisMonth.bind(this) );
					break;
				case 'PrevMonth':
					e=$c('a',{ 'href' : '#none','innerHTML' : '先月'});
					Event.observe( e, 'click',this.OnClickPrevMonth.bind(this) );
					break;
				case 'Next7days':
					e=$c('a',{ 'href' : '#none', 'innerHTML' : '一週間以内'});
					Event.observe( e, 'click',this.OnClickNext7days.bind(this) );
					break;
				case 'Next2week':
					e=$c('a',{ 'href' : '#none','innerHTML' : '二週間以内'});
					Event.observe( e, 'click',this.OnClickNext2week.bind(this) );
					break;
				case 'Prev7days':
					e=$c('a',{ 'href' : '#none', 'innerHTML' : '過去一週間'});
					Event.observe( e, 'click',this.OnClickPrev7days.bind(this) );
					break;
				case 'Prev2week':
					e=$c('a',{ 'href' : '#none','innerHTML' : '過去二週間'});
					Event.observe( e, 'click',this.OnClickPrev2week.bind(this) );
					break;
				case 'Clear':
					e=$c('a',{ 'href' : '#none','innerHTML' : 'クリア'});
					Event.observe( e, 'click',this.OnClickClear.bind(this) );
					break;
				default:
					break;
			}
			$(target).appendChild( e );
			if(i!==links.length-1)
			$(target).appendChild( document.createTextNode(' | ') );
		}.bind(this));
	},
	OnClickThisMonth : function (){
		curdate = new Date();
		curdate.setFirstDayOfMonth();
		this.start_date.value = curdate.formatString(this.formatString);
		curdate.setLastDayOfMonth();
		this.end_date.value = curdate.formatString(this.formatString);
		return false;
	},
	OnClickPrevMonth : function (){
		curdate = new Date();
		curdate.setFirstDayOfMonth(-1);
		this.start_date.value = curdate.formatString(this.formatString);
		curdate.setLastDayOfMonth();
		this.end_date.value = curdate.formatString(this.formatString);
		return false;
	},
	OnClickNext7days : function (){
		curdate = new Date();
		this.start_date.value = curdate.formatString(this.formatString);	
		curdate.setDate(curdate.getDate()+6);
		this.end_date.value = curdate.formatString(this.formatString);
		return false;
	},
	OnClickNext2week : function (){
		curdate = new Date();
		this.start_date.value = curdate.formatString(this.formatString);	
		curdate.setDate(curdate.getDate()+13);
		this.end_date.value = curdate.formatString(this.formatString);
		return false;
	},
	OnClickPrev7days : function (){
		curdate = new Date();
		this.end_date.value = curdate.formatString(this.formatString);
		curdate.setDate(curdate.getDate()-6);
		this.start_date.value = curdate.formatString(this.formatString);	
		return false;
	},
	OnClickPrev2week : function (){
		curdate = new Date();
		this.end_date.value = curdate.formatString(this.formatString);
		curdate.setDate(curdate.getDate()-13);
		this.start_date.value = curdate.formatString(this.formatString);	
		return false;
	},
	OnClickYesterday : function (){
		curdate = new Date();
		curdate.setDate(curdate.getDate()-1);
		this.end_date.value = curdate.formatString(this.formatString);
		this.start_date.value = curdate.formatString(this.formatString);	
		return false;
	},
	OnClickToday : function (){
		curdate = new Date();
		this.end_date.value = curdate.formatString(this.formatString);
		this.start_date.value = curdate.formatString(this.formatString);	
		return false;
	},
	OnClickClear : function (){
		this.start_date.value='';	
		this.end_date.value='';	
		return false;
	}
}