Can a DOM element handle both keyup and input event? - javascript

In an application I have a text input elements with an input handler. There is a special action I'd like to do on backspace so I added a keyup handler to handle this case. It doesn't gets called unless the field is empty - apparently when the input handler is called it suppresses the keyup handler.
I could probably rewrite the code using the keyup handler for everything but that would involve reproducing proper handling of pasting and other keys (delete, enter, tab, etc.), which I'd rather not do.
This is on chrome but I tested it on firefox and safari too and get the same behavior so it must be expected, but I can't find it documented. The following code demonstrates the issue. When loaded as is and text is entered only the input handler is called. When the field is empty the keyup handler is called. If the input handler is deleted then of course the keyup handler is called on every key press.
<html>
<head>
<script>
function setup() {
document.getElementById("xxx").addEventListener("input", (ev) => alert("input"));
document.getElementById("xxx").addEventListener("keyup", (ev) => alert("keyup"));
}
window.addEventListener("load", () => setup());
</script>
</head>
<body>
test handlers: <input type="text" id="xxx" />
</body>
</html>
(sample edited to use addEventListener rather than onevent)
The workaround I'm thinking about now is using a keydown event, which is called, but I'd like to understand why it has this behavior.

They are both getting called every time only the one alert is invalidating the other call as you can see if you change the alert to a log
<html>
<head>
</head>
<body>
test handlers: <input type="text" oninput="console.log('input')" onkeyup="alert('keyup')" />
</body>
</html>
or if you set a timeout
<html>
<head>
</head>
<body>
test handlers: <input type="text" oninput="setTimeout(()=>alert('input'),1000)" onkeyup="alert('keyup')" />
</body>
</html>
This is expected as a backspace is changing the input and a keyup is when a key is released and the keyup is released when the alert is in the window

Related

Element.focus() doesn't work when called within a function handler for addEventListener()

Here is my code. For some reason, this code does not give focus to the textbox with the id "dude" even though the paragraph tag with id "answer" does get the key code of the button that I clicked. It is like the line with the focus() command gets completely ignored.
document.getElementById("thing").addEventListener("keypress", function() {
myFunction(event);
});
function myFunction(event) {
document.getElementById("answer").innerHTML = event.keyCode;
document.getElementById("dude").focus();
}
<!DOCTYPE html>
<html>
<body>
<input type="text" id="thing">
<input type="text" id="dude">
<p id="answer"></p>
</body>
</html>
However, if I were to make a slight modification and put the line with the focus() outside of the addEventListener(), then the focus() would work. For example, the following code works:
document.getElementById("dude").focus();
document.getElementById("thing").addEventListener("keypress", function() {
myFunction(event);
});
function myFunction(event) {
document.getElementById("answer").innerHTML = event.keyCode;
}
<!DOCTYPE html>
<html>
<body>
<input type="text" id="thing">
<input type="text" id="dude">
<p id="answer"></p>
</body>
</html>
The above code would actually start by giving the "dude" textbox focus.
Is there any reason for this and anything that I can do about this?
The keypress event handler fires too early - the user hasn't finished pressing the key down and entering in the value at that point, so the focus reverts to the initial input field. See how if you change the focus after a setTimeout it'll work:
document.getElementById("thing").addEventListener("keypress", function() {
myFunction(event);
});
function myFunction(event) {
document.getElementById("answer").innerHTML = event.keyCode;
setTimeout(() => document.getElementById("dude").focus());
}
<input type="text" id="thing">
<input type="text" id="dude">
<p id="answer"></p>
Or watch for the keyup event instead:
document.getElementById("thing").addEventListener("keyup", function() {
myFunction(event);
});
function myFunction(event) {
document.getElementById("answer").innerHTML = event.keyCode;
document.getElementById("dude").focus();
}
<input type="text" id="thing">
<input type="text" id="dude">
<p id="answer"></p>
For example, the following code works:
Not exactly, because with that code, you're focusing the dude input on pageload, rather than when the thing input has stuff typed into it.
You also should avoid using keypress in modern code, it's deprecated:
This feature is no longer recommended. Though some browsers might still support it, it may have already been removed from the relevant web standards, may be in the process of being dropped, or may only be kept for compatibility purposes. Avoid using it, and update existing code if possible; see the compatibility table at the bottom of this page to guide your decision. Be aware that this feature may cease to work at any time.
Since this event has been deprecated, you should look to use beforeinput or keydown instead.
keyCode is too, technically, but the replacement for it - .code - isn't compatible everywhere.
Use the keyup event instead of keypress, because the default action of the keypress event sets the focus back to that input element.
document.getElementById("thing").addEventListener("keyup", function() {
myFunction(event);
});
function myFunction(event) {
document.getElementById("answer").innerHTML = event.keyCode;
document.getElementById("dude").focus();
}
<!DOCTYPE html>
<html>
<body>
<input type="text" id="thing">
<input type="text" id="dude">
<p id="answer"></p>
</body>
</html>
It seems like you are trying to shift focus from input "thing" to input "dude" after you complete a "keypress" or "keyup" on input "thing".
I don't understand the use case for this. But, IMO if you are trying to change the focus state after you input a value, I would recommend placing an event listener on the "change" event. You could simply press your "TAB" key on your keyboard after you are done inputting data into input "thing" and focus will be shifted to the input "dude" and the function will execute. Both achieved!
document.getElementById('thing').addEventListener('change', function (event) {
myFunction(event.target.value)
})
function myFunction(answer) {
document.getElementById('answer').innerText = answer
}
<input type="text" id="thing" />
<input type="text" id="dude" />
<p id="answer"></p>

How to fires onClick event before onChange (even if the value has changed)?

Hello everyone and sorry for my english.
Following this jdfiddle, I have a problem I don't understand.
First I change the value of the input, then I click on the button and what I expected to see is "click" but I see "change" meaning onclick is called after onchange.
<input type="text" onChange="alert('change')" />
<button type="button" onClick="alert('click');">Click!</button>
I found on this post that it's because of chrome which fires onchange event before the onclick event. But I don't really have the same need as this post because my event are not declared in the same tag. And secondly, if I click on the button I would like to only execute the onclick function and not onclick and then onchange (this methods consists in using onMouseDown).
Do you have a good method to do that?
Ok so I can see that you really wan't this.
You could let the on change function run first, and then afterward see what has focus, if it is that button, you would know that it was clicked, and thus was the reason for loosing focus.
you cannot check this while the change function is running, as the body still has focus at this time..
<head>
<script language="javascript">
function focussed()
{
var triggerElement = document.activeElement
alert(triggerElement)
console.info(triggerElement)
}
function change()
{
alert("change")
setTimeout(focussed, 1)
return true
}
</script>
</head>
<body>
<input type="text" onChange="alert('change')" />
<button type="button" onClick="alert('click');">Click!</button>
</body>

submit a form with mooTools, and have the forms inline onsubmit event fire...help

Im writing a class that replaces all input type="button" and input type="submit" in the document with a custom button, that is actually a span stuffed inside of an anchor tag, i've got everything written, and it all works, except the inline onsubmit event is not being fired when the form is submitted with a javascript.
Actually, even writing a static anchor tag
Submit
will not fire the inline onsubmit event for the form, but <input type="submit" /> will fire the event...anyways there has to be a way to fire this onsubmit event with javascript.
Heres a snippet of what im working with:
click: function() {
//get parent form
var thisForm = this.getParent('form');
//fire onsubmit event
thisForm.fireEvent('submit'); //this doesnt work!
//submit form...the event isn't fired here either!
thisForm.submit();
}
anybody have any ideas? this class needs to need no configuration and there are some older sites using our cms system that we want to plug this into, and there are quite a few inline submit events on the forms we need to account for
Thanks
UPDATE,
I took the suggestion and came up with this:
if(this.getParent().onsubmit()) {
this.getParent().submit();
}
works perfectly for evaluating the forms onsubmit event and submitting the form based on its output, but what if the function doesn't exist at all? Any ideas?
Firing submit on a form doesn't trigger it's inline onSubmit, this is default javascript behaviour (found this: http://www.codestore.net/store.nsf/unid/DOMM-4QS3RL/)
You can try calling onsubmit yourself though, this works for me:
<!DOCTYPE html>
<html>
<head>
<script type="text/javascript" src="https://ajax.googleapis.com/ajax/libs/mootools/1.3.1/mootools-yui-compressed.js"></script>
<script type="text/javascript" charset="utf-8">
window.addEvent('domready', function(e) {
$$('span.submit').each(function(el) {
el.addEvent('click', function(e) {
this.getParent().onsubmit();
});
});
});
</script>
</head>
<body>
<form method="post" onsubmit="alert('hi');" class="form">
<input type="text" value="test" />
<span class="submit">Submit the form</span>
</form>
</body>
</html>
You might want to try this code instead as it will check to see if the onsubmit event has been attached as an event listener rather than being a hard encoded attribute. If the event was attached as a listener the [form element].onsubmit() part won't work.
function myOnSubmit(formId){
var f = document.getElementById(formId);
if(document.createEvent){
var e = document.createEvent('Event');
e.initEvent('submit',true,false);
f.dispatchEvent(e);
} elseif(document.createEventObject){
var e = document.createEventObject('Event');
e.button = 1;
f.fireEvent('onsubmit',e);
} elseif(typeof(f.onsubmit) == 'function'){
f.onsubmit();
}
}

IE not triggering keyboard event on a form with ONE FIELD

I'm seeing my Friend's code here...
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<TITLE> Check action </TITLE>
<script>
function detectEvent(){
if(window.event.keyCode==13)
{
alert("you hit return!");
}
}
</script>
</HEAD>
<BODY>
<form name="name1" onkeyup="detectEvent()" action="page2.html">
<p> Field1
<input type="text" id="text1"/>
</p>
</form>
</BODY>
</HTML>
and when he tried entering a value in the textbox and pressed enter, it did not call the detectEvent(). I said, it'll always call onSubmit on enter button.....
and he surprised me,
<!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 4.0 Transitional//EN">
<HTML>
<HEAD>
<TITLE> Check action </TITLE>
<script>
function detectEvent(){
if(window.event.keyCode==13)
{
alert("you hit return!");
}
}
</script>
</HEAD>
<BODY>
<form name="name1" onkeyup="detectEvent()" action="page2.html">
<p> Field1
<input type="text" id="text1"/>
</p>
<p> Field1
<input type="text" id="text2"/>
</p>
</form>
</BODY>
</HTML>
Now press enter, The function gets called.....
Why so!?
Why onKeyUp not called on forms with just one field.!!! am i missing something?
The order of events is:
keydown
keypress
submit
keyup
So by the time your keyup handler would have been called, the form has already started submitting. If the action of the form is a page2.html on the local filesystem, that's going to navigate very quickly and probably move away from the page before keyup can be called; set the action to an external site, on the other hand, and keyup will have time to fire.
Adding the second input field is a different issue: in this case the form is not submitted at all. It is a curious historical quirk that browsers will submit a form that has only one input and no submit button, but refuse to submit a form with more than one input, and no submit button. This goes back to the HTML 2.0 spec:
When there is only one single-line text input field in a form, the user agent should accept Enter in that field as a request to submit the form.
HTML 2.0 didn't specify whether or not Enter should be accepted to submit a form in any other circumstances (the intention seems only to have been to duplicate the functionality of the ancient <isindex> element), but browsers of the day seem to have interpreted that to mean that Enter-submission shouldn't happen where there are multiple fields, but then any submit button causes Enter-submission to happen anyway. IE and other later browsers copied this odd behaviour.
Unrelated point: the reliance on window.event makes the code needlessly IE-only. For all other browsers, the event object is passed in as an argument to the event handler function. You can do onkeyup="detectEvent(event)" in the HTML and then use that argument in the detectEvent function, which works on both models because either the local argument event or the global window.event is used. But the usual approach would be to lose the event handler attribute and assign from JavaScript:
<form action="page2.html" id="enterform">
<p> Field1
<input type="text" id="text1">
<!-- Note: *no* trailing slash - the doctype says HTML4, not XHTML -->
</p>
</form>
<script type="text/javascript">
document.getElementById('enterform').onkeyup= function(event) {
if (event===undefined) event= window.event; // for IE
if (event.keyCode===13)
alert('You pressed Enter');
};
</script>
Having said all that... I'm generally suspicious of trapping the Enter key. I'm not quite sure what you're trying to do, but if it's the common case of changing the default button in a form this definitely isn't the way to do it and will cause an assortment of problems. There is no good reason you should be trapping the Enter key to call .submit() on a form.
Interestingly enough, in Google Chrome, the form with the second input field will still submit, so it never catches the enter key on a keyup event, regardless of how many fields you have.
Solution = use keypress or keydown.

How to get the new value of an HTML input after a keypress has modified it?

I have an HTML input box
<input type="text" id="foo" value="bar">
I've attached a handler for the 'keyup' event, but if I retrieve the current value of the input box during the event handler, I get the value as it was, and not as it will be!
I've tried picking up 'keypress' and 'change' events, same problem.
I'm sure this is simple to solve, but at present I think the only solution is for me to use a short timeout to trigger some code a few milliseconds in the future!
Is there anyway to obtain the current value during those events?
EDIT: looks like I had a caching problem with my js file as I checked the same code later on and it worked just fine. I would delete the question, but not sure if that loses rep for the kind folk who posted ideas :)
Can you post your code? I'm not finding any issue with this. Tested on Firefox 3.01/safari 3.1.2 with:
function showMe(e) {
// i am spammy!
alert(e.value);
}
....
<input type="text" id="foo" value="bar" onkeyup="showMe(this)" />
To give a modern approach to this question. This works well, including Ctrl+v. GlobalEventHandlers.oninput.
var onChange = function(evt) {
console.info(this.value);
// or
console.info(evt.target.value);
};
var input = document.getElementById('some-id');
input.addEventListener('input', onChange, false);
There are two kinds of input value: field's property and field's html attribute.
If you use keyup event and field.value you shuld get current value of the field.
It's not the case when you use field.getAttribute('value') which would return what's in the html attribute (value=""). The property represents what's been typed into the field and changes as you type, while attribute doesn't change automatically (you can change it using field.setAttribute method).
<html>
<head>
<script>
function callme(field) {
alert("field:" + field.value);
}
</script>
</head>
<body>
<form name="f1">
<input type="text" onkeyup="callme(this);" name="text1">
</form>
</body>
</html>
It looks like you can use the onkeyup to get the new value of the HTML input control. Hope it helps.
Here is a table of the different events and the levels of browser support. You need to pick an event which is supported across at least all modern browsers.
As you will see from the table, the keypress and change event do not have uniform support whereas the keyup event does.
Also make sure you attach the event handler using a cross-browser-compatible method...
You can try this code (requires jQuery):
<html>
<head>
<script type="text/javascript" src="jquery.js"></script>
<script type="text/javascript">
$(document).ready(function() {
$('#foo').keyup(function(e) {
var v = $('#foo').val();
$('#debug').val(v);
})
});
</script>
</head>
<body>
<form>
<input type="text" id="foo" value="bar"><br>
<textarea id="debug"></textarea>
</form>
</body>
</html>

Categories

Resources