From 13b256cdf8e3cef810d1b3dcf580be751b94c9fe Mon Sep 17 00:00:00 2001 From: wei <> Date: Tue, 29 Aug 2006 11:12:33 +0000 Subject: Add separate debug javascript build. --- framework/Web/Javascripts/js/debug/validator.js | 1279 +++++++++++++++++++++++ 1 file changed, 1279 insertions(+) create mode 100644 framework/Web/Javascripts/js/debug/validator.js (limited to 'framework/Web/Javascripts/js/debug/validator.js') diff --git a/framework/Web/Javascripts/js/debug/validator.js b/framework/Web/Javascripts/js/debug/validator.js new file mode 100644 index 00000000..a77b6f42 --- /dev/null +++ b/framework/Web/Javascripts/js/debug/validator.js @@ -0,0 +1,1279 @@ + +/** + * Prado client-side javascript validation fascade. + * + * There are 4 basic classes, Validation, ValidationManager, ValidationSummary + * and TBaseValidator, that interact together to perform validation. + * The Prado.Validation class co-ordinates together the + * validation scheme and is responsible for maintaining references + * to ValidationManagers. + * + * The ValidationManager class is responsible for maintaining refereneces + * to individual validators, validation summaries and their associated + * groupings. + * + * The ValidationSummary take cares of display the validator error messages + * as html output or an alert output. + * + * The TBaseValidator is the base class for all validators and contains + * methods to interact with the actual inputs, data type conversion. + * + * An instance of ValidationManager must be instantiated first for a + * particular form before instantiating validators and summaries. + * + * Usage example: adding a required field to a text box input with + * ID "input1" in a form with ID "form1". + * + * + * + *
+ *
+ * + * + * + * + *
+ *
+ *
+ */ +Prado.Validation = Class.create(); + +/** + * A global validation manager. + * To validate the inputs of a particular form, call + * Prado.Validation.validate(formID, groupID) + * where formID is the HTML form ID, and the optional + * groupID if present will only validate the validators + * in a particular group. + */ +Object.extend(Prado.Validation, +{ + managers : {}, + + /** + * Validate the validators (those that DO NOT + * belong to a particular group) the form specified by the + * formID parameter. If groupID is specified + * then only validators belonging to that group will be validated. + * @param string ID of the form to validate + * @param string ID of the group to validate. + * @param HTMLElement element that calls for validation + */ + validate : function(formID, groupID, invoker) + { + if(this.managers[formID]) + { + return this.managers[formID].validate(groupID, invoker); + } + else + { + throw new Error("Form '"+form+"' is not registered with Prado.Validation"); + } + }, + + /** + * Check if the validators are valid for a particular form (and group). + * The validators states will not be changed. + * The validate function should be called first. + * @param string ID of the form to validate + * @param string ID of the group to validate. + */ + isValid : function(formID, groupID) + { + if(this.managers[formID]) + return this.managers[formID].isValid(groupID); + return true; + }, + + /** + * Add a new validator to a particular form. + * @param string the form that the validator belongs. + * @param object a validator + * @return object the manager + */ + addValidator : function(formID, validator) + { + if(this.managers[formID]) + this.managers[formID].addValidator(validator); + else + throw new Error("A validation manager for form '"+formID+"' needs to be created first."); + return this.managers[formID]; + }, + + /** + * Add a new validation summary. + * @param string the form that the validation summary belongs. + * @param object a validation summary + * @return object manager + */ + addSummary : function(formID, validator) + { + if(this.managers[formID]) + this.managers[formID].addSummary(validator); + else + throw new Error("A validation manager for form '"+formID+"' needs to be created first."); + return this.managers[formID]; + } +}); + +Prado.ValidationManager = Class.create(); +/** + * Validation manager instances. Manages validators for a particular + * HTML form. The manager contains references to all the validators + * summaries, and their groupings for a particular form. + * Generally, Prado.Validation methods should be called rather + * than calling directly the ValidationManager. + */ +Prado.ValidationManager.prototype = +{ + validators : [], // list of validators + summaries : [], // validation summaries + groups : [], // validation groups + options : {}, + + /** + * + * options['FormID']* The ID of HTML form to manage. + * + */ + initialize : function(options) + { + this.options = options; + Prado.Validation.managers[options.FormID] = this; + }, + + /** + * Validate the validators managed by this validation manager. + * @param string only validate validators belonging to a group (optional) + * @param HTMLElement element that calls for validation + * @return boolean true if all validators are valid, false otherwise. + */ + validate : function(group, invoker) + { + if(group) + return this._validateGroup(group, invoker); + else + return this._validateNonGroup(invoker); + }, + + /** + * Validate a particular group of validators. + * @param string ID of the form + * @param HTMLElement element that calls for validation + * @return boolean false if group is not valid, true otherwise. + */ + _validateGroup: function(groupID, invoker) + { + var valid = true; + if(this.groups.include(groupID)) + { + this.validators.each(function(validator) + { + if(validator.group == groupID) + valid = valid & validator.validate(invoker); + else + validator.hide(); + }); + } + this.updateSummary(groupID, true); + return valid; + }, + + /** + * Validate validators that doesn't belong to any group. + * @return boolean false if not valid, true otherwise. + * @param HTMLElement element that calls for validation + */ + _validateNonGroup : function(invoker) + { + var valid = true; + this.validators.each(function(validator) + { + if(!validator.group) + valid = valid & validator.validate(invoker); + else + validator.hide(); + }); + this.updateSummary(null, true); + return valid; + }, + + /** + * Gets the state of all the validators, true if they are all valid. + * @return boolean true if the validators are valid. + */ + isValid : function(group) + { + if(group) + return this._isValidGroup(group); + else + return this._isValidNonGroup(); + }, + + /** + * @return boolean true if all validators not belonging to a group are valid. + */ + _isValidNonGroup : function() + { + var valid = true; + this.validators.each(function(validator) + { + if(!validator.group) + valid = valid & validator.isValid; + }); + return valid; + }, + + /** + * @return boolean true if all validators belonging to the group are valid. + */ + _isValidGroup : function(groupID) + { + var valid = true; + if(this.groups.include(groupID)) + { + this.validators.each(function(validator) + { + if(validator.group == groupID) + valid = valid & validator.isValid; + }); + } + return valid; + }, + + /** + * Add a validator to this manager. + * @param Prado.WebUI.TBaseValidator a new validator + */ + addValidator : function(validator) + { + this.validators.push(validator); + if(validator.group && !this.groups.include(validator.group)) + this.groups.push(validator.group); + }, + + /** + * Add a validation summary. + * @param Prado.WebUI.TValidationSummary validation summary. + */ + addSummary : function(summary) + { + this.summaries.push(summary); + }, + + /** + * Gets all validators that belong to a group or that the validator + * group is null and the validator validation was false. + * @return array list of validators with error. + */ + getValidatorsWithError : function(group) + { + var validators = this.validators.findAll(function(validator) + { + var notValid = !validator.isValid; + var inGroup = group && validator.group == group; + var noGroup = validator.group == null; + return notValid && (inGroup || noGroup); + }); + return validators; + }, + + /** + * Update the summary of a particular group. + * @param string validation group to update. + */ + updateSummary : function(group, refresh) + { + var validators = this.getValidatorsWithError(group); + this.summaries.each(function(summary) + { + var inGroup = group && summary.group == group; + var noGroup = !group && !summary.group; + if(inGroup || noGroup) + summary.updateSummary(validators, refresh); + else + summary.hideSummary(true); + }); + } +}; + +/** + * TValidationSummary displays a summary of validation errors inline on a Web page, + * in a message box, or both. By default, a validation summary will collect + * ErrorMessage of all failed validators on the page. If + * ValidationGroup is not empty, only those validators who belong + * to the group will show their error messages in the summary. + * + * The summary can be displayed as a list, as a bulleted list, or as a single + * paragraph based on the DisplayMode option. + * The messages shown can be prefixed with HeaderText. + * + * The summary can be displayed on the Web page and in a message box by setting + * the ShowSummary and ShowMessageBox + * options, respectively. + */ +Prado.WebUI.TValidationSummary = Class.create(); +Prado.WebUI.TValidationSummary.prototype = +{ + group : null, + options : {}, + visible : false, + messages : null, + + /** + * + * options['ID']* Validation summary ID, i.e., an HTML element ID + * options['FormID']* HTML form that this summary belongs. + * options['ShowMessageBox'] True to show the summary in an alert box. + * options['ShowSummary'] True to show the inline summary. + * options['HeaderText'] Summary header text + * options['DisplayMode'] Summary display style, 'BulletList', 'List', 'SingleParagraph' + * options['Refresh'] True to update the summary upon validator state change. + * options['ValidationGroup'] Validation summary group + * options['Display'] Display mode, 'None', 'Static', 'Dynamic'. + * options['ScrollToSummary'] True to scroll to the validation summary upon refresh. + * + */ + initialize : function(options) + { + this.options = options; + this.group = options.ValidationGroup; + this.messages = $(options.ID); + this.visible = this.messages.style.visibility != "hidden" + this.visible = this.visible && this.messages.style.display != "none"; + Prado.Validation.addSummary(options.FormID, this); + }, + + /** + * Update the validation summary to show the error message from + * validators that failed validation. + * @param array list of validators that failed validation. + * @param boolean update the summary; + */ + updateSummary : function(validators, update) + { + if(validators.length <= 0) + { + if(update || this.options.Refresh != false) + { + return this.hideSummary(validators); + } + return; + } + + var refresh = update || this.visible == false || this.options.Refresh != false; + + if(this.options.ShowSummary != false && refresh) + { + this.updateHTMLMessages(this.getMessages(validators)); + this.showSummary(validators); + } + + if(this.options.ScrollToSummary != false && refresh) + window.scrollTo(this.messages.offsetLeft-20, this.messages.offsetTop-20); + + if(this.options.ShowMessageBox == true && refresh) + { + this.alertMessages(this.getMessages(validators)); + this.visible = true; + } + }, + + /** + * Display the validator error messages as inline HTML. + */ + updateHTMLMessages : function(messages) + { + while(this.messages.childNodes.length > 0) + this.messages.removeChild(this.messages.lastChild); + new Insertion.Bottom(this.messages, this.formatSummary(messages)); + }, + + /** + * Display the validator error messages as an alert box. + */ + alertMessages : function(messages) + { + var text = this.formatMessageBox(messages); + setTimeout(function(){ alert(text); },20); + }, + + /** + * @return array list of validator error messages. + */ + getMessages : function(validators) + { + var messages = []; + validators.each(function(validator) + { + var message = validator.getErrorMessage(); + if(typeof(message) == 'string' && message.length > 0) + messages.push(message); + }) + return messages; + }, + + /** + * Hides the validation summary. + */ + hideSummary : function(validators) + { if(typeof(this.options.OnHideSummary) == "function") + { + this.messages.style.visibility="visible"; + this.options.OnHideSummary(this,validators) + } + else + { + this.messages.style.visibility="hidden"; + if(this.options.Display == "None" || this.options.Display == "Dynamic") + this.messages.hide(); + } + this.visible = false; + }, + + /** + * Shows the validation summary. + */ + showSummary : function(validators) + { + this.messages.style.visibility="visible"; + if(typeof(this.options.OnShowSummary) == "function") + this.options.OnShowSummary(this,validators); + else + this.messages.show(); + this.visible = true; + }, + + /** + * 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 : ""}; + } + }, + + /** + * Format the message summary. + * @param array list of error messages. + * @type string formatted message + */ + formatSummary : function(messages) + { + var format = this.formats(this.options.DisplayMode); + var output = this.options.HeaderText ? this.options.HeaderText + format.header : ""; + output += format.first; + messages.each(function(message) + { + output += message.length > 0 ? format.pre + message + format.post : ""; + }); +// for(var i = 0; i < messages.length; i++) + // output += (messages[i].length>0) ? format.pre + messages[i] + format.post : ""; + output += format.last; + return output; + }, + /** + * Format the message alert box. + * @param array a list of error messages. + * @type string format message for alert. + */ + formatMessageBox : function(messages) + { + var output = this.options.HeaderText ? this.options.HeaderText + "\n" : ""; + for(var i = 0; i < messages.length; i++) + { + switch(this.options.DisplayMode) + { + case "List": + output += messages[i] + "\n"; + break; + case "BulletList": + default: + output += " - " + messages[i] + "\n"; + break; + case "SingleParagraph": + output += messages[i] + " "; + break; + } + } + return output; + } +}; + +/** + * TBaseValidator serves as the base class for validator controls. + * + * Validation is performed when a postback control, such as a TButton, + * a TLinkButton or a TTextBox (under AutoPostBack mode) is submitting + * the page and its CausesValidation option is true. + * The input control to be validated is specified by ControlToValidate + * option. + */ +Prado.WebUI.TBaseValidator = Class.create(); +Prado.WebUI.TBaseValidator.prototype = +{ + enabled : true, + visible : false, + isValid : true, + options : {}, + _isObserving : {}, + group : null, + manager : null, + message : null, + + /** + * + * options['ID']* Validator ID, e.g. span with message + * options['FormID']* HTML form that the validator belongs + * options['ControlToValidate']*HTML form input to validate + * options['Display'] Display mode, 'None', 'Static', 'Dynamic' + * options['ErrorMessage'] Validation error message + * options['FocusOnError'] True to focus on validation error + * options['FocusElementID'] Element to focus on error + * options['ValidationGroup'] Validation group + * options['ControlCssClass'] Css class to use on the input upon error + * options['OnValidate'] Function to call immediately after validation + * options['OnSuccess'] Function to call upon after successful validation + * options['OnError'] Function to call upon after error in validation. + * options['ObserveChanges'] True to observe changes in input + * + */ + 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); + this.group = options.ValidationGroup; + + this.manager = Prado.Validation.addValidator(options.FormID, this); + }, + + /** + * @return string validation error message. + */ + getErrorMessage : function() + { + return this.options.ErrorMessage; + }, + + /** + * Update the validator span, input CSS class, and focus particular + * element. Updating the validator control will set the validator + * visible property to true. + */ + updateControl: function() + { + if(this.message) + { + if(this.options.Display == "Dynamic") + this.isValid ? this.message.hide() : this.message.show(); + this.message.style.visibility = this.isValid ? "hidden" : "visible"; + } + + if(this.control) + this.updateControlCssClass(this.control, this.isValid); + + if(this.options.FocusOnError && !this.isValid) + Prado.Element.focus(this.options.FocusElementID); + + this.visible = true; + }, + + /** + * Add a css class to the input control if validator is invalid, + * removes the css class if valid. + * @param object html control element + * @param boolean true to remove the css class, false to add. + */ + updateControlCssClass : function(control, valid) + { + var CssClass = this.options.ControlCssClass; + if(typeof(CssClass) == "string" && CssClass.length > 0) + { + if(valid) + control.removeClassName(CssClass); + else + control.addClassName(CssClass); + } + }, + + /** + * Hides the validator messages and remove any validation changes. + */ + hide : function() + { + this.isValid = true; + this.updateControl(); + this.visible = false; + }, + + /** + * 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(invoker) + { + 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) + { + if(typeof(this.options.OnSuccess) == "function") + { + this.visible = true; + this.message.style.visibility = "visible"; + this.updateControlCssClass(this.control, this.isValid); + this.options.OnSuccess(this, invoker); + } + else + this.updateControl(); + } + else + { + if(typeof(this.options.OnError) == "function") + { + this.visible = true; + this.message.style.visibility = "visible"; + this.updateControlCssClass(this.control, this.isValid); + this.options.OnError(this, invoker); + } + else + this.updateControl(); + } + + this.observeChanges(this.control); + + return this.isValid; + }, + + /** + * Observe changes to the control input, re-validate upon change. If + * the validator is not visible, no updates are propagated. + * @param HTMLElement element that calls for validation + */ + observeChanges : function(control) + { + if(!control) return; + + var canObserveChanges = this.options.ObserveChanges != false; + var currentlyObserving = this._isObserving[control.id+this.options.ID]; + + if(canObserveChanges && !currentlyObserving) + { + var validator = this; + + Event.observe(control, 'change', function() + { + if(validator.visible) + { + validator.validate(); + validator.manager.updateSummary(validator.group); + } + }); + this._isObserving[control.id+this.options.ID] = true; + } + }, + + /** + * @return string trims the string value, empty string if value is not string. + */ + trim : function(value) + { + return typeof(value) == "string" ? value.trim() : ""; + }, + + /** + * Convert the value to a specific data type. + * @param {string} the data type, "Integer", "Double", "Date" or "String" + * @param {string} the value to convert. + * @type {mixed|null} the converted data value. + */ + convert : function(dataType, value) + { + if(typeof(value) == "undefined") + value = this.getValidationValue(); + var string = new String(value); + switch(dataType) + { + case "Integer": + return string.toInteger(); + case "Double" : + case "Float" : + return string.toDouble(this.options.DecimalChar); + case "Date": + if(typeof(value) != "string") + return value; + else + { + var value = string.toDate(this.options.DateFormat); + if(value && typeof(value.getTime) == "function") + return value.getTime(); + else + return null; + } + case "String": + return string.toString(); + } + return value; + }, + + /** + * The ControlType property comes from TBaseValidator::getClientControlClass() + * Be sure to update the TBaseValidator::$_clientClass if new cases are added. + * @return mixed control value to validate + */ + getValidationValue : function(control) + { + if(!control) + control = this.control + switch(this.options.ControlType) + { + case 'TDatePicker': + if(control.type == "text") + { + value = this.trim($F(control)); + + if(this.options.DateFormat) + { + date = value.toDate(this.options.DateFormat); + return date == null ? '' : date; + } + else + return value; + } + else + { + this.observeDatePickerChanges(); + + return Prado.WebUI.TDatePicker.getDropDownDate(control).getTime(); + } + case 'THtmlArea': + if(typeof tinyMCE != "undefined") + tinyMCE.triggerSave(); + return this.trim($F(control)); + case 'TRadioButton': + if(this.options.GroupName) + return this.getRadioButtonGroupValue(); + default: + if(this.isListControlType()) + return this.getFirstSelectedListValue(); + else + return this.trim($F(control)); + } + }, + + getRadioButtonGroupValue : function() + { + name = this.control.name; + value = ""; + $A(document.getElementsByName(name)).each(function(el) + { + if(el.checked) + value = el.value; + }); + return value; + }, + + /** + * Observe changes in the drop down list date picker, IE only. + */ + observeDatePickerChanges : function() + { + if(Prado.Browser().ie) + { + var DatePicker = Prado.WebUI.TDatePicker; + this.observeChanges(DatePicker.getDayListControl(this.control)); + this.observeChanges(DatePicker.getMonthListControl(this.control)); + this.observeChanges(DatePicker.getYearListControl(this.control)); + } + }, + + /** + * Gets numeber selections and their values. + * @return object returns selected values in values property + * and number of selections in checks property. + */ + getSelectedValuesAndChecks : function(elements, initialValue) + { + var checked = 0; + var values = []; + var isSelected = this.isCheckBoxType(elements[0]) ? 'checked' : 'selected'; + elements.each(function(element) + { + if(element[isSelected] && element.value != initialValue) + { + checked++; + values.push(element.value); + } + }); + return {'checks' : checked, 'values' : values}; + }, + + /** + * 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. + */ + getListElements : function() + { + switch(this.options.ControlType) + { + case 'TCheckBoxList': case 'TRadioButtonList': + var elements = []; + for(var i = 0; i < this.options.TotalItems; i++) + { + var element = $(this.options.ControlToValidate+"_c"+i); + if(this.isCheckBoxType(element)) + elements.push(element); + } + return elements; + case 'TListBox': + var elements = []; + var element = $(this.options.ControlToValidate); + if(element && (type = element.type.toLowerCase())) + { + if(type == "select-one" || type == "select-multiple") + elements = $A(element.options); + } + return elements; + default: + return []; + } + }, + + /** + * @return boolean true if element is of checkbox or radio type. + */ + isCheckBoxType : function(element) + { + if(element && element.type) + { + var type = element.type.toLowerCase(); + return type == "checkbox" || type == "radio"; + } + return false; + }, + + /** + * @return boolean true if control to validate is of some of the TListControl type. + */ + isListControlType : function() + { + var list = ['TCheckBoxList', 'TRadioButtonList', 'TListBox']; + return list.include(this.options.ControlType); + }, + + /** + * @return string gets the first selected list value, initial value if none found. + */ + getFirstSelectedListValue : function() + { + var initial = ""; + if(typeof(this.options.InitialValue) != "undefined") + initial = this.options.InitialValue; + var elements = this.getListElements(); + var selection = this.getSelectedValuesAndChecks(elements, initial); + return selection.values.length > 0 ? selection.values[0] : initial; + } +} + + +/** + * TRequiredFieldValidator makes the associated input control a required field. + * The input control fails validation if its value does not change from + * the InitialValue option upon losing focus. + * + * options['InitialValue'] Validation fails if control input equals initial value. + * + */ +Prado.WebUI.TRequiredFieldValidator = Class.extend(Prado.WebUI.TBaseValidator, +{ + /** + * @return boolean true if the input value is not empty nor equal to the initial value. + */ + evaluateIsValid : function() + { + var inputType = this.control.getAttribute("type"); + if(inputType == 'file') + { + return true; + } + else + { + var a = this.getValidationValue(); + var b = this.trim(this.options.InitialValue); + return(a != b); + } + } +}); + + +/** + * TCompareValidator compares the value entered by the user into an input + * control with the value entered into another input control or a constant value. + * To compare the associated input control with another input control, + * set the ControlToCompare option to the ID path + * of the control to compare with. To compare the associated input control with + * a constant value, specify the constant value to compare with by setting the + * ValueToCompare option. + * + * The DataType property is used to specify the data type + * of both comparison values. Both values are automatically converted to this data + * type before the comparison operation is performed. The following value 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. The format can be by the DateFormat option. + * - String A string data type. + * + * Use the Operator property to specify the type of comparison + * to perform. Valid operators include Equal, NotEqual, GreaterThan, GreaterThanEqual, + * LessThan and LessThanEqual. + * + * options['ControlToCompare'] + * options['ValueToCompare'] + * options['Operator'] + * options['Type'] + * options['DateFormat'] + * + */ +Prado.WebUI.TCompareValidator = Class.extend(Prado.WebUI.TBaseValidator, +{ + //_observingComparee : false, + + /** + * Compares the input to another input or a given value. + */ + evaluateIsValid : function() + { + var value = this.getValidationValue(); + if (value.length <= 0) + return true; + + var comparee = $(this.options.ControlToCompare); + + if(comparee) + var compareTo = this.getValidationValue(comparee); + else + var compareTo = this.options.ValueToCompare || ""; + + var isValid = this.compare(value, compareTo); + + if(comparee) + { + this.updateControlCssClass(comparee, isValid); + this.observeChanges(comparee); + } + return isValid; + }, + + /** + * Compares two values, their values are casted to type defined + * by DataType option. False is returned if the first + * operand converts to null. Returns true if the second operand + * converts to null. The comparision is done based on the + * Operator option. + */ + compare : function(operand1, operand2) + { + var op1, op2; + if((op1 = this.convert(this.options.DataType, operand1)) == null) + return false; + if ((op2 = this.convert(this.options.DataType, operand2)) == null) + return true; + switch (this.options.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); + } + } +}); + +/** + * TCustomValidator performs user-defined client-side validation on an + * input component. + * + * To create a client-side validation function, add the client-side + * validation javascript function to the page template. + * The function should have the following signature: + * + * + * + * Use the ClientValidationFunction option + * to specify the name of the client-side validation script function associated + * with the TCustomValidator. + * + * options['ClientValidationFunction'] custom validation function. + * + */ +Prado.WebUI.TCustomValidator = Class.extend(Prado.WebUI.TBaseValidator, +{ + /** + * Calls custom validation function. + */ + evaluateIsValid : function() + { + var value = this.getValidationValue(); + var clientFunction = this.options.ClientValidationFunction; + if(typeof(clientFunction) == "string" && clientFunction.length > 0) + { + validate = clientFunction.toFunction(); + return validate(this, value); + } + return true; + } +}); + +/** + * TRangeValidator tests whether an input value is within a specified range. + * + * TRangeValidator uses three key properties to perform its validation. + * The MinValue and MaxValue options specify the minimum + * and maximum values of the valid range. The DataType option is + * used to specify the data type of the value and the minimum and maximum range values. + * These values are converted to this data type before the validation + * operation is performed. The following value 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. The date format can be specified by + * setting DateFormat option, which must be recognizable + * by Date.SimpleParse javascript function. + * - String A string data type. + * + * options['MinValue'] Minimum range value + * options['MaxValue'] Maximum range value + * options['DataType'] Value data type + * options['DateFormat'] Date format for date data type. + * + */ +Prado.WebUI.TRangeValidator = Class.extend(Prado.WebUI.TBaseValidator, +{ + /** + * Compares the input value with a minimum and/or maximum value. + * @return boolean true if the value is empty, returns false if conversion fails. + */ + evaluateIsValid : function() + { + var value = this.getValidationValue(); + if(value.length <= 0) + 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); + var max = this.convert(this.options.DataType, this.options.MaxValue || null); + value = this.convert(this.options.DataType, value); + } + else + { + var min = this.options.MinValue || 0; + var max = this.options.MaxValue || Number.POSITIVE_INFINITY; + value = value.length; + } + + if(value == null) + return false; + + var valid = true; + + if(min != null) + valid = valid && value >= min; + if(max != null) + valid = valid && value <= max; + return valid; + } +}); + +/** + * TRegularExpressionValidator validates whether the value of an associated + * input component matches the pattern specified by a regular expression. + * + * options['ValidationExpression'] regular expression to match against. + * + */ +Prado.WebUI.TRegularExpressionValidator = Class.extend(Prado.WebUI.TBaseValidator, +{ + /** + * Compare the control input against a regular expression. + */ + evaluateIsValid : function() + { + var value = this.getValidationValue(); + if (value.length <= 0) + return true; + + var rx = new RegExp(this.options.ValidationExpression); + var matches = rx.exec(value); + return (matches != null && value == matches[0]); + } +}); + +/** + * TEmailAddressValidator validates whether the value of an associated + * input component is a valid email address. + */ +Prado.WebUI.TEmailAddressValidator = Prado.WebUI.TRegularExpressionValidator; + + +/** + * TListControlValidator checks the number of selection and their values + * for a TListControl that allows multiple selections. + */ +Prado.WebUI.TListControlValidator = Class.extend(Prado.WebUI.TBaseValidator, +{ + /** + * @return true if the number of selections and/or their values + * match the requirements. + */ + evaluateIsValid : function() + { + var elements = this.getListElements(); + if(elements && elements.length <= 0) + return true; + + this.observeListElements(elements); + + var selection = this.getSelectedValuesAndChecks(elements); + return this.isValidList(selection.checks, selection.values); + }, + + /** + * Observe list elements for IE browsers of changes + */ + observeListElements : function(elements) + { + if(Prado.Browser().ie && this.isCheckBoxType(elements[0])) + { + var validator = this; + elements.each(function(element) + { + validator.observeChanges(element); + }); + } + }, + + /** + * Determine if the number of checked and the checked values + * satisfy the required number of checks and/or the checked values + * equal to the required values. + * @return boolean true if checked values and number of checks are satisfied. + */ + isValidList : function(checked, values) + { + var exists = true; + + //check the required values + var required = this.getRequiredValues(); + if(required.length > 0) + { + if(values.length < required.length) + return false; + required.each(function(requiredValue) + { + exists = exists && values.include(requiredValue); + }); + } + + var min = typeof(this.options.Min) == "undefined" ? + Number.NEGATIVE_INFINITY : this.options.Min; + var max = typeof(this.options.Max) == "undefined" ? + Number.POSITIVE_INFINITY : this.options.Max; + return exists && checked >= min && checked <= max; + }, + + /** + * @return array list of required options that must be selected. + */ + getRequiredValues : function() + { + var required = []; + if(this.options.Required && this.options.Required.length > 0) + required = this.options.Required.split(/,\s*/); + return required; + } +}); + + +/** + * 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; + } +}); + + + -- cgit v1.2.3