1/** 2 * jquery.mask.js 3 * @version: v1.10.13 4 * @author: Igor Escobar 5 * 6 * Created by Igor Escobar on 2012-03-10. Please report any bug at http://blog.igorescobar.com 7 * 8 * Copyright (c) 2012 Igor Escobar http://blog.igorescobar.com 9 * 10 * The MIT License (http://www.opensource.org/licenses/mit-license.php) 11 * 12 * Permission is hereby granted, free of charge, to any person 13 * obtaining a copy of this software and associated documentation 14 * files (the "Software"), to deal in the Software without 15 * restriction, including without limitation the rights to use, 16 * copy, modify, merge, publish, distribute, sublicense, and/or sell 17 * copies of the Software, and to permit persons to whom the 18 * Software is furnished to do so, subject to the following 19 * conditions: 20 * 21 * The above copyright notice and this permission notice shall be 22 * included in all copies or substantial portions of the Software. 23 * 24 * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, 25 * EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES 26 * OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND 27 * NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT 28 * HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, 29 * WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING 30 * FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR 31 * OTHER DEALINGS IN THE SOFTWARE. 32 */ 33/*jshint laxbreak: true */ 34/* global define */ 35 36// UMD (Universal Module Definition) patterns for JavaScript modules that work everywhere. 37// https://github.com/umdjs/umd/blob/master/jqueryPlugin.js 38(function (factory) { 39 if (typeof define === "function" && define.amd) { 40 // AMD. Register as an anonymous module. 41 define(["jquery"], factory); 42 } else { 43 // Browser globals 44 factory(window.jQuery || window.Zepto); 45 } 46}(function ($) { 47 "use strict"; 48 var Mask = function (el, mask, options) { 49 el = $(el); 50 51 var jMask = this, old_value = el.val(), regexMask; 52 53 mask = typeof mask === "function" ? mask(el.val(), undefined, el, options) : mask; 54 55 var p = { 56 invalid: [], 57 getCaret: function () { 58 try { 59 var sel, 60 pos = 0, 61 ctrl = el.get(0), 62 dSel = document.selection, 63 cSelStart = ctrl.selectionStart; 64 65 // IE Support 66 if (dSel && navigator.appVersion.indexOf("MSIE 10") === -1) { 67 sel = dSel.createRange(); 68 sel.moveStart('character', el.is("input") ? -el.val().length : -el.text().length); 69 pos = sel.text.length; 70 } 71 // Firefox support 72 else if (cSelStart || cSelStart === '0') { 73 pos = cSelStart; 74 } 75 76 return pos; 77 } catch (e) {} 78 }, 79 setCaret: function(pos) { 80 try { 81 if (el.is(":focus")) { 82 var range, ctrl = el.get(0); 83 84 if (ctrl.setSelectionRange) { 85 ctrl.setSelectionRange(pos,pos); 86 } else if (ctrl.createTextRange) { 87 range = ctrl.createTextRange(); 88 range.collapse(true); 89 range.moveEnd('character', pos); 90 range.moveStart('character', pos); 91 range.select(); 92 } 93 } 94 } catch (e) {} 95 }, 96 events: function() { 97 el 98 .on('keyup.mask', p.behaviour) 99 .on("paste.mask drop.mask", function() { 100 setTimeout(function() { 101 el.keydown().keyup(); 102 }, 100); 103 }) 104 .on('change.mask', function(){ 105 el.data('changed', true); 106 }) 107 .on("blur.mask", function(){ 108 if (old_value !== el.val() && !el.data('changed')) { 109 el.trigger("change"); 110 } 111 el.data('changed', false); 112 }) 113 // it's very important that this callback remains in this position 114 // otherwhise old_value it's going to work buggy 115 .on('keydown.mask, blur.mask', function() { 116 old_value = el.val(); 117 }) 118 // clear the value if it not complete the mask 119 .on("focusout.mask", function() { 120 if (options.clearIfNotMatch && !regexMask.test(p.val())) { 121 p.val(''); 122 } 123 }); 124 }, 125 getRegexMask: function() { 126 var maskChunks = [], translation, pattern, optional, recursive, oRecursive, r; 127 128 for (var i = 0; i < mask.length; i++) { 129 translation = jMask.translation[mask[i]]; 130 131 if (translation) { 132 133 pattern = translation.pattern.toString().replace(/.{1}$|^.{1}/g, ""); 134 optional = translation.optional; 135 recursive = translation.recursive; 136 137 if (recursive) { 138 maskChunks.push(mask[i]); 139 oRecursive = {digit: mask[i], pattern: pattern}; 140 } else { 141 maskChunks.push(!optional && !recursive ? pattern : (pattern + "?")); 142 } 143 144 } else { 145 maskChunks.push(mask[i].replace(/[-\/\\^$*+?.()|[\]{}]/g, '\\$&')); 146 } 147 } 148 149 r = maskChunks.join(""); 150 151 if (oRecursive) { 152 r = r.replace(new RegExp("(" + oRecursive.digit + "(.*" + oRecursive.digit + ")?)"), "($1)?") 153 .replace(new RegExp(oRecursive.digit, "g"), oRecursive.pattern); 154 } 155 156 return new RegExp(r); 157 }, 158 destroyEvents: function() {
159 el.off(['keydown', 'keyup', 'paste', 'drop', 'blur', 'focusout', ''].join('.mask ')); 160 }, 161 val: function(v) { 162 var isInput = el.is('input'), 163 method = isInput ? 'val' : 'text', 164 r; 165 166 if (arguments.length > 0) { 167 if (el[method]() !== v) { 168 el[method](v); 169 } 170 r = el; 171 } else { 172 r = el[method](); 173 } 174 175 return r; 176 }, 177 getMCharsBeforeCount: function(index, onCleanVal) { 178 for (var count = 0, i = 0, maskL = mask.length; i < maskL && i < index; i++) { 179 if (!jMask.translation[mask.charAt(i)]) { 180 index = onCleanVal ? index + 1 : index; 181 count++; 182 } 183 } 184 return count; 185 }, 186 caretPos: function (originalCaretPos, oldLength, newLength, maskDif) { 187 var translation = jMask.translation[mask.charAt(Math.min(originalCaretPos - 1, mask.length - 1))]; 188 189 return !translation ? p.caretPos(originalCaretPos + 1, oldLength, newLength, maskDif) 190 : Math.min(originalCaretPos + newLength - oldLength - maskDif, newLength); 191 }, 192 behaviour: function(e) { 193 e = e || window.event; 194 p.invalid = []; 195 var keyCode = e.keyCode || e.which; 196 if ($.inArray(keyCode, jMask.byPassKeys) === -1) { 197 198 var caretPos = p.getCaret(), 199 currVal = p.val(), 200 currValL = currVal.length, 201 changeCaret = caretPos < currValL, 202 newVal = p.getMasked(), 203 newValL = newVal.length, 204 maskDif = p.getMCharsBeforeCount(newValL - 1) - p.getMCharsBeforeCount(currValL - 1); 205 206 p.val(newVal); 207 208 // change caret but avoid CTRL+A 209 if (changeCaret && !(keyCode === 65 && e.ctrlKey)) { 210 // Avoid adjusting caret on backspace or delete 211 if (!(keyCode === 8 || keyCode === 46)) { 212 caretPos = p.caretPos(caretPos, currValL, newValL, maskDif); 213 } 214 p.setCaret(caretPos); 215 } 216 217 return p.callbacks(e); 218 } 219 }, 220 getMasked: function (skipMaskChars) { 221 var buf = [], 222 value = p.val(), 223 m = 0, maskLen = mask.length, 224 v = 0, valLen = value.length, 225 offset = 1, addMethod = "push", 226 resetPos = -1, 227 lastMaskChar, 228 check; 229 230 if (options.reverse) { 231 addMethod = "unshift"; 232 offset = -1; 233 lastMaskChar = 0; 234 m = maskLen - 1; 235 v = valLen - 1; 236 check = function () { 237 return m > -1 && v > -1; 238 }; 239 } else { 240 lastMaskChar = maskLen - 1; 241 check = function () { 242 return m < maskLen && v < valLen; 243 }; 244 } 245 246 while (check()) { 247 var maskDigit = mask.charAt(m), 248 valDigit = value.charAt(v), 249 translation = jMask.translation[maskDigit]; 250 251 if (translation) { 252 if (valDigit.match(translation.pattern)) { 253 buf[addMethod](valDigit); 254 if (translation.recursive) { 255 if (resetPos === -1) { 256 resetPos = m; 257 } else if (m === lastMaskChar) { 258 m = resetPos - offset; 259 } 260 261 if (lastMaskChar === resetPos) { 262 m -= offset; 263 } 264 } 265 m += offset; 266 } else if (translation.optional) { 267 m += offset; 268 v -= offset; 269 } else if (translation.fallback) { 270 buf[addMethod](translation.fallback); 271 m += offset; 272 v -= offset; 273 } else { 274 p.invalid.push({p: v, v: valDigit, e: translation.pattern}); 275 } 276 v += offset; 277 } else { 278 if (!skipMaskChars) { 279 buf[addMethod](maskDigit); 280 } 281 282 if (valDigit === maskDigit) { 283 v += offset; 284 } 285 286 m += offset; 287 } 288 } 289 290 var lastMaskCharDigit = mask.charAt(lastMaskChar); 291 if (maskLen === valLen + 1 && !jMask.translation[lastMaskCharDigit]) { 292 buf.push(lastMaskCharDigit); 293 } 294 295 return buf.join(""); 296 }, 297 callbacks: function (e) { 298 var val = p.val(), 299 changed = val !== old_value, 300 defaultArgs = [val, e, el, options], 301 callback = function(name, criteria, args) { 302 if (typeof options[name] === "function" && criteria) { 303 options[name].apply(this, args); 304 } 305 }; 306 307 callback('onChange', changed === true, defaultArgs); 308 callback('onKeyPress', changed === true, defaultArgs); 309 callback('onComplete', val.length === mask.length, defaultArgs); 310 callback('onInvalid', p.invalid.length > 0, [val, e, el, p.invalid, options]); 311 } 312 }; 313 314 315 // public methods 316 jMask.mask = mask; 317 jMask.options = options; 318 jMask.remove = function() { 319 var caret = p.getCaret(); 320 p.destroyEvents(); 321 p.val(jMask.getCleanVal()); 322 p.setCaret(caret - p.getMCharsBeforeCount(caret)); 323 return el; 324 }; 325 326 // get value without mask 327 jMask.getCleanVal = function() { 328 return p.getMasked(true); 329 }; 330 331 jMask.init = function(only_mask) { 332 only_mask = only_mask || false; 333 options = options || {}; 334 335 jMask.byPassKeys = $.jMaskGlobals.byPassKeys; 336 jMask.translation = $.jMaskGlobals.translation; 337 338 jMask.translation = $.extend({}, jMask.translation, options.translation); 339 jMask = $.extend(true, {}
339, jMask, options); 340 341 regexMask = p.getRegexMask(); 342 343 if (only_mask === false) { 344 345 if (options.placeholder) { 346 el.attr('placeholder' , options.placeholder); 347 } 348 349 // autocomplete needs to be off. we can't intercept events 350 // the browser doesn't fire any kind of event when something is 351 // selected in a autocomplete list so we can't sanitize it. 352 el.attr('autocomplete', 'off'); 353 p.destroyEvents(); 354 p.events(); 355 356 var caret = p.getCaret(); 357 p.val(p.getMasked()); 358 p.setCaret(caret + p.getMCharsBeforeCount(caret, true)); 359 360 } else { 361 p.events(); 362 p.val(p.getMasked()); 363 } 364 }; 365 366 jMask.init(!el.is("input")); 367 368 }; 369 370 $.maskWatchers = {}; 371 var HTMLAttributes = function () { 372 var input = $(this), 373 options = {}, 374 prefix = "data-mask-", 375 mask = input.attr('data-mask'); 376 377 if (input.attr(prefix + 'reverse')) { 378 options.reverse = true; 379 } 380 381 if (input.attr(prefix + 'clearifnotmatch')) { 382 options.clearIfNotMatch = true; 383 } 384 385 if (notSameMaskObject(input, mask, options)) { 386 return input.data('mask', new Mask(this, mask, options)); 387 } 388 }, 389 notSameMaskObject = function(field, mask, options) { 390 options = options || {}; 391 var maskObject = $(field).data('mask'), 392 stringify = JSON.stringify, 393 value = $(field).val() || $(field).text(); 394 try { 395 if (typeof mask === "function") { 396 mask = mask(value); 397 } 398 return typeof maskObject !== "object" || stringify(maskObject.options) !== stringify(options) || maskObject.mask !== mask; 399 } catch (e) {} 400 }; 401 402 403 $.fn.mask = function(mask, options) { 404 options = options || {}; 405 var selector = this.selector, 406 globals = $.jMaskGlobals, 407 interval = $.jMaskGlobals.watchInterval, 408 maskFunction = function() { 409 if (notSameMaskObject(this, mask, options)) { 410 return $(this).data('mask', new Mask(this, mask, options)); 411 } 412 }; 413 414 $(this).each(maskFunction); 415 416 if (selector && selector !== "" && globals.watchInputs) { 417 clearInterval($.maskWatchers[selector]); 418 $.maskWatchers[selector] = setInterval(function(){ 419 $(document).find(selector).each(maskFunction); 420 }, interval); 421 } 422 }; 423 424 $.fn.unmask = function() { 425 clearInterval($.maskWatchers[this.selector]); 426 delete $.maskWatchers[this.selector]; 427 return this.each(function() { 428 var dataMask = $(this).data('mask'); 429 if (dataMask) { 430 dataMask.remove().removeData('mask'); 431 } 432 }); 433 }; 434 435 $.fn.cleanVal = function() { 436 return this.data('mask').getCleanVal(); 437 }; 438 439 var globals = { 440 maskElements: 'input,td,span,div', 441 dataMaskAttr: '*[data-mask]', 442 dataMask: true, 443 watchInterval: 300, 444 watchInputs: true, 445 watchDataMask: false, 446 byPassKeys: [9, 16, 17, 18, 36, 37, 38, 39, 40, 91], 447 translation: { 448 '0': {pattern: /\d/}, 449 '9': {pattern: /\d/, optional: true}, 450 '#': {pattern: /\d/, recursive: true}, 451 'A': {pattern: /[a-zA-Z0-9]/}, 452 'S': {pattern: /[a-zA-Z]/} 453 } 454 }; 455 456 $.jMaskGlobals = $.jMaskGlobals || {}; 457 globals = $.jMaskGlobals = $.extend(true, {}, globals, $.jMaskGlobals); 458 459 // looking for inputs with data-mask attribute 460 if (globals.dataMask) { 461 $(globals.dataMaskAttr).each(HTMLAttributes); 462 } 463 464 setInterval(function(){ 465 if ($.jMaskGlobals.watchDataMask) { 466 $(document).find($.jMaskGlobals.maskElements).filter(globals.dataMaskAttr).each(HTMLAttributes); 467 } 468 }, globals.watchInterval); 469}));
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.