1/* 2 jQuery Masked Input Plugin 3 Copyright (c) 2007 - 2015 Josh Bush (digitalbush.com) 4 Licensed under the MIT license (http://digitalbush.com/projects/masked-input-plugin/#license) 5 Version: 1.4.1 6 7 *** THIS INCLUDES A FIX FROM LINK BELOW. THE FIX ALLOWS PROPER ENTRY OF DATA ON SAMSUNG ANDROIDS (bug in Samsung keyboard?) 8 * parthurs 7/16/2017 9 * https://raw.githubusercontent.com/RubtsovAV/jquery.maskedinput/master/src/jquery.maskedinput.js 10 11 * this includes fix for jQuery 3.5 compliance 12*/ 13(function (factory) { 14 if (typeof define === 'function' && define.amd) { 15 // AMD. Register as an anonymous module. 16 define(['jquery'], factory); 17 } else if (typeof exports === 'object') { 18 // Node/CommonJS 19 factory(require('jquery')); 20 } else { 21 // Browser globals 22 factory(jQuery); 23 } 24}(function ($) { 25 26 var ua = navigator.userAgent, 27 iPhone = /iphone/i.test(ua), 28 chrome = /chrome/i.test(ua), 29 android = /android/i.test(ua), 30 caretTimeoutId; 31 32 $.mask = { 33 //Predefined character definitions 34 definitions: { 35 '9': "[0-9]", 36 'a': "[A-Za-z]", 37 '*': "[A-Za-z0-9]" 38 }, 39 autoclear: true, 40 dataName: "rawMaskFn", 41 placeholder: '_' 42 }; 43 44 $.fn.extend({ 45 //Helper Function for Caret positioning 46 caret: function(begin, end) { 47 var range; 48 49 if (this.length === 0 || this.is(":hidden") || this.get(0) !== document.activeElement) { 50 return; 51 } 52 53 if (typeof begin == 'number') { 54 end = (typeof end === 'number') ? end : begin; 55 return this.each(function() { 56 if (this.setSelectionRange) { 57 this.setSelectionRange(begin, end); 58 } else if (this.createTextRange) { 59 range = this.createTextRange(); 60 range.collapse(true); 61 range.moveEnd('character', end); 62 range.moveStart('character', begin); 63 range.select(); 64 } 65 }); 66 } else { 67 if (this[0].setSelectionRange) { 68 begin = this[0].selectionStart; 69 end = this[0].selectionEnd; 70 } else if (document.selection && document.selection.createRange) { 71 range = document.selection.createRange(); 72 begin = 0 - range.duplicate().moveStart('character', -100000); 73 end = begin + range.text.length; 74 } 75 return { begin: begin, end: end }; 76 } 77 }, 78 unmask: function() { 79 return this.trigger("unmask"); 80 }, 81 mask: function(mask, settings) { 82 var input, 83 defs, 84 tests, 85 partialPosition, 86 firstNonMaskPos, 87 lastRequiredNonMaskPos, 88 len, 89 oldVal; 90 91 if (!mask && this.length > 0) { 92 input = $(this[0]); 93 var fn = input.data($.mask.dataName) 94 return fn?fn():undefined; 95 } 96 97 settings = $.extend({ 98 autoclear: $.mask.autoclear, 99 placeholder: $.mask.placeholder, // Load default placeholder 100 completed: null 101 }, settings); 102 103 104 defs = $.mask.definitions; 105 tests = []; 106 partialPosition = len = mask.length; 107 firstNonMaskPos = null; 108 109 mask = String(mask); 110 111 $.each(mask.split(""), function(i, c) { 112 if (c == '?') { 113 len--; 114 partialPosition = i; 115 } else if (defs[c]) { 116 tests.push(new RegExp(defs[c])); 117 if (firstNonMaskPos === null) { 118 firstNonMaskPos = tests.length - 1; 119 } 120 if(i < partialPosition){ 121 lastRequiredNonMaskPos = tests.length - 1; 122 } 123 } else { 124 tests.push(null); 125 } 126 }); 127 128 return this.trigger("unmask").each(function() { 129 var input = $(this), 130 buffer = $.map( 131 mask.split(""), 132 function(c, i) { 133 if (c != '?') { 134 return defs[c] ? getPlaceholder(i) : c; 135 } 136 }), 137 defaultBuffer = buffer.join(''), 138 focusText = input.val(); 139 140 function tryFireCompleted(){ 141 if (!settings.completed) { 142 return; 143 } 144 145 for (var i = firstNonMaskPos; i <= lastRequiredNonMaskPos; i++) { 146 if (tests[i] && buffer[i] === getPlaceholder(i)) { 147 return; 148 } 149 } 150 settings.completed.call(input); 151 } 152 153 function getPlaceholder(i){ 154 if(i < settings.placeholder.length) 155 return settings.placeholder.charAt(i); 156 return settings.placeholder.charAt(0);
157 } 158 159 function seekNext(pos) { 160 while (++pos < len && !tests[pos]); 161 return pos; 162 } 163 164 function seekPrev(pos) { 165 while (--pos >= 0 && !tests[pos]); 166 return pos; 167 } 168 169 function shiftL(begin,end) { 170 var i, 171 j; 172 173 if (begin<0) { 174 return; 175 } 176 177 for (i = begin, j = seekNext(end); i < len; i++) { 178 if (tests[i]) { 179 if (j < len && tests[i].test(buffer[j])) { 180 buffer[i] = buffer[j]; 181 buffer[j] = getPlaceholder(j); 182 } else { 183 break; 184 } 185 186 j = seekNext(j); 187 } 188 } 189 writeBuffer(); 190 input.caret(Math.max(firstNonMaskPos, begin)); 191 } 192 193 function shiftR(pos) { 194 var i, 195 c, 196 j, 197 t; 198 199 for (i = pos, c = getPlaceholder(pos); i < len; i++) { 200 if (tests[i]) { 201 j = seekNext(i); 202 t = buffer[i]; 203 buffer[i] = c; 204 if (j < len && tests[j].test(t)) { 205 c = t; 206 } else { 207 break; 208 } 209 } 210 } 211 } 212 213 function androidInputEvent(e) { 214 var curVal = input.val(); 215 var pos = input.caret(); 216 var proxy = function () { 217 $.proxy($.fn.caret, input, pos.begin, pos.begin)(); 218 }; 219 220 if (oldVal && oldVal.length && oldVal.length > curVal.length ) { 221 // a deletion or backspace happened 222 var nextPos = checkVal(true); 223 var curPos = pos.end; 224 while (curPos > 0 && !tests[curPos-1]) { 225 curPos--; 226 } 227 if (curPos === 0) { 228 curPos = nextPos; 229 } 230 pos.begin = curPos; 231 setTimeout(function() { 232 proxy(); 233 tryFireCompleted(); 234 }, 0); 235 } else { 236 pos.begin = checkVal(true); 237 setTimeout(function() { 238 proxy(); 239 tryFireCompleted(); 240 }, 0); 241 } 242 } 243 244 245 function blurEvent(e) { 246 checkVal(); 247 248 if (input.val() != focusText) 249 input.trigger('change'); 250 } 251 252 function keydownEvent(e) { 253 if (input.prop("readonly")){ 254 return; 255 } 256 257 var k = e.which || e.keyCode, 258 pos, 259 begin, 260 end; 261 oldVal = input.val(); 262 //backspace, delete, and escape get special treatment 263 if (k === 8 || k === 46 || (iPhone && k === 127)) { 264 pos = input.caret(); 265 begin = pos.begin; 266 end = pos.end; 267 268 if (end - begin === 0) { 269 begin=k!==46?seekPrev(begin):(end=seekNext(begin-1));
270 end=k===46?seekNext(end):end; 271 } 272 clearBuffer(begin, end); 273 shiftL(begin, end - 1); 274 275 e.preventDefault(); 276 } else if( k === 13 ) { // enter 277 blurEvent.call(this, e); 278 } else if (k === 27) { // escape 279 input.val(focusText); 280 input.caret(0, checkVal()); 281 e.preventDefault(); 282 } 283 } 284 285 function keypressEvent(e) { 286 if (input.prop("readonly")){ 287 return; 288 } 289 290 var k = e.which || e.keyCode, 291 pos = input.caret(), 292 p, 293 c, 294 next; 295 if (e.ctrlKey || e.altKey || e.metaKey || k < 32) {//Ignore 296 return; 297 } else if ( k && k !== 13 ) { 298 if (pos.end - pos.begin !== 0){ 299 clearBuffer(pos.begin, pos.end); 300 shiftL(pos.begin, pos.end-1); 301 } 302 303 p = seekNext(pos.begin - 1); 304 if (p < len) { 305 c = String.fromCharCode(k); 306 if (tests[p].test(c)) { 307 shiftR(p); 308 309 buffer[p] = c; 310 writeBuffer(); 311 next = seekNext(p); 312 313 if(android){ 314 //Path for CSP Violation on FireFox OS 1.1 315 var proxy = function() { 316 $.proxy($.fn.caret,input,next)(); 317 }; 318 319 setTimeout(proxy,0); 320 }else{ 321 input.caret(next); 322 } 323 if(pos.begin <= lastRequiredNonMaskPos){ 324 tryFireCompleted(); 325 } 326 } 327 } 328 e.preventDefault(); 329 } 330 } 331 332 function clearBuffer(start, end) { 333 var i; 334 for (i = start; i < end && i < len; i++) { 335 if (tests[i]) { 336 buffer[i] = getPlaceholder(i); 337 } 338 } 339 } 340 341 function writeBuffer() { input.val(buffer.join('')); } 342 343 function checkVal(allow) { 344 //try to place characters where they belong 345 var test = input.val(), 346 lastMatch = -1, 347 i, 348 c, 349 pos; 350 351 for (i = 0, pos = 0; i < len; i++) { 352 if (tests[i]) { 353 buffer[i] = getPlaceholder(i); 354 while (pos++ < test.length) { 355 c = test.charAt(pos - 1); 356 if (tests[i].test(c)) { 357 buffer[i] = c; 358 lastMatch = i; 359 break; 360 } 361 } 362 if (pos > test.length) { 363 clearBuffer(i + 1, len); 364 break; 365 } 366 } else { 367 if (buffer[i] === test.charAt(pos)) { 368 pos++; 369 } 370 if( i < partialPosition){ 371 lastMatch = i; 372 } 373 } 374 } 375 if (allow) { 376 writeBuffer(); 377 } else if (lastMatch + 1 < partialPosition) { 378 if (settings.autoclear || buffer.join('') === defaultBuffer) { 379 // Invalid value. Remove it and replace it with the 380 // mask, which is the default behavior. 381 if(input.val()) input.val(""); 382 clearBuffer(0, len); 383 } else { 384 // Invalid value, but we opt to show the value to the 385 // user and allow them to correct their mistake. 386 writeBuffer(); 387 } 388 } else { 389 writeBuffer(); 390 input.val(input.val().substring(0, lastMatch + 1)); 391 } 392 return (partialPosition ? i : firstNonMaskPos);
393 } 394 395 input.data($.mask.dataName,function(){ 396 return $.map(buffer, function(c, i) { 397 return tests[i]&&c!=getPlaceholder(i) ? c : null; 398 }).join(''); 399 }); 400 401 402 input 403 .one("unmask", function() { 404 input 405 .off(".mask") 406 .removeData($.mask.dataName); 407 }) 408 .on("focus.mask", function() { 409 if (input.prop("readonly")){ 410 return; 411 } 412 413 clearTimeout(caretTimeoutId); 414 var pos; 415 416 focusText = input.val(); 417 418 pos = checkVal(); 419 420 caretTimeoutId = setTimeout(function(){ 421 if(input.get(0) !== document.activeElement){ 422 return; 423 } 424 writeBuffer(); 425 if (pos == mask.replace("?","").length) { 426 input.caret(0, pos); 427 } else { 428 input.caret(pos); 429 } 430 }, 10); 431 }) 432 .on("blur.mask", blurEvent) 433 .on("keydown.mask", keydownEvent) 434 .on("keypress.mask", keypressEvent) 435 .on("input.mask paste.mask", function() { 436 if (input.prop("readonly")){ 437 return; 438 } 439 440 setTimeout(function() { 441 var pos=checkVal(true); 442 input.caret(pos); 443 tryFireCompleted(); 444 }, 0); 445 }); 446 if (chrome && android) 447 { 448 input 449 .off('input.mask') 450 .on('input.mask', androidInputEvent); 451 } 452 checkVal(); //Perform initial check for existing values 453 }); 454 } 455 }); 456}));
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.