jquery-inputmask-rails 2.0.1 → 2.5.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: ae89110e71f88ab05d14ddef77c04fdd42ebd754
4
+ data.tar.gz: 22e209a41b45cb097d9f382e68fb00f09d547412
5
+ SHA512:
6
+ metadata.gz: bc17ced2ce15653409fe1003aac3b4ff4deb29c998f6339416533ead45d3907938afe259872ab16bf5ccfb44f0b15153acd60bf96cffb9f5d152de11a0842158
7
+ data.tar.gz: 768046dc6db59d732a977c7aa69ae7d25ecd2c34ff22a9a321da30914021f0aaf27f16ecc813864f47217ea86c46a7966a388b0ad3b97bc91e0d01457ae3dafe
@@ -1,7 +1,7 @@
1
1
  module Jquery
2
2
  module Inputmask
3
3
  module Rails
4
- VERSION = "2.0.1"
4
+ VERSION = "2.5.5"
5
5
  end
6
6
  end
7
7
  end
@@ -0,0 +1,2727 @@
1
+ /**
2
+ * @license Input Mask plugin for jquery
3
+ * http://github.com/RobinHerbots/jquery.inputmask
4
+ * Copyright (c) 2010 - 2014 Robin Herbots
5
+ * Licensed under the MIT license (http://www.opensource.org/licenses/mit-license.php)
6
+ * Version: 2.5.5
7
+ */
8
+
9
+ (function ($) {
10
+ if ($.fn.inputmask === undefined) {
11
+ //helper functions
12
+ function isInputEventSupported(eventName) {
13
+ var el = document.createElement('input'),
14
+ eventName = 'on' + eventName,
15
+ isSupported = (eventName in el);
16
+ if (!isSupported) {
17
+ el.setAttribute(eventName, 'return;');
18
+ isSupported = typeof el[eventName] == 'function';
19
+ }
20
+ el = null;
21
+ return isSupported;
22
+ }
23
+ function resolveAlias(aliasStr, options, opts) {
24
+ var aliasDefinition = opts.aliases[aliasStr];
25
+ if (aliasDefinition) {
26
+ if (aliasDefinition.alias) resolveAlias(aliasDefinition.alias, undefined, opts); //alias is another alias
27
+ $.extend(true, opts, aliasDefinition); //merge alias definition in the options
28
+ $.extend(true, opts, options); //reapply extra given options
29
+ return true;
30
+ }
31
+ return false;
32
+ }
33
+ function generateMaskSets(opts) {
34
+ var ms = [];
35
+ var genmasks = []; //used to keep track of the masks that where processed, to avoid duplicates
36
+ function getMaskTemplate(mask) {
37
+ if (opts.numericInput) {
38
+ mask = mask.split('').reverse().join('');
39
+ }
40
+ var escaped = false, outCount = 0, greedy = opts.greedy, repeat = opts.repeat;
41
+ if (repeat == "*") greedy = false;
42
+ //if (greedy == true && opts.placeholder == "") opts.placeholder = " ";
43
+ if (mask.length == 1 && greedy == false && repeat != 0) { opts.placeholder = ""; } //hide placeholder with single non-greedy mask
44
+ var singleMask = $.map(mask.split(""), function (element, index) {
45
+ var outElem = [];
46
+ if (element == opts.escapeChar) {
47
+ escaped = true;
48
+ }
49
+ else if ((element != opts.optionalmarker.start && element != opts.optionalmarker.end) || escaped) {
50
+ var maskdef = opts.definitions[element];
51
+ if (maskdef && !escaped) {
52
+ for (var i = 0; i < maskdef.cardinality; i++) {
53
+ outElem.push(opts.placeholder.charAt((outCount + i) % opts.placeholder.length));
54
+ }
55
+ } else {
56
+ outElem.push(element);
57
+ escaped = false;
58
+ }
59
+ outCount += outElem.length;
60
+ return outElem;
61
+ }
62
+ });
63
+
64
+ //allocate repetitions
65
+ var repeatedMask = singleMask.slice();
66
+ for (var i = 1; i < repeat && greedy; i++) {
67
+ repeatedMask = repeatedMask.concat(singleMask.slice());
68
+ }
69
+
70
+ return { "mask": repeatedMask, "repeat": repeat, "greedy": greedy };
71
+ }
72
+ //test definition => {fn: RegExp/function, cardinality: int, optionality: bool, newBlockMarker: bool, offset: int, casing: null/upper/lower, def: definitionSymbol}
73
+ function getTestingChain(mask) {
74
+ if (opts.numericInput) {
75
+ mask = mask.split('').reverse().join('');
76
+ }
77
+ var isOptional = false, escaped = false;
78
+ var newBlockMarker = false; //indicates wheter the begin/ending of a block should be indicated
79
+
80
+ return $.map(mask.split(""), function (element, index) {
81
+ var outElem = [];
82
+
83
+ if (element == opts.escapeChar) {
84
+ escaped = true;
85
+ } else if (element == opts.optionalmarker.start && !escaped) {
86
+ isOptional = true;
87
+ newBlockMarker = true;
88
+ }
89
+ else if (element == opts.optionalmarker.end && !escaped) {
90
+ isOptional = false;
91
+ newBlockMarker = true;
92
+ }
93
+ else {
94
+ var maskdef = opts.definitions[element];
95
+ if (maskdef && !escaped) {
96
+ var prevalidators = maskdef["prevalidator"], prevalidatorsL = prevalidators ? prevalidators.length : 0;
97
+ for (var i = 1; i < maskdef.cardinality; i++) {
98
+ var prevalidator = prevalidatorsL >= i ? prevalidators[i - 1] : [], validator = prevalidator["validator"], cardinality = prevalidator["cardinality"];
99
+ 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: maskdef["definitionSymbol"] || element });
100
+ if (isOptional == true) //reset newBlockMarker
101
+ newBlockMarker = false;
102
+ }
103
+ 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: maskdef["definitionSymbol"] || element });
104
+ } else {
105
+ outElem.push({ fn: null, cardinality: 0, optionality: isOptional, newBlockMarker: newBlockMarker, offset: 0, casing: null, def: element });
106
+ escaped = false;
107
+ }
108
+ //reset newBlockMarker
109
+ newBlockMarker = false;
110
+ return outElem;
111
+ }
112
+ });
113
+ }
114
+ function markOptional(maskPart) { //needed for the clearOptionalTail functionality
115
+ return opts.optionalmarker.start + maskPart + opts.optionalmarker.end;
116
+ }
117
+ function splitFirstOptionalEndPart(maskPart) {
118
+ var optionalStartMarkers = 0, optionalEndMarkers = 0, mpl = maskPart.length;
119
+ for (var i = 0; i < mpl; i++) {
120
+ if (maskPart.charAt(i) == opts.optionalmarker.start) {
121
+ optionalStartMarkers++;
122
+ }
123
+ if (maskPart.charAt(i) == opts.optionalmarker.end) {
124
+ optionalEndMarkers++;
125
+ }
126
+ if (optionalStartMarkers > 0 && optionalStartMarkers == optionalEndMarkers)
127
+ break;
128
+ }
129
+ var maskParts = [maskPart.substring(0, i)];
130
+ if (i < mpl) {
131
+ maskParts.push(maskPart.substring(i + 1, mpl));
132
+ }
133
+ return maskParts;
134
+ }
135
+ function splitFirstOptionalStartPart(maskPart) {
136
+ var mpl = maskPart.length;
137
+ for (var i = 0; i < mpl; i++) {
138
+ if (maskPart.charAt(i) == opts.optionalmarker.start) {
139
+ break;
140
+ }
141
+ }
142
+ var maskParts = [maskPart.substring(0, i)];
143
+ if (i < mpl) {
144
+ maskParts.push(maskPart.substring(i + 1, mpl));
145
+ }
146
+ return maskParts;
147
+ }
148
+ function generateMask(maskPrefix, maskPart, metadata) {
149
+ var maskParts = splitFirstOptionalEndPart(maskPart);
150
+ var newMask, maskTemplate;
151
+
152
+ var masks = splitFirstOptionalStartPart(maskParts[0]);
153
+ if (masks.length > 1) {
154
+ newMask = maskPrefix + masks[0] + markOptional(masks[1]) + (maskParts.length > 1 ? maskParts[1] : "");
155
+ if ($.inArray(newMask, genmasks) == -1 && newMask != "") {
156
+ genmasks.push(newMask);
157
+ maskTemplate = getMaskTemplate(newMask);
158
+ ms.push({
159
+ "mask": newMask,
160
+ "_buffer": maskTemplate["mask"],
161
+ "buffer": maskTemplate["mask"].slice(),
162
+ "tests": getTestingChain(newMask),
163
+ "lastValidPosition": -1,
164
+ "greedy": maskTemplate["greedy"],
165
+ "repeat": maskTemplate["repeat"],
166
+ "metadata": metadata
167
+ });
168
+ }
169
+ newMask = maskPrefix + masks[0] + (maskParts.length > 1 ? maskParts[1] : "");
170
+ if ($.inArray(newMask, genmasks) == -1 && newMask != "") {
171
+ genmasks.push(newMask);
172
+ maskTemplate = getMaskTemplate(newMask);
173
+ ms.push({
174
+ "mask": newMask,
175
+ "_buffer": maskTemplate["mask"],
176
+ "buffer": maskTemplate["mask"].slice(),
177
+ "tests": getTestingChain(newMask),
178
+ "lastValidPosition": -1,
179
+ "greedy": maskTemplate["greedy"],
180
+ "repeat": maskTemplate["repeat"],
181
+ "metadata": metadata
182
+ });
183
+ }
184
+ if (splitFirstOptionalStartPart(masks[1]).length > 1) { //optional contains another optional
185
+ generateMask(maskPrefix + masks[0], masks[1] + maskParts[1], metadata);
186
+ }
187
+ if (maskParts.length > 1 && splitFirstOptionalStartPart(maskParts[1]).length > 1) {
188
+ generateMask(maskPrefix + masks[0] + markOptional(masks[1]), maskParts[1], metadata);
189
+ generateMask(maskPrefix + masks[0], maskParts[1], metadata);
190
+ }
191
+ }
192
+ else {
193
+ newMask = maskPrefix + maskParts;
194
+ if ($.inArray(newMask, genmasks) == -1 && newMask != "") {
195
+ genmasks.push(newMask);
196
+ maskTemplate = getMaskTemplate(newMask);
197
+ ms.push({
198
+ "mask": newMask,
199
+ "_buffer": maskTemplate["mask"],
200
+ "buffer": maskTemplate["mask"].slice(),
201
+ "tests": getTestingChain(newMask),
202
+ "lastValidPosition": -1,
203
+ "greedy": maskTemplate["greedy"],
204
+ "repeat": maskTemplate["repeat"],
205
+ "metadata": metadata
206
+ });
207
+ }
208
+ }
209
+
210
+ }
211
+
212
+ if ($.isFunction(opts.mask)) { //allow mask to be a preprocessing fn - should return a valid mask
213
+ opts.mask = opts.mask.call(this, opts);
214
+ }
215
+ if ($.isArray(opts.mask)) {
216
+ $.each(opts.mask, function (ndx, msk) {
217
+ if (msk["mask"] != undefined) {
218
+ generateMask("", msk["mask"].toString(), msk);
219
+ } else
220
+ generateMask("", msk.toString());
221
+ });
222
+ } else generateMask("", opts.mask.toString());
223
+
224
+ return opts.greedy ? ms : ms.sort(function (a, b) { return a["mask"].length - b["mask"].length; });
225
+ }
226
+
227
+ var msie1x = typeof ScriptEngineMajorVersion === "function"
228
+ ? ScriptEngineMajorVersion() //IE11 detection
229
+ : new Function("/*@cc_on return @_jscript_version; @*/")() >= 10, //conditional compilation from mickeysoft trick
230
+ ua = navigator.userAgent,
231
+ iphone = ua.match(new RegExp("iphone", "i")) !== null,
232
+ android = ua.match(new RegExp("android.*safari.*", "i")) !== null,
233
+ androidchrome = ua.match(new RegExp("android.*chrome.*", "i")) !== null,
234
+ androidfirefox = ua.match(new RegExp("android.*firefox.*", "i")) !== null,
235
+ kindle = /Kindle/i.test(ua) || /Silk/i.test(ua) || /KFTT/i.test(ua) || /KFOT/i.test(ua) || /KFJWA/i.test(ua) || /KFJWI/i.test(ua) || /KFSOWI/i.test(ua) || /KFTHWA/i.test(ua) || /KFTHWI/i.test(ua) || /KFAPWA/i.test(ua) || /KFAPWI/i.test(ua),
236
+ PasteEventType = isInputEventSupported('paste') ? 'paste' : isInputEventSupported('input') ? 'input' : "propertychange";
237
+
238
+ //if (androidchrome) {
239
+ // var browser = navigator.userAgent.match(new RegExp("chrome.*", "i")),
240
+ // version = parseInt(new RegExp(/[0-9]+/).exec(browser));
241
+ // androidchrome32 = (version == 32);
242
+ //}
243
+
244
+ //masking scope
245
+ //actionObj definition see below
246
+ function maskScope(masksets, activeMasksetIndex, opts, actionObj) {
247
+ var isRTL = false,
248
+ valueOnFocus = getActiveBuffer().join(''),
249
+ $el,
250
+ skipKeyPressEvent = false, //Safari 5.1.x - modal dialog fires keypress twice workaround
251
+ skipInputEvent = false, //skip when triggered from within inputmask
252
+ ignorable = false;
253
+
254
+
255
+ //maskset helperfunctions
256
+
257
+ function getActiveMaskSet() {
258
+ return masksets[activeMasksetIndex];
259
+ }
260
+
261
+ function getActiveTests() {
262
+ return getActiveMaskSet()['tests'];
263
+ }
264
+
265
+ function getActiveBufferTemplate() {
266
+ return getActiveMaskSet()['_buffer'];
267
+ }
268
+
269
+ function getActiveBuffer() {
270
+ return getActiveMaskSet()['buffer'];
271
+ }
272
+
273
+ function isValid(pos, c, strict) { //strict true ~ no correction or autofill
274
+ strict = strict === true; //always set a value to strict to prevent possible strange behavior in the extensions
275
+
276
+ function _isValid(position, activeMaskset, c, strict) {
277
+ var testPos = determineTestPosition(position), loopend = c ? 1 : 0, chrs = '', buffer = activeMaskset["buffer"];
278
+ for (var i = activeMaskset['tests'][testPos].cardinality; i > loopend; i--) {
279
+ chrs += getBufferElement(buffer, testPos - (i - 1));
280
+ }
281
+
282
+ if (c) {
283
+ chrs += c;
284
+ }
285
+
286
+ //return is false or a json object => { pos: ??, c: ??} or true
287
+ return activeMaskset['tests'][testPos].fn != null ?
288
+ activeMaskset['tests'][testPos].fn.test(chrs, buffer, position, strict, opts)
289
+ : (c == getBufferElement(activeMaskset['_buffer'].slice(), position, true) || c == opts.skipOptionalPartCharacter) ?
290
+ { "refresh": true, c: getBufferElement(activeMaskset['_buffer'].slice(), position, true), pos: position }
291
+ : false;
292
+ }
293
+
294
+ function PostProcessResults(maskForwards, results) {
295
+ var hasValidActual = false;
296
+ $.each(results, function (ndx, rslt) {
297
+ hasValidActual = $.inArray(rslt["activeMasksetIndex"], maskForwards) == -1 && rslt["result"] !== false;
298
+ if (hasValidActual) return false;
299
+ });
300
+ if (hasValidActual) { //strip maskforwards
301
+ results = $.map(results, function (rslt, ndx) {
302
+ if ($.inArray(rslt["activeMasksetIndex"], maskForwards) == -1) {
303
+ return rslt;
304
+ } else {
305
+ masksets[rslt["activeMasksetIndex"]]["lastValidPosition"] = actualLVP;
306
+ }
307
+ });
308
+ } else { //keep maskforwards with the least forward
309
+ var lowestPos = -1, lowestIndex = -1, rsltValid;
310
+ $.each(results, function (ndx, rslt) {
311
+ if ($.inArray(rslt["activeMasksetIndex"], maskForwards) != -1 && rslt["result"] !== false & (lowestPos == -1 || lowestPos > rslt["result"]["pos"])) {
312
+ lowestPos = rslt["result"]["pos"];
313
+ lowestIndex = rslt["activeMasksetIndex"];
314
+ }
315
+ });
316
+ results = $.map(results, function (rslt, ndx) {
317
+ if ($.inArray(rslt["activeMasksetIndex"], maskForwards) != -1) {
318
+ if (rslt["result"]["pos"] == lowestPos) {
319
+ return rslt;
320
+ } else if (rslt["result"] !== false) {
321
+ for (var i = pos; i < lowestPos; i++) {
322
+ rsltValid = _isValid(i, masksets[rslt["activeMasksetIndex"]], masksets[lowestIndex]["buffer"][i], true);
323
+ if (rsltValid === false) {
324
+ masksets[rslt["activeMasksetIndex"]]["lastValidPosition"] = lowestPos - 1;
325
+ break;
326
+ } else {
327
+ setBufferElement(masksets[rslt["activeMasksetIndex"]]["buffer"], i, masksets[lowestIndex]["buffer"][i], true);
328
+ masksets[rslt["activeMasksetIndex"]]["lastValidPosition"] = i;
329
+ }
330
+ }
331
+ //also check check for the lowestpos with the new input
332
+ rsltValid = _isValid(lowestPos, masksets[rslt["activeMasksetIndex"]], c, true);
333
+ if (rsltValid !== false) {
334
+ setBufferElement(masksets[rslt["activeMasksetIndex"]]["buffer"], lowestPos, c, true);
335
+ masksets[rslt["activeMasksetIndex"]]["lastValidPosition"] = lowestPos;
336
+ }
337
+ //console.log("ndx " + rslt["activeMasksetIndex"] + " validate " + masksets[rslt["activeMasksetIndex"]]["buffer"].join('') + " lv " + masksets[rslt["activeMasksetIndex"]]['lastValidPosition']);
338
+ return rslt;
339
+ }
340
+ }
341
+ });
342
+ }
343
+ return results;
344
+ }
345
+
346
+ if (strict) {
347
+ var result = _isValid(pos, getActiveMaskSet(), c, strict); //only check validity in current mask when validating strict
348
+ if (result === true) {
349
+ result = { "pos": pos }; //always take a possible corrected maskposition into account
350
+ }
351
+ return result;
352
+ }
353
+
354
+ var results = [], result = false, currentActiveMasksetIndex = activeMasksetIndex,
355
+ actualBuffer = getActiveBuffer().slice(), actualLVP = getActiveMaskSet()["lastValidPosition"],
356
+ actualPrevious = seekPrevious(pos),
357
+ maskForwards = [];
358
+ $.each(masksets, function (index, value) {
359
+ if (typeof (value) == "object") {
360
+ activeMasksetIndex = index;
361
+
362
+ var maskPos = pos;
363
+ var lvp = getActiveMaskSet()['lastValidPosition'],
364
+ rsltValid;
365
+ if (lvp == actualLVP) {
366
+ if ((maskPos - actualLVP) > 1) {
367
+ for (var i = lvp == -1 ? 0 : lvp; i < maskPos; i++) {
368
+ rsltValid = _isValid(i, getActiveMaskSet(), actualBuffer[i], true);
369
+ if (rsltValid === false) {
370
+ break;
371
+ } else {
372
+ setBufferElement(getActiveBuffer(), i, actualBuffer[i], true);
373
+ if (rsltValid === true) {
374
+ rsltValid = { "pos": i }; //always take a possible corrected maskposition into account
375
+ }
376
+ var newValidPosition = rsltValid.pos || i;
377
+ if (getActiveMaskSet()['lastValidPosition'] < newValidPosition)
378
+ getActiveMaskSet()['lastValidPosition'] = newValidPosition; //set new position from isValid
379
+ }
380
+ }
381
+ }
382
+ //does the input match on a further position?
383
+ if (!isMask(maskPos) && !_isValid(maskPos, getActiveMaskSet(), c, strict)) {
384
+ var maxForward = seekNext(maskPos) - maskPos;
385
+ for (var fw = 0; fw < maxForward; fw++) {
386
+ if (_isValid(++maskPos, getActiveMaskSet(), c, strict) !== false)
387
+ break;
388
+ }
389
+ maskForwards.push(activeMasksetIndex);
390
+ //console.log('maskforward ' + activeMasksetIndex + " pos " + pos + " maskPos " + maskPos);
391
+ }
392
+ }
393
+
394
+ if (getActiveMaskSet()['lastValidPosition'] >= actualLVP || activeMasksetIndex == currentActiveMasksetIndex) {
395
+ if (maskPos >= 0 && maskPos < getMaskLength()) {
396
+ result = _isValid(maskPos, getActiveMaskSet(), c, strict);
397
+ if (result !== false) {
398
+ if (result === true) {
399
+ result = { "pos": maskPos }; //always take a possible corrected maskposition into account
400
+ }
401
+ var newValidPosition = result.pos || maskPos;
402
+ if (getActiveMaskSet()['lastValidPosition'] < newValidPosition)
403
+ getActiveMaskSet()['lastValidPosition'] = newValidPosition; //set new position from isValid
404
+ }
405
+ //console.log("pos " + pos + " ndx " + activeMasksetIndex + " validate " + getActiveBuffer().join('') + " lv " + getActiveMaskSet()['lastValidPosition']);
406
+ results.push({ "activeMasksetIndex": index, "result": result });
407
+ }
408
+ }
409
+ }
410
+ });
411
+ activeMasksetIndex = currentActiveMasksetIndex; //reset activeMasksetIndex
412
+
413
+ return PostProcessResults(maskForwards, results); //return results of the multiple mask validations
414
+ }
415
+
416
+ function determineActiveMasksetIndex() {
417
+ var currentMasksetIndex = activeMasksetIndex,
418
+ highestValid = { "activeMasksetIndex": 0, "lastValidPosition": -1, "next": -1 };
419
+ $.each(masksets, function (index, value) {
420
+ if (typeof (value) == "object") {
421
+ activeMasksetIndex = index;
422
+ if (getActiveMaskSet()['lastValidPosition'] > highestValid['lastValidPosition']) {
423
+ highestValid["activeMasksetIndex"] = index;
424
+ highestValid["lastValidPosition"] = getActiveMaskSet()['lastValidPosition'];
425
+ highestValid["next"] = seekNext(getActiveMaskSet()['lastValidPosition']);
426
+ } else if (getActiveMaskSet()['lastValidPosition'] == highestValid['lastValidPosition'] &&
427
+ (highestValid['next'] == -1 || highestValid['next'] > seekNext(getActiveMaskSet()['lastValidPosition']))) {
428
+ highestValid["activeMasksetIndex"] = index;
429
+ highestValid["lastValidPosition"] = getActiveMaskSet()['lastValidPosition'];
430
+ highestValid["next"] = seekNext(getActiveMaskSet()['lastValidPosition']);
431
+ }
432
+ }
433
+ });
434
+
435
+ activeMasksetIndex = highestValid["lastValidPosition"] != -1 && masksets[currentMasksetIndex]["lastValidPosition"] == highestValid["lastValidPosition"] ? currentMasksetIndex : highestValid["activeMasksetIndex"];
436
+ if (currentMasksetIndex != activeMasksetIndex) {
437
+ clearBuffer(getActiveBuffer(), seekNext(highestValid["lastValidPosition"]), getMaskLength());
438
+ getActiveMaskSet()["writeOutBuffer"] = true;
439
+ }
440
+ $el.data('_inputmask')['activeMasksetIndex'] = activeMasksetIndex; //store the activeMasksetIndex
441
+ }
442
+
443
+ function isMask(pos) {
444
+ var testPos = determineTestPosition(pos);
445
+ var test = getActiveTests()[testPos];
446
+
447
+ return test != undefined ? test.fn : false;
448
+ }
449
+
450
+ function determineTestPosition(pos) {
451
+ return pos % getActiveTests().length;
452
+ }
453
+
454
+ function getMaskLength() {
455
+ var buffer=getActiveBufferTemplate(), greedy=getActiveMaskSet()['greedy'], repeat=getActiveMaskSet()['repeat'], currentBuffer=getActiveBuffer();
456
+
457
+ if($.isFunction(opts.getMaskLength)) return opts.getMaskLength(buffer, greedy, repeat, currentBuffer, opts);
458
+
459
+ var calculatedLength = buffer.length;
460
+ if (!greedy) {
461
+ if (repeat == "*") {
462
+ calculatedLength = currentBuffer.length + 1;
463
+ } else if (repeat > 1) {
464
+ calculatedLength += (buffer.length * (repeat - 1));
465
+ }
466
+ }
467
+ return calculatedLength;
468
+ }
469
+
470
+ //pos: from position
471
+
472
+ function seekNext(pos) {
473
+ var maskL = getMaskLength();
474
+ if (pos >= maskL) return maskL;
475
+ var position = pos;
476
+ while (++position < maskL && !isMask(position)) {
477
+ }
478
+ return position;
479
+ }
480
+
481
+ //pos: from position
482
+
483
+ function seekPrevious(pos) {
484
+ var position = pos;
485
+ if (position <= 0) return 0;
486
+
487
+ while (--position > 0 && !isMask(position)) {
488
+ }
489
+ ;
490
+ return position;
491
+ }
492
+
493
+ function setBufferElement(buffer, position, element, autoPrepare) {
494
+ if (autoPrepare) position = prepareBuffer(buffer, position);
495
+
496
+ var test = getActiveTests()[determineTestPosition(position)];
497
+ var elem = element;
498
+ if (elem != undefined && test != undefined) {
499
+ switch (test.casing) {
500
+ case "upper":
501
+ elem = element.toUpperCase();
502
+ break;
503
+ case "lower":
504
+ elem = element.toLowerCase();
505
+ break;
506
+ }
507
+ }
508
+
509
+ buffer[position] = elem;
510
+ }
511
+
512
+ function getBufferElement(buffer, position, autoPrepare) {
513
+ if (autoPrepare) position = prepareBuffer(buffer, position);
514
+ return buffer[position];
515
+ }
516
+
517
+ //needed to handle the non-greedy mask repetitions
518
+
519
+ function prepareBuffer(buffer, position) {
520
+ var j;
521
+ while (buffer[position] == undefined && buffer.length < getMaskLength()) {
522
+ j = 0;
523
+ while (getActiveBufferTemplate()[j] !== undefined) { //add a new buffer
524
+ buffer.push(getActiveBufferTemplate()[j++]);
525
+ }
526
+ }
527
+
528
+ return position;
529
+ }
530
+
531
+ function writeBuffer(input, buffer, caretPos) {
532
+ input._valueSet(buffer.join(''));
533
+ if (caretPos != undefined) {
534
+ caret(input, caretPos);
535
+ }
536
+ }
537
+
538
+ function clearBuffer(buffer, start, end, stripNomasks) {
539
+ for (var i = start, maskL = getMaskLength() ; i < end && i < maskL; i++) {
540
+ if (stripNomasks === true) {
541
+ if (!isMask(i))
542
+ setBufferElement(buffer, i, "");
543
+ } else
544
+ setBufferElement(buffer, i, getBufferElement(getActiveBufferTemplate().slice(), i, true));
545
+ }
546
+ }
547
+
548
+ function setReTargetPlaceHolder(buffer, pos) {
549
+ var testPos = determineTestPosition(pos);
550
+ setBufferElement(buffer, pos, getBufferElement(getActiveBufferTemplate(), testPos));
551
+ }
552
+
553
+ function getPlaceHolder(pos) {
554
+ return opts.placeholder.charAt(pos % opts.placeholder.length);
555
+ }
556
+
557
+ function checkVal(input, writeOut, strict, nptvl, intelliCheck) {
558
+ var inputValue = nptvl != undefined ? nptvl.slice() : truncateInput(input._valueGet()).split('');
559
+
560
+ $.each(masksets, function (ndx, ms) {
561
+ if (typeof (ms) == "object") {
562
+ ms["buffer"] = ms["_buffer"].slice();
563
+ ms["lastValidPosition"] = -1;
564
+ ms["p"] = -1;
565
+ }
566
+ });
567
+ if (strict !== true) activeMasksetIndex = 0;
568
+ if (writeOut) input._valueSet(""); //initial clear
569
+ var ml = getMaskLength();
570
+ $.each(inputValue, function (ndx, charCode) {
571
+ if (intelliCheck === true) {
572
+ var p = getActiveMaskSet()["p"], lvp = p == -1 ? p : seekPrevious(p),
573
+ pos = lvp == -1 ? ndx : seekNext(lvp);
574
+ if ($.inArray(charCode, getActiveBufferTemplate().slice(lvp + 1, pos)) == -1) {
575
+ keypressEvent.call(input, undefined, true, charCode.charCodeAt(0), writeOut, strict, ndx);
576
+ }
577
+ } else {
578
+ keypressEvent.call(input, undefined, true, charCode.charCodeAt(0), writeOut, strict, ndx);
579
+ strict = strict || (ndx > 0 && ndx > getActiveMaskSet()["p"]);
580
+ }
581
+ });
582
+
583
+ if (strict === true && getActiveMaskSet()["p"] != -1) {
584
+ getActiveMaskSet()["lastValidPosition"] = seekPrevious(getActiveMaskSet()["p"]);
585
+ }
586
+ }
587
+
588
+ function escapeRegex(str) {
589
+ return $.inputmask.escapeRegex.call(this, str);
590
+ }
591
+
592
+ function truncateInput(inputValue) {
593
+ return inputValue.replace(new RegExp("(" + escapeRegex(getActiveBufferTemplate().join('')) + ")*$"), "");
594
+ }
595
+
596
+ function clearOptionalTail(input) {
597
+ var buffer = getActiveBuffer(), tmpBuffer = buffer.slice(), testPos, pos;
598
+ for (var pos = tmpBuffer.length - 1; pos >= 0; pos--) {
599
+ var testPos = determineTestPosition(pos);
600
+ if (getActiveTests()[testPos].optionality) {
601
+ if (!isMask(pos) || !isValid(pos, buffer[pos], true))
602
+ tmpBuffer.pop();
603
+ else break;
604
+ } else break;
605
+ }
606
+ writeBuffer(input, tmpBuffer);
607
+ }
608
+
609
+ function unmaskedvalue($input, skipDatepickerCheck) {
610
+ if (getActiveTests() && (skipDatepickerCheck === true || !$input.hasClass('hasDatepicker'))) {
611
+ var umValue = $.map(getActiveBuffer(), function (element, index) {
612
+ return isMask(index) && isValid(index, element, true) ? element : null;
613
+ });
614
+ var unmaskedValue = (isRTL ? umValue.reverse() : umValue).join('');
615
+ return $.isFunction(opts.onUnMask) ? opts.onUnMask.call($input, getActiveBuffer().join(''), unmaskedValue, opts) : unmaskedValue;
616
+ } else {
617
+ return $input[0]._valueGet();
618
+ }
619
+ }
620
+
621
+ function TranslatePosition(pos) {
622
+ if (isRTL && typeof pos == 'number' && (!opts.greedy || opts.placeholder != "")) {
623
+ var bffrLght = getActiveBuffer().length;
624
+ pos = bffrLght - pos;
625
+ }
626
+ return pos;
627
+ }
628
+
629
+ function caret(input, begin, end) {
630
+ var npt = input.jquery && input.length > 0 ? input[0] : input, range;
631
+ if (typeof begin == 'number') {
632
+ begin = TranslatePosition(begin);
633
+ end = TranslatePosition(end);
634
+ if (!$(npt).is(':visible')) {
635
+ return;
636
+ }
637
+ end = (typeof end == 'number') ? end : begin;
638
+ npt.scrollLeft = npt.scrollWidth;
639
+ if (opts.insertMode == false && begin == end) end++; //set visualization for insert/overwrite mode
640
+ if (npt.setSelectionRange) {
641
+ npt.selectionStart = begin;
642
+ npt.selectionEnd = end;
643
+
644
+ } else if (npt.createTextRange) {
645
+ range = npt.createTextRange();
646
+ range.collapse(true);
647
+ range.moveEnd('character', end);
648
+ range.moveStart('character', begin);
649
+ range.select();
650
+ }
651
+ } else {
652
+ if (!$(input).is(':visible')) {
653
+ return { "begin": 0, "end": 0 };
654
+ }
655
+ if (npt.setSelectionRange) {
656
+ begin = npt.selectionStart;
657
+ end = npt.selectionEnd;
658
+ } else if (document.selection && document.selection.createRange) {
659
+ range = document.selection.createRange();
660
+ begin = 0 - range.duplicate().moveStart('character', -100000);
661
+ end = begin + range.text.length;
662
+ }
663
+ begin = TranslatePosition(begin);
664
+ end = TranslatePosition(end);
665
+ return { "begin": begin, "end": end };
666
+ }
667
+ }
668
+
669
+ function isComplete(buffer) { //return true / false / undefined (repeat *)
670
+ if($.isFunction(opts.isComplete)) return opts.isComplete.call($el, buffer, opts);
671
+ if (opts.repeat == "*") return undefined;
672
+ var complete = false, highestValidPosition = 0, currentActiveMasksetIndex = activeMasksetIndex;
673
+ $.each(masksets, function (ndx, ms) {
674
+ if (typeof (ms) == "object") {
675
+ activeMasksetIndex = ndx;
676
+ var aml = seekPrevious(getMaskLength());
677
+ if (ms["lastValidPosition"] >= highestValidPosition && ms["lastValidPosition"] == aml) {
678
+ var msComplete = true;
679
+ for (var i = 0; i <= aml; i++) {
680
+ var mask = isMask(i), testPos = determineTestPosition(i);
681
+ if ((mask && (buffer[i] == undefined || buffer[i] == getPlaceHolder(i))) || (!mask && buffer[i] != getActiveBufferTemplate()[testPos])) {
682
+ msComplete = false;
683
+ break;
684
+ }
685
+ }
686
+ complete = complete || msComplete;
687
+ if (complete) //break loop
688
+ return false;
689
+ }
690
+ highestValidPosition = ms["lastValidPosition"];
691
+ }
692
+ });
693
+ activeMasksetIndex = currentActiveMasksetIndex; //reset activeMaskset
694
+ return complete;
695
+ }
696
+
697
+ function isSelection(begin, end) {
698
+ return isRTL ? (begin - end) > 1 || ((begin - end) == 1 && opts.insertMode) :
699
+ (end - begin) > 1 || ((end - begin) == 1 && opts.insertMode);
700
+ }
701
+
702
+
703
+ //private functions
704
+ function installEventRuler(npt) {
705
+ var events = $._data(npt).events;
706
+
707
+ $.each(events, function (eventType, eventHandlers) {
708
+ $.each(eventHandlers, function (ndx, eventHandler) {
709
+ if (eventHandler.namespace == "inputmask") {
710
+ if (eventHandler.type != "setvalue") {
711
+ var handler = eventHandler.handler;
712
+ eventHandler.handler = function (e) {
713
+ if (this.readOnly || this.disabled)
714
+ e.preventDefault;
715
+ else
716
+ return handler.apply(this, arguments);
717
+ };
718
+ }
719
+ }
720
+ });
721
+ });
722
+ }
723
+
724
+ function patchValueProperty(npt) {
725
+ function PatchValhook(type) {
726
+ if ($.valHooks[type] == undefined || $.valHooks[type].inputmaskpatch != true) {
727
+ var valueGet = $.valHooks[type] && $.valHooks[type].get ? $.valHooks[type].get : function (elem) { return elem.value; };
728
+ var valueSet = $.valHooks[type] && $.valHooks[type].set ? $.valHooks[type].set : function (elem, value) {
729
+ elem.value = value;
730
+ return elem;
731
+ };
732
+
733
+ $.valHooks[type] = {
734
+ get: function (elem) {
735
+ var $elem = $(elem);
736
+ if ($elem.data('_inputmask')) {
737
+ if ($elem.data('_inputmask')['opts'].autoUnmask)
738
+ return $elem.inputmask('unmaskedvalue');
739
+ else {
740
+ var result = valueGet(elem),
741
+ inputData = $elem.data('_inputmask'), masksets = inputData['masksets'],
742
+ activeMasksetIndex = inputData['activeMasksetIndex'];
743
+ return result != masksets[activeMasksetIndex]['_buffer'].join('') ? result : '';
744
+ }
745
+ } else return valueGet(elem);
746
+ },
747
+ set: function (elem, value) {
748
+ var $elem = $(elem);
749
+ var result = valueSet(elem, value);
750
+ if ($elem.data('_inputmask')) $elem.triggerHandler('setvalue.inputmask');
751
+ return result;
752
+ },
753
+ inputmaskpatch: true
754
+ };
755
+ }
756
+ }
757
+ var valueProperty;
758
+ if (Object.getOwnPropertyDescriptor)
759
+ valueProperty = Object.getOwnPropertyDescriptor(npt, "value");
760
+ if (valueProperty && valueProperty.get) {
761
+ if (!npt._valueGet) {
762
+ var valueGet = valueProperty.get;
763
+ var valueSet = valueProperty.set;
764
+ npt._valueGet = function () {
765
+ return isRTL ? valueGet.call(this).split('').reverse().join('') : valueGet.call(this);
766
+ };
767
+ npt._valueSet = function (value) {
768
+ valueSet.call(this, isRTL ? value.split('').reverse().join('') : value);
769
+ };
770
+
771
+ Object.defineProperty(npt, "value", {
772
+ get: function () {
773
+ var $self = $(this), inputData = $(this).data('_inputmask'), masksets = inputData['masksets'],
774
+ activeMasksetIndex = inputData['activeMasksetIndex'];
775
+ return inputData && inputData['opts'].autoUnmask ? $self.inputmask('unmaskedvalue') : valueGet.call(this) != masksets[activeMasksetIndex]['_buffer'].join('') ? valueGet.call(this) : '';
776
+ },
777
+ set: function (value) {
778
+ valueSet.call(this, value);
779
+ $(this).triggerHandler('setvalue.inputmask');
780
+ }
781
+ });
782
+ }
783
+ } else if (document.__lookupGetter__ && npt.__lookupGetter__("value")) {
784
+ if (!npt._valueGet) {
785
+ var valueGet = npt.__lookupGetter__("value");
786
+ var valueSet = npt.__lookupSetter__("value");
787
+ npt._valueGet = function () {
788
+ return isRTL ? valueGet.call(this).split('').reverse().join('') : valueGet.call(this);
789
+ };
790
+ npt._valueSet = function (value) {
791
+ valueSet.call(this, isRTL ? value.split('').reverse().join('') : value);
792
+ };
793
+
794
+ npt.__defineGetter__("value", function () {
795
+ var $self = $(this), inputData = $(this).data('_inputmask'), masksets = inputData['masksets'],
796
+ activeMasksetIndex = inputData['activeMasksetIndex'];
797
+ return inputData && inputData['opts'].autoUnmask ? $self.inputmask('unmaskedvalue') : valueGet.call(this) != masksets[activeMasksetIndex]['_buffer'].join('') ? valueGet.call(this) : '';
798
+ });
799
+ npt.__defineSetter__("value", function (value) {
800
+ valueSet.call(this, value);
801
+ $(this).triggerHandler('setvalue.inputmask');
802
+ });
803
+ }
804
+ } else {
805
+ if (!npt._valueGet) {
806
+ npt._valueGet = function () { return isRTL ? this.value.split('').reverse().join('') : this.value; };
807
+ npt._valueSet = function (value) { this.value = isRTL ? value.split('').reverse().join('') : value; };
808
+ }
809
+ PatchValhook(npt.type);
810
+ }
811
+ }
812
+
813
+ //shift chars to left from start to end and put c at end position if defined
814
+ function shiftL(start, end, c, maskJumps) {
815
+ var buffer = getActiveBuffer();
816
+ if (maskJumps !== false) //jumping over nonmask position
817
+ while (!isMask(start) && start - 1 >= 0) start--;
818
+ for (var i = start; i < end && i < getMaskLength() ; i++) {
819
+ if (isMask(i)) {
820
+ setReTargetPlaceHolder(buffer, i);
821
+ var j = seekNext(i);
822
+ var p = getBufferElement(buffer, j);
823
+ if (p != getPlaceHolder(j)) {
824
+ if (j < getMaskLength() && isValid(i, p, true) !== false && getActiveTests()[determineTestPosition(i)].def == getActiveTests()[determineTestPosition(j)].def) {
825
+ setBufferElement(buffer, i, p, true);
826
+ } else {
827
+ if (isMask(i))
828
+ break;
829
+ }
830
+ }
831
+ } else {
832
+ setReTargetPlaceHolder(buffer, i);
833
+ }
834
+ }
835
+ if (c != undefined)
836
+ setBufferElement(buffer, seekPrevious(end), c);
837
+
838
+ if (getActiveMaskSet()["greedy"] == false) {
839
+ var trbuffer = truncateInput(buffer.join('')).split('');
840
+ buffer.length = trbuffer.length;
841
+ for (var i = 0, bl = buffer.length; i < bl; i++) {
842
+ buffer[i] = trbuffer[i];
843
+ }
844
+ if (buffer.length == 0) getActiveMaskSet()["buffer"] = getActiveBufferTemplate().slice();
845
+ }
846
+ return start; //return the used start position
847
+ }
848
+
849
+ function shiftR(start, end, c) {
850
+ var buffer = getActiveBuffer();
851
+ if (getBufferElement(buffer, start, true) != getPlaceHolder(start)) {
852
+ for (var i = seekPrevious(end) ; i > start && i >= 0; i--) {
853
+ if (isMask(i)) {
854
+ var j = seekPrevious(i);
855
+ var t = getBufferElement(buffer, j);
856
+ if (t != getPlaceHolder(j)) {
857
+ if (isValid(i, t, true) !== false && getActiveTests()[determineTestPosition(i)].def == getActiveTests()[determineTestPosition(j)].def) {
858
+ setBufferElement(buffer, i, t, true);
859
+ setReTargetPlaceHolder(buffer, j);
860
+ } //else break;
861
+ }
862
+ } else
863
+ setReTargetPlaceHolder(buffer, i);
864
+ }
865
+ }
866
+ if (c != undefined && getBufferElement(buffer, start) == getPlaceHolder(start))
867
+ setBufferElement(buffer, start, c);
868
+ var lengthBefore = buffer.length;
869
+ if (getActiveMaskSet()["greedy"] == false) {
870
+ var trbuffer = truncateInput(buffer.join('')).split('');
871
+ buffer.length = trbuffer.length;
872
+ for (var i = 0, bl = buffer.length; i < bl; i++) {
873
+ buffer[i] = trbuffer[i];
874
+ }
875
+ if (buffer.length == 0) getActiveMaskSet()["buffer"] = getActiveBufferTemplate().slice();
876
+ }
877
+ return end - (lengthBefore - buffer.length); //return new start position
878
+ }
879
+
880
+ ;
881
+
882
+
883
+ function HandleRemove(input, k, pos) {
884
+ if (opts.numericInput || isRTL) {
885
+ switch (k) {
886
+ case opts.keyCode.BACKSPACE:
887
+ k = opts.keyCode.DELETE;
888
+ break;
889
+ case opts.keyCode.DELETE:
890
+ k = opts.keyCode.BACKSPACE;
891
+ break;
892
+ }
893
+ if (isRTL) {
894
+ var pend = pos.end;
895
+ pos.end = pos.begin;
896
+ pos.begin = pend;
897
+ }
898
+ }
899
+
900
+ var isSelection = true;
901
+ if (pos.begin == pos.end) {
902
+ var posBegin = k == opts.keyCode.BACKSPACE ? pos.begin - 1 : pos.begin;
903
+ if (opts.isNumeric && opts.radixPoint != "" && getActiveBuffer()[posBegin] == opts.radixPoint) {
904
+ pos.begin = (getActiveBuffer().length - 1 == posBegin) /* radixPoint is latest? delete it */ ? pos.begin : k == opts.keyCode.BACKSPACE ? posBegin : seekNext(posBegin);
905
+ pos.end = pos.begin;
906
+ }
907
+ isSelection = false;
908
+ if (k == opts.keyCode.BACKSPACE)
909
+ pos.begin--;
910
+ else if (k == opts.keyCode.DELETE)
911
+ pos.end++;
912
+ } else if (pos.end - pos.begin == 1 && !opts.insertMode) {
913
+ isSelection = false;
914
+ if (k == opts.keyCode.BACKSPACE)
915
+ pos.begin--;
916
+ }
917
+
918
+ clearBuffer(getActiveBuffer(), pos.begin, pos.end);
919
+
920
+ var ml = getMaskLength();
921
+ if (opts.greedy == false && (isNaN(opts.repeat) || opts.repeat > 0)) {
922
+ shiftL(pos.begin, ml, undefined, !isRTL && (k == opts.keyCode.BACKSPACE && !isSelection));
923
+ } else {
924
+ var newpos = pos.begin;
925
+ for (var i = pos.begin; i < pos.end; i++) { //seeknext to skip placeholders at start in selection
926
+ if (isMask(i) || !isSelection)
927
+ newpos = shiftL(pos.begin, ml, undefined, !isRTL && (k == opts.keyCode.BACKSPACE && !isSelection));
928
+ }
929
+ if (!isSelection) pos.begin = newpos;
930
+ }
931
+ var firstMaskPos = seekNext(-1);
932
+ clearBuffer(getActiveBuffer(), pos.begin, pos.end, true);
933
+ checkVal(input, false, false, getActiveBuffer());
934
+ if (getActiveMaskSet()['lastValidPosition'] < firstMaskPos) {
935
+ getActiveMaskSet()["lastValidPosition"] = -1;
936
+ getActiveMaskSet()["p"] = firstMaskPos;
937
+ } else {
938
+ getActiveMaskSet()["p"] = pos.begin;
939
+ }
940
+ }
941
+
942
+ function keydownEvent(e) {
943
+ //Safari 5.1.x - modal dialog fires keypress twice workaround
944
+ skipKeyPressEvent = false;
945
+ var input = this, $input = $(input), k = e.keyCode, pos = caret(input);
946
+
947
+ //backspace, delete, and escape get special treatment
948
+ if (k == opts.keyCode.BACKSPACE || k == opts.keyCode.DELETE || (iphone && k == 127) || e.ctrlKey && k == 88) { //backspace/delete
949
+ e.preventDefault(); //stop default action but allow propagation
950
+ if (k == 88) valueOnFocus = getActiveBuffer().join('');
951
+ HandleRemove(input, k, pos);
952
+ determineActiveMasksetIndex();
953
+ writeBuffer(input, getActiveBuffer(), getActiveMaskSet()["p"]);
954
+ if (input._valueGet() == getActiveBufferTemplate().join(''))
955
+ $input.trigger('cleared');
956
+
957
+ if (opts.showTooltip) { //update tooltip
958
+ $input.prop("title", getActiveMaskSet()["mask"]);
959
+ }
960
+ } else if (k == opts.keyCode.END || k == opts.keyCode.PAGE_DOWN) { //when END or PAGE_DOWN pressed set position at lastmatch
961
+ setTimeout(function () {
962
+ var caretPos = seekNext(getActiveMaskSet()["lastValidPosition"]);
963
+ if (!opts.insertMode && caretPos == getMaskLength() && !e.shiftKey) caretPos--;
964
+ caret(input, e.shiftKey ? pos.begin : caretPos, caretPos);
965
+ }, 0);
966
+ } else if ((k == opts.keyCode.HOME && !e.shiftKey) || k == opts.keyCode.PAGE_UP) { //Home or page_up
967
+ caret(input, 0, e.shiftKey ? pos.begin : 0);
968
+ } else if (k == opts.keyCode.ESCAPE || (k == 90 && e.ctrlKey)) { //escape && undo
969
+ checkVal(input, true, false, valueOnFocus.split(''));
970
+ $input.click();
971
+ } else if (k == opts.keyCode.INSERT && !(e.shiftKey || e.ctrlKey)) { //insert
972
+ opts.insertMode = !opts.insertMode;
973
+ caret(input, !opts.insertMode && pos.begin == getMaskLength() ? pos.begin - 1 : pos.begin);
974
+ } else if (opts.insertMode == false && !e.shiftKey) {
975
+ if (k == opts.keyCode.RIGHT) {
976
+ setTimeout(function () {
977
+ var caretPos = caret(input);
978
+ caret(input, caretPos.begin);
979
+ }, 0);
980
+ } else if (k == opts.keyCode.LEFT) {
981
+ setTimeout(function () {
982
+ var caretPos = caret(input);
983
+ caret(input, caretPos.begin - 1);
984
+ }, 0);
985
+ }
986
+ }
987
+
988
+ var currentCaretPos = caret(input);
989
+ if (opts.onKeyDown.call(this, e, getActiveBuffer(), opts) === true) //extra stuff to execute on keydown
990
+ caret(input, currentCaretPos.begin, currentCaretPos.end);
991
+ ignorable = $.inArray(k, opts.ignorables) != -1;
992
+ }
993
+
994
+
995
+ function keypressEvent(e, checkval, k, writeOut, strict, ndx) {
996
+ //Safari 5.1.x - modal dialog fires keypress twice workaround
997
+ if (k == undefined && skipKeyPressEvent) return false;
998
+ skipKeyPressEvent = true;
999
+
1000
+ var input = this, $input = $(input);
1001
+
1002
+ e = e || window.event;
1003
+ var k = checkval ? k : (e.which || e.charCode || e.keyCode);
1004
+
1005
+ if (checkval !== true && (!(e.ctrlKey && e.altKey) && (e.ctrlKey || e.metaKey || ignorable))) {
1006
+ return true;
1007
+ } else {
1008
+ if (k) {
1009
+ //special treat the decimal separator
1010
+ if (checkval !== true && k == 46 && e.shiftKey == false && opts.radixPoint == ",") k = 44;
1011
+
1012
+ var pos, results, result, c = String.fromCharCode(k);
1013
+ if (checkval) {
1014
+ var pcaret = strict ? ndx : getActiveMaskSet()["lastValidPosition"] + 1;
1015
+ pos = { begin: pcaret, end: pcaret };
1016
+ } else {
1017
+ pos = caret(input);
1018
+ }
1019
+
1020
+ //should we clear a possible selection??
1021
+ var isSlctn = isSelection(pos.begin, pos.end),
1022
+ initialIndex = activeMasksetIndex;
1023
+ if (isSlctn) {
1024
+ $.each(masksets, function (ndx, lmnt) { //init undobuffer for recovery when not valid
1025
+ if (typeof (lmnt) == "object") {
1026
+ activeMasksetIndex = ndx;
1027
+ getActiveMaskSet()["undoBuffer"] = getActiveBuffer().join('');
1028
+ }
1029
+ });
1030
+ activeMasksetIndex = initialIndex; //restore index
1031
+ HandleRemove(input, opts.keyCode.DELETE, pos);
1032
+ if (!opts.insertMode) { //preserve some space
1033
+ $.each(masksets, function (ndx, lmnt) {
1034
+ if (typeof (lmnt) == "object") {
1035
+ activeMasksetIndex = ndx;
1036
+ shiftR(pos.begin, getMaskLength());
1037
+ getActiveMaskSet()["lastValidPosition"] = seekNext(getActiveMaskSet()["lastValidPosition"]);
1038
+ }
1039
+ });
1040
+ }
1041
+ activeMasksetIndex = initialIndex; //restore index
1042
+ }
1043
+
1044
+ var radixPosition = getActiveBuffer().join('').indexOf(opts.radixPoint);
1045
+ if (opts.isNumeric && checkval !== true && radixPosition != -1) {
1046
+ if (opts.greedy && pos.begin <= radixPosition) {
1047
+ pos.begin = seekPrevious(pos.begin);
1048
+ pos.end = pos.begin;
1049
+ } else if (c == opts.radixPoint) {
1050
+ pos.begin = radixPosition;
1051
+ pos.end = pos.begin;
1052
+ }
1053
+ }
1054
+
1055
+
1056
+ var p = pos.begin;
1057
+ results = isValid(p, c, strict);
1058
+ if (strict === true) results = [{ "activeMasksetIndex": activeMasksetIndex, "result": results }];
1059
+ var minimalForwardPosition = -1;
1060
+ $.each(results, function (index, result) {
1061
+ activeMasksetIndex = result["activeMasksetIndex"];
1062
+ getActiveMaskSet()["writeOutBuffer"] = true;
1063
+ var np = result["result"];
1064
+ if (np !== false) {
1065
+ var refresh = false, buffer = getActiveBuffer();
1066
+ if (np !== true) {
1067
+ refresh = np["refresh"]; //only rewrite buffer from isValid
1068
+ p = np.pos != undefined ? np.pos : p; //set new position from isValid
1069
+ c = np.c != undefined ? np.c : c; //set new char from isValid
1070
+ }
1071
+ if (refresh !== true) {
1072
+ if (opts.insertMode == true) {
1073
+ var lastUnmaskedPosition = getMaskLength();
1074
+ var bfrClone = buffer.slice();
1075
+ while (getBufferElement(bfrClone, lastUnmaskedPosition, true) != getPlaceHolder(lastUnmaskedPosition) && lastUnmaskedPosition >= p) {
1076
+ lastUnmaskedPosition = lastUnmaskedPosition == 0 ? -1 : seekPrevious(lastUnmaskedPosition);
1077
+ }
1078
+ if (lastUnmaskedPosition >= p) {
1079
+ shiftR(p, getMaskLength(), c);
1080
+ //shift the lvp if needed
1081
+ var lvp = getActiveMaskSet()["lastValidPosition"], nlvp = seekNext(lvp);
1082
+ if (nlvp != getMaskLength() && lvp >= p && (getBufferElement(getActiveBuffer().slice(), nlvp, true) != getPlaceHolder(nlvp))) {
1083
+ getActiveMaskSet()["lastValidPosition"] = nlvp;
1084
+ }
1085
+ } else getActiveMaskSet()["writeOutBuffer"] = false;
1086
+ } else setBufferElement(buffer, p, c, true);
1087
+ if (minimalForwardPosition == -1 || minimalForwardPosition > seekNext(p)) {
1088
+ minimalForwardPosition = seekNext(p);
1089
+ }
1090
+ } else if (!strict) {
1091
+ var nextPos = p < getMaskLength() ? p + 1 : p;
1092
+ if (minimalForwardPosition == -1 || minimalForwardPosition > nextPos) {
1093
+ minimalForwardPosition = nextPos;
1094
+ }
1095
+ }
1096
+ if (minimalForwardPosition > getActiveMaskSet()["p"])
1097
+ getActiveMaskSet()["p"] = minimalForwardPosition; //needed for checkval strict
1098
+ }
1099
+ });
1100
+
1101
+ if (strict !== true) {
1102
+ activeMasksetIndex = initialIndex;
1103
+ determineActiveMasksetIndex();
1104
+ }
1105
+ if (writeOut !== false) {
1106
+ $.each(results, function (ndx, rslt) {
1107
+ if (rslt["activeMasksetIndex"] == activeMasksetIndex) {
1108
+ result = rslt;
1109
+ return false;
1110
+ }
1111
+ });
1112
+ if (result != undefined) {
1113
+ var self = this;
1114
+ setTimeout(function () { opts.onKeyValidation.call(self, result["result"], opts); }, 0);
1115
+ if (getActiveMaskSet()["writeOutBuffer"] && result["result"] !== false) {
1116
+ var buffer = getActiveBuffer();
1117
+
1118
+ var newCaretPosition;
1119
+ if (checkval) {
1120
+ newCaretPosition = undefined;
1121
+ } else if (opts.numericInput) {
1122
+ if (p > radixPosition) {
1123
+ newCaretPosition = seekPrevious(minimalForwardPosition);
1124
+ } else if (c == opts.radixPoint) {
1125
+ newCaretPosition = minimalForwardPosition - 1;
1126
+ } else newCaretPosition = seekPrevious(minimalForwardPosition - 1);
1127
+ } else {
1128
+ newCaretPosition = minimalForwardPosition;
1129
+ }
1130
+
1131
+ writeBuffer(input, buffer, newCaretPosition);
1132
+ if (checkval !== true) {
1133
+ setTimeout(function () { //timeout needed for IE
1134
+ if (isComplete(buffer) === true)
1135
+ $input.trigger("complete");
1136
+ skipInputEvent = true;
1137
+ $input.trigger("input");
1138
+ }, 0);
1139
+ }
1140
+ } else if (isSlctn) {
1141
+ getActiveMaskSet()["buffer"] = getActiveMaskSet()["undoBuffer"].split('');
1142
+ }
1143
+ } else if (isSlctn) {
1144
+ getActiveMaskSet()["buffer"] = getActiveMaskSet()["undoBuffer"].split('');
1145
+ }
1146
+ }
1147
+
1148
+ if (opts.showTooltip) { //update tooltip
1149
+ $input.prop("title", getActiveMaskSet()["mask"]);
1150
+ }
1151
+
1152
+ //needed for IE8 and below
1153
+ if (e) e.preventDefault ? e.preventDefault() : e.returnValue = false;
1154
+ }
1155
+ }
1156
+ }
1157
+
1158
+ function keyupEvent(e) {
1159
+ var $input = $(this), input = this, k = e.keyCode, buffer = getActiveBuffer();
1160
+
1161
+ opts.onKeyUp.call(this, e, buffer, opts); //extra stuff to execute on keyup
1162
+ if (k == opts.keyCode.TAB && opts.showMaskOnFocus) {
1163
+ if ($input.hasClass('focus.inputmask') && input._valueGet().length == 0) {
1164
+ buffer = getActiveBufferTemplate().slice();
1165
+ writeBuffer(input, buffer);
1166
+ caret(input, 0);
1167
+ valueOnFocus = getActiveBuffer().join('');
1168
+ } else {
1169
+ writeBuffer(input, buffer);
1170
+ if (buffer.join('') == getActiveBufferTemplate().join('') && $.inArray(opts.radixPoint, buffer) != -1) {
1171
+ caret(input, TranslatePosition(0));
1172
+ $input.click();
1173
+ } else
1174
+ caret(input, TranslatePosition(0), TranslatePosition(getMaskLength()));
1175
+ }
1176
+ }
1177
+ }
1178
+
1179
+ function pasteEvent(e) {
1180
+ if (skipInputEvent === true && e.type == "input") {
1181
+ skipInputEvent = false;
1182
+ return true;
1183
+ }
1184
+
1185
+ var input = this, $input = $(input);
1186
+ //paste event for IE8 and lower I guess ;-)
1187
+ if (e.type == "propertychange" && input._valueGet().length <= getMaskLength()) {
1188
+ return true;
1189
+ }
1190
+ setTimeout(function () {
1191
+ var pasteValue = $.isFunction(opts.onBeforePaste) ? opts.onBeforePaste.call(input, input._valueGet(), opts) : input._valueGet();
1192
+ checkVal(input, false, false, pasteValue.split(''), true);
1193
+ writeBuffer(input, getActiveBuffer());
1194
+ if (isComplete(getActiveBuffer()) === true)
1195
+ $input.trigger("complete");
1196
+ $input.click();
1197
+ }, 0);
1198
+ }
1199
+
1200
+ //not used - attempt to support android
1201
+ function mobileInputEvent(e) {
1202
+ var input = this, $input = $(input);
1203
+
1204
+ //backspace in chrome32 only fires input event - detect & treat
1205
+ var caretPos = caret(input),
1206
+ currentValue = input._valueGet();
1207
+
1208
+ currentValue = currentValue.replace(new RegExp("(" + escapeRegex(getActiveBufferTemplate().join('')) + ")*"), "");
1209
+ //correct caretposition for chrome
1210
+ if (caretPos.begin > currentValue.length) {
1211
+ caret(input, currentValue.length);
1212
+ caretPos = caret(input);
1213
+ }
1214
+ if ((getActiveBuffer().length - currentValue.length) == 1 && currentValue.charAt(caretPos.begin) != getActiveBuffer()[caretPos.begin]
1215
+ && currentValue.charAt(caretPos.begin + 1) != getActiveBuffer()[caretPos.begin]
1216
+ && !isMask(caretPos.begin)) {
1217
+ e.keyCode = opts.keyCode.BACKSPACE;
1218
+ keydownEvent.call(input, e);
1219
+ } else { //nonnumerics don't fire keypress
1220
+ checkVal(input, false, false, currentValue.split(''));
1221
+ writeBuffer(input, getActiveBuffer());
1222
+ if (isComplete(getActiveBuffer()) === true)
1223
+ $input.trigger("complete");
1224
+ $input.click();
1225
+ }
1226
+ e.preventDefault();
1227
+ }
1228
+
1229
+ function mask(el) {
1230
+ $el = $(el);
1231
+ if ($el.is(":input")) {
1232
+ //store tests & original buffer in the input element - used to get the unmasked value
1233
+ $el.data('_inputmask', {
1234
+ 'masksets': masksets,
1235
+ 'activeMasksetIndex': activeMasksetIndex,
1236
+ 'opts': opts,
1237
+ 'isRTL': false
1238
+ });
1239
+
1240
+ //show tooltip
1241
+ if (opts.showTooltip) {
1242
+ $el.prop("title", getActiveMaskSet()["mask"]);
1243
+ }
1244
+
1245
+ //correct greedy setting if needed
1246
+ getActiveMaskSet()['greedy'] = getActiveMaskSet()['greedy'] ? getActiveMaskSet()['greedy'] : getActiveMaskSet()['repeat'] == 0;
1247
+
1248
+ //handle maxlength attribute
1249
+ if ($el.attr("maxLength") != null) //only when the attribute is set
1250
+ {
1251
+ var maxLength = $el.prop('maxLength');
1252
+ if (maxLength > -1) { //handle *-repeat
1253
+ $.each(masksets, function (ndx, ms) {
1254
+ if (typeof (ms) == "object") {
1255
+ if (ms["repeat"] == "*") {
1256
+ ms["repeat"] = maxLength;
1257
+ }
1258
+ }
1259
+ });
1260
+ }
1261
+ if (getMaskLength() >= maxLength && maxLength > -1) { //FF sets no defined max length to -1
1262
+ if (maxLength < getActiveBufferTemplate().length) getActiveBufferTemplate().length = maxLength;
1263
+ if (getActiveMaskSet()['greedy'] == false) {
1264
+ getActiveMaskSet()['repeat'] = Math.round(maxLength / getActiveBufferTemplate().length);
1265
+ }
1266
+ $el.prop('maxLength', getMaskLength() * 2);
1267
+ }
1268
+ }
1269
+
1270
+ patchValueProperty(el);
1271
+
1272
+ if (opts.numericInput) opts.isNumeric = opts.numericInput;
1273
+ if (el.dir == "rtl" || (opts.numericInput && opts.rightAlignNumerics) || (opts.isNumeric && opts.rightAlignNumerics))
1274
+ $el.css("text-align", "right");
1275
+
1276
+ if (el.dir == "rtl" || opts.numericInput) {
1277
+ el.dir = "ltr";
1278
+ $el.removeAttr("dir");
1279
+ var inputData = $el.data('_inputmask');
1280
+ inputData['isRTL'] = true;
1281
+ $el.data('_inputmask', inputData);
1282
+ isRTL = true;
1283
+ }
1284
+
1285
+ //unbind all events - to make sure that no other mask will interfere when re-masking
1286
+ $el.unbind(".inputmask");
1287
+ $el.removeClass('focus.inputmask');
1288
+ //bind events
1289
+ $el.closest('form').bind("submit", function () { //trigger change on submit if any
1290
+ if (valueOnFocus != getActiveBuffer().join('')) {
1291
+ $el.change();
1292
+ }
1293
+ }).bind('reset', function () {
1294
+ setTimeout(function () {
1295
+ $el.trigger("setvalue");
1296
+ }, 0);
1297
+ });
1298
+ $el.bind("mouseenter.inputmask", function () {
1299
+ var $input = $(this), input = this;
1300
+ if (!$input.hasClass('focus.inputmask') && opts.showMaskOnHover) {
1301
+ if (input._valueGet() != getActiveBuffer().join('')) {
1302
+ writeBuffer(input, getActiveBuffer());
1303
+ }
1304
+ }
1305
+ }).bind("blur.inputmask", function () {
1306
+ var $input = $(this), input = this, nptValue = input._valueGet(), buffer = getActiveBuffer();
1307
+ $input.removeClass('focus.inputmask');
1308
+ if (valueOnFocus != getActiveBuffer().join('')) {
1309
+ $input.change();
1310
+ }
1311
+ if (opts.clearMaskOnLostFocus && nptValue != '') {
1312
+ if (nptValue == getActiveBufferTemplate().join(''))
1313
+ input._valueSet('');
1314
+ else { //clearout optional tail of the mask
1315
+ clearOptionalTail(input);
1316
+ }
1317
+ }
1318
+ if (isComplete(buffer) === false) {
1319
+ $input.trigger("incomplete");
1320
+ if (opts.clearIncomplete) {
1321
+ $.each(masksets, function (ndx, ms) {
1322
+ if (typeof (ms) == "object") {
1323
+ ms["buffer"] = ms["_buffer"].slice();
1324
+ ms["lastValidPosition"] = -1;
1325
+ }
1326
+ });
1327
+ activeMasksetIndex = 0;
1328
+ if (opts.clearMaskOnLostFocus)
1329
+ input._valueSet('');
1330
+ else {
1331
+ buffer = getActiveBufferTemplate().slice();
1332
+ writeBuffer(input, buffer);
1333
+ }
1334
+ }
1335
+ }
1336
+ }).bind("focus.inputmask", function () {
1337
+ var $input = $(this), input = this, nptValue = input._valueGet();
1338
+ if (opts.showMaskOnFocus && !$input.hasClass('focus.inputmask') && (!opts.showMaskOnHover || (opts.showMaskOnHover && nptValue == ''))) {
1339
+ if (input._valueGet() != getActiveBuffer().join('')) {
1340
+ writeBuffer(input, getActiveBuffer(), seekNext(getActiveMaskSet()["lastValidPosition"]));
1341
+ }
1342
+ }
1343
+ $input.addClass('focus.inputmask');
1344
+ valueOnFocus = getActiveBuffer().join('');
1345
+ }).bind("mouseleave.inputmask", function () {
1346
+ var $input = $(this), input = this;
1347
+ if (opts.clearMaskOnLostFocus) {
1348
+ if (!$input.hasClass('focus.inputmask') && input._valueGet() != $input.attr("placeholder")) {
1349
+ if (input._valueGet() == getActiveBufferTemplate().join('') || input._valueGet() == '')
1350
+ input._valueSet('');
1351
+ else { //clearout optional tail of the mask
1352
+ clearOptionalTail(input);
1353
+ }
1354
+ }
1355
+ }
1356
+ }).bind("click.inputmask", function () {
1357
+ var input = this;
1358
+ setTimeout(function () {
1359
+ var selectedCaret = caret(input), buffer = getActiveBuffer();
1360
+ if (selectedCaret.begin == selectedCaret.end) {
1361
+ var clickPosition = isRTL ? TranslatePosition(selectedCaret.begin) : selectedCaret.begin,
1362
+ lvp = getActiveMaskSet()["lastValidPosition"],
1363
+ lastPosition;
1364
+ if (opts.isNumeric) {
1365
+ lastPosition = opts.skipRadixDance === false && opts.radixPoint != "" && $.inArray(opts.radixPoint, buffer) != -1 ?
1366
+ (opts.numericInput ? seekNext($.inArray(opts.radixPoint, buffer)) : $.inArray(opts.radixPoint, buffer)) :
1367
+ seekNext(lvp);
1368
+ } else {
1369
+ lastPosition = seekNext(lvp);
1370
+ }
1371
+ if (clickPosition < lastPosition) {
1372
+ if (isMask(clickPosition))
1373
+ caret(input, clickPosition);
1374
+ else caret(input, seekNext(clickPosition));
1375
+ } else
1376
+ caret(input, lastPosition);
1377
+ }
1378
+ }, 0);
1379
+ }).bind('dblclick.inputmask', function () {
1380
+ var input = this;
1381
+ setTimeout(function () {
1382
+ caret(input, 0, seekNext(getActiveMaskSet()["lastValidPosition"]));
1383
+ }, 0);
1384
+ }).bind(PasteEventType + ".inputmask dragdrop.inputmask drop.inputmask", pasteEvent
1385
+ ).bind('setvalue.inputmask', function () {
1386
+ var input = this;
1387
+ checkVal(input, true);
1388
+ valueOnFocus = getActiveBuffer().join('');
1389
+ if (input._valueGet() == getActiveBufferTemplate().join(''))
1390
+ input._valueSet('');
1391
+ }).bind('complete.inputmask', opts.oncomplete
1392
+ ).bind('incomplete.inputmask', opts.onincomplete
1393
+ ).bind('cleared.inputmask', opts.oncleared);
1394
+
1395
+ $el.bind("keydown.inputmask", keydownEvent
1396
+ ).bind("keypress.inputmask", keypressEvent
1397
+ ).bind("keyup.inputmask", keyupEvent);
1398
+
1399
+ // as the other inputevents aren't reliable for the moment we only base on the input event
1400
+ // needs follow-up
1401
+ if (android || androidfirefox || androidchrome || kindle) {
1402
+ $el.attr("autocomplete", "off")
1403
+ .attr("autocorrect", "off")
1404
+ .attr("autocapitalize", "off")
1405
+ .attr("spellcheck", false);
1406
+
1407
+ if (androidfirefox || kindle) {
1408
+ $el.unbind("keydown.inputmask", keydownEvent
1409
+ ).unbind("keypress.inputmask", keypressEvent
1410
+ ).unbind("keyup.inputmask", keyupEvent);
1411
+ if (PasteEventType == "input") {
1412
+ $el.unbind(PasteEventType + ".inputmask");
1413
+ }
1414
+ $el.bind("input.inputmask", mobileInputEvent);
1415
+ }
1416
+ }
1417
+
1418
+ if (msie1x)
1419
+ $el.bind("input.inputmask", pasteEvent);
1420
+
1421
+ //apply mask
1422
+ var initialValue = $.isFunction(opts.onBeforeMask) ? opts.onBeforeMask.call(el, el._valueGet(), opts) : el._valueGet();
1423
+ checkVal(el, true, false, initialValue.split(''));
1424
+ valueOnFocus = getActiveBuffer().join('');
1425
+ // Wrap document.activeElement in a try/catch block since IE9 throw "Unspecified error" if document.activeElement is undefined when we are in an IFrame.
1426
+ var activeElement;
1427
+ try {
1428
+ activeElement = document.activeElement;
1429
+ } catch (e) {
1430
+ }
1431
+ if (activeElement === el) { //position the caret when in focus
1432
+ $el.addClass('focus.inputmask');
1433
+ caret(el, seekNext(getActiveMaskSet()["lastValidPosition"]));
1434
+ } else if (opts.clearMaskOnLostFocus) {
1435
+ if (getActiveBuffer().join('') == getActiveBufferTemplate().join('')) {
1436
+ el._valueSet('');
1437
+ } else {
1438
+ clearOptionalTail(el);
1439
+ }
1440
+ } else {
1441
+ writeBuffer(el, getActiveBuffer());
1442
+ }
1443
+
1444
+ installEventRuler(el);
1445
+ }
1446
+ }
1447
+
1448
+ //action object
1449
+ if (actionObj != undefined) {
1450
+ switch (actionObj["action"]) {
1451
+ case "isComplete":
1452
+ return isComplete(actionObj["buffer"]);
1453
+ case "unmaskedvalue":
1454
+ isRTL = actionObj["$input"].data('_inputmask')['isRTL'];
1455
+ return unmaskedvalue(actionObj["$input"], actionObj["skipDatepickerCheck"]);
1456
+ case "mask":
1457
+ mask(actionObj["el"]);
1458
+ break;
1459
+ case "format":
1460
+ $el = $({});
1461
+ $el.data('_inputmask', {
1462
+ 'masksets': masksets,
1463
+ 'activeMasksetIndex': activeMasksetIndex,
1464
+ 'opts': opts,
1465
+ 'isRTL': opts.numericInput
1466
+ });
1467
+ if (opts.numericInput) {
1468
+ opts.isNumeric = opts.numericInput;
1469
+ isRTL = true;
1470
+ }
1471
+
1472
+ checkVal($el, false, false, actionObj["value"].split(''), true);
1473
+ return getActiveBuffer().join('');
1474
+ case "isValid":
1475
+ $el = $({});
1476
+ $el.data('_inputmask', {
1477
+ 'masksets': masksets,
1478
+ 'activeMasksetIndex': activeMasksetIndex,
1479
+ 'opts': opts,
1480
+ 'isRTL': opts.numericInput
1481
+ });
1482
+ if (opts.numericInput) {
1483
+ opts.isNumeric = opts.numericInput;
1484
+ isRTL = true;
1485
+ }
1486
+
1487
+ checkVal($el, false, true, actionObj["value"].split(''));
1488
+ return isComplete(getActiveBuffer());
1489
+ }
1490
+ }
1491
+ };
1492
+
1493
+ $.inputmask = {
1494
+ //options default
1495
+ defaults: {
1496
+ placeholder: "_",
1497
+ optionalmarker: { start: "[", end: "]" },
1498
+ quantifiermarker: { start: "{", end: "}" },
1499
+ groupmarker: { start: "(", end: ")" },
1500
+ escapeChar: "\\",
1501
+ mask: null,
1502
+ oncomplete: $.noop, //executes when the mask is complete
1503
+ onincomplete: $.noop, //executes when the mask is incomplete and focus is lost
1504
+ oncleared: $.noop, //executes when the mask is cleared
1505
+ repeat: 0, //repetitions of the mask: * ~ forever, otherwise specify an integer
1506
+ greedy: true, //true: allocated buffer for the mask and repetitions - false: allocate only if needed
1507
+ autoUnmask: false, //automatically unmask when retrieving the value with $.fn.val or value if the browser supports __lookupGetter__ or getOwnPropertyDescriptor
1508
+ clearMaskOnLostFocus: true,
1509
+ insertMode: true, //insert the input or overwrite the input
1510
+ clearIncomplete: false, //clear the incomplete input on blur
1511
+ aliases: {}, //aliases definitions => see jquery.inputmask.extensions.js
1512
+ onKeyUp: $.noop, //override to implement autocomplete on certain keys for example
1513
+ onKeyDown: $.noop, //override to implement autocomplete on certain keys for example
1514
+ onBeforeMask: undefined, //executes before masking the initial value to allow preprocessing of the initial value. args => initialValue, opts => return processedValue
1515
+ onBeforePaste: undefined, //executes before masking the pasted value to allow preprocessing of the pasted value. args => pastedValue, opts => return processedValue
1516
+ onUnMask: undefined, //executes after unmasking to allow postprocessing of the unmaskedvalue. args => maskedValue, unmaskedValue, opts
1517
+ showMaskOnFocus: true, //show the mask-placeholder when the input has focus
1518
+ showMaskOnHover: true, //show the mask-placeholder when hovering the empty input
1519
+ onKeyValidation: $.noop, //executes on every key-press with the result of isValid. Params: result, opts
1520
+ skipOptionalPartCharacter: " ", //a character which can be used to skip an optional part of a mask
1521
+ showTooltip: false, //show the activemask as tooltip
1522
+ numericInput: false, //numericInput input direction style (input shifts to the left while holding the caret position)
1523
+ //numeric basic properties
1524
+ isNumeric: false, //enable numeric features
1525
+ radixPoint: "", //".", // | ","
1526
+ skipRadixDance: false, //disable radixpoint caret positioning
1527
+ rightAlignNumerics: true, //align numerics to the right
1528
+ //numeric basic properties
1529
+ definitions: {
1530
+ '9': {
1531
+ validator: "[0-9]",
1532
+ cardinality: 1,
1533
+ definitionSymbol: "*"
1534
+ },
1535
+ 'a': {
1536
+ validator: "[A-Za-z\u0410-\u044F\u0401\u0451]",
1537
+ cardinality: 1,
1538
+ definitionSymbol: "*"
1539
+ },
1540
+ '*': {
1541
+ validator: "[A-Za-z\u0410-\u044F\u0401\u04510-9]",
1542
+ cardinality: 1
1543
+ }
1544
+ },
1545
+ keyCode: {
1546
+ 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,
1547
+ 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
1548
+ },
1549
+ //specify keycodes which should not be considered in the keypress event, otherwise the preventDefault will stop their default behavior especially in FF
1550
+ ignorables: [8, 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],
1551
+ getMaskLength: undefined, //override for getMaskLength - args => buffer, greedy, repeat, currentBuffer, opts - return length
1552
+ isComplete: undefined //override for isComplete - args => buffer, opts - return true || false
1553
+ },
1554
+ escapeRegex: function (str) {
1555
+ var specials = ['/', '.', '*', '+', '?', '|', '(', ')', '[', ']', '{', '}', '\\'];
1556
+ return str.replace(new RegExp('(\\' + specials.join('|\\') + ')', 'gim'), '\\$1');
1557
+ },
1558
+ format: function (value, options) {
1559
+ var opts = $.extend(true, {}, $.inputmask.defaults, options);
1560
+ resolveAlias(opts.alias, options, opts);
1561
+ return maskScope(generateMaskSets(opts), 0, opts, { "action": "format", "value": value });
1562
+ },
1563
+ isValid: function (value, options) {
1564
+ var opts = $.extend(true, {}, $.inputmask.defaults, options);
1565
+ resolveAlias(opts.alias, options, opts);
1566
+ return maskScope(generateMaskSets(opts), 0, opts, { "action": "isValid", "value": value });
1567
+ }
1568
+ };
1569
+
1570
+ $.fn.inputmask = function (fn, options) {
1571
+ var opts = $.extend(true, {}, $.inputmask.defaults, options),
1572
+ masksets,
1573
+ activeMasksetIndex = 0;
1574
+
1575
+ if (typeof fn === "string") {
1576
+ switch (fn) {
1577
+ case "mask":
1578
+ //resolve possible aliases given by options
1579
+ resolveAlias(opts.alias, options, opts);
1580
+ masksets = generateMaskSets(opts);
1581
+ if (masksets.length == 0) { return this; }
1582
+
1583
+ return this.each(function () {
1584
+ maskScope($.extend(true, {}, masksets), 0, opts, { "action": "mask", "el": this });
1585
+ });
1586
+ case "unmaskedvalue":
1587
+ var $input = $(this), input = this;
1588
+ if ($input.data('_inputmask')) {
1589
+ masksets = $input.data('_inputmask')['masksets'];
1590
+ activeMasksetIndex = $input.data('_inputmask')['activeMasksetIndex'];
1591
+ opts = $input.data('_inputmask')['opts'];
1592
+ return maskScope(masksets, activeMasksetIndex, opts, { "action": "unmaskedvalue", "$input": $input });
1593
+ } else return $input.val();
1594
+ case "remove":
1595
+ return this.each(function () {
1596
+ var $input = $(this), input = this;
1597
+ if ($input.data('_inputmask')) {
1598
+ masksets = $input.data('_inputmask')['masksets'];
1599
+ activeMasksetIndex = $input.data('_inputmask')['activeMasksetIndex'];
1600
+ opts = $input.data('_inputmask')['opts'];
1601
+ //writeout the unmaskedvalue
1602
+ input._valueSet(maskScope(masksets, activeMasksetIndex, opts, { "action": "unmaskedvalue", "$input": $input, "skipDatepickerCheck": true }));
1603
+ //clear data
1604
+ $input.removeData('_inputmask');
1605
+ //unbind all events
1606
+ $input.unbind(".inputmask");
1607
+ $input.removeClass('focus.inputmask');
1608
+ //restore the value property
1609
+ var valueProperty;
1610
+ if (Object.getOwnPropertyDescriptor)
1611
+ valueProperty = Object.getOwnPropertyDescriptor(input, "value");
1612
+ if (valueProperty && valueProperty.get) {
1613
+ if (input._valueGet) {
1614
+ Object.defineProperty(input, "value", {
1615
+ get: input._valueGet,
1616
+ set: input._valueSet
1617
+ });
1618
+ }
1619
+ } else if (document.__lookupGetter__ && input.__lookupGetter__("value")) {
1620
+ if (input._valueGet) {
1621
+ input.__defineGetter__("value", input._valueGet);
1622
+ input.__defineSetter__("value", input._valueSet);
1623
+ }
1624
+ }
1625
+ try { //try catch needed for IE7 as it does not supports deleting fns
1626
+ delete input._valueGet;
1627
+ delete input._valueSet;
1628
+ } catch (e) {
1629
+ input._valueGet = undefined;
1630
+ input._valueSet = undefined;
1631
+
1632
+ }
1633
+ }
1634
+ });
1635
+ break;
1636
+ case "getemptymask": //return the default (empty) mask value, usefull for setting the default value in validation
1637
+ if (this.data('_inputmask')) {
1638
+ masksets = this.data('_inputmask')['masksets'];
1639
+ activeMasksetIndex = this.data('_inputmask')['activeMasksetIndex'];
1640
+ return masksets[activeMasksetIndex]['_buffer'].join('');
1641
+ }
1642
+ else return "";
1643
+ case "hasMaskedValue": //check wheter the returned value is masked or not; currently only works reliable when using jquery.val fn to retrieve the value
1644
+ return this.data('_inputmask') ? !this.data('_inputmask')['opts'].autoUnmask : false;
1645
+ case "isComplete":
1646
+ masksets = this.data('_inputmask')['masksets'];
1647
+ activeMasksetIndex = this.data('_inputmask')['activeMasksetIndex'];
1648
+ opts = this.data('_inputmask')['opts'];
1649
+ return maskScope(masksets, activeMasksetIndex, opts, { "action": "isComplete", "buffer": this[0]._valueGet().split('') });
1650
+ case "getmetadata": //return mask metadata if exists
1651
+ if (this.data('_inputmask')) {
1652
+ masksets = this.data('_inputmask')['masksets'];
1653
+ activeMasksetIndex = this.data('_inputmask')['activeMasksetIndex'];
1654
+ return masksets[activeMasksetIndex]['metadata'];
1655
+ }
1656
+ else return undefined;
1657
+ default:
1658
+ //check if the fn is an alias
1659
+ if (!resolveAlias(fn, options, opts)) {
1660
+ //maybe fn is a mask so we try
1661
+ //set mask
1662
+ opts.mask = fn;
1663
+ }
1664
+ masksets = generateMaskSets(opts);
1665
+ if (masksets.length == 0) { return this; }
1666
+ return this.each(function () {
1667
+ maskScope($.extend(true, {}, masksets), activeMasksetIndex, opts, { "action": "mask", "el": this });
1668
+ });
1669
+
1670
+ break;
1671
+ }
1672
+ } else if (typeof fn == "object") {
1673
+ opts = $.extend(true, {}, $.inputmask.defaults, fn);
1674
+
1675
+ resolveAlias(opts.alias, fn, opts); //resolve aliases
1676
+ masksets = generateMaskSets(opts);
1677
+ if (masksets.length == 0) { return this; }
1678
+ return this.each(function () {
1679
+ maskScope($.extend(true, {}, masksets), activeMasksetIndex, opts, { "action": "mask", "el": this });
1680
+ });
1681
+ } else if (fn == undefined) {
1682
+ //look for data-inputmask atribute - the attribute should only contain optipns
1683
+ return this.each(function () {
1684
+ var attrOptions = $(this).attr("data-inputmask");
1685
+ if (attrOptions && attrOptions != "") {
1686
+ try {
1687
+ attrOptions = attrOptions.replace(new RegExp("'", "g"), '"');
1688
+ var dataoptions = $.parseJSON("{" + attrOptions + "}");
1689
+ $.extend(true, dataoptions, options);
1690
+ opts = $.extend(true, {}, $.inputmask.defaults, dataoptions);
1691
+ resolveAlias(opts.alias, dataoptions, opts);
1692
+ opts.alias = undefined;
1693
+ $(this).inputmask(opts);
1694
+ } catch (ex) { } //need a more relax parseJSON
1695
+ }
1696
+ });
1697
+ }
1698
+ };
1699
+ }
1700
+ })(jQuery);
1701
+ /*
1702
+ Input Mask plugin extensions
1703
+ http://github.com/RobinHerbots/jquery.inputmask
1704
+ Copyright (c) 2010 - 2014 Robin Herbots
1705
+ Licensed under the MIT license (http://www.opensource.org/licenses/mit-license.php)
1706
+ Version: 2.5.5
1707
+
1708
+ Optional extensions on the jquery.inputmask base
1709
+ */
1710
+ (function ($) {
1711
+ //extra definitions
1712
+ $.extend($.inputmask.defaults.definitions, {
1713
+ 'A': {
1714
+ validator: "[A-Za-z]",
1715
+ cardinality: 1,
1716
+ casing: "upper" //auto uppercasing
1717
+ },
1718
+ '#': {
1719
+ validator: "[A-Za-z\u0410-\u044F\u0401\u04510-9]",
1720
+ cardinality: 1,
1721
+ casing: "upper"
1722
+ }
1723
+ });
1724
+ $.extend($.inputmask.defaults.aliases, {
1725
+ 'url': {
1726
+ mask: "ir",
1727
+ placeholder: "",
1728
+ separator: "",
1729
+ defaultPrefix: "http://",
1730
+ regex: {
1731
+ urlpre1: new RegExp("[fh]"),
1732
+ urlpre2: new RegExp("(ft|ht)"),
1733
+ urlpre3: new RegExp("(ftp|htt)"),
1734
+ urlpre4: new RegExp("(ftp:|http|ftps)"),
1735
+ urlpre5: new RegExp("(ftp:/|ftps:|http:|https)"),
1736
+ urlpre6: new RegExp("(ftp://|ftps:/|http:/|https:)"),
1737
+ urlpre7: new RegExp("(ftp://|ftps://|http://|https:/)"),
1738
+ urlpre8: new RegExp("(ftp://|ftps://|http://|https://)")
1739
+ },
1740
+ definitions: {
1741
+ 'i': {
1742
+ validator: function (chrs, buffer, pos, strict, opts) {
1743
+ return true;
1744
+ },
1745
+ cardinality: 8,
1746
+ prevalidator: (function () {
1747
+ var result = [], prefixLimit = 8;
1748
+ for (var i = 0; i < prefixLimit; i++) {
1749
+ result[i] = (function () {
1750
+ var j = i;
1751
+ return {
1752
+ validator: function (chrs, buffer, pos, strict, opts) {
1753
+ if (opts.regex["urlpre" + (j + 1)]) {
1754
+ var tmp = chrs, k;
1755
+ if (((j + 1) - chrs.length) > 0) {
1756
+ tmp = buffer.join('').substring(0, ((j + 1) - chrs.length)) + "" + tmp;
1757
+ }
1758
+ var isValid = opts.regex["urlpre" + (j + 1)].test(tmp);
1759
+ if (!strict && !isValid) {
1760
+ pos = pos - j;
1761
+ for (k = 0; k < opts.defaultPrefix.length; k++) {
1762
+ buffer[pos] = opts.defaultPrefix[k]; pos++;
1763
+ }
1764
+ for (k = 0; k < tmp.length - 1; k++) {
1765
+ buffer[pos] = tmp[k]; pos++;
1766
+ }
1767
+ return { "pos": pos };
1768
+ }
1769
+ return isValid;
1770
+ } else {
1771
+ return false;
1772
+ }
1773
+ }, cardinality: j
1774
+ };
1775
+ })();
1776
+ }
1777
+ return result;
1778
+ })()
1779
+ },
1780
+ "r": {
1781
+ validator: ".",
1782
+ cardinality: 50
1783
+ }
1784
+ },
1785
+ insertMode: false,
1786
+ autoUnmask: false
1787
+ },
1788
+ "ip": { //ip-address mask
1789
+ mask: ["[[x]y]z.[[x]y]z.[[x]y]z.x[yz]", "[[x]y]z.[[x]y]z.[[x]y]z.[[x]y][z]"],
1790
+ definitions: {
1791
+ 'x': {
1792
+ validator: "[012]",
1793
+ cardinality: 1,
1794
+ definitionSymbol: "i"
1795
+ },
1796
+ 'y': {
1797
+ validator: function (chrs, buffer, pos, strict, opts) {
1798
+ if (pos - 1 > -1 && buffer[pos - 1] != ".")
1799
+ chrs = buffer[pos - 1] + chrs;
1800
+ else chrs = "0" + chrs;
1801
+ return new RegExp("2[0-5]|[01][0-9]").test(chrs);
1802
+ },
1803
+ cardinality: 1,
1804
+ definitionSymbol: "i"
1805
+ },
1806
+ 'z': {
1807
+ validator: function (chrs, buffer, pos, strict, opts) {
1808
+ if (pos - 1 > -1 && buffer[pos - 1] != ".") {
1809
+ chrs = buffer[pos - 1] + chrs;
1810
+ if (pos - 2 > -1 && buffer[pos - 2] != ".") {
1811
+ chrs = buffer[pos - 2] + chrs;
1812
+ } else chrs = "0" + chrs;
1813
+ } else chrs = "00" + chrs;
1814
+ return new RegExp("25[0-5]|2[0-4][0-9]|[01][0-9][0-9]").test(chrs);
1815
+ },
1816
+ cardinality: 1,
1817
+ definitionSymbol: "i"
1818
+ }
1819
+ }
1820
+ }
1821
+ });
1822
+ })(jQuery);
1823
+ /*
1824
+ Input Mask plugin extensions
1825
+ http://github.com/RobinHerbots/jquery.inputmask
1826
+ Copyright (c) 2010 - 2014 Robin Herbots
1827
+ Licensed under the MIT license (http://www.opensource.org/licenses/mit-license.php)
1828
+ Version: 2.5.5
1829
+
1830
+ Optional extensions on the jquery.inputmask base
1831
+ */
1832
+ (function ($) {
1833
+ //date & time aliases
1834
+ $.extend($.inputmask.defaults.definitions, {
1835
+ 'h': { //hours
1836
+ validator: "[01][0-9]|2[0-3]",
1837
+ cardinality: 2,
1838
+ prevalidator: [{ validator: "[0-2]", cardinality: 1 }]
1839
+ },
1840
+ 's': { //seconds || minutes
1841
+ validator: "[0-5][0-9]",
1842
+ cardinality: 2,
1843
+ prevalidator: [{ validator: "[0-5]", cardinality: 1 }]
1844
+ },
1845
+ 'd': { //basic day
1846
+ validator: "0[1-9]|[12][0-9]|3[01]",
1847
+ cardinality: 2,
1848
+ prevalidator: [{ validator: "[0-3]", cardinality: 1 }]
1849
+ },
1850
+ 'm': { //basic month
1851
+ validator: "0[1-9]|1[012]",
1852
+ cardinality: 2,
1853
+ prevalidator: [{ validator: "[01]", cardinality: 1 }]
1854
+ },
1855
+ 'y': { //basic year
1856
+ validator: "(19|20)\\d{2}",
1857
+ cardinality: 4,
1858
+ prevalidator: [
1859
+ { validator: "[12]", cardinality: 1 },
1860
+ { validator: "(19|20)", cardinality: 2 },
1861
+ { validator: "(19|20)\\d", cardinality: 3 }
1862
+ ]
1863
+ }
1864
+ });
1865
+ $.extend($.inputmask.defaults.aliases, {
1866
+ 'dd/mm/yyyy': {
1867
+ mask: "1/2/y",
1868
+ placeholder: "dd/mm/yyyy",
1869
+ regex: {
1870
+ val1pre: new RegExp("[0-3]"), //daypre
1871
+ val1: new RegExp("0[1-9]|[12][0-9]|3[01]"), //day
1872
+ val2pre: function (separator) { var escapedSeparator = $.inputmask.escapeRegex.call(this, separator); return new RegExp("((0[1-9]|[12][0-9]|3[01])" + escapedSeparator + "[01])"); }, //monthpre
1873
+ val2: function (separator) { var escapedSeparator = $.inputmask.escapeRegex.call(this, separator); return new RegExp("((0[1-9]|[12][0-9])" + escapedSeparator + "(0[1-9]|1[012]))|(30" + escapedSeparator + "(0[13-9]|1[012]))|(31" + escapedSeparator + "(0[13578]|1[02]))"); }//month
1874
+ },
1875
+ leapday: "29/02/",
1876
+ separator: '/',
1877
+ yearrange: { minyear: 1900, maxyear: 2099 },
1878
+ isInYearRange: function (chrs, minyear, maxyear) {
1879
+ var enteredyear = parseInt(chrs.concat(minyear.toString().slice(chrs.length)));
1880
+ var enteredyear2 = parseInt(chrs.concat(maxyear.toString().slice(chrs.length)));
1881
+ return (enteredyear != NaN ? minyear <= enteredyear && enteredyear <= maxyear : false) ||
1882
+ (enteredyear2 != NaN ? minyear <= enteredyear2 && enteredyear2 <= maxyear : false);
1883
+ },
1884
+ determinebaseyear: function (minyear, maxyear, hint) {
1885
+ var currentyear = (new Date()).getFullYear();
1886
+ if (minyear > currentyear) return minyear;
1887
+ if (maxyear < currentyear) {
1888
+ var maxYearPrefix = maxyear.toString().slice(0, 2);
1889
+ var maxYearPostfix = maxyear.toString().slice(2, 4);
1890
+ while (maxyear < maxYearPrefix + hint) {
1891
+ maxYearPrefix--;
1892
+ }
1893
+ var maxxYear = maxYearPrefix + maxYearPostfix;
1894
+ return minyear > maxxYear ? minyear : maxxYear;
1895
+ }
1896
+
1897
+ return currentyear;
1898
+ },
1899
+ onKeyUp: function (e, buffer, opts) {
1900
+ var $input = $(this);
1901
+ if (e.ctrlKey && e.keyCode == opts.keyCode.RIGHT) {
1902
+ var today = new Date();
1903
+ $input.val(today.getDate().toString() + (today.getMonth() + 1).toString() + today.getFullYear().toString());
1904
+ }
1905
+ },
1906
+ definitions: {
1907
+ '1': { //val1 ~ day or month
1908
+ validator: function (chrs, buffer, pos, strict, opts) {
1909
+ var isValid = opts.regex.val1.test(chrs);
1910
+ if (!strict && !isValid) {
1911
+ if (chrs.charAt(1) == opts.separator || "-./".indexOf(chrs.charAt(1)) != -1) {
1912
+ isValid = opts.regex.val1.test("0" + chrs.charAt(0));
1913
+ if (isValid) {
1914
+ buffer[pos - 1] = "0";
1915
+ return { "pos": pos, "c": chrs.charAt(0) };
1916
+ }
1917
+ }
1918
+ }
1919
+ return isValid;
1920
+ },
1921
+ cardinality: 2,
1922
+ prevalidator: [{
1923
+ validator: function (chrs, buffer, pos, strict, opts) {
1924
+ var isValid = opts.regex.val1pre.test(chrs);
1925
+ if (!strict && !isValid) {
1926
+ isValid = opts.regex.val1.test("0" + chrs);
1927
+ if (isValid) {
1928
+ buffer[pos] = "0";
1929
+ pos++;
1930
+ return { "pos": pos };
1931
+ }
1932
+ }
1933
+ return isValid;
1934
+ }, cardinality: 1
1935
+ }]
1936
+ },
1937
+ '2': { //val2 ~ day or month
1938
+ validator: function (chrs, buffer, pos, strict, opts) {
1939
+ var frontValue = buffer.join('').substr(0, 3);
1940
+ if (frontValue.indexOf(opts.placeholder[0]) != -1) frontValue = "01" + opts.separator;
1941
+ var isValid = opts.regex.val2(opts.separator).test(frontValue + chrs);
1942
+ if (!strict && !isValid) {
1943
+ if (chrs.charAt(1) == opts.separator || "-./".indexOf(chrs.charAt(1)) != -1) {
1944
+ isValid = opts.regex.val2(opts.separator).test(frontValue + "0" + chrs.charAt(0));
1945
+ if (isValid) {
1946
+ buffer[pos - 1] = "0";
1947
+ return { "pos": pos, "c": chrs.charAt(0) };
1948
+ }
1949
+ }
1950
+ }
1951
+ return isValid;
1952
+ },
1953
+ cardinality: 2,
1954
+ prevalidator: [{
1955
+ validator: function (chrs, buffer, pos, strict, opts) {
1956
+ var frontValue = buffer.join('').substr(0, 3);
1957
+ if (frontValue.indexOf(opts.placeholder[0]) != -1) frontValue = "01" + opts.separator;
1958
+ var isValid = opts.regex.val2pre(opts.separator).test(frontValue + chrs);
1959
+ if (!strict && !isValid) {
1960
+ isValid = opts.regex.val2(opts.separator).test(frontValue + "0" + chrs);
1961
+ if (isValid) {
1962
+ buffer[pos] = "0";
1963
+ pos++;
1964
+ return { "pos": pos };
1965
+ }
1966
+ }
1967
+ return isValid;
1968
+ }, cardinality: 1
1969
+ }]
1970
+ },
1971
+ 'y': { //year
1972
+ validator: function (chrs, buffer, pos, strict, opts) {
1973
+ if (opts.isInYearRange(chrs, opts.yearrange.minyear, opts.yearrange.maxyear)) {
1974
+ var dayMonthValue = buffer.join('').substr(0, 6);
1975
+ if (dayMonthValue != opts.leapday)
1976
+ return true;
1977
+ else {
1978
+ var year = parseInt(chrs, 10);//detect leap year
1979
+ if (year % 4 === 0)
1980
+ if (year % 100 === 0)
1981
+ if (year % 400 === 0)
1982
+ return true;
1983
+ else return false;
1984
+ else return true;
1985
+ else return false;
1986
+ }
1987
+ } else return false;
1988
+ },
1989
+ cardinality: 4,
1990
+ prevalidator: [
1991
+ {
1992
+ validator: function (chrs, buffer, pos, strict, opts) {
1993
+ var isValid = opts.isInYearRange(chrs, opts.yearrange.minyear, opts.yearrange.maxyear);
1994
+ if (!strict && !isValid) {
1995
+ var yearPrefix = opts.determinebaseyear(opts.yearrange.minyear, opts.yearrange.maxyear, chrs + "0").toString().slice(0, 1);
1996
+
1997
+ isValid = opts.isInYearRange(yearPrefix + chrs, opts.yearrange.minyear, opts.yearrange.maxyear);
1998
+ if (isValid) {
1999
+ buffer[pos++] = yearPrefix[0];
2000
+ return { "pos": pos };
2001
+ }
2002
+ yearPrefix = opts.determinebaseyear(opts.yearrange.minyear, opts.yearrange.maxyear, chrs + "0").toString().slice(0, 2);
2003
+
2004
+ isValid = opts.isInYearRange(yearPrefix + chrs, opts.yearrange.minyear, opts.yearrange.maxyear);
2005
+ if (isValid) {
2006
+ buffer[pos++] = yearPrefix[0];
2007
+ buffer[pos++] = yearPrefix[1];
2008
+ return { "pos": pos };
2009
+ }
2010
+ }
2011
+ return isValid;
2012
+ },
2013
+ cardinality: 1
2014
+ },
2015
+ {
2016
+ validator: function (chrs, buffer, pos, strict, opts) {
2017
+ var isValid = opts.isInYearRange(chrs, opts.yearrange.minyear, opts.yearrange.maxyear);
2018
+ if (!strict && !isValid) {
2019
+ var yearPrefix = opts.determinebaseyear(opts.yearrange.minyear, opts.yearrange.maxyear, chrs).toString().slice(0, 2);
2020
+
2021
+ isValid = opts.isInYearRange(chrs[0] + yearPrefix[1] + chrs[1], opts.yearrange.minyear, opts.yearrange.maxyear);
2022
+ if (isValid) {
2023
+ buffer[pos++] = yearPrefix[1];
2024
+ return { "pos": pos };
2025
+ }
2026
+
2027
+ yearPrefix = opts.determinebaseyear(opts.yearrange.minyear, opts.yearrange.maxyear, chrs).toString().slice(0, 2);
2028
+ if (opts.isInYearRange(yearPrefix + chrs, opts.yearrange.minyear, opts.yearrange.maxyear)) {
2029
+ var dayMonthValue = buffer.join('').substr(0, 6);
2030
+ if (dayMonthValue != opts.leapday)
2031
+ isValid = true;
2032
+ else {
2033
+ var year = parseInt(chrs, 10);//detect leap year
2034
+ if (year % 4 === 0)
2035
+ if (year % 100 === 0)
2036
+ if (year % 400 === 0)
2037
+ isValid = true;
2038
+ else isValid = false;
2039
+ else isValid = true;
2040
+ else isValid = false;
2041
+ }
2042
+ } else isValid = false;
2043
+ if (isValid) {
2044
+ buffer[pos - 1] = yearPrefix[0];
2045
+ buffer[pos++] = yearPrefix[1];
2046
+ buffer[pos++] = chrs[0];
2047
+ return { "pos": pos };
2048
+ }
2049
+ }
2050
+ return isValid;
2051
+ }, cardinality: 2
2052
+ },
2053
+ {
2054
+ validator: function (chrs, buffer, pos, strict, opts) {
2055
+ return opts.isInYearRange(chrs, opts.yearrange.minyear, opts.yearrange.maxyear);
2056
+ }, cardinality: 3
2057
+ }
2058
+ ]
2059
+ }
2060
+ },
2061
+ insertMode: false,
2062
+ autoUnmask: false
2063
+ },
2064
+ 'mm/dd/yyyy': {
2065
+ placeholder: "mm/dd/yyyy",
2066
+ alias: "dd/mm/yyyy", //reuse functionality of dd/mm/yyyy alias
2067
+ regex: {
2068
+ val2pre: function (separator) { var escapedSeparator = $.inputmask.escapeRegex.call(this, separator); return new RegExp("((0[13-9]|1[012])" + escapedSeparator + "[0-3])|(02" + escapedSeparator + "[0-2])"); }, //daypre
2069
+ val2: function (separator) { var escapedSeparator = $.inputmask.escapeRegex.call(this, separator); return new RegExp("((0[1-9]|1[012])" + escapedSeparator + "(0[1-9]|[12][0-9]))|((0[13-9]|1[012])" + escapedSeparator + "30)|((0[13578]|1[02])" + escapedSeparator + "31)"); }, //day
2070
+ val1pre: new RegExp("[01]"), //monthpre
2071
+ val1: new RegExp("0[1-9]|1[012]") //month
2072
+ },
2073
+ leapday: "02/29/",
2074
+ onKeyUp: function (e, buffer, opts) {
2075
+ var $input = $(this);
2076
+ if (e.ctrlKey && e.keyCode == opts.keyCode.RIGHT) {
2077
+ var today = new Date();
2078
+ $input.val((today.getMonth() + 1).toString() + today.getDate().toString() + today.getFullYear().toString());
2079
+ }
2080
+ }
2081
+ },
2082
+ 'yyyy/mm/dd': {
2083
+ mask: "y/1/2",
2084
+ placeholder: "yyyy/mm/dd",
2085
+ alias: "mm/dd/yyyy",
2086
+ leapday: "/02/29",
2087
+ onKeyUp: function (e, buffer, opts) {
2088
+ var $input = $(this);
2089
+ if (e.ctrlKey && e.keyCode == opts.keyCode.RIGHT) {
2090
+ var today = new Date();
2091
+ $input.val(today.getFullYear().toString() + (today.getMonth() + 1).toString() + today.getDate().toString());
2092
+ }
2093
+ },
2094
+ definitions: {
2095
+ '2': { //val2 ~ day or month
2096
+ validator: function (chrs, buffer, pos, strict, opts) {
2097
+ var frontValue = buffer.join('').substr(5, 3);
2098
+ if (frontValue.indexOf(opts.placeholder[5]) != -1) frontValue = "01" + opts.separator;
2099
+ var isValid = opts.regex.val2(opts.separator).test(frontValue + chrs);
2100
+ if (!strict && !isValid) {
2101
+ if (chrs.charAt(1) == opts.separator || "-./".indexOf(chrs.charAt(1)) != -1) {
2102
+ isValid = opts.regex.val2(opts.separator).test(frontValue + "0" + chrs.charAt(0));
2103
+ if (isValid) {
2104
+ buffer[pos - 1] = "0";
2105
+ return { "pos": pos, "c": chrs.charAt(0) };
2106
+ }
2107
+ }
2108
+ }
2109
+
2110
+ //check leap yeap
2111
+ if (isValid) {
2112
+ var dayMonthValue = buffer.join('').substr(4, 4) + chrs;
2113
+ if (dayMonthValue != opts.leapday)
2114
+ return true;
2115
+ else {
2116
+ var year = parseInt(buffer.join('').substr(0, 4), 10); //detect leap year
2117
+ if (year % 4 === 0)
2118
+ if (year % 100 === 0)
2119
+ if (year % 400 === 0)
2120
+ return true;
2121
+ else return false;
2122
+ else return true;
2123
+ else return false;
2124
+ }
2125
+ }
2126
+
2127
+ return isValid;
2128
+ },
2129
+ cardinality: 2,
2130
+ prevalidator: [{
2131
+ validator: function (chrs, buffer, pos, strict, opts) {
2132
+ var frontValue = buffer.join('').substr(5, 3);
2133
+ if (frontValue.indexOf(opts.placeholder[5]) != -1) frontValue = "01" + opts.separator;
2134
+ var isValid = opts.regex.val2pre(opts.separator).test(frontValue + chrs);
2135
+ if (!strict && !isValid) {
2136
+ isValid = opts.regex.val2(opts.separator).test(frontValue + "0" + chrs);
2137
+ if (isValid) {
2138
+ buffer[pos] = "0";
2139
+ pos++;
2140
+ return { "pos": pos };
2141
+ }
2142
+ }
2143
+ return isValid;
2144
+ }, cardinality: 1
2145
+ }]
2146
+ }
2147
+ }
2148
+ },
2149
+ 'dd.mm.yyyy': {
2150
+ mask: "1.2.y",
2151
+ placeholder: "dd.mm.yyyy",
2152
+ leapday: "29.02.",
2153
+ separator: '.',
2154
+ alias: "dd/mm/yyyy"
2155
+ },
2156
+ 'dd-mm-yyyy': {
2157
+ mask: "1-2-y",
2158
+ placeholder: "dd-mm-yyyy",
2159
+ leapday: "29-02-",
2160
+ separator: '-',
2161
+ alias: "dd/mm/yyyy"
2162
+ },
2163
+ 'mm.dd.yyyy': {
2164
+ mask: "1.2.y",
2165
+ placeholder: "mm.dd.yyyy",
2166
+ leapday: "02.29.",
2167
+ separator: '.',
2168
+ alias: "mm/dd/yyyy"
2169
+ },
2170
+ 'mm-dd-yyyy': {
2171
+ mask: "1-2-y",
2172
+ placeholder: "mm-dd-yyyy",
2173
+ leapday: "02-29-",
2174
+ separator: '-',
2175
+ alias: "mm/dd/yyyy"
2176
+ },
2177
+ 'yyyy.mm.dd': {
2178
+ mask: "y.1.2",
2179
+ placeholder: "yyyy.mm.dd",
2180
+ leapday: ".02.29",
2181
+ separator: '.',
2182
+ alias: "yyyy/mm/dd"
2183
+ },
2184
+ 'yyyy-mm-dd': {
2185
+ mask: "y-1-2",
2186
+ placeholder: "yyyy-mm-dd",
2187
+ leapday: "-02-29",
2188
+ separator: '-',
2189
+ alias: "yyyy/mm/dd"
2190
+ },
2191
+ 'datetime': {
2192
+ mask: "1/2/y h:s",
2193
+ placeholder: "dd/mm/yyyy hh:mm",
2194
+ alias: "dd/mm/yyyy",
2195
+ regex: {
2196
+ hrspre: new RegExp("[012]"), //hours pre
2197
+ hrs24: new RegExp("2[0-9]|1[3-9]"),
2198
+ hrs: new RegExp("[01][0-9]|2[0-3]"), //hours
2199
+ ampm: new RegExp("^[a|p|A|P][m|M]")
2200
+ },
2201
+ timeseparator: ':',
2202
+ hourFormat: "24", // or 12
2203
+ definitions: {
2204
+ 'h': { //hours
2205
+ validator: function (chrs, buffer, pos, strict, opts) {
2206
+ var isValid = opts.regex.hrs.test(chrs);
2207
+ if (!strict && !isValid) {
2208
+ if (chrs.charAt(1) == opts.timeseparator || "-.:".indexOf(chrs.charAt(1)) != -1) {
2209
+ isValid = opts.regex.hrs.test("0" + chrs.charAt(0));
2210
+ if (isValid) {
2211
+ buffer[pos - 1] = "0";
2212
+ buffer[pos] = chrs.charAt(0);
2213
+ pos++;
2214
+ return { "pos": pos };
2215
+ }
2216
+ }
2217
+ }
2218
+
2219
+ if (isValid && opts.hourFormat !== "24" && opts.regex.hrs24.test(chrs)) {
2220
+
2221
+ var tmp = parseInt(chrs, 10);
2222
+
2223
+ if (tmp == 24) {
2224
+ buffer[pos + 5] = "a";
2225
+ buffer[pos + 6] = "m";
2226
+ } else {
2227
+ buffer[pos + 5] = "p";
2228
+ buffer[pos + 6] = "m";
2229
+ }
2230
+
2231
+ tmp = tmp - 12;
2232
+
2233
+ if (tmp < 10) {
2234
+ buffer[pos] = tmp.toString();
2235
+ buffer[pos - 1] = "0";
2236
+ } else {
2237
+ buffer[pos] = tmp.toString().charAt(1);
2238
+ buffer[pos - 1] = tmp.toString().charAt(0);
2239
+ }
2240
+
2241
+ return { "pos": pos, "c": buffer[pos] };
2242
+ }
2243
+
2244
+ return isValid;
2245
+ },
2246
+ cardinality: 2,
2247
+ prevalidator: [{
2248
+ validator: function (chrs, buffer, pos, strict, opts) {
2249
+ var isValid = opts.regex.hrspre.test(chrs);
2250
+ if (!strict && !isValid) {
2251
+ isValid = opts.regex.hrs.test("0" + chrs);
2252
+ if (isValid) {
2253
+ buffer[pos] = "0";
2254
+ pos++;
2255
+ return { "pos": pos };
2256
+ }
2257
+ }
2258
+ return isValid;
2259
+ }, cardinality: 1
2260
+ }]
2261
+ },
2262
+ 't': { //am/pm
2263
+ validator: function (chrs, buffer, pos, strict, opts) {
2264
+ return opts.regex.ampm.test(chrs + "m");
2265
+ },
2266
+ casing: "lower",
2267
+ cardinality: 1
2268
+ }
2269
+ },
2270
+ insertMode: false,
2271
+ autoUnmask: false
2272
+ },
2273
+ 'datetime12': {
2274
+ mask: "1/2/y h:s t\\m",
2275
+ placeholder: "dd/mm/yyyy hh:mm xm",
2276
+ alias: "datetime",
2277
+ hourFormat: "12"
2278
+ },
2279
+ 'hh:mm t': {
2280
+ mask: "h:s t\\m",
2281
+ placeholder: "hh:mm xm",
2282
+ alias: "datetime",
2283
+ hourFormat: "12"
2284
+ },
2285
+ 'h:s t': {
2286
+ mask: "h:s t\\m",
2287
+ placeholder: "hh:mm xm",
2288
+ alias: "datetime",
2289
+ hourFormat: "12"
2290
+ },
2291
+ 'hh:mm:ss': {
2292
+ mask: "h:s:s",
2293
+ autoUnmask: false
2294
+ },
2295
+ 'hh:mm': {
2296
+ mask: "h:s",
2297
+ autoUnmask: false
2298
+ },
2299
+ 'date': {
2300
+ alias: "dd/mm/yyyy" // "mm/dd/yyyy"
2301
+ },
2302
+ 'mm/yyyy': {
2303
+ mask: "1/y",
2304
+ placeholder: "mm/yyyy",
2305
+ leapday: "donotuse",
2306
+ separator: '/',
2307
+ alias: "mm/dd/yyyy"
2308
+ }
2309
+ });
2310
+ })(jQuery);
2311
+ /*
2312
+ Input Mask plugin extensions
2313
+ http://github.com/RobinHerbots/jquery.inputmask
2314
+ Copyright (c) 2010 - 2014 Robin Herbots
2315
+ Licensed under the MIT license (http://www.opensource.org/licenses/mit-license.php)
2316
+ Version: 2.5.5
2317
+
2318
+ Optional extensions on the jquery.inputmask base
2319
+ */
2320
+ (function ($) {
2321
+ //number aliases
2322
+ $.extend($.inputmask.defaults.aliases, {
2323
+ 'decimal': {
2324
+ mask: "~",
2325
+ placeholder: "",
2326
+ repeat: "*",
2327
+ greedy: false,
2328
+ numericInput: false,
2329
+ isNumeric: true,
2330
+ digits: "*", //number of fractionalDigits
2331
+ groupSeparator: "",//",", // | "."
2332
+ radixPoint: ".",
2333
+ groupSize: 3,
2334
+ autoGroup: false,
2335
+ allowPlus: true,
2336
+ allowMinus: true,
2337
+ //todo
2338
+ integerDigits: "*", //number of integerDigits
2339
+ defaultValue: "",
2340
+ prefix: "",
2341
+ suffix: "",
2342
+
2343
+ //todo
2344
+ getMaskLength: function (buffer, greedy, repeat, currentBuffer, opts) { //custom getMaskLength to take the groupSeparator into account
2345
+ var calculatedLength = buffer.length;
2346
+
2347
+ if (!greedy) {
2348
+ if (repeat == "*") {
2349
+ calculatedLength = currentBuffer.length + 1;
2350
+ } else if (repeat > 1) {
2351
+ calculatedLength += (buffer.length * (repeat - 1));
2352
+ }
2353
+ }
2354
+
2355
+ var escapedGroupSeparator = $.inputmask.escapeRegex.call(this, opts.groupSeparator);
2356
+ var escapedRadixPoint = $.inputmask.escapeRegex.call(this, opts.radixPoint);
2357
+ var currentBufferStr = currentBuffer.join(''), strippedBufferStr = currentBufferStr.replace(new RegExp(escapedGroupSeparator, "g"), "").replace(new RegExp(escapedRadixPoint), ""),
2358
+ groupOffset = currentBufferStr.length - strippedBufferStr.length;
2359
+ return calculatedLength + groupOffset;
2360
+ },
2361
+ postFormat: function (buffer, pos, reformatOnly, opts) {
2362
+ if (opts.groupSeparator == "") return pos;
2363
+ var cbuf = buffer.slice(),
2364
+ radixPos = $.inArray(opts.radixPoint, buffer);
2365
+ if (!reformatOnly) {
2366
+ cbuf.splice(pos, 0, "?"); //set position indicator
2367
+ }
2368
+ var bufVal = cbuf.join('');
2369
+ if (opts.autoGroup || (reformatOnly && bufVal.indexOf(opts.groupSeparator) != -1)) {
2370
+ var escapedGroupSeparator = $.inputmask.escapeRegex.call(this, opts.groupSeparator);
2371
+ bufVal = bufVal.replace(new RegExp(escapedGroupSeparator, "g"), '');
2372
+ var radixSplit = bufVal.split(opts.radixPoint);
2373
+ bufVal = radixSplit[0];
2374
+ var reg = new RegExp('([-\+]?[\\d\?]+)([\\d\?]{' + opts.groupSize + '})');
2375
+ while (reg.test(bufVal)) {
2376
+ bufVal = bufVal.replace(reg, '$1' + opts.groupSeparator + '$2');
2377
+ bufVal = bufVal.replace(opts.groupSeparator + opts.groupSeparator, opts.groupSeparator);
2378
+ }
2379
+ if (radixSplit.length > 1)
2380
+ bufVal += opts.radixPoint + radixSplit[1];
2381
+ }
2382
+ buffer.length = bufVal.length; //align the length
2383
+ for (var i = 0, l = bufVal.length; i < l; i++) {
2384
+ buffer[i] = bufVal.charAt(i);
2385
+ }
2386
+ var newPos = $.inArray("?", buffer);
2387
+ if (!reformatOnly) buffer.splice(newPos, 1);
2388
+
2389
+ return reformatOnly ? pos : newPos;
2390
+ },
2391
+ regex: {
2392
+ number: function (opts) {
2393
+ var escapedGroupSeparator = $.inputmask.escapeRegex.call(this, opts.groupSeparator);
2394
+ var escapedRadixPoint = $.inputmask.escapeRegex.call(this, opts.radixPoint);
2395
+ var digitExpression = isNaN(opts.digits) ? opts.digits : '{0,' + opts.digits + '}';
2396
+ var signedExpression = opts.allowPlus || opts.allowMinus ? "[" + (opts.allowPlus ? "\+" : "") + (opts.allowMinus ? "-" : "") + "]?" : "";
2397
+ return new RegExp("^" + signedExpression + "(\\d+|\\d{1," + opts.groupSize + "}((" + escapedGroupSeparator + "\\d{" + opts.groupSize + "})?)+)(" + escapedRadixPoint + "\\d" + digitExpression + ")?$");
2398
+ }
2399
+ },
2400
+ onKeyDown: function (e, buffer, opts) {
2401
+ var $input = $(this), input = this;
2402
+ if (e.keyCode == opts.keyCode.TAB) {
2403
+ var radixPosition = $.inArray(opts.radixPoint, buffer);
2404
+ if (radixPosition != -1) {
2405
+ var masksets = $input.data('_inputmask')['masksets'];
2406
+ var activeMasksetIndex = $input.data('_inputmask')['activeMasksetIndex'];
2407
+ for (var i = 1; i <= opts.digits && i < opts.getMaskLength(masksets[activeMasksetIndex]["_buffer"], masksets[activeMasksetIndex]["greedy"], masksets[activeMasksetIndex]["repeat"], buffer, opts) ; i++) {
2408
+ if (buffer[radixPosition + i] == undefined || buffer[radixPosition + i] == "") buffer[radixPosition + i] = "0";
2409
+ }
2410
+ input._valueSet(buffer.join(''));
2411
+ }
2412
+ } else if (e.keyCode == opts.keyCode.DELETE || e.keyCode == opts.keyCode.BACKSPACE) {
2413
+ opts.postFormat(buffer, 0, true, opts);
2414
+ input._valueSet(buffer.join(''));
2415
+ return true;
2416
+ }
2417
+ },
2418
+ definitions: {
2419
+ '~': { //real number
2420
+ validator: function (chrs, buffer, pos, strict, opts) {
2421
+ var iopts = $.extend({}, opts, { digits: strict ? "*" : opts.digits });
2422
+ if (chrs == "") return false;
2423
+ if (!strict && pos <= 1 && buffer[0] === '0' && new RegExp("[\\d-]").test(chrs) && buffer.join('').length == 1) { //handle first char
2424
+ buffer[0] = "";
2425
+ return { "pos": 0 };
2426
+ }
2427
+
2428
+ var cbuf = strict ? buffer.slice(0, pos) : buffer.slice();
2429
+
2430
+ cbuf.splice(pos, 0, chrs);
2431
+ var bufferStr = cbuf.join('');
2432
+
2433
+ //strip groupseparator
2434
+ var escapedGroupSeparator = $.inputmask.escapeRegex.call(this, opts.groupSeparator);
2435
+ bufferStr = bufferStr.replace(new RegExp(escapedGroupSeparator, "g"), '');
2436
+ if (strict && bufferStr.lastIndexOf(opts.radixPoint) == bufferStr.length - 1) {
2437
+ var escapedRadixPoint = $.inputmask.escapeRegex.call(this, opts.radixPoint);
2438
+ bufferStr = bufferStr.replace(new RegExp(escapedRadixPoint, "g"), '');
2439
+ }
2440
+ if (!strict && bufferStr == "") return false;
2441
+
2442
+ var isValid = opts.regex.number(iopts).test(bufferStr);
2443
+ if (!isValid) {
2444
+ //let's help the regex a bit
2445
+ bufferStr += "0";
2446
+ isValid = opts.regex.number(iopts).test(bufferStr);
2447
+ if (!isValid) {
2448
+ //make a valid group
2449
+ var lastGroupSeparator = bufferStr.lastIndexOf(opts.groupSeparator);
2450
+ for (var i = bufferStr.length - lastGroupSeparator; i <= 3; i++) {
2451
+ bufferStr += "0";
2452
+ }
2453
+
2454
+ isValid = opts.regex.number(iopts).test(bufferStr);
2455
+ if (!isValid && !strict) {
2456
+ if (chrs == opts.radixPoint) {
2457
+ isValid = opts.regex.number(iopts).test("0" + bufferStr + "0");
2458
+ if (isValid) {
2459
+ buffer[pos] = "0";
2460
+ pos++;
2461
+ return { "pos": pos };
2462
+ }
2463
+ }
2464
+ }
2465
+ }
2466
+ }
2467
+
2468
+ if (isValid != false && !strict && chrs != opts.radixPoint) {
2469
+ var newPos = opts.postFormat(buffer, pos, (chrs == "-" || chrs == "+") ? true : false, opts);
2470
+ return { "pos": newPos };
2471
+ }
2472
+
2473
+ return isValid;
2474
+ },
2475
+ cardinality: 1,
2476
+ prevalidator: null
2477
+ }
2478
+ },
2479
+ insertMode: true,
2480
+ autoUnmask: false
2481
+ },
2482
+ 'integer': {
2483
+ regex: {
2484
+ number: function (opts) {
2485
+ var escapedGroupSeparator = $.inputmask.escapeRegex.call(this, opts.groupSeparator);
2486
+ var signedExpression = opts.allowPlus || opts.allowMinus ? "[" + (opts.allowPlus ? "\+" : "") + (opts.allowMinus ? "-" : "") + "]?" : "";
2487
+ return new RegExp("^" + signedExpression + "(\\d+|\\d{1," + opts.groupSize + "}((" + escapedGroupSeparator + "\\d{" + opts.groupSize + "})?)+)$");
2488
+ }
2489
+ },
2490
+ alias: "decimal"
2491
+ }
2492
+ });
2493
+ })(jQuery);
2494
+ /*
2495
+ Input Mask plugin extensions
2496
+ http://github.com/RobinHerbots/jquery.inputmask
2497
+ Copyright (c) 2010 - 2014 Robin Herbots
2498
+ Licensed under the MIT license (http://www.opensource.org/licenses/mit-license.php)
2499
+ Version: 2.5.5
2500
+
2501
+ Regex extensions on the jquery.inputmask base
2502
+ Allows for using regular expressions as a mask
2503
+ */
2504
+ (function ($) {
2505
+ $.extend($.inputmask.defaults.aliases, { // $(selector).inputmask("Regex", { regex: "[0-9]*"}
2506
+ 'Regex': {
2507
+ mask: "r",
2508
+ greedy: false,
2509
+ repeat: "*",
2510
+ regex: null,
2511
+ regexTokens: null,
2512
+ //Thx to https://github.com/slevithan/regex-colorizer for the tokenizer regex
2513
+ tokenizer: /\[\^?]?(?:[^\\\]]+|\\[\S\s]?)*]?|\\(?:0(?:[0-3][0-7]{0,2}|[4-7][0-7]?)?|[1-9][0-9]*|x[0-9A-Fa-f]{2}|u[0-9A-Fa-f]{4}|c[A-Za-z]|[\S\s]?)|\((?:\?[:=!]?)?|(?:[?*+]|\{[0-9]+(?:,[0-9]*)?\})\??|[^.?*+^${[()|\\]+|./g,
2514
+ quantifierFilter: /[0-9]+[^,]/,
2515
+ definitions: {
2516
+ 'r': {
2517
+ validator: function (chrs, buffer, pos, strict, opts) {
2518
+ function regexToken(isGroup, isQuantifier) {
2519
+ this.matches = [];
2520
+ this.isGroup = isGroup || false;
2521
+ this.isQuantifier = isQuantifier || false;
2522
+ this.quantifier = { min: 1, max: 1 };
2523
+ this.repeaterPart = undefined;
2524
+ }
2525
+ function analyseRegex() {
2526
+ var currentToken = new regexToken(), match, m, opengroups = [];
2527
+
2528
+ opts.regexTokens = [];
2529
+
2530
+ // The tokenizer regex does most of the tokenization grunt work
2531
+ while (match = opts.tokenizer.exec(opts.regex)) {
2532
+ m = match[0];
2533
+ switch (m.charAt(0)) {
2534
+ case "(": // Group opening
2535
+ opengroups.push(new regexToken(true));
2536
+ break;
2537
+ case ")": // Group closing
2538
+ var groupToken = opengroups.pop();
2539
+ if (opengroups.length > 0) {
2540
+ opengroups[opengroups.length - 1]["matches"].push(groupToken);
2541
+ } else {
2542
+ currentToken.matches.push(groupToken);
2543
+ }
2544
+ break;
2545
+ case "{": case "+": case "*": //Quantifier
2546
+ var quantifierToken = new regexToken(false, true);
2547
+ m = m.replace(/[{}]/g, "");
2548
+ var mq = m.split(","), mq0 = isNaN(mq[0]) ? mq[0] : parseInt(mq[0]), mq1 = mq.length == 1 ? mq0 : (isNaN(mq[1]) ? mq[1] : parseInt(mq[1]));
2549
+ quantifierToken.quantifier = { min: mq0, max: mq1 };
2550
+ if (opengroups.length > 0) {
2551
+ var matches = opengroups[opengroups.length - 1]["matches"];
2552
+ match = matches.pop();
2553
+ if (!match["isGroup"]) {
2554
+ var groupToken = new regexToken(true);
2555
+ groupToken.matches.push(match);
2556
+ match = groupToken;
2557
+ }
2558
+ matches.push(match);
2559
+ matches.push(quantifierToken);
2560
+ } else {
2561
+ match = currentToken.matches.pop();
2562
+ if (!match["isGroup"]) {
2563
+ var groupToken = new regexToken(true);
2564
+ groupToken.matches.push(match);
2565
+ match = groupToken;
2566
+ }
2567
+ currentToken.matches.push(match);
2568
+ currentToken.matches.push(quantifierToken);
2569
+ }
2570
+ break;
2571
+ default:
2572
+ if (opengroups.length > 0) {
2573
+ opengroups[opengroups.length - 1]["matches"].push(m);
2574
+ } else {
2575
+ currentToken.matches.push(m);
2576
+ }
2577
+ break;
2578
+ }
2579
+ }
2580
+
2581
+ if (currentToken.matches.length > 0)
2582
+ opts.regexTokens.push(currentToken);
2583
+ };
2584
+
2585
+ function validateRegexToken(token, fromGroup) {
2586
+ var isvalid = false;
2587
+ if (fromGroup) {
2588
+ regexPart += "(";
2589
+ openGroupCount++;
2590
+ }
2591
+ for (var mndx = 0; mndx < token["matches"].length; mndx++) {
2592
+ var matchToken = token["matches"][mndx];
2593
+ if (matchToken["isGroup"] == true) {
2594
+ isvalid = validateRegexToken(matchToken, true);
2595
+ } else if (matchToken["isQuantifier"] == true) {
2596
+ var crrntndx = token["matches"].indexOf(matchToken),
2597
+ matchGroup = token["matches"][crrntndx - 1];
2598
+ var regexPartBak = regexPart;
2599
+ if (isNaN(matchToken.quantifier.max)) {
2600
+ while (matchToken["repeaterPart"] && matchToken["repeaterPart"] != regexPart && matchToken["repeaterPart"].length > regexPart.length) {
2601
+ isvalid = validateRegexToken(matchGroup, true);
2602
+ if (isvalid) break;
2603
+ }
2604
+ isvalid = isvalid || validateRegexToken(matchGroup, true);
2605
+ if (isvalid) matchToken["repeaterPart"] = regexPart;
2606
+ regexPart = regexPartBak + matchToken.quantifier.max;
2607
+ } else {
2608
+ for (var i = 0, qm = matchToken.quantifier.max - 1; i < qm; i++) {
2609
+ isvalid = validateRegexToken(matchGroup, true);
2610
+ if (isvalid) break;
2611
+ }
2612
+ regexPart = regexPartBak + "{" + matchToken.quantifier.min + "," + matchToken.quantifier.max + "}";
2613
+ }
2614
+ } else if (matchToken["matches"] != undefined) {
2615
+ for (var k = 0; k < matchToken.length; k++) {
2616
+ isvalid = validateRegexToken(matchToken[k], fromGroup);
2617
+ if (isvalid) break;
2618
+ }
2619
+ } else {
2620
+ var testExp;
2621
+ if (matchToken[0] == "[") {
2622
+ testExp = regexPart;
2623
+ testExp += matchToken;
2624
+ for (var j = 0; j < openGroupCount; j++) {
2625
+ testExp += ")";
2626
+ }
2627
+ var exp = new RegExp("^(" + testExp + ")$");
2628
+ isvalid = exp.test(bufferStr);
2629
+ } else {
2630
+ for (var l = 0, tl = matchToken.length; l < tl; l++) {
2631
+ if (matchToken[l] == "\\") continue;
2632
+ testExp = regexPart;
2633
+ testExp += matchToken.substr(0, l + 1);
2634
+ testExp = testExp.replace(/\|$/, "");
2635
+ for (var j = 0; j < openGroupCount; j++) {
2636
+ testExp += ")";
2637
+ }
2638
+ var exp = new RegExp("^(" + testExp + ")$");
2639
+ isvalid = exp.test(bufferStr);
2640
+ if (isvalid) break;
2641
+ }
2642
+ }
2643
+ regexPart += matchToken;
2644
+ }
2645
+ if (isvalid) break;
2646
+ }
2647
+
2648
+ if (fromGroup) {
2649
+ regexPart += ")";
2650
+ openGroupCount--;
2651
+ }
2652
+
2653
+ return isvalid;
2654
+ }
2655
+
2656
+
2657
+ if (opts.regexTokens == null) {
2658
+ analyseRegex();
2659
+ }
2660
+
2661
+ var cbuffer = buffer.slice(), regexPart = "", isValid = false, openGroupCount = 0;
2662
+ cbuffer.splice(pos, 0, chrs);
2663
+ var bufferStr = cbuffer.join('');
2664
+ for (var i = 0; i < opts.regexTokens.length; i++) {
2665
+ var regexToken = opts.regexTokens[i];
2666
+ isValid = validateRegexToken(regexToken, regexToken["isGroup"]);
2667
+ if (isValid) break;
2668
+ }
2669
+
2670
+ return isValid;
2671
+ },
2672
+ cardinality: 1
2673
+ }
2674
+ }
2675
+ }
2676
+ });
2677
+ })(jQuery);
2678
+ /*
2679
+ Input Mask plugin extensions
2680
+ http://github.com/RobinHerbots/jquery.inputmask
2681
+ Copyright (c) 2010 - 2014 Robin Herbots
2682
+ Licensed under the MIT license (http://www.opensource.org/licenses/mit-license.php)
2683
+ Version: 2.5.5
2684
+
2685
+ Phone extension.
2686
+ When using this extension make sure you specify the correct url to get the masks
2687
+
2688
+ $(selector).inputmask("phone", {
2689
+ url: "Scripts/jquery.inputmask/phone-codes/phone-codes.json",
2690
+ onKeyValidation: function () { //show some metadata in the console
2691
+ console.log($(this).inputmask("getmetadata")["name_en"]);
2692
+ }
2693
+ });
2694
+
2695
+
2696
+ */
2697
+ (function ($) {
2698
+ $.extend($.inputmask.defaults.aliases, {
2699
+ 'phone': {
2700
+ url: "phone-codes/phone-codes.json",
2701
+ mask: function (opts) {
2702
+ opts.definitions = {
2703
+ 'p': {
2704
+ validator: function () { return false; },
2705
+ cardinality: 1
2706
+ },
2707
+ '#': {
2708
+ validator: "[0-9]",
2709
+ cardinality: 1
2710
+ }
2711
+ };
2712
+ var maskList = [];
2713
+ $.ajax({
2714
+ url: opts.url,
2715
+ async: false,
2716
+ dataType: 'json',
2717
+ success: function (response) {
2718
+ maskList = response;
2719
+ }
2720
+ });
2721
+
2722
+ maskList.splice(0, 0, "+p(ppp)ppp-pppp");
2723
+ return maskList;
2724
+ }
2725
+ }
2726
+ });
2727
+ })(jQuery);