Copyright © 2013 W3C® (MIT, ERCIM, Keio), All Rights Reserved. W3C liability, trademark and document use rules apply.
IndieUI: Events 1.0 is an abstraction between physical, device-specific user interaction events and inferred user intent such as scrolling or changing values. This provides an intermediate layer between device- and modality-specific user interaction events, and the basic user interface functionality used by web applications. IndieUI: Events focuses on granular user interface interactions such as scrolling the view, canceling an action, changing the value of a user input widget, selecting a range, placing focus on an object, etc. Implementing platforms will combine modality-specific user input, user idiosyncratic heuristics to determine the specific corresponding Indie UI event, and send that to the web application in addition to the modality-specific input such as mouse or keyboard events, should applications wish to process it.
See the introduction for background and usage examples.
This section describes the status of this document at the time of its publication. Other documents may supersede this document. A list of current W3C publications and the latest revision of this technical report can be found in the W3C technical reports index at http://www.w3.org/TR/.
This is a First Public Working Draft by the IndieUI Working Group (IndieUI WG) of the Web Accessibility Initiative. The Independent User Interface Task Force has produced this document based on initial proposals and review of features critical to include for this first review opportunity. The task force has identified use cases and requirements to inform this draft, although not all requirements are yet addressed in this version. Open issues and actions are tracked in the IndieUI: Events tracker product. A history of changes to IndieUI: Events 1.0 is available.
The Independent User Interface Task Force is comprised of members of the IndieUI Working Group and the Web Events Working Group. The IndieUI Working Group charter specifies that this document is a joint deliverable with the Web Events Working Group. Since the time this charter was approved, the Web Events WG has become a maintenance-only group with its work items superceded by deliverables of the new Pointer Events Working Group. Therefore this document is now a publication solely of the IndieUI Working Group.
Feedback on this specification is essential to success of the technology. The IndieUI WG asks in particular:
To comment on this document, send email to public-indie-ui-comments@w3.org (comment archive). Comments should be made by 22 February 2013. In-progress updates to the document may be viewed in the publicly visible editors' draft.
Publication as a Working Draft does not imply endorsement by the W3C Membership. This is a draft document and may be updated, replaced or obsoleted by other documents at any time. It is inappropriate to cite this document as other than work in progress.
This document was produced by a group operating under the 5 February 2004 W3C Patent Policy. W3C maintains a public list of any patent disclosures made in connection with the deliverables of the group; that page also includes instructions for disclosing a patent. An individual who has actual knowledge of a patent which the individual believes contains Essential Claim(s) must disclose the information in accordance with section 6 of the W3C Patent Policy.
This section is non-normative.
This section is non-normative.
Scripting usable interfaces can be difficult, especially when one considers that user interface design patterns differ across software platforms, hardware, and locales, and that those interactions can be further customized based on personal preference. Individuals are accustomed to the way the interface works on their own system, and their preferred interface frequently differs from that of the web application author's preferred interface.
For example, web application authors, wishing to intercept a user's intent to 'undo' the last action, need to "listen" for all of the following events:
It would be simpler to listen for a single, normalized request to 'undo' the previous action.
In addition to the general user interface challenges, custom interfaces often don't take into account users who access web content via assistive technologies that use alternate forms of input such as screen readers, switch interfaces, or speech-based command and control interfaces.
For example, a web page author may script a custom interface to look like a slider (e.g. one styled to look like an HTML 'range' input) and behave like a slider when using standard mouse input, but there is no standard way for the value of the slider to be controlled programmatically, so the control may not be usable without a mouse or other pointer-based input.
This section is non-normative.
The primary goals of this specification are declared as the following:
This section is non-normative.
Decisions regarding which specific physical user interactions (keyboard combinations, gestures, speech, etc.) trigger IndieUI events are explicitly listed as out-of-scope in the Working Group charter. User interface is—and should be—defined and controlled by each operating system, rather than defined as part of any technical specification.
However, throughout this document are listed informative examples of certain keyboard and mouse events that may trigger each IndieUI event. There is no requirement for a user agent to implement these examples, and they are listed here purely to aid in clarifying the reader's conceptual understanding of each event, as well as illustrating certain UI differences between platforms. These informative examples will be limited to keyboard and mouse events, because those physical modalities have been common in software interaction for decades, and their use is familiar to most readers.
For example, it may be common for the ESC key to trigger a 'dismissrequest' event to close a dialog, but the specification does not require the user agent to use any particular physical event. It is an implementation detail, and left for the developers of each platform or assistive technology to determine whether ESC or some other interaction is the most appropriate way to trigger the 'dismissrequest' event. As long as there is a way to initiate each event, the user agent will be considered a conforming implementation.
This section is non-normative.
The following example uses a 'dismissrequest' event to close or cancel out of a modal application dialog.
<!-- Declare which IndieUI event(s) this element receives. --> <dialog ui-actions="dismiss" id="myDialog"> ... </dialog> <script type="text/javascript"> var myDialog = document.getElementById('myDialog'); // register the event at initialization // Option #1: On the receiver itself... (See next example for Option #2) myDialog.addEventListener('dismissrequest', dismissHandler); // at some point during runtime, the handler will be called // (e.g. if, for example, the user presses ESC key while focus is inside the dialog) function dismissHandler(e) { // cancel and close the dialog (don't forget to move focus before closing) closeDialog(e.receiver); // Event.receiver is a readonly property like Event.target // then cancel the event e.stopPropagation(); // stop the event from bubbling. e.preventDefault(); // let the UA/AT know the event was intercepted successfully. } </script>
The following example uses a 'valuechangerequest' event to modify the value of a custom ARIA slider.
<!-- Declare which IndieUI event(s) this element receives. --> <canvas ui-actions="valuechange" id="slider" role="slider" aria-valuemin="0" aria-valuemax="100" aria-valuenow="42"></canvas> <script type="text/javascript"> // register the event at initialization // Option #2: Using event delegation on any node (such as the body) that is higher in the DOM than the receiver element... document.body.addEventListener('valuechangerequest', valueChangeHandler); // at some point during runtime, the handler will be called function valueChangeHandler(e) { // Find the event receiver element var slider = e.receiver; // grab context info from the Event object var changeType = e.request.changeType; // todo: Event.request object yet to be defined // update the model and display myApp.requestValueChangeForElement(changeType, slider); // cancel the event e.stopPropagation(); // stop the event from bubbling e.preventDefault(); // let the UA/AT know the event was intercepted successfully } </script>
This section is non-normative.
One of the core principles behind UI Change Request Events is that they operate on a backwards-compatible, opt-in basis. In other words, the web application author has to first be aware of these events, then explicitly declare each event receiver and register an event listener, or user agents behave as they normally would.
Change request events do not cause any direct manipulation or mutation of the DOM, and do not have any 'default action' in the context of a web view. Instead, the event conveys the user's intent to the web application, and allows the web application to perform the appropriate action on behalf of the user, including making potential changes to the DOM. If a web application is authored to understand the change request event, it can cancel the event, which informs the user agent that the event has been captured and understood. If a web application does not cancel the event, the user agent may attempt fallback behavior or communicate to the user that the input has not been recognized.
User interface actions are declared as enumerated token attribute values on an element. Each value corresponds to a specific UI Request Event, and declares the web page author's ability to receive and handle each of the request events initiated by the user agent. In order to receive each request event, authors must also register for the event using Element.addEventListener()
at this node or higher in the DOM. User agents should not initiate a UI Request Event when the user's point-of-regard is not inside an element with the corresponding defined action.
uiActions
IDL AttributeThe uiActions
attribute of each instance of the Element interface must return a DOMString reflecting the ui-actions
content attribute.
partial interface Element {
attribute DOMString uiActions;
};
uiActions
of type DOMStringui-actions
content attribute.It may be more appropriate to name this receives/@receives than uiActions/@ui-actions.
ui-actions
Content AttributeEvery element may have a ui-actions
attribute specified, which is necessary to define the receiver of each type of request event. The attribute, if specified, must have a value that is a set of whitespace-separated tokens representing the various actions to which the web application responds on behalf of this element. The actions that an element has assigned to it consists of all the tokens returned when the value of the ui-actions
attribute is split on whitespace. (Duplicates are ignored.)
User agents must reflect the ui-actions
content attribute in the uiActions
IDL attribute.
<!-- body element is event listener for all events, but event receiver only for 'undo' actions. --> <body ui-actions="undo"> <!-- Element container for custom 'mapview' is the event receiver for 'pan' and 'zoom' actions. --> <div id="mapview" ui-actions="pan zoom"> ... </div> <!-- This Dialog is the event receiver for 'dismiss' actions initiated on any lower-level event target. --> <dialog ui-actions="dismiss"> ... </dialog> </body> <script type="text/javascript"> // registered all of these on the body as an example of event delegation to help illustrate the difference between event // target (document.activeElement or other point-of-regard), receiver (element with defined actions), and listener (body) document.body.addEventListener('dismissrequest', handleDismiss); document.body.addEventListener('panrequest', handlePan); document.body.addEventListener('undorequest', handleUndo); document.body.addEventListener('zoomrequest', handleZoom); </script>
In the previous example, the 'undorequest' event may be fired any time the user's point-of-regard was inside the document. However, the 'dismissrequest' would only be fired when the user's point-of-regard was inside the dialog. Likewise, the 'panrequest' and 'zoomrequest' would only be fired when the user's point-of-regard was inside the map view.
There is purposefully no request event for activating the default action. Authors are encouraged to use a standard click
event for default actions.
Event fires on point-of-regard (document.activeElement
, clicked element, or AT equivalent) if applicable, or otherwise document.body
.
Event order: These events should be asynchronous, but when used in conjunction with keyboard events, we need to define where each IndieUI event fires in the chain of keydown
, keyup
, and keypress
. Probably also need an identifier to associate each event with other related physical events: e.g. this dismissrequest
event is associated with the keyboard events keydown
, keyup
, and keypress
of the ESC key.
Separate interface from UIEvent because the @ui-actions attribute will 1) affect when and where these events are fired, and 2) adds the distinction of an event receiver element (element declaring the ui-actions attribute) in addition to the "target" element where the event initiates and the "listener" element where the event is registered for and handled.
[Constructor(DOMString typeArg, optional UIRequestEventInit dictUIRequestEventInit)]
interface UIRequestEvent : UIEvent {
readonly attribute EventTarget receiver;
};
receiver
of type EventTarget, readonlyui-actions
content attribute on an ancestor node of the event target. Note: This may need to be defined as a partial interface on AbstractView, rather than in this interface.
May also need a way to associate IndieUI events with their physical event counterparts.
[Example] partial interface UIEvent { readonly attribute EventID id; // UID of current event readonly attribute EventList relatedEvents; // List of related events, with ID and potentially type of each event. // e.g. This 'dismissrequest' event is associated with the previous 'keydown' and 'keyup' events. }
This might not need its own UIRequestEventInit, it could potentially use UIEventInit, depending on whether the EventTarget receiver is implemented here or on AbstractView.
dictionary UIRequestEventInit {
boolean bubbles = true;
boolean cancelable = true;
AbstractView? view = null;
long detail = 0;
};
UIRequestEventInit
Membersbubbles
of type boolean, defaulting to true
cancelable
of type boolean, defaulting to true
detail
of type long, defaulting to 0
view
of type AbstractView, nullable, defaulting to null
The different types of UIRequestEvents that can occur are:
undorequest
)Indicates the user desires to 'undo' the previous action.
May be superseded by the UndoManager interface.
Users, wanting to 'undo' a discrete action in a web application, can indicate their intent a number of ways, including pressing Control+Z on Windows or Linux, Command+Z on Mac OS X, and even by shaking some accelerometer- or gyroscope-enabled mobile devices.
redorequest
)Indicates the user desires to 'redo' the previously 'undone' action.
May be superseded by the UndoManager interface.
Users, wanting to 'redo' a discrete action in a web application, can indicate their intent a number of ways, including pressing Control+Shift+Z on Windows or Linux, Command+Shift+Z on Mac OS X.
expandrequest
)Indicates the user desires to to reveal information in a collapsed section (e.g. a disclosure widget) or branch node in a hierarchy (e.g., a tree view).
collapserequest
)Indicates the user desires to hide or collapse information in an expanded section (e.g. a disclosure widget) or branch node in a hierarchy (e.g., a tree view).
dismissrequest
)Indicates the user desires 'dismiss' the current view (e.g. canceling a dialog, or closing a popup menu).
Users, wanting to 'escape from' or 'dismiss' a web application state (for example, closing a modal dialog), can indicate their intent a number of ways, most commonly by pressing Escape on keyboard-controlled operating systems. Web authors who have registered for this event should process the event to determine whether to cancel the event. If the 'dismiss' action is understood in the context of the web application, web authors should perform the appropriate action (such as closing the dialog), and cancel the event using the event object's preventDefault()
method.
deleterequest
)Indicates the user wants to initiate a 'delete' action on the marked element or current view.
[Constructor(DOMString typeArg, optional UIManipulationRequestEventInit dictUIManipulationRequestEventInit)]
interface UIManipulationRequestEvent : UIRequestEvent
{
};
dictionary UIManipulationRequestEventInit {
boolean bubbles = false;
boolean cancelable = false;
AbstractView? view = null;
long detail = 0;
optional double originX = 0.0;
optional double originY = 0.0;
optional double deltaX = 0.0;
optional double deltaY = 0.0;
optional double scaleFactor = 1.0;
optional double rotation = 0.0;
};
UIManipulationRequestEventInit
Membersbubbles
of type boolean, defaulting to false
cancelable
of type boolean, defaulting to false
deltaX
of type optional double, defaulting to 0.0
deltaY
of type optional double, defaulting to 0.0
detail
of type long, defaulting to 0
originX
of type optional double, defaulting to 0.0
originY
of type optional double, defaulting to 0.0
rotation
of type optional double, defaulting to 0.0
scaleFactor
of type optional double, defaulting to 1.0
view
of type AbstractView, nullable, defaulting to null
Move, Pan, and Scroll request events are functionally identical, but are specified individually to aid in authoring clarity when using similar concepts like 1) moving an object on a layout canvas, 2) panning a continuous view like a map, and 3) scrolling a scroll view.
The types of UIManipulationRequestEvents that can occur are:
moverequest
)Initiated when the user agent sends a move request to the web application with accompanying x/y delta values. This is used, for example, when moving an object to a new location on a layout canvas.
deltaX
, deltaY
panrequest
)Initiated when the user agent sends a pan request to the web application with accompanying x/y delta values. This is used, for example, when changing the center point while panning a map or another custom image viewer.
deltaX
, deltaY
rotationrequest
)Initiated when the user agent sends a rotation request to the web application with accompanying origin x/y values and a rotation value in degrees.
originX
, originY
, rotation
scrollrequest
)Initiated when the user agent sends a scroll request to the web application with accompanying x/y delta values.
Need to specify algorithm for determining x/y deltas for events like pagedown/pageup. Should probably be max of receiver element width/height, or user agent viewport width/height (delta if overlapped inexactly), with potential for a smaller assistive technology viewport (e.g. if screen zoom does not show entirety of previous calculation's width/height).
deltaX
, deltaY
zoomrequest
)Initiated when the user agent sends a zoom request to the web application with accompanying origin x/y values and the zoom scale factor.
originX
, originY
, scaleFactor
There may be a need for a combined, continuous manipulation events (e.g. Pan+Zoom simultaneously) in addition to the discrete events listed above, but specification ideas are incomplete. Currently an author could achieve the same result by listening for the series of discrete Zoom and Pan events.
[Constructor(DOMString typeArg, optional UIValueChangeRequestEventInit dictUIValueChangeRequestEventInit)]
interface UIValueChangeRequestEvent : UIRequestEvent
{
const unsigned short INCREMENT = 1;
const unsigned short INCREMENT_SMALL = 2;
const unsigned short INCREMENT_LARGE = 3;
const unsigned short INCREMENT_MAX = 4;
const unsigned short DECREMENT = 5;
const unsigned short DECREMENT_SMALL = 6;
const unsigned short DECREMENT_LARGE = 7;
const unsigned short DECREMENT_MIN = 8;
};
DECREMENT
of type unsigned shortDECREMENT_LARGE
of type unsigned shortDECREMENT_MIN
of type unsigned shortDECREMENT_SMALL
of type unsigned shortINCREMENT
of type unsigned shortINCREMENT_LARGE
of type unsigned shortINCREMENT_MAX
of type unsigned shortINCREMENT_SMALL
of type unsigned shortdictionary UIValueChangeRequestEventInit {
boolean bubbles = false;
boolean cancelable = false;
AbstractView? view = null;
long detail = 0;
unsigned short? changeType = null;
};
UIValueChangeRequestEventInit
Membersbubbles
of type boolean, defaulting to false
cancelable
of type boolean, defaulting to false
changeType
of type unsigned short, nullable, defaulting to null
detail
of type long, defaulting to 0
view
of type AbstractView, nullable, defaulting to null
The single type of UIValueChangeRequestEvent that can occur is:
valuechangerequest
)Initiated when the user agent sends a value change request to the web application. Used on custom range controls like sliders, carousels, etc.
Web authors must code applications to accept all values of the changeType
attribute. For example, if there is no special behavior for INCREMENT_SMALL
or INCREMENT_LARGE
, web applications would behave as if they had received a basic INCREMENT
change type.
changeType
Users, wanting to change the value of a custom range widget (e.g. sliders or carousels) in a web application, can indicate their intent a number of ways, including pressing various keys (Up, Down, Left, Right, PageUp, PageDown, Home, End) on most keyboard-controlled interfaces. User agents understanding this intent should initiate a valuechangerequest
event. Web authors who have registered for this event, should process the event to determine whether to cancel the event. If the value change action is understood in the context of the web application, web authors should change the value of the associated widget by an amount determined via the changeType
argument, and cancel the event using the event object's preventDefault()
method.
TBD
TBD. Will be defined in conjunction with markrequest, which is covered by ACTION-25, and not yet in the spec.
UIRequestEvents initiate from the element representing the point-of-regard, and are referenced in the Event object's target
property.
For mainstream user agents, the point-of-regard will likely be the element under a pointer (e.g. mouse cursor) or, in the case of keyboard events, the currently focused element (e.g. document.activeElement). Assistive technologies or other alternative inputs may determine another element to be the subject of the user's attention, and initiate events from this new point-of-regard.
Attributes whose DOM property and content attribute values remain in sync. Identical to reflected attributes in HTML.
The closest DOM ancestor to the user's point-of-regard that declares the current event type via the @ui-actions content attribute or uiActions DOM attribute. The Request Event Receiver is referenced in the Event object's receiver
property.
UI Request Events are not initiated by the user agent unless the following are true:
@ui-actions
element.addEventListener()
Some of this definition will need to be massaged and move into the normative sections above defining @ui-actions.
TBD
At the time of publishing, the following individuals were active, participating members of the IndieUI Working Group.