Skip to content

Commit 58c538b

Browse files
committed
New version 2.5.16
1 parent 5fa7e7d commit 58c538b

File tree

3 files changed

+129
-46
lines changed

3 files changed

+129
-46
lines changed

build/jquery.datetimepicker.full.js

Lines changed: 127 additions & 44 deletions
Original file line numberDiff line numberDiff line change
@@ -2283,58 +2283,141 @@ var datetimepickerFactory = function ($) {
22832283
setCaretPos(input[0], 0);
22842284
}
22852285

2286-
input.on('keydown.xdsoft', function (event) {
2287-
var val = this.value,
2288-
key = event.which,
2289-
pos,
2290-
digit;
2291-
2292-
if (((key >= KEY0 && key <= KEY9) || (key >= _KEY0 && key <= _KEY9)) || (key === BACKSPACE || key === DEL)) {
2293-
pos = getCaretPos(this);
2294-
digit = (key !== BACKSPACE && key !== DEL) ? String.fromCharCode((_KEY0 <= key && key <= _KEY9) ? key - KEY0 : key) : '_';
2295-
2296-
if ((key === BACKSPACE || key === DEL) && pos) {
2297-
pos -= 1;
2298-
digit = '_';
2299-
}
2286+
input.on('paste.xdsoft', function (event) {
2287+
// couple options here
2288+
// 1. return false - tell them they can't paste
2289+
// 2. insert over current characters - minimal validation
2290+
// 3. full fledged parsing and validation
2291+
// let's go option 2 for now
2292+
2293+
// fires multiple times for some reason
2294+
2295+
// https://stackoverflow.com/a/30496488/1366033
2296+
var clipboardData = event.clipboardData || event.originalEvent.clipboardData || window.clipboardData,
2297+
pastedData = clipboardData.getData('text'),
2298+
val = this.value,
2299+
pos = this.selectionStart
2300+
2301+
var valueBeforeCursor = val.substr(0, pos);
2302+
var valueAfterPaste = val.substr(pos + pastedData.length);
2303+
2304+
val = valueBeforeCursor + pastedData + valueAfterPaste;
2305+
pos += pastedData.length;
2306+
2307+
if (isValidValue(options.mask, val)) {
2308+
this.value = val;
2309+
setCaretPos(this, pos);
2310+
} else if ($.trim(val) === '') {
2311+
this.value = options.mask.replace(/[0-9]/g, '_');
2312+
} else {
2313+
input.trigger('error_input.xdsoft');
2314+
}
2315+
2316+
event.preventDefault();
2317+
return false;
2318+
});
2319+
2320+
input.on('keydown.xdsoft', function (event) {
2321+
var val = this.value,
2322+
key = event.which,
2323+
pos = this.selectionStart,
2324+
selEnd = this.selectionEnd,
2325+
hasSel = pos !== selEnd,
2326+
digit;
2327+
2328+
// only alow these characters
2329+
if (((key >= KEY0 && key <= KEY9) ||
2330+
(key >= _KEY0 && key <= _KEY9)) ||
2331+
(key === BACKSPACE || key === DEL)) {
2332+
2333+
// get char to insert which is new character or placeholder ('_')
2334+
digit = (key === BACKSPACE || key === DEL) ? '_' :
2335+
String.fromCharCode((_KEY0 <= key && key <= _KEY9) ? key - KEY0 : key);
2336+
2337+
// we're deleting something, we're not at the start, and have normal cursor, move back one
2338+
// if we have a selection length, cursor actually sits behind deletable char, not in front
2339+
if (key === BACKSPACE && pos && !hasSel) {
2340+
pos -= 1;
2341+
}
23002342

2301-
while (/[^0-9_]/.test(options.mask.substr(pos, 1)) && pos < options.mask.length && pos > 0) {
2302-
pos += (key === BACKSPACE || key === DEL) ? -1 : 1;
2303-
}
2343+
// don't stop on a separator, continue whatever direction you were going
2344+
// value char - keep incrementing position while on separator char and we still have room
2345+
// del char - keep decrementing position while on separator char and we still have room
2346+
while (true) {
2347+
var maskValueAtCurPos = options.mask.substr(pos, 1);
2348+
var posShorterThanMaskLength = pos < options.mask.length;
2349+
var posGreaterThanZero = pos > 0;
2350+
var notNumberOrPlaceholder = /[^0-9_]/;
2351+
var curPosOnSep = notNumberOrPlaceholder.test(maskValueAtCurPos);
2352+
var continueMovingPosition = curPosOnSep && posShorterThanMaskLength && posGreaterThanZero
23042353

2305-
val = val.substr(0, pos) + digit + val.substr(pos + 1);
2354+
// if we hit a real char, stay where we are
2355+
if (!continueMovingPosition) break;
23062356

2307-
if ($.trim(val) === '') {
2308-
val = options.mask.replace(/[0-9]/g, '_');
2309-
} else {
2310-
if (pos === options.mask.length) {
2311-
event.preventDefault();
2312-
return false;
2313-
}
2314-
}
2357+
// hitting backspace in a selection, you can possibly go back any further - go forward
2358+
pos += (key === BACKSPACE && !hasSel) ? -1 : 1;
23152359

2316-
pos += (key === BACKSPACE || key === DEL) ? 0 : 1;
2317-
while (/[^0-9_]/.test(options.mask.substr(pos, 1)) && pos < options.mask.length && pos > 0) {
2318-
pos += (key === BACKSPACE || key === DEL) ? -1 : 1;
2319-
}
2360+
}
2361+
2362+
2363+
if (hasSel) {
2364+
// pos might have moved so re-calc length
2365+
var selLength = selEnd - pos
2366+
2367+
// if we have a selection length we will wipe out entire selection and replace with default template for that range
2368+
var defaultBlank = options.mask.replace(/[0-9]/g, '_');
2369+
var defaultBlankSelectionReplacement = defaultBlank.substr(pos, selLength);
2370+
var selReplacementRemainder = defaultBlankSelectionReplacement.substr(1) // might be empty
2371+
2372+
var valueBeforeSel = val.substr(0, pos);
2373+
var insertChars = digit + selReplacementRemainder;
2374+
var charsAfterSelection = val.substr(pos + selLength);
2375+
2376+
val = valueBeforeSel + insertChars + charsAfterSelection
23202377

2321-
if (isValidValue(options.mask, val)) {
2322-
this.value = val;
2323-
setCaretPos(this, pos);
2324-
} else if ($.trim(val) === '') {
2325-
this.value = options.mask.replace(/[0-9]/g, '_');
2326-
} else {
2327-
input.trigger('error_input.xdsoft');
2328-
}
23292378
} else {
2330-
if (([AKEY, CKEY, VKEY, ZKEY, YKEY].indexOf(key) !== -1 && ctrlDown) || [ESC, ARROWUP, ARROWDOWN, ARROWLEFT, ARROWRIGHT, F5, CTRLKEY, TAB, ENTER].indexOf(key) !== -1) {
2331-
return true;
2332-
}
2379+
var valueBeforeCursor = val.substr(0, pos);
2380+
var insertChar = digit;
2381+
var valueAfterNextChar = val.substr(pos + 1);
2382+
2383+
val = valueBeforeCursor + insertChar + valueAfterNextChar
23332384
}
23342385

2335-
event.preventDefault();
2336-
return false;
2337-
});
2386+
if ($.trim(val) === '') {
2387+
// if empty, set to default
2388+
val = defaultBlank
2389+
} else {
2390+
// if at the last character don't need to do anything
2391+
if (pos === options.mask.length) {
2392+
event.preventDefault();
2393+
return false;
2394+
}
2395+
}
2396+
2397+
// resume cursor location
2398+
pos += (key === BACKSPACE) ? 0 : 1;
2399+
// don't stop on a separator, continue whatever direction you were going
2400+
while (/[^0-9_]/.test(options.mask.substr(pos, 1)) && pos < options.mask.length && pos > 0) {
2401+
pos += (key === BACKSPACE) ? 0 : 1;
2402+
}
2403+
2404+
if (isValidValue(options.mask, val)) {
2405+
this.value = val;
2406+
setCaretPos(this, pos);
2407+
} else if ($.trim(val) === '') {
2408+
this.value = options.mask.replace(/[0-9]/g, '_');
2409+
} else {
2410+
input.trigger('error_input.xdsoft');
2411+
}
2412+
} else {
2413+
if (([AKEY, CKEY, VKEY, ZKEY, YKEY].indexOf(key) !== -1 && ctrlDown) || [ESC, ARROWUP, ARROWDOWN, ARROWLEFT, ARROWRIGHT, F5, CTRLKEY, TAB, ENTER].indexOf(key) !== -1) {
2414+
return true;
2415+
}
2416+
}
2417+
2418+
event.preventDefault();
2419+
return false;
2420+
});
23382421
}
23392422
}
23402423

build/jquery.datetimepicker.full.min.js

Lines changed: 1 addition & 1 deletion
Some generated files are not rendered by default. Learn more about customizing how changed files appear on GitHub.

package.json

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
{
22
"name": "jquery-datetimepicker",
3-
"version": "2.5.15",
3+
"version": "2.5.16",
44
"description": "jQuery Plugin DateTimePicker it is DatePicker and TimePicker in one",
55
"main": "build/jquery.datetimepicker.full.min.js",
66
"scripts": {

0 commit comments

Comments
 (0)