summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitattributes4
-rw-r--r--buildscripts/jsbuilder/build.php8
-rw-r--r--framework/Web/Javascripts/js/ajax.js63
-rw-r--r--framework/Web/Javascripts/js/prado.js9
-rw-r--r--framework/Web/Javascripts/prado/activecontrols3.js43
-rw-r--r--framework/Web/Javascripts/prado/element.js17
-rw-r--r--framework/Web/UI/ActiveControls/TActiveControlAdapter.php4
-rw-r--r--framework/Web/UI/ActiveControls/TActivePageAdapter.php2
-rw-r--r--framework/Web/UI/ActiveControls/TAutoComplete.php186
-rw-r--r--framework/Web/UI/ActiveControls/TCallbackResponse.php13
-rw-r--r--tests/FunctionalTests/features/protected/pages/ActiveControls/AutoComplete.page26
-rw-r--r--tests/FunctionalTests/features/protected/pages/ActiveControls/AutoComplete.php17
-rw-r--r--tests/FunctionalTests/features/protected/pages/ActiveControls/Calculator.php1
-rw-r--r--tests/FunctionalTests/features/protected/pages/ActiveControls/config.xml6
14 files changed, 378 insertions, 21 deletions
diff --git a/.gitattributes b/.gitattributes
index 329e6e51..81846ece 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -879,6 +879,7 @@ framework/Web/Javascripts/js/prado.js -text
framework/Web/Javascripts/js/rico.js -text
framework/Web/Javascripts/js/validator.js -text
framework/Web/Javascripts/prado/activecontrols.js -text
+framework/Web/Javascripts/prado/activecontrols3.js -text
framework/Web/Javascripts/prado/ajax.js -text
framework/Web/Javascripts/prado/ajax3.js -text
framework/Web/Javascripts/prado/controls.js -text
@@ -931,6 +932,7 @@ framework/Web/UI/ActiveControls/TActiveLabel.php -text
framework/Web/UI/ActiveControls/TActivePageAdapter.php -text
framework/Web/UI/ActiveControls/TActivePanel.php -text
framework/Web/UI/ActiveControls/TActiveTextBox.php -text
+framework/Web/UI/ActiveControls/TAutoComplete.php -text
framework/Web/UI/ActiveControls/TCallback.php -text
framework/Web/UI/ActiveControls/TCallbackClientScript.php -text
framework/Web/UI/ActiveControls/TCallbackClientSideOptions.php -text
@@ -1041,6 +1043,8 @@ tests/FunctionalTests/features/protected/controls/Layout.php -text
tests/FunctionalTests/features/protected/controls/Layout.tpl -text
tests/FunctionalTests/features/protected/pages/ActiveControls/ActiveControl.page -text
tests/FunctionalTests/features/protected/pages/ActiveControls/ActiveControl.php -text
+tests/FunctionalTests/features/protected/pages/ActiveControls/AutoComplete.page -text
+tests/FunctionalTests/features/protected/pages/ActiveControls/AutoComplete.php -text
tests/FunctionalTests/features/protected/pages/ActiveControls/Calculator.page -text
tests/FunctionalTests/features/protected/pages/ActiveControls/Calculator.php -text
tests/FunctionalTests/features/protected/pages/ActiveControls/config.xml -text
diff --git a/buildscripts/jsbuilder/build.php b/buildscripts/jsbuilder/build.php
index 9cd1da74..33e5d133 100644
--- a/buildscripts/jsbuilder/build.php
+++ b/buildscripts/jsbuilder/build.php
@@ -102,11 +102,11 @@ $libraries = array(
'prototype/ajax.js',
'prado/ajax3.js',
'extra/json.js',
+ 'effects/controls.js',
'prado/activecontrols3.js'
-/* 'effects/controls.js',
- 'effects/dragdrop.js',
- 'effects/slider.js',
- 'prado/activecontrols.js'*/
+// 'effects/dragdrop.js',
+// 'effects/slider.js',
+// 'prado/activecontrols.js'
),
//logging
'logger.js' => array(
diff --git a/framework/Web/Javascripts/js/ajax.js b/framework/Web/Javascripts/js/ajax.js
index e082c7bb..48b4689a 100644
--- a/framework/Web/Javascripts/js/ajax.js
+++ b/framework/Web/Javascripts/js/ajax.js
@@ -132,5 +132,64 @@ break;case'n':if(next()=='u'&&next()=='l'&&next()=='l'){next();return null;}
break;}
error("Syntax error");}
function value(){white();switch(ch){case'{':return object();case'[':return array();case'"':return string();case'-':return number();default:return ch>='0'&&ch<='9'?number():word();}}
-return value();}};Prado.WebUI.CallbackControl=Class.extend(Prado.WebUI.PostBackControl,{onPostBack:function(event,options)
-{new Prado.CallbackRequest(options.EventTarget,options);Event.stop(event);}});Prado.WebUI.TActiveButton=Class.extend(Prado.WebUI.CallbackControl); \ No newline at end of file
+return value();}};var Autocompleter={}
+Autocompleter.Base=function(){};Autocompleter.Base.prototype={baseInitialize:function(element,update,options){this.element=$(element);this.update=$(update);this.hasFocus=false;this.changed=false;this.active=false;this.index=0;this.entryCount=0;if(this.setOptions)
+this.setOptions(options);else
+this.options=options||{};this.options.paramName=this.options.paramName||this.element.name;this.options.tokens=this.options.tokens||[];this.options.frequency=this.options.frequency||0.4;this.options.minChars=this.options.minChars||1;this.options.onShow=this.options.onShow||function(element,update){if(!update.style.position||update.style.position=='absolute'){update.style.position='absolute';Position.clone(element,update,{setHeight:false,offsetTop:element.offsetHeight});}
+Effect.Appear(update,{duration:0.15});};this.options.onHide=this.options.onHide||function(element,update){new Effect.Fade(update,{duration:0.15})};if(typeof(this.options.tokens)=='string')
+this.options.tokens=new Array(this.options.tokens);this.observer=null;this.element.setAttribute('autocomplete','off');Element.hide(this.update);Event.observe(this.element,"blur",this.onBlur.bindAsEventListener(this));Event.observe(this.element,"keypress",this.onKeyPress.bindAsEventListener(this));},show:function(){if(Element.getStyle(this.update,'display')=='none')this.options.onShow(this.element,this.update);if(!this.iefix&&(navigator.appVersion.indexOf('MSIE')>0)&&(navigator.userAgent.indexOf('Opera')<0)&&(Element.getStyle(this.update,'position')=='absolute')){new Insertion.After(this.update,'<iframe id="'+this.update.id+'_iefix" '+'style="display:none;position:absolute;filter:progid:DXImageTransform.Microsoft.Alpha(opacity=0);" '+'src="javascript:false;" frameborder="0" scrolling="no"></iframe>');this.iefix=$(this.update.id+'_iefix');}
+if(this.iefix)setTimeout(this.fixIEOverlapping.bind(this),50);},fixIEOverlapping:function(){Position.clone(this.update,this.iefix);this.iefix.style.zIndex=1;this.update.style.zIndex=2;Element.show(this.iefix);},hide:function(){this.stopIndicator();if(Element.getStyle(this.update,'display')!='none')this.options.onHide(this.element,this.update);if(this.iefix)Element.hide(this.iefix);},startIndicator:function(){if(this.options.indicator)Element.show(this.options.indicator);},stopIndicator:function(){if(this.options.indicator)Element.hide(this.options.indicator);},onKeyPress:function(event){if(this.active)
+switch(event.keyCode){case Event.KEY_TAB:case Event.KEY_RETURN:this.selectEntry();Event.stop(event);case Event.KEY_ESC:this.hide();this.active=false;Event.stop(event);return;case Event.KEY_LEFT:case Event.KEY_RIGHT:return;case Event.KEY_UP:this.markPrevious();this.render();if(navigator.appVersion.indexOf('AppleWebKit')>0)Event.stop(event);return;case Event.KEY_DOWN:this.markNext();this.render();if(navigator.appVersion.indexOf('AppleWebKit')>0)Event.stop(event);return;}
+else
+if(event.keyCode==Event.KEY_TAB||event.keyCode==Event.KEY_RETURN||(navigator.appVersion.indexOf('AppleWebKit')>0&&event.keyCode==0))return;this.changed=true;this.hasFocus=true;if(this.observer)clearTimeout(this.observer);this.observer=setTimeout(this.onObserverEvent.bind(this),this.options.frequency*1000);},activate:function(){this.changed=false;this.hasFocus=true;this.getUpdatedChoices();},onHover:function(event){var element=Event.findElement(event,'LI');if(this.index!=element.autocompleteIndex)
+{this.index=element.autocompleteIndex;this.render();}
+Event.stop(event);},onClick:function(event){var element=Event.findElement(event,'LI');this.index=element.autocompleteIndex;this.selectEntry();this.hide();},onBlur:function(event){setTimeout(this.hide.bind(this),250);this.hasFocus=false;this.active=false;},render:function(){if(this.entryCount>0){for(var i=0;i<this.entryCount;i++)
+this.index==i?Element.addClassName(this.getEntry(i),"selected"):Element.removeClassName(this.getEntry(i),"selected");if(this.hasFocus){this.show();this.active=true;}}else{this.active=false;this.hide();}},markPrevious:function(){if(this.index>0)this.index--
+else this.index=this.entryCount-1;},markNext:function(){if(this.index<this.entryCount-1)this.index++
+else this.index=0;},getEntry:function(index){return this.update.firstChild.childNodes[index];},getCurrentEntry:function(){return this.getEntry(this.index);},selectEntry:function(){this.active=false;this.updateElement(this.getCurrentEntry());},updateElement:function(selectedElement){if(this.options.updateElement){this.options.updateElement(selectedElement);return;}
+var value='';if(this.options.select){var nodes=document.getElementsByClassName(this.options.select,selectedElement)||[];if(nodes.length>0)value=Element.collectTextNodes(nodes[0],this.options.select);}else
+value=Element.collectTextNodesIgnoreClass(selectedElement,'informal');var lastTokenPos=this.findLastToken();if(lastTokenPos!=-1){var newValue=this.element.value.substr(0,lastTokenPos+1);var whitespace=this.element.value.substr(lastTokenPos+1).match(/^\s+/);if(whitespace)
+newValue+=whitespace[0];this.element.value=newValue+value;}else{this.element.value=value;}
+this.element.focus();if(this.options.afterUpdateElement)
+this.options.afterUpdateElement(this.element,selectedElement);},updateChoices:function(choices){if(!this.changed&&this.hasFocus){this.update.innerHTML=choices;Element.cleanWhitespace(this.update);Element.cleanWhitespace(this.update.firstChild);if(this.update.firstChild&&this.update.firstChild.childNodes){this.entryCount=this.update.firstChild.childNodes.length;for(var i=0;i<this.entryCount;i++){var entry=this.getEntry(i);entry.autocompleteIndex=i;this.addObservers(entry);}}else{this.entryCount=0;}
+this.stopIndicator();this.index=0;this.render();}},addObservers:function(element){Event.observe(element,"mouseover",this.onHover.bindAsEventListener(this));Event.observe(element,"click",this.onClick.bindAsEventListener(this));},onObserverEvent:function(){this.changed=false;if(this.getToken().length>=this.options.minChars){this.startIndicator();this.getUpdatedChoices();}else{this.active=false;this.hide();}},getToken:function(){var tokenPos=this.findLastToken();if(tokenPos!=-1)
+var ret=this.element.value.substr(tokenPos+1).replace(/^\s+/,'').replace(/\s+$/,'');else
+var ret=this.element.value;return/\n/.test(ret)?'':ret;},findLastToken:function(){var lastTokenPos=-1;for(var i=0;i<this.options.tokens.length;i++){var thisTokenPos=this.element.value.lastIndexOf(this.options.tokens[i]);if(thisTokenPos>lastTokenPos)
+lastTokenPos=thisTokenPos;}
+return lastTokenPos;}}
+Ajax.Autocompleter=Class.create();Object.extend(Object.extend(Ajax.Autocompleter.prototype,Autocompleter.Base.prototype),{initialize:function(element,update,url,options){this.baseInitialize(element,update,options);this.options.asynchronous=true;this.options.onComplete=this.onComplete.bind(this);this.options.defaultParams=this.options.parameters||null;this.url=url;},getUpdatedChoices:function(){entry=encodeURIComponent(this.options.paramName)+'='+
+encodeURIComponent(this.getToken());this.options.parameters=this.options.callback?this.options.callback(this.element,entry):entry;if(this.options.defaultParams)
+this.options.parameters+='&'+this.options.defaultParams;new Ajax.Request(this.url,this.options);},onComplete:function(request){this.updateChoices(request.responseText);}});Autocompleter.Local=Class.create();Autocompleter.Local.prototype=Object.extend(new Autocompleter.Base(),{initialize:function(element,update,array,options){this.baseInitialize(element,update,options);this.options.array=array;},getUpdatedChoices:function(){this.updateChoices(this.options.selector(this));},setOptions:function(options){this.options=Object.extend({choices:10,partialSearch:true,partialChars:2,ignoreCase:true,fullSearch:false,selector:function(instance){var ret=[];var partial=[];var entry=instance.getToken();var count=0;for(var i=0;i<instance.options.array.length&&ret.length<instance.options.choices;i++){var elem=instance.options.array[i];var foundPos=instance.options.ignoreCase?elem.toLowerCase().indexOf(entry.toLowerCase()):elem.indexOf(entry);while(foundPos!=-1){if(foundPos==0&&elem.length!=entry.length){ret.push("<li><strong>"+elem.substr(0,entry.length)+"</strong>"+
+elem.substr(entry.length)+"</li>");break;}else if(entry.length>=instance.options.partialChars&&instance.options.partialSearch&&foundPos!=-1){if(instance.options.fullSearch||/\s/.test(elem.substr(foundPos-1,1))){partial.push("<li>"+elem.substr(0,foundPos)+"<strong>"+
+elem.substr(foundPos,entry.length)+"</strong>"+elem.substr(foundPos+entry.length)+"</li>");break;}}
+foundPos=instance.options.ignoreCase?elem.toLowerCase().indexOf(entry.toLowerCase(),foundPos+1):elem.indexOf(entry,foundPos+1);}}
+if(partial.length)
+ret=ret.concat(partial.slice(0,instance.options.choices-ret.length))
+return"<ul>"+ret.join('')+"</ul>";}},options||{});}});Field.scrollFreeActivate=function(field){setTimeout(function(){Field.activate(field);},1);}
+Ajax.InPlaceEditor=Class.create();Ajax.InPlaceEditor.defaultHighlightColor="#FFFF99";Ajax.InPlaceEditor.prototype={initialize:function(element,url,options){this.url=url;this.element=$(element);this.options=Object.extend({okButton:true,okText:"ok",cancelLink:true,cancelText:"cancel",savingText:"Saving...",clickToEditText:"Click to edit",okText:"ok",rows:1,onComplete:function(transport,element){new Effect.Highlight(element,{startcolor:this.options.highlightcolor});},onFailure:function(transport){alert("Error communicating with the server: "+transport.responseText.stripTags());},callback:function(form){return Form.serialize(form);},handleLineBreaks:true,loadingText:'Loading...',savingClassName:'inplaceeditor-saving',loadingClassName:'inplaceeditor-loading',formClassName:'inplaceeditor-form',highlightcolor:Ajax.InPlaceEditor.defaultHighlightColor,highlightendcolor:"#FFFFFF",externalControl:null,submitOnBlur:false,ajaxOptions:{},evalScripts:false},options||{});if(!this.options.formId&&this.element.id){this.options.formId=this.element.id+"-inplaceeditor";if($(this.options.formId)){this.options.formId=null;}}
+if(this.options.externalControl){this.options.externalControl=$(this.options.externalControl);}
+this.originalBackground=Element.getStyle(this.element,'background-color');if(!this.originalBackground){this.originalBackground="transparent";}
+this.element.title=this.options.clickToEditText;this.onclickListener=this.enterEditMode.bindAsEventListener(this);this.mouseoverListener=this.enterHover.bindAsEventListener(this);this.mouseoutListener=this.leaveHover.bindAsEventListener(this);Event.observe(this.element,'click',this.onclickListener);Event.observe(this.element,'mouseover',this.mouseoverListener);Event.observe(this.element,'mouseout',this.mouseoutListener);if(this.options.externalControl){Event.observe(this.options.externalControl,'click',this.onclickListener);Event.observe(this.options.externalControl,'mouseover',this.mouseoverListener);Event.observe(this.options.externalControl,'mouseout',this.mouseoutListener);}},enterEditMode:function(evt){if(this.saving)return;if(this.editing)return;this.editing=true;this.onEnterEditMode();if(this.options.externalControl){Element.hide(this.options.externalControl);}
+Element.hide(this.element);this.createForm();this.element.parentNode.insertBefore(this.form,this.element);Field.scrollFreeActivate(this.editField);if(evt){Event.stop(evt);}
+return false;},createForm:function(){this.form=document.createElement("form");this.form.id=this.options.formId;Element.addClassName(this.form,this.options.formClassName)
+this.form.onsubmit=this.onSubmit.bind(this);this.createEditField();if(this.options.textarea){var br=document.createElement("br");this.form.appendChild(br);}
+if(this.options.okButton){okButton=document.createElement("input");okButton.type="submit";okButton.value=this.options.okText;okButton.className='editor_ok_button';this.form.appendChild(okButton);}
+if(this.options.cancelLink){cancelLink=document.createElement("a");cancelLink.href="#";cancelLink.appendChild(document.createTextNode(this.options.cancelText));cancelLink.onclick=this.onclickCancel.bind(this);cancelLink.className='editor_cancel';this.form.appendChild(cancelLink);}},hasHTMLLineBreaks:function(string){if(!this.options.handleLineBreaks)return false;return string.match(/<br/i)||string.match(/<p>/i);},convertHTMLLineBreaks:function(string){return string.replace(/<br>/gi,"\n").replace(/<br\/>/gi,"\n").replace(/<\/p>/gi,"\n").replace(/<p>/gi,"");},createEditField:function(){var text;if(this.options.loadTextURL){text=this.options.loadingText;}else{text=this.getText();}
+var obj=this;if(this.options.rows==1&&!this.hasHTMLLineBreaks(text)){this.options.textarea=false;var textField=document.createElement("input");textField.obj=this;textField.type="text";textField.name="value";textField.value=text;textField.style.backgroundColor=this.options.highlightcolor;textField.className='editor_field';var size=this.options.size||this.options.cols||0;if(size!=0)textField.size=size;if(this.options.submitOnBlur)
+textField.onblur=this.onSubmit.bind(this);this.editField=textField;}else{this.options.textarea=true;var textArea=document.createElement("textarea");textArea.obj=this;textArea.name="value";textArea.value=this.convertHTMLLineBreaks(text);textArea.rows=this.options.rows;textArea.cols=this.options.cols||40;textArea.className='editor_field';if(this.options.submitOnBlur)
+textArea.onblur=this.onSubmit.bind(this);this.editField=textArea;}
+if(this.options.loadTextURL){this.loadExternalText();}
+this.form.appendChild(this.editField);},getText:function(){return this.element.innerHTML;},loadExternalText:function(){Element.addClassName(this.form,this.options.loadingClassName);this.editField.disabled=true;new Ajax.Request(this.options.loadTextURL,Object.extend({asynchronous:true,onComplete:this.onLoadedExternalText.bind(this)},this.options.ajaxOptions));},onLoadedExternalText:function(transport){Element.removeClassName(this.form,this.options.loadingClassName);this.editField.disabled=false;this.editField.value=transport.responseText.stripTags();},onclickCancel:function(){this.onComplete();this.leaveEditMode();return false;},onFailure:function(transport){this.options.onFailure(transport);if(this.oldInnerHTML){this.element.innerHTML=this.oldInnerHTML;this.oldInnerHTML=null;}
+return false;},onSubmit:function(){var form=this.form;var value=this.editField.value;this.onLoading();if(this.options.evalScripts){new Ajax.Request(this.url,Object.extend({parameters:this.options.callback(form,value),onComplete:this.onComplete.bind(this),onFailure:this.onFailure.bind(this),asynchronous:true,evalScripts:true},this.options.ajaxOptions));}else{new Ajax.Updater({success:this.element,failure:null},this.url,Object.extend({parameters:this.options.callback(form,value),onComplete:this.onComplete.bind(this),onFailure:this.onFailure.bind(this)},this.options.ajaxOptions));}
+if(arguments.length>1){Event.stop(arguments[0]);}
+return false;},onLoading:function(){this.saving=true;this.removeForm();this.leaveHover();this.showSaving();},showSaving:function(){this.oldInnerHTML=this.element.innerHTML;this.element.innerHTML=this.options.savingText;Element.addClassName(this.element,this.options.savingClassName);this.element.style.backgroundColor=this.originalBackground;Element.show(this.element);},removeForm:function(){if(this.form){if(this.form.parentNode)Element.remove(this.form);this.form=null;}},enterHover:function(){if(this.saving)return;this.element.style.backgroundColor=this.options.highlightcolor;if(this.effect){this.effect.cancel();}
+Element.addClassName(this.element,this.options.hoverClassName)},leaveHover:function(){if(this.options.backgroundColor){this.element.style.backgroundColor=this.oldBackground;}
+Element.removeClassName(this.element,this.options.hoverClassName)
+if(this.saving)return;this.effect=new Effect.Highlight(this.element,{startcolor:this.options.highlightcolor,endcolor:this.options.highlightendcolor,restorecolor:this.originalBackground});},leaveEditMode:function(){Element.removeClassName(this.element,this.options.savingClassName);this.removeForm();this.leaveHover();this.element.style.backgroundColor=this.originalBackground;Element.show(this.element);if(this.options.externalControl){Element.show(this.options.externalControl);}
+this.editing=false;this.saving=false;this.oldInnerHTML=null;this.onLeaveEditMode();},onComplete:function(transport){this.leaveEditMode();this.options.onComplete.bind(this)(transport,this.element);},onEnterEditMode:function(){},onLeaveEditMode:function(){},dispose:function(){if(this.oldInnerHTML){this.element.innerHTML=this.oldInnerHTML;}
+this.leaveEditMode();Event.stopObserving(this.element,'click',this.onclickListener);Event.stopObserving(this.element,'mouseover',this.mouseoverListener);Event.stopObserving(this.element,'mouseout',this.mouseoutListener);if(this.options.externalControl){Event.stopObserving(this.options.externalControl,'click',this.onclickListener);Event.stopObserving(this.options.externalControl,'mouseover',this.mouseoverListener);Event.stopObserving(this.options.externalControl,'mouseout',this.mouseoutListener);}}};Ajax.InPlaceCollectionEditor=Class.create();Object.extend(Ajax.InPlaceCollectionEditor.prototype,Ajax.InPlaceEditor.prototype);Object.extend(Ajax.InPlaceCollectionEditor.prototype,{createEditField:function(){if(!this.cached_selectTag){var selectTag=document.createElement("select");var collection=this.options.collection||[];var optionTag;collection.each(function(e,i){optionTag=document.createElement("option");optionTag.value=(e instanceof Array)?e[0]:e;if(this.options.value==optionTag.value)optionTag.selected=true;optionTag.appendChild(document.createTextNode((e instanceof Array)?e[1]:e));selectTag.appendChild(optionTag);}.bind(this));this.cached_selectTag=selectTag;}
+this.editField=this.cached_selectTag;if(this.options.loadTextURL)this.loadExternalText();this.form.appendChild(this.editField);this.options.callback=function(form,value){return"value="+encodeURIComponent(value);}}});Form.Element.DelayedObserver=Class.create();Form.Element.DelayedObserver.prototype={initialize:function(element,delay,callback){this.delay=delay||0.5;this.element=$(element);this.callback=callback;this.timer=null;this.lastValue=$F(this.element);Event.observe(this.element,'keyup',this.delayedListener.bindAsEventListener(this));},delayedListener:function(event){if(this.lastValue==$F(this.element))return;if(this.timer)clearTimeout(this.timer);this.timer=setTimeout(this.onTimerEvent.bind(this),this.delay*1000);this.lastValue=$F(this.element);},onTimerEvent:function(){this.timer=null;this.callback(this.element,$F(this.element));}};Prado.WebUI.CallbackControl=Class.extend(Prado.WebUI.PostBackControl,{onPostBack:function(event,options)
+{new Prado.CallbackRequest(options.EventTarget,options);Event.stop(event);}});Prado.WebUI.TActiveButton=Class.extend(Prado.WebUI.CallbackControl);Prado.WebUI.TAutoComplete=Class.extend(Autocompleter.Base,{initialize:function(options)
+{this.options=options;this.baseInitialize(options.ID,options.ResultPanel,options);Object.extend(this.options,{onSuccess:this.onComplete.bind(this)});},getUpdatedChoices:function()
+{Prado.Callback(this.options.EventTarget,this.getToken(),null,this.options);},onComplete:function(request,boundary)
+{result=Prado.Element.extractContent(request.responseText,boundary);this.updateChoices(result);}}); \ No newline at end of file
diff --git a/framework/Web/Javascripts/js/prado.js b/framework/Web/Javascripts/js/prado.js
index 9442ed26..c09cf64c 100644
--- a/framework/Web/Javascripts/js/prado.js
+++ b/framework/Web/Javascripts/js/prado.js
@@ -265,9 +265,12 @@ el.options[el.options.length]=new Option(options[i][0],options[i][1]);}},focus:f
{var obj=$(element);if(typeof(obj)!="undefined"&&typeof(obj.focus)!="undefined")
setTimeout(function(){obj.focus();},100);return false;},replace:function(element,method,content,boundary,transport)
{if(boundary)
-{var f=RegExp('(<!--'+boundary+'-->)([\\s\\S\\w\\W]*)(<!--//'+boundary+'-->)',"m");var result=transport.responseText.match(f);if(result&&result.length>=2)
-content=result[2];}
-method.toFunction().apply(this,[element,content]);}}
+{result=Prado.Element.extractContent(transport.responseText,boundary);if(result!=null)
+content=result;}
+method.toFunction().apply(this,[element,content]);},extractContent:function(text,boundary)
+{f=RegExp('(<!--'+boundary+'-->)([\\s\\S\\w\\W]*)(<!--//'+boundary+'-->)',"m");result=text.match(f);if(result&&result.length>=2)
+return result[2];else
+return null;}}
Prado.Element.Selection={inputValue:function(el,value)
{switch(el.type.toLowerCase())
{case'checkbox':case'radio':return el.checked=value;}},selectValue:function(el,value)
diff --git a/framework/Web/Javascripts/prado/activecontrols3.js b/framework/Web/Javascripts/prado/activecontrols3.js
new file mode 100644
index 00000000..c22af98c
--- /dev/null
+++ b/framework/Web/Javascripts/prado/activecontrols3.js
@@ -0,0 +1,43 @@
+/**
+ * Generic postback control.
+ */
+Prado.WebUI.CallbackControl = Class.extend(Prado.WebUI.PostBackControl,
+{
+ onPostBack : function(event, options)
+ {
+ new Prado.CallbackRequest(options.EventTarget, options);
+ Event.stop(event);
+ }
+});
+
+/**
+ * TActiveButton control.
+ */
+Prado.WebUI.TActiveButton = Class.extend(Prado.WebUI.CallbackControl);
+
+/**
+ * TAutoComplete control.
+ */
+Prado.WebUI.TAutoComplete = Class.extend(Autocompleter.Base,
+{
+ initialize : function(options)
+ {
+ this.options = options;
+ this.baseInitialize(options.ID, options.ResultPanel, options);
+ Object.extend(this.options,
+ {
+ onSuccess : this.onComplete.bind(this)
+ });
+ },
+
+ getUpdatedChoices : function()
+ {
+ Prado.Callback(this.options.EventTarget, this.getToken(), null, this.options);
+ },
+
+ onComplete : function(request, boundary)
+ {
+ result = Prado.Element.extractContent(request.responseText, boundary);
+ this.updateChoices(result);
+ }
+}); \ No newline at end of file
diff --git a/framework/Web/Javascripts/prado/element.js b/framework/Web/Javascripts/prado/element.js
index eec7fb92..0ff0e8fa 100644
--- a/framework/Web/Javascripts/prado/element.js
+++ b/framework/Web/Javascripts/prado/element.js
@@ -67,12 +67,21 @@ Prado.Element =
{
if(boundary)
{
- var f = RegExp('(<!--'+boundary+'-->)([\\s\\S\\w\\W]*)(<!--//'+boundary+'-->)',"m");
- var result = transport.responseText.match(f);
- if(result && result.length >= 2)
- content = result[2];
+ result = Prado.Element.extractContent(transport.responseText, boundary);
+ if(result != null)
+ content = result;
}
method.toFunction().apply(this,[element,content]);
+ },
+
+ extractContent : function(text, boundary)
+ {
+ f = RegExp('(<!--'+boundary+'-->)([\\s\\S\\w\\W]*)(<!--//'+boundary+'-->)',"m");
+ result = text.match(f);
+ if(result && result.length >= 2)
+ return result[2];
+ else
+ return null;
}
}
diff --git a/framework/Web/UI/ActiveControls/TActiveControlAdapter.php b/framework/Web/UI/ActiveControls/TActiveControlAdapter.php
index 2409d9fe..1cdd5d73 100644
--- a/framework/Web/UI/ActiveControls/TActiveControlAdapter.php
+++ b/framework/Web/UI/ActiveControls/TActiveControlAdapter.php
@@ -14,9 +14,11 @@ class TActiveControlAdapter extends TControlAdapter
{
if(!self::$_renderedPosts)
{
+ $cs = $this->getPage()->getClientScript();
+ $cs->registerPradoScript('ajax');
$options = TJavascript::encode($this->getPage()->getPostDataLoaders(),false);
$script = "Prado.CallbackRequest.PostDataLoaders = {$options};";
- $this->getPage()->getClientScript()->registerEndScript(get_class($this), $script);
+ $cs->registerEndScript(get_class($this), $script);
self::$_renderedPosts = true;
}
parent::render($writer);
diff --git a/framework/Web/UI/ActiveControls/TActivePageAdapter.php b/framework/Web/UI/ActiveControls/TActivePageAdapter.php
index 11c3303e..e92c9cdc 100644
--- a/framework/Web/UI/ActiveControls/TActivePageAdapter.php
+++ b/framework/Web/UI/ActiveControls/TActivePageAdapter.php
@@ -257,7 +257,7 @@ class TCallbackEventParameter extends TEventParameter
*/
public function getOutput()
{
- return $this->_response->createHtmlWriter();
+ return $this->_response->createHtmlWriter(null,$this);
}
/**
diff --git a/framework/Web/UI/ActiveControls/TAutoComplete.php b/framework/Web/UI/ActiveControls/TAutoComplete.php
new file mode 100644
index 00000000..2ebba495
--- /dev/null
+++ b/framework/Web/UI/ActiveControls/TAutoComplete.php
@@ -0,0 +1,186 @@
+<?php
+/*
+ * Created on 7/05/2006
+ */
+
+class TAutoComplete extends TActiveTextBox implements ICallbackEventHandler, INamingContainer
+{
+ /**
+ * @var ITemplate template for repeater items
+ */
+ private $_repeater=null;
+ private $_resultPanel=null;
+
+ public function setDataSource($data)
+ {
+ $this->getSuggestions()->setDataSource($data);
+ }
+
+ public function getResultPanel()
+ {
+ if(is_null($this->_resultPanel))
+ $this->_resultPanel = $this->createResultPanel();
+ return $this->_resultPanel;
+ }
+
+ protected function createResultPanel()
+ {
+ $panel = Prado::createComponent('System.Web.UI.WebControls.TPanel');
+ $this->getControls()->add($panel);
+ $panel->setID('result');
+ return $panel;
+ }
+
+ /**
+ * @return TRepeater suggestion list repeater
+ */
+ public function getSuggestions()
+ {
+ if(is_null($this->_repeater))
+ $this->_repeater = $this->createRepeater();
+ return $this->_repeater;
+ }
+
+ /**
+ *
+ */
+ protected function createRepeater()
+ {
+ $repeater = Prado::createComponent('System.Web.UI.WebControls.TRepeater');
+ $repeater->setHeaderTemplate(new TAutoCompleteTemplate('<ul>'));
+ $repeater->setFooterTemplate(new TAutoCompleteTemplate('</ul>'));
+ $repeater->setItemTemplate(new TTemplate('<li><%# $this->DataItem %></li>',null));
+ $this->getControls()->add($repeater);
+ return $repeater;
+ }
+
+ /**
+ * @return TCallbackClientSideOptions callback client-side options.
+ */
+ protected function createClientSideOptions()
+ {
+ $options = new TAutoCompleteClientSideOptions;
+ $options->setEnablePageStateUpdate(false);
+ return $options;
+ }
+
+ public function renderEndTag($writer)
+ {
+ $this->getPage()->getClientScript()->registerPradoScript('effects');
+ parent::renderEndTag($writer);
+ $this->renderResultPanel($writer);
+ }
+
+ public function renderResultPanel($writer)
+ {
+ $this->getResultPanel()->render($writer);
+ }
+
+ public function render($writer)
+ {
+ if($this->canUpdateClientSide())
+ {
+ $this->getSuggestions()->render($writer);
+ $boundary = $writer->getWriter()->getBoundary();
+ $writer->getWriter()->getResponse()->setData($boundary);
+ }
+ else
+ parent::render($writer);
+ }
+
+ /**
+ * @return array list of callback options.
+ */
+ protected function getCallbackOptions()
+ {
+ $options = $this->getClientSide()->getOptions()->toArray();
+ if($this->getAutoPostBack())
+ $options = array_merge($options,$this->getPostBackOptions());
+ $options['ResultPanel'] = $this->getResultPanel()->getClientID();
+ $options['ID'] = $this->getClientID();
+ $options['EventTarget'] = $this->getUniqueID();
+ return $options;
+ }
+
+ /**
+ * Adds attribute name-value pairs to renderer.
+ * This method overrides the parent implementation with additional textbox specific attributes.
+ * @param THtmlWriter the writer used for the rendering purpose
+ */
+ protected function addAttributesToRender($writer)
+ {
+ parent::addAttributesToRender($writer);
+ $this->renderClientControlScript($writer);
+ }
+
+}
+
+/**
+ * Client-side options for TAutoComplete.
+ *
+ * @author Wei Zhuo <weizhuo[at]gmail[dot]com>
+ * @version $Revision: $ $Date: $
+ * @package System.Web.UI.ActiveControls
+ * @since 3.0
+ */
+class TAutoCompleteClientSideOptions extends TCallbackClientSideOptions
+{
+ public function getSeparator()
+ {
+ return $this->getOption('tokens');
+ }
+
+ public function setSeparator($value)
+ {
+ $this->setOption('tokens', $chars = preg_split('//', $value, -1, PREG_SPLIT_NO_EMPTY));
+ }
+
+ public function getFrequency()
+ {
+ return $this->getOption('frequency');
+ }
+
+ public function setFrequency($value)
+ {
+ $this->setOption('frequency', TPropertyValue::ensureFloat($value));
+ }
+
+ public function getMinChars()
+ {
+ return $this->getOption('minChars');
+ }
+
+ public function setMinChars($value)
+ {
+ $this->setOption('minChars', TPropertyValue::ensureInteger($value));
+ }
+}
+
+/**
+ * TWizardSideBarTemplate class.
+ * TWizardSideBarTemplate is the default template for wizard sidebar.
+ * @author Qiang Xue <qiang.xue@gmail.com>
+ * @version $Revision: $ $Date: $
+ * @package System.Web.UI.WebControls
+ * @since 3.0
+ */
+class TAutoCompleteTemplate extends TComponent implements ITemplate
+{
+ private $_template;
+
+ public function __construct($template)
+ {
+ $this->_template = $template;
+ }
+ /**
+ * Instantiates the template.
+ * It creates a {@link TDataList} control.
+ * @param TControl parent to hold the content within the template
+ */
+ public function instantiateIn($parent)
+ {
+ $parent->getControls()->add($this->_template);
+ }
+}
+
+?> \ No newline at end of file
diff --git a/framework/Web/UI/ActiveControls/TCallbackResponse.php b/framework/Web/UI/ActiveControls/TCallbackResponse.php
index 024ad6ef..b28d817b 100644
--- a/framework/Web/UI/ActiveControls/TCallbackResponse.php
+++ b/framework/Web/UI/ActiveControls/TCallbackResponse.php
@@ -7,9 +7,9 @@ class TCallbackResponse extends THttpResponse
{
private $_writers=array();
- public function createHtmlWriter($type=null)
+ public function createHtmlWriter($type=null,$parameter=null)
{
- $writer = new TCallbackResponseWriter();
+ $writer = new TCallbackResponseWriter($parameter);
$this->_writers[] = $writer;
if($type===null)
$type=$this->getHtmlWriterType();
@@ -27,12 +27,19 @@ class TCallbackResponse extends THttpResponse
class TCallbackResponseWriter extends TTextWriter
{
private $_boundary;
+ private $_response;
- public function __construct()
+ public function __construct($response)
{
+ $this->_response = $response;
$this->_boundary = sprintf('%x',crc32((string)$this));
}
+ public function getResponse()
+ {
+ return $this->_response;
+ }
+
public function getBoundary()
{
return $this->_boundary;
diff --git a/tests/FunctionalTests/features/protected/pages/ActiveControls/AutoComplete.page b/tests/FunctionalTests/features/protected/pages/ActiveControls/AutoComplete.page
new file mode 100644
index 00000000..f0d78267
--- /dev/null
+++ b/tests/FunctionalTests/features/protected/pages/ActiveControls/AutoComplete.page
@@ -0,0 +1,26 @@
+<com:TContent ID="Content">
+ <style>
+.autocomplete
+{
+ border:1px solid black;
+ background-color:white;
+}
+.autocomplete .selected
+{
+ background-color: #888;
+}
+ </style>
+ <com:TAutoComplete OnCallback="suggestEmails" ResultPanel.CssClass="autocomplete" />
+
+<p><br /></p>
+<p><br /></p>
+<p><br /></p>
+<p><br /></p>
+<p><br /></p>
+<p><br /></p>
+<p><br /></p>
+<p><br /></p>
+<p><br /></p>
+<p><br /></p>
+
+</com:TContent> \ No newline at end of file
diff --git a/tests/FunctionalTests/features/protected/pages/ActiveControls/AutoComplete.php b/tests/FunctionalTests/features/protected/pages/ActiveControls/AutoComplete.php
new file mode 100644
index 00000000..81508000
--- /dev/null
+++ b/tests/FunctionalTests/features/protected/pages/ActiveControls/AutoComplete.php
@@ -0,0 +1,17 @@
+<?php
+/*
+ * Created on 7/05/2006
+ */
+
+class AutoComplete extends TPage
+{
+ public function suggestEmails($sender, $param)
+ {
+ $words = array('hello', 'world');
+ $sender->setDataSource($words);
+ $sender->dataBind();
+ $sender->render($param->getOutput());
+ }
+}
+
+?> \ No newline at end of file
diff --git a/tests/FunctionalTests/features/protected/pages/ActiveControls/Calculator.php b/tests/FunctionalTests/features/protected/pages/ActiveControls/Calculator.php
index bcf0f9cd..9821d8c9 100644
--- a/tests/FunctionalTests/features/protected/pages/ActiveControls/Calculator.php
+++ b/tests/FunctionalTests/features/protected/pages/ActiveControls/Calculator.php
@@ -2,6 +2,7 @@
/*
* Created on 6/05/2006
*/
+Prado::using('System.Web.UI.ActiveControls.*');
class Calculator extends TPage
{
diff --git a/tests/FunctionalTests/features/protected/pages/ActiveControls/config.xml b/tests/FunctionalTests/features/protected/pages/ActiveControls/config.xml
index 1bbc0acf..37988c44 100644
--- a/tests/FunctionalTests/features/protected/pages/ActiveControls/config.xml
+++ b/tests/FunctionalTests/features/protected/pages/ActiveControls/config.xml
@@ -1,7 +1,7 @@
<?xml version="1.0" encoding="utf-8"?>
<configuration>
- <paths>
- <using namespace="System.Web.UI.ActiveControls.*" />
- </paths>
+ <paths>
+ <using namespace="System.Web.UI.ActiveControls.*" />
+ </paths>
</configuration>