User Interface Adaptation and User Preferences
What is UI Adaptation?
The goal of UI adaptation is two-fold:
- To build a degree of flexibility into Web-based user interfaces so they can better accommodate the diverse needs of users under differing circumstances and contexts
- to make it easier for Web developers to make UIs accessible from the start, and harder to cut corners or bolt on "one-size fits all" solutions.
We envision a UI framework that leverages good code design techniques, markup and styling practices, and dependency injection in order to minimize the built-in expectations about how a user interface is presented and controlled that tend to make them brittle, less reusable, and hard to configure.
Fluid's UI adaptation layer will allow users to configure certain preferences up-front, using an embeddable preferences editor component, and also to adjust these preferences on-the-fly when needed.
How Will Fluid User Interfaces be Flexible?
The Fluid framework will allow three main aspects of the user interface to be varied based on context or preference:
- Layout, sizing, and presentation: leveraging Web standards such as HTML and CSS, and providing easy ways deliver alternatives as needed
- Navigation: using simple, embedded microformats, the framework will generate alternative ways to navigate within an application
- Control: customize keyboard controls, accelerators, and tabbing schemes by injecting alternative JavaScript handlers
Rather than a wholesale swapping of Fluid components, we're planning to leverage existing Web technologies that foster separation of structure from presentation, and augmenting those with a more effective means for delivering variations on the presentation and control bindings at runtime. Simply put, Fluid will use the strengths of HTML and CSS to deliver modified presentations and behaviour for our components based on user preferences.
Categories of Adaptation
Flexible Layout and Linearization
- Expandable spacing, sizing, fonts, layouts
- Flattening multiple columns into a single column
- Expanding and collapsing views
Enhanced Navigation
- Site maps, summaries, breadcrumbs to allow quicker navigation and understanding of a site's structure
- Graphic cues, highlights, structural markers
Control
- Keyboard remapping to avoid conflicts with other components, browser, assistive technology
- Alternate tabbing behaviour: quick vs. comprehensive
Metadata and Preferences
Metadata
Markup Metadata:
Markup metadata defines characteristics within an HTML document:
- columns
- exandability/collapsibility & current state
- primary content vs. navigation vs. informational vs. error
- landmarks/areas of interest
- declared keyboard mappings (action + modifier + keys)
- enabled/disabled
Some of this material is already available in ARIA, others will need to be defined.
UI Semantics:
User interface semantics provide agreed-upon names for aspects of user interfaces:
- familar operations (cut, copy, paste, etc.)
Template Metadata
Template metadata defines an alternative stylesheet or fragment of HTML's affect on the markup, directly corresponding to the markup metadata and user preferences fields.
User Preferences
- Fine grained typographical requirements that take into account document structure
- Preferred UI density (eg. collapse all by default)
- Navigation enhancements
- Keyboard mapping overrides
Architecture
Composition = Flexibility & Reusability
Fluid components are built out of smaller, encapsulated units that are injected in as parameters. Not only might you combine several smaller components into a larger one, but individual components themselves are composed of logical units that can be substituted or extended during development or at runtime based on user preferences.
For example, a typical component will provide a set of configurable properties that can be modified to change the behaviour of the component. Layout managers, keyboard handlers, and connections to the server are parameterized so that alternative strategies can be plugged in. This compositional approach provides the underlying model for both reuse across contexts and accessibility personalization.
Server-side presentation frameworks will need to be extended to more easily deliver alternative stylesheets or fragments of HTML based on checking the user's stated preferences. Alternatively, this could done on the client side in JavaScript, albeit less efficiently.
The Fluid framework will include a simple inversion of control (IoC) container that will be responsible for injecting components with their required dependencies. Decisions about which depenency implementations will be injected could be performed at run time based on:
- The browser and platform being used
- Information about the device capabilities
- User preferences
- Configuration specified when the application is initially deployed
A Declarative Approach
The use of an IoC container will foster a more declarative approach to building user interfaces, allowing developers to wire up behaviour and declare bindings in a way that can be overridden by the user or implementor. The key to this is offloading the types of programmatic logic that is most susceptible to the risk of hard-coding to the framework. For example, keyboard handlers:
Example 1: Typical barebones JavaScript approach. In this example, keyboard bindings are hard-coded into the handler function, making them hard to modify.
function handleCutKeyPress () { $ (element).keydown (function (event) { if (event.which === fluid.keys.C && event.ctrlKey === true) { copyFunction (); } }); }
Example 2: Framework-managed key bindings. In this example, the keyboard bindings have been externalized and the framework is responsible for generating the appropriate handlers, calling client code when needed.
var keymap = { modifier: CTRL, key: C }; $ (element).bindActionToKey ("Copy", keymap, copyFunction);
Example 3: Declarative dependency injection. In this example, keyboard handlers are defined in an entirely declarative manner. Functionality is "wired up" by injecting keyboard maps and their associated logic into the component. While this JSON syntax is more verbose than the previous example, it contains no code, and thus other wirings can be more easily substituted to reconfigure the component. This approach is also significantly lighter-weight than parsing XML data.
beans { textEditorComponent: { bindings: { keyMaps: windows actions: actionBindings } }, windows: { Copy: { modifier: CTRL, key: C } }, mac: { Copy: { modifier: Command, key: C } }, actionBindings: { Copy: myObject.copyFunction } }