1/** 2 * Yii validation module. 3 * 4 * This JavaScript module provides the validation methods for the built-in validators. 5 * 6 * @link http://www.yiiframework.com/ 7 * @copyright Copyright (c) 2008 Yii Software LLC 8 * @license http://www.yiiframework.com/license/ 9 * @author Qiang Xue <[email protected]> 10 * @since 2.0 11 */ 12 13yii.validation = (function ($) { 14 var pub = { 15 isEmpty: function (value) { 16 return value === null || value === undefined || ($.isArray(value) && value.length === 0) || value === ''; 17 }, 18 19 addMessage: function (messages, message, value) { 20 messages.push(message.replace(/\{value\}/g, value)); 21 }, 22 23 required: function (value, messages, options) { 24 var valid = false; 25 if (options.requiredValue === undefined) { 26 var isString = typeof value == 'string' || value instanceof String; 27 if (options.strict && value !== undefined || !options.strict && !pub.isEmpty(isString ? $.trim(value) : value)) { 28 valid = true; 29 } 30 } else if (!options.strict && value == options.requiredValue || options.strict && value === options.requiredValue) { 31 valid = true; 32 } 33 34 if (!valid) { 35 pub.addMessage(messages, options.message, value); 36 } 37 }, 38 39 // "boolean" is a reserved keyword in older versions of ES so it's quoted for IE < 9 support 40 'boolean': function (value, messages, options) { 41 if (options.skipOnEmpty && pub.isEmpty(value)) { 42 return; 43 } 44 var valid = !options.strict && (value == options.trueValue || value == options.falseValue) 45 || options.strict && (value === options.trueValue || value === options.falseValue); 46 47 if (!valid) { 48 pub.addMessage(messages, options.message, value); 49 } 50 }, 51 52 string: function (value, messages, options) { 53 if (options.skipOnEmpty && pub.isEmpty(value)) { 54 return; 55 } 56 57 if (typeof value !== 'string') { 58 pub.addMessage(messages, options.message, value); 59 return; 60 } 61 62 if (options.is !== undefined && value.length != options.is) { 63 pub.addMessage(messages, options.notEqual, value); 64 return; 65 } 66 if (options.min !== undefined && value.length < options.min) { 67 pub.addMessage(messages, options.tooShort, value); 68 } 69 if (options.max !== undefined && value.length > options.max) { 70 pub.addMessage(messages, options.tooLong, value); 71 } 72 }, 73 74 file: function (attribute, messages, options) { 75 var files = getUploadedFiles(attribute, messages, options); 76 $.each(files, function (i, file) { 77 validateFile(file, messages, options); 78 }); 79 }, 80 81 image: function (attribute, messages, options, deferredList) { 82 var files = getUploadedFiles(attribute, messages, options); 83 $.each(files, function (i, file) { 84 validateFile(file, messages, options); 85 86 // Skip image validation if FileReader API is not available 87 if (typeof FileReader === "undefined") { 88 return; 89 } 90 91 var deferred = $.Deferred(); 92 pub.validateImage(file, messages, options, deferred, new FileReader(), new Image()); 93 deferredList.push(deferred); 94 }); 95 }, 96 97 validateImage: function (file, messages, options, deferred, fileReader, image) { 98 image.onload = function() { 99 validateImageSize(file, image, messages, options); 100 deferred.resolve(); 101 }; 102 103 image.onerror = function () { 104 messages.push(options.notImage.replace(/\{file\}/g, file.name)); 105 deferred.resolve(); 106 }; 107 108 fileReader.onload = function () { 109 image.src = this.result; 110 }; 111 112 // Resolve deferred if there was error while reading data 113 fileReader.onerror = function () { 114 deferred.resolve(); 115 }; 116
117 fileReader.readAsDataURL(file); 118 }, 119 120 number: function (value, messages, options) { 121 if (options.skipOnEmpty && pub.isEmpty(value)) { 122 return; 123 } 124 125 if (typeof value === 'string' && !options.pattern.test(value)) { 126 pub.addMessage(messages, options.message, value); 127 return; 128 } 129 130 if (options.min !== undefined && value < options.min) { 131 pub.addMessage(messages, options.tooSmall, value); 132 } 133 if (options.max !== undefined && value > options.max) { 134 pub.addMessage(messages, options.tooBig, value); 135 } 136 }, 137 138 range: function (value, messages, options) { 139 if (options.skipOnEmpty && pub.isEmpty(value)) { 140 return; 141 } 142 143 if (!options.allowArray && $.isArray(value)) { 144 pub.addMessage(messages, options.message, value); 145 return; 146 } 147 148 var inArray = true; 149 150 $.each($.isArray(value) ? value : [value], function (i, v) { 151 if ($.inArray(v, options.range) == -1) { 152 inArray = false; 153 return false; 154 } else { 155 return true; 156 } 157 }); 158 159 if (options.not === undefined) { 160 options.not = false; 161 } 162 163 if (options.not === inArray) { 164 pub.addMessage(messages, options.message, value); 165 } 166 }, 167 168 regularExpression: function (value, messages, options) { 169 if (options.skipOnEmpty && pub.isEmpty(value)) { 170 return; 171 } 172 173 if (!options.not && !options.pattern.test(value) || options.not && options.pattern.test(value)) { 174 pub.addMessage(messages, options.message, value); 175 } 176 }, 177 178 email: function (value, messages, options) { 179 if (options.skipOnEmpty && pub.isEmpty(value)) { 180 return; 181 } 182 183 var valid = true, 184 regexp = /^((?:"?([^"]*)"?\s)?)(?:\s+)?(?:(<?)((.+)@([^>]+))(>?))$/, 185 matches = regexp.exec(value); 186 187 if (matches === null) { 188 valid = false; 189 } else { 190 var localPart = matches[5], 191 domain = matches[6]; 192 193 if (options.enableIDN) { 194 localPart = punycode.toASCII(localPart); 195 domain = punycode.toASCII(domain); 196 197 value = matches[1] + matches[3] + localPart + '@' + domain + matches[7]; 198 } 199 200 if (localPart.length > 64) { 201 valid = false; 202 } else if ((localPart + '@' + domain).length > 254) { 203 valid = false; 204 } else { 205 valid = options.pattern.test(value) || (options.allowName && options.fullPattern.test(value)); 206 } 207 } 208 209 if (!valid) { 210 pub.addMessage(messages, options.message, value); 211 } 212 }, 213 214 url: function (value, messages, options) { 215 if (options.skipOnEmpty && pub.isEmpty(value)) { 216 return; 217 } 218 219 if (options.defaultScheme && !/:\/\//.test(value)) { 220 value = options.defaultScheme + '://' + value; 221 } 222 223 var valid = true; 224 225 if (options.enableIDN) { 226 var matches = /^([^:]+):\/\/([^\/]+)(.*)$/.exec(value); 227 if (matches === null) { 228 valid = false; 229 } else { 230 value = matches[1] + '://' + punycode.toASCII(matches[2]) + matches[3]; 231 } 232 } 233 234 if (!valid || !options.pattern.test(value)) { 235 pub.addMessage(messages, options.message, value); 236 } 237 }, 238 239 trim: function ($form, attribute, options) { 240 var $input = $form.find(attribute.input); 241 var value = $input.val(); 242 if (!options.skipOnEmpty || !pub.isEmpty(value)) { 243 value = $.trim(value); 244 $input.val(value); 245 } 246 247 return value; 248 }, 249 250 captcha: function (value, messages, options) { 251 if (options.skipOnEmpty && pub.isEmpty(value)) { 252 return; 253 } 254 255 // CAPTCHA may be updated via AJAX and the updated hash is stored in body data 256 var hash = $('body').data(options.hashKey); 257 hash = hash == null ? options.hash : hash[options.caseSensitive ? 0 : 1]; 258 var v = options.caseSensitive ? value : value.toLowerCase(); 259 for (var i = v.length - 1, h = 0; i >= 0; --i) { 260 h += v.charCodeAt(i); 261 } 262 if (h != hash) { 263 pub.addMessage(messages, options.message, value); 264 } 265 }, 266 267 compare: function (value, messages, options) { 268 if (options.skipOnEmpty && pub.isEmpty(value)) { 269 return; 270 } 271 272 var compareValue, 273 valid = true; 274 if (options.compareAttribute === undefined) { 275 compareValue = options.compareValue; 276 } else { 277 compareValue = $('#' + options.compareAttribute).val(); 278 } 279 280 if (options.type === 'number') { 281 value = parseFloat(value); 282 compareValue = parseFloat(compareValue); 283 } 284 switch (options.operator) { 285 case '==': 286 valid = value == compareValue; 287 break; 288 case '===': 289 valid = value === compareValue; 290 break; 291 case '!=': 292 valid = value != compareValue; 293 break; 294 case '!==': 295 valid = value !== compareValue; 296 break; 297 case '>': 298 valid = value > compareValue; 299 break; 300 case '>=': 301 valid = value >= compareValue; 302 break; 303 case '<': 304 valid = value < compareValue; 305 break; 306 case '<=': 307 valid = value <= compareValue; 308 break; 309 default: 310 valid = false;
311 break; 312 } 313 314 if (!valid) { 315 pub.addMessage(messages, options.message, value); 316 } 317 }, 318 319 ip: function (value, messages, options) { 320 if (options.skipOnEmpty && pub.isEmpty(value)) { 321 return; 322 } 323 324 var negation = null, 325 cidr = null, 326 matches = new RegExp(options.ipParsePattern).exec(value); 327 if (matches) { 328 negation = matches[1] || null; 329 value = matches[2]; 330 cidr = matches[4] || null; 331 } 332 333 if (options.subnet === true && cidr === null) { 334 pub.addMessage(messages, options.messages.noSubnet, value); 335 return; 336 } 337 if (options.subnet === false && cidr !== null) { 338 pub.addMessage(messages, options.messages.hasSubnet, value); 339 return; 340 } 341 if (options.negation === false && negation !== null) { 342 pub.addMessage(messages, options.messages.message, value); 343 return; 344 } 345 346 var ipVersion = value.indexOf(':') === -1 ? 4 : 6; 347 if (ipVersion == 6) { 348 if (!(new RegExp(options.ipv6Pattern)).test(value)) { 349 pub.addMessage(messages, options.messages.message, value); 350 } 351 if (!options.ipv6) { 352 pub.addMessage(messages, options.messages.ipv6NotAllowed, value); 353 } 354 } else { 355 if (!(new RegExp(options.ipv4Pattern)).test(value)) { 356 pub.addMessage(messages, options.messages.message, value); 357 } 358 if (!options.ipv4) { 359 pub.addMessage(messages, options.messages.ipv4NotAllowed, value); 360 } 361 } 362 } 363 }; 364 365 function getUploadedFiles(attribute, messages, options) { 366 // Skip validation if File API is not available 367 if (typeof File === "undefined") { 368 return []; 369 } 370 371 var files = $(attribute.input, attribute.$form).get(0).files; 372 if (!files) { 373 messages.push(options.message); 374 return []; 375 } 376 377 if (files.length === 0) { 378 if (!options.skipOnEmpty) { 379 messages.push(options.uploadRequired); 380 } 381 382 return []; 383 } 384 385 if (options.maxFiles && options.maxFiles < files.length) { 386 messages.push(options.tooMany); 387 return []; 388 } 389 390 return files; 391 } 392 393 function validateFile(file, messages, options) { 394 if (options.extensions && options.extensions.length > 0) { 395 var index = file.name.lastIndexOf('.'); 396 var ext = !~index ? '' : file.name.substr(index + 1, file.name.length).toLowerCase(); 397 398 if (!~options.extensions.indexOf(ext)) { 399 messages.push(options.wrongExtension.replace(/\{file\}/g, file.name)); 400 } 401 } 402 403 if (options.mimeTypes && options.mimeTypes.length > 0) { 404 if (!validateMimeType(options.mimeTypes, file.type)) { 405 messages.push(options.wrongMimeType.replace(/\{file\}/g, file.name)); 406 } 407 } 408 409 if (options.maxSize && options.maxSize < file.size) { 410 messages.push(options.tooBig.replace(/\{file\}/g, file.name)); 411 } 412 413 if (options.minSize && options.minSize > file.size) { 414 messages.push(options.tooSmall.replace(/\{file\}/g, file.name)); 415 } 416 } 417 418 function validateMimeType(mimeTypes, fileType) { 419 for (var i = 0, len = mimeTypes.length; i < len; i++) { 420 if (new RegExp(mimeTypes[i]).test(fileType)) { 421 return true; 422 } 423 } 424 425 return false; 426 } 427 428 function validateImageSize(file, image, messages, options) { 429 if (options.minWidth && image.width < options.minWidth) { 430 messages.push(options.underWidth.replace(/\{file\}/g, file.name)); 431 } 432 433 if (options.maxWidth && image.width > options.maxWidth) { 434 messages.push(options.overWidth.replace(/\{file\}/g, file.name)); 435 } 436 437 if (options.minHeight && image.height < options.minHeight) { 438 messages.push(options.underHeight.replace(/\{file\}/g, file.name)); 439 } 440 441 if (options.maxHeight && image.height > options.maxHeight) { 442 messages.push(options.overHeight.replace(/\{file\}/g, file.name)); 443 } 444 } 445 446 return pub; 447})(jQuery);
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.