Skip to content

Commit 1a9c725

Browse files
committed
Fix cursor position
To calculate the correct cursor position, mask characters before and after the cursor are counted separately.
1 parent f6d0afa commit 1a9c725

File tree

1 file changed

+71
-20
lines changed

1 file changed

+71
-20
lines changed

src/jquery.mask.js

Lines changed: 71 additions & 20 deletions
Original file line numberDiff line numberDiff line change
@@ -100,6 +100,8 @@
100100
.on('keydown.mask', function(e) {
101101
el.data('mask-keycode', e.keyCode || e.which);
102102
el.data('mask-previus-value', el.val());
103+
el.data('mask-previus-caret-pos', p.getCaret());
104+
p.maskDigitPosMapOld = p.maskDigitPosMap;
103105
})
104106
.on($.jMaskGlobals.useInput ? 'input.mask' : 'keyup.mask', p.behaviour)
105107
.on('paste.mask drop.mask', function() {
@@ -186,26 +188,64 @@
186188

187189
return r;
188190
},
189-
calculateCaretPosition: function(caretPos, newVal) {
190-
var newValL = newVal.length,
191-
oValue = el.data('mask-previus-value') || '',
192-
oValueL = oValue.length;
193-
194-
// edge cases when erasing digits
195-
if (el.data('mask-keycode') === 8 && oValue !== newVal) {
196-
caretPos = caretPos - (newVal.slice(0, caretPos).length - oValue.slice(0, caretPos).length);
197-
198-
// edge cases when typing new digits
199-
} else if (oValue !== newVal) {
200-
// if the cursor is at the end keep it there
201-
if (caretPos >= oValueL) {
202-
caretPos = newValL;
203-
} else {
204-
caretPos = caretPos + (newVal.slice(0, caretPos).length - oValue.slice(0, caretPos).length);
191+
calculateCaretPosition: function(caretPosNew, newVal) {
192+
var oldVal = el.data('mask-previus-value') || '';
193+
if (oldVal !== newVal) {
194+
var caretPosOld = el.data('mask-previus-caret-pos') || 0,
195+
newValL = newVal.length,
196+
oldValL = oldVal.length,
197+
maskDigitsBeforeCaret = 0,
198+
maskDigitsAfterCaret = 0,
199+
maskDigitsBeforeCaretAll = 0,
200+
maskDigitsBeforeCaretAllOld = 0,
201+
i = 0;
202+
203+
for (i = caretPosNew; i < newValL; i++) {
204+
if (!p.maskDigitPosMap[i]) {
205+
break;
206+
}
207+
maskDigitsAfterCaret++;
208+
}
209+
210+
for (i = caretPosNew - 1; i >= 0; i--) {
211+
if (!p.maskDigitPosMap[i]) {
212+
break;
213+
}
214+
maskDigitsBeforeCaret++;
205215
}
206-
}
207216

208-
return caretPos;
217+
for (i = caretPosNew - 1; i >= 0; i--) {
218+
if (p.maskDigitPosMap[i]) {
219+
maskDigitsBeforeCaretAll++;
220+
}
221+
}
222+
223+
for (i = caretPosOld - 1; i >= 0; i--) {
224+
if (p.maskDigitPosMapOld[i]) {
225+
maskDigitsBeforeCaretAllOld++;
226+
}
227+
}
228+
229+
if (caretPosNew > oldValL) {
230+
// if the cursor is at the end keep it there
231+
caretPosNew = newValL;
232+
}
233+
else if (caretPosOld >= caretPosNew) {
234+
if (!p.maskDigitPosMapOld[caretPosNew]) {
235+
var caretPos = caretPosNew;
236+
caretPosNew -= maskDigitsBeforeCaretAllOld - maskDigitsBeforeCaretAll;
237+
caretPosNew -= maskDigitsBeforeCaret;
238+
if (p.maskDigitPosMap[caretPosNew]) {
239+
caretPosNew = caretPos;
240+
}
241+
}
242+
}
243+
else if (caretPosNew > caretPosOld) {
244+
caretPosNew += maskDigitsBeforeCaretAll - maskDigitsBeforeCaretAllOld;
245+
caretPosNew += maskDigitsAfterCaret;
246+
}
247+
}
248+
return caretPosNew;
209249
},
210250
behaviour: function(e) {
211251
e = e || window.event;
@@ -233,6 +273,8 @@
233273
v = 0, valLen = value.length,
234274
offset = 1, addMethod = 'push',
235275
resetPos = -1,
276+
maskDigitCount = 0,
277+
maskDigitPosArr = [],
236278
lastMaskChar,
237279
check;
238280

@@ -277,6 +319,7 @@
277319
// matched the last untranslated (raw) mask character that we encountered
278320
// likely an insert offset the mask character from the last entry; fall
279321
// through and only increment v
322+
maskDigitCount--;
280323
lastUntranslatedMaskChar = undefined;
281324
} else if (translation.optional) {
282325
m += offset;
@@ -295,9 +338,12 @@
295338
}
296339

297340
if (valDigit === maskDigit) {
341+
maskDigitPosArr.push(v);
298342
v += offset;
299343
} else {
300344
lastUntranslatedMaskChar = maskDigit;
345+
maskDigitPosArr.push(v + maskDigitCount);
346+
maskDigitCount++;
301347
}
302348

303349
m += offset;
@@ -309,7 +355,13 @@
309355
buf.push(lastMaskCharDigit);
310356
}
311357

312-
return buf.join('');
358+
var newVal = buf.join('');
359+
var maskDiff = options.reverse ? newVal.length - valLen : 0;
360+
p.maskDigitPosMap = {};
361+
for (var i = 0; i < maskDigitPosArr.length; i++) {
362+
p.maskDigitPosMap[maskDigitPosArr[i] + maskDiff] = 1;
363+
}
364+
return newVal;
313365
},
314366
callbacks: function (e) {
315367
var val = p.val(),
@@ -538,4 +590,3 @@
538590
}
539591
}, globals.watchInterval);
540592
}, window.jQuery, window.Zepto));
541-

0 commit comments

Comments
 (0)