/* SpryValidationTextarea.js - Revision: Spry Preview Release 1.4 */ // 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.Widget.BrowserSniff = function() { var b = navigator.appName.toString(); var up = navigator.platform.toString(); var ua = navigator.userAgent.toString(); this.mozilla = this.ie = this.opera = r = false; var re_opera = /Opera.([0-9\.]*)/i; var re_msie = /MSIE.([0-9\.]*)/i; var re_gecko = /gecko/i; var re_safari = /safari\/([\d\.]*)/i; if (ua.match(re_opera)) { r = ua.match(re_opera); this.opera = true; this.version = parseFloat(r[1]); } else if (ua.match(re_msie)) { r = ua.match(re_msie); this.ie = true; this.version = parseFloat(r[1]); } else if (ua.match(re_safari)) { this.safari = true; this.version = 1.4; } 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.ValidationTextarea = function(element, options){ options = options || {}; this.flags = {locked: false}; this.options = {}; this.element = element; this.init(element); if (!this.isBrowserSupported()){ return; } options.useCharacterMasking = Spry.Widget.Utils.firstValid(options.useCharacterMasking, true); options.hint = Spry.Widget.Utils.firstValid(options.hint, ''); options.isRequired = Spry.Widget.Utils.firstValid(options.isRequired, true); Spry.Widget.Utils.setOptions(this, options); Spry.Widget.Utils.setOptions(this.options, 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.ValidationTextarea.ONSUBMIT : 0); this.validateOn = this.validateOn | (validateOn.indexOf('blur') != -1 ? Spry.Widget.ValidationTextarea.ONBLUR : 0); this.validateOn = this.validateOn | (validateOn.indexOf('change') != -1 ? Spry.Widget.ValidationTextarea.ONCHANGE : 0); if (Spry.Widget.ValidationTextarea.onloadDidFire){ this.attachBehaviors(); }else{ Spry.Widget.ValidationTextarea.loadQueue.push(this); } }; Spry.Widget.ValidationTextarea.ONCHANGE = 1; Spry.Widget.ValidationTextarea.ONBLUR = 2; Spry.Widget.ValidationTextarea.ONSUBMIT = 4; Spry.Widget.ValidationTextarea.INITIAL = 'Initial'; Spry.Widget.ValidationTextarea.REQUIRED = 'Required'; Spry.Widget.ValidationTextarea.INVALID = 'Invalid Format'; Spry.Widget.ValidationTextarea.MINIMUM = 'Minimum Number of Chars Not Met'; Spry.Widget.ValidationTextarea.MAXIMUM = 'Maximum Number of Chars Exceeded'; Spry.Widget.ValidationTextarea.VALID = 'Valid'; Spry.Widget.ValidationTextarea.prototype.init = function(element) { this.element = this.getElement(element); this.event_handlers = []; this.requiredClass = "textareaRequiredState"; this.invalidCharsMaxClass = "textareaMaxCharsState"; this.invalidCharsMinClass = "textareaMinCharsState"; this.validClass = "textareaValidState"; this.focusClass = "textareaFocusState"; this.textareaFlashClass = "textareaFlashState"; this.isMaxInvalid = false; this.isMinInvalid = false; this.isRequireInvalid = false; this.safariClicked = false; this.state = Spry.Widget.ValidationTextarea.INITIAL; }; Spry.Widget.ValidationTextarea.prototype.destroy = function() { for (var i=0; i= 5 && Spry.is.windows || Spry.is.mozilla && Spry.is.v >= 1.4 || Spry.is.safari || Spry.is.opera && Spry.is.v >= 9; }; /* * register our input to different event notifiers * */ Spry.Widget.ValidationTextarea.prototype.attachBehaviors = function() { if (this.element){ if (this.element.nodeName == "TEXTAREA") { this.input = this.element; } else { this.input = Spry.Widget.Utils.getFirstChildWithNodeNameAtAnyLevel(this.element, "TEXTAREA"); } } if (this.options && this.options.counterType && (this.options.counterType == 'chars_count' || this.options.counterType == 'chars_remaining')){ this.counterEl = document.getElementById(this.options.counterId); this.counterChar(); } if (this.input) { this.input.setAttribute("AutoComplete", "off"); this.putHint(); this.cursorPosition = new Spry.Widget.SelectionDescriptor(this.input); var self = this; this.event_handlers = []; //attach the pattern related event handlers (to stop invalid keys) if (this.useCharacterMasking) { if (Spry.is.ie){ this.event_handlers.push([this.input, "propertychange", function(e) { return self.onKeyEvent(e || event); }]); this.event_handlers.push([this.input, "drop", function(e) { return self.onDrop (e || event); }]); this.event_handlers.push([this.input, "keypress", function(e) { return self.onKeyPress(e || event); }]); } else{ this.event_handlers.push([this.input, "keydown", function(e) { return self.onKeyDown(e); }]); this.event_handlers.push([this.input, "keypress", function(e) { return self.safariKeyPress(e); }]); this.event_handlers.push([this.input, "keyup", function(e) { return self.safariValidate(e); }]); if (Spry.is.safari){ this.event_handlers.push([this.input, "mouseup", function(e) { return self.safariMouseUp(e); }]); this.event_handlers.push([this.input, "mousedown", function(e) { return self.safariMouseDown(e); }]); } else { //Firefox bug: 355219 //this.event_handlers.push([this.input, "input", function(e) { self.onKeyEvent(e); return true;}]); this.event_handlers.push([this.input, "dragdrop", function(e) { return self.onKeyEvent(e); }]); this.event_handlers.push([this.input, "dragenter", function(e) { self.removeHint(); return self.onKeyDown(e); }]); this.event_handlers.push([this.input, "dragexit", function(e) { return self.putHint(); }]); } } // we need to save an initial state in case of invalid input this.event_handlers.push([this.input, "keydown", function(e) {return self.onKeyDown(e || event); }]); } this.event_handlers.push([this.input, "focus", function(e) { return self.onFocus(e || event); }]); this.event_handlers.push([this.input, "mousedown", function(e) { return self.onMouseDown(e || event); }]); this.event_handlers.push([this.input, "blur", function(e) { return self.onBlur(e || event); }]); if (this.validateOn & Spry.Widget.ValidationTextarea.ONCHANGE){ if (Spry.is.ie){ this.event_handlers.push([this.input, "propertychange", function(e) { return self.onChange(e || event); }]); this.event_handlers.push([this.input, "drop", function(e) { return self.onChange(e || event); }]); } else{ this.event_handlers.push([this.input, "keydown", function(e) { return self.onKeyDown(e); }]); this.event_handlers.push([this.input, "keypress", function(e) { return self.safariChangeKeyPress(e); }]); this.event_handlers.push([this.input, "keyup", function(e) { return self.safariChangeValidate(e); }]); if (Spry.is.safari){ this.event_handlers.push([this.input, "mouseup", function(e) { return self.safariChangeMouseUp(e); }]); this.event_handlers.push([this.input, "mousedown", function(e) { return self.safariMouseDown(e); }]); } else { // Firefox bug: 355219 //this.event_handlers.push([this.input, "input", function(e) { return self.onChange(e); }]); this.event_handlers.push([this.input, "dragdrop", function(e) {return self.onChange(e); }]); this.event_handlers.push([this.input, "dragenter", function(e) { self.removeHint(); return self.onKeyDown(e); }]); this.event_handlers.push([this.input, "dragexit", function(e) { return self.putHint(); }]); } } } // The counter should be called directly when no enforcement or change restrictions exists if (! (this.validateOn & Spry.Widget.ValidationTextarea.ONCHANGE) && !this.useCharacterMasking){ if (Spry.is.ie){ this.event_handlers.push([this.input, "propertychange", function(e) { return self.counterChar(); }]); this.event_handlers.push([this.input, "drop", function(e) { return self.counterChar(); }]); } else{ this.event_handlers.push([this.input, "keypress", function(e) { return self.counterChar(); }]); this.event_handlers.push([this.input, "keyup", function(e) { return self.counterChar(); }]); if (Spry.is.safari){ this.event_handlers.push([this.input, "mouseup", function(e) { return self.counterChar(); }]); } else { // Firefox bug: 355219 //this.event_handlers.push([this.input, "input", function(e) { return self.onChange(e); }]); this.event_handlers.push([this.input, "dragdrop", function(e) {return self.counterChar(); }]); } } } for (var i=0; i 0 && ret){ if ( val.length > this.options.maxChars && ((!Spry.Widget.Utils.isSpecialKey(e) && this.cursorPosition.start == this.cursorPosition.end) || (Spry.Widget.Utils.isSpecialKey(e) && val != this.initialValue) || this.cursorPosition.start != this.cursorPosition.end) ){ // cut the extra chars and display error this.flags.locked = true; var initial = this.initialValue; var start = this.initialCursor.start; var end = this.initialCursor.end; if (initial.length && this.initialCursor.end < initial.length) { // we try to behave more like maxlength textfield var tmp = end - start + this.options.maxChars - initial.length; var newValue = initial.substring(0, start) + val.substring(start, start+tmp) + initial.substring(end, initial.length < this.options.maxChars ? initial.length:this.options.maxChars); end = start + tmp; }else{ var newValue = val.substring(0, this.options.maxChars); end = start = this.options.maxChars; } if (Spry.is.ie) { this.input.innerText = newValue; } else { this.input.value = newValue; } this.redTextFlash(); this.cursorPosition.moveTo(end, end); this.flags.locked = false; ret = false; } else{ this.setState(Spry.Widget.ValidationTextarea.VALID); this.isMaxInvalid = false; } } this.counterChar(); return ret; }; Spry.Widget.ValidationTextarea.prototype.validateMinRequired = function(val){ var oldInvalid = false; if (typeof this.notFireMinYet == 'undefined'){ this.notFireMinYet = false; }else{ oldInvalid = true; this.notFireMinYet = true; } if (this.onBlurOn){ this.notFireMinYet = true; }else if (!this.onKeyEventOn){ this.notFireMinYet = true; } if (this.input && this.options && this.options.isRequired){ if (val.length > 0 && this.isRequireInvalid && (!this.hint || (this.hint && !this.flags.hintOn) || (this.hint && val != this.hint))){ this.switchClassName(this.validClass); this.setState(Spry.Widget.ValidationTextarea.VALID); this.isRequireInvalid = false; }else if ((val.length == 0 || !(!this.hint || (this.hint && !this.flags.hintOn) || (this.hint && val != this.hint))) && (!this.isRequireInvalid || oldInvalid)){ if (this.notFireMinYet || Spry.is.ie){ this.switchClassName(this.requiredClass); this.setState(Spry.Widget.ValidationTextarea.REQUIRED); } this.isRequireInvalid = true; this.isMinInvalid = false; } } if (this.input && this.options && this.options.minChars > 0 && !this.isRequireInvalid){ if (val.length >= this.options.minChars && (!this.hint || (this.hint && !this.flags.hintOn) || (this.hint && val != this.hint)) && this.isMinInvalid){ this.switchClassName(this.validClass); this.setState(Spry.Widget.ValidationTextarea.VALID); this.isMinInvalid = false; }else if ( (val.length < this.options.minChars || (this.hint && val == this.hint && this.flags.hintOn)) && !this.isMinInvalid){ this.switchClassName(this.invalidCharsMinClass); this.setState(Spry.Widget.ValidationTextarea.MINIMUM); this.isMinInvalid = true; } } }; Spry.Widget.ValidationTextarea.prototype.counterChar = function(){ if (!this.counterEl || !this.options || !this.options.counterType || (this.options.counterType != 'chars_remaining' && this.options.counterType != 'chars_count')){ return; } if (this.options.counterType == 'chars_remaining') { if (this.options.maxChars > 0){ if (this.flags.hintOn){ this.setCounterElementValue(this.options.maxChars); } else { if (this.options.maxChars > this.input.value.length){ this.setCounterElementValue(this.options.maxChars - this.input.value.length); }else{ this.setCounterElementValue(0); } } } } else { if (this.flags.hintOn){ this.setCounterElementValue(0); } else { if (this.useCharacterMasking && typeof this.options.maxChars != 'undefined' && this.options.maxChars < this.input.value.length){ this.setCounterElementValue(this.options.maxChars); } else { this.setCounterElementValue(this.input.value.length); } } } }; Spry.Widget.ValidationTextarea.prototype.setCounterElementValue = function(val){ if ( this.counterEl.nodeName.toLowerCase() != 'input' && this.counterEl.nodeName.toLowerCase() != 'textarea' && this.counterEl.nodeName.toLowerCase() != 'select' && this.counterEl.nodeName.toLowerCase() != 'img'){ this.counterEl.innerHTML = val; } }; Spry.Widget.ValidationTextarea.prototype.reset = function() { this.removeHint(); this.removeClassName(this.requiredClass); this.removeClassName(this.invalidCharsMinClass); this.removeClassName(this.invalidCharsMaxClass); this.removeClassName(this.validClass); this.setState(Spry.Widget.ValidationTextarea.INITIAL); var self = this; setTimeout(function() {self.putHint();self.counterChar();}, 10); }; Spry.Widget.ValidationTextarea.prototype.validate = function(){ if (this.input.disabled == true || this.input.readOnly == true){ return true; } var val = this.input.value; this.validateMinRequired(val); var ret = !this.isMinInvalid && !this.isRequireInvalid; if (ret && this.options.maxChars > 0 && !this.useCharacterMasking){ if (val.length <= this.options.maxChars || (this.hint && this.hint == val && this.flags.hintOn)) { this.switchClassName(this.validClass); this.setState(Spry.Widget.ValidationTextarea.VALID); this.isMaxInvalid = false; }else{ this.switchClassName(this.invalidCharsMaxClass); this.setState(Spry.Widget.ValidationTextarea.MAXIMUM); this.isMaxInvalid = true; } } ret = ret && !this.isMaxInvalid; if (ret) { this.switchClassName(this.validClass); } this.counterChar(); return ret; }; Spry.Widget.ValidationTextarea.prototype.setState = function(newstate){ this.state = newstate; }; Spry.Widget.ValidationTextarea.prototype.getState = function(){ return this.state; }; Spry.Widget.ValidationTextarea.prototype.removeHint = function() { if (this.flags.hintOn) { this.flags.locked = true; this.input.value = ""; this.flags.locked = false; this.flags.hintOn = false; } }; Spry.Widget.ValidationTextarea.prototype.putHint = function() { if(this.hint && this.input.value == "") { this.flags.hintOn = true; this.input.value = this.hint; } }; Spry.Widget.ValidationTextarea.prototype.redTextFlash = function() { var self = this; this.addClassName(this.textareaFlashClass); setTimeout(function() { self.removeClassName(self.textareaFlashClass) }, 200); }; Spry.Widget.ValidationTextarea.prototype.onKeyPress = function(e) { //ENTER has length 2 on IE Windows, so will exceed maxLength on proximity if (Spry.is.ie && Spry.is.windows && e.keyCode == 13) { if ( (this.initialCursor.length + this.options.maxChars - this.input.value.length) < 2) { Spry.Widget.Utils.stopEvent(e); return false; } } }; Spry.Widget.ValidationTextarea.prototype.onKeyDown = function(e) { this.saveState(); this.keyCode = e.keyCode; return true; }; /* * hadle for the max chars restrictions * if key pressed or the input text is invalid it returns false * */ Spry.Widget.ValidationTextarea.prototype.onKeyEvent = function(e){ // on IE we look only for this input value changes if (e.type == 'propertychange' && e.propertyName != 'value'){ return true; } var allow = this.onTyping(e); if (!allow){ Spry.Widget.Utils.stopEvent(e); } //return allow; }; /* * handle for the min or required value * if the input text is invalid it returns false * */ Spry.Widget.ValidationTextarea.prototype.onChange = function(e){ if (Spry.is.ie && e && e.type == 'propertychange' && 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 true; } if (this.flags.hintOn) { return true; } this.onKeyEventOn = true; var answer = this.validate(); this.onKeyEventOn = false; return answer; }; Spry.Widget.ValidationTextarea.prototype.onMouseDown = function(e) { if (this.flags.active) { //mousedown fires before focus //avoid double saveState on first focus by mousedown by checking if the control has focus //do nothing if it's not focused because saveState will be called onfocus this.saveState(); } }; Spry.Widget.ValidationTextarea.prototype.onDrop = function(e) { //mark that a drop operation is in progress to avoid race conditions with event handlers for other events //especially onchange and onfocus this.flags.drop = true; this.removeHint(); if (Spry.is.ie) { var rng = document.body.createTextRange(); rng.moveToPoint(e.x, e.y); rng.select(); } this.saveState(); this.flags.active = true; this.addClassName(this.focusClass); }; Spry.Widget.ValidationTextarea.prototype.onFocus = function(e) { if (this.flags.drop) { return; } this.removeHint(); this.saveState(); this.flags.active = true; this.addClassName(this.focusClass); }; Spry.Widget.ValidationTextarea.prototype.onBlur = function(e){ this.removeClassName(this.focusClass); if (this.validateOn & Spry.Widget.ValidationTextarea.ONBLUR) { this.onBlurOn = true; this.validate(); this.onBlurOn = false; } this.flags.active = false; var self = this; setTimeout(function() {self.putHint();}, 10); }; Spry.Widget.ValidationTextarea.prototype.safariMouseDown = function(e){ this.safariClicked = true; }; Spry.Widget.ValidationTextarea.prototype.safariChangeMouseUp = function(e){ if (!this.safariClicked){ this.onKeyDown(e); return this.safariChangeValidate(e, false); }else{ this.safariClicked = false; return true; } }; Spry.Widget.ValidationTextarea.prototype.safariMouseUp = function(e){ if (!this.safariClicked){ this.onKeyDown(e); return this.safariValidate(e, false); }else{ this.safariClicked = false; return true; } }; Spry.Widget.ValidationTextarea.prototype.safariKeyPress = function(e){ this.safariFlag = new Date(); return this.safariValidate(e, true); }; Spry.Widget.ValidationTextarea.prototype.safariValidate = function(e, recall) { if (e.keyCode && Spry.Widget.Utils.isSpecialKey(e) && e.keyCode != 8 && e.keyCode != 46){ return true; } var answer = this.onTyping(e); // the answer to this is not yet final - we schedule another closing check if (new Date() - this.safariFlag < 1000 && recall){ var self = this; setTimeout(function(){self.safariValidate(e, false);}, 1000); } return answer; }; Spry.Widget.ValidationTextarea.prototype.safariChangeKeyPress = function(e){ this.safariChangeFlag = new Date(); return this.safariChangeValidate(e, true); }; Spry.Widget.ValidationTextarea.prototype.safariChangeValidate = function(e, recall){ if(e.keyCode && Spry.Widget.Utils.isSpecialKey(e) && e.keyCode != 8 && e.keyCode != 46){ return true; } var answer = this.onChange(e); // the answer to this is not yet final - we schedule another closing check if (new Date() - this.safariChangeFlag < 1000 && recall){ var self = this; setTimeout(function(){ self.safariChangeValidate(e, false);}, 1000 - new Date() + this.safariChangeFlag); } return answer; }; /* * save an initial state of the input to restore if the value is invalid * */ Spry.Widget.ValidationTextarea.prototype.saveState = function(e){ // we don't need this initial value that is already invalid if (this.options.maxChars > 0 && this.input.value.length > this.options.maxChars){ return; } this.cursorPosition.update(); if (!this.flags.hintOn){ this.initialValue = this.input.value; }else{ this.initialValue = ''; } this.initialCursor = this.cursorPosition; return true; }; Spry.Widget.ValidationTextarea.prototype.checkClassName = function(ele, className){ if (!ele || !className){ return false; } if (typeof ele == 'string' ) { ele = document.getElementById(ele); if (!ele){ return false; } } if (!ele.className){ ele.className = ' '; } return ele; }; Spry.Widget.ValidationTextarea.prototype.switchClassName = function (className){ var classes = [this.invalidCharsMaxClass, this.validClass, this.requiredClass, this.invalidCharsMinClass]; var self = this; for (var k in classes){ if (classes[k] != className){ this.removeClassName(classes[k]); } } this.addClassName(className); }; Spry.Widget.ValidationTextarea.prototype.addClassName = function(clssName){ var ele = this.checkClassName(this.element, clssName); if (!ele || ele.className.search(new RegExp("\\b" + clssName + "\\b")) != -1){ return; } this.element.className += ' ' + clssName; }; Spry.Widget.ValidationTextarea.prototype.removeClassName = function(className){ var ele = this.checkClassName(this.element, className); if (!ele){ return; } ele.className = ele.className.replace(new RegExp("\\s*\\b" + className + "\\b", "g"), ''); }; /** * 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) { if (this.element.nodeName == "TEXTAREA") { var range = this.element.ownerDocument.selection.createRange(); 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"){ this.range = this.element.ownerDocument.selection.createRange(); 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.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.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.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