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