app/scripts/ui-lib/jslib-widget-base.coffee

AbstractWidget

The AbstractWidget class provides an abstraction for JS library widgets.

author: Julien Ramboz
version: 1.0
references: jQuery CoffeeScript plugin requires: UI_Lib

AMD loader

Try loading as AMD module or fall back to default loading

((plugin) -> if typeof define is "function" and define.amd define ["jslib", "core", "plugin"], plugin else plugin @$, _, AbstractPlugin ) plugin = ($, _, AbstractPlugin) ->

Plugin

The actual plugin class

class AbstractWidget extends AbstractPlugin

Default options for the widget. Redefine this dictionary in extending classes to specify default options. These options can be overriden using 'data-' attributes, or by passing them directly to the constructor.

@defaultOptions: {}

Initialisation

The default constructor calls the initialize method with the specified method, sets the element, and binds events to the elements. Remember to call super in subclasses if you want to maintain behaviour.

  • element Object: the element the plugin is applied to
  • options Object: the options for the plugin initialization

returns the element

constructor: (@element, options) -> @initializer(options) @accessibilizer() @eventsBinder()

Accessibility markup

Wrapper method for the accessibility layer.

accessibilizer: () -> @aria()

Add ARIA attributes to the elements according to the following references:

aria: () ->

Key handling

Handle key press according to AOL's XXX style guide.

Attach keyboard key listeners for typical ARIA-compatible keys.

  • elements Object or Object[]: the elements to add the key listener to
  • ns String: an optional namespace to add to the event
handleKeys: ($elements, ns) -> $elements.on "keydown." + @options.pluginName, (e) => return if @element.attr("aria-disabled") is "true"

TODO: use e.keyIdentifier for better targetting than key codes

switch e.keyCode || e.which when 9 then @keyTab(e) when 13 then @keyEnter(e) when 32 then @keySpace(e) when 27 then @keyEscape(e) when 37 then @keyLeft(e) when 38 then @keyUp(e) when 39 then @keyRight(e) when 40 then @keyDown(e) when 33 then @keyPageUp(e) when 34 then @keyPageDown(e) when 36 then @keyHome(e) when 35 then @keyEnd(e) when 106 then @keyAsterisk(e) else if e.keyCode >= 48 and e.keyCode <= 57 @keyNumber(e) else if e.keyCode >= 65 and e.keyCode <= 90 @keyLetter(e)

Handle tab key press.

  • e Object: the event that was triggered
keyTab: (e) ->

Handle enter key press.

  • e Object: the event that was triggered
keyEnter: (e) ->

Handle space key press.

  • e Object: the event that was triggered
keySpace: (e) -> @keyEnter(e)

Handle escape key press.

  • e Object: the event that was triggered
keyEscape: (e) ->

Handle left key press.

  • e Object: the event that was triggered
keyLeft: (e) ->

Handle right key press.

  • e Object: the event that was triggered
keyRight: (e) ->

Handle up key press.

  • e Object: the event that was triggered
keyUp: (e) ->

Handle down key press.

  • e Object: the event that was triggered
keyDown: (e) ->

Handle page up key press.

  • e Object: the event that was triggered
keyPageUp: (e) ->

Handle page down key press.

  • e Object: the event that was triggered
keyPageDown: (e) ->

Handle home key press.

  • e Object: the event that was triggered
keyHome: (e) ->

Handle end key press.

  • e Object: the event that was triggered
keyEnd: (e) ->

Handle asterisk key press.

  • e Object: the event that was triggered
keyAsterisk: (e) ->

Handle key press on numbers.

  • e Object: the event that was triggered
keyNumber: (e) ->

Handle key press on letters.

  • e Object: the event that was triggered
keyLetter: (e) ->

Installation

Install the plugin into the JS library. Remember to call install in the plugin class as:

Plugin.install([pluginName],[namespace],[initFunction])
  • pluginName String: the name of the plugin
  • namespace String: an optional namespace for the plugin
  • init Function: some initialization code to execute after the plugin was loaded
@install: (pluginName = @name, namespace = _.namespace, init) -> pluginClass = @ if typeof pluginName is "function" init = pluginName pluginName = @name else if typeof namespace is "function" init = namespace namespace = _.namespace _[pluginName] = @ pluginName = pluginName.toLowerCase() @::.name = pluginName nsPluginName = (namespace or "") + pluginName

Install as JS library function

$.fn[nsPluginName] = (options, args...) ->

Iterate over all elements of the selector and add the plugin

return @each () -> $this = $(this)

Load default options

localoptions = $.extend( { pluginName: nsPluginName }, pluginClass.defaultOptions)

Override with options specfied as 'data-'' attributes

$.each localoptions, (o) -> v = $this.attr "data-"+o localoptions[o] = v if v v

Override with options specified in the direct call

localoptions = $.extend({}, localoptions, if $.isPlainObject(options) then options else {})

Do not create a new instance if one exists

instance = $this.data(nsPluginName) if instance?

Call internal instance methods

if $.type(options) is "string" instance[options].apply instance, args

Re-initialize the plugin with new options

else if instance.initialize? instance.initialize.apply instance, [localoptions].concat args

Create a new instance

else plugin = new pluginClass $this, localoptions, args...

Attach the plugin to the data attribute of the element

$this.data(nsPluginName, plugin)

Add a class corresponding to the plugin name

typeClass = pluginClass:: loop break if typeClass is (AbstractWidget::) or not typeClass $this.addClass _.cssNamespace+typeClass.name typeClass = Object.getPrototypeOf?(typeClass) or typeClass.__proto__

Add a listener for jQuery's remove event

$this.on "ui-destroy.#{nsPluginName}", () -> if $.isFunction($this.removeData) $this.removeData(nsPluginName) else $this.data(nsPluginName, undefined) typeClass = pluginClass:: loop break if typeClass is (AbstractWidget::) or not typeClass $this.off ".#{_.namespace}#{typeClass.name}" typeClass = Object.getPrototypeOf?(typeClass) or typeClass.__proto__

Call plugin specific cleanup

plugin.destructor() plugin $( init ) if typeof init is "function" pluginClass

Add the class to the library

_.AbstractWidget = AbstractWidget AbstractWidget