PageSourceSearch

http://inomarka72.ru/media-templates/js/jquery.inputmask.js?version=5.0.27.01.15

js inomarka72.ru collected 2026-10-05 00:28:51 UTC 70,671 bytes, 1,272 lines download raw bytes

1/**
2* @license Input Mask plugin for jquery
3* http://github.com/RobinHerbots/jquery.inputmask
4* Copyright (c) 2010 - 2013 Robin Herbots
5* Licensed under the MIT license (http://www.opensource.org/licenses/mit-license.php)
6* Version: 0.0.0
7*/
8
9(function ($) {
10    if ($.fn.inputmask == undefined) {
11        $.inputmask = {
12            //options default
13            defaults: {
14                placeholder: "_",
15                optionalmarker: {
16                    start: "[",
17                    end: "]"
18                },
19                escapeChar: "\\",
20                mask: null,
21                oncomplete: $.noop, //executes when the mask is complete
22                onincomplete: $.noop, //executes when the mask is incomplete and focus is lost
23                oncleared: $.noop, //executes when the mask is cleared
24                repeat: 0, //repetitions of the mask
25                greedy: true, //true: allocated buffer for the mask and repetitions - false: allocate only if needed
26                autoUnmask: false, //automatically unmask when retrieving the value with $.fn.val or value if the browser supports __lookupGetter__ or getOwnPropertyDescriptor
27                clearMaskOnLostFocus: true,
28                insertMode: true, //insert the input or overwrite the input
29                clearIncomplete: false, //clear the incomplete input on blur
30                aliases: {}, //aliases definitions => see jquery.inputmask.extensions.js
31                onKeyUp: $.noop, //override to implement autocomplete on certain keys for example
32                onKeyDown: $.noop, //override to implement autocomplete on certain keys for example
33                showMaskOnFocus: true, //show the mask-placeholder when the input has focus
34                showMaskOnHover: true, //show the mask-placeholder when hovering the empty input
35                onKeyValidation: $.noop, //executes on every key-press with the result of isValid
36                skipOptionalPartCharacter: " ", //a character which can be used to skip an optional part of a mask
37                //numeric basic properties
38                numericInput: false, //numericInput input direction style (input shifts to the left while holding the caret position)
39                radixPoint: "", //".", // | ","
40                //numeric basic properties
41                definitions: {
42                    '9': {
43                        validator: "[0-9]",
44                        cardinality: 1
45                    },
46                    'a': {
47                        validator: "[A-Za-z\u0410-\u044F\u0401\u0451]",
48                        cardinality: 1
49                    },
50                    '*': {
51                        validator: "[A-Za-z\u0410-\u044F\u0401\u04510-9]",
52                        cardinality: 1
53                    }
54                },
55                keyCode: {
56                    ALT: 18, BACKSPACE: 8, CAPS_LOCK: 20, COMMA: 188, COMMAND: 91, COMMAND_LEFT: 91, COMMAND_RIGHT: 93, CONTROL: 17, DELETE: 46, DOWN: 40, END: 35, ENTER: 13, ESCAPE: 27, HOME: 36, INSERT: 45, LEFT: 37, MENU: 93, NUMPAD_ADD: 107, NUMPAD_DECIMAL: 110, NUMPAD_DIVIDE: 111, NUMPAD_ENTER: 108,
57                    NUMPAD_MULTIPLY: 106, NUMPAD_SUBTRACT: 109, PAGE_DOWN: 34, PAGE_UP: 33, PERIOD: 190, RIGHT: 39, SHIFT: 16, SPACE: 32, TAB: 9, UP: 38, WINDOWS: 91
58                },
59                //specify keycodes which should not be considered in the keypress event, otherwise the preventDefault will stop their default behavior especially in FF
60                ignorables: [9, 13, 19, 27, 33, 34, 35, 36, 37, 38, 39, 40, 45, 46, 93, 112, 113, 114, 115, 116, 117, 118, 119, 120, 121, 122, 123],
61                getMaskLength: function (buffer, greedy, repeat, currentBuffer, opts) {
62                    var calculatedLength = buffer.length;
63                    if (!greedy && repeat > 1) {
64                        calculatedLength += (buffer.length * (repeat - 1));
65                    }
66                    return calculatedLength;
67                }
68            },
69            val: $.fn.val, //store the original jquery val function
70            escapeRegex: function (str) {
71                var specials = ['/', '.', '*', '+', '?', '|', '(', ')', '[', ']', '{', '}', '\\'];
72                return str.replace(new RegExp('(\\' + specials.join('|\\') + ')', 'gim'), '\\$1');
73            }
74        };
75
76        $.fn.inputmask = function (fn, options) {
77            var opts = $.extend(true, {}, $.inputmask.defaults, options);
78            var pasteEvent = isInputEventSupported('paste') ? 'paste' : 'input';
79
80            var iphone = navigator.userAgent.match(/iphone/i) != null;
81            var android = navigator.userAgent.match(/android.*safari.*/i) != null,
82	    	android534;
83            if (android) {
84                var browser = navigator.userAgent.match(/safari.*/i);
85                var version = parseInt(new RegExp(/[0-9]+/).exec(browser));
86                android = (version <= 533);
87                android534 = (533 < version <= 534);
88            }
89            var caretposCorrection = null;
90            var masksets,
91	        activeMasksetIndex = 0;
92
93            if (typeof fn == "string") {
94                switch (fn) {
95                    case "mask":
96                        //resolve possible aliases given by options
97                        resolveAlias(opts.alias, options);
98                        masksets = generateMaskSets();
99
100                        return this.each(function () {
101                            mask(this);
102                        });
103                        break;
104                    case "unmaskedvalue":
105                        masksets = this.data('inputmask')['masksets'];
106                        activeMasksetIndex = this.data('inputmask')['activeMasksetIndex'];
107                        opts.definitions = this.data('inputmask')['definitions'];
108                        return unmaskedvalue(this);
109                        break;
110                    case "remove":
111                        return this.each(function () {
112                            var $input = $(this), input = this;
113                            setTimeout(function () {
114                                if ($input.data('inputmask')) {
115                                    masksets = $input.data('inputmask')['masksets'];
116                                    activeMasksetIndex = $input.data('inputmask')['activeMasksetIndex'];
117                                    opts.definitions = $input.data('inputmask')['definitions'];
118                                    //writeout the unmaskedvalue
119                                    input._valueSet(unmaskedvalue($input, true));
120                                    //clear data
121                                    $input.removeData('inputmask');
122                                    //unbind all events
123                                    $input.unbind(".inputmask");
124                                    $input.removeClass('focus.inputmask');
125                                    //restore the value property
126                                    var valueProperty;
127                                    if (Object.getOwnPropertyDescriptor)
128                                        valueProperty = Object.getOwnPropertyDescriptor(input, "value");
129                                    if (valueProperty && valueProperty.get) {
130                                        if (input._valueGet) {
131                                            Object.defineProperty(input, "value", {
132                                                get: input._valueGet,
133                                                set: input._valueSet
134                                            });
135                                        }
136                                    } else if (document.__lookupGetter__ && input.__lookupGetter__("value")) {
137                                        if (input._valueGet) {
138                                            input.__defineGetter__("value", input._valueGet);
139                                            input.__defineSetter__("value", input._valueSet);
140                                        }
141                                    }
142                                    delete input._valueGet;
143                                    delete input._valueSet;
144                                }
145                            }, 0);
146                        });
147                        break;
148                    case "getemptymask": //return the default (empty) mask value, usefull for setting the default value in validation
149                        if (this.data('inputmask')) {
150                            masksets = this.data('inputmask')['masksets'];
151                            activeMasksetIndex = this.data('inputmask')['activeMasksetIndex'];
152                            return masksets[activeMasksetIndex]['_buffer'].join('');
153                        }
154                        else return "";
155                    case "hasMaskedValue": //check wheter the returned value is masked or not;
155 currently only works reliable when using jquery.val fn to retrieve the value 
156                        return this.data('inputmask') ? !this.data('inputmask')['autoUnmask'] : false;
157                    case "isComplete":
158                        masksets = this.data('inputmask')['masksets'];
159                        activeMasksetIndex = this.data('inputmask')['activeMasksetIndex'];
160                        opts.definitions = this.data('inputmask')['definitions'];
161                        return isComplete(this[0].split(''));
162                    default:
163                        //check if the fn is an alias
164                        if (!resolveAlias(fn, options)) {
165                            //maybe fn is a mask so we try
166                            //set mask
167                            opts.mask = fn;
168                        }
169                        masksets = generateMaskSets();
170
171                        return this.each(function () {
172                            mask(this);
173                        });
174
175                        break;
176                }
177            } else if (typeof fn == "object") {
178                opts = $.extend(true, {}, $.inputmask.defaults, fn);
179
180                resolveAlias(opts.alias, fn); //resolve aliases
181                masksets = generateMaskSets();
182
183                return this.each(function () {
184                    mask(this);
185                });
186            } else if (fn == undefined) {
187                //look for data-inputmask atribute - the attribute should only contain optipns
188                return this.each(function () {
189                    var attrOptions = $(this).attr("data-inputmask");
190                    if (attrOptions && attrOptions != "") {
191                        try {
192                            attrOptions = attrOptions.replace(new RegExp("'", "g"), '"');
193                            var options = $.parseJSON("{" + attrOptions + "}");
194                            opts = $.extend(true, {}, $.inputmask.defaults, options);
195                            resolveAlias(opts.alias, options);
196                            opts.alias = undefined;
197                            $(this).inputmask(opts);
198                        } catch (ex) { } //need a more relax parseJSON
199                    }
200                });
201            }
202
203            //helper functions
204            function isInputEventSupported(eventName) {
205                var el = document.createElement('input'),
206		        eventName = 'on' + eventName,
207		        isSupported = (eventName in el);
208                if (!isSupported) {
209                    el.setAttribute(eventName, 'return;');
210                    isSupported = typeof el[eventName] == 'function';
211                }
212                el = null;
213                return isSupported;
214            }
215
216            function resolveAlias(aliasStr, options) {
217                var aliasDefinition = opts.aliases[aliasStr];
218                if (aliasDefinition) {
219                    if (aliasDefinition.alias) resolveAlias(aliasDefinition.alias); //alias is another alias
220                    $.extend(true, opts, aliasDefinition);  //merge alias definition in the options
221                    $.extend(true, opts, options);  //reapply extra given options
222                    return true;
223                }
224                return false;
225            }
226
227            function getMaskTemplate(mask) {
228                var escaped = false, outCount = 0, greedy = opts.greedy, repeat = opts.repeat;
229                if (mask.length == 1 && greedy == false) { opts.placeholder = ""; } //hide placeholder with single non-greedy mask
230                var singleMask = $.map(mask.split(""), function (element, index) {
231                    var outElem = [];
232                    if (element == opts.escapeChar) {
233                        escaped = true;
234                    }
235                    else if ((element != opts.optionalmarker.start && element != opts.optionalmarker.end) || escaped) {
236                        var maskdef = opts.definitions[element];
237                        if (maskdef && !escaped) {
238                            for (var i = 0; i < maskdef.cardinality; i++) {
239                                outElem.push(getPlaceHolder(outCount + i));
240                            }
241                        } else {
242                            outElem.push(element);
243                            escaped = false;
244                        }
245                        outCount += outElem.length;
246                        return outElem;
247                    }
248                });
249
250                //allocate repetitions
251                var repeatedMask = singleMask.slice();
252                for (var i = 1; i < repeat && greedy; i++) {
253                    repeatedMask = repeatedMask.concat(singleMask.slice());
254                }
255
256                return { "mask": repeatedMask, "repeat": repeat, "greedy": greedy };
257            }
258
259            //test definition => {fn: RegExp/function, cardinality: int, optionality: bool, newBlockMarker: bool, offset: int, casing: null/upper/lower, def: definitionSymbol}
260            function getTestingChain(mask) {
261                var isOptional = false, escaped = false;
262                var newBlockMarker = false; //indicates wheter the begin/ending of a block should be indicated
263
264                return $.map(mask.split(""), function (element, index) {
265                    var outElem = [];
266
267                    if (element == opts.escapeChar) {
268                        escaped = true;
269                    } else if (element == opts.optionalmarker.start && !escaped) {
270                        isOptional = true;
271                        newBlockMarker = true;
272                    }
273                    else if (element == opts.optionalmarker.end && !escaped) {
274                        isOptional = false;
275                        newBlockMarker = true;
276                    }
277                    else {
278                        var maskdef = opts.definitions[element];
279                        if (maskdef && !escaped) {
280                            var prevalidators = maskdef["prevalidator"], prevalidatorsL = prevalidators ? prevalidators.length : 0;
281                            for (var i = 1; i < maskdef.cardinality; i++) {
282                                var prevalidator = prevalidatorsL >= i ? prevalidators[i - 1] : [], validator = prevalidator["validator"], cardinality = prevalidator["cardinality"];
283                                outElem.push({ fn: validator ? typeof validator == 'string' ? new RegExp(validator) : new function () { this.test = validator; } : new RegExp("."), cardinality: cardinality ? cardinality : 1, optionality: isOptional, newBlockMarker: isOptional == true ? newBlockMarker : false, offset: 0, casing: maskdef["casing"], def: element });
284                                if (isOptional == true) //reset newBlockMarker
285                                    newBlockMarker = false;
286                            }
287                            outElem.push({ fn: maskdef.validator ? typeof maskdef.validator == 'string' ? new RegExp(maskdef.validator) : new function () { this.test = maskdef.validator; } : new RegExp("."), cardinality: maskdef.cardinality, optionality: isOptional, newBlockMarker: newBlockMarker, offset: 0, casing: maskdef["casing"], def: element });
288                        } else {
289                            outElem.push({ fn: null, cardinality: 0, optionality: isOptional, newBlockMarker: newBlockMarker, offset: 0, casing: null, def: element });
290                            escaped = false;
291                        }
292                        //reset newBlockMarker
293                        newBlockMarker = false;
294                        return outElem;
295                    }
296                });
297            }
298
299            function generateMaskSets() {  //TODO improve generate masksets
300                var ms = [];
301                function markOptional(maskPart) { //needed for the clearOptionalTail functionality
302                    return opts.optionalmarker.start + maskPart + opts.optionalmarker.end;
303                }
304                function generateMask(maskPrefix, maskPart) {
305                    var maskParts = maskPart.split(opts.optionalmarker.end, 2);
306                    var newMask, maskTemplate;
307
308
309                    var masks = maskParts[0].split(opts.optionalmarker.start);
310                    if (masks.length > 1) {
311                        newMask = maskPrefix + masks[0] + markOptional(masks[1]) + (maskParts.length > 1 ? maskParts[1] : "");
312                        maskTemplate = getMaskTemplate(newMask);
313                        ms.push({
314                            "_buffer": maskTemplate["mask"],
315                            "tests": getTestingChain(newMask),
316                            "lastValidPosition": 0,
317                            "greedy": maskTemplate["greedy"],
318                            "repeat": maskTemplate["repeat"]
319                        });
320                        newMask = maskPrefix + masks[0] + (maskParts.length > 1 ? maskParts[1] : "");
321                        maskTemplate = getMaskTemplate(newMask);
322                        ms.push({
323                            "_buffer": maskTemplate["mask"],
324                            "tests": getTestingChain(newMask),
325                            "lastValidPosition": 0,
326                            "greedy": maskTemplate["greedy"],
327                            "repeat": maskTemplate["repeat"]
328                        });
329                        if (maskParts.length > 1 && maskParts[1].split(opts.optionalmarker.start).length > 1) {
330                            generateMask(maskPrefix + masks[0] + markOptional(masks[1]), maskParts[1]);
331                            generateMask(maskPrefix + masks[0], maskParts[1]);
332                        }
333                    }
334                    else {
335                        newMask = maskPrefix + maskParts;
336                        maskTemplate = getMaskTemplate(newMask);
337                        ms.push({
338                            "_buffer": maskTemplate["mask"],
339                            "tests": getTestingChain(newMask),
340                            "lastValidPosition": 0,
341                            "greedy": maskTemplate["greedy"],
342                            "repeat": maskTemplate["repeat"]
343                        });
344                    }
345
346                }
347
348                generateMask("", opts.mask.toString());
349                return ms;
350            }
351
352            //maskset helperfunctions
353            function getActiveMaskSet() {
354                return masksets[activeMasksetIndex];
355            }
356
357            function getActiveTests() {
358                return getActiveMaskSet()['tests'];
359            }
360
361            function getActiveBuffer() {
362                return getActiveMaskSet()['_buffer'];
363            }
364
365            function isValid(pos, c, buffer, strict, isRTL) { //strict true ~ no correction or autofill
366                function _isValid(position, activeMaskset) {
367                    var testPos = determineTestPosition(position), loopend = c ? 1 : 0, chrs = '';
368                    for (var i = activeMaskset['tests'][testPos].cardinality; i > loopend; i--) {
369                        chrs += getBufferElement(buffer, testPos - (i - 1));
370                    }
371
372                    if (c) {
373                        chrs += c;
374                    }
375
376                    //return is false or a json object => { pos: ??, c: ??} or true
377                    return activeMaskset['tests'][testPos].fn != null ? activeMaskset['tests'][testPos].fn.test(chrs, buffer, position, strict, opts) : false;
378                }
379
380                if (strict) return _isValid(pos, getActiveMaskSet()); //only check validity in current mask when validating strict
381
382                var results = [], result = false, currentActiveMasksetIndex = activeMasksetIndex;
383                $.each(masksets, function (index, value) {
384                    var activeMaskset = this;
385                    activeMasksetIndex = index;
386
387                    var maskPos = pos;
388                    if (currentActiveMasksetIndex != activeMasksetIndex && !isMask(pos)) {
389                        if (c == activeMaskset['_buffer'][maskPos] || c == opts.skipOptionalPartCharacter) { //match non-mask item
390                            results[index] = { "refresh": true };  //new command hack only rewrite buffer
391                            activeMaskset['lastValidPosition'] = maskPos;
392                            return false;
393                        }
394
395                        maskPos = isRTL ? seekPrevious(buffer, pos) : seekNext(buffer, pos);
396                    }
397                    if ((isRTL || opts.numericInput) ? activeMaskset['lastValidPosition'] <= opts.numericInput ? getMaskLength(buffer) : seekNext(buffer, maskPos) : activeMaskset['lastValidPosition'] >= seekPrevious(buffer, maskPos)) {
398                        if (maskPos >= 0 && maskPos < getMaskLength(buffer)) {
399                            results[index] = _isValid(maskPos, activeMaskset);
400                            if (results[index] !== false) {
401                                if (results[index] === true) {
402                                    results[index] = { "pos": maskPos }; //always take a possible corrected maskposition into account
403                                }
404                                activeMaskset['lastValidPosition'] = results[index].pos || maskPos; //set new position from isValid
405                            } else activeMaskset['lastValidPosition'] = isRTL ? seekNext(buffer, pos) : seekPrevious(buffer, pos); //autocorrect validposition from backspace etc  	
406                        }
407                    }
408                });
409                activeMasksetIndex = currentActiveMasksetIndex; //reset activeMasksetIndex
410                determineActiveMasksetIndex(buffer, pos, currentActiveMasksetIndex, isRTL);
411                result = results[activeMasksetIndex] || result;
412                setTimeout(function () { opts.onKeyValidation.call(this, result, opts); }, 0); //extra stuff to execute on keydown
413                return result;
414            }
415
416            function determineActiveMasksetIndex(buffer, pos, currentActiveMasksetIndex, isRTL) {
417                $.each(masksets, function (index, value) {
418                    var activeMaskset = this;
419                    if ((isRTL || opts.numericInput) ? activeMaskset['lastValidPosition'] <= pos : activeMaskset['lastValidPosition'] >= pos) {
420                        activeMasksetIndex = index;
421                        //reset to correct masktemplate
422                        if (activeMasksetIndex != currentActiveMasksetIndex) {
423                            var abl = getMaskLength(buffer), bufTemplate = getActiveBuffer();
424                            if (isRTL || opts.numericInput) {
425                                buffer.reverse();
426                                bufTemplate.reverse();
427                            }
428                            buffer.length = pos; //clearout beyond the current
429                            for (var i = pos; i < abl; i++) {
430                                var testPos = determineTestPosition(i);
431                                setBufferElement(buffer, i, getBufferElement(bufTemplate, testPos));
432                            }
433                            if (isRTL) {
434                                buffer.reverse();
435                            }
436                        }
437                        return false; //breaks
438                    }
439                });
440            }
441
442            function isMask(pos) {
443                var testPos = determineTestPosition(pos);
444                var test = getActiveTests()[testPos];
445
446                return test != undefined ? test.fn : false;
447            }
448
449            function determineTestPosition(pos) {
450                return pos % getActiveTests().length;
451            }
452
453            function getPlaceHolder(pos) {
454                return opts.placeholder.charAt(pos % opts.placeholder.length);
455            }
456
457            function getMaskLength(currentBuffer) {
458                return opts.getMaskLength(getActiveBuffer(), getActiveMaskSet()['greedy'], getActiveMaskSet()['repeat'], currentBuffer, opts);
459            }
460
461            //pos: from position
462            function seekNext(buffer, pos) {
463                var maskL = getMaskLength(buffer);
464                if (pos >= maskL) return maskL;
465                var position = pos;
466                while (++position < maskL && !isMask(position)) { };
467                return position;
468            }
469            //pos: from position
470            function seekPrevious(buffer, pos) {
471                var position = pos;
472                if (position <= 0) return 0;
473
474                while (--position > 0 && !isMask(position)) { };
475                return position;
476            }
477
478            function setBufferElement(buffer, position, element) {
479                //position = prepareBuffer(buffer, position);
480
481                var test = getActiveTests()[determineTestPosition(position)];
482                var elem = element;
483                if (elem != undefined) {
484                    switch (test.casing) {
485                        case "upper":
486                            elem = element.toUpperCase();
487                            break;
488                        case "lower":
489                            elem = element.toLowerCase();
490                            break;
491                    }
492                }
493
494                buffer[position] = elem;
495            }
496            function getBufferElement(buffer, position, autoPrepare) {
497                if (autoPrepare) position = prepareBuffer(buffer, position);
498                return buffer[position];
499            }
500
501            //needed to handle the non-greedy mask repetitions
502            function prepareBuffer(buffer, position, isRTL) {
503                var j;
504                if (isRTL) {
505                    while (position < 0 && buffer.length < getMaskLength(buffer)) {
506                        j = getActiveBuffer().length - 1;
507                        position = getActiveBuffer().length;
508                        while (getActiveBuffer()[j] !== undefined) {
509                            buffer.unshift(getActiveBuffer()[j--]);
510                        }
511                    }
512                } else {
513                    while (buffer[position] == undefined && buffer.length < getMaskLength(buffer)) {
514                        j = 0;
515                        while (getActiveBuffer()[j] !== undefined) { //add a new buffer
516                            buffer.push(getActiveBuffer()[j++]);
517                        }
518                    }
519                }
520
521                return position;
522            }
523
524            function writeBuffer(input, buffer, caretPos) {
525                input._valueSet(buffer.join(''));
526                if (caretPos != undefined) {
527                    if (android) {
528                        setTimeout(function () {
529                            caret(input, caretPos);
530                        }, 100);
531                    }
532                    else caret(input, caretPos);
533                }
534            };
535            function clearBuffer(buffer, start, end) {
536                for (var i = start, maskL = getMaskLength(buffer) ; i < end && i < maskL; i++) {
537                    setBufferElement(buffer, i, getBufferElement(getActiveBuffer().slice(), i));
538                }
539            };
540
541            function setReTargetPlaceHolder(buffer, pos) {
542                var testPos = determineTestPosition(pos);
543                setBufferElement(buffer, pos, getBufferElement(getActiveBuffer(), testPos));
544            }
545
546            function checkVal(input, buffer, clearInvalid, skipRadixHandling) {
547                var isRTL = $(input).data('inputmask')['isRTL'],
548                    inputValue = truncateInput(input._valueGet(), isRTL).split('');
549
550                var maskL = getMaskLength(buffer);
551                if (isRTL) { //align inputValue for RTL/numeric input
552                    var inputValueRev = inputValue.reverse(); inputValueRev.length = maskL;
553
554                    for (var i = 0; i < maskL; i++) {
555                        var targetPosition = determineTestPosition(maskL - (i + 1));
556                        if (getActiveTests()[targetPosition].fn == null && inputValueRev[i] != getBufferElement(getActiveBuffer(), targetPosition)) {
557                            inputValueRev.splice(i, 0, getBufferElement(getActiveBuffer(), targetPosition));
558                            inputValueRev.length = maskL;
559                        } else {
560                            inputValueRev[i] = inputValueRev[i] || getBufferElement(getActiveBuffer(), targetPosition);
561                        }
562                    }
563                    inputValue = inputValueRev.reverse();
564                }
565                clearBuffer(buffer, 0, buffer.length);
566                buffer.length = getActiveBuffer().length;
567                var lastMatch = -1, checkPosition = -1, np, ivl = inputValue.length, rtlMatch = ivl == 0 ? maskL : -1;
568                for (var i = 0; i < ivl; i++) {
569                    for (var pos = checkPosition + 1; pos < maskL; pos++) {
570                        if (isMask(pos)) {
571                            var c = inputValue[i];
572                            if ((np = isValid(pos, c, buffer, !clearInvalid, isRTL)) !== false) {
573                                if (np !== true) {
574                                    pos = np.pos != undefined ? np.pos : pos; //set new position from isValid
575                                    c = np.c != undefined ? np.c : c; //set new char from isValid
576                                }
577                                setBufferElement(buffer, pos, c);
578                                lastMatch = checkPosition = pos;
579                            } else {
580                                setReTargetPlaceHolder(buffer, pos);
581                                if (c == getPlaceHolder(pos)) {
582                                    checkPosition = pos;
583                                    rtlMatch = pos;
584                                }
585                            }
586                            break;
587                        } else {   //nonmask
588                            setReTargetPlaceHolder(buffer, pos);
589                            if (lastMatch == checkPosition) //once outsync the nonmask cannot be the lastmatch
590                                lastMatch = pos;
591                            checkPosition = pos;
592                            if (inputValue[i] == getBufferElement(buffer, pos))
593                                break;
594                        }
595                    }
596                }
597                //Truncate buffer when using non-greedy masks
598                if (getActiveMaskSet()['greedy'] == false) {
599                    var newBuffer = truncateInput(buffer.join(''), isRTL).split('');
600                    while (buffer.length != newBuffer.length) {  //map changes into the original buffer
601                        isRTL ? buffer.shift() : buffer.pop();
602                    }
603                }
604
605                if (clearInvalid) {
606                    writeBuffer(input, buffer);
607                }
608                return isRTL ? (opts.numericInput ? (opts.radixPoint != "" && $.inArray(opts.radixPoint, buffer) != -1 && skipRadixHandling !== true ? $.inArray(opts.radixPoint, buffer) : seekNext(buffer, maskL)) : seekNext(buffer, rtlMatch)) : seekNext(buffer, lastMatch);
609            }
610
611            function escapeRegex(str) {
612                return $.inputmask.escapeRegex.call(this, str);
613            }
614
615            function truncateInput(inputValue, rtl) {
616                return rtl ? inputValue.replace(new RegExp("^(" + escapeRegex(getActiveBuffer().join('')) + ")*"), "") : inputValue.replace(new RegExp("(" + escapeRegex(getActiveBuffer().join('')) + ")*$"), "");
617            }
618
619            function clearOptionalTail(input, buffer) {
620                checkVal(input, buffer, false);
621                var tmpBuffer = buffer.slice(), testPos, pos;
622                if ($(input).data('inputmask')['isRTL']) {
623                    for (var pos = 0; pos <= tmpBuffer.length - 1; pos++) {
624                        var testPos = determineTestPosition(pos);
625                        if (getActiveTests()[testPos].optionality) {
626                            if (!isMask(pos) || !isValid(pos, buffer[pos], buffer, true))
627                                tmpBuffer.splice(0, 1);
628                            else break;
629                        } else break;
630                    }
631                } else {
632                    for (var pos = tmpBuffer.length - 1; pos >= 0; pos--) {
633                        var testPos = determineTestPosition(pos);
634                        if (getActiveTests()[testPos].optionality) {
635                            if (!isMask(pos) || !isValid(pos, buffer[pos], buffer, true))
636                                tmpBuffer.pop();
637                            else break;
638                        } else break;
639                    }
640                }
641                writeBuffer(input, tmpBuffer);
642            }
643
644            //functionality fn
645            function unmaskedvalue($input, skipDatepickerCheck) {
646                var input = $input[0];
647                if (getActiveTests() && (skipDatepickerCheck === true || !$input.hasClass('hasDatepicker'))) {
648                    var buffer = getActiveBuffer().slice();
649                    checkVal(input, buffer);
650                    return $.map(buffer, function (element, index) {
651                        return isMask(index) && isValid(index, element, buffer, true) ? element : null;
652                    }).join('');
653                }
654                else {
655                    return input._valueGet();
656                }
657            }
658
659            function caret(input, begin, end) {       
660                var npt = input.jquery && input.length > 0 ? input[0] : input;
661                if (typeof begin == 'number') {
662                  	if (!$(input).is(':visible')) {
663                    	return;
664                	}
665                    end = (typeof end == 'number') ? end : begin;
666                    if (opts.insertMode == false && begin == end) end++; //set visualization for insert/overwrite mode
667                    if (npt.setSelectionRange) {
668                        if (end == begin) {
669                       		npt.focus();
670                        	npt.setSelectionRange(begin, end);
671                    	} else {
672                        	npt.select();
673                        	npt.selectionStart = begin;
674                        	npt.selectionEnd = android534 ? begin : end;
675                    	}
676                    } else if (npt.createTextRange) {
677                        var range = npt.createTextRange();
678                        range.collapse(true);
679                        range.moveEnd('character', end);
680                        range.moveStart('character', begin);
681                        range.select();
682                    }
683                    npt.focus();
684                    if (android && end != npt.selectionEnd) caretposCorrection = { begin: begin, end: end };
685                } else {
686                	if (!$(input).is(':visible')) {
687                    	return { begin: 0, end: 0 };
688                	}
689                    var caretpos = android ? caretposCorrection : null, caretposCorrection = null;
690                    if (caretpos == null) {
691                        if (npt.setSelectionRange) {
692                            begin = npt.selectionStart;
693                            end = npt.selectionEnd;
694                        } else if (document.selection && document.selection.createRange) {
695                            var range = document.selection.createRange();
696                            begin = 0 - range.duplicate().moveStart('character', -100000);
697                            end = begin + range.text.length;
698                        }
699                        caretpos = { begin: begin, end: end };
700                    }
701                    return caretpos;
702                }
703            };
704
705            function isComplete(buffer) {
706                var complete = false;
707                currentActiveMasksetIndex = activeMasksetIndex, highestValidPosition = 0;
708                $.each(masksets, function (ndx, ms) {
709                    activeMasksetIndex = ndx;
710                    var aml = getMaskLength(buffer);
711                    if (ms["lastValidPosition"] >= highestValidPosition && ms["lastValidPosition"] == (aml - 1)) {
712                        var msComplete = true;
713                        for (var i = 0; i < aml; i++) {
714                            var mask = isMask(i);
715                            if ((mask && buffer[i] == getPlaceHolder(i)) || (!mask && buffer[i] != getActiveBuffer()[i])) {
716                                msComplete = false;
717                                break;
718                            }
719                        }
720                        complete = complete || msComplete;
721                        if (complete) //break loop
722                            return false;
723                    }
724                    highestValidPosition = ms["lastValidPosition"];
725                });
726                activeMasksetIndex = currentActiveMasksetIndex; //reset activeMaskset
727                return complete;
728            }
729
730            function mask(el) {
731                var $input = $(el);
732                if (!$input.is(":input")) return;
733
734                var buffer = getActiveBuffer().slice();
735
736                //correct greedy setting if needed
737                getActiveMaskSet()['greedy'] = getActiveMaskSet()['greedy'] ? getActiveMaskSet()['greedy'] : getActiveMaskSet()['repeat'] == 0;
738
739                //handle maxlength attribute
740                var maxLength = $input.prop('maxLength');
741                if (getMaskLength(buffer) > maxLength && maxLength > -1) { //FF sets no defined max length to -1 
742                    if (maxLength < getActiveBuffer().length) getActiveBuffer().length = maxLength;
743                    if (getActiveMaskSet()['greedy'] == false) {
744                        getActiveMaskSet()['repeat'] = Math.round(maxLength / getActiveBuffer().length);
745                    }
746                    $input.prop('maxLength', getMaskLength(buffer) * 2);
747                }
748
749                //store tests & original buffer in the input element - used to get the unmasked value
750                $input.data('inputmask', {
751                    'masksets': masksets,
752                    'activeMasksetIndex': activeMasksetIndex,
753                    'autoUnmask': opts.autoUnmask,
754                    'definitions': opts.definitions,
755                    'isRTL': false
756                });
757
758                patchValueProperty(el);
759
760                //init vars
761                var buffer = getActiveBuffer().slice(),
762                undoBuffer = el._valueGet(),
763
764                skipKeyPressEvent = false, //Safari 5.1.x - modal dialog fires keypress twice workaround
765                ignorable = false,
766                lastPosition = -1,
767                firstMaskPos = seekNext(buffer, -1),
768                lastMaskPos = seekPrevious(buffer, getMaskLength(buffer)),
769                isRTL = false;
770                if (el.dir == "rtl" || opts.numericInput) {
771                    el.dir = "ltr"
772                    $input.css("text-align", "right");
773                    $input.removeAttr("dir");
774                    var inputData = $input.data('inputmask');
775                    inputData['isRTL'] = true;
776                    $input.data('inputmask', inputData);
777                    isRTL = true;
778                }
779
780                //unbind all events - to make sure that no other mask will interfere when re-masking
781                $input.unbind(".inputmask");
782                $input.removeClass('focus.inputmask');
783                //bind events
784                $input.bind("mouseenter.inputmask", function () {
785                    var $input = $(this), input = this;
786                    if (!$input.hasClass('focus.inputmask') && opts.showMaskOnHover) {
787                        var nptL = input._valueGet().length;
788                        if (nptL < buffer.length) {
789                            if (nptL == 0)
790                                buffer = getActiveBuffer().slice();
791                            writeBuffer(input, buffer);
792                        }
793                    }
794                }).bind("blur.inputmask", function () {
795                    var $input = $(this), input = this, nptValue = input._valueGet();
796                    $input.removeClass('focus.inputmask');
797                    if (nptValue != undoBuffer) {
798                        $input.change();
799                    }
800                    if (opts.clearMaskOnLostFocus && nptValue != '') {
801                        if (nptValue == getActiveBuffer().join(''))
802                            input._valueSet('');
803                        else { //clearout optional tail of the mask
804                            clearOptionalTail(input, buffer);
805                        }
806                    }
807                    if (!isComplete(buffer)) {
808                        $input.trigger("incomplete");
809                        if (opts.clearIncomplete) {
810                            if (opts.clearMaskOnLostFocus)
811                                input._valueSet('');
812                            else {
813                                buffer = getActiveBuffer().slice();
814                                writeBuffer(input, buffer);
815                            }
816                        }
817                    }
818                }).bind("focus.inputmask", function () {
819                    var $input = $(this), input = this, nptValue = input._valueGet();
820                    if (opts.showMaskOnFocus && !$input.hasClass('focus.inputmask') && (!opts.showMaskOnHover || (opts.showMaskOnHover && nptValue == ''))) {
821                        var nptL = nptValue.length;
822                        if (nptL < buffer.length) {
823                            if (nptL == 0)
824                                buffer = getActiveBuffer().slice();
825                            caret(input, checkVal(input, buffer, true));
826                        }
827                    }
828                    $input.addClass('focus.inputmask');
829                    undoBuffer = input._valueGet();
830                }).bind("mouseleave.inputmask", function () {
831                    var $input = $(this), input = this;
832                    if (opts.clearMaskOnLostFocus) {
833                        if (!$input.hasClass('focus.inputmask')) {
834                            if (input._valueGet() == getActiveBuffer().join('') || input._valueGet() == '')
835                                input._valueSet('');
836                            else { //clearout optional tail of the mask
837                                clearOptionalTail(input, buffer);
838                            }
839                        }
840                    }
841                }).bind("click.inputmask", function () {
842                    var input = this;
843                    setTimeout(function () {
844                        var selectedCaret = caret(input);
845                        if (selectedCaret.begin == selectedCaret.end) {
846                            var clickPosition = selectedCaret.begin;
847                            lastPosition = checkVal(input, buffer, false);
848                            determineInputDirection(input, selectedCaret);
849                            if (isRTL)
850                                caret(input, clickPosition > lastPosition && (isValid(clickPosition, buffer[clickPosition], buffer, true, isRTL) !== false || !isMask(clickPosition)) ? clickPosition : lastPosition);
851                            else
852                                caret(input, clickPosition < lastPosition && (isValid(clickPosition, buffer[clickPosition], buffer, true, isRTL) !== false || !isMask(clickPosition)) ? clickPosition : lastPosition);
853                        }
854                    }, 0);
855                }).bind('dblclick.inputmask', function () {
856                    var input = this;
857                    setTimeout(function () {
858                        caret(input, 0, lastPosition);
859                    }, 0);
860                }).bind("keydown.inputmask", keydownEvent
861                ).bind("keypress.inputmask", keypressEvent
862                ).bind("keyup.inputmask", keyupEvent
863                ).bind(pasteEvent + ".inputmask dragdrop.inputmask drop.inputmask", function () {
864                    var input = this;
865                    setTimeout(function () {
866                        caret(input, checkVal(input, buffer, true));
867                        if (isComplete(buffer))
868                            $input.trigger("complete");
869                    }, 0);
870                }).bind('setvalue.inputmask', function () {
871                    var input = this;
872                    undoBuffer = input._valueGet();
873                    checkVal(input, buffer, true);
874                    if (input._valueGet() == getActiveBuffer().join(''))
875                        input._valueSet('');
876                }).bind('complete.inputmask', opts.oncomplete)
877                .bind('incomplete.inputmask', opts.onincomplete)
878                .bind('cleared.inputmask', opts.oncleared);
879
880                //apply mask
881                lastPosition = checkVal(el, buffer, true);
882
883                // Wrap document.activeElement in a try/catch block since IE9 throw "Unspecified error" if document.activeElement is undefined when we are in an IFrame.
884                var activeElement;
885                try {
886                    activeElement = document.activeElement;
887                } catch (e) { }
888                if (activeElement === el) { //position the caret when in focus
889                    $input.addClass('focus.inputmask');
890                    caret(el, lastPosition);
891                } else if (opts.clearMaskOnLostFocus) {
892                    if (el._valueGet() == getActiveBuffer().join('')) {
893                        el._valueSet('');
894                    } else {
895                        clearOptionalTail(el, buffer);
896                    }
897                }
898
899                installEventRuler(el);
900
901                //private functions
902                function installEventRuler(npt) {
903                    var events = $._data(npt).events;
904
905                    $.each(events, function (eventType, eventHandlers) {
906                        $.each(eventHandlers, function (ndx, eventHandler) {
907                            if (eventHandler.namespace == "inputmask") {
908                                var handler = eventHandler.handler;
909                                eventHandler.handler = function () {
910                                    if (this.readOnly || this.disabled)
911                                        return false;
912                                    return handler.apply(this, arguments);
913                                };
914                            }
915                        });
916                    });
917                }
918
919                function patchValueProperty(npt) {
920                    var valueProperty;
921                    if (Object.getOwnPropertyDescriptor)
922                        valueProperty = Object.getOwnPropertyDescriptor(npt, "value");
923                    if (valueProperty && valueProperty.get) {
924                        if (!npt._valueGet) {
925
926                            npt._valueGet = valueProperty.get;
927                            npt._valueSet = valueProperty.set;
928
929                            Object.defineProperty(npt, "value", {
930                                get: function () {
931                                    var $self = $(this), inputData = $(this).data('inputmask'), masksets = inputData['masksets'],
932                                    activeMasksetIndex = inputData['activeMasksetIndex'];
933                                    return inputData && inputData['autoUnmask'] ? $self.inputmask('unmaskedvalue') : this._valueGet() != masksets[activeMasksetIndex]['_buffer'].join('') ? this._valueGet() : '';
934                                },
935                                set: function (value) {
936                                    this._valueSet(value); $(this).triggerHandler('setvalue.inputmask');
937                                }
938                            });
939                        }
940                    } else if (document.__lookupGetter__ && npt.__lookupGetter__("value")) {
941                        if (!npt._valueGet) {
942                            npt._valueGet = npt.__lookupGetter__("value");
943                            npt._valueSet = npt.__lookupSetter__("value");
944
945                            npt.__defineGetter__("value", function () {
946                                var $self = $(this), inputData = $(this).data('inputmask'), masksets = inputData['masksets'],
947                                    activeMasksetIndex = inputData['activeMasksetIndex'];
948                                return inputData && inputData['autoUnmask'] ? $self.inputmask('unmaskedvalue') : this._valueGet() != masksets[activeMasksetIndex]['_buffer'].join('') ? this._valueGet() : '';
949                            });
950                            npt.__defineSetter__("value", function (value) {
951                                this._valueSet(value); $(this).triggerHandler('setvalue.inputmask');
952                            });
953                        }
954                    } else {
955                        if (!npt._valueGet) {
956                            npt._valueGet = function () { return this.value; }
957                            npt._valueSet = function (value) { this.value = value; }
958                        }
959                        if ($.fn.val.inputmaskpatch != true) {
960                            $.fn.val = function () {
961                                if (arguments.length == 0) {
962                                    var $self = $(this);
963                                    if ($self.data('inputmask')) {
964                                        if ($self.data('inputmask')['autoUnmask'])
965                                            return $self.inputmask('unmaskedvalue');
966                                        else {
967                                            var result = $.inputmask.val.apply($self);
968                                            var inputData = $(this).data('inputmask'), masksets = inputData['masksets'],
969                                            activeMasksetIndex = inputData['activeMasksetIndex'];
970                                            return result != masksets[activeMasksetIndex]['_buffer'].join('') ? result : '';
971                                        }
972                                    } else return $.inputmask.val.apply($self);
973                                } else {
974                                    var args = arguments;
975                                    return this.each(function () {
976                                        var $self = $(this);
977                                        var result = $.inputmask.val.apply($self, args);
978                                        if ($self.data('inputmask')) $self.triggerHandler('setvalue.inputmask');
979                                        return result;
980                                    });
981                                }
982                            };
983                            $.extend($.fn.val, {
984                                inputmaskpatch: true
985                            });
986                        }
987                    }
988                }
989
990                function determineInputDirection(input, pos) {
991                    //set input direction according the position to the radixPoint
992                    if (opts.numericInput && opts.radixPoint != "") {
993                        var nptStr = input._valueGet();
994                        var radixPosition = nptStr.indexOf(opts.radixPoint);
995                        isRTL = pos.begin <= radixPosition || pos.end <= radixPosition || radixPosition == -1;
996                    }
997                }
998
999                //shift chars to left from start to end and put c at end position if defined
1000                function shiftL(start, end, c) {
1001                    while (!isMask(start) && start - 1 >= 0) start--;
1002                    for (var i = start; i < end && i < getMaskLength(buffer) ; i++) {
1003                        if (isMask(i)) {
1004                            setReTargetPlaceHolder(buffer, i);
1005                            var j = seekNext(buffer, i);
1006                            var p = getBufferElement(buffer, j);
1007                            if (p != getPlaceHolder(j)) {
1008                                if (j < getMaskLength(buffer) && isValid(i, p, buffer, true, isRTL) !== false && getActiveTests()[determineTestPosition(i)].def == getActiveTests()[determineTestPosition(j)].def) {
1009                                    setBufferElement(buffer, i, getBufferElement(buffer, j));
1010                                    setReTargetPlaceHolder(buffer, j); //cleanup next position
1011                                } else {
1012                                    if (isMask(i))
1013                                        break;
1014                                }
1015                            } else if (c == undefined) break;
1016                        } else {
1017                            setReTargetPlaceHolder(buffer, i);
1018                        }
1019                    }
1020                    if (c != undefined)
1021                        setBufferElement(buffer, isRTL ? end : seekPrevious(buffer, end), c);
1022
1023                    buffer = truncateInput(buffer.join(''), isRTL).split('');
1024                    if (buffer.length == 0) buffer = getActiveBuffer().slice();
1025
1026                    return start; //return the used start position
1027                }
1028                function shiftR(start, end, c, full) { //full => behave like a push right ~ do not stop on placeholders
1029                    for (var i = start; i <= end && i < getMaskLength(buffer) ; i++) {
1030                        if (isMask(i)) {
1031                            var t = getBufferElement(buffer, i);
1032                            setBufferElement(buffer, i, c);
1033                            if (t != getPlaceHolder(i)) {
1034                                var j = seekNext(buffer, i);
1035                                if (j < getMaskLength(buffer)) {
1036                                    if (isValid(j, t, buffer, true, isRTL) !== false && getActiveTests()[determineTestPosition(i)].def == getActiveTests()[determineTestPosition(j)].def)
1037                                        c = t;
1038                                    else {
1039                                        if (isMask(j))
1040                                            break;
1041                                        else c = t;
1042                                    }
1043                                } else break;
1044                            } else if (full !== true) break;
1045                        } else
1046                            setReTargetPlaceHolder(buffer, i);
1047                    }
1048                    var lengthBefore = buffer.length;
1049                    buffer = truncateInput(buffer.join(''), isRTL).split('');
1050                    if (buffer.length == 0) buffer = getActiveBuffer().slice();
1051
1052                    return end - (lengthBefore - buffer.length);  //return new start position
1053                };
1054
1055                function keydownEvent(e) {
1056                    //Safari 5.1.x - modal dialog fires keypress twice workaround
1057                    skipKeyPressEvent = false;
1058
1059                    var input = this, k = e.keyCode, pos = caret(input);
1060
1061                    determineInputDirection(input, pos);
1062
1063                    //backspace, delete, and escape get special treatment
1064                    if (k == opts.keyCode.BACKSPACE || k == opts.keyCode.DELETE || (iphone && k == 127)) {//backspace/delete
1065                        var maskL = getMaskLength(buffer);
1066                        if (pos.begin == 0 && pos.end == maskL) { //remove full selection
1067                            activeMasksetIndex = 0; //reset activemask
1068                            buffer = getActiveBuffer().slice();
1069                            writeBuffer(input, buffer);
1070                            caret(input, checkVal(input, buffer, false));
1071                        } else if ((pos.end - pos.begin) > 1 || ((pos.end - pos.begin) == 1 && opts.insertMode)) { //partial selection
1072                            clearBuffer(buffer, pos.begin, pos.end);
1073                            determineActiveMasksetIndex(buffer, pos.begin, activeMasksetIndex);
1074                            writeBuffer(input, buffer, isRTL ? checkVal(input, buffer, false) : pos.begin);
1075                        } else { //handle delete
1076                            var beginPos = pos.begin;
1077                            if (k == opts.keyCode.DELETE) {
1078                                if (beginPos < firstMaskPos)
1079                                    beginPos = firstMaskPos;
1080                                if (beginPos < maskL) {
1081                                    if (opts.numericInput && opts.radixPoint != "" && buffer[beginPos] == opts.radixPoint) {
1082                                        beginPos = (buffer.length - 1 == beginPos) /* radixPoint is latest? delete it */ ? beginPos : seekNext(buffer, beginPos);
1083                                        beginPos = shiftL(beginPos, maskL);
1084                                    } else {
1085                                        if (isRTL) {
1086                                            beginPos = shiftR(firstMaskPos, beginPos, getPlaceHolder(beginPos), true);
1087                                            beginPos = seekNext(buffer, beginPos);
1088                                        } else {
1089                                            beginPos = shiftL(beginPos, maskL);
1090                                        }
1091                                    }
1092                                    determineActiveMasksetIndex(buffer, beginPos, activeMasksetIndex);
1093                                    writeBuffer(input, buffer, beginPos);
1094                                }
1095                            } else if (k == opts.keyCode.BACKSPACE) { //handle backspace
1096                                if (beginPos > firstMaskPos) {
1097                                    beginPos -= 1;
1098                                    if (opts.numericInput && opts.radixPoint != "" && buffer[beginPos] == opts.radixPoint) {
1099                                        beginPos = shiftR(firstMaskPos, (buffer.length - 1 == beginPos) /* radixPoint is latest? delete it */ ? beginPos : beginPos - 1, getPlaceHolder(beginPos), true);
1100                                        beginPos++;
1101                                    } else {
1102                                        if (isRTL) {
1103                                            beginPos = shiftR(firstMaskPos, beginPos, getPlaceHolder(beginPos), true);
1104                                            beginPos = buffer[beginPos + 1] == opts.radixPoint ? beginPos + 1 : seekNext(buffer, beginPos);
1105                                        } else {
1106                                            beginPos = shiftL(beginPos, maskL);
1107                                        }
1108                                    }
1109                                    determineActiveMasksetIndex(buffer, beginPos, activeMasksetIndex);
1110                                    writeBuffer(input, buffer, beginPos);
1111                                }
1112                            }
1113                        }
1114                        if (input._valueGet() == getActiveBuffer().join(''))
1115                            $(input).trigger('cleared');
1116
1117                        e.preventDefault(); //stop default action but allow propagation
1118                    } else if (k == opts.keyCode.END || k == opts.keyCode.PAGE_DOWN) { //when END or PAGE_DOWN pressed set position at lastmatch
1119                        setTimeout(function () {
1120                            var caretPos = checkVal(input, buffer, false, true);
1121                            if (!opts.insertMode && caretPos == getMaskLength(buffer) && !e.shiftKey) caretPos--;
1122                            caret(input, e.shiftKey ? pos.begin : caretPos, caretPos);
1123                        }, 0);
1124                    } else if (k == opts.keyCode.HOME || k == opts.keyCode.PAGE_UP) {//Home or page_up
1125                        caret(input, 0, e.shiftKey ? pos.begin : 0);
1126                    }
1127                    else if (k == opts.keyCode.ESCAPE) {//escape
1128                        input._valueSet(undoBuffer);
1129                        caret(input, 0, checkVal(input, buffer));
1130                    } else if (k == opts.keyCode.INSERT) {//insert
1131                        opts.insertMode = !opts.insertMode;
1132                        caret(input, !opts.insertMode && pos.begin == getMaskLength(buffer) ? pos.begin - 1 : pos.begin);
1133                    } else if (e.ctrlKey && k == 88) {
1134                        setTimeout(function () {
1135                            caret(input, checkVal(input, buffer, true));
1136                        }, 0);
1137                    } else if (!opts.insertMode) { //overwritemode
1138                        if (k == opts.keyCode.RIGHT) {//right
1139                            var caretPos = pos.begin == pos.end ? pos.end + 1 : pos.end;
1140                            caretPos = caretPos < getMaskLength(buffer) ? caretPos : pos.end;
1141                            caret(input, e.shiftKey ? pos.begin : caretPos, e.shiftKey ? caretPos + 1 : caretPos);
1142                        } else if (k == opts.keyCode.LEFT) {//left
1143                            var caretPos = pos.begin - 1;
1144                            caretPos = caretPos > 0 ? caretPos : 0;
1145                            caret(input, caretPos, e.shiftKey ? pos.end : caretPos);
1146                        }
1147                    }
1148
1149                    opts.onKeyDown.call(this, e, buffer, opts); //extra stuff to execute on keydown
1150                    ignorable = $.inArray(k, opts.ignorables) != -1;
1151                }
1152
1153                function keypressEvent(e) {
1154                    //Safari 5.1.x - modal dialog fires keypress twice workaround
1155                    if (skipKeyPressEvent) return false;
1156                    skipKeyPressEvent = true;
1157
1158                    var input = this, $input = $(input);
1159
1160                    e = e || window.event;
1161                    var k = e.which || e.charCode || e.keyCode,
1162                        c = String.fromCharCode(k);
1163
1164                    if (opts.numericInput && c == opts.radixPoint) {
1165                        var nptStr = input._valueGet();
1166                        var radixPosition = nptStr.indexOf(opts.radixPoint);
1167                        caret(input, seekNext(buffer, radixPosition != -1 ? radixPosition : getMaskLength(buffer)));
1168                    }
1169
1170                    if (e.ctrlKey || e.altKey || e.metaKey || ignorable) {
1171                        return true;
1172                    } else {
1173                        if (k) {
1174                            $input.trigger('input');
1175
1176                            var pos = caret(input), maskL = getMaskLength(buffer), writeOutBuffer = true;
1177                            clearBuffer(buffer, pos.begin, pos.end);
1178
1179                            if (isRTL) {
1180                                var p = seekPrevious(buffer, pos.end), np;
1181                                if ((np = isValid(p == maskL || getBufferElement(buffer, p) == opts.radixPoint ? seekPrevious(buffer, p) : p, c, buffer, false, isRTL)) !== false) {
1182                                    var refresh = false;
1183                                    if (np !== true) {
1184                                        refresh = np["refresh"]; //only rewrite buffer from isValid
1185                                        p = np.pos != undefined ? np.pos : p; //set new position from isValid
1186                                        c = np.c != undefined ? np.c : c; //set new char from isValid
1187                                    }
1188                                    if (refresh !== true) {
1189                                        maskL = getMaskLength(buffer); //update masklength to include possible groupSeparator offset
1190                                        var firstUnmaskedPosition = firstMaskPos;
1191                                        if (opts.insertMode == true) {
1192                                            if (getActiveMaskSet()['greedy'] == true) {
1193                                                var bfrClone = buffer.slice();
1194                                                while (getBufferElement(bfrClone, firstUnmaskedPosition, true) != getPlaceHolder(firstUnmaskedPosition) && firstUnmaskedPosition <= p) {
1195                                                    firstUnmaskedPosition = firstUnmaskedPosition == maskL ? (maskL + 1) : seekNext(buffer, firstUnmaskedPosition);
1196                                                }
1197                                            }
1198                                            if (firstUnmaskedPosition <= p && (getActiveMaskSet()['greedy'] || buffer.length < maskL)) {
1199                                                if (buffer[firstMaskPos] != getPlaceHolder(firstMaskPos) && buffer.length < maskL) {
1200                                                    var offset = prepareBuffer(buffer, -1, isRTL);
1201                                                    if (pos.end != 0) p = p + offset;
1202                                                    maskL = buffer.length;
1203                                                }
1204                                                shiftL(firstUnmaskedPosition, p, c);
1205                                            } else writeOutBuffer = false;
1206                                        } else setBufferElement(buffer, p, c);
1207                                    }
1208
1209                                    if (writeOutBuffer) {
1210                                        writeBuffer(input, buffer, opts.numericInput ? p + 1 : p);
1211                                        setTimeout(function () { //timeout needed for IE
1212                                            if (isComplete(buffer))
1213                                                $input.trigger("complete");
1214                                        }, 0);
1215                                    }
1216                                } else if (android) writeBuffer(input, buffer, pos.begin);
1217                            }
1218                            else {
1219                                var p = seekNext(buffer, pos.begin - 1), np;
1220                                prepareBuffer(buffer, p, isRTL);
1221                                if ((np = isValid(p, c, buffer, false, isRTL)) !== false) {
1222                                    var refresh = false;
1223                                    if (np !== true) {
1224                                        refresh = np["refresh"]; //only rewrite buffer from isValid
1225                                        p = np.pos != undefined ? np.pos : p; //set new position from isValid
1226                                        c = np.c != undefined ? np.c : c; //set new char from isValid
1227                                    }
1228                                    if (refresh !== true) {
1229                                        if (opts.insertMode == true) {
1230                                            var lastUnmaskedPosition = getMaskLength(buffer);
1231                                            var bfrClone = buffer.slice();
1232                                            while (getBufferElement(bfrClone, lastUnmaskedPosition, true) != getPlaceHolder(lastUnmaskedPosition) && lastUnmaskedPosition >= p) {
1233                                                lastUnmaskedPosition = lastUnmaskedPosition == 0 ? -1 : seekPrevious(buffer, lastUnmaskedPosition);
1234                                            }
1235                                            if (lastUnmaskedPosition >= p)
1236                                                shiftR(p, buffer.length, c);
1237                                            else writeOutBuffer = false;
1238                                        } else setBufferElement(buffer, p, c);
1239                                    }
1240                                    if (writeOutBuffer) {
1241                                        var next = seekNext(buffer, p);
1242                                        writeBuffer(input, buffer, next);
1243
1244                                        setTimeout(function () { //timeout needed for IE
1245                                            if (isComplete(buffer))
1246                                                $input.trigger("complete");
1247                                        }, 0);
1248                                    }
1249                                } else if (android) writeBuffer(input, buffer, pos.begin);
1250                            }
1251                            e.preventDefault();
1252                        }
1253                    }
1254                }
1255
1256                function keyupEvent(e) {
1257                    var $input = $(this), input = this;
1258                    var k = e.keyCode;
1259                    opts.onKeyUp.call(this, e, buffer, opts); //extra stuff to execute on keyup
1260                    if (k == opts.keyCode.TAB && $input.hasClass('focus.inputmask') && input._valueGet().length == 0 && opts.showMaskOnFocus) {
1261                        buffer = getActiveBuffer().slice();
1262                        writeBuffer(input, buffer);
1263                        if (!isRTL) caret(input, 0);
1264                        undoBuffer = input._valueGet();
1265                    }
1266                }
1267            }
1268
1269            return this; //return this to expose publics
1270        };
1271    }
1272})(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.