1/* 2 Masked Input plugin for jQuery 3 Copyright (c) 2007-2013 Josh Bush (digitalbush.com) 4 Licensed under the MIT license (http://digitalbush.com/projects/masked-input-plugin/#license) 5 Version: 1.3.1 6*/ 7(function($) { 8 function getPasteEvent() { 9 var el = document.createElement('input'), 10 name = 'onpaste'; 11 el.setAttribute(name, ''); 12 return (typeof el[name] === 'function')?'paste':'input'; 13} 14 15var pasteEventName = getPasteEvent() + ".mask", 16 ua = navigator.userAgent, 17 iPhone = /iphone/i.test(ua), 18 android=/android/i.test(ua), 19 caretTimeoutId; 20 21$.mask = { 22 //Predefined character definitions 23 definitions: { 24 '9': "[0-9]", 25 'a': "[A-Za-z]", 26 'A': "[A-Za-z0-9]", 27 '*': "[A-Za-z0-9]" 28 }, 29 dataName: "rawMaskFn", 30 placeholder: '_', 31}; 32 33$.fn.extend({ 34 //Helper Function for Caret positioning 35 caret: function(begin, end) { 36 var range; 37 38 if (this.length === 0 || this.is(":hidden")) { 39 return; 40 } 41 42 if (typeof begin == 'number') { 43 end = (typeof end === 'number') ? end : begin; 44 return this.each(function() { 45 if (this.setSelectionRange) { 46 this.setSelectionRange(begin, end); 47 } else if (this.createTextRange) { 48 range = this.createTextRange(); 49 range.collapse(true); 50 range.moveEnd('character', end); 51 range.moveStart('character', begin); 52 range.select(); 53 } 54 }); 55 } else { 56 if (this[0].setSelectionRange) { 57 begin = this[0].selectionStart; 58 end = this[0].selectionEnd; 59 } else if (document.selection && document.selection.createRange) { 60 range = document.selection.createRange(); 61 begin = 0 - range.duplicate().moveStart('character', -100000); 62 end = begin + range.text.length; 63 } 64 return { begin: begin, end: end }; 65 } 66 }, 67 unmask: function() { 68 return this.trigger("unmask"); 69 }, 70 mask: function(mask, settings) { 71 var input, 72 defs, 73 tests, 74 partialPosition, 75 firstNonMaskPos, 76 len; 77 78 if (!mask && this.length > 0) { 79 input = $(this[0]); 80 return input.data($.mask.dataName)(); 81 } 82 settings = $.extend({ 83 placeholder: $.mask.placeholder, // Load default placeholder 84 partional: false, 85 completed: null 86 }, settings); 87 88 89 defs = $.mask.definitions; 90 tests = []; 91 partialPosition = len = mask.length; 92 firstNonMaskPos = null; 93 94 $.each(mask.split(""), function(i, c) { 95 if (c == '?') { 96 len--; 97 partialPosition = i; 98 } else if (defs[c]) { 99 tests.push(new RegExp(defs[c])); 100 if (firstNonMaskPos === null) { 101 firstNonMaskPos = tests.length - 1; 102 } 103 } else { 104 tests.push(null); 105 } 106 }); 107 108 return this.trigger("unmask").each(function() { 109 var input = $(this), 110 buffer = $.map( 111 mask.split(""), 112 function(c, i) { 113 if (c != '?') { 114 return defs[c] ? settings.placeholder : c; 115 } 116 }), 117 focusText = input.val(); 118 119 function seekNext(pos) { 120 while (++pos < len && !tests[pos]); 121 return pos; 122 } 123 124 function seekPrev(pos) { 125 while (--pos >= 0 && !tests[pos]); 126 return pos; 127 } 128 129 function shiftL(begin,end) { 130 var i, 131 j; 132 133 if (begin<0) { 134 return; 135 } 136 137 for (i = begin, j = seekNext(end); i < len; i++) { 138 if (tests[i]) { 139 if (j < len && tests[i].test(buffer[j])) { 140 buffer[i] = buffer[j]; 141 buffer[j] = settings.placeholder; 142 } else { 143 break; 144 } 145 146 j = seekNext(j); 147 } 148 } 149 writeBuffer(); 150 input.caret(Math.max(firstNonMaskPos, begin)); 151 } 152 153 function shiftR(pos) { 154 var i, 155 c, 156 j, 157 t; 158 159 for (i = pos, c = settings.placeholder; i < len; i++) { 160 if (tests[i]) { 161 j = seekNext(i); 162 t = buffer[i]; 163 buffer[i] = c; 164 if (j < len && tests[j].test(t)) { 165 c = t; 166 } else { 167 break; 168 } 169 } 170 } 171 } 172 173 function keydownEvent(e) { 174 var k = e.which, 175 pos, 176 begin, 177 end; 178 179 //backspace, delete, and escape get special treatment 180 if (k === 8 || k === 46 || (iPhone && k === 127)) { 181 pos = input.caret(); 182 begin = pos.begin; 183 end = pos.end; 184 185 if (end - begin === 0) { 186 begin=k!==46?seekPrev(begin):(end=seekNext(begin-1));
187 end=k===46?seekNext(end):end; 188 } 189 clearBuffer(begin, end); 190 shiftL(begin, end - 1); 191 192 e.preventDefault(); 193 } else if (k == 27) {//escape 194 input.val(focusText); 195 input.caret(0, checkVal()); 196 e.preventDefault(); 197 } 198 } 199 200 function keypressEvent(e) { 201 var k = e.which, 202 pos = input.caret(), 203 p, 204 c, 205 next; 206 207 if (e.ctrlKey || e.altKey || e.metaKey || k < 32) {//Ignore 208 return; 209 } else if (k) { 210 if (pos.end - pos.begin !== 0){ 211 clearBuffer(pos.begin, pos.end); 212 shiftL(pos.begin, pos.end-1); 213 } 214 215 p = seekNext(pos.begin - 1); 216 if (p < len) { 217 c = String.fromCharCode(k); 218 if (tests[p].test(c)) { 219 shiftR(p); 220 221 buffer[p] = c; 222 writeBuffer(); 223 next = seekNext(p); 224 225 if(android){ 226 setTimeout($.proxy($.fn.caret,input,next),0); 227 }else{ 228 input.caret(next); 229 } 230 231 if (settings.completed && next >= len) { 232 settings.completed.call(input); 233 } 234 } 235 } 236 e.preventDefault(); 237 } 238 } 239 240 function clearBuffer(start, end) { 241 var i; 242 for (i = start; i < end && i < len; i++) { 243 if (tests[i]) { 244 buffer[i] = settings.placeholder; 245 } 246 } 247 } 248 249 function writeBuffer() { input.val(buffer.join('')); } 250 251 function checkVal(allow) { 252 //try to place characters where they belong 253 var test = input.val(), 254 lastMatch = -1, 255 i, 256 c; 257 258 for (i = 0, pos = 0; i < len; i++) { 259 if (tests[i]) { 260 buffer[i] = settings.placeholder; 261 while (pos++ < test.length) { 262 c = test.charAt(pos - 1); 263 if (tests[i].test(c)) { 264 buffer[i] = c; 265 lastMatch = i; 266 break; 267 } 268 } 269 if (pos > test.length) { 270 break; 271 } 272 } else if (buffer[i] === test.charAt(pos) && i !== partialPosition) { 273 pos++; 274 lastMatch = i; 275 } 276 } 277 if (allow) { 278 writeBuffer(); 279 } else if ((lastMatch + 1 < partialPosition) && (settings.partional == false)) { 280 input.val(""); 281 clearBuffer(0, len); 282 } else { 283 writeBuffer(); 284 input.val(input.val().substring(0, lastMatch + 1)); 285 } 286 return (partialPosition ? i : firstNonMaskPos); 287 } 288 289 input.data($.mask.dataName,function(){ 290 return $.map(buffer, function(c, i) { 291 return tests[i]&&c!=settings.placeholder ? c : null; 292 }).join(''); 293 }); 294 295 if (!input.attr("readonly")) 296 input 297 .one("unmask", function() { 298 input 299 .unbind(".mask") 300 .removeData($.mask.dataName); 301 }) 302 .bind("focus.mask", function() { 303 clearTimeout(caretTimeoutId); 304 var pos, 305 moveCaret; 306 307 focusText = input.val(); 308 pos = checkVal(); 309 310 caretTimeoutId = setTimeout(function(){ 311 writeBuffer(); 312 if (pos == mask.length) { 313 input.caret(0, pos); 314 } else { 315 input.caret(pos); 316 } 317 }, 10); 318 }) 319 .bind("blur.mask", function() { 320 checkVal(); 321 if (input.val() != focusText) 322 input.change(); 323 }) 324 .bind("keydown.mask", keydownEvent) 325 .bind("keypress.mask", keypressEvent) 326 .bind(pasteEventName, function() { 327 setTimeout(function() { 328 var pos=checkVal(true); 329 input.caret(pos); 330 if (settings.completed && pos == input.val().length) 331 settings.completed.call(input); 332 }, 0); 333 }); 334 checkVal(); //Perform initial check for existing values 335 }); 336 } 337}); 338 339 340})(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.