Insert "/" in MM/YYYY textbox on keypress event - javascript

I want to enter a "/" when user enters MM(2 digit) so it will be like MM/YYYY.
I have done similar for credit card number input which insert a space after 4 digit on keypress.
let ccNumber = e.target.value.split(" ").join("");
if (ccNumber.length > 0) {
ccNumber = ccNumber.match(new RegExp('.{1,4}', 'g')).join(" ");
}
e.target.value = ccNumber;

Fiddle
This works with
Regular keyboard input
Copy/Cut/Paste
Selected text
Adding the /
Because you're programmatically adding the / character, you have to update the cursor position whenever that affects the new input value. This can be more than one character if the user is pasting something. Most of the code complexity revolves around this issue.
There are a lot of comments in the code explaining the various situations that come up because of the /.
Full Code
var date = document.getElementById('date');
date.addEventListener('keypress', updateInput);
date.addEventListener('change', updateInput);
date.addEventListener('paste', updateInput);
date.addEventListener('keydown', removeText);
date.addEventListener('cut', removeText);
function updateInput(event) {
event.preventDefault();
var string = getString(event);
var selectionStart = this.selectionStart;
var selectionEnd = this.selectionEnd;
var selectionLength = selectionEnd - selectionStart;
var sanitizedString = string.replace(/[^0-9]+/g, '');
// Do nothing if nothing is added after sanitization
if (sanitizedString.length === 0) {
return;
}
// Only paste numbers that will fit
var valLength = date.value.replace(/[^0-9]+/g, '').length;
var availableSpace = 6 - valLength + selectionLength;
// If `/` is selected it should not count as available space
if (selectionStart <= 2 && selectionEnd >= 3) {
availableSpace -= 1;
}
// Remove numbers that don't fit
if (sanitizedString.length > availableSpace) {
sanitizedString = sanitizedString.substring(0, availableSpace);
}
var newCursorPosition = selectionEnd + sanitizedString.length - selectionLength;
// Add one to cursor position if a `/` gets inserted
if (selectionStart <= 2 && newCursorPosition >= 2) {
newCursorPosition += 1;
}
// Previous input value before current cursor position
var valueStart = date.value.substring(0, this.selectionStart);
// Previous input value after current cursor position
var valueEnd = date.value.substring(this.selectionEnd, date.value.length);
var proposedValue = valueStart + sanitizedString + valueEnd;
// Remove anything that's not a number
var sanitized = proposedValue.replace(/[^0-9]+/g, '');
format(sanitized);
this.setSelectionRange(newCursorPosition, newCursorPosition);
}
function removeText(event) {
if (event.key === 'Backspace' || event.type === 'cut') {
event.preventDefault();
var selectionStart = this.selectionStart;
var selectionEnd = this.selectionEnd;
var selectionLength = selectionEnd - selectionStart;
// If pressing backspace with no selected text
if (selectionLength === 0 && event.type !== 'cut') {
selectionStart -= 1;
// Remove number from before `/` if attempting to delete `/`
if (selectionStart === 2) {
selectionStart -= 1;
}
}
var valueStart = date.value.substring(0, selectionStart);
var valueEnd = date.value.substring(selectionEnd, date.value.length);
// Account for added `/`
if (selectionStart === 2) {
selectionStart += 1;
}
var proposedValue = valueStart + valueEnd;
var sanitized = proposedValue.replace(/[^0-9]+/g, '');
format(sanitized);
this.setSelectionRange(selectionStart, selectionStart);
}
}
function getString(event) {
if (event.type === 'paste') {
var clipboardData = event.clipboardData || window.clipboardData;
return clipboardData.getData('Text');
} else {
return String.fromCharCode(event.which);
}
}
function format(sanitized) {
var newValue;
var month = sanitized.substring(0, 2);
if (sanitized.length < 2) {
newValue = month;
} else {
var year = sanitized.substring(2, 6);
newValue = month + '/' + year;
}
date.value = newValue;
}
<input id="date" type="text" maxlength="7">

Try:
var date = document.getElementById('date');
date.addEventListener('keypress', function (event) {
var char = String.fromCharCode(event.which),
offset = date.selectionStart;
console.log(offset)
if (/\d/.test(char) && offset < 7) {
if (offset === 2) {
offset += 1;
}
date.value = date.value.substr(0, offset) + char + date.value.substr(offset + 1);
date.selectionStart = date.selectionEnd = offset + 1;
}
if (!event.keyCode) {
event.preventDefault();
}
});
<input id="date" type="text" value="mm/yyyy" maxlength="6" size="6">

function keypress(elem) { // get Input
if (typeof elem == 'string') {
if (document.getElementById(elem)) elem = document.getElementById(elem);
if (typeof elem == 'string') elem = document.getElementsByName(elem).item(0);
}
const el = elem; //handle error if not found input
el.maxLength = 19;
el.addEventListener('keypress', function (e) {
const t = e.keyCode || e.which
if (t == 8 || (t > 47 && t < 58)) { // limit numeric characters and backspace
if (t != 8) {
if (el.value.length == 2) el.value += '/';
if (el.value.length == 5) el.value += '/';
if (el.value.length == 10) el.value += ' ';
if (el.value.length == 13) el.value += ':';
if (el.value.length == 16) el.value += ':';
}
} else {
e.preventDefault();
}
});}

Related

How to add plus one position to setSelectionRange

I am trying to move cursor one more position to the right in input.
var start = this.selectionStart,
end = this.selectionEnd;
this.setSelectionRange(start, end);
This works for keeping position in the same place after input value changed, but iam trying to add one more position to it, because my format code add "-" character after 4 chars.
$("input[name=login-access-token]").keypress(function(event){
var start = this.selectionStart,
end = this.selectionEnd;
console.log(start);
var input = $(this).val();
input = input.replace(/[\W\s\._\-]+/g, '');
var split = 4;
var chunk = [];
for (var i = 0, len = input.length; i < len; i += split) {
split = 4;
chunk.push( input.substr( i, split ) );
}
var test = [];
chunk.forEach(element => {
test.push(element.match(/.{1,4}/g));
});
test.forEach(element => {
if(element.length!=4){
$(this).val(function() {
var out = chunk.join("-").toUpperCase();
if(out.length == 4 && event.keyCode != 8){
out += "-";
}
if(out.length == 9 && event.keyCode != 8 ){
out += "-";
}
return out;
});
}
});
this.setSelectionRange(start, end);
var selection = window.getSelection();
selection.addRange(1);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
<input type="text" name="login-access-token" placeholder="Code" />
var selection = window.getSelection();
selection.addRange(1); //not working :/
I solved it! Just add +1 to start and end which is values what we get from selectionStart.
if(out.length == 4 && event.keyCode != 8){
out += "-";
start = start+1;
end = end +1;
}
if(out.length == 9 && event.keyCode != 8 ){
out += "-";
start = start+1;
end = end +1;
}

Autocomplete usernames when TAB is pressed

I'm working on a "autocomplete usernames when TAB is pressed" feature.
I've been able to detect # and to search in a username list.
How to perform the autocompletion now, with a different matching username each time we press TAB ?
var userlist = ['bonjour', 'bleuet', 'bonobo', 'coucou'];
function getCaretPosition(ctrl) {
var start, end;
if (ctrl.setSelectionRange) {
start = ctrl.selectionStart;
end = ctrl.selectionEnd;
} else if (document.selection && document.selection.createRange) {
var range = document.selection.createRange();
start = 0 - range.duplicate().moveStart('character', -100000);
end = start + range.text.length;
}
return {
start: start,
end: end
}
}
$('#writing').keydown(function(e) {
if (e.keyCode == 9) {
var caret = getCaretPosition(this);
var word = /\S+$/.exec(this.value.slice(0, this.value.indexOf(' ',caret.end)));
word = word ? word[0] : null;
if (word.charAt(0) === '#')
alert(userlist.filter((x) => x.indexOf(word.slice(1)) === 0));
e.preventDefault();
return false;
}
});
#writing { width: 500px; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<textarea id="writing">Hello #b what's up? hello #you as well... Type #b and then "TAB" key it should autocomplete usernames
</textarea>
Here is the solution for your issue:
I used .on() to bind keydown to textbox, rather than keypress.
var userlist = ['bonjour', 'bleuet', 'bonobo', 'coucou'];
function getCaretPosition(ctrl) {
var start, end;
if (ctrl.setSelectionRange) {
start = ctrl.selectionStart;
end = ctrl.selectionEnd;
} else if (document.selection && document.selection.createRange) {
var range = document.selection.createRange();
start = 0 - range.duplicate().moveStart('character', -100000);
end = start + range.text.length;
}
return {
start: start,
end: end
}
}
$('#writing').keydown(function(e) {
if (e.keyCode == 9) {
var caret = getCaretPosition(this);
var word = /\S+$/.exec(this.value.slice(0, this.value.indexOf(' ',caret.end)));
word = word ? word[0] : null;
if (word.charAt(0) === '#')
//alert(userlist.filter((x) => x.indexOf(word.slice(1)) === 0));
var stringParts = $(this).val().split('#');
var nameToInsert = userlist.filter((x) => x.indexOf(word.slice(1)) === 0)[0];
var completeString = stringParts[0] + '#' + nameToInsert;
$(this).val(completeString);
e.preventDefault();
return false;
}
});
#writing { width: 500px; }
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.9.1/jquery.min.js"></script>
<textarea id="writing">Hello #b what's up? hello #you as well... Type #b and then "TAB" key it should autocomplete usernames
</textarea>
Now it completes the name. But I would work on improving on the algorithm predicting the name.
Here's a very basic example that works in modern browsers (Chrome, Firefox, Edge):
const users = ['asdasd', 'fgsfds', 'Foobar']
const input = document.getElementById('input')
const patt = /\S+$/
input.addEventListener('keydown', e => {
if (e.key !== 'Tab') {
return
}
e.preventDefault()
const start = input.selectionStart
const seg = input.value.slice(0, start)
const match = (seg.match(patt) || [])[0]
if (!match) {
return
}
const idx = users.findIndex(x => x.startsWith(match))
if (idx < 0) {
return
}
const replace = users[users[idx] === match ? (idx + 1) % users.length : idx]
const newSeg = seg.replace(patt, replace)
input.value = newSeg + input.value.slice(start)
input.setSelectionRange(newSeg.length, newSeg.length)
})
<input type="text" id="input" size="50" value="bla asd bla fgs">
It cycles through the names and works at any point in the line. Support for older browsers can be added with Babel and es6-shim.
Replace keypress with keydown. Keypress doesn't fire when tab is pressed, I guess because tab gets input out of focus.
EDIT:
Not perfect, gets undefined sometimes, but you can work from here
EDIT:
ok don't mind this, it's half done and #slikts solution is obviously better, made from scratch and all.
var userlist = ['bonjour', 'bleuet', 'bonobo', 'coucou'];
function getCaretPosition(ctrl) {
var start, end;
if (ctrl.setSelectionRange) {
start = ctrl.selectionStart;
end = ctrl.selectionEnd;
} else if (document.selection && document.selection.createRange) {
var range = document.selection.createRange();
start = 0 - range.duplicate().moveStart('character', -100000);
end = start + range.text.length;
}
return {
start: start,
end: end
}
}
function setCaretPosition(elem, caretPos, caretPosEnd) {
caretPosEnd = caretPosEnd || 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, caretPosEnd);
}
else
elem.focus();
}
}
}
function getIndexCloserTo(str, char, ref) {
if(str.indexOf(char) == -1) return false;
//flip string and find char beggining from reference point
var nstr = str.split("").reverse().join("");
return str.length - 1 - nstr.indexOf(char, str.length - 1 - ref);
}
var lastWordToMatch = "";
var lastAddedWord = "";
var lastIndexUsed = 0;
$(document).ready( function() {
$('#writing').keydown(function(e) {
if (e.keyCode == 9) {
var caret = getCaretPosition(this);
//Get username input part, from the "#" closer to the cursor
//to the position of the cursor
var beginning = getIndexCloserTo(this.value, '#', caret.start);
if( beginning !== false){
var word = this.value.slice( beginning , caret.start);
word = word ? word[0] : null;
if (word.charAt(0) === '#'){
//Get array of names that match what is written after the #
var usermatches = userlist.filter((x) => x.indexOf(word.slice(1)) === 0);
//Check if any matches were found
if( usermatches.length > 0 ){
//If the word is the same as last time, use the next match
if( word == lastWordToMatch ){
//use mod to circle back to beginning of array
index = (lastIndexUsed + 1 ) % usermatches.length;
lastIndexUsed = index;
} else {
//otherwise get first match
index = 0;
lastWordToMatch = word;
}
var text = this.value;
//Remove #
word = word.slice(1);
//replace the portion of the word written by the user plus the
//word added by autocompletion, with the match
$(this).val(text.replace(word+lastAddedWord, usermatches[index]) );
//save the replacement for the previous step, without the user input
//just what autocompetion added
lastAddedWord = usermatches[index].replace(word, '');
//put cursor back where it was
setCaretPosition(this,caret.start);
}
}
}
e.preventDefault();
return false;
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<textarea id="writing">Hello #b what's up? hello #you as well... Type #b and then "TAB" key it should autocomplete usernames
</textarea>

JQuery / JavaScript Keyboard event

I have a typing speed test with a textarea and I have I paragraph split into spans. Every time the user hits space, it highlights the next span. Then I split the textarea val() and compare the two at the end. I have everything working except I cannot get the enter key to do what I want it to do. I need it to act like the space bar(in the background) and act as the enter key on screen.
$(function() {
//APPEARANCE
$('#error').hide();
$('#oldTextOne').hide();
$('#oldTextTwo').hide();
$('#oldTextThree').hide();
$('#oldTextFour').hide();
$('#oldTextFive').hide();
$('.linkBox').hover(function() {
$(this).removeClass('linkBox').addClass('linkHover');
}, function() {
$(this).removeClass('linkHover').addClass('linkBox');
});
//FUNCTIONALITY VARIABLES
var min = '5';
var sec = '00';
var realSec = 0;
var errorTest = "hasn't started yet";
var oldTextVal;
var para;
// PICK A RANDOM PARAGRAPH
function pickRandom() {
var date = new Date();
date = date.getTime();
date += '';
var dateSplit = date.split('');
var temp = dateSplit.length - 1;
var picker = dateSplit[temp];
if (picker === '0' || picker === '1') {
para = $('#oldTextOne').text();
}
else if (picker === '2' || picker === '3') {
para = $('#oldTextTwo').text();
}
else if (picker === '4' || picker === '5') {
para = $('#oldTextThree').text();
}
else if (picker === '6' || picker === '7') {
para = $('#oldTextFour').text();
}
else {
para = $('#oldTextFive').text();
}
var splitPara = para.split(' ');
for (i in splitPara) {
$('#oldTextBox').append('<span id="pw' + i + '">' + splitPara[i] + '</span> ');
}
}
pickRandom();
//FUNCTION FOR TIMER
//APPEARANCE
function show() {
$('#timer').text(min + ' : ' + sec);
}
show();
//COUNT-DOWN
var count = function() {
sec = +sec - 1;
sec += '';
realSec++;
if (+sec === -1) {
sec = '59';
min -= 1;
min += '';
}
if (sec.length === 1) {
sec = '0' + sec;
}
show();
if (sec === '00' && min === '0') {
clearInterval(run);
checkIt();
}
};
// TYPE THE TEXT INTO #TYPEDTEXTBOX
$('#pw0').addClass('green');
var lastLetter;
$('#typedTextBox').focus().keypress(function() {
if (errorTest === "hasn't started yet") {
errorTest = 'running';
run = setInterval(count, 1000);
}
//STOP ERRORS FROM PEOPLE HITTING SPACE BAR TWICE IN A ROW !!NOT WORKING IN IE8
var thisLetter = event.which;
if (lastLetter === 32 && event.which === 32) {
event.preventDefault();
}
lastLetter = thisLetter;
}).keyup(function() {
//STOP ERRORS FROM BACKSPACE NOT REGISTERING WITH KEYPRESS FUNCTION
if (event.which === 8) {
lastLetter = 8;
}
if (event.which === 13) {
?????????????????????????????????????????????
}
//SPLIT THE TYPED WORDS INTO AN ARRAY TO MATCH THE OLD TXT SPANS (TO HIGHLIGHT THE CURRENT WORD IN OLDTXT)
var typedWords = $(this).val().split(' ');
var temp = typedWords.length - 1;
var oldTemp = temp - 1;
var stopErrors = temp + 1;
$('span:nth(' + temp + ')').addClass('green');
$('span:nth(' + oldTemp + ')').removeClass('green');
$('span:nth(' + stopErrors + ')').removeClass('green');
//SCROLL
if (typedWords.length < 50) {
return;
}
else if (typedWords.length > 50 && typedWords.length < 100) {
$('#oldTextBox').scrollTop(30);
}
else if (typedWords.length > 100 && typedWords.length < 150) {
$('#oldTextBox').scrollTop(60);
}
else if (typedWords.length > 150 && typedWords.length < 200) {
$('#oldTextBox').scrollTop(90);
}
else if (typedWords.length > 200) {
$('#oldTextBox').scrollTop(120);
}
//KEEP FOCUS IN THE TYPING AREA
}).blur(function() {
if (errorTest !== 'done') {
$(this).focus();
}
});
//COMPARE
//MAKE AN ARRAY OF THE OLDTEXT
var oldWords = para.split(' ');
//FUNCTION TO DISPLAY RESULTS
var checkIt = function() {
errorTest = 'done';
var correct = 0;
var typed = $('#typedTextBox').val();
var typedWords = typed.split(' ');
$('#typedTextBox').blur();
for (i = 0; i < typedWords.length; i++) {
if (typedWords[i] === oldWords[i]) {
correct += 1;
}
}
var errors = typedWords.length - correct;
var epm = (errors / realSec) * 60;
var wpm = Math.round(( ($('#typedTextBox').val().length / 5 ) / realSec ) * 60);
var realWpm = Math.round(wpm - epm);
//SHOW RESULTS
$('#oldTextBox').html('<br><span id="finalOne">WPM : <strong>' + realWpm + ' </strong></span><span class="small">(error adjusted)</span><br><br><span id="finalTwo">You made ' + errors + ' errors </span><br><span id="finalThree">Total character count of ' + $('#typedTextBox').val().length + '</span><br><span id="finalFour">Gross WPM : ' + wpm + '</span>');
};
//STOP BUTTON APPEARANCE AND FUNCTIONALITY
$('#stop').mouseover(function() {
$(this).addClass('stopHover');
}).mouseout(function() {
$(this).removeClass('stopHover');
}).click(function() {
if (errorTest === 'running') {
checkIt();
clearInterval(run);
errorTest = 'done';
}
});
});
try this:
//ENTER KEY
if (event.which === 13) {
//event.stopPropagation(); or
event.preventDefault();
//simulate spacebar
$(window).trigger({type: 'keypress', which: 32, keyCode: 32});
}
#james - Thanks for the help. I found a better way of thinking about the problem. Instead of changing the enter key action, I changed the split function to var typedWords = typed.split(/[ \r\n]+/);

How to handle <tab> in textarea?

I would like a textarea that handles a situation of pressing tab key.
In default case if you press a tab key then focus leaves the textarea. But what about the situation when user wants to type tab key in textarea?
Can I catch this event and return focus to the textarea and add a tab to a current cursor position?
You can: http://jsfiddle.net/sdDVf/8/.
$("textarea").keydown(function(e) {
if(e.keyCode === 9) { // tab was pressed
// get caret position/selection
var start = this.selectionStart;
var end = this.selectionEnd;
var $this = $(this);
var value = $this.val();
// set textarea value to: text before caret + tab + text after caret
$this.val(value.substring(0, start)
+ "\t"
+ value.substring(end));
// put caret at right position again (add one for the tab)
this.selectionStart = this.selectionEnd = start + 1;
// prevent the focus lose
e.preventDefault();
}
});
Here is a modified version of pimvdb's answer that doesn't need JQuery:
document.querySelector("textarea").addEventListener('keydown',function(e) {
if(e.keyCode === 9) { // tab was pressed
// get caret position/selection
var start = this.selectionStart;
var end = this.selectionEnd;
var target = e.target;
var value = target.value;
// set textarea value to: text before caret + tab + text after caret
target.value = value.substring(0, start)
+ "\t"
+ value.substring(end);
// put caret at right position again (add one for the tab)
this.selectionStart = this.selectionEnd = start + 1;
// prevent the focus lose
e.preventDefault();
}
},false);
I tested it in Firefox 21.0 and Chrome 27. Don't know if it works anywhere else.
Good god, all previous answers failed to provide the commonly decent (i.e. for programmers) tab control.
That is, a hitting TAB on selection of lines will indent those lines, and SHIFTTAB will un-indent them.
_edited (Nov 2016): keyCode replaced with charCode || keyCode, per KeyboardEvent.charCode - Web APIs | MDN
(function($) {
$.fn.enableSmartTab = function() {
var $this;
$this = $(this);
$this.keydown(function(e) {
var after, before, end, lastNewLine, changeLength, re, replace, selection, start, val;
if ((e.charCode === 9 || e.keyCode === 9) && !e.altKey && !e.ctrlKey && !e.metaKey) {
e.preventDefault();
start = this.selectionStart;
end = this.selectionEnd;
val = $this.val();
before = val.substring(0, start);
after = val.substring(end);
replace = true;
if (start !== end) {
selection = val.substring(start, end);
if (~selection.indexOf('\n')) {
replace = false;
changeLength = 0;
lastNewLine = before.lastIndexOf('\n');
if (!~lastNewLine) {
selection = before + selection;
changeLength = before.length;
before = '';
} else {
selection = before.substring(lastNewLine) + selection;
changeLength = before.length - lastNewLine;
before = before.substring(0, lastNewLine);
}
if (e.shiftKey) {
re = /(\n|^)(\t|[ ]{1,8})/g;
if (selection.match(re)) {
start--;
changeLength--;
}
selection = selection.replace(re, '$1');
} else {
selection = selection.replace(/(\n|^)/g, '$1\t');
start++;
changeLength++;
}
$this.val(before + selection + after);
this.selectionStart = start;
this.selectionEnd = start + selection.length - changeLength;
}
}
if (replace && !e.shiftKey) {
$this.val(before + '\t' + after);
this.selectionStart = this.selectionEnd = start + 1;
}
}
});
};
})(jQuery);
$(function() {
$("textarea").enableSmartTab();
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<textarea rows="10" cols="80">
/* Just some code to edit with our new superTab */
(function($) {
$.fn.enableSmartTab = function() {
$this = $(this);
$this.keydown(function(e) {
if ((e.charCode === 9 || e.keyCode === 9) && !e.metaKey && !e.ctrlKey && !e.altKey) {
e.preventDefault();
}
}
}
}
</textarea>
In Vanilla (Default) JS this would be:
var textareas = document.getElementsByTagName('textarea');
if ( textareas ) {
for ( var i = 0; i < textareas.length; i++ ) {
textareas[i].addEventListener( 'keydown', function ( e ) {
if ( e.which != 9 ) return;
var start = this.selectionStart;
var end = this.selectionEnd;
this.value = this.value.substr( 0, start ) + "\t" + this.value.substr( end );
this.selectionStart = this.selectionEnd = start + 1;
e.preventDefault();
return false;
});
}
}
textarea {
border: 1px solid #cfcfcf;
width: 100%;
margin-left: 0px;
top: 0px;
bottom: 0px;
position: absolute;
}
<textarea>
var x = 10;
var y = 10;
</textarea>
Found this while searching google. I made a really short one that can also indent and reverse indent selections of text:
jQ(document).on('keydown', 'textarea', function(e) {
if (e.keyCode !== 9) return;
var Z;
var S = this.selectionStart;
var E = Z = this.selectionEnd;
var A = this.value.slice(S, E);
A = A.split('\n');
if (!e.shiftKey)
for (var x in A) {
A[x] = '\t' + A[x];
Z++;
}
else
for (var x in A) {
if (A[x][0] == '\t')
A[x] = A[x].substr(1);
Z--;
}
A = A.join('\n');
this.value = this.value.slice(0, S) + A + this.value.slice(E);
this.selectionStart = S != E ? S : Z;;
this.selectionEnd = Z;
e.preventDefault();
});
Enable tabbing inside (multiple) textarea elements
Correcting #alexwells answer and enable a live demo
var textAreaArray = document.querySelectorAll("textarea");
for (var i = textAreaArray.length-1; i >=0;i--){
textAreaArray[i].addEventListener('keydown',function(e) {
if(e.keyCode === 9) { // tab was pressed
// get caret position/selection
var start = this.selectionStart;
var end = this.selectionEnd;
var target = e.target;
var value = target.value;
// set textarea value to: text before caret + tab + text after caret
target.value = value.substring(0, start)
+ "\t"
+ value.substring(end);
// put caret at right position again (add one for the tab)
this.selectionStart = this.selectionEnd = start + 1;
// prevent the focus lose
e.preventDefault();
}
},false);
}
<textarea rows="10" cols="80"></textarea>
<textarea rows="10" cols="80"></textarea>

Getting Deleted character

in in Input field, if the user presses Backspace or Delete key, is there a way to get the deleted character.
I need to check it against a RegExp.
Assuming the input box has an id 'input'. Here is how with least amount of code you can find out the last character from the input box.
document.getElementById("input").onkeydown = function(evt) {
const t = evt.target;
if (evt.keyCode === 8) { // for backspace key
console.log(t.value[t.selectionStart - 1]);
} else if (evt.keyCode === 46) { // for delete key
console.log(t.value[t.selectionStart]);
}
};
<input id="input" />
The following will work in all major browsers for text <input> elements. It shouldn't be used for <textarea> elements because the getInputSelection function doesn't account for line breaks correctly in IE. See this answer for a (longer) function that will do this.
function getInputSelection(input) {
var start = 0, end = 0;
input.focus();
if ( typeof input.selectionStart == "number" &&
typeof input.selectionEnd == "number") {
start = input.selectionStart;
end = input.selectionEnd;
} else if (document.selection && document.selection.createRange) {
var range = document.selection.createRange();
if (range) {
var inputRange = input.createTextRange();
var workingRange = inputRange.duplicate();
var bookmark = range.getBookmark();
inputRange.moveToBookmark(bookmark);
workingRange.setEndPoint("EndToEnd", inputRange);
end = workingRange.text.length;
workingRange.setEndPoint("EndToStart", inputRange);
start = workingRange.text.length;
}
}
return {
start: start,
end: end,
length: end - start
};
}
document.getElementById("aTextBox").onkeydown = function(evt) {
evt = evt || window.event;
var keyCode = evt.keyCode;
var deleteKey = (keyCode == 46), backspaceKey = (keyCode == 8);
var sel, deletedText, val;
if (deleteKey || backspaceKey) {
val = this.value;
sel = getInputSelection(this);
if (sel.length) {
deletedText = val.slice(sel.start, sel.end);
} else {
deletedText = val.charAt(deleteKey ? sel.start : sel.start - 1);
}
alert("About to be deleted: " + deletedText);
}
};
No, there is no variable that stores the deleted char. Unless you have a history for Undo/Redo, but it would be difficult to get the information out of that component.
Easiest would be to compare the contents of the input field before and after delete/backspace have been pressed.
You could try something with the caret position:
function getCaretPosition(control){
var position = {};
if (control.selectionStart && control.selectionEnd){
position.start = control.selectionStart;
position.end = control.selectionEnd;
} else {
var range = document.selection.createRange();
position.start = (range.offsetLeft - 1) / 7;
position.end = position.start + (range.text.length);
}
position.length = position.end - position.start;
return position;
}
document.getElementById('test').​​​​onkeydown = function(e){
var selection = getCaretPosition(this);
var val = this.value;
if((e.keyCode==8 || e.keyCode==46) && selection.start!==selection.end){
alert(val.substr(selection.start, selection.length));
} else if(e.keyCode==8){
alert(val.substr(selection.start-1, 1));
} else if(e.keyCode==46){
alert(val.substr(selection.start, 1));
}
}​
Tested on Chrome 6. See jsFiddle for an example

Categories