
/*
	var fields = {
	"qty":{type:"text",name:"qty",bVerify:true,empty:"",errmsg:"Please fill in the quantity (QTY).<br>",cb: qtycb}
	,"sizechoice": {type:"select"
		,name:"sizechoice"
		,idLabel:null		//id of label, where red arrow goes after verification
		,bVerify:true	//verify this field
		,empty:""	//for select boxes, the item in list with this value return "" from getValue();
		,errmsg:"Please fill in the size.<br>"
		} 
	,"colorchoice": {type:"select",name:"colorchoice",bVerify:true,empty:"",errmsg:"Please fill in the color.<br>"}
	,"amount":{type:"text",name:"price",bVerify:true,empty:"",errmsg:"Please fill in the amount of your donation.<br>",cb: amountcb}
	}

*/

Sonata.Form = function(fields,opts)
{
	/*	called when document is ready
		fields
		{id: {type:,bVerify:true/false,empty:"",errmsg:"Please fill in name",cb:function}, ... }
		where type is "input", "select", "radio" , "check"
		empty is the empty string, for selects this could be "Select"
	*/
	this.fields = fields;
	this.opts = this.getOpts(opts);
	//Sonata.prObject("opts",this.opts);
	var name;
	for(name in fields) {
		var o = fields[name];
		o.idField = name;
		o.arrowDiv = null;
		//Sonata.prObject(name,o);
		o.ctl = $("#"+name);
		if(typeof o.idLabel=='undefined') o.idLabel = "";
		if(typeof o.name=='undefined') o.name = name;
		if(typeof o.grpName=='undefined') o.grpName = o.name;	//for radiogrp and checkgrp
		if(typeof o.empty=='undefined') o.empty = "";
		if(typeof o.errmsg=='undefined') o.errmsg = "Please fill in " + name;
		if(typeof o.cb == 'undefined') o.cb = null;
		if(o.ctl.size()==0)
			o.ctl = null;
		o.toString = this.getFieldToString(o);
	}
	if(this.opts.bShowRedArrows)
		this.$makeRedArrows();
	//Sonata.prObject("fields",this.fields);
}
Sonata.Form.prototype.getFieldToString = function(ctl) {
	var thisptr = this;
	return f;
	function f() {
		var s="{name:'"+ctl.name+"', type:'"+ctl.type+"', value:'"+thisptr.getValue(ctl)+"'}";
		return s;
	}
}
Sonata.Form.defOpts = {
	bShowRedArrows: true	// type == select returns "" when the first item is selected
}
Sonata.Form.prototype.getOpts = function(opts) {
	var name;
	if(typeof opts == 'undefined') opts = {};
	var ret = {};
	for(name in Sonata.Form.defOpts) {
		//mprint("name="+name);
		ret[name] = Sonata.Form.defOpts[name];
	}
	for(name in opts)
		ret[name] = opts[name];
	return ret;
}
Sonata.Form.prototype.getValue = function(field) {
	return Sonata.Form.getValue(field);
}
Sonata.Form.prototype.setValue = function(field,value) {
	Sonata.Form.setValue(field,value);
}
Sonata.Form.getValue = function(field) {
	if(field.ctl == null) return "";
	var v = "";
	//mprint("getValue name="+field.idField);
	switch(field.type) {
		case "textarea":
		case "hidden":
		case "text": 
			v = Sonata.Form.getTextValue(field.ctl);
			break;
		case "select": 
			v = Sonata.Form.getSelectValue(field.ctl,field.empty);
			break;
		case "checkbox": 
		case "radio": 
			v = Sonata.Form.getBtnValue(field.ctl);
			break;
		case "radiogrp":
			v = Sonata.Form.getRadioGrpValue(field);
			break;
		case "checkgrp":
			//returns a string with value1|value2|...
			v = Sonata.Form.getCheckGrpValue(field);
			break;
	}
	return Sonata.Form.escapeValue(v);

}
Sonata.Form.getRadioGrpValue = function(field) {
	var id = "input[name='"+field.grpName+"']";
	var btns = $(id);
	//mprint("id="+id+" btns.size="+btns.size());
	var ret = "";
	btns.each(cb);
	return ret;
	
	function cb() {
		//mprint("this.value="+this.value);
		if(this.checked) ret=this.value;
	}
}
Sonata.Form.setRadioGrpValue = function(field,value) {
	var btns = $("input[name='"+field.grpName+"']");
	var ret = "";
	btns.each(cb);
	return ret;
	
	function cb() {
		if(this.value == value)
			this.checked = true;
		else
			this.checked = false;
	}
}
Sonata.Form.getCheckGrpValue = function(field) {
	var btns = $("input[name='"+field.grpName+"']");
	var ret = "";
	var sep = "";
	btns.each(cb);
	return ret;
	
	function cb() {
		if(this.checked) {
			ret=sep + this.value;
			sep = "|";
		}
	}
}
Sonata.Form.setCheckGrpValue = function(field,value) {
	var btns = $("input[name='"+field.grpName+"']");
	var values = value.split("|");
	var i,n = values.length;
	for(i=0;i<btns.size();i++)
		btns[i].checked = false;
	for(i=0;i<n;i++) {
		if(btns[i].value == values[i])
			btns[i].checked = true;
	}
}
Sonata.Form.escapeValue = function(value) {
	var s = value.replace(/\n/g,"[NL]");
	s = s.replace(/"/g,"[DQ]");
	s = s.replace(/'/g,"[SQ]");
	s = s.replace(/\r/g,"");
	return s;
}
Sonata.Form.unescapeValue = function(value) {
	var s = value.replace(/\[DQ]/g,'"');
	s = s.replace(/\[NL]/g,"\n");
	s = s.replace(/\[SQ]/g,"'");
	return s;
}

Sonata.Form.setValue = function(field,value) {
	if(field.ctl == null) return "";
	value = Sonata.Form.unescapeValue(value);
	switch(field.type) {
		case "textarea":
		case "hidden":
		case "text": Sonata.Form.setTextValue(field.ctl,value);break;
		case "select": Sonata.Form.setSelectValue(field.ctl,value);break;
		case "checkbox": 
		case "radio": Sonata.Form.setBtnValue(field.ctl,value);
			break;
		case "radiogrp":
			Sonata.Form.setRadioGrpValue(field,value);
			break;
		case "checkgrp":
			Sonata.Form.setCheckGrpValue(field,value);
			break;
	}

}
Sonata.Form.checkEmpty = function(field,value) {
	if(value=="") return {ok:false,errmsg:field.errmsg};
	return {ok:true,errmsg:""};
}
Sonata.Form.prototype.getData = function() {
	//just get the data from the fields, do not check the values
	var name;
	var v,field;
	var ret = {};
	for(name in this.fields) {
		field = this.fields[name];
		v = this.getValue(field);
		ret[name] = v;
	}
	return ret;
}
Sonata.Form.prototype.setData = function(data) {
	//set the data into the fields
	var name;
	var v,field;
	for(name in data) {
		if(typeof this.fields[name] == 'undefined') continue;
		field = this.fields[name];
		this.setValue(field,data[name]);
	}
}
Sonata.Form.prototype.clearFields = function() {
	var name;
	var field;
	for(name in this.fields) {
		field = this.fields[name];
		if(field.ctl == null) continue;
		switch(field.type) {
			case 'hidden':
			case 'select':
			case "text":
				this.setValue(field,"");
				break;
			case 'radio':	
			case 'checkbox':
			case "radiogrp":
			case "checkgrp":
				this.setValue(field,false);
				break;
		}
	}
}
Sonata.Form.prototype.verify = function() {
	//dlg is class Dialogs
	//mprint("in Click");
	var values = {};
	var name;
	var i,n;
	
	var error = "";
	var ok = true;
	var fok = true;
	var fld;
	this.hideRedArrows();
	//mprint("in verify");
	for(name in this.fields) {
		var o = this.fields[name];
		//Sonata.prObject("field",o);
		var tvalue = this.getValue(o);
		fld = {field:o,value:tvalue,ok:true,toString:this.getFieldToString(o)};
		values[name] = fld;
		//mprint("VERIFY name="+name+" arrowDiv="+o.arrowDiv);
		fok = true;
		if(o.ctl!=null && o.bVerify) {
			//mprint("o.cb="+o.cb);
			if(typeof o.cb == 'function') {
				var t = o.cb(o,tvalue);
				if(t.ok==false)
					error += t.errmsg+"<br>";
				fok = t.ok;
			}
			else  {
				switch(o.type) {
				case 'hidden':
				case 'select':
				case "text":
				case "radiogrp":
				case "checkgrp":
					if(tvalue=="") { //o.empty) {
						error += o.errmsg+"<br>";
						fok = false;
					}
					break;
				case 'radio':	//check individual buttons checked is completed, unchecked is not completed
				case 'checkbox':
					if(tvalue == false) {
						error += o.errmsg+"<br>";
						fok = false;
					}
					break;
				}
			}
		}
		//mprint("OK="+fok);
		fld.ok = fok;
		if(ok == true) ok = fok;
	}
	var ret = {ok:ok,errmsg:error,values:values};
	if(ok==false)
		this.showRedArrows(ret);
	return ret;
}
Sonata.Form.prototype.eachField = function(cb) {
	if(typeof cb != 'function') return;
	
	var flds = this.fields;
	var name;
	
	for(name in	flds) {
		//mprint("each name="+name);
		cb(name,flds[name]);
	}
}
Sonata.Form.prototype.$makeRedArrows = function() {
	var arrows = {};
	//mprint("makeRedArrows");
	this.eachField(doit);
	
	this.arrows = arrows;
	
	function doit(id,field) {
		//mprint("makeRedArrows name="+id);
		// <div id=arrowid class='sonata-form-field-arrow'><span class='sonata-form-field-bad'></span></div>
		var arrowid = id + "ARROW";
		var elem = field.ctl;
		//mprint("field.ctl="+field.ctl);
		if(elem==null) return;
		if(field.idLabel != "") {
			elem = $("#"+field.idLabel);
			//mprint("red idLabel="+field.idLabel+" size="+elem.size());
			if(elem.size() == 0)
				elem = field.ctl;
		}
		//<span class='sonata-form-field-bad'></span>
		//mprint("elem="+elem[0]);
		var pos = elem.offset();
		var div = document.createElement("div");
		div.id = arrowid;
		div.style.display = "none";
		div.style.position = "absolute";
		var left = pos.left-14;
		var top = pos.top-5;
		div.style.left = left+"px";
		div.style.top = top+"px";
		div.innerHTML = "<img src='" + Sonata.JSPLATFORM+"images/redarrow.gif'>";
		document.body.appendChild(div);
		field.arrowDiv = {div:$(div),elem:elem,left: left,top:top};
		return;
	}
}
Sonata.Form.prototype.hideRedArrows = function() {
	if(this.opts.bShowRedArrows==false) return;

	this.eachField(doit);
	
	function doit(id,field) {
		if(field.arrowDiv != null) {
			field.arrowDiv.div.hide();
		}
	}
}
Sonata.Form.prototype.showRedArrows = function(vflds) {
	//vflds={ok:ok,errmsg:error,values:values};values = {field:o,value:tvalue,ok:true}; keyed by name
	
	if(this.opts.bShowRedArrows==false) return;
	
	if(vflds.ok==true) {
		this.hideRedArrows();
		return;
	}
	var name;
	var flds = vflds.values;
	for(name in flds) {
		var p = flds[name];	//{field:o,value:tvalue,ok:true};
		if(p.ok)
			hideArrow(p.field);
		else
			showArrow(p.field);
	}
	function hideArrow(field) {
		if(field.arrowDiv != null) {
			//var pos = field.arrowDiv.div.offset();
			//mprint("pos left="+pos.left+" top="+pos.top);
			field.arrowDiv.div.hide();
		}
	}
	function showArrow(field) {
		if(field.arrowDiv != null) {
			var p = field.arrowDiv;
			var ctl = field.arrowDiv.elem;//ctl;
			var pos = ctl.offset();
			var w = p.div.width();
			var h2 = p.div.height();
			var h = ctl.height();
			var dif = h-h2;
			if(dif<=0) dif = 0;
			else dif = dif/2;
			
			var left = pos.left-w-4;
			var top = pos.top+dif;
			p.left = left;
			p.top = top;
			p.div.css("left",left+"px");
			p.div.css("top",top+"px");
			//mprint("left="+p.left+" top="+p.top);		
			field.arrowDiv.div.show();
		}
	}
	
}
Sonata.Form.prototype.toJSON = function(obj) {
	return Sonata.Form.toJSON(obj);
}
Sonata.Form.toJSON = function(obj) {
	s = doit(obj);
	return s;
	
	function doit(obj) {
		var t = obj instanceof Array;
		var s = "";
		if(t)
			s += getArray(obj);
		else if(typeof obj == "object")
			s += getObject(obj);
		else
			s += '"' + obj + '"';
		return s;
	}
	function getArray(arr) {
		var s = "[";
		var i,n = arr.length;
		var sep = "";
		for(i=0;i<n;i++) {
			var p = arr[i];
			s += sep + doit(p);
			sep = " , ";
		}
		s += "]";
		return s;
	}
	function getObject(obj) {
		var name;
		var s = "{";
		var sep = "";
		for(name in obj) {
			var v = doit(obj[name]);
			s += sep + '"'+name+'" : ' + v + '';
			sep = " , ";
		}
		s += " }";
		return s;
	}
}
Sonata.Form.getSelectValue = function(ctl,empty) {
	//ctl is jQuery object
	if(typeof empty == 'undefined')
		empty = "";
	var elem = ctl[0];
	if(elem.selectedIndex<0)
		return "";
	var s = elem.options[elem.selectedIndex].value;
	//mprint("elem="+elem+" selected="+elem.selectedIndex);
	//mprint("s="+s+" empty="+empty);
	if(s == empty) return "";
	return s;
}
Sonata.Form.setSelectValue = function(ctl,value) {
	var elem = ctl[0];
	var i,n = elem.options.length;
	if(value == "") {
		elem.selectedIndex = 0;
	}
	else {
		for(i=0;i<n;i++) {
			var o = elem.options[i];
			if(o.value == value) {
				elem.selectedIndex = i;
				break;
			}
		}
	}
}

Sonata.Form.getTextValue = function(ctl) {
	return ctl[0].value;
}
Sonata.Form.setTextValue = function(ctl,value) {
	ctl[0].value = value;
}

Sonata.Form.getBtnValue = function(ctl) {
	return ctl[0].checked;
}
Sonata.Form.setBtnValue = function(ctl,on) {
	ctl[0].checked = on;
}
Sonata.Form.getIntInfo = function(s) {
	var num = 0;
	var ok = true;
	num = parseInt(s);
	if(isNaN(num)) {
		ok = false;
		num = 0;
	}
	return {ok:ok,number:num};
}
Sonata.Form.getFloatInfo = function(s) {
	var num = 0;
	var ok = true;
	num = parseFloat(s);
	if(isNaN(num)) {
		ok = false;
		num = 0;
	}
	return {ok:ok,number:num};
}

Sonata.Form.isInt = function(s) {
	//s is string
	var t = Sonata.Form.getIntInfo(s);
	return t.ok;
}
Sonata.Form.isFloat = function(s) {
	//s is string
	var t = Sonata.Form.getFloatInfo(s);
	return t.ok;
}
Sonata.Form.isNumber = function(s) {
	var t = Sonata.Form.getIntInfo(s);
	if(t.ok==false) 
		t = Sonata.Form.getFloatInfo(s);
	return t.ok;
}
Sonata.Form.getInt = function(s) {
	var num = 0;
	num = parseInt(s);
	if(isNaN(num))
		num = 0;
	return num;
}
Sonata.Form.getNumber = function(s) {
	var d = Sonata.Form.getFloatInfo(s);
	return d.number;
}
Sonata.Form.getFloat = function(s) {
	var num = 0;
	num = parseFloat(s);
	if(isNaN(num))
		num = 0;
	return num;
}
Sonata.Form.eval = function(text)
{
	var v = '(' + text + ')';
	//mprint("eval v=" + v);
	return eval(v);
}

