How to tell if a keypress event would generate input - javascript

Some keypress events generate input (e.g. normal characters) and some don't (e.g. arrow keys). Is there any way to tell whether a particular keypress event is input-generating?
Additional context as requested:
I'm using contentEditable to edit text. I would like to pass non-input-generating events (cursor movement, selection, etc.) to the underlying element, but handle input-generating events myself.

It turns out that most browsers don't generate keypress events for arrow keys (although this doesn't seem to be guaranteed to be the case by the standard as far as I can see).
In addition, the standard defines a beforeinput event, which looks to be exactly what I want. Except it doesn't actually seem to be implemented by any browsers.

not sure what you mean... maybe you are talking of
var key = ev? ev.which: window.event.keyCode
what gives you the key that was pressed, so you can find out if "char" or not...
regards Joachim

Related

What's the difference between keyup, keydown, keypress and input events?

I have been trying to understand JavaScript keypress, keydown, keyup and input events. But I found them quite confusing. Could someone please point out the exact differences? Also I would like to know do all of them get triggered when the user paste a piece of text.
According to jQuery docs:
The keypress event is sent to an element when the browser registers keyboard input. This is similar to the keydown event, except that modifier and non-printing keys such as Shift, Esc, and delete trigger keydown events but not keypress events. Other differences between the two events may arise depending on platform and browser.
The keyup event is sent to an element when the user releases a key on the keyboard.
The oninput event it's an event that triggers whenever the input changes.
However the input event is not supported in IE version below 9. In that case, you could use proprietary event onpropertychange, it does the same as oninput.
But in your case, you could use the paste and change event together. You should use change too because paste only happens on browsers that support it on an explicit paste.
Since this is being treated as the definitive JS answer (rather than just a jQuery answer) here's a current standard JavaScript answer with MDN references:
input event - fired when the content changes. This includes mouse pastes and non-keyboard input.
keyup event - fired when a key is released. This includes shift key, control key, and other keys that don't change the value of input elements.
Docs for all events

`keydown` event: find the character that would have got typed, had shift been pressed down as well

In JavaScript, on a keydown or keypress event, is there a way to determine the character that would have got typed if the shift key was pressed down as well (irrespective of whether the shift key is actually held down at the time)
E.g: if the keydown corresponds to '1', I need to get '!'
This would depend on the keyboard type as well. So, is there a way to factor that in too?
Theoretically, keypress events should give the character representing the key you have pressed (which is what you are aiming at), however the implementation on browsers vary (yes, it's 2013 and we're still at that).
See the answer on this question

Synchronizing identical html forms

I'd like to have two (or even more) identical html forms on my website.
For example, one - at the top, and another - at the bottom of the page.
What i want is for them to have exactly the same content at any given time. If user changes a value in one of them, all the rest are updated.
Is there a better way to synchronize then javascript onchange/onkeyup events?
onchange fires only after element loses focus.
onkeyup is not perfect too. It wastes a lot of cpu on long text copying and won't fire if element lost focus between onkeydown and onkeyup events.
Update: I just learned that HTML5 has a more appropriate event for this, oninput, but of course it doesn't work in older browsers. oninput will detect any kind of text change, including Paste, Cut, and Delete from the right-click menu. So the best option may be to check if the browser supports oninput (e.g. by using the function recommended here), falling back to the below method if not. On older versions of IE, onpropertychange can be used to simulate oninput.
I decided to change my answer, based on how KnockoutJS accomplishes this. From this page in the Knockout docs:
"afterkeydown" - updates your view model as soon as the user begins typing a
character. This works by catching the browser’s keydown event and handling the event
asynchronously.
Of these options, "afterkeydown" is the best choice if you want to keep your view model
updated in real-time.
It accomplishes the asynchronous behavior by using setTimeout with a time value of zero. Other than that, it appears to be just like a regular keydown event handler.
Here's a simple example, using jQuery, which I believe behaves equivalently to Knockout's "afterkeydown" event:
$('#email').keydown(function() {
setTimeout( $.proxy(handler, this), 0);
});
function handler() {
console.log( this.value );
}
Note:
This will not catch right-click paste events and drag-and-drop events. If you want to update the text on those events too, simply listen for them in the same manner as keydown, e.g.:
$('#email').on('keydown paste drop', function() {
setTimeout( $.proxy(handler, this), 0);
});
Like keydown, paste and drop also need the setTimeout in order to update with the latest value of the text.
Original answer:
onkeyup is probably the way to go, but you raise a good point about it not firing if the element loses focus between keydown and keyup. Based on this answer, I'm pretty sure the solution would be to listen for the keyup event on a container element (or on the body, although in this case it would probably make the most sense to bind it to the <form> element).
As to CPU usage on paste, you could try canceling the event unless a certain amount of time has passed (say 50 ms)...hopefully that will be sufficient. If not, you could look at how some of the popular 2-way data-binding frameworks handle this...most of the ones I've seen use onkeyup.

Difference between typing and pasteing in a field

If I use xss, what's the difference between typing in ALERT('DSSA');, or just paste it to a search textfield? In a site, typing works, and makes the alert, but if I just paste it, than it doesn't. To prevent the question, I don't want to hack any site, I'm just interested in network security.
thanks for the answer
This will be because the programmer who built the website is lazy and hasn't listened for the onpaste event.
Typing fires the onkeydown, onkeypress and onkeyup events, and are the standard events to consider when watching for user input.
It would seem those are the only events the programmer has listened for (which makes this irrelevant of network security).
If this is not the case, then he'll be using two different event handlers for the events; one which escapes the input, and in the other he's forgotten.
I may not have understood the question properly.
Typing triggers keyUp, keyDown and keyPress events on the element. If the codes are programmed to capture them only, then only those events will be captured.
Pasting can be done using keyboards, mouse and browser options. So this depends on which events you are listening too. There is a separate event called onpaste which will ease everything.
What I mean is, lets say my code is written to capture the pasting my pressing "Ctrl" + "v" only, but if mouse and browser options are used to paste on the
element, then it is configured to capture mouse events also, it cannot
be captured.

Asking for undo/redo events in html/javascript

I have an interactive html5 canvas thing where sometimes users will want to undo their actions. I have the logic for doing that implemented, but I'm not sure of how to properly catch the "user wants to undo" event.
Currently, I just listen to keyboard events and interpret "CTRL+Z" as a request-to-undo, like this:
document.addEventListener("keydown", e => {
const Z_KEY = 90;
let isUndo = e.keyCode == Z_KEY && e.ctrlKey && !e.shiftKey;
if (isUndo) {
restore(revision.undo());
}
});
The problem is that the standard shortcut for undo-ing varies by OS, and there are totally orthogonal ways to trigger it (such as shaking your phone).
What I want is to somehow tell the browser that I'm supporting undo, and that it should forward all the crazy OS-specific ways of triggering undo to a method I specify. As things stand now, the browser has no idea the user is doing anything that would involve undo-ing. All the browser sees is a canvas being clicked on and drawn to.
Is there a standard way to ask the browser to catch all the undo events for me? In a future-proof way that keeps working even as vendors invent new undo actions? What about a hacky workaround? Or perhaps there's a library whose focus is to solve this particular problem?
Notes:
This question differs from How to handle undo/redo event in javascript?. That one is asking about catching changes to an element, whereas I always know about any changes because my code is the one performing those changes.
The question Listen to undo/redo event in contenteditable div is also about change-detection instead of implementing undo, and is limited to a particular type of element. I'm willing to use custom elements to make this work.
There's no standard javascript way of hooking things like undo/redo as there is no specific event for them.
Maybe Mousetrap does what you want. It's a library for abstracting keyboard events in javascript and includes a way to do a generic [system modifier]+key hotkey kind of thing.
That said, you'll probably need a button somewhere if you want mobile. (I'm not familiar with the shake-to-undo action. That seems like new age hippy nonsense. =P )

Categories