summaryrefslogtreecommitdiff
path: root/framework/Web
diff options
context:
space:
mode:
authorwei <>2005-12-13 01:42:19 +0000
committerwei <>2005-12-13 01:42:19 +0000
commit66e71b1d5ff97e04311f8b761cc040b1188437d3 (patch)
treea810745466c1ea5b8cb932bb6ff0415f1958c9b0 /framework/Web
parent9a2764c1ad41d4c187a55849029416abda697183 (diff)
Adding client side javascript validators.
Diffstat (limited to 'framework/Web')
-rw-r--r--framework/Web/Javascripts/js/dom.js1365
-rw-r--r--framework/Web/Javascripts/js/validator.js536
-rw-r--r--framework/Web/UI/TClientScriptManager.php1092
-rw-r--r--framework/Web/UI/WebControls/TBaseValidator.php654
4 files changed, 2890 insertions, 757 deletions
diff --git a/framework/Web/Javascripts/js/dom.js b/framework/Web/Javascripts/js/dom.js
new file mode 100644
index 00000000..a0f4a3f3
--- /dev/null
+++ b/framework/Web/Javascripts/js/dom.js
@@ -0,0 +1,1365 @@
+document.getElementsByClassName=function(_1,_2){
+var _3=($(_2)||document.body).getElementsByTagName("*");
+return $A(_3).inject([],function(_4,_5){
+if(Element.hasClassName(_5,_1)){
+_4.push(_5);
+}
+return _4;
+});
+};
+if(!window.Element){
+var Element=new Object();
+}
+Object.extend(Element,{visible:function(_6){
+return $(_6).style.display!="none";
+},toggle:function(){
+for(var i=0;i<arguments.length;i++){
+var _8=$(arguments[i]);
+Element[Element.visible(_8)?"hide":"show"](_8);
+}
+},hide:function(){
+for(var i=0;i<arguments.length;i++){
+var _9=$(arguments[i]);
+_9.style.display="none";
+}
+},show:function(){
+for(var i=0;i<arguments.length;i++){
+var _10=$(arguments[i]);
+_10.style.display="";
+}
+},remove:function(_11){
+_11=$(_11);
+_11.parentNode.removeChild(_11);
+},getHeight:function(_12){
+_12=$(_12);
+return _12.offsetHeight;
+},classNames:function(_13){
+return new Element.ClassNames(_13);
+},hasClassName:function(_14,_15){
+if(!(_14=$(_14))){
+return;
+}
+return Element.classNames(_14).include(_15);
+},addClassName:function(_16,_17){
+if(!(_16=$(_16))){
+return;
+}
+return Element.classNames(_16).add(_17);
+},removeClassName:function(_18,_19){
+if(!(_18=$(_18))){
+return;
+}
+return Element.classNames(_18).remove(_19);
+},cleanWhitespace:function(_20){
+if(undef(_20)||isNull(_20)){
+return;
+}
+_20=$(_20);
+for(var i=0;i<_20.childNodes.length;i++){
+var _21=_20.childNodes[i];
+if(_21.nodeType==3&&!/\S/.test(_21.nodeValue)){
+_21.parentNode.removeChild(_21);
+}
+}
+},empty:function(_22){
+return $(_22).innerHTML.match(/^\s*$/);
+},scrollTo:function(_23){
+_23=$(_23);
+var x=_23.x?_23.x:_23.offsetLeft,y=_23.y?_23.y:_23.offsetTop;
+window.scrollTo(x,y);
+},getStyle:function(_25,_26){
+_25=$(_25);
+var _27=_25.style[_26.camelize()];
+if(!_27){
+if(document.defaultView&&document.defaultView.getComputedStyle){
+var css=document.defaultView.getComputedStyle(_25,null);
+_27=css?css.getPropertyValue(_26):null;
+}else{
+if(_25.currentStyle){
+_27=_25.currentStyle[_26.camelize()];
+}
+}
+}
+if(window.opera&&["left","top","right","bottom"].include(_26)){
+if(Element.getStyle(_25,"position")=="static"){
+_27="auto";
+}
+}
+return _27=="auto"?null:_27;
+},getDimensions:function(_29){
+_29=$(_29);
+if(Element.getStyle(_29,"display")!="none"){
+return {width:_29.offsetWidth,height:_29.offsetHeight};
+}
+var els=_29.style;
+var _31=els.visibility;
+var _32=els.position;
+els.visibility="hidden";
+els.position="absolute";
+els.display="";
+var _33=_29.clientWidth;
+var _34=_29.clientHeight;
+els.display="none";
+els.position=_32;
+els.visibility=_31;
+return {width:_33,height:_34};
+},makePositioned:function(_35){
+_35=$(_35);
+var pos=Element.getStyle(_35,"position");
+if(pos=="static"||!pos){
+_35._madePositioned=true;
+_35.style.position="relative";
+if(window.opera){
+_35.style.top=0;
+_35.style.left=0;
+}
+}
+},undoPositioned:function(_37){
+_37=$(_37);
+if(_37._madePositioned){
+_37._madePositioned=undefined;
+_37.style.position=_37.style.top=_37.style.left=_37.style.bottom=_37.style.right="";
+}
+},makeClipping:function(_38){
+_38=$(_38);
+if(_38._overflow){
+return;
+}
+_38._overflow=_38.style.overflow;
+if((Element.getStyle(_38,"overflow")||"visible")!="hidden"){
+_38.style.overflow="hidden";
+}
+},undoClipping:function(_39){
+_39=$(_39);
+if(_39._overflow){
+return;
+}
+_39.style.overflow=_39._overflow;
+_39._overflow=undefined;
+}});
+var Toggle=new Object();
+Toggle.display=Element.toggle;
+Abstract.Insertion=function(_40){
+this.adjacency=_40;
+};
+Abstract.Insertion.prototype={initialize:function(_41,_42){
+this.element=$(_41);
+this.content=_42;
+if(this.adjacency&&this.element.insertAdjacentHTML){
+try{
+this.element.insertAdjacentHTML(this.adjacency,this.content);
+}
+catch(e){
+if(this.element.tagName.toLowerCase()=="tbody"){
+this.insertContent(this.contentFromAnonymousTable());
+}else{
+throw e;
+}
+}
+}else{
+this.range=this.element.ownerDocument.createRange();
+if(this.initializeRange){
+this.initializeRange();
+}
+this.insertContent([this.range.createContextualFragment(this.content)]);
+}
+},contentFromAnonymousTable:function(){
+var div=document.createElement("div");
+div.innerHTML="<table><tbody>"+this.content+"</tbody></table>";
+return $A(div.childNodes[0].childNodes[0].childNodes);
+}};
+var Insertion=new Object();
+Insertion.Before=Class.create();
+Insertion.Before.prototype=Object.extend(new Abstract.Insertion("beforeBegin"),{initializeRange:function(){
+this.range.setStartBefore(this.element);
+},insertContent:function(_44){
+_44.each((function(_45){
+this.element.parentNode.insertBefore(_45,this.element);
+}).bind(this));
+}});
+Insertion.Top=Class.create();
+Insertion.Top.prototype=Object.extend(new Abstract.Insertion("afterBegin"),{initializeRange:function(){
+this.range.selectNodeContents(this.element);
+this.range.collapse(true);
+},insertContent:function(_46){
+_46.reverse().each((function(_47){
+this.element.insertBefore(_47,this.element.firstChild);
+}).bind(this));
+}});
+Insertion.Bottom=Class.create();
+Insertion.Bottom.prototype=Object.extend(new Abstract.Insertion("beforeEnd"),{initializeRange:function(){
+this.range.selectNodeContents(this.element);
+this.range.collapse(this.element);
+},insertContent:function(_48){
+_48.each((function(_49){
+this.element.appendChild(_49);
+}).bind(this));
+}});
+Insertion.After=Class.create();
+Insertion.After.prototype=Object.extend(new Abstract.Insertion("afterEnd"),{initializeRange:function(){
+this.range.setStartAfter(this.element);
+},insertContent:function(_50){
+_50.each((function(_51){
+this.element.parentNode.insertBefore(_51,this.element.nextSibling);
+}).bind(this));
+}});
+Element.ClassNames=Class.create();
+Element.ClassNames.prototype={initialize:function(_52){
+this.element=$(_52);
+},_each:function(_53){
+this.element.className.split(/\s+/).select(function(_54){
+return _54.length>0;
+})._each(_53);
+},set:function(_55){
+this.element.className=_55;
+},add:function(_56){
+if(this.include(_56)){
+return;
+}
+this.set(this.toArray().concat(_56).join(" "));
+},remove:function(_57){
+if(!this.include(_57)){
+return;
+}
+this.set(this.select(function(_58){
+return _58!=_57;
+}));
+},toString:function(){
+return this.toArray().join(" ");
+}};
+Object.extend(Element.ClassNames.prototype,Enumerable);
+
+Object.extend(Element,{condClassName:function(_1,_2,_3){
+(_3?Element.addClassName:Element.removeClassName)(_1,_2);
+}});
+
+var Field={clear:function(){
+for(var i=0;i<arguments.length;i++){
+$(arguments[i]).value="";
+}
+},focus:function(_2){
+$(_2).focus();
+},present:function(){
+for(var i=0;i<arguments.length;i++){
+if($(arguments[i]).value==""){
+return false;
+}
+}
+return true;
+},select:function(_3){
+$(_3).select();
+},activate:function(_4){
+$(_4).focus();
+$(_4).select();
+}};
+var Form={serialize:function(_5){
+var _6=Form.getElements($(_5));
+var _7=new Array();
+for(var i=0;i<_6.length;i++){
+var _8=Form.Element.serialize(_6[i]);
+if(_8){
+_7.push(_8);
+}
+}
+return _7.join("&");
+},getElements:function(_9){
+var _9=$(_9);
+var _10=new Array();
+for(tagName in Form.Element.Serializers){
+var _11=_9.getElementsByTagName(tagName);
+for(var j=0;j<_11.length;j++){
+_10.push(_11[j]);
+}
+}
+return _10;
+},getInputs:function(_13,_14,_15){
+var _13=$(_13);
+var _16=_13.getElementsByTagName("input");
+if(!_14&&!_15){
+return _16;
+}
+var _17=new Array();
+for(var i=0;i<_16.length;i++){
+var _18=_16[i];
+if((_14&&_18.type!=_14)||(_15&&_18.name!=_15)){
+continue;
+}
+_17.push(_18);
+}
+return _17;
+},disable:function(_19){
+var _20=Form.getElements(_19);
+for(var i=0;i<_20.length;i++){
+var _21=_20[i];
+_21.blur();
+_21.disabled="true";
+}
+},enable:function(_22){
+var _23=Form.getElements(_22);
+for(var i=0;i<_23.length;i++){
+var _24=_23[i];
+_24.disabled="";
+}
+},focusFirstElement:function(_25){
+var _25=$(_25);
+var _26=Form.getElements(_25);
+for(var i=0;i<_26.length;i++){
+var _27=_26[i];
+if(_27.type!="hidden"&&!_27.disabled){
+Field.activate(_27);
+break;
+}
+}
+},reset:function(_28){
+$(_28).reset();
+}};
+Form.Element={serialize:function(_29){
+var _29=$(_29);
+var _30=_29.tagName.toLowerCase();
+var _31=Form.Element.Serializers[_30](_29);
+if(_31){
+return encodeURIComponent(_31[0])+"="+encodeURIComponent(_31[1]);
+}
+},getValue:function(_32){
+var _32=$(_32);
+var _33=_32.tagName.toLowerCase();
+var _34=Form.Element.Serializers[_33](_32);
+if(_34){
+return _34[1];
+}
+}};
+Form.Element.Serializers={input:function(_35){
+switch(_35.type.toLowerCase()){
+case "submit":
+case "hidden":
+case "password":
+case "text":
+return Form.Element.Serializers.textarea(_35);
+case "checkbox":
+case "radio":
+return Form.Element.Serializers.inputSelector(_35);
+}
+return false;
+},inputSelector:function(_36){
+if(_36.checked){
+return [_36.name,_36.value];
+}
+},textarea:function(_37){
+return [_37.name,_37.value];
+},select:function(_38){
+return Form.Element.Serializers[_38.type=="select-one"?"selectOne":"selectMany"](_38);
+},selectOne:function(_39){
+var _40="",opt,index=_39.selectedIndex;
+if(index>=0){
+opt=_39.options[index];
+_40=opt.value;
+if(!_40&&!("value" in opt)){
+_40=opt.text;
+}
+}
+return [_39.name,_40];
+},selectMany:function(_41){
+var _42=new Array();
+for(var i=0;i<_41.length;i++){
+var opt=_41.options[i];
+if(opt.selected){
+var _44=opt.value;
+if(!_44&&!("value" in opt)){
+_44=opt.text;
+}
+_42.push(_44);
+}
+}
+return [_41.name,_42];
+}};
+var $F=Form.Element.getValue;
+Abstract.TimedObserver=function(){
+};
+Abstract.TimedObserver.prototype={initialize:function(_45,_46,_47){
+this.frequency=_46;
+this.element=$(_45);
+this.callback=_47;
+this.lastValue=this.getValue();
+this.registerCallback();
+},registerCallback:function(){
+setInterval(this.onTimerEvent.bind(this),this.frequency*1000);
+},onTimerEvent:function(){
+var _48=this.getValue();
+if(this.lastValue!=_48){
+this.callback(this.element,_48);
+this.lastValue=_48;
+}
+}};
+Form.Element.Observer=Class.create();
+Form.Element.Observer.prototype=Object.extend(new Abstract.TimedObserver(),{getValue:function(){
+return Form.Element.getValue(this.element);
+}});
+Form.Observer=Class.create();
+Form.Observer.prototype=Object.extend(new Abstract.TimedObserver(),{getValue:function(){
+return Form.serialize(this.element);
+}});
+Abstract.EventObserver=function(){
+};
+Abstract.EventObserver.prototype={initialize:function(_49,_50){
+this.element=$(_49);
+this.callback=_50;
+this.lastValue=this.getValue();
+if(this.element.tagName.toLowerCase()=="form"){
+this.registerFormCallbacks();
+}else{
+this.registerCallback(this.element);
+}
+},onElementEvent:function(){
+var _51=this.getValue();
+if(this.lastValue!=_51){
+this.callback(this.element,_51);
+this.lastValue=_51;
+}
+},registerFormCallbacks:function(){
+var _52=Form.getElements(this.element);
+for(var i=0;i<_52.length;i++){
+this.registerCallback(_52[i]);
+}
+},registerCallback:function(_53){
+if(_53.type){
+switch(_53.type.toLowerCase()){
+case "checkbox":
+case "radio":
+_53.target=this;
+_53.prev_onclick=_53.onclick||Prototype.emptyFunction;
+_53.onclick=function(){
+this.prev_onclick();
+this.target.onElementEvent();
+};
+break;
+case "password":
+case "text":
+case "textarea":
+case "select-one":
+case "select-multiple":
+_53.target=this;
+_53.prev_onchange=_53.onchange||Prototype.emptyFunction;
+_53.onchange=function(){
+this.prev_onchange();
+this.target.onElementEvent();
+};
+break;
+}
+}
+}};
+Form.Element.EventObserver=Class.create();
+Form.Element.EventObserver.prototype=Object.extend(new Abstract.EventObserver(),{getValue:function(){
+return Form.Element.getValue(this.element);
+}});
+Form.EventObserver=Class.create();
+Form.EventObserver.prototype=Object.extend(new Abstract.EventObserver(),{getValue:function(){
+return Form.serialize(this.element);
+}});
+
+if(!window.Event){
+var Event=new Object();
+}
+Object.extend(Event,{KEY_BACKSPACE:8,KEY_TAB:9,KEY_RETURN:13,KEY_ESC:27,KEY_LEFT:37,KEY_UP:38,KEY_RIGHT:39,KEY_DOWN:40,KEY_DELETE:46,element:function(_1){
+return _1.target||_1.srcElement;
+},isLeftClick:function(_2){
+return (((_2.which)&&(_2.which==1))||((_2.button)&&(_2.button==1)));
+},pointerX:function(_3){
+return _3.pageX||(_3.clientX+(document.documentElement.scrollLeft||document.body.scrollLeft));
+},pointerY:function(_4){
+return _4.pageY||(_4.clientY+(document.documentElement.scrollTop||document.body.scrollTop));
+},stop:function(_5){
+if(_5.preventDefault){
+_5.preventDefault();
+_5.stopPropagation();
+}else{
+_5.returnValue=false;
+_5.cancelBubble=true;
+}
+},findElement:function(_6,_7){
+var _8=Event.element(_6);
+while(_8.parentNode&&(!_8.tagName||(_8.tagName.toUpperCase()!=_7.toUpperCase()))){
+_8=_8.parentNode;
+}
+return _8;
+},observers:false,_observeAndCache:function(_9,_10,_11,_12){
+if(!this.observers){
+this.observers=[];
+}
+if(_9.addEventListener){
+this.observers.push([_9,_10,_11,_12]);
+_9.addEventListener(_10,_11,_12);
+}else{
+if(_9.attachEvent){
+this.observers.push([_9,_10,_11,_12]);
+_9.attachEvent("on"+_10,_11);
+}
+}
+},unloadCache:function(){
+if(!Event.observers){
+return;
+}
+for(var i=0;i<Event.observers.length;i++){
+Event.stopObserving.apply(this,Event.observers[i]);
+Event.observers[i][0]=null;
+}
+Event.observers=false;
+},observe:function(_14,_15,_16,_17){
+var _14=$(_14);
+_17=_17||false;
+if(_15=="keypress"&&(navigator.appVersion.match(/Konqueror|Safari|KHTML/)||_14.attachEvent)){
+_15="keydown";
+}
+this._observeAndCache(_14,_15,_16,_17);
+},stopObserving:function(_18,_19,_20,_21){
+var _18=$(_18);
+_21=_21||false;
+if(_19=="keypress"&&(navigator.appVersion.match(/Konqueror|Safari|KHTML/)||_18.detachEvent)){
+_19="keydown";
+}
+if(_18.removeEventListener){
+_18.removeEventListener(_19,_20,_21);
+}else{
+if(_18.detachEvent){
+_18.detachEvent("on"+_19,_20);
+}
+}
+}});
+Event.observe(window,"unload",Event.unloadCache,false);
+
+Object.extend(Event,{OnLoad:function(fn){
+var w=document.addEventListener&&!window.addEventListener?document:window;
+Event.__observe(w,"load",fn);
+},observe:function(_3,_4,_5,_6){
+if(isElement(_3)){
+return this.__observe(_3,_4,_5,_6);
+}
+for(var i=0;i<_3.length;i++){
+this.__observe(_3[i],_4,_5,_6);
+}
+},__observe:function(_8,_9,_10,_11){
+var _8=$(_8);
+_11=_11||false;
+if(_9=="keypress"&&((navigator.appVersion.indexOf("AppleWebKit")>0)||_8.attachEvent)){
+_9="keydown";
+}
+this._observeAndCache(_8,_9,_10,_11);
+}});
+
+var Position={includeScrollOffsets:false,prepare:function(){
+this.deltaX=window.pageXOffset||document.documentElement.scrollLeft||document.body.scrollLeft||0;
+this.deltaY=window.pageYOffset||document.documentElement.scrollTop||document.body.scrollTop||0;
+},realOffset:function(_1){
+var _2=0,valueL=0;
+do{
+_2+=_1.scrollTop||0;
+valueL+=_1.scrollLeft||0;
+_1=_1.parentNode;
+}while(_1);
+return [valueL,_2];
+},cumulativeOffset:function(_3){
+var _4=0,valueL=0;
+do{
+_4+=_3.offsetTop||0;
+valueL+=_3.offsetLeft||0;
+_3=_3.offsetParent;
+}while(_3);
+return [valueL,_4];
+},positionedOffset:function(_5){
+var _6=0,valueL=0;
+do{
+_6+=_5.offsetTop||0;
+valueL+=_5.offsetLeft||0;
+_5=_5.offsetParent;
+if(_5){
+p=Element.getStyle(_5,"position");
+if(p=="relative"||p=="absolute"){
+break;
+}
+}
+}while(_5);
+return [valueL,_6];
+},offsetParent:function(_7){
+if(_7.offsetParent){
+return _7.offsetParent;
+}
+if(_7==document.body){
+return _7;
+}
+while((_7=_7.parentNode)&&_7!=document.body){
+if(Element.getStyle(_7,"position")!="static"){
+return _7;
+}
+}
+return document.body;
+},within:function(_8,x,y){
+if(this.includeScrollOffsets){
+return this.withinIncludingScrolloffsets(_8,x,y);
+}
+this.xcomp=x;
+this.ycomp=y;
+this.offset=this.cumulativeOffset(_8);
+return (y>=this.offset[1]&&y<this.offset[1]+_8.offsetHeight&&x>=this.offset[0]&&x<this.offset[0]+_8.offsetWidth);
+},withinIncludingScrolloffsets:function(_11,x,y){
+var _12=this.realOffset(_11);
+this.xcomp=x+_12[0]-this.deltaX;
+this.ycomp=y+_12[1]-this.deltaY;
+this.offset=this.cumulativeOffset(_11);
+return (this.ycomp>=this.offset[1]&&this.ycomp<this.offset[1]+_11.offsetHeight&&this.xcomp>=this.offset[0]&&this.xcomp<this.offset[0]+_11.offsetWidth);
+},overlap:function(_13,_14){
+if(!_13){
+return 0;
+}
+if(_13=="vertical"){
+return ((this.offset[1]+_14.offsetHeight)-this.ycomp)/_14.offsetHeight;
+}
+if(_13=="horizontal"){
+return ((this.offset[0]+_14.offsetWidth)-this.xcomp)/_14.offsetWidth;
+}
+},clone:function(_15,_16){
+_15=$(_15);
+_16=$(_16);
+_16.style.position="absolute";
+var _17=this.cumulativeOffset(_15);
+_16.style.top=_17[1]+"px";
+_16.style.left=_17[0]+"px";
+_16.style.width=_15.offsetWidth+"px";
+_16.style.height=_15.offsetHeight+"px";
+},page:function(_18){
+var _19=0,valueL=0;
+var _20=_18;
+do{
+_19+=_20.offsetTop||0;
+valueL+=_20.offsetLeft||0;
+if(_20.offsetParent==document.body){
+if(Element.getStyle(_20,"position")=="absolute"){
+break;
+}
+}
+}while(_20=_20.offsetParent);
+_20=_18;
+do{
+_19-=_20.scrollTop||0;
+valueL-=_20.scrollLeft||0;
+}while(_20=_20.parentNode);
+return [valueL,_19];
+},clone:function(_21,_22){
+var _23=Object.extend({setLeft:true,setTop:true,setWidth:true,setHeight:true,offsetTop:0,offsetLeft:0},arguments[2]||{});
+_21=$(_21);
+var p=Position.page(_21);
+_22=$(_22);
+var _25=[0,0];
+var _26=null;
+if(Element.getStyle(_22,"position")=="absolute"){
+_26=Position.offsetParent(_22);
+_25=Position.page(_26);
+}
+if(_26==document.body){
+_25[0]-=document.body.offsetLeft;
+_25[1]-=document.body.offsetTop;
+}
+if(_23.setLeft){
+_22.style.left=(p[0]-_25[0]+_23.offsetLeft)+"px";
+}
+if(_23.setTop){
+_22.style.top=(p[1]-_25[1]+_23.offsetTop)+"px";
+}
+if(_23.setWidth){
+_22.style.width=_21.offsetWidth+"px";
+}
+if(_23.setHeight){
+_22.style.height=_21.offsetHeight+"px";
+}
+},absolutize:function(_27){
+_27=$(_27);
+if(_27.style.position=="absolute"){
+return;
+}
+Position.prepare();
+var _28=Position.positionedOffset(_27);
+var top=_28[1];
+var _30=_28[0];
+var _31=_27.clientWidth;
+var _32=_27.clientHeight;
+_27._originalLeft=_30-parseFloat(_27.style.left||0);
+_27._originalTop=top-parseFloat(_27.style.top||0);
+_27._originalWidth=_27.style.width;
+_27._originalHeight=_27.style.height;
+_27.style.position="absolute";
+_27.style.top=top+"px";
+_27.style.left=_30+"px";
+_27.style.width=_31+"px";
+_27.style.height=_32+"px";
+},relativize:function(_33){
+_33=$(_33);
+if(_33.style.position=="relative"){
+return;
+}
+Position.prepare();
+_33.style.position="relative";
+var top=parseFloat(_33.style.top||0)-(_33._originalTop||0);
+var _34=parseFloat(_33.style.left||0)-(_33._originalLeft||0);
+_33.style.top=top+"px";
+_33.style.left=_34+"px";
+_33.style.height=_33._originalHeight;
+_33.style.width=_33._originalWidth;
+}};
+if(/Konqueror|Safari|KHTML/.test(navigator.userAgent)){
+Position.cumulativeOffset=function(_35){
+var _36=0,valueL=0;
+do{
+_36+=_35.offsetTop||0;
+valueL+=_35.offsetLeft||0;
+if(_35.offsetParent==document.body){
+if(Element.getStyle(_35,"position")=="absolute"){
+break;
+}
+}
+_35=_35.offsetParent;
+}while(_35);
+return [valueL,_36];
+};
+}
+
+function getAllChildren(e){
+return e.all?e.all:e.getElementsByTagName("*");
+}
+document.getElementsBySelector=function(_2){
+if(!document.getElementsByTagName){
+return new Array();
+}
+var _3=_2.split(" ");
+var _4=new Array(document);
+for(var i=0;i<_3.length;i++){
+token=_3[i].replace(/^\s+/,"").replace(/\s+$/,"");
+if(token.indexOf("#")>-1){
+var _6=token.split("#");
+var _7=_6[0];
+var id=_6[1];
+var _9=document.getElementById(id);
+if(_7&&_9.nodeName.toLowerCase()!=_7){
+return new Array();
+}
+_4=new Array(_9);
+continue;
+}
+if(token.indexOf(".")>-1){
+var _6=token.split(".");
+var _7=_6[0];
+var _10=_6[1];
+if(!_7){
+_7="*";
+}
+var _11=new Array;
+var _12=0;
+for(var h=0;h<_4.length;h++){
+var _14;
+if(_7=="*"){
+_14=getAllChildren(_4[h]);
+}else{
+_14=_4[h].getElementsByTagName(_7);
+}
+for(var j=0;j<_14.length;j++){
+_11[_12++]=_14[j];
+}
+}
+_4=new Array;
+var _16=0;
+for(var k=0;k<_11.length;k++){
+if(_11[k].className&&_11[k].className.match(new RegExp("\\b"+_10+"\\b"))){
+_4[_16++]=_11[k];
+}
+}
+continue;
+}
+if(token.match(/^(\w*)\[(\w+)([=~\|\^\$\*]?)=?"?([^\]"]*)"?\]$/)){
+var _7=RegExp.$1;
+var _18=RegExp.$2;
+var _19=RegExp.$3;
+var _20=RegExp.$4;
+if(!_7){
+_7="*";
+}
+var _11=new Array;
+var _12=0;
+for(var h=0;h<_4.length;h++){
+var _14;
+if(_7=="*"){
+_14=getAllChildren(_4[h]);
+}else{
+_14=_4[h].getElementsByTagName(_7);
+}
+for(var j=0;j<_14.length;j++){
+_11[_12++]=_14[j];
+}
+}
+_4=new Array;
+var _16=0;
+var _21;
+switch(_19){
+case "=":
+_21=function(e){
+return (e.getAttribute(_18)==_20);
+};
+break;
+case "~":
+_21=function(e){
+return (e.getAttribute(_18).match(new RegExp("\\b"+_20+"\\b")));
+};
+break;
+case "|":
+_21=function(e){
+return (e.getAttribute(_18).match(new RegExp("^"+_20+"-?")));
+};
+break;
+case "^":
+_21=function(e){
+return (e.getAttribute(_18).indexOf(_20)==0);
+};
+break;
+case "$":
+_21=function(e){
+return (e.getAttribute(_18).lastIndexOf(_20)==e.getAttribute(_18).length-_20.length);
+};
+break;
+case "*":
+_21=function(e){
+return (e.getAttribute(_18).indexOf(_20)>-1);
+};
+break;
+default:
+_21=function(e){
+return e.getAttribute(_18);
+};
+}
+_4=new Array;
+var _16=0;
+for(var k=0;k<_11.length;k++){
+if(_21(_11[k])){
+_4[_16++]=_11[k];
+}
+}
+continue;
+}
+_7=token;
+var _11=new Array;
+var _12=0;
+for(var h=0;h<_4.length;h++){
+var _14=_4[h].getElementsByTagName(_7);
+for(var j=0;j<_14.length;j++){
+_11[_12++]=_14[j];
+}
+}
+_4=_11;
+}
+return _4;
+};
+
+var Behaviour={list:new Array,register:function(_1){
+Behaviour.list.push(_1);
+},start:function(){
+Behaviour.addLoadEvent(function(){
+Behaviour.apply();
+});
+},apply:function(){
+for(h=0;sheet=Behaviour.list[h];h++){
+for(selector in sheet){
+list=document.getElementsBySelector(selector);
+if(!list){
+continue;
+}
+for(i=0;element=list[i];i++){
+sheet[selector](element);
+}
+}
+}
+},addLoadEvent:function(_2){
+var _3=window.onload;
+if(typeof window.onload!="function"){
+window.onload=_2;
+}else{
+window.onload=function(){
+_3();
+_2();
+};
+}
+}};
+Behaviour.start();
+
+Object.debug=function(_1){
+var _2=[];
+if(typeof _1 in ["string","number"]){
+return _1;
+}else{
+for(property in _1){
+if(typeof _1[property]!="function"){
+_2.push(property+" => "+(typeof _1[property]=="string"?"\""+_1[property]+"\"":_1[property]));
+}
+}
+}
+return ("'"+_1+"' #"+typeof _1+": {"+_2.join(", ")+"}");
+};
+String.prototype.toArray=function(){
+var _3=[];
+for(var i=0;i<this.length;i++){
+_3.push(this.charAt(i));
+}
+return _3;
+};
+var Builder={NODEMAP:{AREA:"map",CAPTION:"table",COL:"table",COLGROUP:"table",LEGEND:"fieldset",OPTGROUP:"select",OPTION:"select",PARAM:"object",TBODY:"table",TD:"table",TFOOT:"table",TH:"table",THEAD:"table",TR:"table"},node:function(_5){
+_5=_5.toUpperCase();
+var _6=this.NODEMAP[_5]||"div";
+var _7=document.createElement(_6);
+_7.innerHTML="<"+_5+"></"+_5+">";
+var _8=_7.firstChild||null;
+if(_8&&(_8.tagName!=_5)){
+_8=_8.getElementsByTagName(_5)[0];
+}
+if(!_8){
+_8=document.createElement(_5);
+}
+if(!_8){
+return;
+}
+if(arguments[1]){
+if(this._isStringOrNumber(arguments[1])||(arguments[1] instanceof Array)){
+this._children(_8,arguments[1]);
+}else{
+var _9=this._attributes(arguments[1]);
+if(_9.length){
+_7.innerHTML="<"+_5+" "+_9+"></"+_5+">";
+_8=_7.firstChild||null;
+if(!_8){
+_8=document.createElement(_5);
+for(attr in arguments[1]){
+_8[attr=="class"?"className":attr]=arguments[1][attr];
+}
+}
+if(_8.tagName!=_5){
+_8=_7.getElementsByTagName(_5)[0];
+}
+}
+}
+}
+if(arguments[2]){
+this._children(_8,arguments[2]);
+}
+return _8;
+},_text:function(_10){
+return document.createTextNode(_10);
+},_attributes:function(_11){
+var _12=[];
+for(attribute in _11){
+_12.push((attribute=="className"?"class":attribute)+"=\""+_11[attribute].toString().escapeHTML()+"\"");
+}
+return _12.join(" ");
+},_children:function(_13,_14){
+if(typeof _14=="object"){
+_14.flatten().each(function(e){
+if(typeof e=="object"){
+_13.appendChild(e);
+}else{
+if(Builder._isStringOrNumber(e)){
+_13.appendChild(Builder._text(e));
+}
+}
+});
+}else{
+if(Builder._isStringOrNumber(_14)){
+_13.appendChild(Builder._text(_14));
+}
+}
+},_isStringOrNumber:function(_16){
+return (typeof _16=="string"||typeof _16=="number");
+}};
+String.prototype.camelize=function(){
+var _17=this.split("-");
+if(_17.length==1){
+return _17[0];
+}
+var ret=this.indexOf("-")==0?_17[0].charAt(0).toUpperCase()+_17[0].substring(1):_17[0];
+for(var i=1,len=_17.length;i<len;i++){
+var s=_17[i];
+ret+=s.charAt(0).toUpperCase()+s.substring(1);
+}
+return ret;
+};
+Element.getStyle=function(_20,_21){
+_20=$(_20);
+var _22=_20.style[_21.camelize()];
+if(!_22){
+if(document.defaultView&&document.defaultView.getComputedStyle){
+var css=document.defaultView.getComputedStyle(_20,null);
+_22=(css!=null)?css.getPropertyValue(_21):null;
+}else{
+if(_20.currentStyle){
+_22=_20.currentStyle[_21.camelize()];
+}
+}
+}
+if(window.opera&&(_21=="left"||_21=="top"||_21=="right"||_21=="bottom")){
+if(Element.getStyle(_20,"position")=="static"){
+_22="auto";
+}
+}
+if(_22=="auto"){
+_22=null;
+}
+return _22;
+};
+String.prototype.parseColor=function(){
+color="#";
+if(this.slice(0,4)=="rgb("){
+var _24=this.slice(4,this.length-1).split(",");
+var i=0;
+do{
+color+=parseInt(_24[i]).toColorPart();
+}while(++i<3);
+}else{
+if(this.slice(0,1)=="#"){
+if(this.length==4){
+for(var i=1;i<4;i++){
+color+=(this.charAt(i)+this.charAt(i)).toLowerCase();
+}
+}
+if(this.length==7){
+color=this.toLowerCase();
+}
+}
+}
+return (color.length==7?color:(arguments[0]||this));
+};
+Element.makePositioned=function(_25){
+_25=$(_25);
+var pos=Element.getStyle(_25,"position");
+if(pos=="static"||!pos){
+_25._madePositioned=true;
+_25.style.position="relative";
+if(window.opera){
+_25.style.top=0;
+_25.style.left=0;
+}
+}
+};
+Element.undoPositioned=function(_27){
+_27=$(_27);
+if(typeof _27._madePositioned!="undefined"){
+_27._madePositioned=undefined;
+_27.style.position="";
+_27.style.top="";
+_27.style.left="";
+_27.style.bottom="";
+_27.style.right="";
+}
+};
+Element.makeClipping=function(_28){
+_28=$(_28);
+if(typeof _28._overflow!="undefined"){
+return;
+}
+_28._overflow=_28.style.overflow;
+if((Element.getStyle(_28,"overflow")||"visible")!="hidden"){
+_28.style.overflow="hidden";
+}
+};
+Element.undoClipping=function(_29){
+_29=$(_29);
+if(typeof _29._overflow=="undefined"){
+return;
+}
+_29.style.overflow=_29._overflow;
+_29._overflow=undefined;
+};
+Element.collectTextNodesIgnoreClass=function(_30,_31){
+var _32=$(_30).childNodes;
+var _33="";
+var _34=new RegExp("^([^ ]+ )*"+_31+"( [^ ]+)*$","i");
+for(var i=0;i<_32.length;i++){
+if(_32[i].nodeType==3){
+_33+=_32[i].nodeValue;
+}else{
+if((!_32[i].className.match(_34))&&_32[i].hasChildNodes()){
+_33+=Element.collectTextNodesIgnoreClass(_32[i],_31);
+}
+}
+}
+return _33;
+};
+Element.setContentZoom=function(_35,_36){
+_35=$(_35);
+_35.style.fontSize=(_36/100)+"em";
+if(navigator.appVersion.indexOf("AppleWebKit")>0){
+window.scrollBy(0,0);
+}
+};
+Element.getOpacity=function(_37){
+var _38;
+if(_38=Element.getStyle(_37,"opacity")){
+return parseFloat(_38);
+}
+if(_38=(Element.getStyle(_37,"filter")||"").match(/alpha\(opacity=(.*)\)/)){
+if(_38[1]){
+return parseFloat(_38[1])/100;
+}
+}
+return 1;
+};
+Element.setOpacity=function(_39,_40){
+_39=$(_39);
+var els=_39.style;
+if(_40==1){
+els.opacity="0.999999";
+if(/MSIE/.test(navigator.userAgent)){
+els.filter=Element.getStyle(_39,"filter").replace(/alpha\([^\)]*\)/gi,"");
+}
+}else{
+if(_40<0.00001){
+_40=0;
+}
+els.opacity=_40;
+if(/MSIE/.test(navigator.userAgent)){
+els.filter=Element.getStyle(_39,"filter").replace(/alpha\([^\)]*\)/gi,"")+"alpha(opacity="+_40*100+")";
+}
+}
+};
+Element.getInlineOpacity=function(_42){
+_42=$(_42);
+var op;
+op=_42.style.opacity;
+if(typeof op!="undefined"&&op!=""){
+return op;
+}
+return "";
+};
+Element.setInlineOpacity=function(_44,_45){
+_44=$(_44);
+var els=_44.style;
+els.opacity=_45;
+};
+Element.getDimensions=function(_46){
+_46=$(_46);
+if(Element.getStyle(_46,"display")=="none"){
+var els=_46.style;
+var _47=els.visibility;
+var _48=els.position;
+els.visibility="hidden";
+els.position="absolute";
+els.display="";
+var _49=_46.clientWidth;
+var _50=_46.clientHeight;
+els.display="none";
+els.position=_48;
+els.visibility=_47;
+return {width:_49,height:_50};
+}
+return {width:_46.offsetWidth,height:_46.offsetHeight};
+};
+Position.positionedOffset=function(_51){
+var _52=0,valueL=0;
+do{
+_52+=_51.offsetTop||0;
+valueL+=_51.offsetLeft||0;
+_51=_51.offsetParent;
+if(_51){
+p=Element.getStyle(_51,"position");
+if(p=="relative"||p=="absolute"){
+break;
+}
+}
+}while(_51);
+return [valueL,_52];
+};
+if(/Konqueror|Safari|KHTML/.test(navigator.userAgent)){
+Position.cumulativeOffset=function(_53){
+var _54=0,valueL=0;
+do{
+_54+=_53.offsetTop||0;
+valueL+=_53.offsetLeft||0;
+if(_53.offsetParent==document.body){
+if(Element.getStyle(_53,"position")=="absolute"){
+break;
+}
+}
+_53=_53.offsetParent;
+}while(_53);
+return [valueL,_54];
+};
+}
+Position.page=function(_55){
+var _56=0,valueL=0;
+var _57=_55;
+do{
+_56+=_57.offsetTop||0;
+valueL+=_57.offsetLeft||0;
+if(_57.offsetParent==document.body){
+if(Element.getStyle(_57,"position")=="absolute"){
+break;
+}
+}
+}while(_57=_57.offsetParent);
+_57=_55;
+do{
+_56-=_57.scrollTop||0;
+valueL-=_57.scrollLeft||0;
+}while(_57=_57.parentNode);
+return [valueL,_56];
+};
+Position.offsetParent=function(_58){
+if(_58.offsetParent){
+return _58.offsetParent;
+}
+if(_58==document.body){
+return _58;
+}
+while((_58=_58.parentNode)&&_58!=document.body){
+if(Element.getStyle(_58,"position")!="static"){
+return _58;
+}
+}
+return document.body;
+};
+Position.clone=function(_59,_60){
+var _61=Object.extend({setLeft:true,setTop:true,setWidth:true,setHeight:true,offsetTop:0,offsetLeft:0},arguments[2]||{});
+_59=$(_59);
+var p=Position.page(_59);
+_60=$(_60);
+var _63=[0,0];
+var _64=null;
+if(Element.getStyle(_60,"position")=="absolute"){
+_64=Position.offsetParent(_60);
+_63=Position.page(_64);
+}
+if(_64==document.body){
+_63[0]-=document.body.offsetLeft;
+_63[1]-=document.body.offsetTop;
+}
+if(_61.setLeft){
+_60.style.left=(p[0]-_63[0]+_61.offsetLeft)+"px";
+}
+if(_61.setTop){
+_60.style.top=(p[1]-_63[1]+_61.offsetTop)+"px";
+}
+if(_61.setWidth){
+_60.style.width=_59.offsetWidth+"px";
+}
+if(_61.setHeight){
+_60.style.height=_59.offsetHeight+"px";
+}
+};
+Position.absolutize=function(_65){
+_65=$(_65);
+if(_65.style.position=="absolute"){
+return;
+}
+Position.prepare();
+var _66=Position.positionedOffset(_65);
+var top=_66[1];
+var _68=_66[0];
+var _69=_65.clientWidth;
+var _70=_65.clientHeight;
+_65._originalLeft=_68-parseFloat(_65.style.left||0);
+_65._originalTop=top-parseFloat(_65.style.top||0);
+_65._originalWidth=_65.style.width;
+_65._originalHeight=_65.style.height;
+_65.style.position="absolute";
+_65.style.top=top+"px";
+_65.style.left=_68+"px";
+_65.style.width=_69+"px";
+_65.style.height=_70+"px";
+};
+Position.relativize=function(_71){
+_71=$(_71);
+if(_71.style.position=="relative"){
+return;
+}
+Position.prepare();
+_71.style.position="relative";
+var top=parseFloat(_71.style.top||0)-(_71._originalTop||0);
+var _72=parseFloat(_71.style.left||0)-(_71._originalLeft||0);
+_71.style.top=top+"px";
+_71.style.left=_72+"px";
+_71.style.height=_71._originalHeight;
+_71.style.width=_71._originalWidth;
+};
+Element.Class={toggle:function(_73,_74){
+if(Element.Class.has(_73,_74)){
+Element.Class.remove(_73,_74);
+if(arguments.length==3){
+Element.Class.add(_73,arguments[2]);
+}
+}else{
+Element.Class.add(_73,_74);
+if(arguments.length==3){
+Element.Class.remove(_73,arguments[2]);
+}
+}
+},get:function(_75){
+return $(_75).className.split(" ");
+},remove:function(_76){
+_76=$(_76);
+var _77=arguments;
+$R(1,arguments.length-1).each(function(_78){
+_76.className=_76.className.split(" ").reject(function(_79){
+return (_79==_77[_78]);
+}).join(" ");
+});
+},add:function(_80){
+_80=$(_80);
+for(var i=1;i<arguments.length;i++){
+Element.Class.remove(_80,arguments[i]);
+_80.className+=(_80.className.length>0?" ":"")+arguments[i];
+}
+},has:function(_81){
+_81=$(_81);
+if(!_81||!_81.className){
+return false;
+}
+var _82;
+for(var i=1;i<arguments.length;i++){
+if((typeof arguments[i]=="object")&&(arguments[i].constructor==Array)){
+for(var j=0;j<arguments[i].length;j++){
+_82=new RegExp("(^|\\s)"+arguments[i][j]+"(\\s|$)");
+if(!_82.test(_81.className)){
+return false;
+}
+}
+}else{
+_82=new RegExp("(^|\\s)"+arguments[i]+"(\\s|$)");
+if(!_82.test(_81.className)){
+return false;
+}
+}
+}
+return true;
+},has_any:function(_84){
+_84=$(_84);
+if(!_84||!_84.className){
+return false;
+}
+var _85;
+for(var i=1;i<arguments.length;i++){
+if((typeof arguments[i]=="object")&&(arguments[i].constructor==Array)){
+for(var j=0;j<arguments[i].length;j++){
+_85=new RegExp("(^|\\s)"+arguments[i][j]+"(\\s|$)");
+if(_85.test(_84.className)){
+return true;
+}
+}
+}else{
+_85=new RegExp("(^|\\s)"+arguments[i]+"(\\s|$)");
+if(_85.test(_84.className)){
+return true;
+}
+}
+}
+return false;
+},childrenWith:function(_86,_87){
+var _88=$(_86).getElementsByTagName("*");
+var _89=new Array();
+for(var i=0;i<_88.length;i++){
+if(Element.Class.has(_88[i],_87)){
+_89.push(_88[i]);
+}
+}
+return _89;
+}};
+
diff --git a/framework/Web/Javascripts/js/validator.js b/framework/Web/Javascripts/js/validator.js
new file mode 100644
index 00000000..5b25118f
--- /dev/null
+++ b/framework/Web/Javascripts/js/validator.js
@@ -0,0 +1,536 @@
+Prado.Validation=Class.create();
+Prado.Validation.Util=Class.create();
+Prado.Validation.Util.toInteger=function(_1){
+var _2=/^\s*[-\+]?\d+\s*$/;
+if(_1.match(_2)==null){
+return null;
+}
+var _3=parseInt(_1,10);
+return (isNaN(_3)?null:_3);
+};
+Prado.Validation.Util.toDouble=function(_4,_5){
+_5=undef(_5)?".":_5;
+var _6=new RegExp("^\\s*([-\\+])?(\\d+)?(\\"+_5+"(\\d+))?\\s*$");
+var m=_4.match(_6);
+if(m==null){
+return null;
+}
+var _8=m[1]+(m[2].length>0?m[2]:"0")+"."+m[4];
+var _9=parseFloat(_8);
+return (isNaN(_9)?null:_9);
+};
+Prado.Validation.Util.toCurrency=function(_10,_11,_12,_13){
+_11=undef(_11)?",":_11;
+_13=undef(_13)?".":_13;
+_12=undef(_12)?2:_12;
+var exp=new RegExp("^\\s*([-\\+])?(((\\d+)\\"+_11+")*)(\\d+)"+((_12>0)?"(\\"+_13+"(\\d{1,"+_12+"}))?":"")+"\\s*$");
+var m=_10.match(exp);
+if(m==null){
+return null;
+}
+var _15=m[2]+m[5];
+var _16=m[1]+_15.replace(new RegExp("(\\"+_11+")","g"),"")+((_12>0)?"."+m[7]:"");
+var num=parseFloat(_16);
+return (isNaN(num)?null:num);
+};
+Prado.Validation.Util.toDate=function(_18,_19){
+var y=0;
+var m=-1;
+var d=0;
+var a=_18.split(/\W+/);
+var b=_19.match(/%./g);
+var i=0,j=0;
+var hr=0;
+var min=0;
+for(i=0;i<a.length;++i){
+if(!a[i]){
+continue;
+}
+switch(b[i]){
+case "%d":
+case "%e":
+d=parseInt(a[i],10);
+break;
+case "%m":
+m=parseInt(a[i],10)-1;
+break;
+case "%Y":
+case "%y":
+y=parseInt(a[i],10);
+(y<100)&&(y+=(y>29)?1900:2000);
+break;
+case "%H":
+case "%I":
+case "%k":
+case "%l":
+hr=parseInt(a[i],10);
+break;
+case "%P":
+case "%p":
+if(/pm/i.test(a[i])&&hr<12){
+hr+=12;
+}
+break;
+case "%M":
+min=parseInt(a[i],10);
+break;
+}
+}
+if(y!=0&&m!=-1&&d!=0){
+var _27=new Date(y,m,d,hr,min,0);
+return (isObject(_27)&&y==_27.getFullYear()&&m==_27.getMonth()&&d==_27.getDate())?_27.valueOf():null;
+}
+return null;
+};
+Prado.Validation.Util.trim=function(_28){
+if(undef(_28)){
+return "";
+}
+return _28.replace(/^\s+|\s+$/g,"");
+};
+Prado.Validation.Util.focus=function(_29){
+var obj=$(_29);
+if(isObject(obj)&&isdef(obj.focus)){
+setTimeout(function(){
+obj.focus();
+},100);
+}
+return false;
+};
+Prado.Validation.validators=[];
+Prado.Validation.forms=[];
+Prado.Validation.summaries=[];
+Prado.Validation.groups=[];
+Prado.Validation.TargetGroups=[];
+Prado.Validation.CurrentTargetGroup=null;
+Prado.Validation.HasTargetGroup=false;
+Prado.Validation.ActiveTarget=null;
+Prado.Validation.IsGroupValidation=false;
+Prado.Validation.AddForm=function(id){
+Prado.Validation.forms.push($(id));
+};
+Prado.Validation.AddTarget=function(id,_32){
+var _33=$(id);
+Event.observe(_33,"click",function(){
+Prado.Validation.ActiveTarget=_33;
+Prado.Validation.CurrentTargetGroup=Prado.Validation.TargetGroups[id];
+});
+if(_32){
+Prado.Validation.TargetGroups[id]=_32;
+Prado.Validation.HasTargetGroup=true;
+}
+};
+Prado.Validation.AddGroup=function(_34,_35){
+_34.active=false;
+_34.target=$(_34.target);
+_34.validators=_35;
+Prado.Validation.groups.push(_34);
+Event.observe(_34.target,"click",Prado.Validation.UpdateActiveGroup);
+};
+Prado.Validation.UpdateActiveGroup=function(ev){
+var _37=Prado.Validation.groups;
+for(var i=0;i<_37.length;i++){
+_37[i].active=(isdef(ev)&&_37[i].target==Event.element(ev));
+}
+Prado.Validation.IsGroupValidation=isdef(ev);
+};
+Prado.Validation.IsValid=function(_38){
+var _39=true;
+var _40=Prado.Validation.validators;
+for(var i=0;i<_40.length;i++){
+_40[i].enabled=!_40[i].control||undef(_40[i].control.form)||_40[i].control.form==_38;
+_40[i].visible=Prado.Validation.IsGroupValidation?_40[i].inActiveGroup():true;
+if(Prado.Validation.HasTargetGroup){
+if(_40[i].group!=Prado.Validation.CurrentTargetGroup){
+_40[i].enabled=false;
+}
+}
+_39&=_40[i].validate();
+}
+Prado.Validation.ShowSummary(_38);
+Prado.Validation.UpdateActiveGroup();
+return _39;
+};
+Prado.Validation.prototype={initialize:function(_41,_42){
+this.evaluateIsValid=_41;
+this.attr=undef(_42)?[]:_42;
+this.message=$(_42.id);
+this.control=$(_42.controltovalidate);
+this.enabled=isdef(_42.enabled)?_42.enabled:true;
+this.visible=isdef(_42.visible)?_42.visible:true;
+this.group=isdef(_42.validationgroup)?_42.validationgroup:null;
+this.isValid=true;
+Prado.Validation.validators.push(this);
+if(this.evaluateIsValid){
+this.evaluateIsValid.bind(this);
+}
+},validate:function(){
+if(this.visible&&this.enabled&&this.evaluateIsValid){
+this.isValid=this.evaluateIsValid();
+}else{
+this.isValid=true;
+}
+this.observe();
+this.update();
+return this.isValid;
+},update:function(){
+if(this.attr.display=="Dynamic"){
+this.isValid?Element.hide(this.message):Element.show(this.message);
+}
+if(this.message){
+this.message.style.visibility=this.isValid?"hidden":"visible";
+}
+var _43=this.attr.controlcssclass;
+if(this.control&&isString(_43)&&_43.length>0){
+Element.condClassName(this.control,_43,!this.isValid);
+}
+Prado.Validation.ShowSummary();
+},setValid:function(_44){
+this.isValid=_44;
+this.update();
+},observe:function(){
+if(undef(this.observing)){
+if(this.control&&this.control.form){
+Event.observe(this.control,"blur",this.validate.bind(this));
+}
+this.observing=true;
+}
+},convert:function(_45,_46){
+if(undef(_46)){
+_46=Form.Element.getValue(this.control);
+}
+switch(_45){
+case "Integer":
+return Prado.Validation.Util.toInteger(_46);
+case "Double":
+case "Float":
+return Prado.Validation.Util.toDouble(_46,this.attr.decimalchar);
+case "Currency":
+return Prado.Validation.Util.toCurrency(_46,this.attr.groupchar,this.attr.digits,this.attr.decimalchar);
+case "Date":
+return Prado.Validation.Util.toDate(_46,this.attr.dateformat);
+}
+return _46.toString();
+},inActiveGroup:function(){
+var _47=Prado.Validation.groups;
+for(var i=0;i<_47.length;i++){
+if(_47[i].active&&_47[i].validators.contains(this.attr.id)){
+return true;
+}
+}
+return false;
+}};
+Prado.Validation.Summary=Class.create();
+Prado.Validation.Summary.prototype={initialize:function(_48){
+this.attr=_48;
+this.div=$(_48.id);
+this.visible=false;
+this.enabled=false;
+this.group=isdef(_48.validationgroup)?_48.validationgroup:null;
+Prado.Validation.summaries.push(this);
+},show:function(_49){
+var _50=_49||this.attr.refresh=="1";
+var _51=this.getMessages();
+if(_51.length<=0||!this.visible||!this.enabled){
+if(_50){
+Element.hide(this.div);
+}
+return;
+}
+if(Prado.Validation.HasTargetGroup){
+if(Prado.Validation.CurrentTargetGroup!=this.group){
+if(_50){
+Element.hide(this.div);
+}
+return;
+}
+}
+if(this.attr.showsummary!="False"&&_50){
+this.div.style.display="block";
+while(this.div.childNodes.length>0){
+this.div.removeChild(this.div.lastChild);
+}
+new Insertion.Bottom(this.div,this.formatSummary(_51));
+}
+if(_49){
+window.scrollTo(this.div.offsetLeft-20,this.div.offsetTop-20);
+}
+var _52=this;
+if(_49&&this.attr.showmessagebox=="True"&&_50){
+setTimeout(function(){
+alert(_52.formatMessageBox(_51));
+},20);
+}
+},getMessages:function(){
+var _53=Prado.Validation.validators;
+var _54=[];
+for(var i=0;i<_53.length;i++){
+if(_53[i].isValid==false&&isString(_53[i].attr.errormessage)&&_53[i].attr.errormessage.length>0){
+_54.push(_53[i].attr.errormessage);
+}
+}
+return _54;
+},formats:function(_55){
+switch(_55){
+case "List":
+return {header:"<br />",first:"",pre:"",post:"<br />",last:""};
+case "SingleParagraph":
+return {header:" ",first:"",pre:"",post:" ",last:"<br />"};
+case "BulletList":
+default:
+return {header:"",first:"<ul>",pre:"<li>",post:"</li>",last:"</ul>"};
+}
+},formatSummary:function(_56){
+var _57=this.formats(this.attr.displaymode);
+var _58=isdef(this.attr.headertext)?this.attr.headertext+_57.header:"";
+_58+=_57.first;
+for(var i=0;i<_56.length;i++){
+_58+=(_56[i].length>0)?_57.pre+_56[i]+_57.post:"";
+}
+_58+=_57.last;
+return _58;
+},formatMessageBox:function(_59){
+var _60=isdef(this.attr.headertext)?this.attr.headertext+"\n":"";
+for(var i=0;i<_59.length;i++){
+switch(this.attr.displaymode){
+case "List":
+_60+=_59[i]+"\n";
+break;
+case "BulletList":
+default:
+_60+=" - "+_59[i]+"\n";
+break;
+case "SingleParagraph":
+_60+=_59[i]+" ";
+break;
+}
+}
+return _60;
+},inActiveGroup:function(){
+var _61=Prado.Validation.groups;
+for(var i=0;i<_61.length;i++){
+if(_61[i].active&&_61[i].id==this.attr.group){
+return true;
+}
+}
+return false;
+}};
+Prado.Validation.ShowSummary=function(_62){
+var _63=Prado.Validation.summaries;
+for(var i=0;i<_63.length;i++){
+if(isdef(_62)){
+if(Prado.Validation.IsGroupValidation){
+_63[i].visible=_63[i].inActiveGroup();
+}else{
+_63[i].visible=undef(_63[i].attr.group);
+}
+_63[i].enabled=$(_63[i].attr.form)==_62;
+}
+_63[i].show(_62);
+}
+};
+Prado.Validation.OnSubmit=function(ev){
+if(typeof tinyMCE!="undefined"){
+tinyMCE.triggerSave();
+}
+if(!Prado.Validation.ActiveTarget){
+return true;
+}
+var _64=Prado.Validation.IsValid(Event.element(ev)||ev);
+if(Event.element(ev)&&!_64){
+Event.stop(ev);
+}
+Prado.Validation.ActiveTarget=null;
+return _64;
+};
+Prado.Validation.OnLoad=function(){
+Event.observe(Prado.Validation.forms,"submit",Prado.Validation.OnSubmit);
+};
+Event.OnLoad(Prado.Validation.OnLoad);
+
+Prado.Validation.TRequiredFieldValidator=function(){
+var _1=this.control.getAttribute("type");
+if(_1=="file"){
+return true;
+}else{
+var _2=Prado.Validation.Util.trim;
+var a=_2(Form.Element.getValue(this.control));
+var b=_2(this.attr.initialvalue);
+return (a!=b);
+}
+};
+Prado.Validation.TRegularExpressionValidator=function(){
+var _5=Prado.Validation.Util.trim;
+var _6=_5(Form.Element.getValue(this.control));
+if(_6==""){
+return true;
+}
+var rx=new RegExp(this.attr.validationexpression);
+var _8=rx.exec(_6);
+return (_8!=null&&_6==_8[0]);
+};
+Prado.Validation.TEmailAddressValidator=Prado.Validation.TRegularExpressionValidator;
+Prado.Validation.TCustomValidator=function(){
+var _9=Prado.Validation.Util.trim;
+var _10=isNull(this.control)?"":_9(Form.Element.getValue(this.control));
+var _11=true;
+var _12=this.attr.clientvalidationfunction;
+if(isString(_12)&&_12!=""){
+eval("valid = ("+_12+"(this, value) != false);");
+}
+return _11;
+};
+Prado.Validation.TRangeValidator=function(){
+var _13=Prado.Validation.Util.trim;
+var _14=_13(Form.Element.getValue(this.control));
+if(_14==""){
+return true;
+}
+var _15=this.attr.minimumvalue;
+var _16=this.attr.maximumvalue;
+if(undef(_15)&&undef(_16)){
+return true;
+}
+if(_15==""){
+_15=0;
+}
+if(_16==""){
+_16=0;
+}
+var _17=this.attr.type;
+if(undef(_17)){
+return (parseFloat(_14)>=parseFloat(_15))&&(parseFloat(_14)<=parseFloat(_16));
+}
+var min=this.convert(_17,_15);
+var max=this.convert(_17,_16);
+_14=this.convert(_17,_14);
+return _14>=min&&_14<=max;
+};
+Prado.Validation.TCompareValidator=function(){
+var _20=Prado.Validation.Util.trim;
+var _21=_20(Form.Element.getValue(this.control));
+if(_21.length==0){
+return true;
+}
+var _22;
+var _23=$(this.attr.controlhookup);
+if(_23){
+_22=_20(Form.Element.getValue(_23));
+}else{
+_22=isString(this.attr.valuetocompare)?this.attr.valuetocompare:"";
+}
+var _24=Prado.Validation.TCompareValidator.compare;
+var _25=_24.bind(this)(_21,_22);
+if(_23){
+var _26=this.attr.controlcssclass;
+if(isString(_26)&&_26.length>0){
+Element.condClassName(_23,_26,!_25);
+}
+if(undef(this.observingComparee)){
+Event.observe(_23,"change",this.validate.bind(this));
+this.observingComparee=true;
+}
+}
+return _25;
+};
+Prado.Validation.TCompareValidator.compare=function(_27,_28){
+var op1,op2;
+if((op1=this.convert(this.attr.type,_27))==null){
+return false;
+}
+if(this.attr.operator=="DataTypeCheck"){
+return true;
+}
+if((op2=this.convert(this.attr.type,_28))==null){
+return true;
+}
+switch(this.attr.operator){
+case "NotEqual":
+return (op1!=op2);
+case "GreaterThan":
+return (op1>op2);
+case "GreaterThanEqual":
+return (op1>=op2);
+case "LessThan":
+return (op1<op2);
+case "LessThanEqual":
+return (op1<=op2);
+default:
+return (op1==op2);
+}
+};
+Prado.Validation.TRequiredListValidator=function(){
+var min=undef(this.attr.min)?Number.NEGATIVE_INFINITY:parseInt(this.attr.min);
+var max=undef(this.attr.max)?Number.POSITIVE_INFINITY:parseInt(this.attr.max);
+var _30=document.getElementsByName(this.attr.selector);
+if(_30.length<=0){
+_30=document.getElementsBySelector(this.attr.selector);
+}
+if(_30.length<=0){
+return true;
+}
+var _31=new Array();
+if(isString(this.attr.required)&&this.attr.required.length>0){
+_31=this.attr.required.split(/,\s* /);
+}
+var _32=true;
+var _33=Prado.Validation.TRequiredListValidator;
+switch(_30[0].type){
+case "radio":
+case "checkbox":
+_32=_33.IsValidRadioList(_30,min,max,_31);
+break;
+case "select-multiple":
+_32=_33.IsValidSelectMultipleList(_30,min,max,_31);
+break;
+}
+var _34=this.attr.elementcssclass;
+if(isString(_34)&&_34.length>0){
+map(_30,function(_35){
+condClass(_35,_34,!_32);
+});
+}
+if(undef(this.observingRequiredList)){
+Event.observe(_30,"change",this.validate.bind(this));
+this.observingRequiredList=true;
+}
+return _32;
+};
+Prado.Validation.TRequiredListValidator.IsValidRadioList=function(_36,min,max,_37){
+var _38=0;
+var _39=new Array();
+for(var i=0;i<_36.length;i++){
+if(_36[i].checked){
+_38++;
+_39.push(_36[i].value);
+}
+}
+return Prado.Validation.TRequiredListValidator.IsValidList(_38,_39,min,max,_37);
+};
+Prado.Validation.TRequiredListValidator.IsValidSelectMultipleList=function(_41,min,max,_42){
+var _43=0;
+var _44=new Array();
+for(var i=0;i<_41.length;i++){
+var _45=_41[i];
+for(var j=0;j<_45.options.length;j++){
+if(_45.options[j].selected){
+_43++;
+_44.push(_45.options[j].value);
+}
+}
+}
+return Prado.Validation.TRequiredListValidator.IsValidList(_43,_44,min,max,_42);
+};
+Prado.Validation.TRequiredListValidator.IsValidList=function(_47,_48,min,max,_49){
+var _50=true;
+if(_49.length>0){
+if(_48.length<_49.length){
+return false;
+}
+for(var k=0;k<_49.length;k++){
+_50=_50&&_48.contains(_49[k]);
+}
+}
+return _50&&_47>=min&&_47<=max;
+};
+
diff --git a/framework/Web/UI/TClientScriptManager.php b/framework/Web/UI/TClientScriptManager.php
index cc5289c5..ca28751f 100644
--- a/framework/Web/UI/TClientScriptManager.php
+++ b/framework/Web/UI/TClientScriptManager.php
@@ -1,457 +1,637 @@
-<?php
-
-class TPostBackOptions extends TComponent
-{
- public $_actionUrl='';
- public $_autoPostBack=false;
- public $_clientSubmit=true;
- public $_performValidation=false;
- public $_validationGroup='';
- public $_trackFocus=false;
-
- public function getActionUrl()
- {
- return $this->_actionUrl;
- }
-
- public function setActionUrl($value)
- {
- $this->_actionUrl=THttpUtility::quoteJavaScriptString($value);
- }
-
- public function getAutoPostBack()
- {
- return $this->_autoPostBack;
- }
-
- public function setAutoPostBack($value)
- {
- $this->_autoPostBack=$value;
- }
-
- public function getClientSubmit()
- {
- return $this->_clientSubmit;
- }
-
- public function setClientSubmit($value)
- {
- $this->_clientSubmit=$value;
- }
-
- public function getPerformValidation()
- {
- return $this->_performValidation;
- }
-
- public function setPerformValidation($value)
- {
- $this->_performValidation=$value;
- }
-
- public function getValidationGroup()
- {
- return $this->_validationGroup;
- }
-
- public function setValidationGroup($value)
- {
- $this->_validationGroup=$value;
- }
-
- public function getTrackFocus()
- {
- return $this->_trackFocus;
- }
-
- public function setTrackFocus($value)
- {
- $this->_trackFocus=$value;
- }
-}
-
-class TClientScriptManager extends TComponent
-{
- const SCRIPT_DIR='Web/Javascripts/js';
- const POSTBACK_FUNC='Prado.doPostBack';
- private $_page;
- private $_hiddenFields=array();
- private $_beginScripts=array();
- private $_endScripts=array();
- private $_scriptFiles=array();
- private $_headScriptFiles=array();
- private $_headScripts=array();
- private $_styleSheetFiles=array();
- private $_styleSheets=array();
- private $_onSubmitStatements=array();
- private $_arrayDeclares=array();
- private $_expandoAttributes=array();
- private $_postBackScriptRegistered=false;
- private $_focusScriptRegistered=false;
- private $_scrollScriptRegistered=false;
- private $_publishedScriptFiles=array();
-
- public function __construct(TPage $owner)
- {
- $this->_page=$owner;
- }
-
- public function getPostBackEventReference($control,$parameter='',$options=null,$javascriptPrefix=true)
- {
- if(!$options || (!$options->getPerformValidation() && !$options->getTrackFocus() && $options->getClientSubmit() && $options->getActionUrl()==''))
- {
- $this->registerPostBackScript();
- if(($form=$this->_page->getForm())!==null)
- $formID=$form->getClientID();
- else
- throw new TInvalidConfigurationException('clientscriptmanager_form_required');
- $postback=self::POSTBACK_FUNC.'(\''.$formID.'\',\''.$control->getUniqueID().'\',\''.THttpUtility::quoteJavaScriptString($parameter).'\')';
- if($options && $options->getAutoPostBack())
- $postback='setTimeout(\''.THttpUtility::quoteJavaScriptString($postback).'\',0)';
- return $javascriptPrefix?'javascript:'.$postback:$postback;
- }
- $opt='';
- $flag=false;
- if($options->getPerformValidation())
- {
- $flag=true;
- $this->registerValidationScript();
- $opt.=',true,';
- }
- else
- $opt.=',false,';
- if($options->getValidationGroup()!=='')
- {
- $flag=true;
- $opt.='"'.$options->getValidationGroup().'",';
- }
- else
- $opt.='\'\',';
- if($options->getActionUrl()!=='')
- {
- $flag=true;
- $this->_page->setCrossPagePostBack(true);
- $opt.='"'.$options->getActionUrl().'",';
- }
- else
- $opt.='null,';
- if($options->getTrackFocus())
- {
- $flag=true;
- $this->registerFocusScript();
- $opt.='true,';
- }
- else
- $opt.='false,';
- if($options->getClientSubmit())
- {
- $flag=true;
- $opt.='true';
- }
- else
- $opt.='false';
- if(!$flag)
- return '';
- $this->registerPostBackScript();
- if(($form=$this->_page->getForm())!==null)
- $formID=$form->getClientID();
- else
- throw new TInvalidConfigurationException('clientscriptmanager_form_required');
- $postback=self::POSTBACK_FUNC.'(\''.$formID.'\',\''.$control->getUniqueID().'\',\''.THttpUtility::quoteJavaScriptString($parameter).'\''.$opt.')';
- if($options && $options->getAutoPostBack())
- $postback='setTimeout(\''.THttpUtility::quoteJavaScriptString($postback).'\',0)';
- return $javascriptPrefix?'javascript:'.$postback:$postback;
- }
-
- public function registerPradoScript($scriptFile)
- {
- if(isset($this->_publishedScriptFiles[$scriptFile]))
- $url=$this->_publishedScriptFiles[$scriptFile];
- else
- {
- $url=$this->_page->getService()->getAssetManager()->publishFilePath(Prado::getFrameworkPath().'/'.self::SCRIPT_DIR.'/'.$scriptFile);
- $this->_publishedScriptFiles[$scriptFile]=$url;
- $this->registerScriptFile('prado:'.$scriptFile,$url);
- }
- return $url;
- }
-
- protected function registerPostBackScript()
- {
- if(!$this->_postBackScriptRegistered)
- {
- $this->_postBackScriptRegistered=true;
- $this->registerHiddenField(TPage::FIELD_POSTBACK_TARGET,'');
- $this->registerHiddenField(TPage::FIELD_POSTBACK_PARAMETER,'');
- $this->registerPradoScript('base.js');
- }
- }
-
- public function registerFocusScript($target)
- {
- if(!$this->_focusScriptRegistered)
- {
- $this->_focusScriptRegistered=true;
- $this->registerPradoScript('base.js');
- $this->registerEndScript('prado:focus','Prado.Focus.setFocus("'.THttpUtility::quoteJavaScriptString($target).'");');
- }
- }
-
- public function registerScrollScript($x,$y)
- {
- if(!$this->_scrollScriptRegistered)
- {
- $this->_scrollScriptRegistered=true;
- $this->registerHiddenField(TPage::FIELD_SCROLL_X,$x);
- $this->registerHiddenField(TPage::FIELD_SCROLL_Y,$y);
- // TBD, need scroll.js
- }
- }
-
- public function registerDefaultButtonScript($button)
- {
- $this->registerPradoScript('base.js');
- return 'return Prado.Button.fireButton(event,\''.$button->getClientID().'\')';
- }
-
- public function registerValidationScript()
- {
- }
-
- public function isHiddenFieldRegistered($key)
- {
- return isset($this->_hiddenFields[$key]);
- }
-
- public function isScriptRegistered($key)
- {
- return isset($this->_scripts[$key]);
- }
-
- public function isScriptFileRegistered($key)
- {
- return isset($this->_scriptFiles[$key]);
- }
-
- public function isBeginScriptRegistered($key)
- {
- return isset($this->_beginScripts[$key]);
- }
-
- public function isEndScriptRegistered($key)
- {
- return isset($this->_endScripts[$key]);
- }
-
- public function isHeadScriptFileRegistered($key)
- {
- return isset($this->_headScriptFiles[$key]);
- }
-
- public function isHeadScriptRegistered($key)
- {
- return isset($this->_headScripts[$key]);
- }
-
- public function isStyleSheetFileRegistered($key)
- {
- return isset($this->_styleSheetFiles[$key]);
- }
-
- public function isStyleSheetRegistered($key)
- {
- return isset($this->_styleSheets[$key]);
- }
-
- public function isOnSubmitStatementRegistered($key)
- {
- return isset($this->_onSubmitStatements[$key]);
- }
-
- public function registerArrayDeclaration($name,$value)
- {
- $this->_arrayDeclares[$name][]=$value;
- }
-
- public function registerScriptFile($key,$url)
- {
- $this->_scriptFiles[$key]=$url;
- }
-
- public function registerHiddenField($name,$value)
- {
- // if the named hidden field exists and has a value null, it means the hidden field is rendered already
- if(!isset($this->_hiddenFields[$name]) || $this->_hiddenFields[$name]!==null)
- $this->_hiddenFields[$name]=$value;
- }
-
- public function registerOnSubmitStatement($key,$script)
- {
- $this->_onSubmitStatements[$key]=$script;
- }
-
- public function registerBeginScript($key,$script)
- {
- $this->_beginScripts[$key]=$script;
- }
-
- public function registerEndScript($key,$script)
- {
- $this->_endScripts[$key]=$script;
- }
-
- public function registerHeadScriptFile($key,$url)
- {
- $this->_headScriptFiles[$key]=$url;
- }
-
- public function registerHeadScript($key,$script)
- {
- $this->_headScripts[$key]=$script;
- }
-
- public function registerStyleSheetFile($key,$url)
- {
- $this->_styleSheetFiles[$key]=$url;
- }
-
- public function registerStyleSheet($key,$css)
- {
- $this->_styleSheets[$key]=$css;
- }
-
- public function registerExpandoAttribute($controlID,$name,$value)
- {
- $this->_expandoAttributes[$controlID][$name]=$value;
- }
-
- public function renderArrayDeclarations($writer)
- {
- if(count($this->_arrayDeclares))
- {
- $str="<script type=\"text/javascript\">\n//<![CDATA[\n";
- foreach($this->_arrayDeclares as $name=>$array)
- $str.="var $name=new Array(".implode(',',$array).");\n";
- $str.="\n//]]>\n</script>\n";
- $writer->write($str);
- }
- }
-
- public function renderScriptFiles($writer)
- {
- $str='';
- foreach($this->_scriptFiles as $include)
- $str.="<script type=\"text/javascript\" src=\"".THttpUtility::htmlEncode($include)."\"></script>\n";
- $writer->write($str);
- }
-
- public function renderOnSubmitStatements($writer)
- {
- // ???
- }
-
- public function renderBeginScripts($writer)
- {
- if(count($this->_beginScripts))
- $writer->write("<script type=\"text/javascript\">\n//<![CDATA[\n".implode("\n",$this->_beginScripts)."\n//]]>\n</script>\n");
- }
-
- public function renderEndScripts($writer)
- {
- if(count($this->_endScripts))
- $writer->write("<script type=\"text/javascript\">\n//<![CDATA[\n".implode("\n",$this->_endScripts)."\n//]]>\n</script>\n");
- }
-
- public function renderHiddenFields($writer)
- {
- $str='';
- foreach($this->_hiddenFields as $name=>$value)
- {
- if($value!==null)
- {
- $value=THttpUtility::htmlEncode($value);
- $str.="<input type=\"hidden\" name=\"$name\" id=\"$name\" value=\"$value\" />\n";
- // set hidden field value to null to indicate this field is rendered
- // Note, hidden field rendering is invoked twice (at the beginning and ending of TForm)
- $this->_hiddenFields[$name]=null;
- }
- }
- if($str!=='')
- $writer->write("<div>\n".$str."</div>\n");
- }
-
- public function renderExpandoAttributes($writer)
- {
- if(count($this->_expandoAttributes))
- {
- $str="<script type=\"text/javascript\">\n//<![CDATA[\n";
- foreach($this->_expandoAttributes as $controlID=>$attrs)
- {
- $str.="var $controlID = document.all ? document.all[\"$controlID\"] : document.getElementById(\"$controlID\");\n";
- foreach($attrs as $name=>$value)
- {
- if($value===null)
- $str.="{$key}[\"$name\"]=null;\n";
- else
- $str.="{$key}[\"$name\"]=\"$value\";\n";
- }
- }
- $str.="\n//]]>\n</script>\n";
- $writer->write($str);
- }
- }
-
- public function renderHeadScriptFiles($writer)
- {
- $str='';
- foreach($this->_headScriptFiles as $url)
- $str.="<script type=\"text/javascript\" src=\"".THttpUtility::htmlEncode($url)."\"></script>\n";
- $writer->write($str);
- }
-
- public function renderHeadScripts($writer)
- {
- if(count($this->_headScripts))
- $writer->write("<script type=\"text/javascript\">\n//<![CDATA[\n".implode("\n",$this->_headScripts)."\n//]]>\n</script>\n");
- }
-
- public function renderStyleSheetFiles($writer)
- {
- $str='';
- foreach($this->_styleSheetFiles as $url)
- {
- $str.="<link rel=\"stylesheet\" type=\"text/css\" href=\"".THttpUtility::htmlEncode($url)."\" />\n";
- }
- $writer->write($str);
- }
-
- public function renderStyleSheets($writer)
- {
- if(count($this->_styleSheets))
- $writer->write("<style type=\"text/css\">\n".implode("\n",$this->_styleSheets)."\n</style>\n");
- }
-
- public function getHasHiddenFields()
- {
- return count($this->_hiddenFields)>0;
- }
-
- public function getHasSubmitStatements()
- {
- return count($this->_onSubmitStatements)>0;
- }
-
-
- /*
- private void EnsureEventValidationFieldLoaded();
- internal string GetEventValidationFieldValue();
- public string GetWebResourceUrl(Type type, string resourceName);
- public void RegisterClientScriptResource(Type type, string resourceName);
- internal void RegisterDefaultButtonScript(Control button, $writer, bool useAddAttribute);
- public function SaveEventValidationField();
- public void ValidateEvent(string uniqueId, string argument);
- public function getCallbackEventReference()
- */
-}
-
+<?php
+
+class TPostBackOptions extends TComponent
+{
+ public $_actionUrl='';
+ public $_autoPostBack=false;
+ public $_clientSubmit=true;
+ public $_performValidation=false;
+ public $_validationGroup='';
+ public $_trackFocus=false;
+
+ public function getActionUrl()
+ {
+ return $this->_actionUrl;
+ }
+
+ public function setActionUrl($value)
+ {
+ $this->_actionUrl=THttpUtility::quoteJavaScriptString($value);
+ }
+
+ public function getAutoPostBack()
+ {
+ return $this->_autoPostBack;
+ }
+
+ public function setAutoPostBack($value)
+ {
+ $this->_autoPostBack=$value;
+ }
+
+ public function getClientSubmit()
+ {
+ return $this->_clientSubmit;
+ }
+
+ public function setClientSubmit($value)
+ {
+ $this->_clientSubmit=$value;
+ }
+
+ public function getPerformValidation()
+ {
+ return $this->_performValidation;
+ }
+
+ public function setPerformValidation($value)
+ {
+ $this->_performValidation=$value;
+ }
+
+ public function getValidationGroup()
+ {
+ return $this->_validationGroup;
+ }
+
+ public function setValidationGroup($value)
+ {
+ $this->_validationGroup=$value;
+ }
+
+ public function getTrackFocus()
+ {
+ return $this->_trackFocus;
+ }
+
+ public function setTrackFocus($value)
+ {
+ $this->_trackFocus=$value;
+ }
+}
+
+class TClientScriptManager extends TComponent
+{
+ const SCRIPT_DIR='Web/Javascripts/js';
+ const POSTBACK_FUNC='Prado.doPostBack';
+ private $_page;
+ private $_hiddenFields=array();
+ private $_beginScripts=array();
+ private $_endScripts=array();
+ private $_scriptFiles=array();
+ private $_headScriptFiles=array();
+ private $_headScripts=array();
+ private $_styleSheetFiles=array();
+ private $_styleSheets=array();
+ private $_onSubmitStatements=array();
+ private $_arrayDeclares=array();
+ private $_expandoAttributes=array();
+ private $_postBackScriptRegistered=false;
+ private $_focusScriptRegistered=false;
+ private $_scrollScriptRegistered=false;
+ private $_publishedScriptFiles=array();
+
+ public function __construct(TPage $owner)
+ {
+ $this->_page=$owner;
+ }
+
+ public function getPostBackEventReference($control,$parameter='',$options=null,$javascriptPrefix=true)
+ {
+ if(!$options || (!$options->getPerformValidation() && !$options->getTrackFocus() && $options->getClientSubmit() && $options->getActionUrl()==''))
+ {
+ $this->registerPostBackScript();
+ if(($form=$this->_page->getForm())!==null)
+ $formID=$form->getClientID();
+ else
+ throw new TInvalidConfigurationException('clientscriptmanager_form_required');
+ $postback=self::POSTBACK_FUNC.'(\''.$formID.'\',\''.$control->getUniqueID().'\',\''.THttpUtility::quoteJavaScriptString($parameter).'\')';
+ if($options && $options->getAutoPostBack())
+ $postback='setTimeout(\''.THttpUtility::quoteJavaScriptString($postback).'\',0)';
+ return $javascriptPrefix?'javascript:'.$postback:$postback;
+ }
+ $opt='';
+ $flag=false;
+ if($options->getPerformValidation())
+ {
+ $flag=true;
+ $this->registerValidationScript();
+ $opt.=',true,';
+ }
+ else
+ $opt.=',false,';
+ if($options->getValidationGroup()!=='')
+ {
+ $flag=true;
+ $opt.='"'.$options->getValidationGroup().'",';
+ }
+ else
+ $opt.='\'\',';
+ if($options->getActionUrl()!=='')
+ {
+ $flag=true;
+ $this->_page->setCrossPagePostBack(true);
+ $opt.='"'.$options->getActionUrl().'",';
+ }
+ else
+ $opt.='null,';
+ if($options->getTrackFocus())
+ {
+ $flag=true;
+ $this->registerFocusScript();
+ $opt.='true,';
+ }
+ else
+ $opt.='false,';
+ if($options->getClientSubmit())
+ {
+ $flag=true;
+ $opt.='true';
+ }
+ else
+ $opt.='false';
+ if(!$flag)
+ return '';
+ $this->registerPostBackScript();
+ if(($form=$this->_page->getForm())!==null)
+ $formID=$form->getClientID();
+ else
+ throw new TInvalidConfigurationException('clientscriptmanager_form_required');
+ $postback=self::POSTBACK_FUNC.'(\''.$formID.'\',\''.$control->getUniqueID().'\',\''.THttpUtility::quoteJavaScriptString($parameter).'\''.$opt.')';
+ if($options && $options->getAutoPostBack())
+ $postback='setTimeout(\''.THttpUtility::quoteJavaScriptString($postback).'\',0)';
+ return $javascriptPrefix?'javascript:'.$postback:$postback;
+ }
+
+ public function registerPradoScript($script)
+ {
+ foreach(TPradoClientScript::getScript($script) as $scriptFile)
+ {
+ if(isset($this->_publishedScriptFiles[$scriptFile]))
+ $url=$this->_publishedScriptFiles[$scriptFile];
+ else
+ {
+ $url=$this->_page->getService()->getAssetManager()->publishFilePath(Prado::getFrameworkPath().'/'.self::SCRIPT_DIR.'/'.$scriptFile);
+ $this->_publishedScriptFiles[$scriptFile]=$url;
+ $this->registerScriptFile('prado:'.$scriptFile,$url);
+ }
+ }
+ //return $url;
+ }
+
+ protected function registerPostBackScript()
+ {
+ if(!$this->_postBackScriptRegistered)
+ {
+ $this->_postBackScriptRegistered=true;
+ $this->registerHiddenField(TPage::FIELD_POSTBACK_TARGET,'');
+ $this->registerHiddenField(TPage::FIELD_POSTBACK_PARAMETER,'');
+ $this->registerPradoScript('base');
+ }
+ }
+
+ public function registerFocusScript($target)
+ {
+ if(!$this->_focusScriptRegistered)
+ {
+ $this->_focusScriptRegistered=true;
+ $this->registerPradoScript('base');
+ $this->registerEndScript('prado:focus','Prado.Focus.setFocus("'.THttpUtility::quoteJavaScriptString($target).'");');
+ }
+ }
+
+ public function registerScrollScript($x,$y)
+ {
+ if(!$this->_scrollScriptRegistered)
+ {
+ $this->_scrollScriptRegistered=true;
+ $this->registerHiddenField(TPage::FIELD_SCROLL_X,$x);
+ $this->registerHiddenField(TPage::FIELD_SCROLL_Y,$y);
+ // TBD, need scroll.js
+ }
+ }
+
+ public function registerDefaultButtonScript($button)
+ {
+ $this->registerPradoScript('base');
+ return 'return Prado.Button.fireButton(event,\''.$button->getClientID().'\')';
+ }
+
+ public function registerValidationScript()
+ {
+ }
+
+ public function isHiddenFieldRegistered($key)
+ {
+ return isset($this->_hiddenFields[$key]);
+ }
+
+ public function isScriptRegistered($key)
+ {
+ return isset($this->_scripts[$key]);
+ }
+
+ public function isScriptFileRegistered($key)
+ {
+ return isset($this->_scriptFiles[$key]);
+ }
+
+ public function isBeginScriptRegistered($key)
+ {
+ return isset($this->_beginScripts[$key]);
+ }
+
+ public function isEndScriptRegistered($key)
+ {
+ return isset($this->_endScripts[$key]);
+ }
+
+ public function isHeadScriptFileRegistered($key)
+ {
+ return isset($this->_headScriptFiles[$key]);
+ }
+
+ public function isHeadScriptRegistered($key)
+ {
+ return isset($this->_headScripts[$key]);
+ }
+
+ public function isStyleSheetFileRegistered($key)
+ {
+ return isset($this->_styleSheetFiles[$key]);
+ }
+
+ public function isStyleSheetRegistered($key)
+ {
+ return isset($this->_styleSheets[$key]);
+ }
+
+ public function isOnSubmitStatementRegistered($key)
+ {
+ return isset($this->_onSubmitStatements[$key]);
+ }
+
+ public function registerArrayDeclaration($name,$value)
+ {
+ $this->_arrayDeclares[$name][]=$value;
+ }
+
+ public function registerScriptFile($key,$url)
+ {
+ $this->_scriptFiles[$key]=$url;
+ }
+
+ public function registerHiddenField($name,$value)
+ {
+ // if the named hidden field exists and has a value null, it means the hidden field is rendered already
+ if(!isset($this->_hiddenFields[$name]) || $this->_hiddenFields[$name]!==null)
+ $this->_hiddenFields[$name]=$value;
+ }
+
+ public function registerOnSubmitStatement($key,$script)
+ {
+ $this->_onSubmitStatements[$key]=$script;
+ }
+
+ public function registerBeginScript($key,$script)
+ {
+ $this->_beginScripts[$key]=$script;
+ }
+
+ public function registerEndScript($key,$script)
+ {
+ $this->_endScripts[$key]=$script;
+ }
+
+ public function registerHeadScriptFile($key,$url)
+ {
+ $this->_headScriptFiles[$key]=$url;
+ }
+
+ public function registerHeadScript($key,$script)
+ {
+ $this->_headScripts[$key]=$script;
+ }
+
+ public function registerStyleSheetFile($key,$url)
+ {
+ $this->_styleSheetFiles[$key]=$url;
+ }
+
+ public function registerStyleSheet($key,$css)
+ {
+ $this->_styleSheets[$key]=$css;
+ }
+
+ public function registerExpandoAttribute($controlID,$name,$value)
+ {
+ $this->_expandoAttributes[$controlID][$name]=$value;
+ }
+
+ public function renderArrayDeclarations($writer)
+ {
+ if(count($this->_arrayDeclares))
+ {
+ $str="<script type=\"text/javascript\">\n//<![CDATA[\n";
+ foreach($this->_arrayDeclares as $name=>$array)
+ $str.="var $name=new Array(".implode(',',$array).");\n";
+ $str.="\n//]]>\n</script>\n";
+ $writer->write($str);
+ }
+ }
+
+ public function renderScriptFiles($writer)
+ {
+ $str='';
+ foreach($this->_scriptFiles as $include)
+ $str.="<script type=\"text/javascript\" src=\"".THttpUtility::htmlEncode($include)."\"></script>\n";
+ $writer->write($str);
+ }
+
+ public function renderOnSubmitStatements($writer)
+ {
+ // ???
+ }
+
+ public function renderBeginScripts($writer)
+ {
+ if(count($this->_beginScripts))
+ $writer->write("<script type=\"text/javascript\">\n//<![CDATA[\n".implode("\n",$this->_beginScripts)."\n//]]>\n</script>\n");
+ }
+
+ public function renderEndScripts($writer)
+ {
+ if(count($this->_endScripts))
+ $writer->write("<script type=\"text/javascript\">\n//<![CDATA[\n".implode("\n",$this->_endScripts)."\n//]]>\n</script>\n");
+ }
+
+ public function renderHiddenFields($writer)
+ {
+ $str='';
+ foreach($this->_hiddenFields as $name=>$value)
+ {
+ if($value!==null)
+ {
+ $value=THttpUtility::htmlEncode($value);
+ $str.="<input type=\"hidden\" name=\"$name\" id=\"$name\" value=\"$value\" />\n";
+ // set hidden field value to null to indicate this field is rendered
+ // Note, hidden field rendering is invoked twice (at the beginning and ending of TForm)
+ $this->_hiddenFields[$name]=null;
+ }
+ }
+ if($str!=='')
+ $writer->write("<div>\n".$str."</div>\n");
+ }
+
+ public function renderExpandoAttributes($writer)
+ {
+ if(count($this->_expandoAttributes))
+ {
+ $str="<script type=\"text/javascript\">\n//<![CDATA[\n";
+ foreach($this->_expandoAttributes as $controlID=>$attrs)
+ {
+ $str.="var $controlID = document.all ? document.all[\"$controlID\"] : document.getElementById(\"$controlID\");\n";
+ foreach($attrs as $name=>$value)
+ {
+ if($value===null)
+ $str.="{$key}[\"$name\"]=null;\n";
+ else
+ $str.="{$key}[\"$name\"]=\"$value\";\n";
+ }
+ }
+ $str.="\n//]]>\n</script>\n";
+ $writer->write($str);
+ }
+ }
+
+ public function renderHeadScriptFiles($writer)
+ {
+ $str='';
+ foreach($this->_headScriptFiles as $url)
+ $str.="<script type=\"text/javascript\" src=\"".THttpUtility::htmlEncode($url)."\"></script>\n";
+ $writer->write($str);
+ }
+
+ public function renderHeadScripts($writer)
+ {
+ if(count($this->_headScripts))
+ $writer->write("<script type=\"text/javascript\">\n//<![CDATA[\n".implode("\n",$this->_headScripts)."\n//]]>\n</script>\n");
+ }
+
+ public function renderStyleSheetFiles($writer)
+ {
+ $str='';
+ foreach($this->_styleSheetFiles as $url)
+ {
+ $str.="<link rel=\"stylesheet\" type=\"text/css\" href=\"".THttpUtility::htmlEncode($url)."\" />\n";
+ }
+ $writer->write($str);
+ }
+
+ public function renderStyleSheets($writer)
+ {
+ if(count($this->_styleSheets))
+ $writer->write("<style type=\"text/css\">\n".implode("\n",$this->_styleSheets)."\n</style>\n");
+ }
+
+ public function getHasHiddenFields()
+ {
+ return count($this->_hiddenFields)>0;
+ }
+
+ public function getHasSubmitStatements()
+ {
+ return count($this->_onSubmitStatements)>0;
+ }
+
+
+ /*
+ private void EnsureEventValidationFieldLoaded();
+ internal string GetEventValidationFieldValue();
+ public string GetWebResourceUrl(Type type, string resourceName);
+ public void RegisterClientScriptResource(Type type, string resourceName);
+ internal void RegisterDefaultButtonScript(Control button, $writer, bool useAddAttribute);
+ public function SaveEventValidationField();
+ public void ValidateEvent(string uniqueId, string argument);
+ public function getCallbackEventReference()
+ */
+}
+
+/**
+ * TJavascript class file. Javascript utilties, converts basic PHP types into
+ * appropriate javascript types.
+ *
+ * Example:
+ * <code>
+ * $options['onLoading'] = "doit";
+ * $options['onComplete'] = "more";
+ * $js = TJavascript::toList($options);
+ * //expects the following javascript code
+ * // {'onLoading':'doit','onComplete':'more'}
+ * </code>
+ *
+ * Namespace: System.Web.UI
+ *
+ * @author Wei Zhuo<weizhuo[at]gmail[dot]com>
+ * @version $Revision: 1.3 $ $Date: 2005/11/10 23:43:26 $
+ * @package System.Web.UI
+ */
+class TJavascript
+{
+ /**
+ * Coverts PHP arrays (only the array values) into javascript array.
+ * @param array the array data to convert
+ * @param string append additional javascript array data
+ * @param boolean if true empty string and empty array will be converted
+ * @return string javascript array as string.
+ */
+ public static function toArray($array,$append=null,$strict=false)
+ {
+ $results = array();
+ $converter = new TJavascript();
+ foreach($array as $v)
+ {
+ if($strict || (!$strict && $v !== '' && $v !== array()))
+ {
+ $type = 'to_'.gettype($v);
+ if($type == 'to_array')
+ $results[] = $converter->toArray($v, $append, $strict);
+ else
+ $results[] = $converter->{$type}($v);
+ }
+ }
+ $extra = '';
+ if(strlen($append) > 0)
+ $extra .= count($results) > 0 ? ','.$append : $append;
+ return '['.implode(',', $results).$extra.']';
+ }
+
+ /**
+ * Coverts PHP arrays (both key and value) into javascript objects.
+ * @param array the array data to convert
+ * @param string append additional javascript object data
+ * @param boolean if true empty string and empty array will be converted
+ * @return string javascript object as string.
+ */
+ public static function toList($array,$append=null, $strict=false)
+ {
+ $results = array();
+ $converter = new TJavascript();
+ foreach($array as $k => $v)
+ {
+ if($strict || (!$strict && $v !== '' && $v !== array()))
+ {
+ $type = 'to_'.gettype($v);
+ if($type == 'to_array')
+ $results[] = "'{$k}':".$converter->toList($v, $append, $strict);
+ else
+ $results[] = "'{$k}':".$converter->{$type}($v);
+ }
+ }
+ $extra = '';
+ if(strlen($append) > 0)
+ $extra .= count($results) > 0 ? ','.$append : $append;
+
+ return '{'.implode(',', $results).$extra.'}';
+ }
+
+ public function to_boolean($v)
+ {
+ return $v ? 'true' : 'false';
+ }
+
+ public function to_integer($v)
+ {
+ return "{$v}";
+ }
+
+ public function to_double($v)
+ {
+ return "{$v}";
+ }
+
+ /**
+ * If string begins with [ and ends ], or begins with { and ends }
+ * it is assumed to be javascript arrays or objects and no further
+ * conversion is applied.
+ */
+ public function to_string($v)
+ {
+ if(strlen($v)>1)
+ {
+ $first = $v{0}; $last = $v{strlen($v)-1};
+ if($first == '[' && $last == ']' ||
+ ($first == '{' && $last == '}'))
+ return $v;
+ }
+ return "'".addslashes($v)."'";
+ }
+
+ public function to_array($v)
+ {
+ return TJavascript::toArray($v);
+ }
+
+ public function to_null($v)
+ {
+ return 'null';
+ }
+}
+
+/**
+ * PradoClientScript class.
+ *
+ * Resolves Prado client script dependencies. e.g. TPradoClientScript::getScripts("dom");
+ *
+ * - <b>base</b> basic javascript utilities, e.g. $()
+ * - <b>dom</b> DOM and Form functions, e.g. $F(inputID) to retrive form input values.
+ * - <b>effects</b> Effects such as fade, shake, move
+ * - <b>controls</b> Prado client-side components, e.g. Slider, AJAX components
+ * - <b>validator</b> Prado client-side validators.
+ * - <b>ajax</b> Prado AJAX library including Prototype's AJAX and JSON.
+ *
+ * Dependencies for each library are automatically resolved.
+ *
+ * Namespace: System.Web.UI
+ *
+ * @author Wei Zhuo<weizhuo[at]gmail[dot]com>
+ * @version $Revision: 1.1 $ $Date: 2005/11/06 23:02:33 $
+ * @package System.Web.UI
+ */
+class TPradoClientScript
+{
+ /**
+ * Client-side javascript library dependencies
+ * @var array
+ */
+ protected static $dependencies = array(
+ 'base' => array('base'),
+ 'dom' => array('base', 'dom'),
+ 'effects' => array('base', 'dom', 'effects'),
+ 'controls' => array('base', 'dom', 'effects', 'controls'),
+ 'validator' => array('base', 'dom', 'validator'),
+ 'logger' => array('base', 'dom', 'logger'),
+ 'ajax' => array('base', 'dom', 'ajax')
+ );
+
+ /**
+ * Resolve dependencies for the given library.
+ * @param array list of libraries to load.
+ * @return array list of libraries including its dependencies.
+ */
+ protected static function getScripts($scripts)
+ {
+ $files = array();
+ if(!is_array($scripts)) $scripts = array($scripts);
+ foreach($scripts as $script)
+ {
+ if(isset(self::$dependencies[$script]))
+ $files = array_merge($files, self::$dependencies[$script]);
+ $files[] = $script;
+ }
+ $files = array_unique($files);
+ return $files;
+ }
+}
+
?> \ No newline at end of file
diff --git a/framework/Web/UI/WebControls/TBaseValidator.php b/framework/Web/UI/WebControls/TBaseValidator.php
index f4627986..ab314087 100644
--- a/framework/Web/UI/WebControls/TBaseValidator.php
+++ b/framework/Web/UI/WebControls/TBaseValidator.php
@@ -1,302 +1,354 @@
-<?php
-/**
- * TBaseValidator class file
- *
- * @author Qiang Xue <qiang.xue@gmail.com>
- * @link http://www.pradosoft.com/
- * @copyright Copyright &copy; 2005 PradoSoft
- * @license http://www.pradosoft.com/license/
- * @version $Revision: $ $Date: $
- * @package System.Web.UI.WebControls
- */
-
-/**
- * TBaseValidator class
- *
- * TBaseValidator serves as the base class for validator controls.
- *
- * Validation is performed when a button control, such a TButton, a TLinkButton
- * or a TImageButton is clicked and the <b>CausesValidation</b> of these controls is true.
- * You can also manually perform validation by using the validate() method of the TPage class.
- *
- * Validator controls always validate the associated input control on the server.
- * TValidation controls also have complete client-side implementation that allow
- * DHTML supported browsers to perform validation on the client via Javascript.
- * Client-side validation will validate user input before it is sent to the server.
- * The form data will not be submitted if any error is detected. This avoids
- * the round-trip of information necessary for server-side validation.
- *
- * You can use multiple validator controls to validate an individual input control,
- * each responsible for validating different criteria. For example, on a user registration
- * form, you may want to make sure the user enters a value in the username text box,
- * and the input must consist of only word characters. You can use a TRequiredFieldValidator
- * to ensure the input of username and a TRegularExpressionValidator to ensure the proper
- * input.
- *
- * If an input control fails validation, the text specified by the <b>ErrorMessage</b>
- * property is displayed in the validation control. If the <b>Text</b> property is set
- * it will be displayed instead, however. If both <b>ErrorMessage</b> and <b>Text</b>
- * are empty, the body content of the validator will be displayed.
- *
- * You can also place a <b>TValidationSummary</b> control on the page to display error messages
- * from the validators together. In this case, only the <b>ErrorMessage</b> property of the
- * validators will be displayed in the TValidationSummary control.
- *
- * Note, the <b>IsValid</b> property of the current TPage instance will be automatically
- * updated by the validation process which occurs after <b>OnLoad</b> of TPage and
- * before the postback events. Therefore, if you use the <b>IsValid</b>
- * property in the <b>OnLoad</b> event of TPage, you must first explicitly call
- * the validate() method of TPage. As an alternative, you can place your code
- * in the postback event handler, such as <b>OnClick</b> or <b>OnCommand</b>,
- * instead of <b>OnLoad</b> event.
- *
- * Note, to use validators derived from this control, you have to
- * copy the file "<framework>/js/prado_validator.js" to the "js" directory
- * which should be under the directory containing the entry script file.
- *
- * <b>Notes to Inheritors</b> When you inherit from the TBaseValidator class,
- * you must override the method {@link evaluateIsValid}.
- *
- * Namespace: System.Web.UI.WebControls
- *
- * Properties
- * - <b>EnableClientScript</b>, boolean, default=true, kept in viewstate
- * <br>Gets or sets a value indicating whether client-side validation is enabled.
- * - <b>Display</b>, string, default=Static, kept in viewstate
- * <br>Gets or sets the display behavior (None, Static, Dynamic) of the error message in a validation control.
- * - <b>ControlToValidate</b>, string, kept in viewstate
- * <br>Gets or sets the input control to validate. This property must be set to
- * the ID path of an input control. The ID path is the dot-connected IDs of
- * the controls reaching from the validator's parent control to the target control.
- * For example, if HomePage is the parent of Validator and SideBar controls, and
- * SideBar is the parent of UserName control, then the ID path for UserName
- * would be "SideBar.UserName" if UserName is to be validated by Validator.
- * - <b>Text</b>, string, kept in viewstate
- * <br>Gets or sets the text of TBaseValidator control.
- * - <b>ErrorMessage</b>, string, kept in viewstate
- * <br>Gets or sets the text for the error message.
- * - <b>EncodeText</b>, boolean, default=true, kept in viewstate
- * <br>Gets or sets the value indicating whether Text and ErrorMessage should be HTML-encoded when rendering.
- * - <b>IsValid</b>, boolean, default=true
- * <br>Gets or sets a value that indicates whether the associated input control passes validation.
- *
- * @author Qiang Xue <qiang.xue@gmail.com>
- * @version $Revision: $ $Date: $
- * @package System.Web.UI.WebControls
- * @since 3.0
- */
-abstract class TBaseValidator extends TLabel implements IValidator
-{
- /**
- * whether the validation succeeds
- * @var boolean
- */
- private $_isValid=true;
-
- public function __construct()
- {
- parent::__construct();
- $this->setForeColor('red');
- }
-
- /**
- * Adds attributes to renderer.
- * @param THtmlWriter the renderer
- */
- protected function addAttributesToRender($writer)
- {
- }
-
- /**
- * This method overrides the parent implementation to forbid setting AssociatedControlID.
- * @param string the associated control ID
- * @throws TNotSupportedException whenever this method is called
- */
- public function setAssociatedControlID($value)
- {
- throw new TNotSupportedException('basevalidator_associatedcontrolid_unsupported',get_class($this));
- }
-
- /**
- * This method overrides parent's implementation by setting {@link setIsValid IsValid} to true if disabled.
- * @param boolean whether the validator is enabled.
- */
- public function setEnabled($value)
- {
- $value=TPropertyValue::ensureBoolean($value);
- parent::setEnabled($value);
- if(!$value)
- $this->_isValid=true;
- }
-
- /**
- * @return string the display behavior (None, Static, Dynamic) of the error message in a validation control. Defaults to Static.
- */
- public function getDisplay()
- {
- return $this->getViewState('Display','Static');
- }
-
- /**
- * Sets the display behavior (None, Static, Dynamic) of the error message in a validation control.
- * @param string the display behavior (None, Static, Dynamic)
- */
- public function setDisplay($value)
- {
- $this->setViewState('Display',TPropertyValue::ensureEnum($value,array('None','Static','Dynamic')),'Static');
- }
-
- /**
- * @return boolean whether client-side validation is enabled.
- */
- public function getEnableClientScript()
- {
- return $this->getViewState('EnableClientScript',true);
- }
-
- /**
- * Sets the value indicating whether client-side validation is enabled.
- * @param boolean whether client-side validation is enabled.
- */
- public function setEnableClientScript($value)
- {
- $this->setViewState('EnableClientScript',TPropertyValue::ensureBoolean($value),true);
- }
-
- /**
- * @return string the text for the error message.
- */
- public function getErrorMessage()
- {
- return $this->getViewState('ErrorMessage','');
- }
-
- /**
- * Sets the text for the error message.
- * @param string the error message
- */
- public function setErrorMessage($value)
- {
- $this->setViewState('ErrorMessage',$value,'');
- }
-
- /**
- * @return string the ID path of the input control to validate
- */
- public function getControlToValidate()
- {
- return $this->getViewState('ControlToValidate','');
- }
-
- /**
- * Sets the ID path of the input control to validate
- * @param string the ID path
- */
- public function setControlToValidate($value)
- {
- $this->setViewState('ControlToValidate',$value,'');
- }
-
- /**
- * @return boolean whether to set focus at the validating place if the validation fails. Defaults to true.
- */
- public function getFocusOnError()
- {
- return $this->getViewState('FocusOnError',true);
- }
-
- /**
- * @param boolean whether to set focus at the validating place if the validation fails
- */
- public function setFocusOnError($value)
- {
- $this->setViewState('FocusOnError',TPropertyValue::ensureBoolean($value),true);
- }
-
- /**
- * Gets the ID of the HTML element that will receive focus if validation fails and {@link getFocusOnError FocusOnError} is true.
- * Defaults to the client ID of the {@link getControlToValidate ControlToValidate}.
- * @return string the ID of the HTML element to receive focus
- */
- public function getFocusElementID()
- {
- // TODO: identify the ControlToValidate
- return $this->getViewState('FocusElementID', '');
- }
-
- /**
- * Sets the ID of the HTML element that will receive focus if validation fails and {@link getFocusOnError FocusOnError} is true.
- * @param string the ID of the HTML element to receive focus
- */
- public function setFocusElementID($value)
- {
- $this->setViewState('FocusElementID', $value, '');
- }
-
- /**
- * @return string the group which this validator belongs to
- */
- public function getValidationGroup()
- {
- return $this->getViewState('ValidationGroup','');
- }
-
- /**
- * @param string the group which this validator belongs to
- */
- public function setValidationGroup($value)
- {
- $this->setViewState('ValidationGroup',$value,'');
- }
-
- /**
- * @return boolean whether the validation succeeds
- */
- public function getIsValid()
- {
- return $this->_isValid;
- }
-
- /**
- * Sets the value indicating whether the validation succeeds
- * @param boolean whether the validation succeeds
- */
- public function setIsValid($value)
- {
- $this->_isValid=TPropertyValue::ensureBoolean($value);
- }
-
- /**
- * Validates the specified control.
- * Do not override this method. Override {@link evaluateIsValid} instead.
- * @return boolean whether the validation succeeds
- */
- public function validate()
- {
- $this->setIsValid(true);
- if($this->getVisible(true) && $this->getEnabled())
- {
- $valid=$this->evaluateIsValid();
- $this->setValid($valid);
- }
- if($this->isVisible() && $this->isEnabled() && strlen($this->getControlToValidate()))
- {
- $valid=$this->evaluateIsValid();
- $this->setValid($valid);
- return $valid;
- }
- else
- {
- $this->setValid(true);
- return true;
- }
- }
-
- /**
- * This is the major method for validation.
- * Derived classes should implement this method to provide customized validation.
- * @return boolean whether the validation succeeds
- */
- abstract protected function evaluateIsValid();
-}
+<?php
+/**
+ * TBaseValidator class file
+ *
+ * @author Qiang Xue <qiang.xue@gmail.com>
+ * @link http://www.pradosoft.com/
+ * @copyright Copyright &copy; 2005 PradoSoft
+ * @license http://www.pradosoft.com/license/
+ * @version $Revision: $ $Date: $
+ * @package System.Web.UI.WebControls
+ */
+
+/**
+ * TBaseValidator class
+ *
+ * TBaseValidator serves as the base class for validator controls.
+ *
+ * Validation is performed when a button control, such a TButton, a TLinkButton
+ * or a TImageButton is clicked and the <b>CausesValidation</b> of these controls is true.
+ * You can also manually perform validation by using the validate() method of the TPage class.
+ *
+ * Validator controls always validate the associated input control on the server.
+ * TValidation controls also have complete client-side implementation that allow
+ * DHTML supported browsers to perform validation on the client via Javascript.
+ * Client-side validation will validate user input before it is sent to the server.
+ * The form data will not be submitted if any error is detected. This avoids
+ * the round-trip of information necessary for server-side validation.
+ *
+ * You can use multiple validator controls to validate an individual input control,
+ * each responsible for validating different criteria. For example, on a user registration
+ * form, you may want to make sure the user enters a value in the username text box,
+ * and the input must consist of only word characters. You can use a TRequiredFieldValidator
+ * to ensure the input of username and a TRegularExpressionValidator to ensure the proper
+ * input.
+ *
+ * If an input control fails validation, the text specified by the <b>ErrorMessage</b>
+ * property is displayed in the validation control. If the <b>Text</b> property is set
+ * it will be displayed instead, however. If both <b>ErrorMessage</b> and <b>Text</b>
+ * are empty, the body content of the validator will be displayed.
+ *
+ * You can also place a <b>TValidationSummary</b> control on the page to display error messages
+ * from the validators together. In this case, only the <b>ErrorMessage</b> property of the
+ * validators will be displayed in the TValidationSummary control.
+ *
+ * Note, the <b>IsValid</b> property of the current TPage instance will be automatically
+ * updated by the validation process which occurs after <b>OnLoad</b> of TPage and
+ * before the postback events. Therefore, if you use the <b>IsValid</b>
+ * property in the <b>OnLoad</b> event of TPage, you must first explicitly call
+ * the validate() method of TPage. As an alternative, you can place your code
+ * in the postback event handler, such as <b>OnClick</b> or <b>OnCommand</b>,
+ * instead of <b>OnLoad</b> event.
+ *
+ * Note, to use validators derived from this control, you have to
+ * copy the file "<framework>/js/prado_validator.js" to the "js" directory
+ * which should be under the directory containing the entry script file.
+ *
+ * <b>Notes to Inheritors</b> When you inherit from the TBaseValidator class,
+ * you must override the method {@link evaluateIsValid}.
+ *
+ * Namespace: System.Web.UI.WebControls
+ *
+ * Properties
+ * - <b>EnableClientScript</b>, boolean, default=true, kept in viewstate
+ * <br>Gets or sets a value indicating whether client-side validation is enabled.
+ * - <b>Display</b>, string, default=Static, kept in viewstate
+ * <br>Gets or sets the display behavior (None, Static, Dynamic) of the error message in a validation control.
+ * - <b>ControlToValidate</b>, string, kept in viewstate
+ * <br>Gets or sets the input control to validate. This property must be set to
+ * the ID path of an input control. The ID path is the dot-connected IDs of
+ * the controls reaching from the validator's parent control to the target control.
+ * For example, if HomePage is the parent of Validator and SideBar controls, and
+ * SideBar is the parent of UserName control, then the ID path for UserName
+ * would be "SideBar.UserName" if UserName is to be validated by Validator.
+ * - <b>Text</b>, string, kept in viewstate
+ * <br>Gets or sets the text of TBaseValidator control.
+ * - <b>ErrorMessage</b>, string, kept in viewstate
+ * <br>Gets or sets the text for the error message.
+ * - <b>EncodeText</b>, boolean, default=true, kept in viewstate
+ * <br>Gets or sets the value indicating whether Text and ErrorMessage should be HTML-encoded when rendering.
+ * - <b>IsValid</b>, boolean, default=true
+ * <br>Gets or sets a value that indicates whether the associated input control passes validation.
+ *
+ * @author Qiang Xue <qiang.xue@gmail.com>
+ * @version $Revision: $ $Date: $
+ * @package System.Web.UI.WebControls
+ * @since 3.0
+ */
+abstract class TBaseValidator extends TLabel implements IValidator
+{
+ /**
+ * whether the validation succeeds
+ * @var boolean
+ */
+ private $_isValid=true;
+
+ public function __construct()
+ {
+ parent::__construct();
+ $this->setForeColor('red');
+ }
+
+ /**
+ * Adds attributes to renderer.
+ * @param THtmlWriter the renderer
+ */
+ protected function addAttributesToRender($writer)
+ {
+ }
+
+ /**
+ * Returns an array of javascript validator options.
+ * @return array javascript validator options.
+ */
+ protected function getClientScriptAttributes()
+ {
+ $options['ID'] = $this->getClientID();
+ $options['Display'] = $this->getDisplay();
+ $options['ErrorMessage'] = $this->getErrorMessage();
+ $options['FocusOnError'] = $this->getFocusOnError();
+ $options['FocusElementID'] = $this->getFocusElementID();
+ $options['ValidationGroup'] = $this->getValidationGroup();
+ $options['ControlToValidate'] = $this->getControlToValidate();
+ return $options;
+ }
+
+ /**
+ * Renders the javascript code to the end script.
+ * If you override this method, be sure to call the parent implementation
+ * so that the event handlers can be invoked.
+ * @param TEventParameter event parameter to be passed to the event handlers
+ */
+ protected function onPreRender($param)
+ {
+ $scripts = $this->getPage()->getClientScript();
+ $scriptKey = "prado:".get_class($this);
+ if($this->getEnableClientScript()
+ && !$script->isEndScriptRegistered($scriptKey))
+ {
+ $scripts->registerPradoScript('validator');
+ $js = "Prado.Validation.AddForm('{$this->Page->Form->ClientID}');";
+ $scripts->registerEndScript($scriptKey, $js);
+ }
+ parent::onPreRender($param);
+ }
+
+ /**
+ * Renders the individual validator client-side javascript code.
+ */
+ protected function renderClientScriptValidator()
+ {
+ if($this->getEnabled(true) && $this->getEnableClientScript())
+ {
+ $class = get_class($this);
+ $scriptKey = "prado:".$this->getClientID();
+ $scripts = $this->getPage()->getClientScript();
+ $option = TJavascript::toList($this->getClientScriptAttributes());
+ $js = "new Prado.Validation(Prado.Validation.{$class}, {$option});";
+ $scripts->registerEndScript($scriptKey, $js);
+ }
+ }
+
+ /**
+ * This method overrides the parent implementation to forbid setting AssociatedControlID.
+ * @param string the associated control ID
+ * @throws TNotSupportedException whenever this method is called
+ */
+ public function setAssociatedControlID($value)
+ {
+ throw new TNotSupportedException('basevalidator_associatedcontrolid_unsupported',get_class($this));
+ }
+
+ /**
+ * This method overrides parent's implementation by setting {@link setIsValid IsValid} to true if disabled.
+ * @param boolean whether the validator is enabled.
+ */
+ public function setEnabled($value)
+ {
+ $value=TPropertyValue::ensureBoolean($value);
+ parent::setEnabled($value);
+ if(!$value)
+ $this->_isValid=true;
+ }
+
+ /**
+ * @return string the display behavior (None, Static, Dynamic) of the error message in a validation control. Defaults to Static.
+ */
+ public function getDisplay()
+ {
+ return $this->getViewState('Display','Static');
+ }
+
+ /**
+ * Sets the display behavior (None, Static, Dynamic) of the error message in a validation control.
+ * @param string the display behavior (None, Static, Dynamic)
+ */
+ public function setDisplay($value)
+ {
+ $this->setViewState('Display',TPropertyValue::ensureEnum($value,array('None','Static','Dynamic')),'Static');
+ }
+
+ /**
+ * @return boolean whether client-side validation is enabled.
+ */
+ public function getEnableClientScript()
+ {
+ return $this->getViewState('EnableClientScript',true);
+ }
+
+ /**
+ * Sets the value indicating whether client-side validation is enabled.
+ * @param boolean whether client-side validation is enabled.
+ */
+ public function setEnableClientScript($value)
+ {
+ $this->setViewState('EnableClientScript',TPropertyValue::ensureBoolean($value),true);
+ }
+
+ /**
+ * @return string the text for the error message.
+ */
+ public function getErrorMessage()
+ {
+ return $this->getViewState('ErrorMessage','');
+ }
+
+ /**
+ * Sets the text for the error message.
+ * @param string the error message
+ */
+ public function setErrorMessage($value)
+ {
+ $this->setViewState('ErrorMessage',$value,'');
+ }
+
+ /**
+ * @return string the ID path of the input control to validate
+ */
+ public function getControlToValidate()
+ {
+ return $this->getViewState('ControlToValidate','');
+ }
+
+ /**
+ * Sets the ID path of the input control to validate
+ * @param string the ID path
+ */
+ public function setControlToValidate($value)
+ {
+ $this->setViewState('ControlToValidate',$value,'');
+ }
+
+ /**
+ * @return boolean whether to set focus at the validating place if the validation fails. Defaults to true.
+ */
+ public function getFocusOnError()
+ {
+ return $this->getViewState('FocusOnError',true);
+ }
+
+ /**
+ * @param boolean whether to set focus at the validating place if the validation fails
+ */
+ public function setFocusOnError($value)
+ {
+ $this->setViewState('FocusOnError',TPropertyValue::ensureBoolean($value),true);
+ }
+
+ /**
+ * Gets the ID of the HTML element that will receive focus if validation fails and {@link getFocusOnError FocusOnError} is true.
+ * Defaults to the client ID of the {@link getControlToValidate ControlToValidate}.
+ * @return string the ID of the HTML element to receive focus
+ */
+ public function getFocusElementID()
+ {
+ // TODO: identify the ControlToValidate
+ return $this->getViewState('FocusElementID', '');
+ }
+
+ /**
+ * Sets the ID of the HTML element that will receive focus if validation fails and {@link getFocusOnError FocusOnError} is true.
+ * @param string the ID of the HTML element to receive focus
+ */
+ public function setFocusElementID($value)
+ {
+ $this->setViewState('FocusElementID', $value, '');
+ }
+
+ /**
+ * @return string the group which this validator belongs to
+ */
+ public function getValidationGroup()
+ {
+ return $this->getViewState('ValidationGroup','');
+ }
+
+ /**
+ * @param string the group which this validator belongs to
+ */
+ public function setValidationGroup($value)
+ {
+ $this->setViewState('ValidationGroup',$value,'');
+ }
+
+ /**
+ * @return boolean whether the validation succeeds
+ */
+ public function getIsValid()
+ {
+ return $this->_isValid;
+ }
+
+ /**
+ * Sets the value indicating whether the validation succeeds
+ * @param boolean whether the validation succeeds
+ */
+ public function setIsValid($value)
+ {
+ $this->_isValid=TPropertyValue::ensureBoolean($value);
+ }
+
+ /**
+ * Validates the specified control.
+ * Do not override this method. Override {@link evaluateIsValid} instead.
+ * @return boolean whether the validation succeeds
+ */
+ public function validate()
+ {
+ $this->setIsValid(true);
+ if($this->getVisible(true) && $this->getEnabled())
+ {
+ $valid=$this->evaluateIsValid();
+ $this->setValid($valid);
+ }
+ if($this->isVisible() && $this->isEnabled() && strlen($this->getControlToValidate()))
+ {
+ $valid=$this->evaluateIsValid();
+ $this->setValid($valid);
+ return $valid;
+ }
+ else
+ {
+ $this->setValid(true);
+ return true;
+ }
+ }
+
+ /**
+ * This is the major method for validation.
+ * Derived classes should implement this method to provide customized validation.
+ * @return boolean whether the validation succeeds
+ */
+ abstract protected function evaluateIsValid();
+}
?> \ No newline at end of file