From f0a6fad58f8eae14554443081ffb166aaf71762a Mon Sep 17 00:00:00 2001 From: wei <> Date: Tue, 29 Aug 2006 12:06:35 +0000 Subject: fixed autocomplete problem and add TInPlcaeTextbox --- .gitattributes | 2 + buildscripts/jsbuilder/build.php | 5 +- framework/Web/Javascripts/extended/base.js | 124 +++++++++- framework/Web/Javascripts/js/ajax.js | 45 +++- framework/Web/Javascripts/js/validator.js | 3 +- framework/Web/Javascripts/prado/activecontrols3.js | 2 +- framework/Web/Javascripts/prado/ajax3.js | 8 +- framework/Web/Javascripts/prado/inlineeditor.js | 208 +++++++++++++++++ framework/Web/Javascripts/prado/validation3.js | 16 +- framework/Web/UI/ActiveControls/TActiveTextBox.php | 25 ++ .../UI/ActiveControls/TCallbackClientScript.php | 9 - .../Web/UI/ActiveControls/TInPlaceTextBox.php | 256 +++++++++++++++++++++ 12 files changed, 663 insertions(+), 40 deletions(-) create mode 100644 framework/Web/Javascripts/prado/inlineeditor.js create mode 100644 framework/Web/UI/ActiveControls/TInPlaceTextBox.php diff --git a/.gitattributes b/.gitattributes index bd659c75..07d26923 100644 --- a/.gitattributes +++ b/.gitattributes @@ -1693,6 +1693,7 @@ framework/Web/Javascripts/prado/ajax3.js -text framework/Web/Javascripts/prado/controls.js -text framework/Web/Javascripts/prado/element.js -text framework/Web/Javascripts/prado/form.js -text +framework/Web/Javascripts/prado/inlineeditor.js -text framework/Web/Javascripts/prado/prado.js -text framework/Web/Javascripts/prado/validation3.js -text framework/Web/Javascripts/prototype/AUTHORS -text @@ -1750,6 +1751,7 @@ framework/Web/UI/ActiveControls/TCallbackClientScript.php -text framework/Web/UI/ActiveControls/TCallbackClientSide.php -text framework/Web/UI/ActiveControls/TCallbackOptions.php -text framework/Web/UI/ActiveControls/TEventTriggeredCallback.php -text +framework/Web/UI/ActiveControls/TInPlaceTextBox.php -text framework/Web/UI/ActiveControls/TTriggeredCallback.php -text framework/Web/UI/ActiveControls/TValueTriggeredCallback.php -text framework/Web/UI/TClientScriptManager.php -text diff --git a/buildscripts/jsbuilder/build.php b/buildscripts/jsbuilder/build.php index fa9ef72a..c4800851 100644 --- a/buildscripts/jsbuilder/build.php +++ b/buildscripts/jsbuilder/build.php @@ -103,7 +103,8 @@ $libraries = array( 'prado/ajax3.js', 'extra/json.js', 'effects/controls.js', - 'prado/activecontrols3.js' + 'prado/activecontrols3.js', + 'prado/inlineeditor.js' // 'effects/dragdrop.js', // 'effects/slider.js', // 'prado/activecontrols.js' @@ -174,7 +175,7 @@ foreach($libraries as $jsFile => $sourceFiles) $jsMin -> minify(); unset($jsMin); @unlink($tempFile); - echo "Saving file {$jsFile}\n"; + echo "Saving file {$jsFile}\n"; $builds++; } diff --git a/framework/Web/Javascripts/extended/base.js b/framework/Web/Javascripts/extended/base.js index cdb7958c..6b755f2d 100644 --- a/framework/Web/Javascripts/extended/base.js +++ b/framework/Web/Javascripts/extended/base.js @@ -2,10 +2,10 @@ /** * Similar to bindAsEventLister, but takes additional arguments. */ -Function.prototype.bindEvent = function() +Function.prototype.bindEvent = function() { var __method = this, args = $A(arguments), object = args.shift(); - return function(event) + return function(event) { return __method.apply(object, [event || window.event].concat(args)); } @@ -23,7 +23,7 @@ Class.extend = function(base, definition) { var component = Class.create(); Object.extend(component.prototype, base.prototype); - if(definition) + if(definition) Object.extend(component.prototype, definition); return component; } @@ -139,16 +139,18 @@ Base.implement = function(_interface) { * Signals and Slots for Prototype: Easy custom javascript events * http://tetlaw.id.au/view/blog/signals-and-slots-for-prototype-easy-custom-javascript-events * Andrew Tetlaw - * Version 1 (2006-05-03) + * Version 1.2 (2006-06-19) * * http://creativecommons.org/licenses/by-sa/2.5/ - */ + * Signal = { throwErrors : true, MT : function(){ return true }, connect : function(obj1, func1, obj2, func2, options) { var options = Object.extend({ - connectOnce : false + connectOnce : false, + before : false, + mutate : function() {return arguments;} }, options || {}); if(typeof func1 != 'string' || typeof func2 != 'string') return; @@ -160,8 +162,13 @@ Signal = { // having the slotFunc in a var and setting it by using an anonymous function in this way // is apparently a good way to prevent memory leaks in IE if the objects are DOM nodes. var slotFunc = function() { - var args = arguments; - var result = sigObj[signame].apply(sigObj,args); + var args = []; + for(var x = 0; x < arguments.length; x++){ + args.push(arguments[x]); + } + args = options.mutate.apply(null,args) + var result; + if(!options.before) result = sigObj[signame].apply(sigObj,arguments); //default: call sign before slot sigObj[slotsname].each(function(slot){ try { if(slot && slot[0]) { // testing for null, a disconnect may have nulled this slot @@ -171,7 +178,8 @@ Signal = { if(Signal.throwErrors) throw e; } }); - return result; + if(options.before) result = sigObj[signame].apply(sigObj,arguments); //call slot before sig + return result; //return sig result }; (function() { sigObj[slotsname] = $A([]); @@ -179,8 +187,8 @@ Signal = { sigObj[func1] = slotFunc; })(); } - var con = (sigObj[slotsname].length > 0) ? - (options.connectOnce ? !sigObj[slotsname].any(function(slot) { return (slot[0] == slotObj && slot[1] == func2) }) : true) : + var con = (sigObj[slotsname].length > 0) ? + (options.connectOnce ? !sigObj[slotsname].any(function(slot) { return (slot[0] == slotObj && slot[1] == func2) }) : true) : true; if(con) { sigObj[slotsname].push([slotObj,func2]); @@ -230,3 +238,97 @@ Signal = { Signal.disconnect(obj1, func1, obj2, func2, Object.extend(options || {}, {disconnectAll : true})) } } +*/ + +/* + Tests + +// 1. Simple Test 1 "hello Fred" should trigger "Fred is a stupid head" + + + sayHello = function(n) { + alert("Hello! " + n); + } + moron = function(n) { + alert(n + " is a stupid head"); + } + Signal.connect(null,'sayHello',null,'moron'); + + onclick="sayHello('Fred')" + + +// 2. Simple Test 2 repeated insults about Fred + + + Signal.connect(null,'sayHello2',null,'moron2'); + Signal.connect(null,'sayHello2',null,'moron2'); + Signal.connect(null,'sayHello2',null,'moron2'); + + +// 3. Simple Test 3 multiple insults about Fred + + + Signal.connect(null,'sayHello3',null,'moron3'); + Signal.connect(null,'sayHello3',null,'bonehead3'); + Signal.connect(null,'sayHello3',null,'idiot3'); + + +// 4. Simple Test 4 3 insults about Fred first - 3 then none + + + Signal.connect(null,'sayHello4',null,'moron4'); + Signal.connect(null,'sayHello4',null,'moron4'); + Signal.connect(null,'sayHello4',null,'moron4'); + Signal.disconnect(null,'sayHello4',null,'moron4'); + Signal.disconnect(null,'sayHello4',null,'moron4'); + Signal.disconnect(null,'sayHello4',null,'moron4'); + + +// 5. Simple Test 5 connect 3 insults about Fred first - only one, then none + + + Signal.connect(null,'sayHello5',null,'moron5'); + Signal.connect(null,'sayHello5',null,'moron5'); + Signal.connect(null,'sayHello5',null,'moron5'); + Signal.disconnectAll(null,'sayHello5',null,'moron5'); + + +// 6. Simple Test 6 connect 3 insults but only one comes out + + + Signal.connectOnce(null,'sayHello6',null,'moron6'); + Signal.connectOnce(null,'sayHello6',null,'moron6'); + Signal.connectOnce(null,'sayHello6',null,'moron6'); + + +// 7. Simple Test 7 connect via objects + + + var o = {}; + o.sayHello = function(n) { + alert("Hello! " + n + " (from object o)"); + } + var m = {}; + m.moron = function(n) { + alert(n + " is a stupid head (from object m)"); + } + + Signal.connect(o,'sayHello',m,'moron'); + + onclick="o.sayHello('Fred')" + + +// 8. Simple Test 8 connect but the insult comes first using {before:true} + + + Signal.connect(null,'sayHello8',null,'moron8', {before:true}); + + +// 9. Simple Test 9 connect but the insult is mutated + + + Signal.connect(null,'sayHello9',null,'moron9', {mutate:function() { return ['smelly ' + arguments[0]] }}); + + +*/ + */ \ No newline at end of file diff --git a/framework/Web/Javascripts/js/ajax.js b/framework/Web/Javascripts/js/ajax.js index 5d929f77..ada940df 100644 --- a/framework/Web/Javascripts/js/ajax.js +++ b/framework/Web/Javascripts/js/ajax.js @@ -62,8 +62,8 @@ msg+=e.version+" "+e.time+"\n";return msg;}},encode:function(data) return Prado.JSON.parse(data);else return null;},dispatchPriorityRequest:function(callback) {this.abortRequestInProgress();callback.request=new Ajax.Request(callback.url,callback.options);callback.timeout=setTimeout(function() -{Prado.CallbackRequest.abortRequestInProgress();},callback.options.RequestTimeOut);this.requestInProgress=callback;},dispatchNormalRequest:function(callback) -{new Ajax.Request(callback.url,callback.options);},abortRequestInProgress:function() +{Prado.CallbackRequest.abortRequestInProgress();},callback.options.RequestTimeOut);this.requestInProgress=callback;return true;},dispatchNormalRequest:function(callback) +{new Ajax.Request(callback.url,callback.options);return true;},abortRequestInProgress:function() {inProgress=Prado.CallbackRequest.requestInProgress;if(inProgress) {inProgress.request.transport.abort();clearTimeout(inProgress.timeout);Prado.CallbackRequest.requestInProgress=null;return true;} return false;},updatePageState:function(request,transport) @@ -88,10 +88,10 @@ Ajax.Responders.register(Prado.CallbackRequest.Exception);});Prado.CallbackReque {return this.options['ValidationGroup'];},dispatch:function() {Object.extend(this.options,{postBody:this._getPostData(),parameters:''});if(this.options.CausesValidation&&typeof(Prado.Validation)!="undefined") {var form=this.options.Form||Prado.Validation.getForm();if(Prado.Validation.validate(form,this.options.ValidationGroup,this)==false) -return;} +return false;} if(this.options.HasPriority) -Prado.CallbackRequest.dispatchPriorityRequest(this);else -Prado.CallbackRequest.dispatchNormalRequest(this);},_getPostData:function() +return Prado.CallbackRequest.dispatchPriorityRequest(this);else +return Prado.CallbackRequest.dispatchNormalRequest(this);},_getPostData:function() {var data={};var callback=Prado.CallbackRequest;if(this.options.PostInputs!=false) {callback.PostDataLoaders.each(function(name) {$A(document.getElementsByName(name)).each(function(element) @@ -212,7 +212,7 @@ this.onInit(options);},doCallback:function(event,options) {request=new Prado.CallbackRequest(options.EventTarget,options);request.dispatch();Event.stop(event);}},onClick:function(event) {var element=Event.findElement(event,'LI');this.index=element.autocompleteIndex;this.selectEntry();this.hide();Event.fireEvent(this.element,"change");},getUpdatedChoices:function() {options=new Array(this.getToken(),"__TAutoComplete_onSuggest__");Prado.Callback(this.options.EventTarget,options,null,this.options);},onComplete:function(request,boundary) -{result=Prado.Element.extractContent(request.responseText,boundary);if(typeof(result)=="string"&&result.length>0) +{result=Prado.Element.extractContent(request.transport.responseText,boundary);if(typeof(result)=="string"&&result.length>0) this.updateChoices(result);}});Prado.WebUI.TTimeTriggeredCallback=Base.extend({count:0,timeout:0,constructor:function(options) {this.options=Object.extend({Interval:1,DecayRate:0},options||{}) this.onComplete=this.options.onComplete;Prado.WebUI.TTimeTriggeredCallback.register(this);},startTimer:function() @@ -250,4 +250,35 @@ this.time=setTimeout(this.checkChanges.bind(this),parseInt(this.options.Interval {request=new Prado.CallbackRequest(this.options.ID,this.options);param={'OldValue':oldValue,'NewValue':newValue};request.setParameter(param);request.dispatch();}},{timers:{},register:function(timer) {this.timers[timer.options.ID]=timer;},stop:function(id) {if(this.timers[id]) -this.timers[id].stopObserving();}}); \ No newline at end of file +this.timers[id].stopObserving();}});Prado.WebUI.TInPlaceTextBox=Base.extend({isSaving:false,isEditing:false,editField:null,constructor:function(options) +{this.options=Object.extend({LoadTextFromSource:false,TextMode:'SingleLine'},options||{});this.element=$(this.options.ID);this.initializeListeners();},initializeListeners:function() +{this.onclickListener=this.enterEditMode.bindAsEventListener(this);Event.observe(this.element,'click',this.onclickListener);if(this.options.ExternalControl) +Event.observe($(this.options.ExternalControl),'click',this.onclickListener);},enterEditMode:function(evt) +{if(this.isSaving)return;if(this.isEditing)return;this.isEditing=true;this.onEnterEditMode();this.createEditorInput();this.showTextBox();this.editField.disabled=false;if(this.options.LoadTextOnEdit) +this.loadExternalText();Prado.Element.focus(this.editField);if(evt) +Event.stop(evt);return false;},showTextBox:function() +{Element.hide(this.element);Element.show(this.editField);},showLabel:function() +{Element.show(this.element);Element.hide(this.editField);},createEditorInput:function() +{if(this.editField==null) +this.createTextBox();this.editField.value=this.getText();},loadExternalText:function() +{this.editField.disabled=true;this.onLoadingText();options=new Array('__InlineEditor_loadExternalText__',this.getText());request=new Prado.CallbackRequest(this.options.EventTarget,this.options);request.setCausesValidation(false);request.setParameter(options);request.options.onSuccess=this.onloadExternalTextSuccess.bind(this);request.options.onFailure=this.onloadExternalTextFailure.bind(this);request.dispatch();},createTextBox:function() +{cssClass=this.options.TextBoxCssClass||'editor_field';inputName=this.options.EventTarget;options={'className':cssClass,name:inputName,id:this.options.TextBoxID};this.editField=this.options.TextMode=='SingleLine'?INPUT(options):TEXTAREA(options);this.editField.style.display="none";this.element.parentNode.insertBefore(this.editField,this.element) +if(this.options.TextMode=='SingleLine') +{Event.observe(this.editField,"keydown",function(e) +{if(Event.keyCode(e)==Event.KEY_RETURN) +{var target=Event.element(e);if(target) +{Event.fireEvent(target,"blur");Event.stop(e);}}});} +Event.observe(this.editField,"blur",this.onTextBoxBlur.bind(this));},getText:function() +{return this.element.innerHTML;},onEnterEditMode:function() +{if(typeof(this.options.onEnterEditMode)=="function") +this.options.onEnterEditMode(this,null);},onTextBoxBlur:function(e) +{text=this.element.innerHTML;if(text!=this.editField.value) +this.onTextChanged(text);else +{this.isEditing=false;this.showLabel();}},onTextChanged:function(text) +{request=new Prado.CallbackRequest(this.options.EventTarget,this.options);request.setParameter(text);request.options.onSuccess=this.onTextChangedSuccess.bind(this);request.options.onFailure=this.onTextChangedFailure.bind(this);if(request.dispatch()) +{this.isSaving=true;this.editField.disabled=true;}},onLoadingText:function() +{},onloadExternalTextSuccess:function(request,parameter) +{this.isEditing=true;this.editField.disabled=false;this.editField.value=this.getText();Prado.Element.focus(this.editField);},onloadExternalTextFailure:function(request,parameter) +{this.isSaving=false;this.isEditing=false;this.showLabel();},onTextChangedSuccess:function(sender,parameter) +{this.isSaving=false;this.isEditing=false;this.showLabel();this.element.innerHTML=parameter==null?this.editField.value:parameter;},onTextChangedFailure:function(sender,parameter) +{this.editField.disabled=false;this.isSaving=false;this.isEditing=false;}}); \ No newline at end of file diff --git a/framework/Web/Javascripts/js/validator.js b/framework/Web/Javascripts/js/validator.js index 711c996e..02380663 100644 --- a/framework/Web/Javascripts/js/validator.js +++ b/framework/Web/Javascripts/js/validator.js @@ -95,7 +95,8 @@ Prado.Element.focus(this.options.FocusElementID);this.visible=true;},updateContr control.removeClassName(CssClass);else control.addClassName(CssClass);}},hide:function() {this.isValid=true;this.updateControl();this.visible=false;},validate:function(invoker) -{if(typeof(this.options.OnValidate)=="function") +{if(!this.control) +this.control=$(this.options.ControlToValidate);if(typeof(this.options.OnValidate)=="function") this.options.OnValidate(this,invoker);if(this.enabled) this.isValid=this.evaluateIsValid();else this.isValid=true;if(this.isValid) diff --git a/framework/Web/Javascripts/prado/activecontrols3.js b/framework/Web/Javascripts/prado/activecontrols3.js index bd8aa6a5..e5be1d49 100644 --- a/framework/Web/Javascripts/prado/activecontrols3.js +++ b/framework/Web/Javascripts/prado/activecontrols3.js @@ -115,7 +115,7 @@ Prado.WebUI.TAutoComplete = Class.extend(Prado.WebUI.TAutoComplete, onComplete : function(request, boundary) { - result = Prado.Element.extractContent(request.responseText, boundary); + result = Prado.Element.extractContent(request.transport.responseText, boundary); if(typeof(result) == "string" && result.length > 0) this.updateChoices(result); } diff --git a/framework/Web/Javascripts/prado/ajax3.js b/framework/Web/Javascripts/prado/ajax3.js index c5683139..a11fe1aa 100644 --- a/framework/Web/Javascripts/prado/ajax3.js +++ b/framework/Web/Javascripts/prado/ajax3.js @@ -262,6 +262,7 @@ Object.extend(Prado.CallbackRequest, },callback.options.RequestTimeOut); this.requestInProgress = callback; + return true; //Logger.info("dispatched "+this.requestInProgress) }, @@ -272,6 +273,7 @@ Object.extend(Prado.CallbackRequest, { // Logger.info("dispatching normal request"); new Ajax.Request(callback.url, callback.options); + return true; }, /** @@ -460,13 +462,13 @@ Prado.CallbackRequest.prototype = { var form = this.options.Form || Prado.Validation.getForm(); if(Prado.Validation.validate(form,this.options.ValidationGroup,this) == false) - return; + return false; } if(this.options.HasPriority) - Prado.CallbackRequest.dispatchPriorityRequest(this); + return Prado.CallbackRequest.dispatchPriorityRequest(this); else - Prado.CallbackRequest.dispatchNormalRequest(this); + return Prado.CallbackRequest.dispatchNormalRequest(this); }, /** diff --git a/framework/Web/Javascripts/prado/inlineeditor.js b/framework/Web/Javascripts/prado/inlineeditor.js new file mode 100644 index 00000000..4eb33d5c --- /dev/null +++ b/framework/Web/Javascripts/prado/inlineeditor.js @@ -0,0 +1,208 @@ +Prado.WebUI.TInPlaceTextBox = Base.extend( +{ + isSaving : false, + isEditing : false, + editField : null, + + constructor : function(options) + { + this.options = Object.extend( + { + LoadTextFromSource : false, + TextMode : 'SingleLine' + + }, options || {}); + this.element = $(this.options.ID); + + this.initializeListeners(); + }, + + /** + * Initialize the listeners. + */ + initializeListeners : function() + { + this.onclickListener = this.enterEditMode.bindAsEventListener(this); + Event.observe(this.element, 'click', this.onclickListener); + if (this.options.ExternalControl) + Event.observe($(this.options.ExternalControl), 'click', this.onclickListener); + }, + + /** + * Changes the panel to an editable input. + * @param {Event} evt event source + */ + enterEditMode : function(evt) + { + if (this.isSaving) return; + if (this.isEditing) return; + this.isEditing = true; + this.onEnterEditMode(); + this.createEditorInput(); + this.showTextBox(); + this.editField.disabled = false; + if(this.options.LoadTextOnEdit) + this.loadExternalText(); + Prado.Element.focus(this.editField); + if (evt) + Event.stop(evt); + return false; + }, + + showTextBox : function() + { + Element.hide(this.element); + Element.show(this.editField); + }, + + showLabel : function() + { + Element.show(this.element); + Element.hide(this.editField); + }, + + /** + * Create the edit input field. + */ + createEditorInput : function() + { + if(this.editField == null) + this.createTextBox(); + + this.editField.value = this.getText(); + }, + + loadExternalText : function() + { + this.editField.disabled = true; + this.onLoadingText(); + options = new Array('__InlineEditor_loadExternalText__', this.getText()); + request = new Prado.CallbackRequest(this.options.EventTarget, this.options); + request.setCausesValidation(false); + request.setParameter(options); + request.options.onSuccess = this.onloadExternalTextSuccess.bind(this); + request.options.onFailure = this.onloadExternalTextFailure.bind(this); + request.dispatch(); + }, + + /** + * Create a new input textbox or textarea + */ + createTextBox : function() + { + cssClass= this.options.TextBoxCssClass || 'editor_field'; + inputName = this.options.EventTarget; + options = {'className' : cssClass, name : inputName, id : this.options.TextBoxID}; + this.editField = this.options.TextMode == 'SingleLine' ? INPUT(options) : TEXTAREA(options); + this.editField.style.display="none"; + this.element.parentNode.insertBefore(this.editField,this.element) + + //handle return key within single line textbox + if(this.options.TextMode == 'SingleLine') + { + Event.observe(this.editField, "keydown", function(e) + { + if(Event.keyCode(e) == Event.KEY_RETURN) + { + var target = Event.element(e); + if(target) + { + Event.fireEvent(target, "blur"); + Event.stop(e); + } + } + }); + } + + Event.observe(this.editField, "blur", this.onTextBoxBlur.bind(this)); + }, + + /** + * @return {String} panel inner html text. + */ + getText: function() + { + return this.element.innerHTML; + }, + + /** + * Edit mode entered, calls optional event handlers. + */ + onEnterEditMode : function() + { + if(typeof(this.options.onEnterEditMode) == "function") + this.options.onEnterEditMode(this,null); + }, + + onTextBoxBlur : function(e) + { + text = this.element.innerHTML; + if(text != this.editField.value) + this.onTextChanged(text); + else + { + this.isEditing = false; + this.showLabel(); + } + }, + + /** + * When the text input value has changed. + * @param {String} original text + */ + onTextChanged : function(text) + { + request = new Prado.CallbackRequest(this.options.EventTarget, this.options); + request.setParameter(text); + request.options.onSuccess = this.onTextChangedSuccess.bind(this); + request.options.onFailure = this.onTextChangedFailure.bind(this); + if(request.dispatch()) + { + this.isSaving = true; + this.editField.disabled = true; + } + }, + + /** + * When loading external text. + */ + onLoadingText : function() + { + //Logger.info("on loading text"); + }, + + onloadExternalTextSuccess : function(request, parameter) + { + this.isEditing = true; + this.editField.disabled = false; + this.editField.value = this.getText(); + Prado.Element.focus(this.editField); + }, + + onloadExternalTextFailure : function(request, parameter) + { + this.isSaving = false; + this.isEditing = false; + this.showLabel(); + }, + + /** + * Text change successfully. + * @param {Object} sender + * @param {Object} parameter + */ + onTextChangedSuccess : function(sender, parameter) + { + this.isSaving = false; + this.isEditing = false; + this.showLabel(); + this.element.innerHTML = parameter == null ? this.editField.value : parameter; + }, + + onTextChangedFailure : function(sender, parameter) + { + this.editField.disabled = false; + this.isSaving = false; + this.isEditing = false; + } +}); \ No newline at end of file diff --git a/framework/Web/Javascripts/prado/validation3.js b/framework/Web/Javascripts/prado/validation3.js index 7df6efeb..86659323 100644 --- a/framework/Web/Javascripts/prado/validation3.js +++ b/framework/Web/Javascripts/prado/validation3.js @@ -97,7 +97,7 @@ Object.extend(Prado.Validation, var keys = $H(this.managers).keys(); return keys[0]; }, - + /** * Check if the validators are valid for a particular form (and group). * The validators states will not be changed. @@ -656,6 +656,10 @@ Prado.WebUI.TBaseValidator.prototype = */ validate : function(invoker) { + //try to find the control. + if(!this.control) + this.control = $(this.options.ControlToValidate); + if(typeof(this.options.OnValidate) == "function") this.options.OnValidate(this, invoker); @@ -765,9 +769,9 @@ Prado.WebUI.TBaseValidator.prototype = return value; }, - /** + /** * The ControlType property comes from TBaseValidator::getClientControlClass() - * Be sure to update the TBaseValidator::$_clientClass if new cases are added. + * Be sure to update the TBaseValidator::$_clientClass if new cases are added. * @return mixed control value to validate */ getValidationValue : function(control) @@ -780,7 +784,7 @@ Prado.WebUI.TBaseValidator.prototype = if(control.type == "text") { value = this.trim($F(control)); - + if(this.options.DateFormat) { date = value.toDate(this.options.DateFormat); @@ -1125,7 +1129,7 @@ Prado.WebUI.TRangeValidator = Class.extend(Prado.WebUI.TBaseValidator, return true; if(typeof(this.options.DataType) == "undefined") this.options.DataType = "String"; - + if(this.options.DataType != "StringLength") { var min = this.convert(this.options.DataType, this.options.MinValue || null); @@ -1138,7 +1142,7 @@ Prado.WebUI.TRangeValidator = Class.extend(Prado.WebUI.TBaseValidator, var max = this.options.MaxValue || Number.POSITIVE_INFINITY; value = value.length; } - + if(value == null) return false; diff --git a/framework/Web/UI/ActiveControls/TActiveTextBox.php b/framework/Web/UI/ActiveControls/TActiveTextBox.php index 20358a36..c5f0f152 100644 --- a/framework/Web/UI/ActiveControls/TActiveTextBox.php +++ b/framework/Web/UI/ActiveControls/TActiveTextBox.php @@ -84,6 +84,31 @@ class TActiveTextBox extends TTextBox implements ICallbackEventHandler, IActiveC $this->raiseEvent('OnCallback', $this, $param); } + /** + * Loads user input data. + * This method is primarly used by framework developers. + * @param string the key that can be used to retrieve data from the input data collection + * @param array the input data collection + * @return boolean whether the data of the component has been changed + */ + public function loadPostData($key,$values) + { + $value=$values[$key]; + if($this->getAutoTrim()) + $value=trim($value); + if(!$this->getReadOnly() && $this->getText()!==$value) + { + $enabled = $this->getActiveControl()->getEnableUpdate(); + $this->getActiveControl()->setEnableUpdate(false); + $this->setText($value); + $this->getActiveControl()->setEnableUpdate($enabled); + return true; + } + else + return false; + } + + /** * Renders the javascript for textbox. */ diff --git a/framework/Web/UI/ActiveControls/TCallbackClientScript.php b/framework/Web/UI/ActiveControls/TCallbackClientScript.php index 4aa3efc6..bdbe6b1c 100644 --- a/framework/Web/UI/ActiveControls/TCallbackClientScript.php +++ b/framework/Web/UI/ActiveControls/TCallbackClientScript.php @@ -221,15 +221,6 @@ class TCallbackClientScript extends TApplicationComponent $this->replace($element, $content, 'Element.update'); } - /** - * Replace the innerHTML of a content with fragements of the response body. - * @param TControl|string control element or element id - */ -/* public function replaceContent($element) - { - $this->callClientFunction('Prado.Element.replaceContent', $element); - } -*/ /** * Add a Css class name to the element. * @param TControl|string control element or element id diff --git a/framework/Web/UI/ActiveControls/TInPlaceTextBox.php b/framework/Web/UI/ActiveControls/TInPlaceTextBox.php new file mode 100644 index 00000000..b783be88 --- /dev/null +++ b/framework/Web/UI/ActiveControls/TInPlaceTextBox.php @@ -0,0 +1,256 @@ +setAdapter(new TActiveControlAdapter($this)); + } + + /** + * @return TBaseActiveControl basic active control options. + */ + public function getActiveControl() + { + return $this->getAdapter()->getBaseActiveControl(); + } + + public function setEditTriggerControlID($value) + { + $this->setViewState('EditTriggerControlID', $value); + } + + public function getEditTriggerControlID() + { + return $this->getViewState('EditTriggerControlID'); + } + + /** + * @return string edit trigger control client ID. + */ + protected function getExternalControlID() + { + $extID = $this->getEditTriggerControlID(); + if(is_null($extID)) return ''; + if(($control = $this->findControl($extID))!==null) + return $control->getClientID(); + return $extID; + } + + /** + * Adds attributes to renderer. + * @param THtmlWriter the renderer + * @throws TInvalidDataValueException if associated control cannot be found using the ID + */ + protected function addAttributesToRender($writer) + { + parent::addAttributesToRender($writer); + $writer->addAttribute('id', $this->getLabelClientID()); + $this->renderClientControlScript($writer); + } + + protected function getLabelClientID() + { + return $this->getClientID().'__label'; + } + + /** + * On callback response, the inner HTMl of the label is updated. + * @param string the text value of the label + */ + public function setText($value) + { + parent::setText($value); + if($this->getActiveControl()->canUpdateClientSide()) + $this->getPage()->getCallbackClient()->update( + $this->getLabelClientID(), $value); + } + + /** + * Raises the callback event. This method is required by {@link + * ICallbackEventHandler} interface. + * This method is mainly used by framework and control developers. + * @param TCallbackEventParameter the event parameter + */ + public function raiseCallbackEvent($param) + { + $this->onCallback($param); + } + + public function setTextBoxCssClass($value) + { + $this->setViewState('TextBoxCssClass', $value); + } + + public function getTextBoxCssClass() + { + return $this->getViewState('TextBoxCssClass'); + } + + /** + * This method is invoked when a callback is requested. The method raises + * 'OnCallback' event to fire up the event handlers. If you override this + * method, be sure to call the parent implementation so that the event + * handler can be invoked. + * @param TCallbackEventParameter event parameter to be passed to the event handlers + */ + public function onCallback($param) + { + $action = $param->getParameter(); + if(is_array($action) && $action[0] === '__InlineEditor_loadExternalText__') + { + $parameter = new TCallbackEventParameter($this->getResponse(), $action[1]); + $this->onLoadingText($parameter); + } + $this->raiseEvent('OnCallback', $this, $param); + } + + /** + * @return array callback options. + */ + protected function getTextBoxOptions() + { + $options['ID'] = $this->getLabelClientID(); + $options['TextBoxID'] = $this->getClientID(); + $options['EventTarget'] = $this->getUniqueID(); + $options['CausesValidation'] = $this->getCausesValidation(); + $options['ValidationGroup'] = $this->getValidationGroup(); + $options['TextMode'] = $this->getTextMode(); + $options['ExternalControl'] = $this->getExternalControlID(); + $options['TextBoxCssClass'] = $this->getTextBoxCssClass(); + if($this->hasEventHandler('OnLoadingText')) + $options['LoadTextOnEdit'] = true; + return $options; + } + + /** + * @return string the behavior mode (SingleLine or MultiLine) of the TextBox component. Defaults to SingleLine. + */ + public function getTextMode() + { + return $this->getViewState('TextMode','SingleLine'); + } + + /** + * Sets the behavior mode (SingleLine or MultiLine) of the TextBox component. + * @param string the text mode + * @throws TInvalidDataValueException if the input value is not a valid text mode. + */ + public function setTextMode($value) + { + $this->setViewState('TextMode',TPropertyValue::ensureEnum($value,array('SingleLine','MultiLine')),'SingleLine'); + } + /** + * Returns the value to be validated. + * This methid is required by IValidatable interface. + * @return mixed the value of the property to be validated. + */ + public function getValidationPropertyValue() + { + return $this->getText(); + } + + /** + * @return boolean whether postback event trigger by this text box will cause input validation, default is true. + */ + public function getCausesValidation() + { + return $this->getViewState('CausesValidation',true); + } + + /** + * @param boolean whether postback event trigger by this text box will cause input validation. + */ + public function setCausesValidation($value) + { + $this->setViewState('CausesValidation',TPropertyValue::ensureBoolean($value),true); + } + + + /** + * @return string the group of validators which the text box causes validation upon postback + */ + public function getValidationGroup() + { + return $this->getViewState('ValidationGroup',''); + } + + /** + * @param string the group of validators which the text box causes validation upon postback + */ + public function setValidationGroup($value) + { + $this->setViewState('ValidationGroup',$value,''); + } + + /** + * Loads user input data. + * This method is primarly used by framework developers. + * @param string the key that can be used to retrieve data from the input data collection + * @param array the input data collection + * @return boolean whether the data of the component has been changed + */ + public function loadPostData($key,$values) + { + $value=$values[$key]; + if($this->getText()!==$value) + { + $enabled = $this->getActiveControl()->getEnableUpdate(); + $this->getActiveControl()->setEnableUpdate(false); + $this->setText($value); + $this->getActiveControl()->setEnableUpdate($enabled); + return true; + } + else + return false; + } + + public function raisePostDataChangedEvent() + { + $this->onTextChanged(null); + } + + public function onLoadingText($param) + { + $this->raiseEvent('OnLoadingText',$this,$param); + } + + /** + * Raises OnTextChanged event. + * This method is invoked when the value of the {@link getText Text} + * property changes on postback. + * If you override this method, be sure to call the parent implementation to ensure + * the invocation of the attached event handlers. + * @param TEventParameter event parameter to be passed to the event handlers + */ + public function onTextChanged($param) + { + $this->raiseEvent('OnTextChanged',$this,$param); + } + + /** + * Registers the javascript code for initializing the active control. + */ + protected function renderClientControlScript($writer) + { + $this->getActiveControl()->registerCallbackClientScript( + $this->getClientClassName(), $this->getTextBoxOptions()); + } + + /** + * @return string corresponding javascript class name for this TActiveLabelTextBox. + */ + protected function getClientClassName() + { + return 'Prado.WebUI.TInPlaceTextBox'; + } +} + +?> \ No newline at end of file -- cgit v1.2.3