summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--.gitattributes2
-rw-r--r--buildscripts/jsbuilder/build.php5
-rw-r--r--framework/Web/Javascripts/extended/base.js124
-rw-r--r--framework/Web/Javascripts/js/ajax.js45
-rw-r--r--framework/Web/Javascripts/js/validator.js3
-rw-r--r--framework/Web/Javascripts/prado/activecontrols3.js2
-rw-r--r--framework/Web/Javascripts/prado/ajax3.js8
-rw-r--r--framework/Web/Javascripts/prado/inlineeditor.js208
-rw-r--r--framework/Web/Javascripts/prado/validation3.js16
-rw-r--r--framework/Web/UI/ActiveControls/TActiveTextBox.php25
-rw-r--r--framework/Web/UI/ActiveControls/TCallbackClientScript.php9
-rw-r--r--framework/Web/UI/ActiveControls/TInPlaceTextBox.php256
12 files changed, 663 insertions, 40 deletions
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
@@ -85,6 +85,31 @@ class TActiveTextBox extends TTextBox implements ICallbackEventHandler, IActiveC
}
/**
+ * 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.
*/
protected function renderClientControlScript($writer)
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
@@ -222,15 +222,6 @@ class TCallbackClientScript extends TApplicationComponent
}
/**
- * 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
* @param string CssClass name to add.
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 @@
+<?php
+
+class TInPlaceTextBox extends TLabel implements
+ IActiveControl, ICallbackEventHandler, IPostBackDataHandler, IValidatable
+{
+ /**
+ * Creates a new callback control, sets the adapter to
+ * TActiveControlAdapter. If you override this class, be sure to set the
+ * adapter appropriately by, for example, by calling this constructor.
+ */
+ public function __construct()
+ {
+ parent::__construct();
+ $this->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 <b>OnTextChanged</b> 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