-
Notifications
You must be signed in to change notification settings - Fork 0
Keyboard and Clipboard Events
The quick-and-dirty: event bubbling is faked in the math DOM, keypress
remembers the last keydown
event and does setTimeout
to check textarea contents
Getting keyboard events to work for normal and special keys, for both a tap and holding down, is stupidly hard. According to this excellent resource, the main hurdles that affect this project are as follows:
- In most browsers,
- it's only possible to reliably tell special keys (like arrow keys, backspace, tab etc) apart from text entry with the
keydown
event object- e.g. on
keypress
the keycodes for the left, up, right and down arrow keys are identical to that of%
,&
,'
and(
, respectively
- e.g. on
- but it's only possible to reliably tell what character was typed on
keypress
- in fact even the jQuery-normalized
event.which
onkeypress
is unreliable, for example on the French keyboard the backslash\
(crucial to MathQuill) is typed with Ctrl+Alt+8, which for all a web app can tell is a browser or OS shortcut #11 - we ended up waiting after
keypress
and seeing what text was entered into the textarea
- in fact even the jQuery-normalized
- it's only possible to reliably tell special keys (like arrow keys, backspace, tab etc) apart from text entry with the
- Unfortunately,
- some browsers, for special keys, only fire
keydown
- some browsers, when you hold down a key, only repeatedly fire
keypress
- some browsers, for special keys, only fire
We provide an abstraction that is cross-browser but doesn't use browser-sniffing to hide these inconsistencies from "higher-level" handlers on math DOM nodes that actually deal with text entry and backspaces and stuff.
Our cross-browser algorithm is to record keydown
events and on keypress
, if there's been no keydown
since the last keypress
of the same kind, replay the recorded one. That way special keys can be handled on keydown
without worry that it doesn't fire repeatedly when you hold down special keys. Text entry is handled by checking the contents of the textarea after keypress
, so there are separate higher-level math DOM event handlers for keydown
and textInput
.
- The actual event handlers bound to the jQuery object (and hence, the HTML DOM element) of the root math element share a closured
lastKeydn
object.- on
keydown
, store the event object and set the flag before triggeringkeydown
in the math DOM - on
keypress
, check the flag and if there's been nokeydown
since the lastkeypress
, triggerkeydown
in the math DOM- now
setTimeout(textInput)
to wait after thekeypress
event has been handled by the browser to see if text has been entered into the textarea, and if so triggertextInput
in the math DOM
- now
- on
- The
.keydown()
and.textInput()
event handlers inherited by all MathElements fromMathElement.prototype
just tail call the parent'skeydown
/textInput
handler (Note: In the new architecture, instead of explicitly tail calling the parent's event handler, events are bubbled by the event triggerer and to cancel bubbling, the event handler explicitly returnsfalse
)- The root math block overrides its
keydown
andkeypress
event handlers to call the cursor's various.write()
and.backspace()
etc methods - Since the event bubbles up starting from the cursor's parent,
MathElement
s likeLatexCommandInput
can override theirkeydown
andtextInput
event handlers to do stuff when the cursor is in them and the user types something- Such
MathElement
key event handlers that don't want to cancel the bubbling of the event are required to explicitly fake the bubbling by calling the key event handlers of their parent MathElement- They can cancel the bubbling of the event by simply not calling their parent's event handlers
- We want the same events to bubble out of the math textboxes as would bubble out of a normal textarea, so we never return false or stop propagation on any of the textarea events, but we often want to prevent the default action, so the
.keydown()
event handler can return false to prevent default. Like normal event handlers, returning other falsy values does not work, it has to=== false
- Such
- The root math block overrides its
Tested (and confirmed working) on Mac for Safari 4, 5, Opera 10.5, Chrome 5+, Camino 2, Firefox 3.6, 4, even OmniWeb 5.
Tested (and confirmed working) on Windows for IE8.