   1. // SpryValidationRadio.js - version 0.1 - Spry Pre-Release 1.5  
   2. //  
   3. // Copyright (c) 2007. 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.   
  30. var Spry;  
  31. if (!Spry) Spry = {};  
  32. if (!Spry.Widget) Spry.Widget = {};  
  33.   
  34. Spry.Widget.ValidationRadio = 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.ValidationRadio.ONSUBMIT : 0);  
  44.     this.validateOn = this.validateOn | (validateOn.indexOf('blur') != -1 ? Spry.Widget.ValidationRadio.ONBLUR : 0);  
  45.     this.validateOn = this.validateOn | (validateOn.indexOf('change') != -1 ? Spry.Widget.ValidationRadio.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.ValidationRadio.onloadDidFire)  
  57.         this.attachBehaviors();  
  58.     else   
  59.         Spry.Widget.ValidationRadio.loadQueue.push(this);  
  60. };  
  61.   
  62. Spry.Widget.ValidationRadio.ONCHANGE = 1;  
  63. Spry.Widget.ValidationRadio.ONBLUR = 2;  
  64. Spry.Widget.ValidationRadio.ONSUBMIT = 4;  
  65.   
  66. Spry.Widget.ValidationRadio.prototype.init = function(element)  
  67. {  
  68.     this.element = this.getElement(element);  
  69.     this.additionalError = false;  
  70.     this.radioElements = null;  
  71.     this.form = null;  
  72.     this.event_handlers = [];  
  73.       
  74.      // this.element can be either the container (<span>)  
  75.      // or the <input type="radio"> element, when no error messages are used.  
  76.     this.requiredClass = "radioRequiredState";  
  77.     this.focusClass = "radioFocusState";  
  78.     this.invalidClass = "radioInvalidState";  
  79.     this.validClass = "radioValidState";  
  80.   
  81.     this.emptyValue = "";  
  82.     this.invalidValue = null;  
  83.     this.isRequired = true;  
  84.     this.validateOn = ["submit"]; // change, submit (blur ?)  
  85. };  
  86.   
  87. Spry.Widget.ValidationRadio.onloadDidFire = false;  
  88. Spry.Widget.ValidationRadio.loadQueue = [];  
  89.   
  90. Spry.Widget.ValidationRadio.prototype.getElement = function(ele)  
  91. {  
  92.     if (ele && typeof ele == "string")  
  93.         return document.getElementById(ele);  
  94.     return ele;  
  95. };  
  96.   
  97. Spry.Widget.ValidationRadio.processLoadQueue = function(handler)  
  98. {  
  99.     Spry.Widget.ValidationRadio.onloadDidFire = true;  
 100.     var q = Spry.Widget.ValidationRadio.loadQueue;  
 101.     var qlen = q.length;  
 102.     for (var i = 0; i < qlen; i++)  
 103.         q[i].attachBehaviors();  
 104. };  
 105.   
 106. Spry.Widget.ValidationRadio.addLoadListener = function(handler)  
 107. {  
 108.     if (typeof window.addEventListener != 'undefined')  
 109.         window.addEventListener('load', handler, false);  
 110.     else if (typeof document.addEventListener != 'undefined')  
 111.         document.addEventListener('load', handler, false);  
 112.     else if (typeof window.attachEvent != 'undefined')  
 113.         window.attachEvent('onload', handler);  
 114. };  
 115.   
 116. Spry.Widget.ValidationRadio.addLoadListener(Spry.Widget.ValidationRadio.processLoadQueue);  
 117. Spry.Widget.ValidationRadio.addLoadListener(function(){  
 118.     Spry.Widget.Utils.addEventListener(window, "unload", Spry.Widget.Form.destroyAll, false);  
 119. });  
 120.   
 121. Spry.Widget.ValidationRadio.prototype.attachBehaviors = function()  
 122. {  
 123.     // find the INPUT type="Radio" element(s) inside current container  
 124.     if (this.element.nodeName == "INPUT") {  
 125.         this.radioElements = [this.element];  
 126.     } else {  
 127.         this.radioElements = this.getRadios();  
 128.     }  
 129.     if (this.radioElements) {  
 130.         var self = this;  
 131.         this.event_handlers = [];  
 132.   
 133.         var qlen = this.radioElements.length;  
 134.         for (var i = 0; i < qlen; i++) {  
 135.             // focus  
 136.             this.event_handlers.push([this.radioElements[i], "focus", function(e) { return self.onFocus(e); }]);  
 137.             // blur  
 138.             this.event_handlers.push([this.radioElements[i], "blur", function(e) { return self.onBlur(e); }]);  
 139.             // add click instead of onChange  
 140.             if (this.validateOn & Spry.Widget.ValidationRadio.ONCHANGE) {  
 141.                 this.event_handlers.push([this.radioElements[i], "click", function(e) { return self.onClick(e); }]);  
 142.             }  
 143.         }  
 144.   
 145.         for (var i=0; i<this.event_handlers.length; i++) {  
 146.             Spry.Widget.Utils.addEventListener(this.event_handlers[i][0], this.event_handlers[i][1], this.event_handlers[i][2], false);  
 147.         }  
 148.   
 149.         // submit  
 150.         this.form = Spry.Widget.Utils.getFirstParentWithNodeName(this.element, "FORM");  
 151.         if (this.form) {  
 152.             // if no "onSubmit" handler has been attached to the current form, attach one  
 153.             if (!this.form.attachedSubmitHandler && !this.form.onsubmit) {  
 154.                 this.form.onsubmit = function(e) { e = e || event; return Spry.Widget.Form.onSubmit(e, e.srcElement || e.currentTarget) };  
 155.                 this.form.attachedSubmitHandler = true;  
 156.             }  
 157.             if (!this.form.attachedResetHandler) {  
 158.                 Spry.Widget.Utils.addEventListener(this.form, "reset", function(e) { e = e || event; return Spry.Widget.Form.onReset(e, e.srcElement || e.currentTarget) }, false);  
 159.                 this.form.attachedResetHandler = true;  
 160.             }  
 161.             // add the currrent widget to the "onSubmit" check queue;  
 162.             Spry.Widget.Form.onSubmitWidgetQueue.push(this);  
 163.         }  
 164.     }  
 165. };  
 166.   
 167. Spry.Widget.ValidationRadio.prototype.getRadios = function()  
 168. {  
 169.     var arrRadios;  
 170.     var elements  = this.element.getElementsByTagName("INPUT");  
 171.     if (elements.length) {  
 172.         arrRadios = [];  
 173.         var qlen = elements.length;  
 174.         for (var i = 0; i < qlen; i++)  
 175.         {  
 176.             if (elements[i].getAttribute('type').toLowerCase() == "radio")  
 177.                 arrRadios.push(elements[i]);  
 178.         }  
 179.         return arrRadios;  
 180.     }  
 181.     return null;  
 182. };  
 183.   
 184. Spry.Widget.ValidationRadio.prototype.addClassName = function(ele, className)  
 185. {  
 186.     if (!ele || !className || (ele.className && ele.className.search(new RegExp("\\b" + className + "\\b")) != -1))  
 187.         return;  
 188.     ele.className += (ele.className ? " " : "") + className;  
 189. };  
 190.   
 191. Spry.Widget.ValidationRadio.prototype.removeClassName = function(ele, className)  
 192. {  
 193.     if (!ele || !className || (ele.className && ele.className.search(new RegExp("\\b" + className + "\\b")) == -1))  
 194.         return;  
 195.     ele.className = ele.className.replace(new RegExp("\\s*\\b" + className + "\\b", "g"), "");  
 196. };  
 197.   
 198. Spry.Widget.ValidationRadio.prototype.onFocus = function(e)  
 199. {  
 200.     var eventRadio = (e.srcElement != null) ? e.srcElement : e.target;  
 201.     if (eventRadio.disabled) return;  
 202.    
 203.     this.addClassName(this.element, this.focusClass);  
 204.     this.addClassName(this.additionalError, this.focusClass);  
 205. };  
 206.   
 207. Spry.Widget.ValidationRadio.prototype.onBlur = function(e)  
 208. {  
 209.     var eventRadio = (e.srcElement != null) ? e.srcElement : e.target;  
 210.     if (eventRadio.disabled) return;  
 211.   
 212.     var doValidation = false;  
 213.     if (this.validateOn & Spry.Widget.ValidationRadio.ONBLUR)  
 214.         doValidation = true;  
 215.     if (doValidation)  
 216.         this.validate();  
 217.     this.removeClassName(this.element, this.focusClass);  
 218.     this.removeClassName(this.additionalError, this.focusClass);  
 219. };  
 220.   
 221. Spry.Widget.ValidationRadio.prototype.onClick = function(e) {  
 222.     var eventRadio = (e.srcElement != null) ? e.srcElement : e.target;  
 223.     if (eventRadio.disabled) return;  
 224.     this.validate();  
 225. };  
 226.   
 227. Spry.Widget.ValidationRadio.prototype.reset = function()  
 228. {  
 229.     this.removeClassName(this.element, this.validClass);  
 230.     this.removeClassName(this.element, this.requiredClass);  
 231.     this.removeClassName(this.element, this.invalidClass);  
 232.     this.removeClassName(this.additionalError, this.validClass);  
 233.     this.removeClassName(this.additionalError, this.requiredClass);  
 234.     this.removeClassName(this.additionalError, this.invalidClass);  
 235. };  
 236.   
 237. Spry.Widget.ValidationRadio.prototype.validate = function()  
 238. {  
 239.     this.reset();  
 240.     var nochecked = 0;  
 241.     var invalid = 0;  
 242.     var required = 0;  
 243.     if (this.radioElements)  
 244.     {  
 245.         var qlen = this.radioElements.length;  
 246.         for (var i = 0; i < qlen; i++)  
 247.         {  
 248.             if (!this.radioElements[i].disabled && this.radioElements[i].checked)  
 249.             {  
 250.                 if (this.radioElements[i].value == this.emptyValue){  
 251.                     required++;  
 252.                 }else if (this.invalidValue && this.radioElements[i].value == this.invalidValue){  
 253.                     invalid++;  
 254.                 }else{  
 255.                     nochecked++;  
 256.                 }  
 257.             }  
 258.         }  
 259.     }  
 260.     if (this.invalidValue && invalid != 0)  
 261.     {  
 262.         this.addClassName(this.element, this.invalidClass);  
 263.         this.addClassName(this.additionalError, this.invalidClass);  
 264.         return false;  
 265.     }  
 266.   
 267.     // check isRequired  
 268.     if (this.isRequired && (nochecked == 0 || required != 0))  
 269.     {  
 270.             this.addClassName(this.element, this.requiredClass);  
 271.             this.addClassName(this.additionalError, this.requiredClass);  
 272.             return false;  
 273.     }  
 274.     this.addClassName(this.element, this.validClass);  
 275.     this.addClassName(this.additionalError, this.validClass);  
 276.     return true;  
 277. };  
 278.   
 279. Spry.Widget.ValidationRadio.prototype.isDisabled = function()  
 280. {  
 281.     var ret = true;  
 282.     if (this.radioElements) {  
 283.         var qlen = this.radioElements.length;  
 284.         for (var i = 0; i < qlen; i++)  
 285.         {  
 286.             if (!this.radioElements[i].disabled)  
 287.             {  
 288.                 ret = false;  
 289.                 break;  
 290.             }  
 291.         }  
 292.     }  
 293.     return ret;  
 294. };  
 295.   
 296. Spry.Widget.ValidationRadio.prototype.destroy = function()  
 297. {  
 298.     for (var i=0; i<this.event_handlers.length; i++) {  
 299.         Spry.Widget.Utils.removeEventListener(this.event_handlers[i][0], this.event_handlers[i][1], this.event_handlers[i][2], false);  
 300.     }  
 301.     try { delete this.element; } catch(err) {}  
 302.     for(var i=0; i < this.radioElements.length; i++) {  
 303.         try { delete this.radioElements[i];} catch(err) {}  
 304.     }  
 305.     try { delete this.radioElements; } catch(err) {}  
 306.     try { delete this.form; } catch(err) {}  
 307.     try { delete this.event_handlers; } catch(err) {}  
 308.   
 309.     var q = Spry.Widget.Form.onSubmitWidgetQueue;  
 310.     var qlen = q.length;  
 311.     for (var i = 0; i < qlen; i++) {  
 312.         if (q[i] == this) {  
 313.             q.splice(i, 1);  
 314.             break;  
 315.         }  
 316.     }  
 317. };  
 318.   
 319. //////////////////////////////////////////////////////////////////////  
 320. //  
 321. // Spry.Widget.Form - common for all widgets  
 322. //  
 323. //////////////////////////////////////////////////////////////////////  
 324.   
 325. if (!Spry.Widget.Form) Spry.Widget.Form = {};  
 326. if (!Spry.Widget.Form.onSubmitWidgetQueue) Spry.Widget.Form.onSubmitWidgetQueue = [];  
 327.   
 328. if (!Spry.Widget.Form.validate) {  
 329.     Spry.Widget.Form.validate = function(vform) {  
 330.         var isValid = true;  
 331.         var isElementValid = true;  
 332.         var q = Spry.Widget.Form.onSubmitWidgetQueue;  
 333.         var qlen = q.length;  
 334.         for (var i = 0; i < qlen; i++) {  
 335.             if (!q[i].isDisabled() && q[i].form == vform) {  
 336.                 isElementValid = q[i].validate();  
 337.                 isValid = isElementValid && isValid;  
 338.             }  
 339.         }  
 340.         return isValid;  
 341.     }  
 342. };  
 343.   
 344. if (!Spry.Widget.Form.onSubmit) {  
 345.     Spry.Widget.Form.onSubmit = function(e, form)  
 346.     {  
 347.         if (Spry.Widget.Form.validate(form) == false) {  
 348.             return false;  
 349.         }  
 350.         return true;  
 351.     };  
 352. };  
 353.   
 354. if (!Spry.Widget.Form.onReset) {  
 355.     Spry.Widget.Form.onReset = function(e, vform)  
 356.     {  
 357.         var q = Spry.Widget.Form.onSubmitWidgetQueue;  

 358.         var qlen = q.length;  
 359.         for (var i = 0; i < qlen; i++) {  
 360.             if (!q[i].isDisabled() && q[i].form == vform && typeof(q[i].reset) == 'function') {  
 361.                 q[i].reset();  
 362.             }  
 363.         }  
 364.         return true;  
 365.     };  
 366. };  
 367.   
 368. if (!Spry.Widget.Form.destroy) {  
 369.     Spry.Widget.Form.destroy = function(form)  
 370.     {  
 371.         var q = Spry.Widget.Form.onSubmitWidgetQueue;  
 372.         for (var i = 0; i < Spry.Widget.Form.onSubmitWidgetQueue.length; i++) {  
 373.             if (q[i].form == form && typeof(q[i].destroy) == 'function') {  
 374.                 q[i].destroy();  
 375.                 i--;  
 376.             }  
 377.         }  
 378.     }  
 379. };  
 380.   
 381. if (!Spry.Widget.Form.destroyAll) {  
 382.     Spry.Widget.Form.destroyAll = function()  
 383.     {  
 384.         var q = Spry.Widget.Form.onSubmitWidgetQueue;  
 385.         for (var i = 0; i < Spry.Widget.Form.onSubmitWidgetQueue.length; i++) {  
 386.             if (typeof(q[i].destroy) == 'function') {  
 387.                 q[i].destroy();  
 388.                 i--;  
 389.             }  
 390.         }  
 391.     }  
 392. };  
 393.   
 394. //////////////////////////////////////////////////////////////////////  
 395. //  
 396. // Spry.Widget.Utils  
 397. //  
 398. //////////////////////////////////////////////////////////////////////  
 399.   
 400. if (!Spry.Widget.Utils) Spry.Widget.Utils = {};  
 401.   
 402. Spry.Widget.Utils.setOptions = function(obj, optionsObj, ignoreUndefinedProps)  
 403. {  
 404.     if (!optionsObj)  
 405.         return;  
 406.     for (var optionName in optionsObj)  
 407.     {  
 408.         if (ignoreUndefinedProps && optionsObj[optionName] == undefined)  
 409.             continue;  
 410.         obj[optionName] = optionsObj[optionName];  
 411.     }  
 412. };  
 413.   
 414.   
 415. Spry.Widget.Utils.getFirstParentWithNodeName = function(node, nodeName)  
 416. {  
 417.     while (node.parentNode  
 418.             && node.parentNode.nodeName.toLowerCase() != nodeName.toLowerCase()  
 419.             && node.parentNode.nodeName != 'BODY') {  
 420.         node = node.parentNode;  
 421.     }  
 422.   
 423.     if (node.parentNode && node.parentNode.nodeName.toLowerCase() == nodeName.toLowerCase()) {  
 424.         return node.parentNode;  
 425.     } else {  
 426.         return null;  
 427.     }  
 428. };  
 429.   
 430. Spry.Widget.Utils.destroyWidgets = function (container)  
 431. {  
 432.     if (typeof container == 'string') {  
 433.         container = document.getElementById(container);  
 434.     }  
 435.   
 436.     var q = Spry.Widget.Form.onSubmitWidgetQueue;  
 437.     for (var i = 0; i < Spry.Widget.Form.onSubmitWidgetQueue.length; i++) {  
 438.         if (typeof(q[i].destroy) == 'function' && Spry.Widget.Utils.contains(container, q[i].element)) {  
 439.             q[i].destroy();  
 440.             i--;  
 441.         }  
 442.     }  
 443. };  
 444. Spry.Widget.Utils.contains = function (who, what)  
 445. {  
 446.     if (typeof who.contains == 'object') {  
 447.         return what && who && (who == what || who.contains(what));  
 448.     } else {  
 449.         var el = what;  
 450.         while(el) {  
 451.             if (el == who) {  
 452.                 return true;  
 453.             }  
 454.             el = el.parentNode;  
 455.         }  
 456.         return false;  
 457.     }  
 458. };  
 459. Spry.Widget.Utils.addEventListener = function(element, eventType, handler, capture)  
 460. {  
 461.     try{  
 462.         if (element.addEventListener)  
 463.             element.addEventListener(eventType, handler, capture);  
 464.         else if (element.attachEvent)  
 465.             element.attachEvent("on" + eventType, handler, capture);  
 466.     }catch (e){}  
 467. };  
 468. Spry.Widget.Utils.removeEventListener = function(element, eventType, handler, capture)  
 469. {  
 470.     try{  
 471.         if (element.removeEventListener)  
 472.             element.removeEventListener(eventType, handler, capture);  
 473.         else if (element.detachEvent)  
 474.             element.detachEvent("on" + eventType, handler, capture);  
 475.     }catch (e) {}  
 476. };  