1 /** 2 * @author Gillis Haasnoot <gillis.haasnoot@gmail.com> 3 * @package Banana.Controls 4 * @summary Base validator class 5 */ 6 7 goog.provide('Banana.Controls.Decorators.Validator'); 8 9 /** @namespace Banana.Controls.Decorators.Validator */ 10 namespace('Banana.Controls.Decorators').Validator = Banana.Controls.Decorators.Decorator.extend( 11 /** @lends Banana.Controls.Decorators.Validator.prototype */ 12 { 13 /** 14 * Creates base control to validate a control 15 * Any Banana.Controls.DataControl can be validated. If you need to change the eventtype where 16 * the validator is triggered on, use setValidateOnEventType. By default the validator 17 * will be triggered when the validated control fires a dataChanged or focusout event 18 * 19 * @param {Banana.Controls.DataControl} controlToValidate 20 * @constructs 21 * @extends Banana.Controls.Decorators.Decorator 22 */ 23 init : function(controlToValidate) 24 { 25 this._super(controlToValidate); 26 27 this.showIndicator = true; //little dot in front visible 28 29 this.validationGroup = 'default'; 30 31 var iconPlaceHolder = new Banana.Controls.Panel().addCssClass('BValidatorIconPlaceHolder').setId('validator icon placeholder');; 32 this.addControl(iconPlaceHolder) 33 34 controlToValidate.addCssClass('BValidatorDecorated'); 35 this.controlToValidate = controlToValidate; 36 this.addControl(controlToValidate); 37 38 this.infoPlaceHolder = new Banana.Controls.Panel().addCssClass('BValidatorInfoPlaceHolder'); 39 this.addControl(this.infoPlaceHolder) 40 41 this.star = new Banana.Controls.Panel().setId('validator star');; 42 this.star.addCssClass('BValidatorStar'); 43 if (this.getInfoText()) 44 { 45 this.star.setAttribute('title', this.getInfoText()); 46 } 47 iconPlaceHolder.addControl(this.star); 48 49 this.arrow = new Banana.Controls.Panel().setId('validator arrow'); 50 this.arrow.addCssClass('BValidatorArrow'); 51 this.infoPlaceHolder.addControl(this.arrow); 52 53 this.info = new Banana.Controls.Panel().addCssClass('BValidatorInfo').setId('validator info placeholder');; 54 this.infoPlaceHolder.addControl(this.info); 55 56 Banana.Util.ValidationManager.addValidator(this); 57 58 return this; 59 }, 60 61 /** 62 * @override 63 */ 64 createComponents : function() 65 { 66 this.info.setVisible(false); 67 this.arrow.setVisible(false); 68 69 this.createLabelText(); 70 71 this.star.setVisible(this.showIndicator); 72 73 //if user explicity gave type of event to validate on 74 if (this.validateOnEventType) 75 { 76 this.controls[1].bind(this.validateOnEventType,this.getProxy(this.isValid)); 77 } 78 //otherwise just use default 79 else 80 { 81 this.controls[1].bind('dataChanged',this.getProxy(this.isValid)); 82 //TODO this cannot count for all type of controls 83 this.controls[1].bind('focusout',this.getProxy(function(){})) 84 } 85 }, 86 87 /** 88 * When control is removed, we also remove it from the validation manager. 89 * TODO: is this really needed here? 90 * @override 91 */ 92 unload : function() 93 { 94 this._super(); 95 Banana.Util.ValidationManager.removeValidator(this); 96 }, 97 98 /** 99 * @ignore 100 */ 101 createLabelText : function() 102 { 103 if (!this.labelText) 104 { 105 this.labelText = new Banana.Controls.Label(); 106 this.labelText.addCssClass('BValidatorLabel'); 107 this.info.addControl(this.labelText); 108 } 109 110 this.labelText.setData(this.getInfoText()); 111 }, 112 113 /** 114 * shows indicator 115 */ 116 showIndicators : function() 117 { 118 this.info.setVisible(true); 119 this.arrow.setVisible(true); 120 }, 121 122 /** 123 * hides indicator 124 */ 125 hideIndicators : function() 126 { 127 this.info.setVisible(false); 128 this.arrow.setVisible(false); 129 }, 130 131 /** 132 * @param {boolean} value if true when show a little dot in front of the control 133 */ 134 setShowIndicator: function(value) 135 { 136 this.showIndicator = value; 137 return this; 138 }, 139 140 /** 141 * default = dataChanged 142 * all dom events are supported, depending on the control type 143 * @param {String} event type to validate on 144 * @return {this} 145 */ 146 setValidateOnEventType : function(event) 147 { 148 this.validateOnEventType = event; 149 return this; 150 }, 151 152 /** 153 * @return {Banana.Controls.DataControl} 154 */ 155 getValidatedControl : function() 156 { 157 return this.controlToValidate; 158 }, 159 160 /** 161 * @override 162 * we need to know the original border color 163 */ 164 updateDisplay : function() 165 { 166 this.orgBorder = this.controls[1].getStyleProperty('border'); 167 }, 168 169 /** 170 * Manual way to invalidate the control 171 * @return {this} 172 */ 173 markInvalid : function(customText) 174 { 175 this.markedInvalid = true; 176 177 if (customText) 178 { 179 this.oldInfoText = this.infoText; 180 this.infoText = customText; 181 } 182 183 this.isValid(); 184 return this; 185 }, 186 187 /** 188 * Removes manual mark as invalid flag 189 */ 190 removeMarkInvalid : function() 191 { 192 this.markedInvalid = undefined; 193 194 if (this.oldInfoText) 195 { 196 this.infoText = this.oldInfoText; 197 } 198 199 this.isValid() 200 }, 201 202 /** 203 * @return bool true when validator is considered as valid 204 */ 205 isValid : function() 206 { 207 if (!this.controls) 208 { 209 //prevent situation that this method is called while child controls are being removed 210 return false; 211 } 212 var c = this.controls[1]; 213 214 //disabled controls no need to validate 215 if (!c.enabled) 216 { 217 return true; 218 } 219 220 var result; 221 222 //when user manually marked this validator invalid we wont look 223 //if this control is really invalid. We follow users wish 224 if (this.markedInvalid) 225 { 226 result = false; 227 } 228 else 229 { 230 result = this.validateData(c.getData(true)); 231 } 232 233 if (result==false) 234 { 235 this.createLabelText(); 236 c.addCssClass('BValidatorControlInvalidated'); 237 c.removeCssClass('BValidatorControlValidated'); 238 this.showIndicators(); 239 return false; 240 } 241 else if (result==true) 242 { 243 c.removeCssClass('BValidatorControlInvalidated'); 244 c.addCssClass('BValidatorControlValidated'); 245 this.hideIndicators(); 246 return true; 247 } 248 }, 249 250 /** 251 * abstract override this method to implement your own validate data 252 * @param mixed 253 */ 254 validateData : function(data) 255 { 256 return true; 257 }, 258 259 /** 260 * @return {String} 261 */ 262 getInfoText : function() 263 { 264 return this.infoText || ''; 265 }, 266 267 /** 268 * @param {String} text shown when control is invalid 269 * @return {this} 270 */ 271 setInfoText : function(text) 272 { 273 this.infoText = text; 274 return this; 275 }, 276 277 /** 278 * Use this method to put validators in a group 279 * @param {String} group 280 * @return {this} 281 */ 282 setValidationGroup : function(group) 283 { 284 this.validationGroup = group; 285 return this; 286 }, 287 288 /** 289 * @return {String} 290 */ 291 getValidationGroup : function() 292 { 293 return this.validationGroup; 294 }, 295 296 /** 297 * @return {mixed} 298 */ 299 getData : function() 300 { 301 return this.controls[1].getData(); 302 }, 303 304 /** 305 * @override 306 * @param {mixed} data 307 * @param {boolean} ignoreEvent 308 * @param {boolean} ignoreDom 309 * @return {this} 310 */ 311 setData : function(data,ignoreEvent,ignoreDom) 312 { 313 this.controls[1].setData(data,ignoreEvent,ignoreDom); 314 return this; 315 }, 316 317 /** 318 * @override 319 */ 320 getHtml : function() 321 { 322 var html = []; 323 324 var childs = this.getControls(); 325 326 for (var i =0, len = childs.length; i < len; i++) 327 { 328 if (childs[i] instanceof Banana.Control) 329 { 330 html.push(childs[i].getHtml()); 331 } 332 333 else if (typeof(childs[i]) == 'string') 334 { 335 html.push(childs[i]); 336 } 337 } 338 339 return html.join(''); 340 } 341 });