(part 4) when scratching an itch becomes a stupid timesink

This is part 4 of a post about how adding a keyboard short-cut for the equation editor in google docs turned in to a week long mission into foreign lands such as google closure, chrome extension API, XPCwrappers and even a bit of C++ 

(Or: Cowboy coding at its most best.)

So I was quite pleased with myself to write a little function that hooked the "$" character "keydown" KeyboardEvent and either set a global variable that was good for 1 second, or inserted an equation widget. It worked almost first time which is rare for my Javascript efforts.

I was happy for the keyboard event to bubble on the first $, because its possibly a non-equation insert event so the $ is important in the text, however on the second dollar, if I trip my switch, then I want to block the bubble of the event because it should be replaced with the equation editor widget and not a dollar character. All well and good. However what to do with the first $ character.

Basically once you have kicked off the equation editor widget, the first KeyboardEvent containing the dollar has bubbled, and completed, gone out of the scope and been garbage collected, so there is no going back on that dollar using the event. At least not in an obviously sensible way.

So the immediate solution that sprung to mind was to delete the first dollar before inserting the equation editor widget. Fantastic, there is loads of code on the web with examples of dispatching events, and I know that I can dispatch mouse events from my previous discoveries, so code something to send a "back space", which is Ascii code 8.

Cue more fucking pointless annoyance, because it turns out there is a bug in chrome's KeyboardEvent event object, in that you cannot set keyCode values directly on it, but that is the value that is important when sending keystrokes.

Its actually mentioned in the source code, so mercifully it didn't take too long to see the problem. Particularly because Chrome's developer tools are really really good in this respect.

After trying a few ways to send a delete keystroke using a "textInput" UIEvent I decided to deploy a hack that any seasoned cowboy programmer would be proud of.

I decided to catch a previous back-space KeyboardEvent and store it in a global variable, and re-dispatch the event to my chosen target at a later time.

There were a number of possible problems with this, such that certain non-editable fields or states could be set on the "used" event, which would make it useless for re-dispatch.

However it turned out not to be a problem, and this hack worked fine, (as long as the user has pressed the delete key at least once since the event handler was registered)

Looking at a other google docs user scripts, it seems possible to make changes to the text using the text selection capabilities of the DOM, and this would probably work better. However I was well pleased with my hack-around so for the moment its staying in.

I had preferred the use of keyboard events, rather than direct DOM mutation, because previously docs crashed in a nasty way, if I had directly tried to add or change contents of divs, so I was disinclined. Also the app has no way to know whether the programmatic events are real or fake, however they can detect code re-jiggery more easily.

Anyway, all this stuff meant the code was really quite chrome specific, so the final user script is chrome only. I have published the current version on userscripts.org as version 0.1, if any wants to see the code that resulted from these investigations.

I also ended up with a chrome extension that allows on-the-fly replacement of included files, which might be of some use to someone somewhere, if only as a working example of the use of some of the chrome.experimental.webRequest API features.

That is not yet in a fit state, but I will publish a post with the link when available.

No comments:

Post a Comment

Don't be nasty. Being rude is fine.