// SpryValidationTextField.js - version 0.38 - 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.
(function() { // BeginSpryComponent
if (typeof Spry == "undefined") window.Spry = {}; if (!Spry.Widget) Spry.Widget = {};
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)
{
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);
//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) {
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 (!Spry.Widget.Form.onSubmit) {
Spry.Widget.Form.onSubmit = function(e, form)
{
if (Spry.Widget.Form.validate(form) == false) {
return false;
}
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