How to simulate back tab in textarea - javascript

I'm trying to simulate tabbing in a textarea, so far tab forward works but I'm not quite sure how to make backtab work. Any suggestions on how to do this, or better ways to do it would be helpful.
$('textarea').on('keydown mousedown', function(e){
var val = this.value,
start = this.selectionStart,
end = this.selectionEnd;
if (e.shiftKey) {
console.log('shift')
if (e.which == 9 || e.keyCode == 9) {
console.log('shift + tab')
e.preventDefault();
this.value = val.substring(0, start) + '\t' + val.substring(end);
}
} else if (e.which == 9 || e.keyCode == 9) {
console.log('tab')
e.preventDefault();
this.value = val.substring(0, start) + '\t' + val.substring(end);
}
})

This might get you started.
$('textarea').on('keydown mousedown', function(e) {
var val = this.value,
start = this.selectionStart,
end = this.selectionEnd;
if (e.which == 9 || e.keyCode == 9) {
e.preventDefault();
if (e.shiftKey) {
var firstTabPoint = val.lastIndexOf('\n', start) + 1;
if (val.substring(firstTabPoint, firstTabPoint + 1) == '\t') {
var startString = val.substr(0, firstTabPoint);
var endString = val.substr(firstTabPoint + 1);
this.value = startString + endString;
this.setSelectionRange(start - 1, end - 1);
}
} else {
this.value = val.substring(0, start) + '\t' + val.substring(end);
this.setSelectionRange(start + 1, end + 1);
}
}
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<textarea rows="20" cols="100">
Add some lines in here, tab them, and then try untabbing.
</textarea>
As a side note, you might look into the attribute contenteditable="true" if you are making a text editor application.

Related

Can you press tab in a textarea without changing focus while still typing?

HTML:
<textarea id="text"></textarea>
JavaScript:
document.querySelector('#text').addEventListener('keydown', e => {
if (e.keyCode == 9) e.preventDefault();
});
Are you able to still write a tab without unfocusing the textarea?
Add spaces to the end when tab is hit:
document.querySelector('#text').addEventListener('keydown', e => {
if (e.keyCode == 9) {
e.preventDefault();
document.querySelector('#text').value += " ";
}
});
Edit: Worked on inserting spaces and I think this works:
<textarea id="text"></textarea>
document.querySelector('#text').addEventListener('keydown', e => {
if (e.keyCode == 9) {
e.preventDefault();
var ele = document.querySelector('#text');
var caretPos = ele.selectionStart;
var textAreaTxt = ele.value;
var txtToAdd = " ";
ele.value = textAreaTxt.substring(0, caretPos)
+ txtToAdd
+ textAreaTxt.substring(caretPos);
ele.selectionStart = caretPos + 4;
ele.selectionEnd = caretPos + 4;
}
});
With help from https://stackoverflow.com/a/15977052/1171702 and a general search for js add spaces at cursor position.

Applying changes to text on pasting into input instead of key down entery

I am trying to append - between phone numbers in user input to be like xxx-xxx-xxxx instead of xxxxxxxxxx .
This is working fine when using Keys to enter value but what about Pasting the number or Chrome Auto-fill function? For example if you copy and paste 2222222222 to the input the - will not added between.
How can I fix this?
$(function () {
$('#txtnumber').keydown(function (e) {
var key = e.charCode || e.keyCode || 0;
$text = $(this);
if (key !== 8 && key !== 9) {
if ($text.val().length === 3) {
$text.val($text.val() + '-');
}
if ($text.val().length === 7) {
$text.val($text.val() + '-');
}
}
return (key == 8 || key == 9 || key == 46 || (key >= 48 && key <= 57) || (key >= 96 && key <= 105));
})
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input id="txtnumber" type="text" maxlength="12" placeholder="xxx-xxx-xxxx" /><br /><br />
you need to capture the Ctrl key + V, and then insert your -'s
var ctrlDown = false,
ctrlKey = 17,
cmdKey = 91,
vKey = 86,
cKey = 67;
$(document).keydown(function(e) {
if (e.keyCode == ctrlKey || e.keyCode == cmdKey) ctrlDown = true;
}).keyup(function(e) {
if (e.keyCode == ctrlKey || e.keyCode == cmdKey) ctrlDown = false;
});
/// your code +
$(function () {
$('#txtnumber').keydown(function (e) {
var key = e.charCode || e.keyCode || 0;
if (ctrlDown && (e.keyCode == vKey)){
//insert the -'s on respective possition
}
else{
$text = $(this);
if (key !== 8 && key !== 9) {
if ($text.val().length === 3) {
$text.val($text.val() + '-');
}
if ($text.val().length === 7) {
$text.val($text.val() + '-');
}
}
}
credits to> https://stackoverflow.com/a/2904944/335905
Original answer (look at the update) [interesting]
Add a change event listener to the input, because keydown is not emmitted when pasting
Something like this should work
$('#txtnumber').change(function(e) {
var x = e.target.value.replace(/\D/g, '').match(/(\d{3})(\d{3})(\d{4})/);
e.target.value = x[1] + '-' + x[2] + '-' + x[3];
});
 Update
Working always on vuejs. Change is the thing. Apparently not for purejs and in google chrome (i will test for other browser later)
For some reason, the change event only fires when the input field loses focus.
Binding to other options ('change keypress paste focus textInput input') will fire the event several times, which is bad.
The below code works even when content is pasted into the text field, and only fires once as expected.
input event come to the rescue (or simple it's our event) (change however is confusing).
$('#txtnumber').bind('input', function(e) {
console.log('This actually fires');
console.log(e.target.value);
});
And a pure js
document.getElementById('txtnumber').addEventListener('input', function(e) {
var x = e.target.value.replace(/\D/g, '').match(/(\d{3})(\d{3})(\d{4})/);
e.target.value = x[1] + '-' + x[2] + '-' + x[3];
});
Final Example
$('#txtnumber').bind('input', function(e) {
if (e.target.value.length === 10) {
var x = e.target.value.replace(/\D/g, '').match(/(\d{3})(\d{3})(\d{4})/);
e.target.value = x[1] + '-' + x[2] + '-' + x[3];
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<input id="txtnumber" type="text" maxlength="12" placeholder="xxx-xxx-xxxx" /><br /><br />

Phone Number Validation With Spacing

I have researched all over the place for a phone number validation in JavaScript that adds spacing as they type.
The closest code I came to was
$('#ssn').keyup(function() {
var val = this.value.replace(/\D/g, '');
var newVal = '';
while (val.length > 3) {
newVal += val.substr(0, 3) + '-';
val = val.substr(3);
}
newVal += val;
this.value = newVal;
});
http://jsfiddle.net/ssthil/nY2QT/.
Expect that is American Mobile Numbers. Anyone know how to do Australia format (XXXX XXX XXX). I tried moving the digits around in the JavaScript but nothing seemed to work.
Try this code :
while (val.length > 3) {
if(newVal.length > 4){
newVal += val.substr(0, 3) + ' ';
val = val.substr(3);
} else {
newVal += val.substr(0, 4) + ' ';
val = val.substr(4);
}
}
newVal += val;
this.value = newVal;
});
Working fiddle :
http://jsfiddle.net/nY2QT/718/
Modifying your code a little bit you can get something like this:
$('#ssn').on('input', function() {
var val = this.value.replace(/\D/g, '');
if(val.length > 10) {
this.value = this.value.slice(0,12);
} else {
this.value = (val.slice(0,4) + ' ' + val.slice(4,7) + ' ' + val.slice(7,10)).trim();
}
});
I have made some changes with loop hope it will works
$('#ssn').keyup(function() {
var val = this.value.replace(/\D/g, '');
var newVal = '';
var flag = true;
while (val.length > 3) {
if(flag){
flag=false;
newVal += val.substr(0, 4) + '-';
val = val.substr(4);
} else {
newVal += val.substr(0, 3) + '-';
val = val.substr(3);
}
}
newVal += val;
if(this.value.length >= 5){
this.value = newVal;
}
});
You could have instead three <input /> elements, give them each maxlength="4", maxlength="3", and maxlength="3" respectively. And as soon as the user completes each input, they're moved to the following:
HTML
<form>
<input maxlength="4" autofocus="autofocus" name="first"/>
-
<input maxlength="3" name="second"/>
-
<input maxlength="3" name="third"/>
</form>
Javascript/jQuery
// Autofocus second after first is complete
$('[name="first"]').keyup(function() {
if ( $(this).val().length == 4) {
$('[name="second"]').focus();
}
});
// Autofocus third after second is complete
$('[name="second"]').keyup(function() {
if ( $(this).val().length == 3) {
$('[name="third"]').focus();
}
});
// Alert numer after third is complete
$('[name="third"]').keyup(function() {
if ( $(this).val().length == 3) {
alert("Number: " + $('[name="first"]').val() + "-" + $('[name="second"]').val() + "-" + $('[name="third"]').val() + ".");
}
});
Also, to valide for only numbers, you can use RegEx:
// The following code is RegEx, used to validate the inputs so that the user can only type in numbers
$('[name="first"], [name="second"], [name="third"]').on('input', function (event) {
this.value = this.value.replace(/[^0-9]/g, '');
});
// Support for old browsers
$('[name="first"], [name="second"], [name="third"]').on('keyup', function (event) {
this.value = this.value.replace(/[^0-9]/g, '');
});
Eureka!
Edit: answer to Z-Dog's "question":
// Autofocus first if backspace is pressed and this is empty
if (!e) e = window.event;
var keyCode = e.keyCode || e.which;
if (keyCode == '8' && $(this).val().length == 0){
$('[name="first"]').focus();
// And delete last character
$('[name="first"]').val(
function(index, value){
return value.substr(0, value.length - 1);
});
return false;
}
Eureka 2.0!
Use Jquery Mask plug-in
https://igorescobar.github.io/jQuery-Mask-Plugin/
It simple to integrate ans use
Use this code it might work
document.getElementById('ssn').addEventListener('input', function (e) {
e.target.value = e.target.value.replace(/(\d{4}) ?(\d{3}) ?(\d{3})/,
'$1 $2 $3');
});

Synchronous input update with selected digit in HTML/JavaScript

I'm trying to implement a customised input that can use left or right arrow key to select the digit and use up/down arrow key to increment/decrement the digit. Here's the code in jsfiddle: http://jsfiddle.net/uk5t3z4d/48/. However, I have two problems:
I cannot add digit using the number pad, the input always stays at X.XX
When I use another function I wrote (parseLocalFloat which is commented out), the output stops displaying anything, and I cannot use the left and right key to select the digit etc.
How can I overcome these two issues? Please shed a light on me, thanks!
HTML
<div class="display" id="out"></div>
<div class="form-group">
<label for="comment">value:</label>
<input class="form-control" type="text" value="0.00" id="in"></input>
</div>
JavaScript
function createSelection(field, start, end) {
if( field.createTextRange ) {
var selRange = field.createTextRange();
selRange.collapse(true);
selRange.moveStart('character', start);
selRange.moveEnd('character', end);
selRange.select();
} else if( field.setSelectionRange ) {
field.setSelectionRange(start, end);
} else if( field.selectionStart ) {
field.selectionStart = start;
field.selectionEnd = end;
}
}
function getLocalDecimalSeparator() {
var n = 1.1;
return n.toLocaleString().substring(1,2);
}
function parseLocalFloat(num) {
return +(num.replace(getLocalDecimalSeparator(), '.'));
}
var inputBox = document.getElementById('in');
//var inputBox = parseLocalFloat(document.getElementByID('in').value);
inputBox.onkeyup = function(){
document.getElementById('out').innerHTML = inputBox.value;
}
$('#in').on("keydown", function(e){
var gotCode = false;
var curPos = this.selectionStart;
var endPos = this.selectionEnd;
if(curPos !== endPos) {
createSelection(this, curPos, curPos+1);
}
// get the position
if(e.keyCode == 37){
curPos--;
gotCode=true;
}
if(e.keyCode == 39){
curPos++;
gotCode=true;
}
var before = $(this).val().substring(0,curPos);
var after = $(this).val().substring(curPos+1);
var cur = Number($(this).val().substring(curPos, curPos+1));
// avoid adding extra stuff
if(curPos < $(this).val().length) {
if(e.keyCode == 38) {
cur++;
if(cur > 9) cur = 0;
$(this).val(before + '' + cur + '' + after);
gotCode=true;
}
if(e.keyCode == 40) {
cur--;
if(cur < 0) cur = 9;
$(this).val(before + '' + cur + '' + after);
gotCode=true;
}
}
if(!gotCode) {
e.preventDefault();
return false;
}
var field = this;
window.setTimeout(function(){
createSelection(field, curPos, curPos+1);
}, 10);
});
as for the "get number keys to work":
as stated you need to add the keys you want to support:
if(e.keyCode >= 48 && e.keyCode <= 57) {
var num = e.keyCode - 48; // 0=48; 9=59
$(this).val(before + '' + num + '' + after);
gotCode = true;
e.preventDefault(); // otherwise a new number is added as well
}
(this needs to come before the if (!gotCode) ... )
as for the customFloat: the the response from Moishe
For #1:
if(!gotCode) {
e.preventDefault();
return false;
}
ensures that if gotCode is false the default event (which in this case is the default keydown event) will not occur.
gotCode only seems to be true if keyCode is equal to 37, 38, 39, or 40 (the arrow keys). You are essentially preventing the other keys (like number keys) from having any effect on the textBox.
You probably would like to enable the number keys (when shift or caps aren't on) and number pad keys.
Additionally, you may want to check that the cur is a number (and not .) before attempting to increment or decrement its value.
You could do:
var isNumberKey = (
( e.keyCode >= 48 //is more than or equal to 0 key
&& e.keyCode <= 57 //is less than or equal to 9 key
&& !e.shiftKey) //shift key or cap key not on
|| ( e.keyCode >= 96 //more than or equal to 0 key in number pad
&& e.keyCode <= 105)); //less than or equal to 9 key in number pad
if(!gotCode && !isNumberKey) { //not arrow key or number key
console.log(e);
e.preventDefault();
return false;
}
For #2:
var inputBox = parseLocalFloat(document.getElementByID('in').value);
is setting inputBox to whatever parseLocalFloat returns which happens to be a number.
This is problematic because you then attempt to attach a keyUp event to that number instead of the inputBox:
inputBox.onkeyup = function(){
document.getElementById('out').innerHTML = inputBox.value;
}
You may want to instead call parseLocalFloat on the number and set the out textBox's value to that:
var inputBox = document.getElementById('in');
inputBox.onkeyup = function(){
document.getElementById('out').innerHTML = parseLocalFloat(inputBox.value);
}
function createSelection(field, start, end) {
if( field.createTextRange ) {
var selRange = field.createTextRange();
selRange.collapse(true);
selRange.moveStart('character', start);
selRange.moveEnd('character', end);
selRange.select();
} else if( field.setSelectionRange ) {
field.setSelectionRange(start, end);
} else if( field.selectionStart ) {
field.selectionStart = start;
field.selectionEnd = end;
}
}
function getLocalDecimalSeparator() {
var n = 1.1;
return n.toLocaleString().substring(1,2);
}
function parseLocalFloat(num) {
return +(num.replace(getLocalDecimalSeparator(), '.'));
}
var inputBox = document.getElementById('in');
// var inputBox = parseLocalFloat(document.getElementByID('in').value);
inputBox.onkeyup = function(){
document.getElementById('out').innerHTML = parseLocalFloat(inputBox.value);
}
$('#in').on("keydown", function(e){
var gotCode = false;
var curPos = this.selectionStart;
var endPos = this.selectionEnd;
if(curPos !== endPos) {
createSelection(this, curPos, curPos+1);
}
// get the position
if(e.keyCode == 37){
curPos--;
gotCode=true;
}
if(e.keyCode == 39){
curPos++;
gotCode=true;
}
var $thisVal = $(this).val();
var before = $thisVal.substring(0,curPos);
var after = $thisVal.substring(curPos+1);
var cur = Number($thisVal.substring(curPos, curPos+1));
// avoid adding extra stuff
if(curPos < $thisVal.length && !isNaN(cur)) {
if(e.keyCode == 38) {
cur++;
if(cur > 9) cur = 0;
$(this).val(before + '' + cur + '' + after);
gotCode=true;
}
if(e.keyCode == 40) {
cur--;
if(cur < 0) cur = 9;
$(this).val(before + '' + cur + '' + after);
gotCode=true;
}
}
var isNumberKey = ((e.keyCode >= 48 && e.keyCode <= 57 && [16, 20].indexOf(e.keyCode) == -1 && !e.shiftKey) || (e.keyCode >= 96 && e.keyCode <= 105));
if(!gotCode && !isNumberKey) {
console.log(e);
e.preventDefault();
return false;
}
var field = this;
window.setTimeout(function(){
createSelection(field, curPos, curPos+1);
}, 10);
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="display" id="out"></div>
<div class="form-group">
<label for="comment">value:</label>
<input class="form-control" type="text" value="0.00" id="in"></input>
</div>

How to make this validation work on cloned inputs

I have this id validation field, i just need to know how i can make the validation and the keydown and keyup functions work on cloned inputs. also inserted data is carrying over to the duplicate fields.
js fiddle- http://www.jsfiddle.net/dawidvdh/xRh9v/
Heres the js:
$(document).ready(function() {
idAmount = [0,1,2,3,4,5,6,7,8,9,10,12,13];
var idinc =1;
var id_val;
jQuery(idAmount).each(function() {
var index = "id"+idinc++;
var id_input = "<input class='id' id="+'"'+index+'"'+" "+" maxlength='1' />";
id_val = $(this).attr('value');
jQuery(id_input).appendTo('#id');
});
$("#clone").click(function () {
var clonedObj=$('#id').clone().insertAfter("#id");
clonedObj.find('.id').each(function(){
this.id='id' + idinc++;
});
});
function Validate() {
jQuery('#error p').remove();
var id_val = '';
$('.id').each(function(){ id_val+=($(this).val());});
var idNumber = id_val;
console.log(id_val);
var correct = true;
if (idNumber.length != 13 || !isNumber(idNumber)) {
correct = false;
}
var tempDate = new Date(idNumber.substring(0, 2), idNumber.substring(2, 4) - 1, idNumber.substring(4, 6));
console.log(tempDate);
var id_date = tempDate.getDate();
var id_month = tempDate.getMonth();
var id_year = tempDate.getFullYear();
var currentYear = (new Date).getFullYear();
var age = currentYear - id_year;
var fullDate = id_date + "-" + (id_month + 1) + "-" + id_year;
if (!((tempDate.getYear() == idNumber.substring(0, 2)) && (id_month == idNumber.substring(2, 4) - 1) && (id_date == idNumber.substring(4, 6)))) {
correct = false;
}
// get the gender
var genderCode = idNumber.substring(6, 10);
var gender = parseInt(genderCode) < 5000 ? "Female" : "Male";
// get country ID for citzenship
var citzenship = parseInt(idNumber.substring(10, 11)) == 0 ? "Yes" : "No";
// apply Luhn formula for check-digits
var tempTotal = 0;
var checkSum = 0;
var multiplier = 1;
for (var i = 0; i < 13; ++i) {
tempTotal = parseInt(idNumber.charAt(i)) * multiplier;
if (tempTotal > 9) {
tempTotal = parseInt(tempTotal.toString().charAt(0)) + parseInt(tempTotal.toString().charAt(1));
}
checkSum = checkSum + tempTotal;
multiplier = (multiplier % 2 == 0) ? 1 : 2;
}
if ((checkSum % 10) != 0) {
correct = false;
};
// if no error found, hide the error message
if (correct) {
jQuery('.id').css("border","1px solid #9A8B7D");
// clear the result div
jQuery('#result').empty();
// and put together a result message
jQuery('#result').append('<p>South African ID Number: ' + idNumber + '</p><p>Birth Date: ' + fullDate + '</p><p>Gender: ' + gender + '</p><p>SA Citizen: ' + citzenship + '</p><p>AGE: ' + age + '</p>');
jQuery('#status').html("correct");
}
// otherwise, show the error
else {
jQuery('.id').css("border","1px solid #FF0000");
jQuery('#status').html("incorrect")
}
return false;
}
function isNumber(n) {
return !isNaN(parseFloat(n)) && isFinite(n);
}
$('input.id').keydown(function(e){
if(e.keyCode == 8){
$(this).val('');
$(this).prev().val('');
$(this).prev().focus();
Validate()
}
});
$('input.id').on('keyup', function(){
if (this.value.match(/\d+/)) {
var $this = $(this);
if ($this.next('input').length) {
$this.next().focus();
} else {
Validate()
}
}
});
$(".id").keydown(function(event) {
// Allow: backspace, delete, tab, escape, and enter
if ( event.keyCode == 46 || event.keyCode == 8 || event.keyCode == 9 || event.keyCode == 27 || event.keyCode == 13 ||
// Allow: Ctrl+A
(event.keyCode == 65 && event.ctrlKey === true) ||
// Allow: home, end, left, right
(event.keyCode >= 35 && event.keyCode <= 39)) {
// let it happen, don't do anything
return;
}
else {
// Ensure that it is a number and stop the keypress
if (event.shiftKey || (event.keyCode < 48 || event.keyCode > 57) && (event.keyCode < 96 || event.keyCode > 105 )) {
event.preventDefault();
}
}
});
});
HTML:
<div id="id">
<span id="label">ID NUMBER:</span>
<span id="status"></span>
</div>
<button id="clone">clone</button>
<div id="result"> </div>
CSS:
#error {
color: red;
border: 1px solid red;
padding: 5px;
display: none;
}
#result {
padding: 20px;
}
.id {
width:16px;
height:16px;
border:1px solid #9A8B7D;
margin:0;
float:left;
text-align:center;
font-family:'itc_avant_garde_gothic_bookOb',Helvetica,sans-serif;
font-size:11pt;
padding:2px;
}
#label {
float:left;
font-family:'itc_avant_garde_gothic_bookOb',Helvetica,sans-serif;
line-height:18px;
font-size:11pt;
margin-right:10px;
}
The only time that I see you call Validate is here :
$('input.id').on('keyup', function(){
//code
});
and here
$('input.id').keydown(function(e){
//code
});
Which means that the issue is the event handler is not delegated to a static element
$(document).on('keyup', 'input.id', function(){
//code
});
$(document).on('keydown', 'input.id', function(){
//code
});
Binding it to the document will ensure that any dynamically created elements will have the same event delegated to them as any static elements of the same selector.
Forgot the last part.
clonedObj.find('.id').each(function(){
this.id='id' + idinc++;
this.value = ''; //simply add this to remove the value
});
Although, because you're using jQuery, you should try to stick to using jQuery.
clonedObj.find('.id').each(function(){
$(this).prop('id', 'id'+ idinc++).val(''); // chain the commands
});

Categories

Resources