/** -- S P R Y T E X T -- **/ // SpryValidationTextField.js - version 0.37 - Spry Pre-Release 1.6.1 // // Copyright (c) 2006. Adobe Systems Incorporated. // All rights reserved. // // Redistribution and use in source and binary forms, with or without // modification, are permitted provided that the following conditions are met: // // * Redistributions of source code must retain the above copyright notice, // this list of conditions and the following disclaimer. // * Redistributions in binary form must reproduce the above copyright notice, // this list of conditions and the following disclaimer in the documentation // and/or other materials provided with the distribution. // * Neither the name of Adobe Systems Incorporated nor the names of its // contributors may be used to endorse or promote products derived from this // software without specific prior written permission. // // THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" // AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE // IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE // ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE // LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR // CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF // SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS // INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN // CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) // ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE // POSSIBILITY OF SUCH DAMAGE. var Spry; if (!Spry) Spry = {}; if (!Spry.Widget) Spry.Widget = {}; Spry.CustomValidation = {}; Spry.OriginalError = {}; Spry.Widget.BrowserSniff = function() { var b = navigator.appName.toString(); var up = navigator.platform.toString(); var ua = navigator.userAgent.toString(); this.mozilla = this.ie = this.opera = this.safari = false; var re_opera = /Opera.([0-9\.]*)/i; var re_msie = /MSIE.([0-9\.]*)/i; var re_gecko = /gecko/i; var re_safari = /(applewebkit|safari)\/([\d\.]*)/i; var r = false; if ( (r = ua.match(re_opera))) { this.opera = true; this.version = parseFloat(r[1]); } else if ( (r = ua.match(re_msie))) { this.ie = true; this.version = parseFloat(r[1]); } else if ( (r = ua.match(re_safari))) { this.safari = true; this.version = parseFloat(r[2]); } else if (ua.match(re_gecko)) { var re_gecko_version = /rv:\s*([0-9\.]+)/i; r = ua.match(re_gecko_version); this.mozilla = true; this.version = parseFloat(r[1]); } this.windows = this.mac = this.linux = false; this.Platform = ua.match(/windows/i) ? "windows" : (ua.match(/linux/i) ? "linux" : (ua.match(/mac/i) ? "mac" : ua.match(/unix/i)? "unix" : "unknown")); this[this.Platform] = true; this.v = this.version; if (this.safari && this.mac && this.mozilla) { this.mozilla = false; } }; Spry.is = new Spry.Widget.BrowserSniff(); Spry.Widget.ValidationTextField = function(element, type, options, custom_validation) { type = Spry.Widget.Utils.firstValid(type, "none"); if (typeof type != 'string') { this.showError('The second parameter in the constructor should be the validation type, the options are the third parameter.'); return; } if (typeof Spry.Widget.ValidationTextField.ValidationDescriptors[type] == 'undefined') { this.showError('Unknown validation type received as the second parameter.'); return; } options = Spry.Widget.Utils.firstValid(options, {}); this.type = type; if (!this.isBrowserSupported()) { //disable character masking and pattern behaviors for low level browsers options.useCharacterMasking = false; } this.init(element, options); Spry.CustomValidation[element] = custom_validation; //make sure we validate at least on submit var validateOn = ['submit'].concat(Spry.Widget.Utils.firstValid(this.options.validateOn, [])); validateOn = validateOn.join(","); this.validateOn = 0; this.validateOn = this.validateOn | (validateOn.indexOf('submit') != -1 ? Spry.Widget.ValidationTextField.ONSUBMIT : 0); this.validateOn = this.validateOn | (validateOn.indexOf('blur') != -1 ? Spry.Widget.ValidationTextField.ONBLUR : 0); this.validateOn = this.validateOn | (validateOn.indexOf('change') != -1 ? Spry.Widget.ValidationTextField.ONCHANGE : 0); if (Spry.Widget.ValidationTextField.onloadDidFire) this.attachBehaviors(); else Spry.Widget.ValidationTextField.loadQueue.push(this); }; Spry.Widget.ValidationTextField.ONCHANGE = 1; Spry.Widget.ValidationTextField.ONBLUR = 2; Spry.Widget.ValidationTextField.ONSUBMIT = 4; Spry.Widget.ValidationTextField.ERROR_REQUIRED = 1; Spry.Widget.ValidationTextField.ERROR_FORMAT = 2; Spry.Widget.ValidationTextField.ERROR_RANGE_MIN = 4; Spry.Widget.ValidationTextField.ERROR_RANGE_MAX = 8; Spry.Widget.ValidationTextField.ERROR_CHARS_MIN = 16; Spry.Widget.ValidationTextField.ERROR_CHARS_MAX = 32; /* validation parameters: * - characterMasking : prevent typing of characters not matching an regular expression * - regExpFilter : additional regular expression to disalow typing of characters * (like the "-" sign in the middle of the value); use for partial matching of the currently typed value; * the typed value must match regExpFilter at any moment * - pattern : enforce character on each position inside a pattern (AX0?) * - validation : function performing logic validation; return false if failed and the typedValue value on success * - minValue, maxValue : range validation; check if typedValue inside the specified range * - minChars, maxChars : value length validation; at least/at most number of characters * */ Spry.Widget.ValidationTextField.ValidationDescriptors = { 'none': { }, 'custom': { }, 'integer': { characterMasking: /[\-\+\d]/, regExpFilter: /^[\-\+]?\d*$/, validation: function(value, options) { if (value == '' || value == '-' || value == '+') { return false; } var regExp = /^[\-\+]?\d*$/; if (!regExp.test(value)) { return false; } options = options || {allowNegative:false}; var ret = parseInt(value, 10); if (!isNaN(ret)) { var allowNegative = true; if (typeof options.allowNegative != 'undefined' && options.allowNegative == false) { allowNegative = false; } if (!allowNegative && value < 0) { ret = false; } } else { ret = false; } return ret; } }, 'real': { characterMasking: /[\d\.,\-\+e]/i, regExpFilter: /^[\-\+]?\d(?:|\.,\d{0,2})|(?:|e{0,1}[\-\+]?\d{0,})$/i, validation: function (value, options) { var regExp = /^[\+\-]?[0-9]+([\.,][0-9]+)?([eE]{0,1}[\-\+]?[0-9]+)?$/; if (!regExp.test(value)) { return false; } var ret = parseFloat(value); if (isNaN(ret)) { ret = false; } return ret; } }, 'currency': { formats: { 'dot_comma': { characterMasking: /[\d\.\,\-\+\$]/, regExpFilter: /^[\-\+]?(?:[\d\.]*)+(|\,\d{0,2})$/, validation: function(value, options) { var ret = false; //2 or no digits after the comma if (/^(\-|\+)?\d{1,3}(?:\.\d{3})*(?:\,\d{2}|)$/.test(value) || /^(\-|\+)?\d+(?:\,\d{2}|)$/.test(value)) { value = value.toString().replace(/\./gi, '').replace(/\,/, '.'); ret = parseFloat(value); } return ret; } }, 'comma_dot': { characterMasking: /[\d\.\,\-\+\$]/, regExpFilter: /^[\-\+]?(?:[\d\,]*)+(|\.\d{0,2})$/, validation: function(value, options) { var ret = false; //2 or no digits after the comma if (/^(\-|\+)?\d{1,3}(?:\,\d{3})*(?:\.\d{2}|)$/.test(value) || /^(\-|\+)?\d+(?:\.\d{2}|)$/.test(value)) { value = value.toString().replace(/\,/gi, ''); ret = parseFloat(value); } return ret; } } } }, 'email': { characterMasking: /[^\s]/, validation: function(value, options) { var rx = /^[\w\.-]+@[\w\.-]+\.\w+$/i; return rx.test(value); } }, 'date': { validation: function(value, options) { var formatRegExp = /^([mdy]+)[\.\-\/\\\s]+([mdy]+)[\.\-\/\\\s]+([mdy]+)$/i; var valueRegExp = this.dateValidationPattern; var formatGroups = options.format.match(formatRegExp); var valueGroups = value.match(valueRegExp); if (formatGroups !== null && valueGroups !== null) { var dayIndex = -1; var monthIndex = -1; var yearIndex = -1; for (var i=1; i 12) { return false; } // Calculate the maxDay according to the current month switch (theMonth) { case 1: // January case 3: // March case 5: // May case 7: // July case 8: // August case 10: // October case 12: // December maxDay = 31; break; case 4: // April case 6: // June case 9: // September case 11: // November maxDay = 30; break; case 2: // February if ((parseInt(theYear/4, 10) * 4 == theYear) && (theYear % 100 != 0 || theYear % 400 == 0)) { maxDay = 29; } else { maxDay = 28; } break; } // Check day value to be between 1..maxDay if (theDay < 1 || theDay > maxDay) { return false; } // If successfull we'll return the date object return (new Date(theYear, theMonth - 1, theDay)); //JavaScript requires a month between 0 and 11 } } else { return false; } } }, 'time': { validation: function(value, options) { // HH:MM:SS T var formatRegExp = /([hmst]+)/gi; var valueRegExp = /(\d+|AM?|PM?)/gi; var formatGroups = options.format.match(formatRegExp); var valueGroups = value.match(valueRegExp); //mast match and have same length if (formatGroups !== null && valueGroups !== null) { if (formatGroups.length != valueGroups.length) { return false; } var hourIndex = -1; var minuteIndex = -1; var secondIndex = -1; //T is AM or PM var tIndex = -1; var theHour = 0, theMinute = 0, theSecond = 0, theT = 'AM'; for (var i=0; i (formatGroups[hourIndex] == 'HH' ? 23 : 12 )) { return false; } } if (minuteIndex != -1) { var theMinute = parseInt(valueGroups[minuteIndex], 10); if (isNaN(theMinute) || theMinute > 59) { return false; } } if (secondIndex != -1) { var theSecond = parseInt(valueGroups[secondIndex], 10); if (isNaN(theSecond) || theSecond > 59) { return false; } } if (tIndex != -1) { var theT = valueGroups[tIndex].toUpperCase(); if ( formatGroups[tIndex].toUpperCase() == 'TT' && !/^a|pm$/i.test(theT) || formatGroups[tIndex].toUpperCase() == 'T' && !/^a|p$/i.test(theT) ) { return false; } } var date = new Date(2000, 0, 1, theHour + (theT.charAt(0) == 'P'?12:0), theMinute, theSecond); return date; } else { return false; } } }, 'credit_card': { characterMasking: /\d/, validation: function(value, options) { var regExp = null; options.format = options.format || 'ALL'; switch (options.format.toUpperCase()) { case 'ALL': regExp = /^[3-6]{1}[0-9]{12,18}$/; break; case 'VISA': regExp = /^4(?:[0-9]{12}|[0-9]{15})$/; break; case 'MASTERCARD': regExp = /^5[1-5]{1}[0-9]{14}$/; break; case 'AMEX': regExp = /^3(4|7){1}[0-9]{13}$/; break; case 'DISCOVER': regExp = /^6011[0-9]{12}$/; break; case 'DINERSCLUB': regExp = /^3(?:(0[0-5]{1}[0-9]{11})|(6[0-9]{12})|(8[0-9]{12}))$/; break; } if (!regExp.test(value)) { return false; } var digits = []; var j = 1, digit = ''; for (var i = value.length - 1; i >= 0; i--) { if ((j%2) == 0) { digit = parseInt(value.charAt(i), 10) * 2; digits[digits.length] = digit.toString().charAt(0); if (digit.toString().length == 2) { digits[digits.length] = digit.toString().charAt(1); } } else { digit = value.charAt(i); digits[digits.length] = digit; } j++; } var sum = 0; for(i=0; i < digits.length; i++ ) { sum += parseInt(digits[i], 10); } if ((sum%10) == 0) { return true; } return false; } }, 'zip_code': { formats: { 'zip_us9': { pattern:'00000-0000' }, 'zip_us5': { pattern:'00000' }, 'zip_uk': { characterMasking: /[\dA-Z\s]/, validation: function(value, options) { //check one of the following masks // AN NAA, ANA NAA, ANN NAA, AAN NAA, AANA NAA, AANN NAA return /^[A-Z]{1,2}\d[\dA-Z]?\s?\d[A-Z]{2}$/.test(value); } }, 'zip_canada': { characterMasking: /[\dA-Z\s]/, pattern: 'A0A 0A0' }, 'zip_custom': {} } }, 'phone_number': { formats: { //US phone number; 10 digits 'phone_us': { pattern:'(000) 000-0000' }, 'phone_custom': {} } }, 'social_security_number': { pattern:'000-00-0000' }, 'ip': { characterMaskingFormats: { 'ipv4': /[\d\.]/i, 'ipv6_ipv4': /[\d\.\:A-F\/]/i, 'ipv6': /[\d\.\:A-F\/]/i }, validation: function (value, options) { return Spry.Widget.ValidationTextField.validateIP(value, options.format); } }, 'url': { characterMasking: /[^\s]/, validation: function(value, options) { //fix for ?ID=223429 and ?ID=223387 /* the following regexp matches components of an URI as specified in http://tools.ietf.org/html/rfc3986#page-51 page 51, Appendix B. scheme = $2 authority = $4 path = $5 query = $7 fragment = $9 */ var URI_spliter = /^(([^:\/?#]+):)?(\/\/([^\/?#]*))?([^?#]*)(\?([^#]*))?(#(.*))?/; var parts = value.match(URI_spliter); if (parts && parts[4]) { //encode each component of the domain name using Punycode encoding scheme: http://tools.ietf.org/html/rfc3492 var host = parts[4].split("."); var punyencoded = ''; for (var i=0; i 1080::8:800:200C:417A FF01:0:0:0:0:0:0:101 --> FF01::101 0:0:0:0:0:0:0:1 --> ::1 0:0:0:0:0:0:0:0 --> :: 2.5.4 IPv6 Addresses with Embedded IPv4 Addresses IPv4-compatible IPv6 address (tunnel IPv6 packets over IPv4 routing infrastructures) ::0:129.144.52.38 IPv4-mapped IPv6 address (represent the addresses of IPv4-only nodes as IPv6 addresses) ::ffff:129.144.52.38 The text representation of IPv6 addresses and prefixes in Augmented BNF (Backus-Naur Form) [ABNF] for reference purposes. [ABNF http://tools.ietf.org/html/rfc2234] IPv6address = hexpart [ ":" IPv4address ] IPv4address = 1*3DIGIT "." 1*3DIGIT "." 1*3DIGIT "." 1*3DIGIT IPv6prefix = hexpart "/" 1*2DIGIT hexpart = hexseq | hexseq "::" [ hexseq ] | "::" [ hexseq ] hexseq = hex4 *( ":" hex4) hex4 = 1*4HEXDIG */ Spry.Widget.ValidationTextField.validateIP = function (value, format) { var validIPv6Addresses = [ //preferred /^(?:[a-f0-9]{1,4}:){7}[a-f0-9]{1,4}(?:\/\d{1,3})?$/i, //various compressed /^[a-f0-9]{0,4}::(?:\/\d{1,3})?$/i, /^:(?::[a-f0-9]{1,4}){1,6}(?:\/\d{1,3})?$/i, /^(?:[a-f0-9]{1,4}:){1,6}:(?:\/\d{1,3})?$/i, /^(?:[a-f0-9]{1,4}:)(?::[a-f0-9]{1,4}){1,6}(?:\/\d{1,3})?$/i, /^(?:[a-f0-9]{1,4}:){2}(?::[a-f0-9]{1,4}){1,5}(?:\/\d{1,3})?$/i, /^(?:[a-f0-9]{1,4}:){3}(?::[a-f0-9]{1,4}){1,4}(?:\/\d{1,3})?$/i, /^(?:[a-f0-9]{1,4}:){4}(?::[a-f0-9]{1,4}){1,3}(?:\/\d{1,3})?$/i, /^(?:[a-f0-9]{1,4}:){5}(?::[a-f0-9]{1,4}){1,2}(?:\/\d{1,3})?$/i, /^(?:[a-f0-9]{1,4}:){6}(?::[a-f0-9]{1,4})(?:\/\d{1,3})?$/i, //IPv6 mixes with IPv4 /^(?:[a-f0-9]{1,4}:){6}(?:\d{1,3}\.){3}\d{1,3}(?:\/\d{1,3})?$/i, /^:(?::[a-f0-9]{1,4}){0,4}:(?:\d{1,3}\.){3}\d{1,3}(?:\/\d{1,3})?$/i, /^(?:[a-f0-9]{1,4}:){1,5}:(?:\d{1,3}\.){3}\d{1,3}(?:\/\d{1,3})?$/i, /^(?:[a-f0-9]{1,4}:)(?::[a-f0-9]{1,4}){1,4}:(?:\d{1,3}\.){3}\d{1,3}(?:\/\d{1,3})?$/i, /^(?:[a-f0-9]{1,4}:){2}(?::[a-f0-9]{1,4}){1,3}:(?:\d{1,3}\.){3}\d{1,3}(?:\/\d{1,3})?$/i, /^(?:[a-f0-9]{1,4}:){3}(?::[a-f0-9]{1,4}){1,2}:(?:\d{1,3}\.){3}\d{1,3}(?:\/\d{1,3})?$/i, /^(?:[a-f0-9]{1,4}:){4}(?::[a-f0-9]{1,4}):(?:\d{1,3}\.){3}\d{1,3}(?:\/\d{1,3})?$/i ]; var validIPv4Addresses = [ //IPv4 /^(\d{1,3}\.){3}\d{1,3}$/i ]; var validAddresses = []; if (format == 'ipv6' || format == 'ipv6_ipv4') { validAddresses = validAddresses.concat(validIPv6Addresses); } if (format == 'ipv4' || format == 'ipv6_ipv4') { validAddresses = validAddresses.concat(validIPv4Addresses); } var ret = false; for (var i=0; i 255 || !regExp.test(pieces[i]) || pieces[i].length>3 || /^0{2,3}$/.test(pieces[i])) { return false; } } } if (ret && value.indexOf("/") != -1) { // if prefix-length is specified must be in [1-128] var prefLen = value.match(/\/\d{1,3}$/); if (!prefLen) return false; var prefLenVal = parseInt(prefLen[0].replace(/^\//,''), 10); if (isNaN(prefLenVal) || prefLenVal > 128 || prefLenVal < 1) { return false; } } return ret; }; Spry.Widget.ValidationTextField.onloadDidFire = false; Spry.Widget.ValidationTextField.loadQueue = []; Spry.Widget.ValidationTextField.prototype.isBrowserSupported = function() { return Spry.is.ie && Spry.is.v >= 5 && Spry.is.windows || Spry.is.mozilla && Spry.is.v >= 1.4 || Spry.is.safari || Spry.is.opera && Spry.is.v >= 9; }; Spry.Widget.ValidationTextField.prototype.init = function(element, options) { this.element = this.getElement(element); this.errors = 0; this.flags = {locked: false, restoreSelection: true}; this.options = {}; this.event_handlers = []; this.validClass = "textfieldValidState"; this.focusClass = "textfieldFocusState"; this.requiredClass = "textfieldRequiredState"; this.hintClass = "textfieldHintState"; this.invalidFormatClass = "textfieldInvalidFormatState"; this.invalidRangeMinClass = "textfieldMinValueState"; this.invalidRangeMaxClass = "textfieldMaxValueState"; this.invalidCharsMinClass = "textfieldMinCharsState"; this.invalidCharsMaxClass = "textfieldMaxCharsState"; this.textfieldFlashTextClass = "textfieldFlashText"; if (Spry.is.safari) { this.flags.lastKeyPressedTimeStamp = 0; } switch (this.type) { case 'phone_number':options.format = Spry.Widget.Utils.firstValid(options.format, 'phone_us');break; case 'currency':options.format = Spry.Widget.Utils.firstValid(options.format, 'comma_dot');break; case 'zip_code':options.format = Spry.Widget.Utils.firstValid(options.format, 'zip_us5');break; case 'date': options.format = Spry.Widget.Utils.firstValid(options.format, 'mm/dd/yy'); break; case 'time': options.format = Spry.Widget.Utils.firstValid(options.format, 'HH:mm'); options.pattern = options.format.replace(/[hms]/gi, "0").replace(/TT/gi, 'AM').replace(/T/gi, 'A'); break; case 'ip': options.format = Spry.Widget.Utils.firstValid(options.format, 'ipv4'); options.characterMasking = Spry.Widget.ValidationTextField.ValidationDescriptors[this.type].characterMaskingFormats[options.format]; break; } //retrieve the validation type descriptor to be used with this instance (base on type and format) //widgets may have different validations depending on format (like zip_code with formats) var validationDescriptor = {}; if (options.format && Spry.Widget.ValidationTextField.ValidationDescriptors[this.type].formats) { if (Spry.Widget.ValidationTextField.ValidationDescriptors[this.type].formats[options.format]) { Spry.Widget.Utils.setOptions(validationDescriptor, Spry.Widget.ValidationTextField.ValidationDescriptors[this.type].formats[options.format]); } } else { Spry.Widget.Utils.setOptions(validationDescriptor, Spry.Widget.ValidationTextField.ValidationDescriptors[this.type]); } //set default values for some parameters which were not aspecified options.useCharacterMasking = Spry.Widget.Utils.firstValid(options.useCharacterMasking, false); options.hint = Spry.Widget.Utils.firstValid(options.hint, ''); options.isRequired = Spry.Widget.Utils.firstValid(options.isRequired, true); options.additionalError = Spry.Widget.Utils.firstValid(options.additionalError, false); if (options.additionalError) options.additionalError = this.getElement(options.additionalError); //set widget validation parameters //get values from validation type descriptor //use the user specified values, if defined options.characterMasking = Spry.Widget.Utils.firstValid(options.characterMasking, validationDescriptor.characterMasking); options.regExpFilter = Spry.Widget.Utils.firstValid(options.regExpFilter, validationDescriptor.regExpFilter); options.pattern = Spry.Widget.Utils.firstValid(options.pattern, validationDescriptor.pattern); options.validation = Spry.Widget.Utils.firstValid(options.validation, validationDescriptor.validation); if (typeof options.validation == 'string') { options.validation = eval(options.validation); } options.minValue = Spry.Widget.Utils.firstValid(options.minValue, validationDescriptor.minValue); options.maxValue = Spry.Widget.Utils.firstValid(options.maxValue, validationDescriptor.maxValue); options.minChars = Spry.Widget.Utils.firstValid(options.minChars, validationDescriptor.minChars); options.maxChars = Spry.Widget.Utils.firstValid(options.maxChars, validationDescriptor.maxChars); Spry.Widget.Utils.setOptions(this, options); Spry.Widget.Utils.setOptions(this.options, options); }; Spry.Widget.ValidationTextField.prototype.destroy = function() { if (this.event_handlers) for (var i=0; i this.maxChars) { errors = errors | Spry.Widget.ValidationTextField.ERROR_CHARS_MAX; continueValidations = false; } } //validation - testValue passes widget validation function if (!mustRevert && this.validation && continueValidations) { var value = this.validation(fixedValue, this.options); if (false === value) { errors = errors | Spry.Widget.ValidationTextField.ERROR_FORMAT; continueValidations = false; } else { this.typedValue = value; } } if(!mustRevert && this.validation && this.minValue !== null && continueValidations) { var minValue = this.validation(this.minValue.toString(), this.options); if (minValue !== false) { if (this.typedValue < minValue) { errors = errors | Spry.Widget.ValidationTextField.ERROR_RANGE_MIN; continueValidations = false; } } } if(!mustRevert && this.validation && this.maxValue !== null && continueValidations) { var maxValue = this.validation(this.maxValue.toString(), this.options); if (maxValue !== false) { if( this.typedValue > maxValue) { errors = errors | Spry.Widget.ValidationTextField.ERROR_RANGE_MAX; continueValidations = false; } } } //an invalid value was tested; must make sure it does not get inside the input if (this.useCharacterMasking && mustRevert) { this.revertState(revertValue); } this.errors = errors; this.fixedValue = fixedValue; this.flags.locked = false; return mustRevert; }; Spry.Widget.ValidationTextField.prototype.onChange = function(e) { if (Spry.is.opera && this.flags.operaRevertOnKeyUp) { return true; } if (Spry.is.ie && e && e.propertyName != 'value') { return true; } if (this.flags.drop) { //delay this if it's a drop operation var self = this; setTimeout(function() { self.flags.drop = false; self.onChange(null); }, 0); return; } if (this.flags.hintOn) { return true; } if (this.keyCode == 8 || this.keyCode == 46 ) { var mustRevert = this.doValidations(this.input.value, this.input.value); this.oldValue = this.input.value; if ((mustRevert || this.errors) && this.validateOn & Spry.Widget.ValidationTextField.ONCHANGE) { var self = this; setTimeout(function() {self.validate();}, 0); return true; } } var mustRevert = this.doValidations(this.input.value, this.oldValue); if ((!mustRevert || this.errors) && this.validateOn & Spry.Widget.ValidationTextField.ONCHANGE) { var self = this; setTimeout(function() {self.validate();}, 0); } return true; }; Spry.Widget.ValidationTextField.prototype.onKeyUp = function(e) { if (this.flags.operaRevertOnKeyUp) { this.setValue(this.oldValue); Spry.Widget.Utils.stopEvent(e); this.selection.moveTo(this.selection.start, this.selection.start); this.flags.operaRevertOnKeyUp = false; return false; } if (this.flags.operaPasteOperation) { window.clearInterval(this.flags.operaPasteOperation); this.flags.operaPasteOperation = null; } }; Spry.Widget.ValidationTextField.prototype.operaPasteMonitor = function() { if (this.input.value != this.oldValue) { var mustRevert = this.doValidations(this.input.value, this.input.value); if (mustRevert) { this.setValue(this.oldValue); this.selection.moveTo(this.selection.start, this.selection.start); } else { this.onChange(); } } }; Spry.Widget.ValidationTextField.prototype.compileDatePattern = function () { var dateValidationPatternString = ""; var groupPatterns = []; var fullGroupPatterns = []; var autocompleteCharacters = []; var formatRegExp = /^([mdy]+)([\.\-\/\\\s]+)([mdy]+)([\.\-\/\\\s]+)([mdy]+)$/i; var formatGroups = this.options.format.match(formatRegExp); if (formatGroups !== null) { for (var i=1; i 0) { var all_messages = $$(' .textfieldRequiredMsg'); for(var counter=0; counter < all_messages.length; counter++) { if(all_messages[counter].parentNode.parentNode.id == this.element.id && all_messages[counter].parentNode.className == "alert alert_text") { if(!Spry.OriginalError[this.element.id]) { Spry.OriginalError[this.element.id] = all_messages[counter].innerHTML; } reset_flag = false; all_messages[counter].innerHTML = custom_validation_result[1]; } } } this.addClassName(this.element, this.requiredClass); this.addClassName(this.additionalError, this.requiredClass); false_flag = false; } } if(reset_flag || typeof(Spry.CustomValidation[this.element.id]) == "undefined") { if(Spry.OriginalError[this.element.id]) { var all_messages = $$(' .textfieldRequiredMsg'); for(var counter=0; counter < all_messages.length; counter++) { if(all_messages[counter].parentNode.parentNode.id == this.element.id && all_messages[counter].parentNode.className == "alert alert_text") { all_messages[counter].innerHTML = Spry.OriginalError[this.element.id]; } } } } //possible states: required, format, rangeMin, rangeMax, charsMin, charsMax if (this.validateOn & Spry.Widget.ValidationTextField.ONSUBMIT) { this.removeHint(); this.doValidations(this.input.value, this.input.value); if(!this.flags.active) { var self = this; setTimeout(function() {self.putHint();}, 10); } } if (false_flag && this.isRequired && this.errors & Spry.Widget.ValidationTextField.ERROR_REQUIRED) { this.addClassName(this.element, this.requiredClass); this.addClassName(this.additionalError, this.requiredClass); false_flag = false; //return false; } if (false_flag && this.errors & Spry.Widget.ValidationTextField.ERROR_FORMAT) { this.addClassName(this.element, this.invalidFormatClass); this.addClassName(this.additionalError, this.invalidFormatClass); false_flag = false; //return false; } if (false_flag && this.errors & Spry.Widget.ValidationTextField.ERROR_RANGE_MIN) { this.addClassName(this.element, this.invalidRangeMinClass); this.addClassName(this.additionalError, this.invalidRangeMinClass); false_flag = false; //return false; } if (false_flag && this.errors & Spry.Widget.ValidationTextField.ERROR_RANGE_MAX) { this.addClassName(this.element, this.invalidRangeMaxClass); this.addClassName(this.additionalError, this.invalidRangeMaxClass); false_flag = false; //return false; } if (false_flag && this.errors & Spry.Widget.ValidationTextField.ERROR_CHARS_MIN) { this.addClassName(this.element, this.invalidCharsMinClass); this.addClassName(this.additionalError, this.invalidCharsMinClass); false_flag = false; //return false; } if (false_flag && this.errors & Spry.Widget.ValidationTextField.ERROR_CHARS_MAX) { this.addClassName(this.element, this.invalidCharsMaxClass); this.addClassName(this.additionalError, this.invalidCharsMaxClass); false_flag = false; //return false; } /**************************************************** M O D I F I E D *************************************************/ if( typeof(spry_additional_error) != "undefined" ) { if(spry_additional_error) { page_validation(false_flag, VAL_ADDFIELD_TEXTFIELD, this); } } /**************************************************** M O D I F I E D *************************************************/ if(!false_flag) { return false; } this.addClassName(this.element, this.validClass); this.addClassName(this.additionalError, this.validClass); return true; }; Spry.Widget.ValidationTextField.prototype.addClassName = function(ele, className) { if (!ele || !className || (ele.className && ele.className.search(new RegExp("\\b" + className + "\\b")) != -1)) return; ele.className += (ele.className ? " " : "") + className; }; Spry.Widget.ValidationTextField.prototype.removeClassName = function(ele, className) { if (!ele || !className || (ele.className && ele.className.search(new RegExp("\\b" + className + "\\b")) == -1)) return; ele.className = ele.className.replace(new RegExp("\\s*\\b" + className + "\\b", "g"), ""); }; Spry.Widget.ValidationTextField.prototype.showError = function(msg) { alert('Spry.Widget.TextField ERR: ' + msg); }; /** * SelectionDescriptor is a wrapper for input type text selection methods and properties * as implemented by various browsers */ Spry.Widget.SelectionDescriptor = function (element) { this.element = element; this.update(); }; Spry.Widget.SelectionDescriptor.prototype.update = function() { if (Spry.is.ie && Spry.is.windows) { var sel = this.element.ownerDocument.selection; if (this.element.nodeName == "TEXTAREA") { if (sel.type != 'None') { try{var range = sel.createRange();}catch(err){return;} if (range.parentElement() == this.element){ var range_all = this.element.ownerDocument.body.createTextRange(); range_all.moveToElementText(this.element); for (var sel_start = 0; range_all.compareEndPoints('StartToStart', range) < 0; sel_start ++){ range_all.moveStart('character', 1); } this.start = sel_start; // create a selection of the whole this.element range_all = this.element.ownerDocument.body.createTextRange(); range_all.moveToElementText(this.element); for (var sel_end = 0; range_all.compareEndPoints('StartToEnd', range) < 0; sel_end++){ range_all.moveStart('character', 1); } this.end = sel_end; this.length = this.end - this.start; // get selected and surrounding text this.text = range.text; } } } else if (this.element.nodeName == "INPUT"){ try{this.range = sel.createRange();}catch(err){return;} this.length = this.range.text.length; var clone = this.range.duplicate(); this.start = -clone.moveStart("character", -10000); clone = this.range.duplicate(); clone.collapse(false); this.end = -clone.moveStart("character", -10000); this.text = this.range.text; } } else { var tmp = this.element; var selectionStart = 0; var selectionEnd = 0; try { selectionStart = tmp.selectionStart;} catch(err) {} try { selectionEnd = tmp.selectionEnd;} catch(err) {} if (Spry.is.safari) { if (selectionStart == 2147483647) { selectionStart = 0; } if (selectionEnd == 2147483647) { selectionEnd = 0; } } this.start = selectionStart; this.end = selectionEnd; this.length = selectionEnd - selectionStart; this.text = this.element.value.substring(selectionStart, selectionEnd); } }; Spry.Widget.SelectionDescriptor.prototype.destroy = function() { try { delete this.range} catch(err) {} try { delete this.element} catch(err) {} }; Spry.Widget.SelectionDescriptor.prototype.move = function(amount) { if (Spry.is.ie && Spry.is.windows) { this.range.move("character", amount); this.range.select(); } else { try { this.element.selectionStart++;}catch(err) {} } this.update(); }; Spry.Widget.SelectionDescriptor.prototype.moveTo = function(start, end) { if (Spry.is.ie && Spry.is.windows) { if (this.element.nodeName == "TEXTAREA") { var ta_range = this.element.createTextRange(); this.range = this.element.createTextRange(); this.range.move("character", start); this.range.moveEnd("character", end - start); var c1 = this.range.compareEndPoints("StartToStart", ta_range); if (c1 < 0) { this.range.setEndPoint("StartToStart", ta_range); } var c2 = this.range.compareEndPoints("EndToEnd", ta_range); if (c2 > 0) { this.range.setEndPoint("EndToEnd", ta_range); } } else if (this.element.nodeName == "INPUT"){ this.range = this.element.ownerDocument.selection.createRange(); this.range.move("character", -10000); this.start = this.range.moveStart("character", start); this.end = this.start + this.range.moveEnd("character", end - start); } this.range.select(); } else { this.start = start; try { this.element.selectionStart = start;} catch(err) {} this.end = end; try { this.element.selectionEnd = end;} catch(err) {} } this.ignore = true; this.update(); }; Spry.Widget.SelectionDescriptor.prototype.moveEnd = function(amount) { if (Spry.is.ie && Spry.is.windows) { this.range.moveEnd("character", amount); this.range.select(); } else { try { this.element.selectionEnd++;} catch(err) {} } this.update(); }; Spry.Widget.SelectionDescriptor.prototype.collapse = function(begin) { if (Spry.is.ie && Spry.is.windows) { this.range = this.element.ownerDocument.selection.createRange(); this.range.collapse(begin); this.range.select(); } else { if (begin) { try { this.element.selectionEnd = this.element.selectionStart;} catch(err) {} } else { try { this.element.selectionStart = this.element.selectionEnd;} catch(err) {} } } this.update(); }; ////////////////////////////////////////////////////////////////////// // // Spry.Widget.Form - common for all widgets // ////////////////////////////////////////////////////////////////////// if (!Spry.Widget.Form) Spry.Widget.Form = {}; if (!Spry.Widget.Form.onSubmitWidgetQueue) Spry.Widget.Form.onSubmitWidgetQueue = []; if (!Spry.Widget.Form.validate) { Spry.Widget.Form.validate = function(vform) { var isValid = true; var isElementValid = true; var q = Spry.Widget.Form.onSubmitWidgetQueue; var qlen = q.length; for (var i = 0; i < qlen; i++) { if (!q[i].isDisabled() && q[i].form == vform) { isElementValid = q[i].validate(); isValid = isElementValid && isValid; } } return isValid; } }; if(typeof(spry_popup_warning) == "undefined") { function spry_popup_warning() { if(typeof(document.getElementById("spry_popup_warning_message")) != "undefined" && document.getElementById("spry_popup_warning_message")) { document.getElementById("spry_popup_warning_message").style.display = "block"; if(typeof(spry_popup_warning_message_delay) != "undefined" && spry_popup_warning_message_delay) { setTimeout(function(){ reset_spry_popup_warning(); }, (spry_popup_warning_message_delay * 1000)); } else { setTimeout(function(){ reset_spry_popup_warning(); }, (3 * 1000)); } } } } if(typeof(reset_spry_popup_warning) == "undefined") { function reset_spry_popup_warning() { if(typeof(document.getElementById("spry_popup_warning_message")) != "undefined" && document.getElementById("spry_popup_warning_message")) { document.getElementById("spry_popup_warning_message").style.display = "none"; } } } if (!Spry.Widget.Form.onSubmit) { Spry.Widget.Form.onSubmit = function(e, form) { /**************************************************** M O D I F I E D *************************************************/ if(typeof(spry_validation_extension) == "function") { if(spry_validation_extension() == false) { spry_popup_warning(); return false; } } /**************************************************** M O D I F I E D *************************************************/ if (Spry.Widget.Form.validate(form) == false) { spry_popup_warning(); return false; } reset_spry_popup_warning(); return true; }; }; if (!Spry.Widget.Form.onReset) { Spry.Widget.Form.onReset = function(e, vform) { var q = Spry.Widget.Form.onSubmitWidgetQueue; var qlen = q.length; for (var i = 0; i < qlen; i++) { if (!q[i].isDisabled() && q[i].form == vform && typeof(q[i].reset) == 'function') { q[i].reset(); } } return true; }; }; if (!Spry.Widget.Form.destroy) { Spry.Widget.Form.destroy = function(form) { var q = Spry.Widget.Form.onSubmitWidgetQueue; for (var i = 0; i < Spry.Widget.Form.onSubmitWidgetQueue.length; i++) { if (q[i].form == form && typeof(q[i].destroy) == 'function') { q[i].destroy(); i--; } } } }; if (!Spry.Widget.Form.destroyAll) { Spry.Widget.Form.destroyAll = function() { var q = Spry.Widget.Form.onSubmitWidgetQueue; for (var i = 0; i < Spry.Widget.Form.onSubmitWidgetQueue.length; i++) { if (typeof(q[i].destroy) == 'function') { q[i].destroy(); i--; } } } }; ////////////////////////////////////////////////////////////////////// // // Spry.Widget.Utils // ////////////////////////////////////////////////////////////////////// if (!Spry.Widget.Utils) Spry.Widget.Utils = {}; Spry.Widget.Utils.punycode_constants = { base : 36, tmin : 1, tmax : 26, skew : 38, damp : 700, initial_bias : 72, initial_n : 0x80, delimiter : 0x2D, maxint : 2<<26-1 }; Spry.Widget.Utils.punycode_encode_digit = function (d) { return String.fromCharCode(d + 22 + 75 * (d < 26)); }; Spry.Widget.Utils.punycode_adapt = function (delta, numpoints, firsttime) { delta = firsttime ? delta / this.punycode_constants.damp : delta >> 1; delta += delta / numpoints; for (var k = 0; delta > ((this.punycode_constants.base - this.punycode_constants.tmin) * this.punycode_constants.tmax) / 2; k += this.punycode_constants.base) { delta /= this.punycode_constants.base - this.punycode_constants.tmin; } return k + (this.punycode_constants.base - this.punycode_constants.tmin + 1) * delta / (delta + this.punycode_constants.skew); }; /** * returns a Punicode representation of a UTF-8 string * adapted from http://tools.ietf.org/html/rfc3492 */ Spry.Widget.Utils.punycode_encode = function (input, max_out) { var inputc = input.split(""); input = []; for(var i=0; i 0) { output += String.fromCharCode(this.punycode_constants.delimiter); out++; } while (h < input_len) { for (m = this.punycode_constants.maxint, j = 0; j < input_len; j++) { if (input[j] >= n && input[j] < m) { m = input[j]; } } if (m - n > (this.punycode_constants.maxint - delta) / (h + 1)) { return false; } delta += (m - n) * (h + 1); n = m; for (j = 0; j < input_len; j++) { if (input[j] < n ) { if (++delta == 0) { return false; } } if (input[j] == n) { for (q = delta, k = this.punycode_constants.base; true; k += this.punycode_constants.base) { if (out >= max_out) { return false; } t = k <= bias ? this.punycode_constants.tmin : k >= bias + this.punycode_constants.tmax ? this.punycode_constants.tmax : k - bias; if (q < t) { break; } output += this.punycode_encode_digit(t + (q - t) % (this.punycode_constants.base - t)); out++; q = (q - t) / (this.punycode_constants.base - t); } output += this.punycode_encode_digit(q); out++; bias = this.punycode_adapt(delta, h + 1, h == b); delta = 0; h++; } } delta++, n++; } return output; }; Spry.Widget.Utils.setOptions = function(obj, optionsObj, ignoreUndefinedProps) { if (!optionsObj) return; for (var optionName in optionsObj) { if (ignoreUndefinedProps && optionsObj[optionName] == undefined) continue; obj[optionName] = optionsObj[optionName]; } }; Spry.Widget.Utils.firstValid = function() { var ret = null; for(var i=0; i 0) return; var handlers = this.event_handlers; if (this.input) { var self = this; this.input.setAttribute("AutoComplete", "off"); if (this.validateOn & Spry.Widget.ValidationConfirm.ONCHANGE) { var changeEvent = Spry.is.mozilla || Spry.is.opera || Spry.is.safari?"input": Spry.is.ie?"propertychange": "change"; handlers.push([this.input, changeEvent, function(e){if (self.isDisabled()) return true; return self.validate(e||event);}]); if (Spry.is.mozilla || Spry.is.safari) handlers.push([this.input, "dragdrop", function(e){if (self.isDisabled()) return true; return self.validate(e);}]); else if (Spry.is.ie) handlers.push([this.input, "drop", function(e){if (self.isDisabled()) return true; return self.validate(event);}]); } handlers.push([this.input, "blur", function(e) {if (self.isDisabled()) return true; return self.onBlur(e||event);}]); handlers.push([this.input, "focus", function(e) { if (self.isDisabled()) return true; return self.onFocus(e || event); }]); for (var i=0; i 0 && this.input.value != this.firstInput.value) { this.switchClassName(this.element, this.invalidClass); this.switchClassName(this.additionalError, this.invalidClass); return false; } this.switchClassName(this.element, this.validClass); this.switchClassName(this.additionalError, this.validClass); return true; }; Spry.Widget.ValidationConfirm.prototype.onBlur = function(e) { this.removeClassName(this.element, this.focusClass); this.removeClassName(this.additionalError, this.focusClass); if (this.validateOn & Spry.Widget.ValidationConfirm.ONBLUR) this.validate(e); }; Spry.Widget.ValidationConfirm.prototype.onFocus = function() { this.addClassName(this.element, this.focusClass); this.addClassName(this.additionalError, this.focusClass); }; Spry.Widget.ValidationConfirm.prototype.switchClassName = function(ele, className) { var classes = [this.validClass, this.requiredClass, this.invalidClass]; for (var i =0; i< classes.length; i++) this.removeClassName(ele, classes[i]); this.addClassName(ele, className); }; Spry.Widget.ValidationConfirm.prototype.addClassName = function(ele, className) { if (!ele || !className || (ele.className && ele.className.indexOf(className) != -1 && ele.className.search(new RegExp("\\b" + className + "\\b")) != -1)) return; ele.className += (ele.className ? " " : "") + className; }; Spry.Widget.ValidationConfirm.prototype.removeClassName = function(ele, className) { if (!ele || !className || (ele.className && ele.className.indexOf(className) != -1 && ele.className.search(new RegExp("\\b" + className + "\\b")) == -1)) return; ele.className = ele.className.replace(new RegExp("\\s*\\b" + className + "\\b", "g"), ""); }; Spry.Widget.ValidationConfirm.prototype.isBrowserSupported = function() { return Spry.is.ie && Spry.is.v >= 5 && Spry.is.windows || Spry.is.mozilla && Spry.is.v >= 1.4 || Spry.is.safari || Spry.is.opera && Spry.is.v >= 9; }; Spry.Widget.ValidationConfirm.prototype.isDisabled = function() { return this.input && (this.input.disabled || this.input.readOnly) || !this.input; }; Spry.Widget.ValidationConfirm.prototype.showError = function(msg) { alert('Spry.ValidationConfirm ERR: ' + msg); }; ////////////////////////////////////////////////////////////////////// // // Spry.Widget.Form - common for all widgets // ////////////////////////////////////////////////////////////////////// if (!Spry.Widget.Form) Spry.Widget.Form = {}; if (!Spry.Widget.Form.onSubmitWidgetQueue) Spry.Widget.Form.onSubmitWidgetQueue = []; if (!Spry.Widget.Form.validate) { Spry.Widget.Form.validate = function(vform) { var isValid = true; var isElementValid = true; var q = Spry.Widget.Form.onSubmitWidgetQueue; var qlen = q.length; for (var i = 0; i < qlen; i++) if (!q[i].isDisabled() && q[i].form == vform) { isElementValid = q[i].validate(); isValid = isElementValid && isValid; } return isValid; }; }; if(typeof(spry_popup_warning) == "undefined") { function spry_popup_warning() { if(typeof(document.getElementById("spry_popup_warning_message")) != "undefined" && document.getElementById("spry_popup_warning_message")) { document.getElementById("spry_popup_warning_message").style.display = "block"; if(typeof(spry_popup_warning_message_delay) != "undefined" && spry_popup_warning_message_delay) { setTimeout(function(){ reset_spry_popup_warning(); }, (spry_popup_warning_message_delay * 1000)); } else { setTimeout(function(){ reset_spry_popup_warning(); }, (3 * 1000)); } } } } if(typeof(reset_spry_popup_warning) == "undefined") { function reset_spry_popup_warning() { if(typeof(document.getElementById("spry_popup_warning_message")) != "undefined" && document.getElementById("spry_popup_warning_message")) { document.getElementById("spry_popup_warning_message").style.display = "none"; } } } if (!Spry.Widget.Form.onSubmit) { Spry.Widget.Form.onSubmit = function(e, form) { if (Spry.Widget.Form.validate(form) == false) { spry_popup_warning(); return false; } reset_spry_popup_warning(); return true; }; }; if (!Spry.Widget.Form.onReset) { Spry.Widget.Form.onReset = function(e, vform) { var q = Spry.Widget.Form.onSubmitWidgetQueue; var qlen = q.length; for (var i = 0; i < qlen; i++) if (!q[i].isDisabled() && q[i].form == vform && typeof(q[i].reset) == 'function') q[i].reset(); return true; }; }; if (!Spry.Widget.Form.destroy) { Spry.Widget.Form.destroy = function(form) { var q = Spry.Widget.Form.onSubmitWidgetQueue; for (var i = 0; i < Spry.Widget.Form.onSubmitWidgetQueue.length; i++) if (q[i].form == form && typeof(q[i].destroy) == 'function') { q[i].destroy(); i--; } } }; if (!Spry.Widget.Form.destroyAll) { Spry.Widget.Form.destroyAll = function() { var q = Spry.Widget.Form.onSubmitWidgetQueue; for (var i = 0; i < Spry.Widget.Form.onSubmitWidgetQueue.length; i++) if (typeof(q[i].destroy) == 'function') { q[i].destroy(); i--; } } }; ////////////////////////////////////////////////////////////////////// // // Spry.Widget.Utils // ////////////////////////////////////////////////////////////////////// if (!Spry.Widget.Utils) Spry.Widget.Utils = {}; Spry.Widget.Utils.setOptions = function(obj, optionsObj, ignoreUndefinedProps) { if (!optionsObj) return; for (var optionName in optionsObj) { if (ignoreUndefinedProps && optionsObj[optionName] == undefined) continue; obj[optionName] = optionsObj[optionName]; } }; Spry.Widget.Utils.firstValid = function() { var ret = null; for(var i=0; i