1// SpryValidationSelect.js - version 0.10 - Spry Pre-Release 1.5 2// 3// Copyright (c) 2006. Adobe Systems Incorporated. 4// All rights reserved. 5// 6// Redistribution and use in source and binary forms, with or without 7// modification, are permitted provided that the following conditions are met: 8// 9// * Redistributions of source code must retain the above copyright notice, 10// this list of conditions and the following disclaimer. 11// * Redistributions in binary form must reproduce the above copyright notice, 12// this list of conditions and the following disclaimer in the documentation 13// and/or other materials provided with the distribution. 14// * Neither the name of Adobe Systems Incorporated nor the names of its 15// contributors may be used to endorse or promote products derived from this 16// software without specific prior written permission. 17// 18// THIS SOFTWARE IS PROVIDED BY THE COPYRIGHT HOLDERS AND CONTRIBUTORS "AS IS" 19// AND ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE 20// IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE 21// ARE DISCLAIMED. IN NO EVENT SHALL THE COPYRIGHT OWNER OR CONTRIBUTORS BE 22// LIABLE FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR 23// CONSEQUENTIAL DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF 24// SUBSTITUTE GOODS OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS 25// INTERRUPTION) HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN 26// CONTRACT, STRICT LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) 27// ARISING IN ANY WAY OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE 28// POSSIBILITY OF SUCH DAMAGE. 29 30var Spry; 31if (!Spry) Spry = {}; 32if (!Spry.Widget) Spry.Widget = {}; 33 34Spry.Widget.ValidationSelect = function(element, opts) 35{ 36 this.init(element); 37 38 Spry.Widget.Utils.setOptions(this, opts); 39 40 // set validateOn flags 41 var validateOn = ['submit'].concat(this.validateOn || []); 42 validateOn = validateOn.join(","); 43 this.validateOn = 0 | (validateOn.indexOf('submit') != -1 ? Spry.Widget.ValidationSelect.ONSUBMIT : 0); 44 this.validateOn = this.validateOn | (validateOn.indexOf('blur') != -1 ? Spry.Widget.ValidationSelect.ONBLUR : 0); 45 this.validateOn = this.validateOn | (validateOn.indexOf('change') != -1 ? Spry.Widget.ValidationSelect.ONCHANGE : 0); 46 47 if (this.additionalError) 48 this.additionalError = this.getElement(this.additionalError); 49 50 // Unfortunately in some browsers like Safari, the Stylesheets our 51 // page depends on may not have been loaded at the time we are called. 52 // This means we have to defer attaching our behaviors until after the 53 // onload event fires, since some of our behaviors rely on dimensions 54 // specified in the CSS. 55 56 if (Spry.Widget.ValidationSelect.onloadDidFire) 57 this.attachBehaviors(); 58 else 59 Spry.Widget.ValidationSelect.loadQueue.push(this); 60}; 61 62Spry.Widget.ValidationSelect.ONCHANGE = 1; 63Spry.Widget.ValidationSelect.ONBLUR = 2; 64Spry.Widget.ValidationSelect.ONSUBMIT = 4; 65 66Spry.Widget.ValidationSelect.prototype.init = function(element) 67{ 68 this.element = this.getElement(element); 69 this.additionalError = false; 70 this.selectElement = null; 71 this.form = null; 72 this.event_handlers = []; 73 74 // this.element can be either the container (<span>) 75 // or the <select> element, when no error messages are used. 76 77 this.requiredClass = "selectRequiredState"; 78 this.invalidClass = "selectInvalidState"; 79 this.focusClass = "selectFocusState"; 80 this.validClass = "selectValidState"; 81 82 this.emptyValue = ""; 83 this.invalidValue = null; 84 this.isRequired = true; 85 86 this.validateOn = ["submit"]; // change, blur, submit 87 // flag used to avoid cascade validation when both 88 // onChange and onBlur events are used to trigger validation 89 this.validatedByOnChangeEvent = false; 90}; 91 92Spry.Widget.ValidationSelect.prototype.destroy = function() { 93 for (var i=0; i<this.event_handlers.length; i++) { 94 Spry.Widget.Utils.removeEventListener(this.event_handlers[i][0], this.event_handlers[i][1], this.event_handlers[i][2], false); 95 } 96 try { delete this.element; } catch(err) {} 97 try { delete this.selectElement; } catch(err) {} 98 try { delete this.form; } catch(err) {} 99 try { delete this.event_handlers; } catch(err) {} 100 101 var q = Spry.Widget.Form.onSubmitWidgetQueue; 102 var qlen = q.length; 103 for (var i = 0; i < qlen; i++) { 104 if (q[i] == this) { 105 q.splice(i, 1); 106 break; 107 } 108 } 109}; 110 111Spry.Widget.ValidationSelect.onloadDidFire = false;
112Spry.Widget.ValidationSelect.loadQueue = []; 113 114Spry.Widget.ValidationSelect.prototype.getElement = function(ele) 115{ 116 if (ele && typeof ele == "string") 117 return document.getElementById(ele); 118 return ele; 119}; 120 121Spry.Widget.ValidationSelect.processLoadQueue = function(handler) 122{ 123 Spry.Widget.ValidationSelect.onloadDidFire = true; 124 var q = Spry.Widget.ValidationSelect.loadQueue; 125 var qlen = q.length; 126 for (var i = 0; i < qlen; i++) 127 q[i].attachBehaviors(); 128}; 129 130Spry.Widget.ValidationSelect.addLoadListener = function(handler) 131{ 132 if (typeof window.addEventListener != 'undefined') 133 window.addEventListener('load', handler, false); 134 else if (typeof document.addEventListener != 'undefined') 135 document.addEventListener('load', handler, false); 136 else if (typeof window.attachEvent != 'undefined') 137 window.attachEvent('onload', handler); 138}; 139 140Spry.Widget.ValidationSelect.addLoadListener(Spry.Widget.ValidationSelect.processLoadQueue); 141Spry.Widget.ValidationSelect.addLoadListener(function(){ 142 Spry.Widget.Utils.addEventListener(window, "unload", Spry.Widget.Form.destroyAll, false); 143}); 144 145Spry.Widget.ValidationSelect.prototype.attachBehaviors = function() 146{ 147 // find the SELECT element inside current container 148 if (this.element.nodeName == "SELECT") { 149 this.selectElement = this.element; 150 } else { 151 this.selectElement = Spry.Widget.Utils.getFirstChildWithNodeNameAtAnyLevel(this.element, "SELECT"); 152 } 153 154 if (this.selectElement) { 155 var self = this; 156 this.event_handlers = []; 157 // focus 158 // attach on beforeactivate instead of focus for 159 // - IE 6 (to overcome this bug: setting a class name onfocus does not affect the open dropdown) 160 // - IE 7 (to overcome this bug: setting a class name, closes the select) 161 var focusEventName = "focus"; 162 var ua = navigator.userAgent.match(/msie (\d+)\./i); 163 if (ua) { 164 ua = parseInt(ua[1], 10); 165 if (ua >= 6) { 166 focusEventName = "beforeactivate"; 167 } 168 } 169 this.event_handlers.push([this.selectElement, focusEventName, function(e) { if (self.isDisabled()) return true; return self.onFocus(e); }]); 170 // blur 171 this.event_handlers.push([this.selectElement, "blur", function(e) { if (self.isDisabled()) return true; return self.onBlur(e); }]); 172 // change 173 if (this.validateOn & Spry.Widget.ValidationSelect.ONCHANGE) { 174 this.event_handlers.push([this.selectElement, "change", function(e) { if (self.isDisabled()) return true; return self.onChange(e); }]); 175 this.event_handlers.push([this.selectElement, "keypress", function(e) { if (self.isDisabled()) return true; return self.onChange(e); }]); 176 } 177 178 for (var i=0; i<this.event_handlers.length; i++) { 179 Spry.Widget.Utils.addEventListener(this.event_handlers[i][0], this.event_handlers[i][1], this.event_handlers[i][2], false); 180 } 181 182 // submit 183 this.form = Spry.Widget.Utils.getFirstParentWithNodeName(this.selectElement, "FORM"); 184 if (this.form) { 185 // if no "onSubmit" handler has been attached to the current form, attach one 186 if (!this.form.attachedSubmitHandler && !this.form.onsubmit) { 187 this.form.onsubmit = function(e) { e = e || event; return Spry.Widget.Form.onSubmit(e, e.srcElement || e.currentTarget) }; 188 this.form.attachedSubmitHandler = true; 189 } 190 if (!this.form.attachedResetHandler) { 191 Spry.Widget.Utils.addEventListener(this.form, "reset", function(e) { e = e || event; return Spry.Widget.Form.onReset(e, e.srcElement || e.currentTarget) }, false); 192 this.form.attachedResetHandler = true; 193 } 194 // add the currrent widget to the "onSubmit" check queue; 195 Spry.Widget.Form.onSubmitWidgetQueue.push(this); 196 } 197 } 198}; 199 200 201Spry.Widget.ValidationSelect.prototype.addClassName = function(ele, className) 202{ 203 if (!ele || !className || (ele.className && ele.className.search(new RegExp("\\b" + className + "\\b")) != -1)) 204 return; 205 ele.className += (ele.className ? " " : "") + className; 206}; 207 208Spry.Widget.ValidationSelect.prototype.removeClassName = function(ele, className) 209{ 210 if (!ele || !className || (ele.className && ele.className.search(new RegExp("\\b" + className + "\\b")) == -1)) 211 return; 212 ele.className = ele.className.replace(new RegExp("\\s*\\b" + className + "\\b", "g"), ""); 213}; 214 215 216 217Spry.Widget.ValidationSelect.prototype.onFocus = function(e) 218{ 219 this.hasFocus = true; 220 this.validatedByOnChangeEvent = false;
221 this.addClassName(this.element, this.focusClass); 222 this.addClassName(this.additionalError, this.focusClass); 223}; 224 225Spry.Widget.ValidationSelect.prototype.onBlur = function(e) 226{ 227 this.hasFocus = false; 228 var doValidation = false; 229 if (this.validateOn & Spry.Widget.ValidationSelect.ONBLUR) 230 doValidation = true; 231 if (doValidation && !this.validatedByOnChangeEvent) 232 this.validate(); 233 this.removeClassName(this.element, this.focusClass); 234 this.removeClassName(this.additionalError, this.focusClass); 235}; 236 237Spry.Widget.ValidationSelect.prototype.onChange = function(e) 238{ 239 this.hasFocus = false; 240 this.validate(); 241 this.validatedByOnChangeEvent = true; 242}; 243 244Spry.Widget.ValidationSelect.prototype.reset = function() { 245 this.removeClassName(this.element, this.requiredClass); 246 this.removeClassName(this.element, this.invalidClass); 247 this.removeClassName(this.element, this.validClass); 248 this.removeClassName(this.additionalError, this.requiredClass); 249 this.removeClassName(this.additionalError, this.invalidClass); 250 this.removeClassName(this.additionalError, this.validClass); 251}; 252 253Spry.Widget.ValidationSelect.prototype.validate = function() { 254 this.reset(); 255 // check isRequired 256 if (this.isRequired) { 257 // there are no options, or no option has been selected 258 if (this.selectElement.options.length == 0 || this.selectElement.selectedIndex == -1) { 259 this.addClassName(this.element, this.requiredClass); 260 this.addClassName(this.additionalError, this.requiredClass); 261 return false; 262 } 263 // the current selected option has no "value" attribute 264 // when no value is set, browsers implement different behaviour for the value property 265 // IE: value = blank string ("") 266 // FF, Opera: value = option text 267 if (this.selectElement.options[this.selectElement.selectedIndex].getAttribute("value") == null) { 268 this.addClassName(this.element, this.requiredClass); 269 this.addClassName(this.additionalError, this.requiredClass); 270 return false; 271 } 272 // the current selected option has blank string ("") value 273 if (this.selectElement.options[this.selectElement.selectedIndex].value == this.emptyValue) { 274 this.addClassName(this.element, this.requiredClass); 275 this.addClassName(this.additionalError, this.requiredClass); 276 return false; 277 } 278 // the current selected option has "disabled" attribute 279 // IE 6 allows to select such options 280 if (this.selectElement.options[this.selectElement.selectedIndex].disabled) { 281 this.addClassName(this.element, this.requiredClass); 282 this.addClassName(this.additionalError, this.requiredClass); 283 return false; 284 } 285 } 286 if (this.invalidValue) { 287 if (this.selectElement.options.length > 0 && 288 this.selectElement.selectedIndex != -1 && 289 this.selectElement.options[this.selectElement.selectedIndex].value == this.invalidValue) { 290 this.addClassName(this.element, this.invalidClass); 291 this.addClassName(this.additionalError, this.invalidClass); 292 return false; 293 } 294 } 295 this.addClassName(this.element, this.validClass); 296 this.addClassName(this.additionalError, this.validClass); 297 return true; 298} 299 300Spry.Widget.ValidationSelect.prototype.isDisabled = function() { 301 return this.selectElement.disabled; 302} 303 304////////////////////////////////////////////////////////////////////// 305// 306// Spry.Widget.Form - common for all widgets 307// 308////////////////////////////////////////////////////////////////////// 309 310if (!Spry.Widget.Form) Spry.Widget.Form = {}; 311if (!Spry.Widget.Form.onSubmitWidgetQueue) Spry.Widget.Form.onSubmitWidgetQueue = []; 312 313if (!Spry.Widget.Form.validate) { 314 Spry.Widget.Form.validate = function(vform) { 315 var isValid = true; 316 var isElementValid = true; 317 var q = Spry.Widget.Form.onSubmitWidgetQueue; 318 var qlen = q.length; 319 for (var i = 0; i < qlen; i++) { 320 if (!q[i].isDisabled() && q[i].form == vform) { 321 isElementValid = q[i].validate(); 322 isValid = isElementValid && isValid; 323 } 324 } 325 return isValid; 326 } 327}; 328 329if (!Spry.Widget.Form.onSubmit) { 330 Spry.Widget.Form.onSubmit = function(e, form) 331 { 332 if (Spry.Widget.Form.validate(form) == false) { 333 return false; 334 } 335 return true; 336 }; 337}; 338 339if (!Spry.Widget.Form.onReset) { 340 Spry.Widget.Form.onReset = function(e, vform) 341 { 342 var q = Spry.Widget.Form.onSubmitWidgetQueue; 343 var qlen = q.length; 344 for (var i = 0; i < qlen; i++) { 345 if (!q[i].isDisabled() && q[i].form == vform && typeof(q[i].reset) == 'function') { 346 q[i].reset(); 347 } 348 } 349 return true; 350 }; 351}; 352 353if (!Spry.Widget.Form.destroy) { 354 Spry.Widget.Form.destroy = function(form) 355 { 356 var q = Spry.Widget.Form.onSubmitWidgetQueue; 357 for (var i = 0; i < Spry.Widget.Form.onSubmitWidgetQueue.length; i++) { 358 if (q[i].form == form && typeof(q[i].destroy) == 'function') { 359 q[i].destroy(); 360 i--; 361 } 362 } 363 } 364}; 365 366if (!Spry.Widget.Form.destroyAll) { 367 Spry.Widget.Form.destroyAll = function() 368 { 369 var q = Spry.Widget.Form.onSubmitWidgetQueue; 370 for (var i = 0; i < Spry.Widget.Form.onSubmitWidgetQueue.length; i++) { 371 if (typeof(q[i].destroy) == 'function') { 372 q[i].destroy(); 373 i--; 374 } 375 } 376 } 377}; 378 379////////////////////////////////////////////////////////////////////// 380// 381// Spry.Widget.Utils 382// 383////////////////////////////////////////////////////////////////////// 384 385if (!Spry.Widget.Utils) Spry.Widget.Utils = {}; 386 387Spry.Widget.Utils.setOptions = function(obj, optionsObj, ignoreUndefinedProps) 388{ 389 if (!optionsObj) 390 return; 391 for (var optionName in optionsObj) 392 { 393 if (ignoreUndefinedProps && optionsObj[optionName] == undefined) 394 continue; 395 obj[optionName] = optionsObj[optionName]; 396 } 397}; 398 399 400Spry.Widget.Utils.getFirstChildWithNodeNameAtAnyLevel = function(node, nodeName) 401{
402 var elements = node.getElementsByTagName(nodeName); 403 if (elements) { 404 return elements[0]; 405 } 406 return null; 407}; 408 409Spry.Widget.Utils.getFirstParentWithNodeName = function(node, nodeName) 410{ 411 while (node.parentNode 412 && node.parentNode.nodeName.toLowerCase() != nodeName.toLowerCase() 413 && node.parentNode.nodeName != 'BODY') { 414 node = node.parentNode; 415 } 416 417 if (node.parentNode && node.parentNode.nodeName.toLowerCase() == nodeName.toLowerCase()) { 418 return node.parentNode; 419 } else { 420 return null; 421 } 422}; 423 424Spry.Widget.Utils.destroyWidgets = function (container) 425{ 426 if (typeof container == 'string') { 427 container = document.getElementById(container); 428 } 429 430 var q = Spry.Widget.Form.onSubmitWidgetQueue; 431 for (var i = 0; i < Spry.Widget.Form.onSubmitWidgetQueue.length; i++) { 432 if (typeof(q[i].destroy) == 'function' && Spry.Widget.Utils.contains(container, q[i].element)) { 433 q[i].destroy(); 434 i--; 435 } 436 } 437}; 438 439Spry.Widget.Utils.contains = function (who, what) 440{ 441 if (typeof who.contains == 'object') { 442 return what && who && (who == what || who.contains(what)); 443 } else { 444 var el = what; 445 while(el) { 446 if (el == who) { 447 return true; 448 } 449 el = el.parentNode; 450 } 451 return false; 452 } 453}; 454 455Spry.Widget.Utils.addEventListener = function(element, eventType, handler, capture) 456{ 457 try 458 { 459 if (element.addEventListener) 460 element.addEventListener(eventType, handler, capture); 461 else if (element.attachEvent) 462 element.attachEvent("on" + eventType, handler, capture); 463 } 464 catch (e) {} 465}; 466 467Spry.Widget.Utils.removeEventListener = function(element, eventType, handler, capture) 468{ 469 try 470 { 471 if (element.removeEventListener) 472 element.removeEventListener(eventType, handler, capture); 473 else if (element.detachEvent) 474 element.detachEvent("on" + eventType, handler, capture); 475 } 476 catch (e) {} 477}; 478 479
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.