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 return value; 247 }, 248 249 captcha: function (value, messages, options) { 250 if (options.skipOnEmpty && pub.isEmpty(value)) { 251 return; 252 } 253 254 // CAPTCHA may be updated via AJAX and the updated hash is stored in body data 255 var hash = $('body').data(options.hashKey); 256 hash = hash == null ? options.hash : hash[options.caseSensitive ? 0 : 1]; 257 var v = options.caseSensitive ? value : value.toLowerCase(); 258 for (var i = v.length - 1, h = 0; i >= 0; --i) { 259 h += v.charCodeAt(i); 260 } 261 if (h != hash) { 262 pub.addMessage(messages, options.message, value); 263 } 264 }, 265 266 compare: function (value, messages, options) { 267 if (options.skipOnEmpty && pub.isEmpty(value)) { 268 return; 269 } 270 271 var compareValue, 272 valid = true; 273 if (options.compareAttribute === undefined) { 274 compareValue = options.compareValue; 275 } else { 276 compareValue = $('#' + options.compareAttribute).val(); 277 } 278 279 if (options.type === 'number') { 280 value = parseFloat(value); 281 compareValue = parseFloat(compareValue); 282 } 283 switch (options.operator) { 284 case '==': 285 valid = value == compareValue; 286 break; 287 case '===': 288 valid = value === compareValue; 289 break; 290 case '!=': 291 valid = value != compareValue; 292 break; 293 case '!==': 294 valid = value !== compareValue; 295 break; 296 case '>': 297 valid = value > compareValue; 298 break; 299 case '>=': 300 valid = value >= compareValue; 301 break; 302 case '<': 303 valid = value < compareValue; 304 break; 305 case '<=': 306 valid = value <= compareValue; 307 break; 308 default: 309 valid = false;
310 break; 311 } 312 313 if (!valid) { 314 pub.addMessage(messages, options.message, value); 315 } 316 }, 317 318 ip: function (value, messages, options) { 319 if (options.skipOnEmpty && pub.isEmpty(value)) { 320 return; 321 } 322 323 var negation = null, 324 cidr = null, 325 matches = new RegExp(options.ipParsePattern).exec(value); 326 if (matches) { 327 negation = matches[1] || null; 328 value = matches[2]; 329 cidr = matches[4] || null; 330 } 331 332 if (options.subnet === true && cidr === null) { 333 pub.addMessage(messages, options.messages.noSubnet, value); 334 return; 335 } 336 if (options.subnet === false && cidr !== null) { 337 pub.addMessage(messages, options.messages.hasSubnet, value); 338 return; 339 } 340 if (options.negation === false && negation !== null) { 341 pub.addMessage(messages, options.messages.message, value); 342 return; 343 } 344 345 var ipVersion = value.indexOf(':') === -1 ? 4 : 6; 346 if (ipVersion == 6) { 347 if (!(new RegExp(options.ipv6Pattern)).test(value)) { 348 pub.addMessage(messages, options.messages.message, value); 349 } 350 if (!options.ipv6) { 351 pub.addMessage(messages, options.messages.ipv6NotAllowed, value); 352 } 353 } else { 354 if (!(new RegExp(options.ipv4Pattern)).test(value)) { 355 pub.addMessage(messages, options.messages.message, value); 356 } 357 if (!options.ipv4) { 358 pub.addMessage(messages, options.messages.ipv4NotAllowed, value); 359 } 360 } 361 } 362 }; 363 364 function getUploadedFiles(attribute, messages, options) { 365 // Skip validation if File API is not available 366 if (typeof File === "undefined") { 367 return []; 368 } 369 370 var files = $(attribute.input, attribute.$form).get(0).files; 371 if (!files) { 372 messages.push(options.message); 373 return []; 374 } 375 376 if (files.length === 0) { 377 if (!options.skipOnEmpty) { 378 messages.push(options.uploadRequired); 379 } 380 return []; 381 } 382 383 if (options.maxFiles && options.maxFiles < files.length) { 384 messages.push(options.tooMany); 385 return []; 386 } 387 388 return files; 389 } 390 391 function validateFile(file, messages, options) { 392 if (options.extensions && options.extensions.length > 0) { 393 var index = file.name.lastIndexOf('.'); 394 var ext = !~index ? '' : file.name.substr(index + 1, file.name.length).toLowerCase(); 395 396 if (!~options.extensions.indexOf(ext)) { 397 messages.push(options.wrongExtension.replace(/\{file\}/g, file.name)); 398 } 399 } 400 401 if (options.mimeTypes && options.mimeTypes.length > 0) { 402 if (!validateMimeType(options.mimeTypes, file.type)) { 403 messages.push(options.wrongMimeType.replace(/\{file\}/g, file.name)); 404 } 405 } 406 407 if (options.maxSize && options.maxSize < file.size) { 408 messages.push(options.tooBig.replace(/\{file\}/g, file.name)); 409 } 410 411 if (options.minSize && options.minSize > file.size) { 412 messages.push(options.tooSmall.replace(/\{file\}/g, file.name)); 413 } 414 } 415 416 function validateMimeType(mimeTypes, fileType) { 417 for (var i = 0, len = mimeTypes.length; i < len; i++) { 418 if (new RegExp(mimeTypes[i]).test(fileType)) { 419 return true; 420 } 421 } 422 423 return false; 424 } 425 426 function validateImageSize(file, image, messages, options) { 427 if (options.minWidth && image.width < options.minWidth) { 428 messages.push(options.underWidth.replace(/\{file\}/g, file.name)); 429 } 430 431 if (options.maxWidth && image.width > options.maxWidth) { 432 messages.push(options.overWidth.replace(/\{file\}/g, file.name)); 433 } 434 435 if (options.minHeight && image.height < options.minHeight) { 436 messages.push(options.underHeight.replace(/\{file\}/g, file.name)); 437 } 438 439 if (options.maxHeight && image.height > options.maxHeight) { 440 messages.push(options.overHeight.replace(/\{file\}/g, file.name)); 441 } 442 } 443 444 return pub; 445})(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.