var FileQ = {
	Version: '0.1',

	KEY_LEFT:     37,
	KEY_UP:       38,
	KEY_RIGHT:    39,
	KEY_DOWN:     40,
	KEY_RETURN:   13,

	getJavaHashMap: function(hash){
		if(hash){
			return {"map": hash.obj, "javaClass": "java.util.HashMap"};
		}
		return {"map": {}, "javaClass": "java.util.HashMap"};
	},

	getElementsByIdPrefix: function(prefix){
		var children = document.getElementsByTagName("*") || document.all;

		var hash = new Hash();

		for (var i = 0; i < children.length; i++) {
	    	var obj = children[i];
			//try{
			if(obj.id!=null && obj.id.length!=0){
				var val = obj.id;
				if( val.search("^"+prefix) != -1){
					//alert(obj.type);
					try{
						hash.set(obj.id, obj.getValue());
					}catch(e){
						hash.set(obj.id, $(obj.id).value);
					}
		    	}
	    	}
	    	//}catch(e){alert(obj.id+"::"+e);}
		}
		return hash;
	},


	//--マウスX座標get
	getMouseX: function(e){
    	if(navigator.userAgent.search(
				 "Opera(\ |\/)6") != -1 )   //o6用
			return e.clientX;
    	else if(document.all)				   //e4,e5,e6用
			return document.body.scrollLeft+event.clientX
		else if(document.layers ||
			document.getElementById)    //n4,n6,n7,m1,o7,s1用
		return e.pageX;
	},

	//--マウスY座標get
	getMouseY: function(e){
		if(navigator.userAgent.search(
				 "Opera(\ |\/)6") != -1 )   //o6用
			return e.clientY;
		else if(document.all)				   //e4,e5,e6用
			return document.body.scrollTop+event.clientY
		else if(document.layers ||
			document.getElementById)    //n4,n6,n7,m1,o7,s1用
		return e.pageY;
	}
}

//-----------------------------------------------------------------------------------------

function log(message){
	try{
		var logelement = document.getElementById("log");
		logelement.innerHTML = message;
	}catch(exception){
	}
}

function logAppend(message){
	try{
		var logelement = document.getElementById("log");
		logelement.innerHTML = logelement.innerHTML + "<br />" + message;
	}catch(exception){
	}
}

//-----------------------------------------------------------------------------------------
FileQ.SelectBox = new Class({
	options:{
		targetElement: null,
		containerId: "SelectBox",
		width:'150px'
	},

	initialize: function(options){
		this.hash = new Hash();
		this.setOptions(options);
		this.selectedindex=-1;

		this.keyArray = new Array();
		this.valArray = new Array();

		this.element = this.options.targetElement;

		this.createFrame();
		this.hidden();
	},

	hidden: function(){
		this.container.style.visibility = "hidden";
	},

	setCallbackfunc: function(func) {
		this.callbackfunc = func;
	},

   pushKeyAndValue: function(key, value){
		this.keyArray.push(key);
		this.valArray.push(value);
   },

   clearKeyAndValue: function(key, value){
		this.keyArray.length=0;
		this.valArray.length=0;
   },

	createFrame: function(){
		this.container = new Element('div', {'class':'sel_container'}).inject(document.body);
		this.selectTable = new Element('table', {'class':'sel_table'}).inject(this.container);

		//--------------------------------------
		this.container.id = this.options.containerId;
		this.selectTable.id=this.containerId+"_table";
		this.selectTable.style.width=this.options.width;

		this.container.addEvent('click', this._mouseEventClick.bind(this));
		this.container.addEvent('mouseover', this._mouseEventOver.bind(this));
		this.container.addEvent('mouseout', this._mouseEventOut.bind(this));
	},

	clearRows: function(){
   		var j = this.selectTable.rows.length;
   		for(var i = 0; i < j; i++){
   			this.selectTable.deleteRow(0);
   		}
	},

	forword: function(){
		try{
			this.selectTable.rows[this.selectedindex+1].cells[0].className="sel_selected_cell";
			this.selectedindex++;
			this.selectTable.rows[this.selectedindex-1].cells[0].className="sel_cell";
		}catch(exception){
		}
	},

	previous: function(){
		try{
			this.selectTable.rows[this.selectedindex-1].cells[0].className="sel_selected_cell";
			this.selectedindex--;
			this.selectTable.rows[this.selectedindex+1].cells[0].className="sel_cell";
		}catch(exception){
		}
	},

	getValue: function(){
		return this.valArray[this.selectedindex];
	},

	setElementForSelectedValue:function(element){
		this.element = element;
	},

	setValueEvent: function(e){
		if ( arguments.length == 0 )
			e = event;

		var eventTarget = e.target ? e.target : e.srcElement;
		if(eventTarget.id==this.element.id){
			try{
				var aa = this.valArray[this.selectedindex];
				if(aa)	this.element.value=aa;
			}catch(exception){}
		}
	},

	display: function(e){
		if(this.valArray.length==0)
			return;

		if ( arguments.length == 0 )
			e = event;

		var pos = this.element.getPosition();
		var x = pos.x;
		var y = pos.y;

		this.clearRows();

   		for(var i = 0; i < this.valArray.length; i++){
   			var row = this.selectTable.insertRow(this.selectTable.rows.length);
			var cell = row.insertCell(0);
			cell.innerHTML = this.valArray[i];
			cell.id = i;
			cell.className="sel_cell";
   		}

		this.container.style.left = x+"px";
		var yy = y+this.element.offsetHeight;
	   	this.container.style.top  = yy+"px";
	   	this.container.style.visibility = "visible";
		this.selectedindex=-1;
	},

	_mouseEventDblClick: function(e){
		this._mouseEventClick(e);
	},

	_mouseEventClick: function(e){
		if ( arguments.length == 0 )
			e = event;

		this.mouseX = FileQ.getMouseX(e);
		this.mouseY = FileQ.getMouseY(e);

		var eventTarget = e.target ? e.target : e.srcElement;

		var id=eventTarget.id;
		var pid = parseInt(id);
		if(pid>=0){
			eventTarget.className="sel_selected_cell";
			this.element.value = this.valArray[pid];
			this.hidden();
			this.selectedindex = pid;

			if(this.callbackfunc){
				this.callbackfunc(this.keyArray[pid], this.valArray[pid]);
			}
		}
	},

	_mouseEventOver: function(e){
		if ( arguments.length == 0 )
			e = event;

		this.mouseX = FileQ.getMouseX(e);
		this.mouseY = FileQ.getMouseY(e);

		var eventTarget = e.target ? e.target : e.srcElement;
		var id=eventTarget.id;
		var pid = parseInt(id);
		if(pid>=0){
			this.selectedindex = pid;
			eventTarget.className="sel_selected_cell";
		}
	},

	_mouseEventOut: function(e){
		if ( arguments.length == 0 )
			e = event;

		var eventTarget = e.target ? e.target : e.srcElement;
		var eventRelatedTarget = e.relatedTarget ? e.relatedTarget : e.toElement;
		var id=eventTarget.id;
		var pid = parseInt(id);
		if(pid>=0){
			eventTarget.className="sel_cell";
		}
	},

	isParent: function(element, pid){
		try{
			while(true){
				if(element.parentNode.id==pid){
					return true;
				}else{
					element = element.parentNode;
				}
			}
		}catch(exception){return false;}
	}
});

FileQ.SelectBox.implement(new Events, new Options);

/*
Element.NativeEvents = [
	'click', 'dblclick', 'mouseup', 'mousedown', //mouse buttons
	'mousewheel', 'DOMMouseScroll', //mouse wheel
	'mouseover', 'mouseout', 'mousemove', //mouse movement
	'keydown', 'keypress', 'keyup', //keys
	'load', 'unload', 'beforeunload', 'resize', 'move', //window
	'focus', 'blur', 'change', 'submit', 'reset', 'select', //forms elements
	'error', 'abort', 'contextmenu', 'scroll' //misc
];
 */
//-----------------------------------------------------------------------------------------
FileQ.FormElementManager = new Class({

	options:{
			FormElement               : null,
			InputEntityClassVariable  : null,
			OutputEntityClassVariable : null,
			IsNullOk : false,
			Length:-1,       // 何文字以上の場合はこちらを使う
			WithinLength:-1, // 何文字以内の場合はこちらを使う
			NullErrorMessage : "空欄です",
			ValidationRegExp : null,
			ValidationErrorMessage : null,
			ZenkakuOK : false,
			ZenkakuNGErrorMessage : "全角文字は使えません",
			ZenkakuOKErrorMessage : "半角文字は使えません",
			InputFilters : [],
			OutputFilters : [],
			InputAssist : null,
			OuterComparisonElement: null, // 外部の比較対象エレメント
			ErrorElementBGColor : "#f2baba",
			ElementBGColor : "#FFFFFF"
	},

	initialize: function(options){
		this.ErrorMessages = new Array();
		this.setOptions(options);
		//try{
		this.options.FormElement.addEvent('focus', this._focusEventHandle.bind(this));
		this.options.FormElement.addEvent('blur', this._blurEventHandle.bind(this));
		this.options.FormElement.addEvent(window.ie ? 'keydown' : 'keypress', this._keypressEventHandle.bind(this));
		//}catch(e){}
	},

	_focusEventHandle: function(e){
		if ( arguments.length == 0 )
		e = event;

		var eventTarget = e.target ? e.target : e.srcElement;
		if(this.options.InputAssist!=null){
			eval(this.options.InputAssist+".display(e);");
		}
	},

	_blurEventHandle: function(e){
		if ( arguments.length == 0 )
		e = event;

		var eventTarget = e.target ? e.target : e.srcElement;
		if(this.options.InputAssist!=null){
			eval(this.options.InputAssist+".setValueEvent(e);");
			eval(this.options.InputAssist+".hidden();");
		}
	},

	_keypressEventHandle: function(e){
		if ( arguments.length == 0 )
		e = event;

		var eventTarget = e.target ? e.target : e.srcElement;
		var eventRelatedTarget = e.relatedTarget ? e.relatedTarget : e.toElement;

		if(this.options.InputAssist!=null){
			if(e.keyCode==FileQ.KEY_UP){
				eval(this.options.InputAssist+".previous();");
			}
			if(e.keyCode==FileQ.KEY_DOWN){
				eval(this.options.InputAssist+".forword();");
			}
			if(e.keyCode==FileQ.KEY_RETURN){
				try{
					eval("var val="+this.options.InputAssist+".getValue();");
					if(val){
						this.options.FormElement.value = val;
						// eval(this.options.InputAssist+".hidden();");
					}
				}catch(exception){}
			}
		}
	},

	clearMessage: function(){
		try{
			//this.popupMessage.clearMessage();
		}catch(exception){}
	},

	/**
		複数のエラーメッセージが入った配列を
		改行<BR/>入りのHTML文字列に変換する
	**/
	createMessageFromErrorMessages: function(){
		if(this.ErrorMessages.length == 0){
			return null;
		}

		var mes = null;

		for(var i = 0; i < this.ErrorMessages.length; i++){
			if(i==0){
				mes = "-" + this.ErrorMessages[i] + "<br />";
			}else{
				mes = mes + "-" + this.ErrorMessages[i] + "<br />";
			}
		}

		return mes;
	},

	/**
		ターゲットエレメントをエラー時の色に変更
	**/
	setElementErrorBgColor: function(){
		this.options.FormElement.style.backgroundColor=this.options.ErrorElementBGColor;
		logAppend(this.id +":"+ this.options.FormElement.style.backgroundColor);
	},

	/**
		ターゲットエレメントを通常時の色に変更
	**/
	setElementBgColor: function(){
		if(this.options.FormElement.tagName=="INPUT"||this.options.FormElement.tagName=="TEXTAREA"){
			this.options.FormElement.style.backgroundColor=this.options.ElementBGColor;
		}
	},

	isNull: function(){
		var val = this.options.FormElement.getValue();
		if(val==null || val.length==0) return true;
		return false;
	},

	/**
		入力された値のバイト数を調べる
	**/
	getByteLength: function(obj){
		var i,cnt = 0;
		for(i=0; i<obj.length; i++)
			if (escape(obj.charAt(i)).length >= 4 ) cnt+=2; else cnt++;
		return cnt;
	},

	/**
		全角文字が含まれているかどうか調べる
		true->全角文字含まれている
		false->全角文字含まれていない
	**/
	IsZenkaku: function(){
		var val = this.options.FormElement.getValue();
		if(this.getByteLength(val) > val.length){
			return true;
		}
		return false;
	},

	/*
		フォームの値をクリア(NULL)にする
	*/
	clearForm: function(){
		this.options.FormElement.value = null;
		if(this.options.FormElement.value == null){
			// フォームタグではないエレメントへ値のセット
			this.innerHTML = "";
			//eval("this.options.FormElement.value = "+this.options.InputEntityClassVariable);
		}else{
			this.options.FormElement.value = "";
		}
	},

	validation: function(){

		this.ErrorMessages.length = 0;
		if(!this.myTips)
			this.myTips = new Tips(this.options.FormElement,
			{
				maxTitleChars:100, /* the maximum number of characters to display in the title of the tip. defaults to 30. */
				showDelay:1,	/* the delay the onShow method is called.  (defaults to 100 ms) */
				hideDelay:1,	/* the delay the onHide method is called.  (defaults to 100 ms) */
				/* className	the prefix for your tooltip classNames. defaults to ‘tool’. */
				offsets: {'x': 0, 'y': 10}
			}
			);

		var val = this.options.FormElement.getValue();

		// NULLチェック
		if(this.isNull()){
			if(this.options.IsNullOk){
				//eval(this.options.OutputEntityClassVariable	+ " = null;");
				return 0;
			}
			this.setElementErrorBgColor();
			this.ErrorMessages.push(this.options.NullErrorMessage);
			logAppend(this.options.NullErrorMessage);
		}

		// 出力フィルタ
		for(var i = 0; i < this.options.OutputFilters.length; i++){
			try{
				eval("val = " + this.options.OutputFilters[i] + "(val);");
			}catch(exception){
				this.ErrorMessages.push(exception);
				logAppend(exception);
			}
		}

		// 全角・半角チェック
		if(!this.options.ZenkakuOK){
			if(this.IsZenkaku()){
				this.ErrorMessages.push(this.options.ZenkakuNGErrorMessage);
				logAppend(this.options.ZenkakuNGErrorMessage);
			}
		}else{
			// 全角OK
			if(!this.IsZenkaku()){
				// 全て半角だったとしてもOKとする
				// this.ErrorMessages.push(this.options.ZenkakuOKErrorMessage);
			}
		}

		// 正規表現チェック
		if(this.options.ValidationRegExp!=null){
			var result = val.match(this.options.ValidationRegExp);
			if(result==null || result.length != 1){
				this.ErrorMessages.push(this.options.ValidationErrorMessage);
				logAppend(this.options.ValidationErrorMessage);
			}
		}

		// 文字数チェック
		if(this.options.Length>-1){
			if(this.options.Length > val.length){
				this.ErrorMessages.push(this.options.Length+"文字以上、入力してください");
				logAppend(this.options.Length+"文字以上、入力してください");
			}
		}
		if(this.options.WithinLength>-1){
			if(this.options.WithinLength < val.length){
				this.ErrorMessages.push(this.options.WithinLength+"文字以内で入力してください");
				logAppend(this.options.WithinLength+"文字以内で入力してください");
			}
		}



		// 外部のフォームエレメントと比較して違っていたらエラーにする
		if(this.options.OuterComparisonElement!=null){
			// logAppend("OuterComparisonElement.getValueFromForm()="+this.options.OuterComparisonElement.getValueFromForm());
			var val2 = this.options.OuterComparisonElement.getValueFromForm();
			if(val!=val2){
				if(this.options.OuterComparisonErrorMessage){
					this.ErrorMessages.push(this.options.OuterComparisonErrorMessage);
					logAppend(this.options.OuterComparisonErrorMessage);
				}else{
					this.ErrorMessages.push("比較したフォームと値が異なります");
					logAppend("比較したフォームと値が異なります");
				}
			}
		}

		this.setElementBgColor();

		if(this.ErrorMessages.length > 0){
			this.setElementErrorBgColor();
			this.options.FormElement.title = this.createMessageFromErrorMessages();
			this.myTips.build(this.options.FormElement);
			return 1;
		}else{
			this.setElementBgColor();
			this.options.FormElement.title = "";
			this.myTips.build(this.options.FormElement);
		}

		try{
			eval(this.options.OutputEntityClassVariable	+ " = val;");
			//this.options.OutputEntityClassVariable = val;
		}catch(exception){}
		return 0;
	}

});

FileQ.FormElementManager.implement(new Events, new Options);

//-----------------------------------------------------------------------------------------
FileQ.FormElementsManager = new Class({

	options:{
	},

	initialize: function(options){
		this.FormElementManagers = new Array();
		this.setOptions(options);
	},

	addFormElementManager: function(options){
		this.FormElementManagers.push(new FileQ.FormElementManager(options));
	},

	validationAll: function(){
		var a = 0;
		this.FormElementManagers.each(function(FormElementManager){
			a+=FormElementManager.validation();
		});
		return a;
	}

});

FileQ.FormElementsManager.implement(new Options);


