/***************************************************************************
| Loans Till PayDay
|---------------------------------------------------------------------------
|	protoTools 2.6 JS library. Requires Prototype.js library v1..6.0.2
|---------------------------------------------------------------------------
| Designed by Dmitry Lopyrev
|****************************************************************************/

var msgProgress = "processing..."

var Utility = {
	Guid:function(){return new Date().getTime().toPaddedString(10,16)},
	ParseXml: function(xtext){
		try {
			var xml;
			if (window.ActiveXObject)	{
				xml=new ActiveXObject("Microsoft.XMLDOM");
				xml.async = false;
				xml.loadXML(xtext);
			} else { // code for Mozilla, Firefox, Opera, etc.	
				var parser=new DOMParser();
				xml=parser.parseFromString(xtext,"text/xml");
			}
			return xml;
		}	catch(e){return false;}
	}
}


Error.prototype.Show = function(msg){
	if (typeof(msg)=='boolean' && !msg) {
		return false;
	} else if (typeof(msg)=='object') {
		for(var key in msg)
			this[key] = msg[key];
		this.message = (this.format ? this.format : "#{message}\nError:#{name}; Object:#{id}").interpolate(this);
	} else if (typeof(msg)=='string')
			this.message = msg;
	else
			this.message = this.name +'::'+this.message;	
	
	window.alert(this.message); 	
	return false;
}


//===========================================================================================================\dlo/
// Display pop window with an error message
// for backward accesability
function processErr(e) {
	new Error(e||'Unknown error').Show();
}

//set time 
Date.prototype.setTime = function(f) {
	if (a=f.split(':'), a.length!=2) return;
	this.setHours(parseInt('0'+a[0],10),parseInt('0'+a[1],10));
	return this;
} 

//override current method
Date.prototype.toString = function(f) {
	return this.format(f || 'mm/dd/yyyy');
}

//===========================================================================================================\dlo/
// return a formated date string, 
// 5/9/07: added Month and Weekday names 
Date.prototype.format = function(f) {
	var d = this;
  return isNaN(this) ? "" : f.replace(/(yyyy|yy|mmm|mm|w|ddd|dd|d|hh|nn|ss|ap)/gi,
      function($1) {
          switch ($1.toLowerCase()) {
						case 'yy':	 return (d.getFullYear()%100).toPaddedString(2);
						case 'yyyy': return d.getFullYear().toPaddedString(4); 
						case 'mmm':  return ['January', 'February', 'March', 'April', 'May', 'June', 'July', 'August', 'September', 'October', 'November', 'December'][d.getMonth()];
						case 'mm':   return (d.getMonth() + 1).toPaddedString(2);
						case 'w':		 return ['Sunday','Monday','Tuesday','Wednesday','Thursday','Friday','Saturday'][d.getDay()];
						case 'dd':   return d.getDate().toPaddedString(2);
						case 'd':		 return d.getDate().toString();		
						case 'hh':   return d.getHours().toPaddedString(2);												//hour (01-24)
						case 'h':    return ((h = d.getHours() % 12) ? h : 12).toPaddedString(2);	//hour (01-12)
						case 'nn':   return d.getMinutes().toPaddedString(2);
						case 'n':		 return d.getMinutes().toString();
						case 'ss':   return d.getSeconds().toPaddedString(2);
						case 'ap':   return d.getHours() < 12 ? 'a' : 'p';
          }
      }
  );
}	




//progress element
var Progress = Class.create({
  initialize: function(host,options) {
		if (Object.isElement(host) || Object.isString(host)) {
			this.host = $(host);
		}
		else {
			this.host = $('progress');
			options=host;
		}
		if (!this.host) return null; 
		Object.extend(this, options);
		this.message = this.message || msgProgress;
		this._inner = this.host.innerHTML;
		this.cssClass = 'progress '+ (Object .isString(this.cssClass) ? this.cssClass : '').strip();
		var p = this.host.positionedOffset();
		this.style = {position:'absolute',top:p.top+'px',left:p.left+'px',width: (this.height || this.host.offsetWidth)+'px', height: (this.height || this.host.offsetHeight)+'px'};
			
	},
	show: function() {
		try {
			if (!this.update) {
				this.obj = new Element('div',{className:this.cssClass,title:'Click here to cancel the request',onclick:this.abort.bind(this)}).update(this.message);
				document.body.appendChild(this.obj.setStyle(this.style));
				if (this.update)
					this.host.update();
				else	
					this.host.setStyle({visibility:'hidden'});
			} else {
				this._inner = this.host.innerHTML;
				this.host.update(this.message);
			}	

		} catch(e){};	
	},
	close: function() {
		try {
			if (this.obj) {
				this.obj.parentNode.removeChild(this.obj);
				delete this.obj;
			}	
			if (this.update)
				this.host.update(this._inner);
			else	
				this.host.setStyle({visibility:'visible'})
		} catch(e){};	
	},
	abort: function() {
		try {
			this.caller.request.transport.abort();
		} catch(e){};	
	}
});



var ajaxRequest = Class.create({
	initialize: function(id){
		this.url = location.href.replace(/[\?#].*/gi,'').concat((/\/$/gi.test(location.pathname) ? "default.aspx" :"")).concat(location.search);
		this.parameters = Object.extend([{'_method_':(id||this.id||'unknown')}].concat($A(arguments).reject(function(a,i){return i<1})),{
			create: function() {
				try{
					var o={}; 
					this.each(function(arg,name){
						if (Object.isUndefined(name)) {
							return;
						} else if (Object.isArray(arg)) { 
							for(var i=0,item; item=arg[i++];)
								arguments.callee.call(this,item,name+String(i));
						} else if (Object.isElement(arg)) {
							arguments.callee.call(this,arg.value, (arg.id || arg.name));
						} else if (arg instanceof Object) { 
							for (var key in arg)
								!Object.isFunction(arg[key]) && (arguments.callee.call(this,arg[key],key));
						} else if (!Object.isUndefined(arg)) { 
							if (name==="methodID") name="_method_";
							o[name] = arg;
						}
					},this);
					return o;	
				}catch(e){e.Show(false)}	
			}
		});		
	},
	onError:function(result){
			this.progress.close();		
			(this["on"+String(result.status)] || 
				function(){
					if (result.responseJSON)
						alert(result.responseJSON);
					else	
						$(document.body).update(result.responseText);
				}	
			)(result);
	},
	process: Prototype.emptyFunction,
	onCreate: Prototype.emptyFunction,
	onComplete: Prototype.emptyFunction,
	onExeption: function(r,e){e.Show()},
	fetch: function(options){
		if (!this.progress || !Object.isFunction(this.progress.show) || !Object.isFunction(this.progress.close))
			this.progress = {show:Prototype.emptyFunction,close:Prototype.emptyFunction} 
		else {
			this.progress.caller = this;
		}	
		var o = Object.extend({
			method: this.method || 'POST',
			parameters : this.parameters.create(),
			onCreate: (function(){this.onCreate.apply(this,$A(arguments));this.progress.show();}).bind(this),
			onSuccess: (function(result){this.progress.close(); this.process.apply(this,$A(arguments))}).bind(this),
			onFailure: this.onError.bind(this),
			onComplete: (function(result){
				this.onComplete.apply(this,$A(arguments)); 
				if (result.headerJSON && result.headerJSON.message)
					alert(result.headerJSON.message)
			 }).bind(this), 
			onException:this.onExeption
		}, options || {})
		this.request=new Ajax.Request(this.url, o);
	}
	
});



var MaskedInput = Class.create();

Object.extend(MaskedInput.prototype, {
		maskChars:{'#':/\d/, 'A':/[A-Za-z]/, '?':/./},
		maskRange: function(char){return this.maskChars[char]},
		isMaskChar: function(char){return this.maskRange(char) != null;},
    initialize: function(obj, mask) {
      if (this.obj = $(obj),  !this.obj ) return;
      if (mask && Object.isString(mask) && mask.length>2 && mask.charAt(0)=="/" && mask.charAt(0)==mask.charAt(mask.length-1)) {
				this.mask = new RegExp(mask.substr(1,mask.length-2))
      } else {
				this.mask=mask;
      }
					
      this.obj.observe('focus',this.activate.bindAsEventListener(this));
      this.obj.observe('blur',this.deactivate.bindAsEventListener(this));
      
      if (this.mask  && !this.obj.readOnly) {
        this.obj.observe('keydown',this.keyDown.bindAsEventListener(this));
        this.obj.observe('keypress',this.keyPress.bindAsEventListener(this));
        this.obj.observe('focus',this.getFocus.bindAsEventListener(this));
        this.obj.observe('blur',this.doLeave.bindAsEventListener(this));
        
			  if (this.ismasked = Object.isString(this.mask), this.ismasked) {
          this.placeholder = '_';
				  this.obj.observe('click',this.doSelect.bindAsEventListener(this));
			  } 
      } 
      for (var i=2,arg; arg=arguments[i++];)
				Object.extend(this,arg);
			this.obj.$class=this;	//???????
    },
    
    keyDown: function(e) {
        var code = ((e=e||event), e.keyCode || e.which || e.charCode);
				if (this.ismasked)
					switch(code) {
							case Event.KEY_BACKSPACE:
									this.doBackspace();break;
							case Event.KEY_DELETE:
									this.doDelete();break;
							case Event.KEY_LEFT:
									this.moveCursor(-1);break;
							case Event.KEY_RIGHT:
									this.moveCursor(1);break;
							case Event.KEY_PAGEUP:
							case Event.KEY_HOME:
									this.setCursor(0);break;
							case Event.KEY_PAGEDOWN:
							case Event.KEY_END:
									this.setCursor(this.obj.value.length - 1);break;
							default:
									return true;
					}
				else 
					switch(code) {
							case Event.KEY_INSERT:
								if (this.combo && e.ctrlKey && !this.obj.readOnly) {
									this.doLeave(e);
								}	
								break;
							default:
									return true;
					}
        Event.stop(e);
		},	
    keyPress: function(e) {
        var b,code = ((e=e||event), e.keyCode || e.which || e.charCode);
        switch(code) {
            case Event.KEY_TAB:
            case Event.KEY_RETURN:
              return true;
						case Event.KEY_BACKSPACE:
						case Event.KEY_DELETE:
						case Event.KEY_LEFT:
						case Event.KEY_RIGHT:
						case Event.KEY_HOME:
						case Event.KEY_END:
                return !Prototype.Browser.IE;
            default:
							if (b=this.checkKey(code), !b) {
								Event.stop(e);
              }
        }      
				this.autoComplete();
				return b;	
    },
    getCursor: function() {
        var left, right;
        if(this.obj.createTextRange) {
            var range = document.selection.createRange().duplicate();
            range.moveEnd("character", this.obj.value.length);
            
            if(!range.text)
                left = this.obj.value.indexOf(this.placeholder);
            else
                left = this.obj.value.lastIndexOf(range.text);
                
            range = document.selection.createRange().duplicate();
            range.moveStart("character", -this.obj.value.length);
            
            right = range.text.length;
        } else {
            left = this.obj.selectionStart;
            right = this.obj.selectionEnd;
        }
        return {left: left, right: right};
    },
    moveCursor: function(step, left) {
        var pos = left || this.getCursor().left;
        
        if ((step == 0) || (pos == 0 && step < 0) || (pos >= (this.obj.value.length - 1) && step > 0))
            return false;
        do {
            pos += step;
        } while(!this.isMaskChar(this.mask.charAt(pos)) && pos > 0 && pos < this.obj.value.length);
        
        if(!this.isMaskChar(this.mask.charAt(pos)))
            return false;
        
        this.setCursor(pos);
        return true;
    },
    doBackspace: function() {
        this.doDelete(true);
    },
    doDelete: function(b) {
        var pos = this.getCursor().left;
        var left = this.obj.value.substr(0, pos);
        var right = this.obj.value.substr(pos + 1, this.obj.value.length - 1);
        this.obj.value = left + this.placeholder + right;
        this.setCursor(pos);
        this.moveCursor(b?-1:1);
    },
    doSelect: function(e) {
        var pos = this.getCursor().left;
        (pos == this.obj.value.length) && (pos--)
        if(!this.isMaskChar(this.mask.charAt(pos))) {
            if(!this.moveCursor(1))
                this.moveCursor(-1);
        } else {
            this.setCursor(pos);
        }
    },
    checkKey: function(code) {
        var ch = String.fromCharCode(code);
        if (this.ismasked) {
					var sp = p = this.getCursor().left;
					var r = new RegExp(this.maskRange(this.mask.charAt(p)));
					if(r.test(ch)) {
							this.obj.value = this.obj.value.substr(0, p) + ch + this.obj.value.substr(p + 1, this.obj.value.length - 1);
							while (!this.isMaskChar(this.mask.charAt(++p)) && p < this.obj.value.length);
							this.isCompleted=(p==this.mask.length);
							this.setCursor(this.isMaskChar(this.mask.charAt(p)) ? p : sp);
					}
					return false;
				} else {
					return	new RegExp(this.mask).test(String.fromCharCode(code));
				}	
    },
    setCursor: function(left, right) {
        right = right || left + 1;
        if(this.obj.createTextRange) {
            var range = this.obj.createTextRange();
            range.moveStart("character", left);
            range.moveEnd("character", right - this.obj.value.length);
            range.select();
        } else {
            this.obj.setSelectionRange(left, right);
        }
    },
    activate: function(e){
				
				this.obj.addClassName('focused');
    },
    deactivate: function(e){
				this.obj.removeClassName('focused');
    },
    getFocus: function(e){
				this.doShowError();
				if (this.ismasked) {
					this.isCompleted=false;
					this.obj.value = this.maskValue();
					this.setCursor(this.obj.value.indexOf(this.placeholder));
					this.doSelect();
				}	
    },
    unmaskValue: function() {
        var b,m=this.mask.toArray();
        var v=this.obj.value.toArray();
        if (v.length)
					for (var i=-1,ch; ch=m[++i];)
						v[i] = this.isMaskChar(ch) ? (v[i]!=this.placeholder ? (b=true, v[i]) : ' ') : ch; 
				return b ? v.join('') : '';        
    },
    maskValue: function() {
        var m=this.mask.toArray();
        var v=this.obj.value.toArray();
        for (var i=-1,ch; ch=m[++i];)
					v[i] = this.isMaskChar(ch) ? (!v[i]||v[i]==' '?this.placeholder:v[i]) : ch;
				return v.join('');        
    },
    autoComplete :function(e){
			if (this.ismasked && this.isCompleted && this.obj.form && Object.isFunction(this.obj.form.Activate)) 
				this.obj.form.Activate(this.obj.tabIndex+1);
		},	
    doLeave : function(e) {
      this.obj.removeClassName('active');
			var v='';
			if (Object.isString(this.mask))
				this.obj.value= this.unmaskValue();	
			if (Object.isFunction(this.format)) 
				if (v=this.format.call(this.obj), typeof(v)=="boolean" && v==false) {
					this.doShowError(true);
				}	else {
					this.obj.value=v;
				}	
			 if (Object.isFunction(this.obj.doComplete))
					this.obj.doComplete.call(this.obj,e);
	//			if (this.isAdded && Object.isFunction(this.doAdd)) {
//				this.doAdd.call(this,this.obj.value);
//				this.isAdded=false;
			return true;
    },
    doClear: function() {
			this.obj.value ='';
			this.doShowError();
    },
    doShowError: function(b) {
			if (this.isError=b,b) {
				this.obj.addClassName("error").up(0).addClassName("error");
			} else {
				this.obj.removeClassName("error").up(0).removeClassName("error");
			}
			return this.isError;
    }
});

//===========================================================================================================\dlo/
//Initializes an element to apply 3D animation style 
//Adds new methods to the HTML element
function initButton(ctrl) {
	try {
		ctrl = $(ctrl);
		if (ctrl.hasClassName('button') && !ctrl.initialized) { //?????
			if (ctrl.onclick && ctrl.hasClassName('up|down')) { // / (down|up)/i.test(ctrl.className)
				ctrl.handler = ctrl.onclick;
				ctrl.onclick = ctrl.doCheck = function(b) {
					this.checked=Object.isUndefined(b) ? this.checked^1 : Boolean(b);
					this.removeClassName("up|down").addClassName(this.checked ? 'down':'up');
					if (Object.isFunction(this.handler)) this.handler.apply(this);
				}
				ctrl.doCheck(ctrl.hasClassName('down'));
			}	
			ctrl.initialized =true;	//??????
		}
		return ctrl;
	} catch(e){return e.Show({id:'Button'})}

}

//===========================================================================================================\dlo/
//Initializes <SELECT> element
//Adds new methods to the HTML element
function initSelect(ctrl,options) {
	try {
		if (ctrl= $(ctrl), !ctrl || ctrl.tagName!="SELECT") return false;

		if (ctrl.status)	return ctrl; //don't initialaze more then one time

		Object.extend(ctrl,{
			status:'initializing',
			toString:function() {//returns a string with all elements: undefined - all options, false - unselected options, true - selected options
				if (!this.options) return '';
				var _a = new Array();
				for(var i=0; i<this.options.length;i++) 
					if (!arguments.length || (arguments.length && this[i].selected==arguments[0]) )
							_a.push(this[i].value);
				return _a.join(",");	
			},
			clear:function() {try{
				var _a = new Array();
				while (this.hasChildNodes()) 
					_a.push(this.removeChild(this.lastChild));
				return a;	
				}catch(e) {this._error=e;}
			},
			sort:function() {try{
				if (!this.hasChildNodes) return;
				var _a = this.clear();
				_a.sort(function(a,b){return (a.value==b.value) ? 0 : (a.value<b.value ? -1 : 1);});
				for(var i=0; i<_a.length;i++) 
					this.appendChild(_a[i]);
				}catch(e) {this._error=e;}
			},
			insert:function(index, text, value, selected) {try{
					//negative - to the begin of the list, 0 - to the end of the list, positive just before existing "index" element
					if (isNaN(index) || index>=this.length) index=0;
					var _i = new Element("option",{value:value}).update(text);
					this.insertBefore(_i,index<0 ? this.firstChild :(index>0 ? this[index]:null));
					
					if (this.multiple)  //for the "multiple" select
						_i.selected = selected;
					else if (selected)	//for the "single" select
						this.selectedIndex = _i.index;
					return _i;	
				}catch(e) {this._error=e;}
			},
			//Copies/removes all selected element from the other <SELECT> object
			copy:function(oS, b) {try{
				if (!oS || oS.tagName!="SELECT" || !oS.options || oS.selectedIndex == -1 )  return;
				for (var i=oS.length-1; i>=0; i-- )
					if ( oS[i].selected ) 
							this.appendChild(b ? oS.removeChild(oS[i]) : oS[i]);
				this.sort();
				}catch(e) {this._error=e;}
			},
			load:function(o,keys) {try{ //loads data from object
					this.clear();
					if (Object.isArray(o) && Object.isArray(keys) && keys.length>=2) {
						for(var i=0, row; row=o[i++];) {
							this.insert(0, row[keys[1]], row[keys[0]], Boolean(row["selected"]));
						};
						return true;	
					} else return false;
				}catch(e) {this._error=e;}
			},
			activate: function(e){
					this.addClassName('focused');
			},
			deactivate: function(e){
					this.removeClassName('focused|error');
			},
			doClear: function() {
				this.obj.value ='';
				this.doShowError();
			}
			
		});
		ctrl.observe('focus',ctrl.activate);
    ctrl.observe('blur',ctrl.deactivate);

		Object.extend(ctrl, options);

	  ctrl.status='initialized';
		return ctrl;
	} catch(e){return e.Show({id:'Select'})}
}


//===========================================================================================================\dlo/
//Initializes a new Input control 
function initControl(ctrl,data, mask) {
	try	{
		if (ctrl=$(ctrl), !ctrl)  
			return false; 
		else if (ctrl.status) 
			return ctrl;

		
		var o = {
			status:'initializing',
			type : function(){var t=/number|word|date|time|email|select|button/i.exec(ctrl.className); return t?t[0].toLowerCase():'';}(),
			combo : /combo/i.test(ctrl.className),
			data : function() {
        if (data) {
			    var xml = Utility.ParseXml(data);
			    if (xml && xml.documentElement && (data=[])) {
			      var f=function() {
				      try {
					      for(var i=0, e; e=this.childNodes[i++]; ) {
							    data.push({value:e.getAttribute('id'),text:e.getAttribute('name')});
						      if (e.childNodes.length )
							      arguments.callee.call(e);
					      }
				      } catch(e){}
				    }.call(xml.documentElement);  
				  }	
			  }	
			  return data;
			}()
			
		};

		switch (o.type) {		
      case 'button':
				ctrl = initButton(ctrl); break;
      case 'select':	
				ctrl = initSelect(ctrl); break;
      case 'word':
				ctrl = new MaskedInput(ctrl, /[\w\s\*\.,-]/,o); break;
      case 'email':
				ctrl = new MaskedInput(ctrl, /[\w\.;-@]/, {
						format:function(){return /^$|^(([\w.-]+@[\w.-]+\.[a-zA-Z]{2,6});?)+$/.test(this.value) ? this.value : false;}},o); 
				break;
      case 'number':
				ctrl= new MaskedInput(ctrl, /[\d\.\*-]/, {
						format:function(){return /^$|^(\*?-?[\d]*(\.?[\d]+)?\*?)$/.test(this.value) ? this.value : false;}},o); 
				break;
      case 'date':
				ctrl = new MaskedInput(ctrl, /[\d\/]/,{
						format:function(){return /^$|^([1-9]|(0[1-9]|1[0-2]))\/([1-9]|(0[1-9]|1\d|2\d|3[0-1]))\/(\d{2}$|\d{4}$)/.test(this.value) ? new Date(this.value).format("mm/dd/yyyy") : false;}},o);
				break;						
      case 'time':
				ctrl= new MaskedInput(ctrl, "##:##", {
						format:function(){return /^$|([01]?\d|2[0123])\:[012345]\d$/.test(this.value) ? this.value : false;}},o);
				break;						
      case '':
				ctrl= new MaskedInput(ctrl, mask, o);
				break;						
		}
		
		if (ctrl.obj && ctrl.combo) {
      ctrl.obj.observe("focus",(function(e){
        if (!this._combo) {
          this.obj.insert({before: this._combo = new Element('div',{className:'ocontrol-down'})});
          this._combo.setStyle({'marginLeft':String(this.obj.offsetWidth-this._combo.offsetWidth)+"px"});
          this._combo.observe('mousedown',function(e){
            Event.stop(e);
            if (Event.isLeftClick(e))
              ctrl.doShow(e); 
          });
        }  
        if (this.popup)
          this.doHide(e);      
      }).bindAsEventListener(ctrl));

      ctrl.obj.observe("blur", (function(e){
	      Event.stop(e);
	      if (this._combo) {
	        this._combo.parentNode.removeChild(this._combo);
	        this._combo=null;
	      }  
	      return false;
      }).bindAsEventListener(ctrl));

      
			Object.extend(ctrl,{
				doCreate : function() {
          try {
				    if (!this.popup) {
              if (/date|time/i.test(this.type)) {
                this.popup = self._calendar = new Element('iframe',{className:'popup','src':'client/oCalendar.htm?#'+this.type});
                self._calendar.setStyle({'border':'none','width':'200px','height':'200px'});
                this.popup._child=this.obj;
                this.popup.observe('blur',this.doHide);
                this.popup.setStyle({'marginTop':this.obj.offsetHeight+1});
                
              } else {
				        this.popup = new Element('select',{className:'popup',size:10}).setStyle({'marginTop':this.obj.offsetHeight+2, 'width':this.obj.offsetWidth});
				        this.obj.data = this.data;
                this.popup.observe('blur',this.doHide);
				        if (initSelect(this.popup,{
				            doClick : (function(e){
						            this.obj.value = e.ctrlKey &&  !this.obj.readOnly ? this.obj.value+(this.obj.value ? ",":"")+this.popup.value : this.popup.value;
						            Object.isFunction(this.obj.onchange) && this.obj.onchange.call(this.obj);
						            (!e.ctrlKey || this.obj.readOnly) && this.obj.focus();
					            }).bindAsEventListener(this)
				            })) {
				          this.popup.observe('click',this.popup.doClick);
					      }   
              }
				      this.obj.insert({before:this.popup});
				    }
				        
				  } catch(e) {return e.Show()}
				},
				doHide : (function(e){
          this.popup.stopObserving('click',this.popup.doClick);
          this.popup.stopObserving('blur',this.doHide);
          if (this.popup.parentNode) {
            this.popup.parentNode.removeChild(this.popup);
            this.popup=null;
          } 
				}).bindAsEventListener(ctrl),
				doShow : function(e) {
					this.doCreate();
					if (!/date|time/i.test(this.type)) {
						this.popup.load(this.data,['text','text']);
						this.popup.value = this.obj.value;
					}				
			    this.popup.show();
//				  this.popup.focus();
				}
			});

		}
		ctrl.status='initialized';
		return ctrl;
	} catch(e){debugger;return e.Show({id:'Control'})}
}




//===========================================================================================================\dlo/
// Initializes Fieldset container and add new methods and properties
// To get/clear all fields within container and return it's values as object or delemited string
function initForm(frm, options) {
	try {
		//don't initialize more then one time or undefined is object isn't found
		if (frm=$(frm), !frm)  
			return false; 
		else if (frm.status) 
			return frm;

		Object.extend($(frm),{
			status : 'initializing',
			initialize: function(options) {
				try {
					this.groups=this.select('fieldset');
					this.groups.each(function(grp){
						if (grp.down(0).tagName=='LEGEND' && grp.hasClassName('show|hide')) {
							Object.extend(grp, {
								Select : function(mode) {
									mode = !(typeof(mode)!='boolean' ? this.hasClassName('show') : mode);
									if (Object.isFunction(this.onSelectHandler))
										if (!this.onSelectHandler.call(this,mode))
											return;
									this.Show(mode);
								},
								Show : function(mode) {
									this.childElements().invoke(mode ? 'show':'hide');
									this.className = mode ? 'show' : 'hide';
									this.down(0).show();
								}
							});
							grp.down(0).observe('click',grp.Select.bindAsEventListener(grp));
							grp.Select(grp.hasClassName('hide'));
						}
						grp.Set=function(o) {this.parentNode.Set.call(this,o);}
						grp.Get=function(b) {return this.parentNode.Get.call(this,b);}
						grp.Invalid=function(b) {return this.parentNode.Invalid.call(this,b);}
						grp.Enable=function(mode){this.parentNode.Enable.call(this,mode);}		
					});
					Object.extend(this,options);
					var ind=1, fields=this.getElements();
					fields.each(function(fld){fld.type!='hidden' && (fld.tabIndex=ind++);});
					$(frm).focusFirstElement();
					this.status='initialized';
				} catch(e) {e.Show()}
			},
			Get : function(b) {
				try {
					var elements = this.getElementsBySelector('input','select','textarea');
					return b ? elements : Form.serializeElements(elements,true); 
				} catch(e){e.Show()}
			},
			Set : function(o) {
				try {
					this.Get(true).each(function(fld){fld.value = o && o[fld.name]!=undefined ? o[fld.name]: ''; fld.removeClassName('error')});
					this.afterUpdate.call(this);
				} catch(e){e.Show()}
			},
			Invalid : function() {
				var a=this.select('.error');
				return a.length ? a : null;
			},
			Enable : function(mode) {
				try {
					for( var i=0, e; e=this.childNodes[i++]; ) {
						//LEGEND element exists, don't disable it
						if (e.tagName!="LEGEND" ) {
							if (e.childNodes.length && !/(iframe|select)/gi.test(e.tagName))
								arguments.callee.call(e,mode,false); //recursive call
							if (e.tagName!="FIELDSET" && e.disabled != undefined) 
								e.disabled=!mode;
						}		
					}
				} catch(e){e.Show()}
			},
			Activate : function(index) {
				try {
					if (!Object.isNumber(index)) index=1;
					var a=this.getElementsBySelector('[tabindex='+index.toString()+']');
					if (a.length)
						a.first().activate();
				} catch(e){e.Show()}
			},
			afterUpdate : function(){}
			
		});
		
		frm.initialize(options);
		
		return frm;

	} catch(e){return e.Show({id:'Form'})}
}



//===========================================================================================================\dlo/
//Object to store DataGrid object data
function Data(o) {
	this.Property = {RecordCount:0,PageCount:0,PageNumber:0,PageBegin:0,PageEnd:0,PageSize:0,PageSort:''}; 
	this.Rows = null; //
		
}

//===========================================================================================================\dlo/

//Initialize the datatable
function initGrid(grid,options) {
	try {
		if (grid=$(grid), !grid || grid.status) return grid;
		Object.extend(grid,{
			status : 'initializing',
			initialize: function(options) {
				this.ShowChanged = true;
				Object.extend(this,options);
				
				this._data = new Data();
				// get a reference to "TableView" part
				this._tbl = $(this.id + "_tbl"); 
				// get a reference to "RecordView" part
				this._rec = $(this.id + "_rec");   
 				//detect View mode (0-record view, 1- details view)
 				this._viewstate = this._tbl && this._tbl.visible() ? 0 : 1;
				//creates table header (THEAD object) if it's not found
				if (this._tbl) {
					if (!this._tbl.tHead) {
						this._tbl.createTHead();
						$A(this._tbl.rows).each(function(r){
							if ($(r).select('th').length )
								this._tbl.tHead.appendChild(r.parentNode.removeChild(r));	
							else if ($(r).hasClassName('filter')) {
								this.InnerFilter = this._tbl.tHead.appendChild(r.parentNode.removeChild(r));
							}  
						},this);
					}
					
					this._tbl.insert(new Element("tbody"));
					this._tbl.insert(this._tbl.tBodies[0].cloneNode(true));
					$(this._tbl.tBodies[0]).hide();
					$(this._tbl.tBodies[2]).select('.expand').invoke('removeClassName',"expand");
					$(this._tbl.tHead).addClassName("header");
					$(this._tbl.tHead).select('a').each(function(o){
							o.onclick = this.Sort.bindAsEventListener(this);
					},this);
					
				}

				//get reference to message container
				if (this.infoBar = $(this.id + "_Info"), !this.infoBar) this.infoBar={};
				//get reference to all grid contros buttons
				this.buttons = {
					Add : (function(id, btn, options){
						if (this.buttons[id]) {
							btn=Object.extend(this.buttons[id],options)
						} else if (btn=$(btn), btn) {
							this.buttons[id] = Object.extend(btn,options)
							btn.Enabled = function(b){b=this.keepActive || b; this.setOpacity(b?1:0.5).disabled= !b}
						}
						return btn;
					}).bind(this),
					Enabled : function(b,elements){
						if (elements) {
							String(elements).split(',').each(function(o){
								this[o] && this[o].Enabled && (this[o].Enabled(b));
						},this);
						}	else {
							for(var o in this)
								this[o].Enabled && (this[o].Enabled(b));
						}		
					}
							
				};
				this.buttons.Add('First',this.id + "_btnFirst",{onclick:this.Navigate.bind(this,0)});
				this.buttons.Add('Prev',this.id + "_btnPrev",{onclick:this.Navigate.bind(this,-1)});
				this.buttons.Add('Next',this.id + "_btnNext",{onclick:this.Navigate.bind(this,1)});
				this.buttons.Add('Last',this.id + "_btnLast",{onclick:this.Navigate.bind(this,-2)});
				this.buttons.Add('View',this.id + "_btnView",{keepActive:true,onclick:this.ChangeView.bindAsEventListener(this)});
				this.buttons.Add('Filter',this.id + "_btnFilter",{onclick:this.SetFilter.bindAsEventListener(this)});
				this.buttons.Add('Clear',this.id + "_btnClear",{keepActive:true, onclick:this.SetFilter.bindAsEventListener(this,false)});
				if (this.buttons.Add('Page',this.id + "_Page")) {
					initControl(this.buttons.Page,null,/[0123456789]/);
					this.buttons.Page.observe("keydown",function(e){
						var p=Event.element(e), n=parseInt(p.value) || this._data.Property.PageNumber;
						
						if (e.keyCode==Event.KEY_UP)
							p.value = Math.min(n+1, this._data.Property.PageCount);
						else if (e.keyCode==Event.KEY_DOWN)
							p.value = Math.max(n-1, 1);
						else if (e.keyCode==Event.KEY_RETURN)	{
							this.Navigate.call(this,p.value);
							Event.stop(e);
						}
					}.bindAsEventListener(this))
					this.buttons.Page.observe("blur",function(e){Event.element(e).value=this._data.Property.PageNumber}.bindAsEventListener(this));
				}
				this.buttons.Add('Toggle',this.id + "_Toggle",{onclick:this.ToggleAll.bindAsEventListener(this,false)});
				this.buttons.Add('ViewAll',this.id + "_ViewAll");
				
				this.__updategrid();
				this.status='initialized';

			},
			Enable: function(b) {
				this.status=b?"complete":"disabled";
				if (!this.__cover) {
					this.insert(this.__cover = new Element("div",{className:'disabled'}).setStyle({position:'absolute',display:'none',opacity:0.5}));
					this.__cover.onclick = function(e){Event.stop(e);return false;}.bindAsEventListener();
				} else
					this.__cover.hide();
				if (!b) 
					this.__cover.clonePosition(this).show();
			},
			ToggleAll : function(e) {
				try {
					e=Event.element(e);
					if (!/input/i.test(e.tagName)) e.checked ^= 1;
					$(this._tbl).select('input[type=checkbox]').each(function(el){el.checked = e.checked;});
				}	catch(er) {er.Show()}
			},
			GetRecords : function(host, status) {
				try {
					host = !host ? this._viewstate ? this._rec:this._tbl : $(host);
					return host.select('input[type=checkbox]').inject([],function(elements,el){
						var b=el.checked;
						while (!/tr|li/i.test(el.tagName))  
							el = el.parentNode;
						var o = this.__bind({}, el);
						o.check=b;
						if (!status || (status && b))
							elements.push(o);
						return elements;
					},this);
				}	catch(er) {er.Show()}
			},
			
			
			ChangeView: function(e){
				try {
					Event.stop(e);
					if (this.status!='complete') return false;
					
					this._viewstate ^= 1;
					Event.element(e).update(this._viewstate ? "Table" : "Record");
					if (this._data.Property.RecordCount)
						this.Request({PageSize:this._data.Property.PageSize*-1});
					else
						this.__updategrid();	
				}	catch(e){e.Show()}
			},
			Navigate: function(page){
				try {	
					if (this.status!='complete') return false;
					if (Object.isString(page))
						page = parseInt(page);
					else
						page = Math.abs(page)==1 ? page+this._data.Property.PageNumber: page;
					this.Request({PageNumber : page });
				} catch(e){e.Show()}	
			},
			Sort: function(e){
				try {
					var el=Event.element(e).up(0);
					Event.stop(e);
					if (this.status!='complete') return false;
					
					//check sort attribute for current element
					if (!this._data.Property.RecordCount || !/_sort_/gi.test(el.id)) return;
					//calculate a new sort field and sort order
					var sf = el.id.replace(/^.*_sort_/,'');
					var so = ((so = String(this._data.Property.PageSort)),  (so.replace(/\^.*/,'')==sf ^ /\^/.test(so)) ? '^' : '');
					this.Request({PageSort : sf+so});
				} catch(e){e.Show()}	
			},
			selectData: function(e){
				try {
					if (this.status!='complete') return false;

					var active=el=Event.element(e);
					//gets data from the selected row/column
					//selected cell MUST have a first child with NAME attribute 
					if (!this._data.Property.RecordCount) return null;
							
					//find parent ROW element for the selected cell
					if (!this._viewstate) {
						while (el.tagName != "TR" )  
							el = el.parentNode;

						if (el.parentNode.tagName!="TBODY")
							return false;
						
						//assign a new selected element (row)
					} else {
						el = this._rec.tBodies[0];
					}
						if (!this.SelectElement(el,active))
							return;
					
					//create a new object  by selected grid element
					var data=this.__bind({}, el);

					if (data && Object.isFunction(this.selectHandler)) {
						Event.stop(e);
						return this.selectHandler.call(this,e,data,active);
                        
					}	

					return true;	
						
				} catch(e){e.Show()}	
			},
			SelectElement: function(el,active){
				try {
					var b;
					if (this.SelectedElement) {
						//if it has a child and the child has CLOSE method - run it
						if (this.SelectedElement._child) {
							b=this.SelectedElement._child._caller == active;
							Object.isFunction(this.SelectedElement._child.close) && (this.SelectedElement._child.close.apply(this.SelectedElement));
							if (b)
								return false;
						}	
						////changes the class name for the selected element
						this.SelectedElement.removeClassName('selected');
						if (this.ShowChanged)
							this.SelectedElement.addClassName('changed');
						//dispose 
						this.SelectedElement=null;
					}	

					if (this.SelectedElement=el, this.SelectedElement)
						$(this.SelectedElement).addClassName(this._viewstate?'':'selected');
					return true;	
				} catch(e){e.Show()}	
			},


			//clears data and update all parts of dataGrid
			Clear: function(b) {
				try {
					this.Filter=null;
					this.Fill();
					this.__updategrid();	
					this.status='complete';					
				} catch(e){e.Show()}	
			},

			SetFilter: function(e,o) {
				try {
					Event.stop(e);
					if (this.status!='complete') return false;
					
					if (this.InnerFilter) {
						var b=this.InnerFilter.visible();
            if (!b) {
              [this.InnerFilter, this.buttons.Clear].invoke('show');						  
						  this.InnerFilter.select('select|input').first().focus();  
						  return;
						} else if (o===false) {
							[this.InnerFilter, this.buttons.Clear].invoke('hide');
              this.Filter = this.__bind(this.InnerFilter, null);
            } else {
						  if (this.InnerFilter.select('.error').length)
							  throw new Error('Some of the filter values are invalid!');
							this.Filter = this.__bind({}, this.InnerFilter);  
            }
					  this.Request();
					}
				} catch(e){e.Show()}	
			},

			Request: function() {
				try {
					if (/(updating)/i.test(this.status)) return false;

					this.status='updating';

					//request data 
					//checks internal request parameters. Must be an object

					var prms = {
							Filter: this.Filter,
							PageNumber: this._data.Property.PageNumber,
							PageSort:this._data.Property.PageSort,
							PageSize:this._viewstate
						};
					$A(arguments).each(function(a){Object.extend(prms,a)});

					
					this.Enable(false);
					this.buttons.Enabled(false);
					if (Object.isFunction(this.requestDataHandler)) {
						this.requestDataHandler.call(this,prms);
					}
				} catch(e){e.Show()}	
			},
			Fill: function(o) {
				//fill dataGrid with data(object)
				try {
					var part;
					this.status='updating';
					//checks and creates the data object structure. Data MUST have 'Rows' property as Array 'Property' as object
					if (o && Object.isArray(o.Rows) && o.Property) {
						//clear grid by calling function itself without arguments
						this.Fill();

						Object.extend(this._data,o)

						if (this._viewstate) { 
							this.__populate(this._rec,this._data.Rows);
							this.__activate(this._rec,true);
						} else {
							this.__populate(this._tbl.tBodies[1],this._data.Rows,$(this._tbl.tBodies[0].rows[0]));
							if (this._data.Property.RecordCount>0)
								$(this._tbl.tBodies[2]).hide();
							this.__activate(this._tbl.tBodies[1],true);
						}	
							
						//updates grid information 
						this.__updategrid();	
						this.status='complete';
					}	else {
						
						//delete selected element
						this.SelectElement();
					
						//create a new data object, and keep filter info if exists
						this._data = new Data();
						//Clears all parts of the grid
						if (this._tbl) {
						    this.__activate(this._tbl.tBodies[1]);
						    $A(this._tbl.tBodies[1].rows).each(function(el){
							    el.parentNode.removeChild(el);
						    });
						    $(this._tbl.tBodies[2]).show();
						}    

						this.__activate(this._rec);
						this.__bind(this._rec ,null);
					}
				} catch(e){e.Show()}
			},

			ShowDetails: function(caller,f) {
				//show child element for the selected row.
				try	{
					//selected element and both parameters must be non empty objects
					var host = this._viewstate ? caller.up(1) : this.SelectedElement;
					//creates child element as a clone of the selected row and insert it after the selected row 
					
						this.SelectedElement._child =	host.cloneNode(false).insert(new Element('td',{className:'internal',colSpan:host.cells.length}).update('Loading...'));
						host.insert({after:this.SelectedElement._child});
					//creates internal structure
					if ($(caller).hasClassName('expand'))
						$(caller).removeClassName('expand').addClassName('collapse')
					this.SelectedElement._child._caller = caller;
					//assign a close method	
					this.SelectedElement._child.close = function(){
					if (this._child._caller.hasClassName('collapse'))
						this._child._caller.removeClassName('collapse').addClassName('expand'); 
					this._child.parentNode.removeChild(this._child); this._child=null;}

					var innerElement = this.SelectedElement._child.down(0);
					if (Object.isFunction(f)) 
						f.apply(this,[innerElement].concat($A(arguments).reject(function(a,i){return i<2})));
					else
						innerElement.update(f);	
					return innerElement;
				} catch(e){e.Show()}	
			},

			__activate: function(el,b){
				try {
					if (el=$(el), !el) return false;;
					el.select('a.active').each(function(o){
						try {
							o.onclick = b ? this.selectData.bindAsEventListener(this) : null;
						} catch(err) {err.Show()}
							
					},this);
				} catch(e){e.Show()}	
			},

			__updategrid: function() {
				try {
					//updates data information and navigation buttons
					var msg, property = {};
					//show current data information
					if (this._data && this._data.Property && Object.isArray(this._data.Rows)) {
						property=this._data.Property;

						var recordName = property.name || 'record';
						if ( property.RecordCount == 0 ) 
							msg = 'No ' + recordName + 's found.';
						else if (property.RecordCount == 1)  
							msg = '1 ' + recordName + ' returned.';
						else { 
							msg = String(property.RecordCount) + ' ' + recordName + 's returned,<br/>'
							if (!this._viewstate)
								msg += String(property.PageBegin+1) + ' to ' + String(property.PageEnd+1) + ' ' + recordName+ ' shown';
							else
								msg += String(property.PageBegin+1) + ' ' + recordName + ' shown';
						}
					}
					if (Object.isElement(this.infoBar)) 
						this.infoBar.update(msg || '&nbsp;');
					
					//change the status of the navigation and additional buttons
					this.buttons.Enabled(property.RecordCount > 0);
					this.buttons.Enabled(true,"View");
					this.buttons.Enabled(!this._viewstate,"Filter");
					this.buttons.Enabled(property.PageNumber > 1,"First,Prev");
					this.buttons.Enabled(property.RecordCount > 0 && property.PageNumber < property.PageCount,"Next,Last");
					if (this.buttons.Page) {
						this.buttons.Page.value = property.PageNumber || '';
					}

					//delete current sort odrer element if exists
					if (this._sortElement) {
						this._sortElement.removeChild(this._sortElement.firstChild);
						this._sortElement = null;
					}		
					//to create the sort order element if GRID state is PAGEVIEW and sort column name is set
					if (!this._viewstate && property.PageSort ) {
					//Display a sort order indicator using sort order value and element ID
						if (this._sortElement = $(this.id+"_sort_"+property.PageSort.replace(/\^.*/,'')), this._sortElement) {
							this._sortElement.insert({top:new Element("div",{className:/\^/.test(property.PageSort) ? 'asc':'desc'})});
						}	
					}
					this.Enable(true);
					//changes the GRID's parts state
					if (Object.isElement(this._tbl))
						!this._viewstate ? this._tbl.show() : this._tbl.hide();
					if (Object.isElement(this._rec))	
						this._viewstate ? this._rec.show() : this._rec.hide();

					//Run external update function if it's assigned
					this.fire("grid::updated",property);
				}catch(e){e.Show()}		
			},
			__bind: function(t,d) {
				//Update range of named children elements. 
				//there are two options: 
				//first: (parameters: 1-html, 2-object) fills innerHTML property of the named HTML element with object property, 
				//second: (parameters: 1-object,2-html) changes an object property based on name property of the HTML element 
				if (!d && !t)
					return false;
				var o, name;			
				//swap objects
				if (d && d.tagName) {o=d, d=t, t=o;}
					
				//gets all chidren
				var all=t.childNodes;
				for( var i=0, e; e=all[i++];) try {
					if (name=e.getAttribute('name'), name) //if HTML object has a NAME attribute
						//if object is't empty copy its value to then the HTML objec body	
						if (!o) 
							if (/(input|select)/i.test(e.tagName))
								e.value = d && !d[name] ? d[name].toString():'';
							else 
								e.innerHTML = d && d[name]!=undefined ? d[name].toString():'';
								
						//otherwise append HTML object body as a new object's property
						else {
							d[name]= e.value!=undefined ? e.value : e.innerHTML.stripTags();
						}
					if (e.childNodes.length) //recursive call	for all children	
						arguments.callee.apply(e,!o?[e,d]:[d,e])
				} catch(er){}	
						
				return !o ? t : d;
			},

			__populate: function(el, data, node) {
					//binds data array to the table
					el=$(el);
					if (!el || !Object.isArray(data))
						return false;
					for(var i=0,o; o=data[i++];) {
						if (Object.isFunction(this.drawDataHandler)) 
							o = this.drawDataHandler.call(this,o);
						if (Object.isElement(node))	
							el.appendChild(e = node.cloneNode(true));
						else							
							e=el;
						this.__bind(e,o,node ? this.__bindHandlers: null);
					}
			}

		});
		grid.initialize(options);
		
		return grid;
	} catch(e){e.Show({id:'Grid'})}

}


//===========================================================================================================
// Add edit functionality to the table or the Row
//===========================================================================================================\dlo/
var EditGrid = Class.create();
Object.extend(EditGrid.prototype, {
  initialize: function(o) {
		try {
      if (this.grid = $(o), !this.grid || !this.grid.hasClassName('edit')) return;
      this.allowAdd = this.allowRemove = this.grid.tagName =='TABLE';
      this.grid.onclick = (function(e){this.Select.call(this,Event.element(e));}).bindAsEventListener(this);
      for (var i=1,arg; arg=arguments[i++];)
				Object.extend(this,arg);
		}	catch(e){e.Show()}			
  },
	CreateField : function(e) {
		try {
			return e.update(new Element("input",{value:e.innerHTML.unescapeHTML().strip()})).down(0);
		}	catch(e){e.Show()}			
	},
	doLeave : function (e) {
		try {
			if (this.hasClassName('error')) return false;
			this.up(0).update(this.value.strip());
		}	catch(e){e.Show()}			
	},
	doKeyDown : function(e) {
		try {
			var _cell;
			if (e.shiftKey && e.keyCode==9) { //shift+tab
				_cell = this._prev;
			} else if (e.keyCode==9 || ((e.ctrlKey || this.autoTab) && e.keyCode==13 ))	{//tab or enter
				_cell = this._next ? this._next : this.addRow.call(this);
			}	else if (e.keyCode==13 ) { //enter
				this.inp.blur();
				return true;
			} else if (e.ctrlKey && e.keyCode==46) { // ctrl+delete
				this.removeRow.call(this,this.inp.up(1));
			}	
			if (_cell)
				this.Select.call(this,_cell),	Event.stop(e);	
		}	catch(e){e.Show()}			
	},
	Select : function(e) {
		try {
			if (e=$(e), e.tagName!="TD") return false;
			if (this.inp=this.CreateField(e), !this.inp) //create a new input field 
				return false;	
			this.inp.setStyle({border:'none 0px',width:'100%',height:'100%'});
			this._prev = this._next = e;
			//get its siblings
			do {
				if (this._prev = this._prev.previous(0), !this._prev)
					this._prev = (e.up(0).previous(0) && e.up(0).previous(0).childElements().last().tagName=='TD') ? e.up(0).previous(0).childElements().last() : e.up(0).childElements().last();
			} while (!this._prev || !this._prev.visible());
			do {
				if (this._next = this._next.next(0), !this._next)
					this._next = (e.up(0).next(0) && e.up(0).next(0).down(0).tagName=='TD') ? e.up(0).next(0).down(0) : e.up(0).down(0);
			} while (!this._next || !this._next.visible());

			this.inp.onblur = this.doLeave.bindAsEventListener(this.inp);
			this.inp.onkeydown = this.doKeyDown.bindAsEventListener(this);
			this.inp.activate(); //activate input element
		}	catch(err) {return false}			
	},
	//add a new row to the table
	addRow : function() {
		try {
			if (!this.allowAdd) return null;
			var r = $(this.grid.insertRow());
			r.previous().childElements().each(function(c){
				$(r.insertCell()).update('&nbsp;')
			});
			return r.cells[0];
		}	catch(e){e.Show()}			
	},
	//remove method to delete entire row from the table
	removeRow : function(r) {
		try {
			if (!this.allowRemove) return null;
			var s = {backgroundColor : r.getStyle('backgroundColor'), color: r.getStyle('color')};
			r.setStyle({backgroundColor:'window',color:'red'});
			if (window.confirm("Delete entire row?"))
				this.deleteRow(r.rowIndex);
			else 
				r.setStyle(s);
		}	catch(e){e.Show(false)}
	},
	//get whole table value as a text 
	//where CR - line separator, TAB - cell separator
	GetValue : function() {
		try {
			var v = [];
			for(var i=0, r; r=this.rows[i++];) {
				var d=[];
				for(var j=0, c; c= r.cells[j++];) 
					if (c.tagName=="TD") d.push(c.innerText);
				if (d.length) v.push(d.join('\t'));	
			}
			return v.join('\n');
		}	catch(e){e.Show(false)}
	}

});





//===========================================================================================================\dlo/
//Open a new document in a new window  using POST method
//parameters: winsetting - object to assign a parameters for new WINDOW
//						others - to send them to a new window as 

function initWindow(options) {
	try	{
		this.initpage="default.htm";
		this.autoopen=true;
		this.autoclose=true;
		this.width=0;
		this.height=0;
		this.top=0;
		this.left=0;
		this.args=$A(arguments).reject(function(a,i){return i<1});
		
		//assign a new window and form parameters 
		Object.extend(this,options);

		//URL property must be non empty
		if (!this.url) return false;
		
		//detects and reassign a new window coordinates
		this.width = (this.max ? screen.availWidth : (!this.width ? screen.availWidth/2 : this.width));
		this.height = (this.max ? screen.availHeight : (!this.height ? screen.availHeight/2 : this.height));
		
		if (this.center) 
			this.left = (screen.availWidth-parseInt('0'+this.width,10))/2,	this.top = (screen.availHeight-parseInt('0'+this.height,10))/2;

		this.Options = function(){
				var a=[];
				a.push("left="+this.left.toString());
				a.push("top="+this.top.toString());
				a.push("width="+this.width.toString());
				a.push("height="+this.height.toString());
				a.push("resizable="+(this.resizable?"1":"0"));
				a.push("menubar="+(this.menubar?"1":"0"));
				a.push("location="+(this.location?"1":"0"));
				a.push("toolbar="+(this.toolbar?"1":"0"));
				return a.join(",");
		}
		
		this.Open = function(){
			try {
				if (!this.id) this.id=Utility.Guid();

				//open default document in a new window
				this.win = window.open(this.args ? this.initpage: this.url,this.id,this.Options(),true);
				//display Progress information
				if (this.progress && this.args ) {
					try {
						this.win.document.body.innerHTML = "<div style='position:absolute;width:100%;top:48%;text-align:center;'>"+this.progress+"</div>";
						this.win.document.body.style.cursor = "wait";
					} catch(x){};	

				}
				//if parameters exist create a new form and its fields and send form to the server
				if (this.args) {
					var frm=new Element('form',{action:this.url, target:this.id, method:'POST'});
					$(document.body).insert(frm);
					$A(this.prms).each(function(prm){
						for(var key in prm)
							frm.insert(new Element('INPUT',{type:'hidden',name:key,value:prm[key]}));
					});
					frm.submit();
					frm.parentNode.removeChild(frm);
				}

				if (this.max)
					this.win.resizeTo(this.width,this.height);

				//define an AutoClose method when a new window losing focus
				this.setAutoClose(this);

				return true;
			}	catch(e){e.Show(false)}	
		}
		
		this.Close = function() {
			try {if (this.win) {this.win.close();this.win = null;}} catch(e){};			
			Event.stopObserving(window,'focus',this.Close);			
		}
		
		this.setAutoClose = function() {
			if (!this.autoclose) return;
			this.win.focus();
			this.Close = this.Close.bindAsEventListener(this);
			Event.observe(window,'focus',this.Close);
		}
		
		//do "AutoOpen"
		if (this.autoopen) this.Open();
		
	}	catch(e){e.Show({id:'Window'})}
}




//Common function: Shows part of help in a new window using part ID
function Help(id) {
	new initWindow({url:'help.aspx?'+id, center:true,resizable:true,progress:'Please wait'},{tt:1});						
}

