Still stinging from last night's defeat, I try to pick up the broken pieces of my soul tonight.
I mean, how cool would it have been to get custom keyboard events working in Dart on the 900th day of the current chain? Having dutifully file the requisite bug, I move on tonight to see what I can salvage from last night's effort.
I start by pulling down the latest Dart DSK (Dart VM version: 0.1.2.0_r28552 (Fri Oct 11 14:06:31 2013) on "linux_x64") from the continuous build archive. The first two listeners in the following still generate errors:
import 'dart:html'; main(){ var subscription = KeyboardEventStream.onKeyDown(document.body).listen( (e) => print('KeyboardEventStream listener')); var subscription2 = KeyEvent.keyDownEvent.forTarget(document.body).listen( (e) => print('KeyEvent listener')); var subscription3 = document.body.onKeyDown.listen( (e) => print('regular listener')); }Only
subscription3
from the document.body.onDown
stream give me results when I hit a key:regular listenerThe other two spew multiple Dartium errors:
Exception: InvalidStateError: Internal Dartium Exception undefinedAs far as I can tell, the first two streams (from
KeyboardEventStream
and KeyEvent
) are both useless in user-facing code. Even if I run the unit tests for the new KeyEvent
in Dartium, hitting any key after running the test generates oodles of Internal Dartium Exceptions. But maybe the onKeyDown
can be of some use?Well, no. The
onKeyDown
property is a _ElementEventStreamImpl
. Sadly that is not a subclass of the new CustomStream
and therefore does not support the add()
method for dispatching events:Exception: Class '_ElementEventStreamImpl' has no instance method 'add'. NoSuchMethodError : method not found: 'add' Receiver: Instance of '_ElementEventStreamImpl@0x3918afae' Arguments: [Instance of 'KeyEvent']Bummer. I suppose this is the purpose of the
KeyboardEventStream
and KeyEvent
wrappers. But still… bummer.Well, it seems that I remain at a dead-end in ICE Code Editor—at least until my bug is addressed. I can write testable code that crashes the browser or non-testable code because the working property does not support dispatching events. In my mind, testing trumps runnable code. At some point the testable code will work—and maybe it already does when compiled to JavaScript.
Even this proves difficult. Consider if I stick with the
KeyEvent
class and listen for keydown events: var subscription2 = KeyEvent.keyDownEvent.forTarget(document.body).listen(
(e) => print('KeyEvent listener'));
// Trigger / listen for event on document.body
var streamDown = KeyEvent.keyDownEvent.forTarget(document.body);
var subscription4 = streamDown.listen(
(e) => print('streamDown listener ${e.keyCode}'));
streamDown.add(new KeyEvent('keydown', keyCode: 4, charCode: 0));
// Trigger / listen for event on the H1
var h1Down = KeyEvent.keyDownEvent.forTarget(query('h1'));
var subscription5 = h1Down.listen(
(e) => print('h1Down listener ${e.keyCode}'));
h1Down.add(new KeyEvent('keydown', keyCode: 5, charCode: 0));
Both subscription2
and subscription4
listen for keydown events on document.body
. When I add a new keydown KeyEvent
to the stream from the second group, I expect to see both event listeners fire. But it turns out that I am adding the KeyEvent
to the second stream and only the second stream. I am not generating an event that will be seen by all listeners on document.body
—only an event that will be seen by that second stream. Worse, when I add an event to the keydown stream of an <h1>
, it is again only to the <h1>
tag's stream and it does not bubble up. I expect the above code to trigger both the
document.body
listeners twice—both should see the custom keyboard event on document.body
and both should see the <h1>
event bubble. But I only see the direct events:streamDown listener 4 undefined:1 h1Down listener 5This is of very limited use for me. For instance, if I want to test that a keydown in the ICE project filter shows all the projects that start with “a” I need access to the
KeyEvent
stream that actually listens to the corresponding text field. For that to work, I would need to expose the filter stream (and every other stream) in the ICE code as a public property. There is no way I am doing that just to support testing.Bother.
As depressing as all of that is, hope is not completely lost. I do believe that the keyboard shortcut code ought to be somewhat testable. Given what I learned today, I doubt that I will be able to add a custom
KeyEvent
for Ctrl+O
to a stream in ICE to test that the open dialog appears. Still, I think the keyboard shortcut library itself ought to be testable. And perhaps I can expose some high-level testing methods from that same package to support limited keyboard testing in ICE. Something for tomorrow. Hope. Day #901
Thank you that Ctrl-alt-foo is finally working again. Just yesterday I found a very odd bug, and I am not sure if you can reproduce it..
ReplyDeleteOn Ctrl-S and Meta-S I do a save operation of the currently open file.
When I hit Ctrl-S it does exactly what it should and the POST HttpRequest works, but when I use Meta-S the save-dialog of dartium opens and the HttpRequest fails (which I think is probably the oddest part about it). Interestingly Meta-S did work before..
If I insert a break point, the open dialog still appears, but after continuing the HttpRequest also works with Meta-S. It appears that there is some kind of race condition when Meta is pressed.
There are some keyboard shortcuts that the browser just won't let though: http://japhr.blogspot.com/2013/08/osx-keyboard-shortcuts-with-dart.html. Is it possible Meta-S is one of them on your platform?
DeleteI tested it with your keyboard event tester, this is the output: https://www.dropbox.com/s/3jl7ixovmf90qcd/KeyTest.tiff
DeleteAs I said, it did work in Dartium before ctrl-alt-foo broke and I reported the bug. Nonetheless, in google mail Meta-S does not open a dialog, so it appears to be possible.
Chris, any update on this? I just updated to Dart 1.0 and my reactive keyboard library is completely kaput. Sigh.
ReplyDeleteSadly, it's still completely broken. I've resorted to this kind of awful hackery: http://japhr.blogspot.com/2013/11/giving-up-on-keyevents-until-after-dart.html
DeleteThe two bugs that need to be addressed are:
* https://code.google.com/p/dart/issues/detail?id=13902
* https://code.google.com/p/dart/issues/detail?id=14044
There hasn't been any recent activity on them, but hopefully that'll change now that the 1.0 dust is settling.
Thanks for the update. I just updated my library to support Dart v1.0: https://github.com/cajurabi/reactive_keyboard
DeleteI haven't pushed it to pub yet due to the lack of proper docs and tests.
> I haven't pushed it to pub yet due to the lack of proper docs and tests.
DeleteThat never stopped me before! :D