vendor/assets/javascripts/sumatra.js.coffee in sumatra-rails-0.0.4.1 vs vendor/assets/javascripts/sumatra.js.coffee in sumatra-rails-0.0.5

- old
+ new

@@ -1,121 +1,242 @@ -#= require_tree ./sumatra/pkg +# SumatraPlugin +# ------------- +# +# A prototype object for common actions when defining jQuery plugins +# in the Sumatra framework. It is designed so that you never have to +# override the constructor. Instead, the constructor sets up a common +# method interface for both initialization (which would happen after +# construction) and the binding of events, a common task in jQuery +# plugins. This prototype even handles some of that for you, with +# the default `bindEvents()` being bound to call the `perform()` +# method (which must be defined by the object extending `SumatraPlugin`) +# whenever the element it was constructed with triggers the event +# defined by `action`. +# +# So essentially, you can define almost any jQuery plugin using this +# interface, even though the only thing binding it to the `sumatra` +# function is its constructor that takes 3 parameters. +# +# `SumatraPlugin` also has facilities for dealing with an options hash +# and merging said options with defaults. You can define the default +# options for your plugin like so: +# +# sumatra 'clickToGo', -> +# class ClickToGo extends SumatraPlugin +# action: 'click' +# defaults: { to: 'http://google.com' } +# perform: (event) => +# if confirm "Are you sure you want to go to #{@options.goTo}?" +# window.location = @options.goTo +# +# Then, when instantiating, just override them. +# +# $('a').clickToGo(to: 'http://yahoo.com'); +# +# This removes the need for writing that boilerplate options hash extend +# code every time you write a jQuery plugin that takes options. All +# plugins defined with `sumatra()` take an optional options hash, which is +# `{}` by default, in case your plugin doesn't require options. +class @SumatraPlugin + # The event to bind to if `perform()` is defined. + action: 'one' + + # A hash of attributes that are extended with an options hash passed + # into the jQuery plugin upon instantiation. Useful for setting up + # data that is required. + defaults: {} + + # Instantiate a `SumatraPlugin` and bind it to the current element + # with options. This also initiates the workflow. + # + # **DO NOT OVERRIDE!!** + constructor: (current_element, index_of_query, init_options) -> + @element = $(current_element) + @index = index_of_query + @options = @mergeDefaultsWith init_options + @element.data 'serviceObject', this + @initialize() and @bindEvents() + + # Merge `options` hash with the `defaults` as set in the definition + # of this object. + mergeDefaultsWith: (options) -> + _.extend @defaults, @options + + # Run custom constructor code, but blocks instantiation if this method + # returns `false`. This method was pretty much designed to be overridden. + initialize: -> + true + + # Bind the `perform()` method to the `action` as set in the definition + # of this plugin. Overriding this method removes the guarantee that + # perform() will be called at all... + bindEvents: -> + if @action? + @element.on @action, @perform + + # The event binding that handles `action`. Override this with your own + # method. You must override this method or the `bindEvents` method to + # get this plugin to do anything. It takes a single argument, `event`, + # which represents the given DOMEvent represented by `action` as passed + # in by `jQuery.on`. + perform: null + +# SumatraRuntime +# -------------- +# +# Defines a jQuery plugin using a service object with a nice, +# consistent, CoffeeScript-style interface. Plugins can extend +# `SumatraPlugin`, a prototype that makes defining plugins with +# Sumatra easier. +# +# The runtime function returns the generated jQuery plugin to the +# global scope so it can be used in your application code. +# +# Arguments: +# +# - **plugin_name:** The jQuery plugin name, called like `$('div').myPlugin();` +# - **plugin_code:** A function that will be executed immediately and must return +# a single object that takes 3 parameters in its constructor. These parameters +# are the `element` being targeted by jQuery, the `index` at which it appears +# in the query, and the `options` hash passed during the instantiation of the +# jQuery plugin. +# +# Example: +# +# sumatra 'myPlugin', -> +# class MyPlugin extends SumatraPlugin +# action: null +# initialize: +# alert 'loaded' +# +@sumatra = (plugin_name, plugin_code) -> + # Instantiate a PluginHelper and apply the current scope. This can + # be any object that responds to 3 parameters in its constructor + # and will be set to whatever is returned by `plugin_code()`. + PluginHelper = plugin_code.apply this + + jQuery.fn[plugin_name] = (options={}) -> + @each (index, element) -> + # For each element, create a `PluginHelper` instance + # of the passed-in `plugin_code` and apply the jQuery + # plugin parameters to the constructor. + new PluginHelper(element, index, options)