//<!--Copyright 2006,2007 Eljakim Information Technology B.V.-->
/*************************************************************
* CTEXTBASE : base klasse voor text input controls
*************************************************************/
//<!--Copyright 2006,2007 Eljakim Information Technology B.V.-->
var DEBUG = 0;
var js_path = "."; // pad naar .js bestanden, geen trailing /
/****************** global functions *********************/

function isDef(v) { return typeof(v)!="undefined"; }
function dbg(o) {alert(o+"::"); for(x in o) alert(x + "=" + o[x]); }

function getTarget(event) {
  return event.target ? event.target : event.srcElement;
}
function addListener(obj, evType, fn, bubble){
  if (obj.addEventListener)  obj.addEventListener(evType, fn, bubble?true:false);
  else obj.attachEvent("on" + evType, fn);
}
function stopDefault(event) {
  if(event.preventDefault) event.preventDefault();
  else event.returnValue = false;
}

function removeNodes(elem) {
  if(elem.childNodes.length) {
    elem.removeChild(elem.childNodes[0]);
	removeNodes(elem);
  }
}
function objToPostString(obj) {
  var ret = "";
  for(x in obj) ret += encodeURIComponent(x) + "=" + encodeURIComponent(obj[x]) + "&";
  return ret;
}
//function filterHTML(str) {  return typeof str == "string" ? str.replace(/</g,'&lt;') : str;}

function showError(err) {
  var d=document.createElement("div");
  d.className = 'error_div';
  d.innerHTML = "Error:<br><pre><xmp>" + err;
  addListener(d,"dblclick",function(e){getTarget(e).style.display="none";});
  document.body.appendChild(d);
}

function findControl(e) {
  var t=getTarget(e);
  while(t && (!t.control)) t = t.parentNode;
  return t;
}

try      { var xml_conn = new XMLHttpRequest(); }
catch(e) { var xml_conn = new ActiveXObject("Msxml2.XMLHTTP"); }


function include(arr) { for(var i=0;i<arr.length;++i) document.write("<script language='JavaScript' src='"+js_path + "/" + arr[i]+"'></s"+"cript>");}
//include(["func.js","CText.js","settings.js","CChoice.js","CLayout.js","CMisc.js","CListview.js","CSlidebar.js","CCombobox.js","CGrid.js","CSearchbox.js","sqlsource.js","errormsg.js"]);

/*********
* FORM   *
*********/
 
function Form(_name,_par,_url) {
  if((!_name)&&(!_par)&&(!window.form_div)) return;
  if(typeof window.form_div=="string") window.form_div = document.getElementById(window.form_div)
 
  if(window.form_div)window.form_div.Form = this;
  
  this.form = document.createElement("form");
  this.form.handler = this;
  this.name    = isDef(_name)?_name:"";
  this.params  = isDef(_par)?_par:{};
  this.content = new Section();
  this.content.html.className = "form_content";
  this.url = _url;
  
  var self = this;
  this.form.onsubmit = function(){
    try { this.handler.post();}
	catch(e) { dbg(e); alert("Fout bij POST request: \n" + e.description); }
	return false;
  };
  
}

Form.prototype.setCaption = function(cap) {
  alert("gebruik setCaption() en niet form.setCaption()");
  setCaption(cap);
}

Form.prototype.show = function() {
  this.form.appendChild(this.content.getHTML());
  window.form_div.appendChild(this.form);
}

Form.prototype.reset = function() {
  this.content.reset();
}

Form.prototype.post = function(xpar) {
  if(DEBUG) alert("submit " + this.name);
  if(!this.content.validate()) return false;

  var cval = this.content.getValue();
  if(cval=="" && (!this.forceDirty)) return true; // niet posten als er niks 'dirty' is
  
  if(!xpar) xpar = {};
  var poststr = "formName=" + this.name + "&" + objToPostString(this.params) + objToPostString(xpar) + cval;
  if(DEBUG) alert("POSTING:" + poststr);
  
  xml_conn.open("POST",this.url?this.url:window.postform_url,false);
  xml_conn.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
  xml_conn.send(poststr);
  
  if(xml_conn.status != 200) {
    alert("Error " + xml_conn.status + "\nfout bij versturen naar server: pagina niet gevonden of kan niet geladen worden\nPagina: " + (this.url?this.url:window.postform_url));
    return false;
  }
  
  if(xml_conn.responseText.length == 0) return true; // alles goed -> server stil
  try {
    if(DEBUG) alert(xml_conn.responseText);
	eval(xml_conn.responseText);
  } catch(e) {
    showError("fatale fout bij het interpreteren javascript afkomstig van:\n" + poststr + "\nError: \n" + e.message + "\nJavascript:\n"+xml_conn.responseText);
  }
  return this.content.validate(); // laat de server errors zien en return validate waarde
}
/****************************
* SECTION : bevat controls  *
****************************/
function Section() {
  this.html = document.createElement("div");
  this.controls = [];
}

Section.prototype.add = function(elem) {
  this.controls.push(elem);
}

Section.prototype.getHTML = function() {
  for(var i=0; i < this.controls.length; ++i) this.html.appendChild(this.controls[i].getHTML());
  return this.html;
}

Section.prototype.reset = function() {
  for(var i=0; i < this.controls.length; ++i) this.controls[i].reset();
}

Section.prototype.validate = function() {
  var ret = true;
  for(var i=0; i < this.controls.length; ++i) if(!this.controls[i].validate()) ret = false;
  return ret;
}
Section.prototype.validate = function() {
  var ret = true;
  for(var i=0; i < this.controls.length; ++i) if(!this.controls[i].validate()) ret = false;
  return ret;
}
/* isDirty <=> getValue != "" */
Section.prototype.getValue = function() {
  var ret = "";
  for(var i=0; i < this.controls.length; ++i) if(this.controls[i].isDirty()) {
    if(this.controls[i].readOnly) ret += this.controls[i].getValue(); // layout control zorgt zelf voor value/name paren
	else ret += this.controls[i].name + "=" + encodeURIComponent(this.controls[i].getValue()) + "&"; // input controls niet
  }
  return ret;
}

Section.prototype.getControlByName = function(name) {
  for(var i=0; i < this.controls.length; ++i) {
    var c = this.controls[i].getControlByName(name)
    if(c) return c;
  }
  return false;
}

/***************************************************************************
* CONTROL : base class voor een control -  x,y,width,height zijn optioneel *
***************************************************************************/

function Control(name,value) {

  if(!isDef(name)) return; // return bij prototype call
  this.name = name;
  this.setDefValue(value);
  
  this.readOnly   = false;
  this.allowEmpty = false;
  
  this.html = document.createElement("span");
  this.html.style.position = "static"; // = "relative"
}
/********* framework gebruiker functies ************************/
Control.prototype.setPosition = function(x,y,width,height) {
  if(  (isDef(x)&&x!=-1) || (isDef(y) && y!=-1) ) {
    if(!isDef(x) || x==-1) x = "static-position";
	if(!isDef(y) || y==-1) y = "static-position";
    this.html.style.position = "absolute";
    this.html.style.left = x + "px";
    this.html.style.top  = y + "px";
  }

  if(isDef(width) || isDef(height)) {
    this.html.display = "block";
	this.html.style.overflow = "auto"; // te groot -> scrollen
  }
  if(isDef(width) && width !=-1 ) this.html.style.width  = width;
  if(isDef(height)&& height!=-1) this.html.style.height = height;
}

Control.prototype.setDefValue = function(value) {
  this.defaultValue = value;
}
Control.prototype.setReadOnly = function(read) {
  this.readOnly = read;
  if(!this.html.className) this.html.className="";
  if(read) this.html.className = "readonly " + this.html.className;
  else this.html.className = this.html.className.replace(/readonly\s*/g,"");
}

/************** interne functies **************************/
Control.prototype.reset = function() {
  this.hideValidateError();
  if(!this.readOnly) this.setValue(this.defaultValue);
}

Control.prototype.getHTML = function() {
  this.reset();
  return this.html;
}
Control.prototype.getValue = function() {
  return this.defaultValue;
}

Control.prototype.isDirty = function() {
  return (this.readOnly ? false : this.defaultValue != this.getValue());
}

Control.prototype.getControlByName = function(name) {
  return this.name==name ? this : false;
}

Control.prototype.fireEvent = function(type,event) {
  this.firing = true;
  var toFire = this["on" + type];
  if(toFire) {
    if(typeof toFire=="string") eval(toFire);
	else toFire.call(this,event); // call function in this scope
  }
  this.firing = false;
}

Control.prototype.validate = function() {
  if(!this.serverValidate()) return false;
  
  if(this.readOnly || this.allowEmpty || this.getValue() !== "") return true;
  this.validateError(this.ve_empty);
  return false;
}

Control.prototype.serverValidate = function() {
  if(this.serverValidateError) {
    this.validateError(this.serverValidateError);
	return false;
  }
  else {
    this.hideValidateError();
    return true;
  }
}

Control.prototype.validateError = function(str) {
  if(!this.feedback) {
    this.feedback = this.createFeedbackElem();
	this.html.appendChild(this.feedback);
  }
  if(this.html.style.position=="static") this.html.style.position = "relative"
  this.feedback.style.display = "inline";
  this.feedback.innerHTML = str;
}

Control.prototype.hideValidateError = function() {
  if(!this.html) dbg(this);
  if(this.feedback) this.feedback.style.display = 'none';
  if(this.html.style.position=="relative") this.html.style.position = "static"
  this.serverValidateError = 0;
}

Control.prototype.focus = function() {
  if(this.inputElem && this.inputElem.focus && (!this.inputElem.readOnly)) this.inputElem.focus();
}

Control.prototype.createFeedbackElem = function() {
  var elem = document.createElement("div");
  elem.className = "feedbackElem";
  var ctrl = this;
  addListener(elem,"click",function(evt){ctrl.hideValidateError(); ctrl.focus();});
  return elem;
}

/***************** default msg ********************/
Control.prototype.ve_empty = "";


/*****************************************
* CSUBFORM: zowel een form als een control
*****************************************/
function CSubForm(name,par,url,width,height) {
 if(!url) url = subform_url;

  Control.call(this,"__subform","");
  var fdbck = window.form_div;
  window.form_div = this.html; // form contructor doet er iets mee
  Form.call(this,name,par,url);
  window.form_div = fdbck;

  this.html.className = "subform";
  
  this.allowEmpty = true;
  this.readOnly = true;
  if(width) {
    this.html.style.display = "block";
    this.html.style.width = width;
  }
  if(height) this.html.style.height = height;

}
CSubForm.prototype = new Form();
for(var i in Control.prototype) CSubForm.prototype[i] = Control.prototype[i]; // multiple inheritance :)

CSubForm.prototype.clear = function() {
  this.content = new Section();
  removeNodes(this.html);
}

CSubForm.prototype.load = function(par) {
  this.clear();
  if(!par) par = {};
  var poststr = "getForm=" + this.name + "&" +  objToPostString(this.params) +  objToPostString(par);
  xml_conn.open("POST",this.url,false);
  xml_conn.setRequestHeader('Content-Type','application/x-www-form-urlencoded');
  xml_conn.send(poststr);
  if(xml_conn.status != 200) {
    alert("Error " + xml_conn.status + "\nfout bij het ophalen van een subformulier: pagina niet gevonden of kan niet geladen worden\nPagina: " + this.url);
    return false;
  }
  if(DEBUG) alert(xml_conn.responseText);
  try      {  eval(xml_conn.responseText);  }
  catch(e) {  showError("fatale fout bij het interpreteren javascript afkomstig van:\n" + poststr + "\nErrormessage: \n" + e.message + "\n" + xml_conn.responseText); }

  this.html.appendChild(this.content.getHTML());
}

CSubForm.prototype.getHTML = function() {
  this.load();
  return this.html;
}




function CTextBase(name,value,mask) {
  if(!isDef(name)) return; // return bij prototype call
  Control.call(this,name,value);
  this.setMask(mask?mask:"^");
}
CTextBase.prototype = new Control();

CTextBase.prototype.addListeners = function() {
  var ctrl = this; // catch scope
  addListener(this.inputElem,"blur",function(evt){ctrl.validate();});
  addListener(this.inputElem,"focus",function(evt){ctrl.hideValidateError();});
  addListener(this.inputElem,"change",function(){ctrl.fireEvent("change");});
  addListener(this.inputElem,"keypress",function(evt){return ctrl.keyHandler(evt);});
}

CTextBase.prototype.reset = function() {
  this.hideValidateError();
  this.setValue(this.defaultValue);
}

CTextBase.prototype.setValue = function(value) {
  this.inputElem.value = value;
}

CTextBase.prototype.getValue = function() {
  return this.inputElem.value;
}

CTextBase.prototype.setReadOnly = function(read) {
  Control.prototype.setReadOnly.call(this,read);
  this.inputElem.readOnly = read;
}

CTextBase.prototype.keyHandler = function(event) {
  this.hideValidateError();
  var key = event.charCode;
  if(!isDef(key)) key = event.keyCode;
  if( (!key) || key == 8 || key == 9 ||(event.ctrlKey)) return true; //  bs | tab | ctrl + vcz
  var ret = this.checkChar(key);
  if(!ret) stopDefault(event);
  return ret;
}

CTextBase.prototype.checkChar = function(c) {
  var inMask = this.mask[c] || false;
  if(this.maskInv) return !inMask;
  else             return inMask;
}


// A-Za-z0-9. voor ranges of  ^a-z" voor inverse ranges
CTextBase.prototype.setMask = function(mstr) {
  this.mask = new Object();
  var len = mstr.length, act = 0;
  if(len==0) return;
  if(mstr.charAt(0) == '^') {
    this.maskInv = true;
	++act;
  }
  else this.maskInv = false;
  while(act < len) {
    var c = mstr.charCodeAt(act++), c2;
    if(act>=(len-1) || mstr.charAt(act)!='-') this.mask[c] = true;
	else { // range
	  ++act;
	  c2 = mstr.charCodeAt(act++);
	  for(var i = c; i <= c2; ++i) this.mask[i] = true;
	}
  }
}

CTextBase.prototype.filterMask = function() {
  var val = this.inputElem.value, ret = true, newval = "";
  
  for(var i=0; i<val.length; ++i) {
    if(this.checkChar(val.charCodeAt(i))) newval += val.charAt(i);
	else ret = false;
  }
  
  if(!ret) this.setValue(newval);
  return ret;
}

CTextBase.prototype.validate = function() {
  if(!this.serverValidate()) return false;
  this.filterMask();
  return Control.prototype.validate.call(this);
}

/*************************************************************
* CTEXT : Text input control                                 *
*************************************************************/
function CText(name,value,maxlen,size,mask) {
  CTextBase.call(this,name,value,mask);
  
  this.inputElem = document.createElement("input");
  this.inputElem.control = this;
  this.inputElem.type = "text";
  this.inputElem.className = "ctext";
  if(maxlen) this.inputElem.maxLength = maxlen;
  if(size)   this.inputElem.size = size;
  
  this.addListeners();

  this.html.appendChild(this.inputElem);
}
CText.prototype = new CTextBase();

/*************************************************************
* CTEXTAREA : Text input control voor meerdere regels
*************************************************************/
function CTextArea(name,value,maxlen,rows,cols,mask) {
  CTextBase.call(this,name,value,mask);

  this.inputElem = document.createElement("textarea");
  this.inputElem.control = this;
  this.inputElem.className = "ctextarea";
  if(maxlen) this.inputElem.maxLength = maxlen;
  if(rows)   this.inputElem.rows  = rows;
  if(cols)   this.inputElem.cols  = cols;
    
  this.addListeners();

  this.html.appendChild(this.inputElem);
}
CTextArea.prototype = new CTextBase();

CTextArea.prototype.getValue = function() {
  return this.inputElem.value.replace(/\r\n/g,"\n");
}


/*************************************************************
* CNumeric : Numeric input control
*************************************************************/
function isDigit(c){return c>='0'&&c<='9';}

function CNumeric(id,name,value,decimals,maxValue,size,allowNeg) {
  /********* settings *************/
  this.maxValue = isDef(maxValue) ? maxValue : 1e20;
  /********************************/
  this.neg = isDef(allowNeg)?allowNeg : 1;
  var object = this;
  CTextBase.call(this,name,value, (this.neg?'-':'') + "0-9" + this.sep1000 + this.decpoint );

  this.dec = decimals;
  this.p10 = Math.pow(10,this.dec);
  this.inputElem  = document.createElement("input");
  this.inputElem.id = id;
  if(!this.inputElem)alert("!!!ERROR FINDING INPUT ELEMENT!!!")
  this.submitElem = document.createElement("input");
  this.submitElem.type = "hidden";
  this.submitElem.name = name;
  var object = this;
  this.inputElem.control = this;
  this.inputElem.type = "text";
  this.inputElem.className = "cnumeric";
  if(size)   this.inputElem.size = size;
  //this.addListeners();

  //this.inputElem.onblur=function(){object.submitElem.value = object.getValue();};
  this.prevValue = "~";

  this.html.appendChild(this.inputElem);
  this.html.appendChild(this.submitElem);
    
    addEvent(this.inputElem,"blur",function(){
									object.submitElem.value = object.getValue();
									}
			);
	addEvent(this.inputElem,"keypress",function(event){
														if(!event)event=window.event;
														if(e.keyCode==13) 		
															object.submitElem.value = object.getValue();														
														return agSubmitViaEnter(event, object.submitElem);
														});
}
CNumeric.prototype = new CTextBase();

CNumeric.prototype.setValue = function(val) {
  if(val=="") this.internVal = "";
  else         this.internVal = Math.round(val*this.p10)/this.p10;
  this.format();
  this.submitElem.value = this.internVal;
}

CNumeric.prototype.parse = function() {
  //this.filterMask();
  /*var val = this.inputElem.value, act = 0, nr="";
  if(val == this.prevValue) return;
  var len = val.length;
  if(val.charAt(0)=='-') {nr="-";act++;}
  while(val.charAt(act)!=this.decpoint && act < len) {
    var c = val.charAt(act);
    if(isDigit(c)) nr += c;
	act++;
  }
  if(this.dec > 0 && act<len) {
    nr += '.';
	while(act < len) {
      var c = val.charAt(act);
      if(isDigit(c)) nr += c;
	  act++;
	}
  }*/
  var val = this.inputElem.value;
  var parser = new NumericParser(this.decpoint,val);
  this.internVal =  parser.parse();

  if(isNaN(this.internVal)) this.internVal = "";
}

CNumeric.prototype.format = function() {
  if(this.internVal === "") 
  {
	this.inputElem.value = this.prevValue = ""; 
	return;
  }
  
  if(Math.abs(this.internVal) > this.maxValue) 
	this.internVal = this.maxValue * (Math.abs(this.internVal)/this.internVal);
  
  var renderer = new NumericRenderer(this.decpoint,this.sep1000,this.dec,this.internVal);
  this.prevValue = renderer.render();
  this.inputElem.value = this.prevValue;
}

CNumeric.prototype.getValue = function() {
  this.parse();
  this.format();
  return this.internVal;
}

CNumeric.prototype.validate = function() {
  if(!this.serverValidate()) return false;
  var v = this.getValue();
  return CTextBase.prototype.validate.call(this);
}
 

 
/*************************************************************
* CDateTime : Datum/Tijd input control
*************************************************************/
function pad(nr,size) {
  return (""+nr).length < size ? pad("0"+nr,size) : nr;
}


function CDateTime(name,value,format,type,maxlen,size,useTimestamp) {
  CTextBase.call(this,name,value,"-0-9/.: ");
  this.onchange = function () {};
  this.inputElem = document.createElement("input");
  this.inputElem.control = this;
  this.inputElem.type = type;
  this.inputElem.name = name;
  this.inputElem.className = "cdatetime";
  if(maxlen) this.inputElem.maxLength = maxlen;
  if(size)   this.inputElem.size = size;
  this.addListeners();
  this.dformat = format;
  this.usestamp = isDef(useTimestamp) ? useTimestamp : 0;
  
  this.pad =  {d:0,D:2,m:0,M:2,y:2,Y:4,h:0,H:2,i:0,I:2,s:0,S:2};
  this.func = {d:"Date",m:"Month",y:"FullYear",h:"Hours",i:"Minutes",s:"Seconds",n:"Month",w:"Day"};
  
  this.sym = [];
  this.fixyear = (new Date().getYear() + 30) % 100;
  
  for(var i=0;i<format.length;++i) {
    var c = format.charAt(i);
	if(c=='\\') {++i;continue;} // \ -> volgende char overslaan
	if(c in this.pad) this.sym.push(c);
  }
  this.defaultDate = null;
  this.prevValue = "~";
  this.html.appendChild(this.inputElem);
}
CDateTime.prototype = new CTextBase();

CDateTime.prototype.setValueByDate = function(date) {
  this.internVal = date;
  this.format();
}
CDateTime.prototype.getValueByDate = function() {
  return this.internVal;
}

CDateTime.prototype.setValue = function(val) {
  if(!val)return;
  if(!this.usestamp) {
    this.inputElem.value = val;
    this.parse();
  }
  else this.internVal = new Date(val);
  this.format();
}

CDateTime.prototype.parse = function() {
  this.filterMask();
  var val = this.inputElem.value;
  if(val == this.prevValue) return;
  this.prevValue = val;
  var date = this.defaultDate;
  if(!date) date = new Date();
  var dFields = {};  
  for(x in this.func) 
	dFields[x] = date["get"+this.func[x]](); //vul datum met vandaag
  var i=0;
  for(;i<this.sym.length;++i) {
    var csym = this.sym[i];
    var len = this.pad[csym] ? this.pad[csym] : 10;
    csym = csym.toLowerCase();
    var reg = new RegExp("\\D*(\\d{1,"+ len +"})(.*)");
    var m = reg.exec(val);
    if(m==null) break;
    val = m[2];
	m[1] = fixInt(m[1]);
	if(csym == 'y' && m[1] < 100) m[1] = parseInt(m[1]) + (m[1] < this.fixyear ? 2000:1900);
	if(csym == 'm') --m[1];
	if(m[1] > 10000) m[1] %= 10000; // te grote getallen zorgen voor inf/NaN
	dFields[csym] = m[1]; // niet set hier, maar in constructor (voor 32-01 => 01-02 etc)
  }
  if(i==0 && !this.defaultDate) {
    this.internVal = null; // 0 tekens herkent en geen default -> leeg
  }
  else this.internVal = new Date(dFields.y,dFields.m,dFields.d,dFields.h,dFields.i,dFields.s);

}

function fixInt(input) //als een nummer met nullen begint halen we de nullen weg zodat parseint ermee overweg kan
{
		input = input + "";
		var chr = "0";
		var i = 0;
		while(chr == "0" && i<input.length)
		{
			chr = input.substr(i,1);
			i++;
		}

		if(i<=input.length)
		{
			return input.substring(i-1);
		}else
			return "0";
}

CDateTime.prototype.format = function() {
  var res = "", date = this.internVal;
  if(!date) {
    this.prevValue = this.inputElem.value = "";
    return;
  }
  for(var i=0; i < this.dformat.length; ++i) {
    var c = this.dformat.charAt(i);
    if(c=='\\') {res+=this.dformat.charAt(++i); continue;} // \ -> volgende char overslaan
	
	if(c.toLowerCase() in this.func) {
	  var dval = date["get"+this.func[c.toLowerCase()]](); // getyear, gethours etc
	  if(c == 'y') dval %= 100;
	  if(c == 'm'||c=='M') ++dval;
	  if(c in this.dateNames) dval = this.dateNames[c][dval];
	  dval = pad(dval,this.pad[c]);
	  res += dval;
	}
	else res += c;
  }
  this.prevValue = this.inputElem.value = res;
}

CDateTime.prototype.getValue = function() {
  this.parse();
  this.format();
  return this.usestamp&&this.internVal ? this.internVal.getTime() : this.inputElem.value;
}

CDateTime.prototype.validate = function() {
  if(!this.serverValidate()) return false;
  var v = this.getValue();
  var ret = CTextBase.prototype.validate.call(this);
  if(this.updateDateValues)this.updateDateValues();
  fireEvent(this.inputElem,"change");//this.onchange();
  return ret;
}
 
 /*************************************************************
* CHours : input control voor een aantal uren
*************************************************************/

function CHours(name,value,size,maxHours) {
  CTextBase.call(this,name,value,"-0-9/.,:");
  
  this.inputElem = document.createElement("input");
  this.inputElem.control = this;
  this.inputElem.type = "text";
  this.inputElem.className = "chours";
  if(size)   this.inputElem.size = size;
  this.addListeners();
  
  this.maxHours = maxHours ? maxHours : 1e9;
  this.prevValue = "~";
  this.html.appendChild(this.inputElem);
}
CHours.prototype = new CTextBase();


CHours.prototype.setValue = function(val) {
  this.inputElem.value = val;
  this.parse();
}
CHours.prototype.parse = function() {
  this.filterMask();
  var val = this.inputElem.value;
  if(val == this.prevValue) return;
  this.prevValue = val;
  var regMinus = /\D*-(\D*)/,
      regColon = /\D*(\d*)\D*?:\D*(\d+)/,
      regComma = /\D*(\d*)\D*?[,.]\D*(\d+)/,
	  regSingle= /\D*(\d+)(.*)/;

  var m, hrs = 0, min = 0, neg = regMinus.exec(val);

       if(m = regColon.exec(val))  { hrs = m[1] ; min = m[2]; }
  else if(m = regComma.exec(val))  { hrs = m[1] ; min = Math.round( parseFloat("0." + m[2]) * 60 ) ; }
  else if(m = regSingle.exec(val)) { hrs = m[1] ;}
  else { this.inputElem.value = ""; return; }
  hrs = parseInt(hrs); if(isNaN(hrs)) hrs = 0;
  if(Math.abs(hrs) > this.maxHours) hrs = this.maxHours;
  this.inputElem.value = (neg?'-':'') + hrs + ":" + pad(min,2);
}

CHours.prototype.getValue = function() {
  this.parse();
  return this.inputElem.value;
}

CHours.prototype.validate = function() {
  if(!this.serverValidate()) return false;
  var v = this.getValue();
  var ret = Control.prototype.validate.call(this);
  return ret;
}
 