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