Skip to content

Spotlight package for Moonstone project

Notifications You must be signed in to change notification settings

enyojs/spotlight

Repository files navigation

SPOTLIGHT DOCUMENTATION

  1. What Is Spotlight?
  2. Modes
  3. Navigation
  4. Containers
  5. Nesting
  6. Events
    1. List of Spotlight Events
    2. Preventing/Allowing Default DOM Events
    3. Sequence of Spotlight Events
    4. Accelerated keydown Events
    5. Scroll Events
    6. Default 5-way controls
  7. Extending Spotlight
    1. Spotlight Decorators
    2. Extending Controls
  8. Control Parameters
  9. Samples
  10. Copyright and License Information

What Is Spotlight?

Spotlight is an extensible utility that enables users to navigate Enyo applications using a keyboard or television remote control. Responding to input from the UP, DOWN, LEFT, RIGHT, and RETURN keys, Spotlight provides a navigation experience that compares favorably to that of a computer-with-mouse.

In addition, Spotlight includes support for point-and-click events, so all bases are covered.

To add Spotlight to an application, simply require spotlight in one of your source files:

    var Spotlight = require('spotlight');

Modes

Spotlight operates in two mutually exclusive modes: 5-way mode and Pointer mode. By default, Spotlight is configured to switch between these modes whenever suitable input is received--i.e., it switches to pointer mode on mousemove and back to 5-way mode on keydown.

The Spotlight API also provides a way to make the switch explicitly:

    Spotlight.setPointerMode(<Boolean>);

Navigation

Spotlight enables navigation between Enyo controls by assigning focus to one control at a time. When a control is focused, it takes on the CSS class .spotlight, which allows focused controls to be styled on a per-kind basis using .<kindClass>.spotlight selectors.

In order to make a control focusable (or "spottable") with Spotlight, simply set its spotlight property to true, like so:

    {name: 'mybutton', tag: 'button', spotlight: true}

When the application loads, Spotlight will initially spot the first spottable control. If a control has been programmatically spotted via Spotlight.spot(control) before render, that control will be spotted instead.

In 5-way mode, Spotlight uses the Nearest Neighbor Algorithm to determine which spottable control is the nearest one in the direction of navigation. The coordinates of a spottable control are derived from its actual position on the screen.

It's worth noting that spottable controls may be found on different hierarchical levels of an Enyo component tree. Spotlight facilitates seamless navigation among the topmost spottable components found in the tree.

For a demonstration of the Nearest Neighbor algorithm's behavior, see "TestPage" in the Enyo Sampler.

Containers

In order to organize controls into navigation groups, we have created Spotlight containers.

A good example of how containers should be used is a set of radio buttons that must be navigable separately from the rest of the app's controls.

When a Spotlight container is focused, it passes the focus to its own hierarchy of spottable child controls--specifically, to the last spottable child to hold focus before the focus moved outside of the container. If the container in question has never been focused, it passes focus to its first spottable child.

To define a container, set a control's spotlight property to "container":

    {
        name: 'mycontainer',
        spotlight: 'container',
        components: [<A list of controls with `spotlight:true`>]
    }

In a way, containers may be thought of as the branches--and spottable controls as the leaves--of the Spotlight navigation tree.

For a demonstration of container behavior, see "ContainerSample" in the Enyo sampler.

Nesting

Spotlight containers may be nested. The inner containers may be remembered as "last focused children" of the outer ones thereby passing focus to descendant spotlight: true controls.

We do not recommend placing spotlight: true controls within other spotlight: true controls because the user will be unable to navigate to them using 5-way controls. Instead, the outer controls should generally be set to spotlight: 'container' to allow the focus to cascade to the contained controls.

6. EVENTS

All Spotlight events are dispatched directly to the currently spotted control, which may prevent bubbling to define custom behavior. (See Extending Spotlight.)

If Spotlight events are allowed to bubble to the application level, the app responds to them with default behavior.


### 6.1. List of Spotlight Events ###

The following events are dispatched by the main Spotlight module:

  • onSpotlightKeyDown: Dispatched in response to keydown
  • onSpotlightKeyUp Dispatched in response to keyup
  • onSpotlightLeft: Dispatched in response to onSpotlightKeyDown event's bubbling to app level with keyCode 37
  • onSpotlightRight: Dispatched in response to onSpotlightKeyDown event's bubbling to app level with keyCode 39
  • onSpotlightUp: Dispatched in response to onSpotlightKeyDown event's bubbling to app level with keyCode 38
  • onSpotlightDown: Dispatched in response to onSpotlightKeyDown event's bubbling to app level with keyCode 40
  • onSpotlightSelect: Dispatched in response to onSpotlightKeyDown event's bubbling to app level with keyCode 13
  • onSpotlightFocus: Dispatched when focus is transferred to a new control in response to events 3 through 7.
  • onSpotlightBlur: Dispatched when focus is transferred away from a control
  • onSpotlightFocused: Dispatched in response to onSpotlightFocus event's bubbling to app level right after its originator is set as current
  • onSpotlightScrollUp: Dispatched when mousewheel event delta exceeds Spotlight.Scrolling.frequency (Default: 40)
  • onSpotlightScrollDown: Dispatched when mousewheel negative event delta exceeds -Spotlight.Scrolling.frequency (Default: 40)

6.2. Preventing or Allowing Default DOM events

By default, if a keydown event carries a 5-way keyCode (13, 37, 38, 39 or 40), it will be prevented from bubbling and triggering default browser behavior. This is done to disable default browser scrolling, because in the presence of Spotlight, scrolling is handled using components such as Scroller.

Of course, there are some cases where you may want to allow the default browser behavior. For example, in text inputs, you may want to allow the cursor to move to the next character when the right arrow key is pressed, without any interference from JavaScript.

For such cases, we have included an Allow DOM Default feature. The events onSpotlightKeyDown, onSpotlightLeft, onSpotlightRight, onSpotlightUp, onSpotlightDown and onSpotlightSelect pass their handlers an event object with an added allowDomDefault method:

    onSpotlightKeyDown: function(sender, event) {
        event.allowDomDefault();
    }

In the above handler, if the Spotlight event is allowed to propagate, it will allow the original DOM keydown to trigger default browser behavior. (See Figure A).


6.3. Sequence of Spotlight Events

Figure A

Spotlight keyboard events

Figure A illustrates the sequence of events in Spotlight's 5-way mode. At each step, the sequence may be modified (bubbling may be prevented) on the level of the currently focused control. (See Extending Spotlight.)

For instance, when onSpotlightKeyDown is dispatched to the focused control, the control may choose to prevent it from ever reaching the app level (where it would be handled by Spotlight) and replace the default behavior with its own custom handling.

If, however, onSpotlightKeydown is allowed to propagate and Spotlight recognizes its keyCode as one of 5-way key codes, it dispatches an onSpotlight<5-Way Direction> event back to the focused control. At this point, the control has, yet again, the option of overriding default behavior.

If the onSpotlight<5-Way Direction> event bubbles up to the app level, Spotlight employs its Nearest Neighbor Algorithm to figure out which spottable control is closest in the <5-Way Direction>. It then dispatches an onSpotlightBlur event to the current control (which also has the .spotlight CSS class removed), and an onSpotlightFocus event to the nearest neighbor (which has the .spotlight CSS class applied).

If onSpotlightFocus is allowed to bubble from the newly focused control, Spotlight sets its originator as current, and it officially becomes the focused control. In recognition of this fact, Spotlight dispatches onSpotlightFocused to the control.


6.4. Accelerated keydown Events

Figure B

Accelerated keydown sequence

While a key is depressed, the browser dispatches keydown events at equal (or nearly equal) intervals.

Looking at Figure B, we can see that not all of these events affect the application. The function of the Spotlight Accelerator is to distribute events over time (according to its configuration).

Spotlight Accelerator may be configured via its array property, Spotlight.Accelerator.frequency. The default configuration is as follows:

//* Firing configuration. At n-th second use every frequency[n] subsequent keydown event
frequency : [3, 3, 3, 2, 2, 2, 1], ...

This tells the Accelerator to do the following:

  • In the first, second, and third seconds after the key is depressed, only let through every third keydown event.
  • In the fourth, fifth, and sixth seconds, allow every second keydown event.
  • In the seventh second and later, allow every keydown event.

This causes Spotlight focus to move across the screen with apparent acceleration while a 5-way key is depressed.


6.5. Scroll Events

In response to mousewheel events from the browser, Spotlight dispatches onSpotlightScrollUp and onSpotlightScrollDown. Here's how the process works:

The mousewheel event has a wheelDeltaY property, which translates to a given amount of wheel rotation. Spotlight Scrolling accumulates wheelDeltaY values in a given direction of rotation (up or down).

Once the cumulative value exceeds Spotlight.Scrolling.frequency, onSpotlightScrollUp or onSpotlightScrollDown is dispatched and the cumulative value is reset to 0.

In this way, Spotlight scrolling events are made to behave more like repeating keydown events, which is useful for controls like pickers and list scrollers that don't use smooth scrolling, instead animating from one item to the next.

Note: In Pointer Mode, Spotlight treats the first scroll event as the first keyboard event; in response, Spotlight returns from pointer mode and re-spots the item that was previously spotted. No scrolling happens on the first scroll event when returning from pointer mode.

6.6. Default 5-way controls

Sometimes Nearest Neighbor algorithm is just not enough. Application UI specs may require you to specify where spotlight focus should move in response to 5-way event.

For cases like that Spotlight has convenience properties:

  • defaultSpotlightUp
  • defaultSpotlightDown
  • defaultSpotlightLeft
  • defaultSpotlightRight
  • defaultSpotlightSelect

Simply add them to your control, and if corresponding events is allowed to bubble, Spotlight will move focus to control, which name is specified in the property:

    {name: 'control1', spotlight: true, defaultSpotlightRight: 'control2'},
    {name: 'control2', spotlight: true, defaultSpotlightRight: 'control1'}

In this example, focus will be passed back and forth between both controls with every right arrow button press.

7. EXTENDING SPOTLIGHT

7.1. Extending Controls

Extending an Enyo control to use Spotlight functionality does not require knowledge of anything beyond Enyo's inheritance patterns and the information presented in this document.

To extend a control to use Spotlight, simply create a subkind of the kind you want to extend and define event handlers to handle Spotlight events.

Please refer to the Moonstone package for examples.

8. CONTROL PARAMETERS

spotlightDisabled: [boolean] - May be added to temporarily make component not spottable without changing it's spotlight property.

spotlightIgnoredKeys: [number | array] - Is used to specifiy a set of keys to be ignored by spotlight when originate at component.

9. SAMPLES

All samples reside in a consolidated sample app for Enyo and its libraries: enyo-strawman

10. COPYRIGHT AND LICENSE INFORMATION

Unless otherwise specified, all content, including all source code files and documentation files in this repository are:

Copyright (c) 2014 LG Electronics

Unless otherwise specified or set forth in the NOTICE file, all content, including all source code files and documentation files in this repository are: Licensed under the Apache License, Version 2.0 (the "License"); you may not use this content except in compliance with the License. You may obtain a copy of the License at

http://www.apache.org/licenses/LICENSE-2.0

Unless required by applicable law or agreed to in writing, software distributed under the License is distributed on an "AS IS" BASIS, WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied. See the License for the specific language governing permissions and limitations under the License.