Wednesday, January 13th, 2010

Virtual DOM Events

Category: JavaScript

virtualdomevents

I am a big fan of using custom events where it makes sense in applications. I took it too far in the early days of Bespin, but I really enjoy them where they make sense.

Chris Vanrensburg was talking to me about Virtual DOM events, and when I asked him about them he told me this:

there are not enough juicy real DOM events, and the DOM standards process is slow moving. It’s long been a bone of contention that the mouseover and mouseout DOM events will fire for a node for which a handler is wired – even when the user mouses around inside the node and is mousing over and mousing out of child nodes. Internet Explorer was a pioneer in supporting the onmouseenter and onmouseleave events, and mouseenter and mouseleave are part of the DOM Level 3 events spec. Until browsers universally support these incredibly useful events, various frameworks abstract them into existence via their event wiring methods. This is a most basic case of frameworks presenting virtual DOM events as real DOM events to an application developer. In this case, of course, the events in question are likely to become real DOM events for all browsers.

However, another interesting case is a mouse rest type of event. Requiring a node to remain in a specific event state for a set amount of time before firing an event is a helpful indicator of the user being truly interested in something (as opposed to just “wandering through”). Consider the classic case of the user mousing over a node and then resting the mouse for a certain period of time over that node. You might like to know if the user does this for a specific node, because this may be an indication that the user is interested in what clicking the node might do, and one may wish to present them with a helpful tooltip that is implemented using HTML and that provides them more information about what they’re considering clicking on.

In such cases, you probably don’t want to trigger the display of an elaborate info tooltip based merely upon the user mousing over the node, since this may hamper the page’s performance – especially if displaying the tooltip requires an Ajax request – and displaying and hiding chunky tooltips as the user moves the mouse across the page may be a dreadful user experience, in any event. In such cases, it would be really nice to have an event that fires only when the user has actually stopped the mouse over a node. Back in August of 2008, a mouserest event was added to UIZE. This event accepts a duration parameter, to let you tune how long the user needs to keep the mouse rested over the node before the event is fired. Problem is, this was just one special-cased virtual event that was hacked deep into the event abstraction code.

The interesting leap that was made recently was to codify this pattern and create a formal construct in the framework of a virtual DOM event, with an extensibility foundation to allow modules to define new sets of these virtual DOM events. This opens up all sorts of possibilities for implementing more complex interaction logic and expressing patterns of user interaction using the event paradigm, and allowing the application developer to think of these interactions as events, just like any other events. Some of the more sophisticated kinds of user interactions that could be expressed using the event paradigm wander into the territory of gestures. For example, one might implement virtual DOM events such as “shake”, “flick”, “whack”, “crossOut”, etc. A “shake” gesture may involve clicking on a node, holding down the mouse key, and then vigorously moving the mouse back and forth. A “flick” gesture may involve clicking on a node, holding down the mouse key, rapidly moving the mouse in one direction, and then quickly releasing the mouse button before the motion is completed. A “whack” gesture may involve rapidly moving the mouse over a node at one edge, and then rapidly moving the mouse in the opposite direction and out of the node, as if to whack it on one of its edges in order to budge it. A “crossOut” gesture may involve moving the mouse diagonally from top right to bottom left, and then from top left to bottom right, without too much of a pause between the two diagonal motions, as if to gesture that an object should be removed.

To get the ball rolling, I implemented some of the more basic kinds of virtual DOM events, such as parameterized remain-in-state events like mouseRemainDown, keyRemainDown, remainFocused, etc. Also, I created some click-with-modifier-key dedicated events. These can all be previewed here…

Then, as part of my further exploration of this construct, I implemented a suite of edge virtual DOM events, such as mouseEnterLeft, mouseEnterTop, mouseExitLeft, mouseExitRight, etc. These can be seen in action here…

I’m quite excited by the potential of this construct to provide a way to encapsulate wiring logic for more sophisticated user interactions with DOM nodes, and provide a model for re-usability of such logic, which often otherwise spills out into the application code and doesn’t have a good place that it can call home.

What do you think about the idea? Would you like to see events like this?

Posted by Dion Almaer at 6:44 am
12 Comments

++++-
4 rating from 33 votes

12 Comments »

Comments feed TrackBack URI

Love it

Comment by V1 — January 13, 2010

Could a jQuery plugin be used to implement this kind of behavior cross-browser?

Comment by stompyj — January 13, 2010

mouseRemainUp, mouseRemainOut, keyRemainUp, remainBlurred

Are totally seems (IMHO) totally useless. Theses are “non-events” that are very likely to be trigered.

Comment by ywg — January 13, 2010

“I took it too far in the early days of Bespin” — I’d be interested in hearing more details on that…

Comment by zellyn — January 13, 2010

@ywg – Haven’t you read the descriptions in the picture? They’re all very specific events, not just a generic “Nothing happened” events.

Comment by Skilldrick — January 13, 2010

It seems to me like most events are timer driven. Start a timer when a certain event occurs, when some counter event doesn’t occur within the timer’s life span, call callback. Otherwise cancel timer.

Wouldn’t call them really usefull (but one might have their own reasons for using them). If you do need them they wouldn’t be really difficult to implement though…

Comment by qFox — January 13, 2010

@ywg
 
Knowing when the user is truly done with interacting with an element, in situations where a mouseout or keyup might be a false / premature trigger, could be useful in some instances. For example, if you provided some kind of extra UI while a user is typing in an input field, you might like to change the state of that UI if the user ceases typing or pauses for sufficient time, even if the field remains focused.
 
Similarly, with a button that is expected to be clicked in a repeated fashion in an interaction, the mouse remaining up for long enough could be used as an indication that the user is no longer engaged in the repeated clicking interaction (whatever that is), even if they are still moused over the button.
 
In any event (no pun intended), since the maker functions for these virtual DOM events are themselves manufactured using a function, adding these events came at a very low price.
 
I agree, though, that there are more obvious applications for the positive remain-in-state events, such as mouseRemainOver, mouseRemainDown, keyRemainDown, etc.
 
Anyway, thanks for the feedback. All feedback is always welcome.

Comment by uize — January 13, 2010

@stompyj
 
Certainly your question is of a rhetorical nature. Naturally, any framework can be used to do anything that any other framework can do. Similarly, UIZE can be used to do anything that jQuery can do, but I digress ;-)
 
The virtual DOM event is a construct, which provides a way to express wiring logic for more sophisticated user interactions in a reusable way. I think (but don’t quote me on it) this goes a little further than the notion of a custom event that requires application logic to fire it. Encapsulation of the wiring and firing logic into the construct of a virtual DOM event allows it to be more easily reused. And, really, I think the crux of the biscuit is finding where such code should go, in order for it to be conveniently reused.
 
I think the other leap here is the parameterization of events. In other words, I’d like to wire a handler not just for when a key is pressed, but specifically for when ctrl-c is pressed. You could implement a virtual DOM event for keypress that accepts the key as a parameter for the event. This turns the tables a bit, because normally you’d be writing switch logic inside a generic keypress event handler. It’s a little bit of a paradigm shift.

Comment by uize — January 13, 2010

@uize

I’m not really convinced we have real use cases here. But I understand that you may want to implement theses event to have an orthogonal / consistant API.

The other ones are quite handy. Good work !

Comment by ywg — January 13, 2010

This is a concept that we’re supporting in YUI 3. Not only are (what we call) synthetic events helpful to normalize xbrowser implementation issues of existing events (e.g. bubbling focus/blur or mouseenter/leave), but are great for encapsulation of common user behavior patterns. And in the end, you end up with very readable code.

input.on(‘typing-pause’, verify);
or
thingy.on(‘click-and-hold’, doSomething, { duration: 1000 });

Comment by lsn — January 13, 2010

@uize

To add to lsn’s comment a bit, YUI3 also implements “a virtual DOM event for keypress that accepts the key as a parameter for the event”:

http://developer.yahoo.com/yui/3/event/#keylistener

It supports combinations and modifiers as well.

@lsn

Is there any documentation on YUI3’s synthetic events? Thanks.

Comment by jlizarraga — January 13, 2010

@jlizarraga
Documentation is thin now while we make the API for creating them more developer friendly. Expect docs in the 3.1 release.

Comment by lsn — January 14, 2010

Leave a comment

You must be logged in to post a comment.