There's probably plugins out there, but nobody's been too forthcoming with any. Here's something I've knocked up during my lunch break :).
It's not perfect, and could be improved with some tweaking. For example, highlighting multiple characters for deletion is a bit screwy, but hopefully it's not a bad starter for 10. Credit to this post for getting/setting the caret position. Also, it does allow invalid dates right now - 12/34/5678. It wouldn't be too difficult to sort that out. I might stick something on Git and finish it off when I get home.
I've hard-coded it for dd/mm/yyyy
format, but, again, with improvments, it could use the user locale.
$.fn.textboxDatePicker = function() {
var _getCaret = function(el) {
if (el.selectionStart) {
return el.selectionStart;
} else if (document.selection) {
el.focus();
var r = document.selection.createRange();
if (r == null) {
return 0;
}
var re = el.createTextRange(), rc = re.duplicate();
re.moveToBookmark(r.getBookmark());
rc.setEndPoint('EndToStart', re);
return rc.text.length;
}
return 0;
};
var _setCaretPosition = function(elem, caretPos) {
if (caretPos == 2 || caretPos == 5) {
caretPos++;
}
if (elem != null) {
if (elem.createTextRange) {
var range = elem.createTextRange();
range.move('character', caretPos);
range.select();
} else {
if (elem.selectionStart) {
elem.focus();
elem.setSelectionRange(caretPos, caretPos);
}
else elem.focus();
}
}
};
$(this).val('dd/mm/yyyy');
$(this).on("keydown", function(e) {
var keyCode = e.which || e.charCode || e.keyCode;
var key = String.fromCharCode(keyCode);
// arrows, home, end
if ([35, 36].indexOf(keyCode) > -1) {
return true;
}
if (keyCode == 37) {
var newCaretPos = _getCaret(this) - 1;
if ([2, 5].indexOf(newCaretPos) > -1) {
_setCaretPosition(this, newCaretPos - 1);
return false;
}
return true;
}
if (keyCode == 39) {
var newCaretPos = _getCaret(this) + 1;
if ([2, 5].indexOf(newCaretPos) > -1) {
_setCaretPosition(this, newCaretPos + 1);
return false;
}
return true;
}
// backspace
if (keyCode == 8) {
var text = this.value;
var caret = _getCaret(this);
if (caret == 3 || caret == 6) {
caret = caret - 2;
} else {
caret--;
}
if (caret < 0) {
return false;
}
var output = text.substring(0, caret);
key = 'd';
if (caret > 2) {
key = 'm'
};
if (caret > 4) {
key = 'y'
};
this.value = output + key + text.substring(caret + 1);
_setCaretPosition(this, caret);
return false;
}
if (/[0-9]/.test(key)) {
var text = this.value;
var caret = _getCaret(this);
if (caret > 9) {
return false;
}
var output = text.substring(0, caret);
this.value = output + key + text.substring(caret + 1);
_setCaretPosition(this, caret + 1);
}
return false;
});
};
$('.date').textboxDatePicker();
UPDATE
Might be overthinking this. Could you just use 3 separate boxes and style them to look like one, with a little JS to sort out focusing between them?
https://jsfiddle.net/w9by2350/3/
MUCH cleaner!