app/scripts/ui-lib/widgets/slideshow.coffee

Slideshow

The Slideshow class provides a slideshow widget.

author: Julien Ramboz version: 1.0 references: WAI-ARIA listbox role, AOL's Listbox style guide usage: Slideshow examples requires: Carousel

AMD loader

Try loading as AMD module or fall back to default loading

((widget) -> if typeof define is "function" and define.amd define ["jslib", "core", "widget", "carousel"], widget else widget @$, _, _.AbstractWidget, _.Carousel ) slideshow = ($, _, AbstractWidget, Carousel) -> "use strict"

Widget

The actual widget class

class Slideshow extends Carousel

Default options for the widget

@defaultOptions:
  • panels: a selector pointing to the panels
panels: ""
  • items: a selector pointing to the items (from within the panels)
items: ""
  • controls: how to display the controls (false: do not display, true or after: display after the panels, before: display before the panels, otherwise use a selector to find them)
controls: "false"
  • prev: whether to display the previous button or not, or the selector to the button
prev: "true"
  • next: whether to display the next button or not, or the selector to the button
next: "true"
  • play: whether to display the play button or not, or the selector to the button
play: "true"
  • pause: whether to display the pause button or not, or the selector to the button
pause: "true"
  • selectors: display the selectors (true, false or a selector pointing to the selectors)
selectors: "true"
  • event: the event to react to
event: "click"
  • cycleItems: whether to cycle though the items or not (true or false)
cycleItems: true
  • autoplay: whether to auto start the slideshow animation or not
autoplay: true
  • duration: the delay before switching to the next item (in ms)
duration: 7000
  • orientation: orientation of the carousel (horizontal or vertical)
orientation: 'horizontal'

Initialisation

Initializer function.

initialize: (options) -> super options @playButton = @findPlay() @pauseButton = @findPause()

Accessibility markup

Add aria attributes

aria: () -> if @controls @playButton?.attr "role": "button" "tabindex": 0 "data-role": "play" @pauseButton?.attr "role": "button" "tabindex": 0 "data-role": "pause" if @selectors @selectors.attr "role": "button" "tabindex": 0 "data-role": "selector" item = null @selectors.each( (i) => item = @items.get(i) if not item.id item.id = _.getGUID("carousel-item-") @selectors.eq(i).attr("aria-controls", item.id)) super() @element.attr("data-role", "slideshow")

Event handling

Attach evenets to the widget

bindEvents: () -> super() if (@controls) @prevButton?.on "#{@options.event}", (e) => if @prevButton.get(0).getAttribute("aria-disabled") isnt "true" @pause() @play() @nextButton?.on "#{@options.event}", (e) => if @nextButton.get(0).getAttribute("aria-disabled") isnt "true" @pause() @play() @playButton?.on "#{@options.event}", (e) => if @playButton.get(0).getAttribute("aria-disabled") isnt "true" e.preventDefault() @play() @pauseButton?.on "#{@options.event}", (e) => if @pauseButton.get(0).getAttribute("aria-disabled") isnt "true" e.preventDefault() @pause() if @selectors @element.on "#{@options.event}", "[data-role='selector']", (e) => e.preventDefault() @selectItem(@items.eq(@selectors.index(e.target))) $(window).on("animations", (e, o) => if @playButton and not o.animations @playButton.attr("aria-disabled", "true") if @playButton and o.animations and @animation @playButton.attr("aria-disabled", "false") if @pauseButton and o.animations and @animation @pauseButton.attr("aria-disabled", "false") if @pauseButton and not o.animations @pauseButton.attr("aria-disabled", "true") ) @play() if @options.autoplay isnt "false" @selectItem()

Select an item

selectItem: ($item) -> super($item) @selectors?.attr("aria-selected", "false") .eq(@items.index(@currentItem)).attr("aria-selected", "true") @currentItem

Play the slideshow

play: () -> @playButton?.attr("aria-disabled", "true") @pauseButton?.attr("aria-disabled", "false") if not @animation @animation = setInterval(Slideshow.autoPlay, @options.duration, @)

Pause the slideshow

pause: () -> @playButton?.attr("aria-disabled", "false") @pauseButton?.attr("aria-disabled", "true") clearTimeout(@animation) @animation = undefined

Auto play

@autoPlay: (inst) -> if _.allowAnimation() inst.selectNextItem()

Structure discovery

Find the widget structure using the specified configuration

Play control

Find the play control using:

  • element with data-role="play" (relative to the controls)
  • play option (selector relative to the controls)
  • fourth child of the controls
  • auto-generated
findPlay: () -> return if not @controls or not @controls.length return if not @options.play or @options.play is "false" $play = @controls.find("[data-role='play']") return $play if $play.length if @options.play is "true" or @options.play is true return @createPlay().appendTo(@controls) $play = $(@options.play, @controls) if $play.length $play else @controls.children().eq(3)

Pause control

Find the pause control using:

  • element with data-role="pause" (relative to the controls)
  • pause option (selector relative to the controls)
  • fifth child of the controls
  • auto-generated
findPause: () -> return if not @controls or not @controls.length return if not @options.pause or @options.pause is "false" $pause = @controls.find("[data-role='pause']") return $pause if $pause.length if @options.pause is "true" or @options.pause is true return @createPause().appendTo(@controls) $pause = $(@options.pause, @controls) if $pause.length $pause else @controls.children().eq(4)

Find the selectors using:

  • elements with data-role="selector" (relative to the controls)
  • selectors attribute (selector relative to the controls)
  • third child of the controls
  • auto-generated
findSelectors: () -> return if not @controls or not @controls.length $selectors = @controls.find("[data-role='selector']") return $selectors if $selectors.length if @options.selectors is "true" or @options.selectors is true $selectors = @createSelectors().appendTo(@controls) for i, j in @items @createSelector().appendTo($selectors) return $selectors $selectors = $(@options.selectors, @controls) if $selectors.length $selectors else $prev = @prevButton and @prevButton.get(0) $next = @nextButton and @nextButton.get(0) @controls.children().filter( () -> this isnt $prev and this isnt $next) .first().children()

Structure creation

Create elements required by the structure if they are not present

Play button

createPlay: () -> $(document.createElement("span"))

Pause button

createPause: () -> $(document.createElement("span"))

Selectors

createSelectors: () -> $(document.createElement("div")).attr("role","group")

Selector

createSelector: () -> $(document.createElement("span"))

Key handling

see Carousel key handling

Handle space key press

keySpace: (e) -> e.preventDefault() if @animation @pause() else @play()

Handle left key press

keyLeft: (e) -> super e $target = $(e.target) if e.target.getAttribute("role") is "button" and e.target isnt @prevButton.get(0) and e.target isnt @nextButton.get(0) @selectors.eq(@selectors.index($target)-1).focus()

Handle right key press

keyRight: (e) -> super e $target = $(e.target) if e.target.getAttribute("role") is "button" and e.target isnt @prevButton.get(0) and e.target isnt @nextButton.get(0) @selectors.eq((@selectors.index($target)+1) % @selectors.length).focus()

Cleanup

Cleanup the widget and remove remaining references

destructor: () -> super()

Installation

Install the widget into the JS library

Slideshow.install("Slideshow", () -> $("[data-widget='slideshow']")["#{_.namespace}slideshow"]() )