Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Respond immediately to textarea changes in Dart

I've got this in my html file:

<textarea id="inputbox" placeholder="type here"></textarea>

What's the correct way to wire up a handler that will fire immediately whenever the content of the textarea changes? (whether by keyboard, mouse/clipboard, speech input, brainwave reader, etc)

I tried:

  query("#inputbox").on.change.add(handler)

but (at least on Dartium) it only fires after you tab out of the field.

The purpose is to update a "live preview" window, similar to the way Stackoverflow renders Markdown output while you type.

like image 367
rkagerer Avatar asked Jan 21 '13 06:01

rkagerer


2 Answers

This is the best I came up with so far. I'd be happy to hear if anyone knows of a more compact or preferable alternative.

Edit: Code snippet updated to the new pattern for event registration.

import 'dart:html';

void main() {
  query("#inputbox")
    ..onChange.listen(handler)
    ..onKeyDown.listen(handler)
    ..onKeyUp.listen(handler)
    ..onCut.listen(handler)
    ..onPaste.listen(handler);
}

void handler(Event event) {
  print((query("#inputbox") as TextAreaElement).value);
}

The precise behavior will vary between browsers and operating systems.

You could skip keyDown, but be aware keyDown and keyUp behavior is influenced by the OS and isn't guaranteed to be symmetric. You might conceivably miss a change, at least until the next keyUp or change event gets fired. Indeed I proved this out by creating a little app on Windows 7 to send an orphan WM_KEYDOWN message to Dartium and IE9.

keyPress could be used instead of keyUp and keyDown, but won't generate events for certain keys like backspace and delete.

cut and paste react immediately to a cut or paste performed with the mouse. If you don't use them, the change event will capture the change, but not until after the field loses focus, or sometimes even later.

The input event could replace all listeners above and seems to work great in Dartium, but under IE9 it only captures character additions, not removals.

Note keyUp and keyDown may generate additional unwanted events for cursor keys, home, end, shift, etc. (e.g. In IE9). It will fire in addition to the cut/paste listeners when the user uses shortcut keys for those actions.

While the question is specific to Dart, a lot of the discussion above applies to any code listening to the DOM. Even keyCode values aren't standardized across browsers (more detail).

It may also be worthwhile checking out the KeyboardEventController class, though by and large when I tested it the edge case behavior was similar to that noted above. That may or may not be by design. The Dart developers do make some effort to insulate you from cross-browser inconsistencies, but it's still a work in progress.

Also while we're talking about textarea, remember to use its value property, not its text property. Finally, be sure your handler throttles its reactions to "bursts" of keyboard activity (e.g. some sort of timer that briefly defers the guts of your handler and rolls up any additional events which occur in the meantime).

Related questions and links:

  • Handle events in DART
  • Handling Keyboard events in Dart Language
  • How do you listen for a keyUp event in Dart?
  • Cross browser key event handler in Dart
  • jQuery example that skips keyboard events and binds to propertychange
like image 69
rkagerer Avatar answered Nov 15 '22 11:11

rkagerer


Its not clear if you are using polymer or not, but if you are, you can subscribe to a change to a variable annotated with @observable by creating a function in the polymer element in the form as [variable name]Changed(oldvalue). I originally found this here: How to subscribe to change of an observable field

like image 41
davesdig Avatar answered Nov 15 '22 10:11

davesdig