app/scripts/jslib-plugin-base.coffee

AbstractPlugin

The AbstractPlugin class provides an abstraction for JS library plugins. It defines the basic methods and logic all plugins should have, and handles installing the plugin into the JS library.

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

AMD loader

Try loading as AMD module or fall back to default loading

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

Plugin

The actual plugin class

class AbstractPlugin

The namespace for the plugins

@namespace = "epfl_"

Default options for the plugin. 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) @eventsBinder()

Wrapper method for the initialization process.

  • options Object: the options for the plugin initialization
initializer: (options) -> @initialize(options)

Method to initialize the plugin instance with the given options.

  • options Object: the options for the plugin initialization
initialize: (options) ->

Reset the instance using its old options if they exist

@reset(@options) if @options @options = options

Event handling

Wrapper method for the event binding.

eventsBinder: () -> @bindEvents()

Attach events to the widget.

bindEvents: () ->

Cleanup

Reset the plugin for re-initialisation.

  • options Object: the options to reset the plugin with
reset: (options) ->

Destroy the plugin.

destroy: () -> @element.trigger "ui-destroy"

Cleanup the plugin and remove remaining references.

destructor: () -> @element.off "ui-destroy" if @element $element = @element @element = null @defaultOptions = null @namespace = null @options = null $element

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=AbstractPlugin.namespace, init) -> pluginClass = @ if typeof pluginName is "function" init = pluginName pluginName = @name else if typeof namespace is "function" init = namespace namespace = "epfl_" 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 listener for jQuery's remove event

$this.on "ui-destroy.#{nsPluginName}", () -> if $.isFunction($this.removeData) $this.removeData(nsPluginName) else $this.data(nsPluginName, undefined) $this.off ".#{nsPluginName}"

Call plugin specific cleanup

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