OnKeyDown or KeyPress, detect the location of the inserted character - javascript

I don't know if this is possible (it looks like it's not), but I'm trying to find a way to detect, inside the onKeyDown or onKeyPress event of an HTML input tag, what the resulting value will be.
It's important that I use these events. I can't just use onKeyUp, because by then the input will have already changed. I want to prevent it from happening in the first place. I've also tried appending the pressed key character to the end of the string, but that doesn't account for cases where you typed a character in the beginning of the string in the input field.
Any ideas? I've looked for a while and it doesn't seem possible but I figured I'd ask.

Here I have 2 versions, one with jQuery and other with JavaScript alone.
$("#inputJQuery").on("keydown", function(ev){
console.log("jQuery value:", $(this).val()); // this is the value before the key is added
console.log("jQuery selectionStart:", this.selectionStart); // the position where the character will be inserted
console.log("jQuery selectionEnd:", this.selectionEnd); // if has a selection this value will be different than the previous
})
document.querySelector("#inputVanilla").onkeydown = function(ev){
console.log("VANILLA value:", this.value); // this is the value before the key is added
console.log("VANILLA selectionStart:", this.selectionStart); // the position where the character will be inserted
console.log("VANILLA selectionEnd:", this.selectionEnd); // if has a selection this value will be different than the previous
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.2.1/jquery.min.js"></script>
<input id="inputJQuery" type="text"/>
<input id="inputVanilla" type="text"/>

Simply check for the length of the value on keydown. This also works for deleting characters.
You can also check against this in a conditional that returns false to prevent the user from typing in more than a certain number of characters. Note that you'll probably want to check this against the backspace and delete keys (keyCodes 8 and 46 respectively) so that you're able to delete keys once the maximum length is reached.
var input = document.getElementById('input');
input.onkeydown = function(e) {
console.log(input.value.length);
if (input.value.length == 10) {
if (e.keyCode === 8 || e.keyCode === 46) {
return true;
} else {
return false;
}
}
}
<input id="input">
Hope this helps! :)

Related

preventDefault() disables text input as well

edit: I want to use the enter key to clear the text box after I have already typed some text. Sorry for the confusion I have caused
edit 2 The missing event parameter was the key of all this. Sorry, I am a failure as a programmer.
I want to disable the new line/break when I press enter. However, version 1 doesn't work as I won't be able to enter any text at all.
Version 2 works and I am still able to clear the field while continue entering new texts.
From how I interpret this, whether I press the shift key + enter together or not, it should still allow me to type. Why is there such a difference? How does the default option of shift key relate to enabling/disabling input on the textbox? What I would like to do, is to just disable the new line/break when pressing the enter button but I found that it disabled the input part as well, which from my understanding, it shouldn't?
// html
<textarea type="text" id="box">Some text</textarea>
// javascript
document.getElementById('box').addEventListener('keypress', (e)=>{
//version 1
if(e.keyCode == 13){ //why does this version also disable any text input?
e.preventDefault();
document.getElementById('box').value = '';
}
//version 2
if(e.keyCode == 13 && e.shiftKey){
e.preventDefault();
document.getElementById('box').value = '';
}
});
Your code is throwing an error because it doesn't know what the variable e is referring to. You should see that error if you watch the error console. To fix it, you should pass that in to the function. This clears the textbook when you press enter. Is that what you want? I left the line in but commented it out.
document.getElementById('box').addEventListener('keypress', (e)=>{
//version 1
if(e.keyCode == 13){ //why does this version also disable any text input?
e.preventDefault();
document.getElementById('box').value = '';
}
});
<textarea type="text" id="box">Some text</textarea>

How to clear a textarea value in jQuery?

I'm trying to validate keycode entry by adding an alert when a user types a key that isn't expected, and then clearing the text area. The alert functions correctly but the text area isn't clearing.
I've checked the documentation here, but I can't see an area with my .val() line. I've also tried this: $("#noteNumberInput").attr('value', "");
Scenario: I type 1-9 in the text box and get no alert (works fine), if I type a letter a-z for example, the alert pops up but the letter remains in the text box.
EDIT:
Something I've noticed is that it does clear the textarea after the first key. If I type the letter 'a' and then 'b', the 'a' is removed and replaced with a 'b'.
HTML:
<textarea id="noteNumberInput" placeholder="Note number"></textarea>
JS:
var noteNumberInput = document.getElementById("noteNumberInput");
//VALIDATE NOTE NUMBER TEXTAREA
function validate(key) {
var keycode = (key.which) ? key.which : key.keyCode;
//comparing pressed keycodes
if (keycode === 8 || (keycode >= 48 && keycode <= 57)) {
return true;
}
if (keycode < 48 || keycode > 57) {
alert("Please only enter the note number e.g. 1, 2..14 etc.");
$("#noteNumberInput").val("");
return false;
}
}
noteNumberInput.addEventListener("keydown", validate);
When you do $("#noteNumberInput").val('');, it removes all the content of the textarea, so if that's not what is happening, the problem is probably somewhere else.
Change noteNumberInput.addEventListener("keydown", validate); to use keyup
Using $("#noteNumberInput").val() will clear the textarea
EDIT
The problem is the keydown handler. In this case the function will be triggered followed by the display of alert & then the text area will be populated. But on using keyup the function will be triggered on release of the key.So by that time the textarea will be populated with value.
Change the keydown to keyup
var noteNumberInput = document.getElementById("noteNumberInput");
noteNumberInput.addEventListener("keyup", validate);
DEMO
Your only asking for the validate() function to actually execute when you've pressed the next key.
I think that´s not the best idea to trigger key events, because cut and paste and drag and drop can also change the input element.
try this:
Element.addEventListener('input', function(){
this.value=this.value.replace(/[^0-9,.]/g, '');
});
this must be adapted to textarea...

prevent "up arrow" key reseting cursor position within textbox

I recently added some predictive text input fields to the web-app I am supporting.
Big deal, right? Not really, seems like if your web-app doesn't do this -- you are already behind the times and your end-users are complaining. (At least that's how it is over here).
So, my question has to do with the "up" arrow key.
The predictive textbox has a onkeyup listener.
The handler segregates the key strokes and does something depending on the character the user entered.
The up arrow key allows the user to navigate in a div I created loaded with "suggestions."
I have several variables tracking indexes, etc...
Basically, when the user hits the up arrow I will change the id of the div to an id that has some css associated with it that will make the div appear as though it is selected. Additionally I will grab the value in that div and assign it to the textbox where the user is able to type.
The problem is an aesthetic one. Inherently with all text boxes I am learning, the up arrow key will reset the cursor position. This is happening just before I am writing the new value to the text field.
So, on each up arrow stroke, the user is seeing a jumping cursor in the textbox (it will jump to the beginning and immediately it will appear at the end).
Here's the code -
if (event.keyCode === 38 && currentUserInput.length > 0) {
// user has toggled out of the text input field, save their typing thus far
if (currentToggledIndex == -1) {
currentToggledIndex = autoFillKeywordsList.length-1;
savedKeywordUserInput = currentUserInput;
}
else {
// revert currently selected index back to its original id
document.getElementById("kw_selected").id = "kw_" + currentToggledIndex ;
// user has toggled back into user input field
if (currentToggledIndex == 0) {
currentToggledIndex = -1;
}
// user has toggled to the next suggestion
else {
currentToggledIndex--;
}
}
// 2. Determine next action based on the updated currentToggledIndex position
// revert the user input field back to what the user had typed prior to
// toggling out of the field
if (currentToggledIndex == -1) {
element.value = savedKeywordUserInput;
}
// mark the toggled index/keyword suggestion as "selected" and copy
// its value into the text field
else {
document.getElementById("kw_"+currentToggledIndex).id = "kw_selected";
element.value = autoFillKeywordsList[currentToggledIndex];
}
// 3. Determine what the user can do based on the current value currently
// selected/displayed
displayAppropriateButtonActions(element.value);
}
The funny thing is - the "down" arrow works perfectly since by default the down arrow key will place the cursor at the end of the string currently located in the textbox.
Ok, so things that I have already tried -
event.preventDefault();
event.stopPropogation();
I also tried to set the cursor position PRIOR to setting the new value to no avail using a setCursorPosition function I found on another post here. (Yeah, I was reaching with this one)
I tagged this as JavaScript and Jquery. I prefer to use JavaScript, but open to suggestions in Jquery too!
As Ryan suggested. how I achieved this in angular 4.x is
.html
<.. (keydown)="keyDownEvent($event)" >
.ts
keyDownEvent(event: any){
if (event.keyCode === 38 && event.key == "ArrowUp")
{
event.preventDefault();
//logic..
}
I think what you can do is when they move the cursor, grab that and find out what element it is ... then store it in a variable and focus() it and erase it and then put the value you stored back into it.
var holdme = $("#myelement").val();
$("#myelement").focus().val('').val(holdme);
This works for me when having weird cursor issues in jquery/javascript most of the time. Give it a try and if it doesn't work, let me know and I'll see what else might be wrong.
I found that it worked well to capture the caret position, blur, restore the caret position, then focus again.
myTextInput.onkeydown = function(e){
//some other code
if(e.key == "ArrowDown" || e.key == 40 || e.key == "ArrowUp" || e.key == 38){
var caretPos = this.selectionStart;
//do your stuff with up and down arrows
e.preventDefault();
this.blur();
this.selectionStart = caretPos;
this.selectionEnd = caretPos;
this.focus();
}
}
The caret will very briefly disappear, but I think you have to be incredibly observant to notice.

Javascript change event on input element fires on only losing focus

I have an input element and I want to keep checking the length of the contents and whenever the length becomes equal to a particular size, I want to enable the submit button, but I am facing a problem with the onchange event of Javascript as the event fires only when the input element goes out of scope and not when the contents change.
<input type="text" id="name" onchange="checkLength(this.value)" />
----onchange does not fire on changing contents of name, but only fires when name goes out of focus.
Is there something I can do to make this event work on content change? or some other event I can use for this?
I found a workaround by using the onkeyup function, but that does not fire when we select some content from the auto completer of the browser.
I want something which can work when the content of the field change whether by keyboard or by mouse... any ideas?
(function () {
var oldVal;
$('#name').on('change textInput input', function () {
var val = this.value;
if (val !== oldVal) {
oldVal = val;
checkLength(val);
}
});
}());
This will catch change, keystrokes, paste, textInput, input (when available). And not fire more than necessary.
http://jsfiddle.net/katspaugh/xqeDj/
References:
textInput — a W3C DOM Level 3 event type. http://www.w3.org/TR/DOM-Level-3-Events/#events-textevents
A user agent must dispatch this event when one or more characters have
been entered. These characters may originate from a variety of
sources, e.g., characters resulting from a key being pressed or
released on a keyboard device, from the processing of an input method
editor, or resulting from a voice command. Where a “paste” operation
generates a simple sequence of characters, i.e., a text passage
without any structure or style information, this event type should be
generated as well.
input — an HTML5 event type.
Fired at controls when the user changes the value
Firefox, Chrome, IE9 and other modern browsers support it.
This event occurs immediately after modification, unlike the onchange event, which occurs when the element loses focus.
It took me 30 minutes to find it, but this is working in June 2019.
<input type="text" id="myInput" oninput="myFunction()">
and if you want to add an event listener programmatically in js
inputElement.addEventListener("input", event => {})
As an extention to katspaugh's answer, here's a way to do it for multiple elements using a css class.
$('.myclass').each(function(){
$(this).attr('oldval',$(this).val());
});
$('.myclass').on('change keypress paste focus textInput input',function(){
var val = $(this).val();
if(val != $(this).attr('oldval') ){
$(this).attr('oldval',val);
checkLength($(this).val());
}
});
Do it the jQuery way:
<input type="text" id="name" name="name"/>
$('#name').keyup(function() {
alert('Content length has changed to: '+$(this).val().length);
});
You can use onkeyup
<input id="name" onkeyup="checkLength(this.value)" />
You would have to use a combination of onkeyup and onclick (or onmouseup) if you want to catch every possibility.
<input id="name" onkeyup="checkLength(this.value)" onmouseup="checkLength(this.value)" />
Here is another solution I develop for the same problem. However I use many input boxes so I keep old value as an user-defined attribute of the elements itself: "data-value". Using jQuery it is so easy to manage.
$(document).delegate('.filterBox', 'keyup', { self: this }, function (e) {
var self = e.data.self;
if (e.keyCode == 13) {
e.preventDefault();
$(this).attr('data-value', $(this).val());
self.filterBy(this, true)
}
else if (e.keyCode == 27) {
$(this).val('');
$(this).attr('data-value', '');
self.filterBy(this, true)
}
else {
if ($(this).attr('data-value') != $(this).val()) {
$(this).attr('data-value', $(this).val());
self.filterBy(this);
}
}
});
here is, I used 5-6 input boxes have class 'filterBox',
I make filterBy method run only if data-value is different than its own value.

Pass keydown event to another textbox

I'm trying to pass an keydown event from one textbox to another. What I mean with this is that if you, for example, press the 'a' key, some code should simulate that key as being pressed in the second textbox.
I do not want to just copy the value of the first textbox into the second - it should be on a per-key basis so to say. Suppose the first textbox contains abc and the second textbox is empty, when you then press the 'd' key in textbox 1, textbox 2 should only contain d.
What I already tried is (http://jsfiddle.net/E5qyr/1/):
$('#t1').keydown(function(e) {
$('#t2').keydown(e);
});
But this does not work (I guess I'm thinking too simple). I know I could append the character pressed by looking at e.keyCode, but also 'backspace' etc. has to be working.
Does anybody have an idea to pass a keydown event from one textbox to another?
Textarea elements don't have listeners automatically installed to them, so triggering a 'keydown' event for the #t2 will not show a response. What you want is to just add the text you get from the #t1 keydown event (of which you are listening) and append it to your #t2.
UPDATED with support for backspace. Other codes found here.
Example:
$('#t1').keydown(function(e) {
if (e.which == 8) { //Backspace
this.text(this.val().substr(0, this.val().length - 1));
} else {
$('#t2').append($('#t1').val());
this.empty();
}
});
Why not replace textbox value onkeydown? It seems it would be more simples to just do txt1.text = txt2.text instead of appending the existing strings in txt1.
Something like this?
$('#t1').keydown(function(e) {
var char = (e.keyCode == 8) ? '' : String.fromCharCode(e.keyCode + (e.shiftKey ? 0 : 32));
$('#t2').val(char);
});

Categories

Resources