From 4aa1f46fcb508271b09cb5736d8bd0ef7206941d Mon Sep 17 00:00:00 2001
From: wei <>
Date: Thu, 27 Apr 2006 08:39:55 +0000
Subject: Added client-side events to client-side validators. see
tests/FunctionalTests/features/index.php?page=ValidatorEffects
---
.gitattributes | 4 +-
HISTORY | 4 +
UPGRADE | 4 +-
framework/Web/Javascripts/TJavaScript.php | 42 +-
framework/Web/Javascripts/js/prado.js | 2 +-
framework/Web/Javascripts/js/validator.js | 100 +--
framework/Web/Javascripts/prado/form.js | 2 +-
framework/Web/Javascripts/prado/prado.js | 2 +-
framework/Web/Javascripts/prado/validation.js | 767 ---------------------
framework/Web/Javascripts/prado/validation3.js | 134 ++--
framework/Web/Javascripts/prado/validators.js | 222 ------
framework/Web/UI/WebControls/TBaseValidator.php | 111 +++
framework/Web/UI/WebControls/TClientScript.php | 75 ++
.../features/protected/controls/Layout.tpl | 5 +
.../features/protected/pages/ValidatorEffects.page | 91 +++
15 files changed, 443 insertions(+), 1122 deletions(-)
delete mode 100644 framework/Web/Javascripts/prado/validation.js
delete mode 100644 framework/Web/Javascripts/prado/validators.js
create mode 100644 framework/Web/UI/WebControls/TClientScript.php
create mode 100644 tests/FunctionalTests/features/protected/pages/ValidatorEffects.page
diff --git a/.gitattributes b/.gitattributes
index c8fb6ada..f70aa0e5 100644
--- a/.gitattributes
+++ b/.gitattributes
@@ -710,9 +710,7 @@ 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/prado.js -text
-framework/Web/Javascripts/prado/validation.js -text
framework/Web/Javascripts/prado/validation3.js -text
-framework/Web/Javascripts/prado/validators.js -text
framework/Web/Javascripts/prototype/AUTHORS -text
framework/Web/Javascripts/prototype/LICENSE -text
framework/Web/Javascripts/prototype/README -text
@@ -771,6 +769,7 @@ framework/Web/UI/WebControls/TButtonColumn.php -text
framework/Web/UI/WebControls/TCheckBox.php -text
framework/Web/UI/WebControls/TCheckBoxColumn.php -text
framework/Web/UI/WebControls/TCheckBoxList.php -text
+framework/Web/UI/WebControls/TClientScript.php -text
framework/Web/UI/WebControls/TColorPicker.php -text
framework/Web/UI/WebControls/TCompareValidator.php -text
framework/Web/UI/WebControls/TContent.php -text
@@ -859,6 +858,7 @@ tests/FunctionalTests/features/protected/pages/I18N/Home.page -text
tests/FunctionalTests/features/protected/pages/I18N/Home.zh_CN.page -text
tests/FunctionalTests/features/protected/pages/I18N/config.xml -text
tests/FunctionalTests/features/protected/pages/RatingList.page -text
+tests/FunctionalTests/features/protected/pages/ValidatorEffects.page -text
tests/FunctionalTests/index.php -text
tests/FunctionalTests/quickstart.php -text
tests/FunctionalTests/quickstart/Advanced/I18N.php -text
diff --git a/HISTORY b/HISTORY
index 1d9430ed..cd9c8482 100644
--- a/HISTORY
+++ b/HISTORY
@@ -16,12 +16,16 @@ ENH: TButtonColumn can now be a column of image buttons (Qiang)
ENH: TLiteral will display body content if Text is empty (Qiang)
ENH: Format string in classes extending TDataGridColumn can now evaluate an expression (Qiang)
ENH: Format string in classes extending TListControl can now evaluate an expression (Qiang)
+ENH: Custom visual effects can be added to client-side validators. (Wei)
+ENH: TJavascript::encode() allows raw javascript code when string begins with "javascript:" (Wei)
CHG: Rewrote client-side javascript validators, check your client-side validation behaviour (Wei)
CHG: Updated the javascript Prototype library, a few utilties functions REMOVED, may break your existing javascript code. (Wei)
CHG: Build javascript without compression, only comments are removed. (Wei)
CHG: TDatePicker's date can be set using Date property, it value must be in same format as DateFormat, TimeStamp must be set as integer (wei)
CHG: TSimpleDateFormatter::parse() now return an integer or null on parse error (Wei)
NEW: TListControlValidator (Wei)
+NEW: TClientScript (Wei)
+
Version 3.0RC2 April 16, 2006
diff --git a/UPGRADE b/UPGRADE
index 20c91cc9..ccf8c289 100644
--- a/UPGRADE
+++ b/UPGRADE
@@ -16,7 +16,9 @@ for both A and B.
Upgrading from v3.0.0 RC2
-------------------------
-There should be no compatibility issues.
+There should be no PHP compatibility issues. Javascript libraries
+were updated and client-side validators rewritten.
+
Upgrading from v3.0.0 RC1
diff --git a/framework/Web/Javascripts/TJavaScript.php b/framework/Web/Javascripts/TJavaScript.php
index a3848201..75fc2438 100644
--- a/framework/Web/Javascripts/TJavaScript.php
+++ b/framework/Web/Javascripts/TJavaScript.php
@@ -84,6 +84,26 @@ class TJavaScript
else
return strtr($js,array("\t"=>'\t',"\n"=>'\n',"\r"=>'\r','"'=>'\"','\''=>'\\\'','\\'=>'\\\\'));
}
+
+ /**
+ * @return string considers the string as raw javascript function code
+ */
+ public static function quoteFunction($js)
+ {
+ if(self::isFunction($js))
+ return $js;
+ else
+ return 'javascript:'.$js;
+ }
+
+ /**
+ * @return boolean true if string is raw javascript function code, i.e., if
+ * the string begins with javascript:
+ */
+ public static function isFunction($js)
+ {
+ return preg_match('/^\s*javascript:/', $js);
+ }
/**
* Encodes a PHP variable into javascript representation.
@@ -96,16 +116,12 @@ class TJavaScript
* //expects the following javascript code
* // {'onLoading':'doit','onComplete':'more'}
*
- *
- * To pass raw javascript statements start strings with
- * javascript:. E.g.
- *
- * $options['onLoading'] = "javascript:function(){ alert('hello'); }";
- * //outputs {'onLoading':function(){ alert('hello'); }}
- *
*
- * For higher complexity data structures use {@link jsonEncode} and {@link
- * jsonDecode} to serialize and unserialize.
+ * For higher complexity data structures use {@link jsonEncode} and {@link jsonDecode}
+ * to serialize and unserialize.
+ *
+ * Note: strings begining with javascript: will be considered as
+ * raw javascript code and no encoding of that string will be enforced.
*
* @param mixed PHP variable to be encoded
* @param boolean whether the output is a map or a list.
@@ -122,9 +138,11 @@ class TJavaScript
if(($first==='[' && $last===']') || ($first==='{' && $last==='}'))
return $value;
}
- else if(strpos($value, 'javascript:')===0)
- return substr($value,11);
- return "'".self::quoteString($value)."'";
+ // if string begins with javascript: return the raw string minus the prefix
+ if(self::isFunction($value))
+ return preg_replace('/^\s*javascript:/', '', $value);
+ else
+ return "'".self::quoteString($value)."'";
}
else if(is_bool($value))
return $value?'true':'false';
diff --git a/framework/Web/Javascripts/js/prado.js b/framework/Web/Javascripts/js/prado.js
index c7145188..9e01fe42 100644
--- a/framework/Web/Javascripts/js/prado.js
+++ b/framework/Web/Javascripts/js/prado.js
@@ -1850,7 +1850,7 @@ var form = $(options['FormID']);
var canSubmit = true;
if(options['CausesValidation'] && typeof(Prado.Validation) != "undefined")
{
-if(!Prado.Validation.validate(options['FormID'], options['ValidationGroup']))
+if(!Prado.Validation.validate(options['FormID'], options['ValidationGroup'], $(options['ID'])))
return Event.stop(event);
}
if(options['PostBackUrl'] && options['PostBackUrl'].length > 0)
diff --git a/framework/Web/Javascripts/js/validator.js b/framework/Web/Javascripts/js/validator.js
index 8659d2e9..a68fbfa1 100644
--- a/framework/Web/Javascripts/js/validator.js
+++ b/framework/Web/Javascripts/js/validator.js
@@ -3,11 +3,11 @@ Prado.Validation =Class.create();
Object.extend(Prado.Validation,
{
managers : {},
-validate : function(formID, groupID)
+validate : function(formID, groupID, invoker)
{
if(this.managers[formID])
{
-return this.managers[formID].validate(groupID);
+return this.managers[formID].validate(groupID, invoker);
}
else
{
@@ -49,14 +49,14 @@ initialize : function(options)
this.options = options;
Prado.Validation.managers[options.FormID] = this;
},
-validate : function(group)
+validate : function(group, invoker)
{
if(group)
-return this._validateGroup(group);
+return this._validateGroup(group, invoker);
else
-return this._validateNonGroup();
+return this._validateNonGroup(invoker);
},
-_validateGroup: function(groupID)
+_validateGroup: function(groupID, invoker)
{
var valid = true;
if(this.groups.include(groupID))
@@ -64,7 +64,7 @@ if(this.groups.include(groupID))
this.validators.each(function(validator)
{
if(validator.group == groupID)
-valid = valid & validator.validate();
+valid = valid & validator.validate(invoker);
else
validator.hide();
});
@@ -72,13 +72,13 @@ validator.hide();
this.updateSummary(groupID, true);
return valid;
},
-_validateNonGroup : function()
+_validateNonGroup : function(invoker)
{
var valid = true;
this.validators.each(function(validator)
{
if(!validator.group)
-valid = valid & validator.validate();
+valid = valid & validator.validate(invoker);
else
validator.hide();
});
@@ -275,11 +275,9 @@ options : {},
_isObserving : {},
group : null,
manager : null,
+message : null,
initialize : function(options)
{
-options.OnValidate = options.OnValidate || Prototype.emptyFunction;
-options.OnSuccess = options.OnSuccess || Prototype.emptyFunction;
-options.OnError = options.OnError || Prototype.emptyFunction;
this.options = options;
this.control = $(options.ControlToValidate);
this.message = $(options.ID);
@@ -321,16 +319,34 @@ this.isValid = true;
this.updateControl();
this.visible = false;
},
-validate : function()
+validate : function(invoker)
{
if(this.enabled)
this.isValid = this.evaluateIsValid();
-this.options.OnValidate(this);
-this.updateControl();
+if(typeof(this.options.OnValidate) == "function")
+this.options.OnValidate(this, invoker);
if(this.isValid)
-this.options.OnSuccess(this);
+{
+if(typeof(this.options.OnSuccess) == "function")
+{
+this.visible = true;
+this.updateControlCssClass(this.control, this.isValid);
+this.options.OnSuccess(this, invoker);
+}
else
-this.options.OnError(this);
+this.updateControl();
+}
+else
+{
+if(typeof(this.options.OnError) == "function")
+{
+this.visible = true;
+this.updateControlCssClass(this.control, this.isValid);
+this.options.OnError(this, invoker);
+}
+else
+this.updateControl();
+}
this.observeChanges(this.control);
return this.isValid;
},
@@ -353,7 +369,7 @@ validator.manager.updateSummary(validator.group);
this._isObserving[control.id+this.options.ID] = true;
}
},
-_trim : function(value)
+trim : function(value)
{
return typeof(value) == "string" ? value.trim() : "";
},
@@ -393,20 +409,20 @@ getValidationValue : function(control)
{
case 'TDatePicker':
if(control.type == "text")
- return this._trim($F(control));
+ return this.trim($F(control));
else
{
- this._observeDatePickerChanges();
+ this.observeDatePickerChanges();
return Prado.WebUI.TDatePicker.getDropDownDate(control).getTime();
}
default:
- if(this._isListControlType())
- return this._getFirstSelectedListValue();
+ if(this.isListControlType())
+ return this.getFirstSelectedListValue();
else
- return this._trim($F(control));
+ return this.trim($F(control));
}
},
-_observeDatePickerChanges : function()
+observeDatePickerChanges : function()
{
if(Prado.Browser().ie)
{
@@ -416,11 +432,11 @@ this.observeChanges(DatePicker.getMonthListControl(this.control));
this.observeChanges(DatePicker.getYearListControl(this.control));
}
},
-_getSelectedValuesAndChecks : function(elements, initialValue)
+getSelectedValuesAndChecks : function(elements, initialValue)
{
var checked = 0;
var values = [];
-var isSelected = this._isCheckBoxType(elements[0]) ? 'checked' : 'selected';
+var isSelected = this.isCheckBoxType(elements[0]) ? 'checked' : 'selected';
elements.each(function(element)
{
if(element[isSelected] && element.value != initialValue)
@@ -431,7 +447,7 @@ values.push(element.value);
});
return {'checks' : checked, 'values' : values};
},
-_getListElements : function()
+getListElements : function()
{
switch(this.options.ControlType)
{
@@ -440,7 +456,7 @@ var elements = [];
for(var i = 0; i < this.options.TotalItems; i++)
{
var element = $(this.options.ControlToValidate+"_"+i);
-if(this._isCheckBoxType(element))
+if(this.isCheckBoxType(element))
elements.push(element);
}
return elements;
@@ -457,7 +473,7 @@ default:
return [];
}
},
-_isCheckBoxType : function(element)
+isCheckBoxType : function(element)
{
if(element && element.type)
{
@@ -466,18 +482,18 @@ return type == "checkbox" || type == "radio";
}
return false;
},
-_isListControlType : function()
+isListControlType : function()
{
var list = ['TCheckBoxList', 'TRadioButtonList', 'TListBox'];
return list.include(this.options.ControlType);
},
-_getFirstSelectedListValue : function()
+getFirstSelectedListValue : function()
{
var initial = "";
if(typeof(this.options.InitialValue) != "undefined")
initial = this.options.InitialValue;
-var elements = this._getListElements();
-var selection = this._getSelectedValuesAndChecks(elements, initial);
+var elements = this.getListElements();
+var selection = this.getSelectedValuesAndChecks(elements, initial);
return selection.values.length > 0 ? selection.values[0] : initial;
}
}
@@ -493,7 +509,7 @@ return true;
else
{
var a = this.getValidationValue();
-var b = this._trim(this.options.InitialValue);
+var b = this.trim(this.options.InitialValue);
return(a != b);
}
}
@@ -595,16 +611,16 @@ Prado.WebUI.TListControlValidator = Class.extend(Prado.WebUI.TBaseValidator,
{
evaluateIsValid : function()
{
-var elements = this._getListElements();
+var elements = this.getListElements();
if(elements && elements.length <= 0)
return true;
this.observeListElements(elements);
-var selection = this._getSelectedValuesAndChecks(elements);
+var selection = this.getSelectedValuesAndChecks(elements);
return this.isValidList(selection.checks, selection.values);
},
observeListElements : function(elements)
{
-if(Prado.Browser().ie && this._isCheckBoxType(elements[0]))
+if(Prado.Browser().ie && this.isCheckBoxType(elements[0]))
{
var validator = this;
elements.each(function(element)
@@ -640,13 +656,3 @@ required = this.options.Required.split(/,\s*/);
return required;
}
});
-Prado.WebUI.TDataTypeValidator = Class.extend(Prado.WebUI.TBaseValidator,
-{
-evaluateIsValid : function()
-{
-var value = this.getValidationValue();
-if(value.length <= 0)
-return true;
-return this.convert(this.options.DataType, value) != null;
-}
-});
diff --git a/framework/Web/Javascripts/prado/form.js b/framework/Web/Javascripts/prado/form.js
index 2beb945b..aec9395d 100644
--- a/framework/Web/Javascripts/prado/form.js
+++ b/framework/Web/Javascripts/prado/form.js
@@ -107,7 +107,7 @@ Prado.PostBack = function(event,options)
if(options['CausesValidation'] && typeof(Prado.Validation) != "undefined")
{
- if(!Prado.Validation.validate(options['FormID'], options['ValidationGroup']))
+ if(!Prado.Validation.validate(options['FormID'], options['ValidationGroup'], $(options['ID'])))
return Event.stop(event);
}
diff --git a/framework/Web/Javascripts/prado/prado.js b/framework/Web/Javascripts/prado/prado.js
index e63c2718..d75c3dda 100644
--- a/framework/Web/Javascripts/prado/prado.js
+++ b/framework/Web/Javascripts/prado/prado.js
@@ -1,7 +1,7 @@
var Prado =
{
- Version: '3.0a',
+ Version: '3.0',
/**
* Returns browser information. Example
diff --git a/framework/Web/Javascripts/prado/validation.js b/framework/Web/Javascripts/prado/validation.js
deleted file mode 100644
index 454f53f0..00000000
--- a/framework/Web/Javascripts/prado/validation.js
+++ /dev/null
@@ -1,767 +0,0 @@
-
-/**
- * Prado client-side javascript validation class.
- */
-Prado.Validation = Class.create();
-
-/**
- * Utilities for validation. Static class.
- */
-Prado.Validation.Util = Class.create();
-
-/**
- * Convert a string into integer, returns null if not integer.
- * @param {string} the string to convert to integer
- * @type {integer|null} null if string does not represent an integer.
- */
-Prado.Validation.Util.toInteger = function(value)
-{
- var exp = /^\s*[-\+]?\d+\s*$/;
- if (value.match(exp) == null)
- return null;
- var num = parseInt(value, 10);
- return (isNaN(num) ? null : num);
-}
-
-/**
- * Convert a string into a double/float value. Internationalization
- * is not supported
- * @param {string} the string to convert to double/float
- * @param {string} the decimal character
- * @return {float|null} null if string does not represent a float value
- */
-Prado.Validation.Util.toDouble = function(value, decimalchar)
-{
- decimalchar = undef(decimalchar) ? "." : decimalchar;
- var exp = new RegExp("^\\s*([-\\+])?(\\d+)?(\\" + decimalchar + "(\\d+))?\\s*$");
- var m = value.match(exp);
- if (m == null)
- return null;
- var cleanInput = m[1] + (m[2].length>0 ? m[2] : "0") + "." + m[4];
- var num = parseFloat(cleanInput);
- return (isNaN(num) ? null : num);
-}
-
-/**
- * Convert strings that represent a currency value (e.g. a float with grouping
- * characters) to float. E.g. "10,000.50" will become "10000.50". The number
- * of dicimal digits, grouping and decimal characters can be specified.
- * The currency input format is very strict, null will be returned if
- * the pattern does not match.
- * @param {string} the currency value
- * @param {string} the grouping character, default is ","
- * @param {int} number of decimal digits
- * @param {string} the decimal character, default is "."
- * @type {float|null} the currency value as float.
- */
-Prado.Validation.Util.toCurrency = function(value, groupchar, digits, decimalchar)
-{
- groupchar = undef(groupchar) ? "," : groupchar;
- decimalchar = undef(decimalchar) ? "." : decimalchar;
- digits = undef(digits) ? 2 : digits;
-
- var exp = new RegExp("^\\s*([-\\+])?(((\\d+)\\" + groupchar + ")*)(\\d+)"
- + ((digits > 0) ? "(\\" + decimalchar + "(\\d{1," + digits + "}))?" : "")
- + "\\s*$");
- var m = value.match(exp);
- if (m == null)
- return null;
- var intermed = m[2] + m[5] ;
- var cleanInput = m[1] + intermed.replace(
- new RegExp("(\\" + groupchar + ")", "g"), "")
- + ((digits > 0) ? "." + m[7] : "");
- var num = parseFloat(cleanInput);
- return (isNaN(num) ? null : num);
-}
-
-/**
- * Get the date from string using the prodivided date format string.
- * The format notations are
- * # day -- %d or %e
- * # month -- %m
- * # year -- %y or %Y
- * # hour -- %H, %I, %k, or %l
- * # minutes -- %M
- * # P.M. -- %p or %P
- * @param {string} the formatted date string
- * @param {string} the date format
- * @type {Date} the date represented in the string
- */
-Prado.Validation.Util.toDate = function(value, format)
-{
- var y = 0;
- var m = -1;
- var d = 0;
- var a = value.split(/\W+/);
- var b = format.match(/%./g);
- var i = 0, j = 0;
- var hr = 0;
- var min = 0;
- for (i = 0; i < a.length; ++i) {
- if (!a[i])
- continue;
- switch (b[i]) {
- case "%d":
- case "%e":
- d = parseInt(a[i], 10);
- break;
-
- case "%m":
- m = parseInt(a[i], 10) - 1;
- break;
-
- case "%Y":
- case "%y":
- y = parseInt(a[i], 10);
- (y < 100) && (y += (y > 29) ? 1900 : 2000);
- break;
-
- case "%H":
- case "%I":
- case "%k":
- case "%l":
- hr = parseInt(a[i], 10);
- break;
-
- case "%P":
- case "%p":
- if (/pm/i.test(a[i]) && hr < 12)
- hr += 12;
- break;
-
- case "%M":
- min = parseInt(a[i], 10);
- break;
- }
- }
- if (y != 0 && m != -1 && d != 0)
- {
- var date = new Date(y, m, d, hr, min, 0);
- return (isObject(date)
- && y == date.getFullYear()
- && m == date.getMonth()
- && d == date.getDate()) ? date.valueOf() : null;
- }
- return null;
-}
-
-/**
- * Trim the value, if the value is undefined, empty string is return.
- * @param {string} string to be trimmed.
- * @type {string} trimmed string.
- */
-Prado.Validation.trim = function(value)
-{
- if(isString(value)) return value.trim();
- return "";
-}
-
-/**
- * A delayed focus on a particular element
- * @param {element} element to apply focus()
- */
-Prado.Validation.Util.focus = function(element)
-{
- var obj = $(element);
- if(isObject(obj) && isdef(obj.focus))
- setTimeout(function(){ obj.focus(); }, 100);
- return false;
-}
-
-/**
- * List of validator instances.
- */
-Prado.Validation.validators = [];
-
-/**
- * List of forms.
- * @type {int}
- */
-Prado.Validation.forms = [];
-
-/**
- * List of summary controls.
- */
-Prado.Validation.summaries = [];
-
-/**
- * Validation groups.
- */
-Prado.Validation.groups = [];
-
-
-/**
- * Second type of grouping.
- */
-Prado.Validation.TargetGroups = {};
-
-
-/**
- * Current Target group.
- */
-Prado.Validation.CurrentTargetGroup = null;
-
-Prado.Validation.HasTargetGroup = false;
-
-/**
- * Targets that can cause validation.
- */
-Prado.Validation.ActiveTarget = null;
-
-
-/**
- * Determine if group validation is active.
- */
-Prado.Validation.IsGroupValidation = false;
-
-/**
- * Add a form for validation.
- * @param {string} form ID
- */
-Prado.Validation.AddForm = function(id)
-{
- Prado.Validation.forms.push($(id));
-}
-
-/**
- * Add a target that causes validation. Only elements that have been added
- * can cause validation.
- * @param {string} target id
- */
-Prado.Validation.AddTarget = function(id, group)
-{
- var target = $(id);
- Event.observe(target, "click", function()
- {
- Prado.Validation.ActiveTarget = target;
- Prado.Validation.CurrentTargetGroup = Prado.Validation.TargetGroups[id];
- });
- if(group)
- {
- Prado.Validation.TargetGroups[id] = group;
- Prado.Validation.HasTargetGroup = true;
- }
-}
-
-Prado.Validation.SetActiveGroup = function(target, group)
-{
- Prado.Validation.ActiveTarget = target;
- Prado.Validation.CurrentTargetGroup = group;
-}
-
-/**
- * Associate a list of validators to a particular control element.
- * This essentially allows a set of validators to be grouped to a particular button.
- * @param {list} group array show have, {group : "id", target : "target button"}
- * @param {array} validator ids
- */
-Prado.Validation.AddGroup = function(group, validators)
-{
- group.active = false; //default active status is false.
- group.target = $(group.target);
- group.validators = validators;
- Prado.Validation.groups.push(group);
-
- //update the active group when the button is clicked.
- Event.observe(group.target, "click", Prado.Validation.UpdateActiveGroup);
-}
-
-/**
- * Update the active group, if call manually it will deactivate all groups.
- * @param {string}
- * @type {int}
- */
-Prado.Validation.UpdateActiveGroup = function(ev)
-{
- var groups = Prado.Validation.groups;
- for (var i = 0; i < groups.length; i++)
- {
- groups[i].active = (isdef(ev) && groups[i].target == Event.element(ev));
- }
- Prado.Validation.IsGroupValidation = isdef(ev);
-}
-
-/**
- * Determine if validation is sucessful. Iterate through the list
- * of validator instances and call validate(). Only validators that
- * for a particular form are evaluated. Other validators will be disabled.
- * If performing group validation, only active validators are visible.
- * @param {element} the form for the controls to validate.
- * @type {boolean} true is all validators are valid, false otherwise.
- */
-Prado.Validation.IsValid = function(form)
-{
- var valid = true;
- var validators = Prado.Validation.validators;
-
- for(var i = 0; i < validators.length; i++)
- {
- //prevent validating multiple forms
- validators[i].enabled = !validators[i].control || undef(validators[i].control.form) || validators[i].control.form == form;
- //when group validation, only validators in the active group are visible.
- validators[i].visible = Prado.Validation.IsGroupValidation ? validators[i].inActiveGroup() : true;
-
- if(Prado.Validation.HasTargetGroup)
- validators[i].enabled = Prado.Validation.CurrentTargetGroup == validators[i].group
-
- valid &= validators[i].validate();
- }
-
- //show the summary including the alert box
- Prado.Validation.ShowSummary(form);
- //reset all the group active status to false
- Prado.Validation.UpdateActiveGroup();
-
- return valid;
-}
-
-/**
- * Base validator class. Supply a different validation function
- * to obtain a different validator. E.g. to use the RequiredFieldValidator
- * new Prado.Validation(Prado.Validation.RequiredFieldValidator, options);
- * or to use the CustomValidator,
- * new Prado.Validation(Prado.Validation.CustomValidator, options);
- */
-Prado.Validation.prototype =
-{
- /**
- * Initialize the validator.
- * @param {function} the function to call to evaluate if
- * the validator is valid
- * @param {string|element} the control ID or element
- * @param {array} the list of attributes for the validator
- */
- initialize : function(validator, attr)
- {
- this.evaluateIsValid = validator;
- this.attr = undef(attr) ? [] : attr;
- this.message = $(attr.id);
- this.control = $(attr.controltovalidate);
- this.enabled = isdef(attr.enabled) ? attr.enabled : true;
- this.visible = isdef(attr.visible) ? attr.visible : true;
- this.group = isdef(attr.validationgroup) ? attr.validationgroup : null;
- this.isValid = true;
- Prado.Validation.validators.push(this);
- if(this.evaluateIsValid)
- this.evaluateIsValid.bind(this);
- },
-
- /**
- * Evaluate the validator only when visible and enabled.
- * @type {boolean} true if valid, false otherwise.
- */
- validate : function()
- {
- if(this.visible && this.enabled && this.evaluateIsValid)
- this.isValid = this.evaluateIsValid();
- else
- this.isValid = true;
-
- this.observe(); //watch for changes to the control values
- this.update(); //update the validation messages
- return this.isValid;
- },
-
- /**
- * Hide or show the error messages for "Dynamic" displays.
- */
- update : function()
- {
- if(this.attr.display == "Dynamic")
- this.isValid ? Element.hide(this.message) : Element.show(this.message);
-
- if(this.message)
- this.message.style.visibility = this.isValid ? "hidden" : "visible";
-
- //update the control css class name
- var className = this.attr.controlcssclass;
- if(this.control && isString(className) && className.length>0)
- Element.condClassName(this.control, className, !this.isValid);
- Prado.Validation.ShowSummary();
-
- var focus = this.attr.focusonerror;
- var hasGroup = Prado.Validation.HasTargetGroup;
- var inGroup = this.group == Prado.Validation.CurrentTargetGroup;
-
- if(focus && (!hasGroup || (hasGroup && inGroup)))
- Prado.Element.focus(this.attr.focuselementid);
- },
-
- /**
- * Change the validity of the validator, calls update().
- * @param {boolean} change the isValid state of the validator.
- */
- setValid : function(valid)
- {
- this.isValid = valid;
- this.update();
- },
-
- /**
- * Observe changes to the control values, add "onchange" event to the control once.
- */
- observe : function()
- {
- if(undef(this.observing))
- {
- if(this.control && this.control.form)
- Event.observe(this.control, "change", this.validate.bind(this));
- this.observing = true;
- }
- },
-
- /**
- * Convert the value of the control to a specific data type.
- * @param {string} the data type, "Integer", "Double", "Currency" or "Date".
- * @param {string} the value to convert, null to get the value from the control.
- * @type {mixed|null} the converted data value.
- */
- convert : function(dataType, value)
- {
- if(undef(value))
- value = Form.Element.getValue(this.control);
- switch(dataType)
- {
- case "Integer":
- return Prado.Validation.Util.toInteger(value);
- case "Double" :
- case "Float" :
- return Prado.Validation.Util.toDouble(value, this.attr.decimalchar);
- case "Currency" :
- return Prado.Validation.Util.toCurrency(
- value, this.attr.groupchar, this.attr.digits, this.attr.decimalchar);
- case "Date":
- return Prado.Validation.Util.toDate(value, this.attr.dateformat);
- }
- return value.toString();
- },
-
- /**
- * Determine if the current validator is part of a active validation group.
- * @type {boolean} true if part of active validation group, false otherwise.
- */
- inActiveGroup : function()
- {
- var groups = Prado.Validation.groups;
- for (var i = 0; i < groups.length; i++)
- {
- if(groups[i].active && groups[i].validators.contains(this.attr.id))
- return true;
- }
- return false;
- }
-}
-
-/**
- * Validation summary class.
- */
-Prado.Validation.Summary = Class.create();
-Prado.Validation.Summary.prototype =
-{
- /**
- * Initialize a validation summary.
- * @param {array} summary options.
- */
- initialize : function(attr)
- {
- this.attr = attr;
- this.div = $(attr.id);
- this.visible = false;
- this.enabled = false;
- this.group = isdef(attr.validationgroup) ? attr.validationgroup : null;
- Prado.Validation.summaries.push(this);
- },
-
- /**
- * Show the validation summary.
- * @param {boolean} true to allow alert message
- */
- show : function(warn)
- {
- var refresh = warn || this.attr.refresh == "1";
- var messages = this.getMessages();
- if(messages.length <= 0 || !this.visible || !this.enabled)
- {
- if(refresh)
- {
- if(this.attr.display == "None" || this.attr.display == "Dynamic")
- Element.hide(this.div);
- else
- this.div.style.visibility="hidden";
- }
- return;
- }
-
- if(Prado.Validation.HasTargetGroup)
- {
- if(Prado.Validation.CurrentTargetGroup != this.group)
- {
- if(refresh)
- {
- if(this.attr.display == "None" || this.attr.display == "Dynamic")
- Element.hide(this.div);
- else
- this.div.style.visibility="hidden";
- }
- return;
- }
- }
-
- if(this.attr.showsummary != "False" && refresh)
- {
- //Element.show(this.div);
- this.div.style.display = "block";
- this.div.style.visibility = "visible";
- while(this.div.childNodes.length > 0)
- this.div.removeChild(this.div.lastChild);
- new Insertion.Bottom(this.div, this.formatSummary(messages));
- }
-
- if(warn)
- window.scrollTo(this.div.offsetLeft-20, this.div.offsetTop-20);
-
- var summary = this;
- if(warn && this.attr.showmessagebox == "True" && refresh)
- setTimeout(function(){alert(summary.formatMessageBox(messages));},20);
- },
-
- /**
- * Get a list of error messages from the validators.
- * @type {array} list of messages
- */
- getMessages : function()
- {
- var validators = Prado.Validation.validators;
- var messages = [];
- for(var i = 0; i < validators.length; i++)
- {
- if(validators[i].isValid == false
- && isString(validators[i].attr.errormessage)
- && validators[i].attr.errormessage.length > 0)
- {
-
- messages.push(validators[i].attr.errormessage);
- }
- }
- return messages;
- },
-
- /**
- * Return the format parameters for the summary.
- * @param {string} format type, "List", "SingleParagraph" or "BulletList"
- * @type {array} formatting parameters
- */
- formats : function(type)
- {
- switch(type)
- {
- case "List":
- return { header : "
", first : "", pre : "", post : "
", last : ""};
- case "SingleParagraph":
- return { header : " ", first : "", pre : "", post : " ", last : "
"};
- case "BulletList":
- default:
- return { header : "", first : "
@@ -543,10 +548,10 @@ Prado.WebUI.TBaseValidator.prototype =
*/
initialize : function(options)
{
- options.OnValidate = options.OnValidate || Prototype.emptyFunction;
+ /* options.OnValidate = options.OnValidate || Prototype.emptyFunction;
options.OnSuccess = options.OnSuccess || Prototype.emptyFunction;
options.OnError = options.OnError || Prototype.emptyFunction;
-
+ */
this.options = options;
this.control = $(options.ControlToValidate);
this.message = $(options.ID);
@@ -617,21 +622,39 @@ Prado.WebUI.TBaseValidator.prototype =
/**
* Calls evaluateIsValid() function to set the value of isValid property.
* Triggers onValidate event and onSuccess or onError event.
+ * @param HTMLElement element that calls for validation
* @return boolean true if valid.
*/
- validate : function()
+ validate : function(invoker)
{
+ if(typeof(this.options.OnValidate) == "function")
+ this.options.OnValidate(this, invoker);
+
if(this.enabled)
this.isValid = this.evaluateIsValid();
-
- this.options.OnValidate(this);
-
- this.updateControl();
-
+
if(this.isValid)
- this.options.OnSuccess(this);
+ {
+ if(typeof(this.options.OnSuccess) == "function")
+ {
+ this.visible = true;
+ this.updateControlCssClass(this.control, this.isValid);
+ this.options.OnSuccess(this, invoker);
+ }
+ else
+ this.updateControl();
+ }
else
- this.options.OnError(this);
+ {
+ if(typeof(this.options.OnError) == "function")
+ {
+ this.visible = true;
+ this.updateControlCssClass(this.control, this.isValid);
+ this.options.OnError(this, invoker);
+ }
+ else
+ this.updateControl();
+ }
this.observeChanges(this.control);
@@ -641,7 +664,7 @@ Prado.WebUI.TBaseValidator.prototype =
/**
* Observe changes to the control input, re-validate upon change. If
* the validator is not visible, no updates are propagated.
- * @param HTMLElement control to observe changes
+ * @param HTMLElement element that calls for validation
*/
observeChanges : function(control)
{
@@ -667,9 +690,9 @@ Prado.WebUI.TBaseValidator.prototype =
},
/**
- * @return string _trims the string value, empty string if value is not string.
+ * @return string trims the string value, empty string if value is not string.
*/
- _trim : function(value)
+ trim : function(value)
{
return typeof(value) == "string" ? value.trim() : "";
},
@@ -720,26 +743,25 @@ Prado.WebUI.TBaseValidator.prototype =
{
case 'TDatePicker':
if(control.type == "text")
- return this._trim($F(control));
+ return this.trim($F(control));
else
{
- this._observeDatePickerChanges();
+ this.observeDatePickerChanges();
return Prado.WebUI.TDatePicker.getDropDownDate(control).getTime();
}
default:
- if(this._isListControlType())
- return this._getFirstSelectedListValue();
+ if(this.isListControlType())
+ return this.getFirstSelectedListValue();
else
- return this._trim($F(control));
+ return this.trim($F(control));
}
},
/**
* Observe changes in the drop down list date picker, IE only.
- * @private
*/
- _observeDatePickerChanges : function()
+ observeDatePickerChanges : function()
{
if(Prado.Browser().ie)
{
@@ -754,13 +776,12 @@ Prado.WebUI.TBaseValidator.prototype =
* Gets numeber selections and their values.
* @return object returns selected values in values property
* and number of selections in checks property.
- * @private
*/
- _getSelectedValuesAndChecks : function(elements, initialValue)
+ getSelectedValuesAndChecks : function(elements, initialValue)
{
var checked = 0;
var values = [];
- var isSelected = this._isCheckBoxType(elements[0]) ? 'checked' : 'selected';
+ var isSelected = this.isCheckBoxType(elements[0]) ? 'checked' : 'selected';
elements.each(function(element)
{
if(element[isSelected] && element.value != initialValue)
@@ -776,9 +797,8 @@ Prado.WebUI.TBaseValidator.prototype =
* Gets an array of the list control item input elements, for TCheckBoxList
* checkbox inputs are returned, for TListBox HTML option elements are returned.
* @return array list control option elements.
- * @private
*/
- _getListElements : function()
+ getListElements : function()
{
switch(this.options.ControlType)
{
@@ -787,7 +807,7 @@ Prado.WebUI.TBaseValidator.prototype =
for(var i = 0; i < this.options.TotalItems; i++)
{
var element = $(this.options.ControlToValidate+"_"+i);
- if(this._isCheckBoxType(element))
+ if(this.isCheckBoxType(element))
elements.push(element);
}
return elements;
@@ -807,9 +827,8 @@ Prado.WebUI.TBaseValidator.prototype =
/**
* @return boolean true if element is of checkbox or radio type.
- * @private
*/
- _isCheckBoxType : function(element)
+ isCheckBoxType : function(element)
{
if(element && element.type)
{
@@ -821,9 +840,8 @@ Prado.WebUI.TBaseValidator.prototype =
/**
* @return boolean true if control to validate is of some of the TListControl type.
- * @private
*/
- _isListControlType : function()
+ isListControlType : function()
{
var list = ['TCheckBoxList', 'TRadioButtonList', 'TListBox'];
return list.include(this.options.ControlType);
@@ -831,15 +849,14 @@ Prado.WebUI.TBaseValidator.prototype =
/**
* @return string gets the first selected list value, initial value if none found.
- * @private
*/
- _getFirstSelectedListValue : function()
+ getFirstSelectedListValue : function()
{
var initial = "";
if(typeof(this.options.InitialValue) != "undefined")
initial = this.options.InitialValue;
- var elements = this._getListElements();
- var selection = this._getSelectedValuesAndChecks(elements, initial);
+ var elements = this.getListElements();
+ var selection = this.getSelectedValuesAndChecks(elements, initial);
return selection.values.length > 0 ? selection.values[0] : initial;
}
}
@@ -868,7 +885,7 @@ Prado.WebUI.TRequiredFieldValidator = Class.extend(Prado.WebUI.TBaseValidator,
else
{
var a = this.getValidationValue();
- var b = this._trim(this.options.InitialValue);
+ var b = this.trim(this.options.InitialValue);
return(a != b);
}
}
@@ -1105,13 +1122,13 @@ Prado.WebUI.TListControlValidator = Class.extend(Prado.WebUI.TBaseValidator,
*/
evaluateIsValid : function()
{
- var elements = this._getListElements();
+ var elements = this.getListElements();
if(elements && elements.length <= 0)
return true;
this.observeListElements(elements);
- var selection = this._getSelectedValuesAndChecks(elements);
+ var selection = this.getSelectedValuesAndChecks(elements);
return this.isValidList(selection.checks, selection.values);
},
@@ -1120,7 +1137,7 @@ Prado.WebUI.TListControlValidator = Class.extend(Prado.WebUI.TBaseValidator,
*/
observeListElements : function(elements)
{
- if(Prado.Browser().ie && this._isCheckBoxType(elements[0]))
+ if(Prado.Browser().ie && this.isCheckBoxType(elements[0]))
{
var validator = this;
elements.each(function(element)
@@ -1171,25 +1188,6 @@ Prado.WebUI.TListControlValidator = Class.extend(Prado.WebUI.TBaseValidator,
}
});
-/**
- * TDataTypeValidator verifies if the input data is of the type specified
- * by DataType option.
- * The following data types are supported:
- * - Integer A 32-bit signed integer data type.
- * - Float A double-precision floating point number data type.
- * - Date A date data type.
- * - String A string data type.
- * For Date type, the option DateFormat
- * will be used to determine how to parse the date string.
- */
-Prado.WebUI.TDataTypeValidator = Class.extend(Prado.WebUI.TBaseValidator,
-{
- evaluateIsValid : function()
- {
- var value = this.getValidationValue();
- if(value.length <= 0)
- return true;
- return this.convert(this.options.DataType, value) != null;
- }
-});
+
+
diff --git a/framework/Web/Javascripts/prado/validators.js b/framework/Web/Javascripts/prado/validators.js
deleted file mode 100644
index 5aa732b4..00000000
--- a/framework/Web/Javascripts/prado/validators.js
+++ /dev/null
@@ -1,222 +0,0 @@
-/**
- * Validates that a given field has some input,
- * @param ${parameter}
- * @return ${return}
- */
-Prado.Validation.TRequiredFieldValidator=function(){
- var inputType = this.control.getAttribute("type");
- if(inputType == 'file'){
- return true;
- }
- else{
- var a= Prado.Validation.trim($F(this.control));
- var b= Prado.Validation.trim(this.attr.initialvalue);
- return(a != b);
- }
-}
-
-
-Prado.Validation.TRegularExpressionValidator = function()
-{
- var value = Prado.Validation.trim($F(this.control));
- if (value == "") return true;
- var rx = new RegExp(this.attr.validationexpression);
- var matches = rx.exec(value);
- return (matches != null && value == matches[0]);
-}
-
-Prado.Validation.TEmailAddressValidator = Prado.Validation.TRegularExpressionValidator;
-
-Prado.Validation.TCustomValidator = function()
-{
- var value = isNull(this.control) ? null : $F(this.control);
- var func = this.attr.clientvalidationfunction;
- eval("var validate = "+func);
- return validate && isFunction(validate) ? validate(this, value) : true;
-}
-
-Prado.Validation.TRangeValidator = function()
-{
- var value = Prado.Validation.trim($F(this.control));
- if (value == "") return true;
-
- var minval = this.attr.minimumvalue;
- var maxval = this.attr.maximumvalue;
-
- if (undef(minval) && undef(maxval))
- return true;
-
- if (minval == "") minval = 0;
- if (maxval == "") maxval = 0;
-
- var dataType = this.attr.type;
-
- if(undef(dataType))
- return (parseFloat(value) >= parseFloat(minval)) && (parseFloat(value) <= parseFloat(maxval));
-
- //now do datatype range check.
- var min = this.convert(dataType, minval);
- var max = this.convert(dataType, maxval);
- value = this.convert(dataType, value);
- return value >= min && value <= max;
-}
-
-Prado.Validation.TCompareValidator = function()
-{
- var value = Prado.Validation.trim($F(this.control));
- if (value.length == 0) return true;
-
- var compareTo;
-
- var comparee = $(this.attr.controlhookup);;
-
- if(comparee)
- compareTo = Prado.Validation.trim($F(comparee));
- else
- {
- compareTo = isString(this.attr.valuetocompare) ? this.attr.valuetocompare : "";
- }
-
- var compare = Prado.Validation.TCompareValidator.compare;
-
- var isValid = compare.bind(this)(value, compareTo);
-
- //update the comparee control css class name and add onchange event once.
- if(comparee)
- {
- var className = this.attr.controlcssclass;
- if(isString(className) && className.length>0)
- Element.condClassName(comparee, className, !isValid);
- if(undef(this.observingComparee))
- {
- Event.observe(comparee, "change", this.validate.bind(this));
- this.observingComparee = true;
- }
- }
- return isValid;
-}
-
-/**
- * Compare the two values, also performs data type check.
- * @param {string} value to compare with
- * @param {string} value to compare
- * @type {boolean} true if comparison or type check is valid, false otherwise.
- */
-Prado.Validation.TCompareValidator.compare = function(operand1, operand2)
-{
- var op1, op2;
- if ((op1 = this.convert(this.attr.type, operand1)) == null)
- return false;
- if (this.attr.operator == "DataTypeCheck")
- return true;
- if ((op2 = this.convert(this.attr.type, operand2)) == null)
- return true;
- switch (this.attr.operator)
- {
- case "NotEqual":
- return (op1 != op2);
- case "GreaterThan":
- return (op1 > op2);
- case "GreaterThanEqual":
- return (op1 >= op2);
- case "LessThan":
- return (op1 < op2);
- case "LessThanEqual":
- return (op1 <= op2);
- default:
- return (op1 == op2);
- }
-}
-
-Prado.Validation.TRequiredListValidator = function()
-{
- var min = undef(this.attr.min) ? Number.NEGATIVE_INFINITY : parseInt(this.attr.min);
- var max = undef(this.attr.max) ? Number.POSITIVE_INFINITY : parseInt(this.attr.max);
-
- var elements = document.getElementsByName(this.attr.selector);
-
- if(elements.length <= 0)
- return true;
-
- var required = new Array();
- if(isString(this.attr.required) && this.attr.required.length > 0)
- required = this.attr.required.split(/,\s* /);
-
- var isValid = true;
-
- var validator = Prado.Validation.TRequiredListValidator;
-
- switch(elements[0].type)
- {
- case 'radio':
- case 'checkbox':
- isValid = validator.IsValidRadioList(elements, min, max, required);
- break;
- case 'select-multiple':
- isValid = validator.IsValidSelectMultipleList(elements, min, max, required);
- break;
- }
-
- var className = this.attr.elementcssclass;
- if(isString(className) && className.length>0)
- map(elements, function(element){ condClass(element, className, !isValid); });
- if(undef(this.observingRequiredList))
- {
- Event.observe(elements, "change", this.validate.bind(this));
- this.observingRequiredList = true;
- }
- return isValid;
-}
-
-//radio group selection
-Prado.Validation.TRequiredListValidator.IsValidRadioList = function(elements, min, max, required)
-{
- var checked = 0;
- var values = new Array();
- for(var i = 0; i < elements.length; i++)
- {
- if(elements[i].checked)
- {
- checked++;
- values.push(elements[i].value);
- }
- }
- return Prado.Validation.TRequiredListValidator.IsValidList(checked, values, min, max, required);
-}
-
-//multiple selection check
-Prado.Validation.TRequiredListValidator.IsValidSelectMultipleList = function(elements, min, max, required)
-{
- var checked = 0;
- var values = new Array();
- for(var i = 0; i < elements.length; i++)
- {
- var selection = elements[i];
- for(var j = 0; j < selection.options.length; j++)
- {
- if(selection.options[j].selected)
- {
- checked++;
- values.push(selection.options[j].value);
- }
- }
- }
- return Prado.Validation.TRequiredListValidator.IsValidList(checked, values, min, max, required);
-}
-
-//check if the list was valid
-Prado.Validation.TRequiredListValidator.IsValidList = function(checkes, values, min, max, required)
-{
- var exists = true;
-
- if(required.length > 0)
- {
- //required and the values must at least be have same lengths
- if(values.length < required.length)
- return false;
- for(var k = 0; k < required.length; k++)
- exists = exists && values.contains(required[k]);
- }
-
- return exists && checkes >= min && checkes <= max;
-}
diff --git a/framework/Web/UI/WebControls/TBaseValidator.php b/framework/Web/UI/WebControls/TBaseValidator.php
index adbc85ae..4ca4c1f6 100644
--- a/framework/Web/UI/WebControls/TBaseValidator.php
+++ b/framework/Web/UI/WebControls/TBaseValidator.php
@@ -41,6 +41,10 @@
* and {@link setText Text} are empty, the body content of the validator will
* be displayed. Error display is controlled by {@link setDisplay Display} property.
*
+ * You can also customized the client-side behaviour by adding javascript
+ * code to the subproperties of the {@link getClientValidation ClientValidation}
+ * property.
+ *
* You can also place a {@link TValidationSummary} control on a page to display error messages
* from the validators together. In this case, only the {@link setErrorMessage ErrorMessage}
* property of the validators will be displayed in the {@link TValidationSummary} control.
@@ -75,6 +79,8 @@ abstract class TBaseValidator extends TLabel implements IValidator
* @var boolean whether the validator has been registered with the page
*/
private $_registered=false;
+
+ private $_clientScript;
/**
* Constructor.
@@ -145,8 +151,43 @@ abstract class TBaseValidator extends TLabel implements IValidator
$options['ControlToValidate'] = $control->getClientID();
$options['ControlCssClass'] = $this->getControlCssClass();
$options['ControlType'] = get_class($control);
+
+ if(!is_null($this->_clientScript))
+ $options = array_merge($options,$this->_clientScript->getOptions());
+
return $options;
}
+
+ /**
+ * Gets the TValidatorClientScript that allows modification of the client-
+ * side validator events.
+ *
+ * The client-side validator supports the following events.
+ * # OnValidate -- raised before client-side validation is
+ * executed.
+ * # OnSuccess -- raised after client-side validation is completed
+ * and is successfull, overrides default validator error messages updates.
+ * # OnError -- raised after client-side validation is completed
+ * and failed, overrides default validator error message updates.
+ *
+ * You can attach custom javascript code to each of these events
+ *
+ * @return TValidatorClientScript javascript validator event options.
+ */
+ public function getClientValidation()
+ {
+ if(is_null($this->_clientScript))
+ $this->_clientScript = $this->createClientScript();
+ return $this->_clientScript;
+ }
+
+ /**
+ * @return TValidatorClientScript javascript validator event options.
+ */
+ protected function createClientScript()
+ {
+ return new TValidatorClientScript($this->getPage()->getClientScript());
+ }
/**
* Renders the javascript code to the end script.
@@ -446,4 +487,74 @@ abstract class TBaseValidator extends TLabel implements IValidator
parent::renderContents($writer);
}
}
+
+/**
+ * TValidatorClientScript class.
+ *
+ * @todo Add doc to quickstart and classes.
+ *
+ * @author Wei Zhuo
+ * @version $Revision: $ $Date: $
+ * @package System.Web.UI.WebControls
+ * @since 3.0
+ */
+class TValidatorClientScript extends TComponent
+{
+ private $_options;
+ private $_manager;
+ private $_effectsEnabled = false;
+
+ public function __construct($manager)
+ {
+ $this->_options = new TMap;
+ $this->_manager = $manager;
+ }
+
+ public function getOnValidate()
+ {
+ return $this->_options->itemAt['OnValidate'];
+ }
+
+ public function setOnValidate($javascript)
+ {
+ $this->_options->add('OnValidate', $this->ensureFunction($javascript));
+ }
+
+ public function setOnSuccess($javascript)
+ {
+ $this->_options->add('OnSuccess', $this->ensureFunction($javascript));
+ }
+
+ public function getOnSuccess()
+ {
+ return $this->_options->itemAt('OnSuccess');
+ }
+
+ public function setOnError($javascript)
+ {
+ $this->_options->add('OnError', $this->ensureFunction($javascript));
+ }
+
+ public function getOnError()
+ {
+ return $this->_options->itemAt('OnError');
+ }
+
+ public function getOptions()
+ {
+ return $this->_options->toArray();
+ }
+
+ private function ensureFunction($javascript)
+ {
+ if(TJavascript::isFunction($javascript))
+ return $javascript;
+ else
+ {
+ $code = "function(validator, invoker){ {$javascript} }";
+ return TJavascript::quoteFunction($code);
+ }
+ }
+}
+
?>
\ No newline at end of file
diff --git a/framework/Web/UI/WebControls/TClientScript.php b/framework/Web/UI/WebControls/TClientScript.php
new file mode 100644
index 00000000..23aa1425
--- /dev/null
+++ b/framework/Web/UI/WebControls/TClientScript.php
@@ -0,0 +1,75 @@
+
+ * @link http://www.pradosoft.com/
+ * @copyright Copyright © 2005 PradoSoft
+ * @license http://www.pradosoft.com/license/
+ * @version $Revision: $ $Date: $
+ * @package System.Web.UI.WebControls
+ */
+
+/**
+ * TClientScript class
+ *
+ * Allows importing of Prado Client Scripts from template via the
+ * {@link setUsingPradoScripts UsingPradoScripts} property. Multiple Prado
+ * client-scripts can be specified using comma delimited string of the
+ * javascript library to include on the page. For example,
+ *
+ *
+ *
+ *
+ *
+ * @TODO May be use it to include stylesheets as well.
+ *
+ * @author Wei Zhuo
+ * @version $Revision: $ $Date: $
+ * @package System.Web.UI.WebControls
+ * @since 3.0
+ */
+class TClientScript extends TControl
+{
+ /**
+ * @return string comma delimited list of javascript libraries to included
+ * on the page.
+ */
+ public function getUsingPradoScripts()
+ {
+ return $this->getViewState('PradoScripts', '');
+ }
+
+ /**
+ * Include javascript library to the current page. The current supported
+ * libraries are: "prado", "effects", "ajax", "validator", "logger",
+ * "datepicker", "rico", "colorpicker". Library dependencies are
+ * automatically resolved.
+ *
+ * @param string comma delimited list of javascript libraries to include.
+ */
+ public function setUsingPradoScripts($value)
+ {
+ $this->setViewState('PradoScripts', $value, '');
+ }
+
+ /**
+ * Calls the client script manager to add each of the requested client
+ * script libraries.
+ * @param mixed event parameter
+ */
+ public function onPreRender($param)
+ {
+ parent::onPreRender($param);
+ $scripts = preg_split('/,|\s+/', $this->getUsingPradoScripts());
+ $cs = $this->getPage()->getClientScript();
+ foreach($scripts as $script)
+ {
+ $script = trim($script);
+ if(strlen($script) > 0)
+ $cs->registerPradoScript($script);
+ }
+ }
+}
+
+?>
\ No newline at end of file
diff --git a/tests/FunctionalTests/features/protected/controls/Layout.tpl b/tests/FunctionalTests/features/protected/controls/Layout.tpl
index 18482377..66b42f6c 100644
--- a/tests/FunctionalTests/features/protected/controls/Layout.tpl
+++ b/tests/FunctionalTests/features/protected/controls/Layout.tpl
@@ -16,6 +16,11 @@
margin-top: 2em;
display: block;
}
+ .required
+ {
+ border:1px solid red;
+ background-color: #fdd;
+ }
/*]]>*/
diff --git a/tests/FunctionalTests/features/protected/pages/ValidatorEffects.page b/tests/FunctionalTests/features/protected/pages/ValidatorEffects.page
new file mode 100644
index 00000000..47d99969
--- /dev/null
+++ b/tests/FunctionalTests/features/protected/pages/ValidatorEffects.page
@@ -0,0 +1,91 @@
+
+
+Validator Visual Effects Test
+
+
+
+
+
+
+
\ No newline at end of file
--
cgit v1.2.3