I have an HTML input. When a user types in it, I've set up the 'input' event to handle updating the input to a filtered version of what the user typed (as well as updating selectionStart and selectionEnd for smooth UX). This happens constantly in order to give the proper effect.
What I've noticed, however, is that whenever JS sets the value of an input via input.value = '...';, it appears the undo history for the input disappears. That is, pressing Ctrl-Z with it focused no longer steps back to the previous state.
Is there any way to either provide the input custom undo history, or otherwise prevent it from losing the history whilst still changing its value?
Here is a minimal example of my issue:
After typing in the top input (which rudimentarily adds periods between every character), Ctrl-Z does not undo.
<body>
<input type="text" id="textbox" placeholder="No undo"/><br/>
<input type="text" id="textbox2" placeholder="Undo"/>
<script>
var tbx = document.getElementById("textbox");
tbx.addEventListener('input', () => {
tbx.value = tbx.value + '.'
});
</script>
</body>
You can try storing the input's previous value in a variable, then listen for the Ctrl + Z key combination in a keydown event listener attached to the input. When it is fired, you can set the value of the input to the previous stored value.
btn.addEventListener('click', function() {
savePrevInput(input.value)
input.value = "Hello World!";
})
var prevInput;
function savePrevInput(input) {
prevInput = input;
}
input.addEventListener("keydown", function(e) {
if (e.ctrlKey && e.keyCode == 90) {
if (prevInput) {
input.value = prevInput;
input.selectionStart = prevInput.length;
}
}
})
<input id="input" />
<button id="btn">Change</button>
Related
I am trying to get the text in a text box as the user types in it (jsfiddle playground):
function edValueKeyPress() {
var edValue = document.getElementById("edValue");
var s = edValue.value;
var lblValue = document.getElementById("lblValue");
lblValue.innerText = "The text box contains: " + s;
//var s = $("#edValue").val();
//$("#lblValue").text(s);
}
<input id="edValue" type="text" onKeyPress="edValueKeyPress()"><br>
<span id="lblValue">The text box contains: </span>
The code runs without errors, except that the value of the input text box, during onKeyPress is always the value before the change:
Question: How do I get the text of a text box during onKeyPress?
Bonus Chatter
There are three events related to "the user is typing" in the HTML DOM:
onKeyDown
onKeyPress
onKeyUp
In Windows, the order of WM_Key messages becomes important when the user holds down a key, and the key begins to repeat:
WM_KEYDOWN('a') - user has pushed down the A key
WM_CHAR('a') - an a character has been received from the user
WM_CHAR('a') - an a character has been received from the user
WM_CHAR('a') - an a character has been received from the user
WM_CHAR('a') - an a character has been received from the user
WM_CHAR('a') - an a character has been received from the user
WM_KEYUP('a') - the user has released the A key
Will result in five characters appearing in a text control: aaaaa
The important point being that the you respond to the WM_CHAR message, the one that repeats. Otherwise you miss events when a key is pressed.
In HTML things are slightly different:
onKeyDown
onKeyPress
onKeyDown
onKeyPress
onKeyDown
onKeyPress
onKeyDown
onKeyPress
onKeyDown
onKeyPress
onKeyUp
Html delivers an KeyDown and KeyPress every key repeat. And the KeyUp event is only raised when the user releases the key.
Take aways
I can respond to onKeyDown or onKeyPress, but both are still raised before the input.value has been updated
I cannot respond to onKeyUp, because it doesn't happen as the text in the text-box changes.
Question: How do I get the text of a text-box during onKeyPress?
Bonus Reading
Getting a form value with jQuery
Get the value in an input text box
Keep it simple. Use both onKeyPress() and onKeyUp():
<input id="edValue" type="text" onKeyPress="edValueKeyPress()" onKeyUp="edValueKeyPress()">
This takes care of getting the most updated string value (after key up) and also updates if the user holds down a key.
jsfiddle: http://jsfiddle.net/VDd6C/8/
Handling the input event is a consistent solution: it is supported for textarea and input elements in all contemporary browsers and it fires exactly when you need it:
function edValueKeyPress() {
var edValue = document.getElementById("edValue");
var s = edValue.value;
var lblValue = document.getElementById("lblValue");
lblValue.innerText = "The text box contains: " + s;
}
<input id="edValue" type="text" onInput="edValueKeyPress()"><br>
<span id="lblValue">The text box contains: </span>
I'd rewrite this a bit, though:
function showCurrentValue(event)
{
const value = event.target.value;
document.getElementById("label").innerText = value;
}
<input type="text" onInput="showCurrentValue(event)"><br>
The text box contains: <span id="label"></span>
the value of the input text box, during onKeyPress is always the value before the change
This is on purpose: This allows the event listener to cancel the keypress.
If the event listeners cancels the event, the value is not updated. If the event is not canceled, the value is updated, but after the event listener was called.
To get the value after the field value has been updated, schedule a function to run on the next event loop. The usual way to do this is to call setTimeout with a timeout of 0:
$('#field').keyup(function() {
var $field = $(this);
// this is the value before the keypress
var beforeVal = $field.val();
setTimeout(function() {
// this is the value after the keypress
var afterVal = $field.val();
}, 0);
});
Try here: http://jsfiddle.net/Q57gY/2/
Edit: Some browsers (e.g. Chrome) do not trigger keypress events for backspace; changed keypress to keyup in code.
keep it Compact.
Each time you press a key, the function edValueKeyPress() is called.
You've also declared and initialized some variables in that function - which slow down the process and requires more CPU and memory as well.
You can simply use this code - derived from simple substitution.
function edValueKeyPress()
{
document.getElementById("lblValue").innerText =""+document.getElementById("edValue").value;
}
That's all you want, and it's faster!
<asp:TextBox ID="txtMobile" runat="server" CssClass="form-control" style="width:92%; margin:0px 5px 0px 5px;" onkeypress="javascript:return isNumberKey(event);" MaxLength="12"></asp:TextBox>
<script>
function isNumberKey(evt) {
var charCode = (evt.which) ? evt.which : event.keyCode;
if (charCode > 31 && (charCode < 48 || charCode > 57)) {
return false;
}
return true;
}
</script>
None of the answers so far offer a complete solution. There are quite a few issues to address:
Not all keypresses are passed onto keydown and keypress handlers (e.g. backspace and delete keys are suppressed by some browsers).
Handling keydown is not a good idea. There are situations where a keydown does NOT result in a keypress!
setTimeout() style solutions get delayed under Google Chrome/Blink web browsers until the user stops typing.
Mouse and touch events may be used to perform actions such as cut, copy, and paste. Those events will not trigger keyboard events.
The browser, depending on the input method, may not deliver notification that the element has changed until the user navigates away from the field.
A more correct solution will handle the keypress, keyup, input, and change events.
Example:
<p><input id="editvalue" type="text"></p>
<p>The text box contains: <span id="labelvalue"></span></p>
<script>
function UpdateDisplay()
{
var inputelem = document.getElementById("editvalue");
var s = inputelem.value;
var labelelem = document.getElementById("labelvalue");
labelelem.innerText = s;
}
// Initial update.
UpdateDisplay();
// Register event handlers.
var inputelem = document.getElementById("editvalue");
inputelem.addEventListener('keypress', UpdateDisplay);
inputelem.addEventListener('keyup', UpdateDisplay);
inputelem.addEventListener('input', UpdateDisplay);
inputelem.addEventListener('change', UpdateDisplay);
</script>
Fiddle:
http://jsfiddle.net/VDd6C/2175/
Handling all four events catches all of the edge cases. When working with input from a user, all types of input methods should be considered and cross-browser and cross-device functionality should be verified. The above code has been tested in Firefox, Edge, and Chrome on desktop as well as the mobile devices I own.
I normally concatenate the field's value (i.e. before it's updated) with the key associated with the key event. The following uses recent JS so would need adjusting for support in older IE's.
Recent JS example
document.querySelector('#test').addEventListener('keypress', function(evt) {
var real_val = this.value + String.fromCharCode(evt.which);
if (evt.which == 8) real_val = real_val.substr(0, real_val.length - 2);
alert(real_val);
}, false);
Support for older IEs example
//get field
var field = document.getElementById('test');
//bind, somehow
if (window.addEventListener)
field.addEventListener('keypress', keypress_cb, false);
else
field.attachEvent('onkeypress', keypress_cb);
//callback
function keypress_cb(evt) {
evt = evt || window.event;
var code = evt.which || evt.keyCode,
real_val = this.value + String.fromCharCode(code);
if (code == 8) real_val = real_val.substr(0, real_val.length - 2);
}
[EDIT - this approach, by default, disables key presses for things like back space, CTRL+A. The code above accommodates for the former, but would need further tinkering to allow for the latter, and a few other eventualities. See Ian Boyd's comment below.]
easy...
In your keyPress event handler, write
void ValidateKeyPressHandler(object sender, KeyPressEventArgs e)
{
var tb = sender as TextBox;
var startPos = tb.SelectionStart;
var selLen= tb.SelectionLength;
var afterEditValue = tb.Text.Remove(startPos, selLen)
.Insert(startPos, e.KeyChar.ToString());
// ... more here
}
So there are advantages and disadvantages to each event. The events onkeypress and onkeydown don't retrieve the latest value, and onkeypress doesn't fire for non-printable characters in some browsers. The onkeyup event doesn't detect when a key is held down for multiple characters.
This is a little hacky, but doing something like
function edValueKeyDown(input) {
var s = input.value;
var lblValue = document.getElementById("lblValue");
lblValue.innerText = "The text box contains: "+s;
//var s = $("#edValue").val();
//$("#lblValue").text(s);
}
<input id="edValue" type="text" onkeydown="setTimeout(edValueKeyDown, 0, this)" />
seems to handle the best of all worlds.
By using event.key we can get values prior entry into HTML Input Text Box. Here is the code.
function checkText()
{
console.log("Value Entered which was prevented was - " + event.key);
//Following will prevent displaying value on textbox
//You need to use your validation functions here and return value true or false.
return false;
}
<input type="text" placeholder="Enter Value" onkeypress="return checkText()" />
Try to concatenate the event charCode to the value you get.
Here is a sample of my code:
<input type="text" name="price" onkeypress="return (cnum(event,this))" maxlength="10">
<p id="demo"></p>
js:
function cnum(event, str) {
var a = event.charCode;
var ab = str.value + String.fromCharCode(a);
document.getElementById('demo').innerHTML = ab;
}
The value in ab will get the latest value in the input field.
There is a better way to do this. Use the concat Method. Example
declare a global variable. this works good on angular 10, just pass it to Vanilla JavaScript. Example:
HTML
<input id="edValue" type="text" onKeyPress="edValueKeyPress($event)"><br>
<span id="lblValue">The text box contains: </span>
CODE
emptyString = ''
edValueKeyPress ($event){
this.emptyString = this.emptyString.concat($event.key);
console.log(this.emptyString);
}
I am very new to Javascript as I began self-learning just yesterday. I am trying to emulate a type racer game.
(spacebar) as the input will signify the completion of my attempt to type the current word, and I have functions to check if it is correct/incorrect, and then resets the input.
So if I type apple and then (space), the input field becomes reset.
However the problem is if the user types too quickly, then the first or more character of the next word is included in the input before the reset function.
Example:
words to type: apple lemon
user input: apple lemon
input field: apple le -> upon space, reset() is called and clears input but user already typed le once reset() is completed -> mon
So I am wondering if there is a way to speed up reset() such that it is called and completed before the next input from the user.
I initially had everything under 1 function "inputMatch", that was called upon keyup, but tried to separate the reset() and inputMatch() functions by having one being called upon keydown, and the other upon keyup.
This is the code I have. I can provide more context/the full code if needed, but since I am new here, I am unsure whether people prefer to read simplified pseudo code or actual code.
<input type="text" class="form-control" id="inputfield" value="" dir="ltr" placeholder="" onkeyup="reset()" onkeydown="inputMatch(event)">
<script>
const inputMatch = () => {
var current = word that I am currently attempting to type;
if(event.keyCode == 32){ //spacebar
change word that was typed to be either correct or incorrect
};
//once at end need to remove the first (current.wordnr - 1) words
}
const reset = () => {
if(event.keyCode == 32){ //spacebar
document.getElementById('inputfield').value = ""; //clear input field
}
}
</script>
Welcome to Stack Overflow! My recommendation would be to use the oninput event handler instead of onkeyup/onkeydown. See the following code:
const handle = (input) => {
if (input.charAt(input.length - 1) === ' ') // If the last character is a space
reset()
else // otherwise, handle your input (in your case, use it in your type racing game)
console.log("Partial word: " + input)
}
const inputField = document.getElementById("inputfield")
const reset = () => {
console.log("Entered word: " + inputField.value.trimRight())
inputField.value = ""
}
<input type="text" id="inputfield" value="" dir="ltr" placeholder="" oninput="handle(this.value)">
oninput runs synchronously, meaning that it's impossible for the user to type too quickly. It also makes the code a lot simpler.
I would like to add text to the active textbox when a button is clicked.
I have read many threads explaining how it is done when one is wishing to add to a specific textbox but nothing on simply adding text to whichever text field is active...
Any help would be appreciated. Thanks.
The below is a solution for a virtual keyboard.
Pure JS + HTML:
function bind() {
var keyArr = document.getElementsByClassName('key');
for(var i = 0; i < keyArr.length; i++) {
keyArr[i].addEventListener('click', function() {
document.getElementById('textinput').value += this.innerHTML;
});
}
var capsLock = document.getElementById('capslock');
capsLock.addEventListener('click', function() {
for(var i = 0; i < keyArr.length; i++) {
if(capsLock.capsactive) {
keyArr[i].innerHTML = keyArr[i].innerHTML.toLowerCase();
} else {
keyArr[i].innerHTML = keyArr[i].innerHTML.toUpperCase();
}
}
capsLock.capsactive = !capsLock.capsactive;
});
}
<body onload='bind()'>
<input id='textinput'><br>
<button class='key'>q</button>
<button class='key'>w</button>
<button class='key'>e</button>
<button class='key'>r</button>
<button class='key'>t</button>
<button class='key'>y</button><br>
<button id='capslock' capsactive=false>CapsLock</button>
</body>
You can access a textbox's value by element.value or by $(selector).val().
For changing, use: element.value = newvalue; (JS) or $(selector).val(newvalue); (jQuery).
In the example, ...addEventListener... attaches a function to each button. The function, here, changes the value of the textinput textbox, to be the previous value + the text of the button which was pressed.
For instance, if the even the capsLock button is given the class key, on clicking capsLock, the text "Caps Lock" will be appended to the textbox.
Note: This solution covers adding text to a definite field. If there are multiple textbox-es present on the page, and the text has to be added to the currently focused one, a different approach has to be taken:
var lfl = -1, capsactive = false;
$(document).ready(function() {
$('*').blur(function() {
lfl = this;
});
$('.key').click(function() {
if($(lfl).hasClass('vkballowed')) {
$(lfl).val($(lfl).val() + $(this).html());
$(lfl).focus();
}
});
$('#capslock').click(function() {
capsactive = !capsactive;
if(capsactive == true) {
$('.key').each(function() {
$(this).html($(this).html().toUpperCase());
});
} else {
$('.key').each(function() {
$(this).html($(this).html().toLowerCase());
});
}
$(lfl).focus();
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.10.2/jquery.min.js"></script>
<input id='input0' class='vkballowed'><p>Editable</p><br>
<input id='input1' class='vkballowed'><p>Editable</p><br>
<input id='input2'><p>Not Editable</p><br>
<button class='key'>q</button>
<button class='key'>w</button>
<button class='key'>e</button>
<button class='key'>r</button>
<button class='key'>t</button>
<button class='key'>y</button><br>
<button id='capslock'>CapsLock</button>
Example instructions: Focus on the Editable text-fields, then press a key on the virtual-keyboard, so that corresponding text is appended to the fields. The virtual-keyboard doesn't work on the Not Editable text-field.
Here, the last element on the page that lost focus (was blurred) is stored in a variable. Next, whenever a key on the virtual-keyboard is pressed, first, it is checked whether the keyboard is allowed on that control, then the button's text is appended to the control, and finally, the control is given its focus back. Note that if the class vkballowed is added to controls such as buttons, no action would be effective on those controls. On other controls such as textareas, which have a value property, the virtual-keyboard will be functional.
The above approach isn't wholly correct. If, for instance, a key on the virtual-keyboard is pressed right after some other interactive button on the page, that button would receive focus again (this may not re-cause the action attached to that button, though). It, hopefully, gives you a starting point though.
jquery
$('#buttonId').click(function(event) {
$('.tstboxClass').val('heelo i am text box value.');
})
I have a few input fields that use onKeyUp="script" to return data the moment something is entered.
As a shortcut, I would like to be able to add a value to one of the fields when data is entered from another location AND trigger the script.
I can use document.getElementById("myID").value = MyValue; to add a specific value to the input box, or .addEventListener(); to watch another input field.
This part works well.
However, I have not been able to trigger anything equivalent to onKeyUp, which will happen either when:
1. You press/release a key while the input field is in focus.
2. You focus the input and release a key AFTER the script has added a value.
3. You enter the input field via [TAB] AFTER the script has added a value.
Adding .keyup(); or .keypress(); have had no effect.
I've been able to use .focus(); to focus and then change the input, but this does not have the same effect as pressing [TAB]
What can I do to trigger the onKeyUp for this field, even if the data was not manually typed?
ADDITIONAL INFO
This part works...
<input type="text" id="box1" onKeyUp="script1();">
<div id="result1" "> (script places result here) </div>
Add value from another location - Option 1
<input type="text" id="Test1">
<button type="button" onclick="TestScript()"> TEST</button>
<script type='text/javascript'>
function TestScript() {
var test1=document.getElementById("Test1").value;
document.getElementById("box1").value = test1;
document.getElementById("box1").keyup();
return false;
}
</script>
Add value from another location - Option 2
<script type='text/javascript'>
window.onload = function () {
document.getElementsByName("box2")[0].addEventListener('change', TestScript2);
function TestScript2(){
var test2=document.getElementById("box2").value;
document.getElementById("box1").value = test2;
}}
</script>
Both of these options will copy the value to the correct location, but I have not been able to get either to trigger the onKeyUp so that the original script realizes something has changed.
Non working Fiddle example: https://jsfiddle.net/mj8g4xa2/4/
Trigger keyup programatically in;
JAVASCRIPT:
Call onkeyup() on the element.
Create a new keyup event and dispatch it using the element. Note: The source here doesn't support IE. Refer this answer for cross-browser support. Also createEvent is deprecated (MDN Docs for reference).
JQUERY:
$("#elem").keyup();
$("#elem").trigger('keyup');
Change events fire only when the input blurs, according to the MDN Docs.
Also, you should have got Uncaught TypeError: element.keyup is not a function error in your console.
var elem = document.getElementById("data");
function triggerKeyUpEvent()
{
var e = document.createEvent('HTMLEvents');
e.initEvent("keyup",false,true);
elem.dispatchEvent(e);
}
function perform()
{
console.log("KeyUp");
}
function add()
{
elem.value = String.fromCharCode(Math.random().toFixed(2)*100).repeat(5);
elem.onkeyup();
triggerKeyUpEvent();
}
<input id="data" onkeyup="perform()">
<button id="add" onclick="add()">Add Random Data</button>
To fix your JSFiddle update the following code:
var elem = document.getElementById("sim1");
function triggerKeyUpEvent() {
var e = document.createEvent('HTMLEvents');
e.initEvent("keyup",false,true);
elem.dispatchEvent(e);
}
function add() {
var sim1=document.getElementById("sim1").value;
document.getElementById("box1").value = sim1;
elem.onkeyup();
triggerKeyUpEvent()
}
by replacing the line elem.dispatchEvent(e) with box1.dispatchEvent(e)
And the line elem.onkeyup() with box1.onkeyup()
Lastly, it would seem that you don't need to call triggerKeyUpEvent as when I removed it, it still works.
Here's the udpated JSFiddle
How to set blank default text on input field and clear it when element is active.
In modern browsers, you may set the placeholder attribute on a field to set its default text.
<input type="text" placeholder="Type some text" id="myField" />
However, in older browsers, you may use JavaScript to capture the focus and blur events:
var addEvent = function(elem, type, fn) { // Simple utility for cross-browser event handling
if (elem.addEventListener) elem.addEventListener(type, fn, false);
else if (elem.attachEvent) elem.attachEvent('on' + type, fn);
},
textField = document.getElementById('myField'),
placeholder = 'Type some text'; // The placeholder text
addEvent(textField, 'focus', function() {
if (this.value === placeholder) this.value = '';
});
addEvent(textField, 'blur', function() {
if (this.value === '') this.value = placeholder;
});
Demo: http://jsbin.com/utecu
Using the onFocus and onBlur events allows you to achieve this, I.e.:
onfocus="if(this.value=='EGTEXT')this.value=''"
and
onblur="if(this.value=='')this.value='EGTEXT'"
The full example is as follows:
<input name="example" type="text" id="example" size="50" value="EGTEXT" onfocus="if(this.value=='EGTEXT')this.value=''" onblur="if(this.value=='')this.value='EGTEXT'" />
Or simply
<input name="example" type="text" id="example" value="Something" onfocus="value=''" />
This will not post back the default text once the box is cleared but also will allow the user to clear the box and see all results in the case of an autocomplete script.
Declare styles for inactive and active states:
.active {
color: black;
}
.inactive {
color: #909090;
}
Add the Javascript to handle the changing of state:
function toggleText(el)
{
var v = el.value;
//Remove text to allow editing
if(v=="Default text") {
el.value = "";
el.className = "active";
}
else {
//Remove whitespace
if(v.indexOf(" ")!=-1) {
split = v.split(" ").join("");
v = split;
}
//Change to inactive state
if(v=="") {
el.value = "Default text";
el.className = "inactive";
}
}
}
Add your input box, with the default value set, the inactive class set and Javascript handlers pointing to the toggleText() function (you could use event listeners to do this if you wish)
<input type="text" value="Default text" class="inactive" onFocus="toggleText(this);" onBlur="toggleText(this);">
From a usability point of view the text in the input component should be preserved only for user's input purposes. The possible default value in the input should be valid if left untouched by the user.
If the placeholder text is meant to be a hint for how to fill the input, it is better to be blaced near the input where it can be seen also when the input has been filled. Moreover, using a placeholder text inside text components can cause troubles e.g. with braille devices.
If a placeholder text is used, regardless of usability guidelines, one should make sure that it is done in an unobtrusive way so that it works with user agents without javascript or when js is turned off.
I have found jQuery plugin (http://www.jason-palmer.com/2008/08/jquery-plugin-form-field-default-value/) and use it :)
What I did is put a placeholder attribute for modern browsers:
<input id='search' placeholder='Search' />
Then, I made a fallback for older browsers using JQuery:
var placeholder = $('search').attr('placeholder');
//Set the value
$('search').val(placeholder);
//On focus (when user clicks into the input)
$('search').focus(function() {
if ($(this).val() == placeholder)
$(this).val('');
});
//If they focus out of the box (tab or click out)
$('search').blur(function() {
if ($(this).val() == '')
$(this).val(placeholder);
});
This works for me.
You can use this plugin (I'm an co-author)
https://github.com/tanin47/jquery.default_text
It clones an input field and put it there.
It works on IE, Firefox, Chrome and even iPhone Safari, which has the famous focus problem.
This way you do not have to be worried about clearing input field before submitting.
OR
If you want to HTML5 only, you can just use attribute "placeholder" on input field
You can use placeholder attribute.
np. <input type="text" name="fname" placeholder="First name">
check http://www.w3schools.com/tags/att_input_placeholder.asp