Wallflower

Reference & Guide

9 Aug 2010

Download from Github.
Wallflower is a jQuery plugin designed to be a focal point for the organization of page behavior (I like the word "feature") initialization. As such, there are two aspects to using wallflower:
  1. Feature code must be introduced to the plugin via a registration API. A feature is really just a piece of code to be called and a minor amount of additional information.
  2. Wallflower is invoked in order to apply registered features to pages at page "ready" time, or to page fragments fetched via a jQuery AJAX API, or even to page fragments synthesized by some client-side templating framework.

Registration

Feature registration is performed through a jQuery "global" function. The idea behind feature registration is to provide the plugin with information about how to identify page elements (that is, elements in the HTML of a page to which some features are to be applied), how to extract feature parameters from the elements, and then finally what code to call when such elements are actually found on a particular page.

The registration API can be invoked in different ways:

$.wallflower('feature-name'); $.wallflower('feature-name', function(params) { ... }); $.wallflower('feature-name', defaults, function(params) { ... }); $.wallflower(configuration);
  1. The first and simplest invocation mode registers a feature and assumes that the feature handler is an established jQuery method of the same name. For example, $.wallflower('datepicker'); would register the jQuery UI "datepicker" widget. Similarly, wallflower assumes that page elements to be located and passed to the feature handler can be identified by checking the "class" for the presence of the feature name: <input type='text' class='datepicker'>
  2. The second invocation method associates a feature name with the given handler function. Again, wallflower assumes that page elements are to be found by class name. The "params" passed to the handler will be those found by wallflower's standard means of discovery. (See also the discussion below of the "handler" configuration option.)
  3. The third invocation method is similar to the second, and also allows a block of registration parameters to be passed. The second parameter should be an object with any/all of the following properties:
    handler
    The handler function for the feature. Handler functions are passed parameters in the form of a single object. The object property names reflect names of parameters supplied to wallflower as defaults at registration time, or found embedded in HTML markup on elements matching the selector for the feature, or passed as application-time overrides to wallflower. The handlers are invoked separately for each DOM element found, such that the "this" context reference will be a jQuery object containing one such DOM element per invocation. (In this way, handler functions can be simple references to members of the "jQuery.fn" object, because their invocation by wallflower mimics ordinary invocation via plain jQuery calls.)
    defaults
    An object to be used as a source of default parameter values. These values may be overridden by parameters embedded in HTML markup and by parameters supplied to wallflower at feature application time.
    selector
    A CSS/jQuery selector string to be used to locate page elements for the feature. The default value for "selector" is "." followed by the feature name, meaning that wallflower assumes that the feature name will appear in the class of elements to be affected.
    attribute
    Names the DOM attribute to be checked by wallflower when checking matching elements for feature parameters. By default, wallflower checks elements for a "data-wf" attribute. (It is not mandatory that elements have the attribute named here, nor the default "data-wf" attribute.)
    evalAttr
    A boolean flag indicating whether the contents of the "data-wf" attribute (or the attribute identified by the "attribute" configuration parameter) should be interpreted as a JSON-notation object, or as a plain string. If true, the attribute value (if any) will be parsed as JSON, and the result used as an object full of parameters to pass to the feature. If false, the attribute value is used plain, with the attribute name used as the parameter name upon feature invocation. (If the attribute name starts with "data-", wallflower strips that for use as the application-time feature parameter.)
    depends
    A list (array) of one or more other wallflower feature names, indicating that the feature being registered should be applied to pages only after the named features are applied. Wallflower imposes an ordering on feature application based on these dependency declarations, but it does not treat missing dependencies as an error condition.
    group
    Provides a group association for the feature. At feature application time, features can be selected by group name. No default group name is synthesized by wallflower.
  4. The fourth and last invocation scheme allows many features to be registered one call. The configuration object should be of the form: { 'feature-name': { config params }, 'feature-name': { config params }, ... } Each block of "config params" should be as per the description given with registration method 3 above.
In all cases, calls to the registration function return a list of zero or more "overridden" features. In other words, if you register a feature called "myfeature" and then register another one with the same name, the return value will be an object with the original "myfeature" details.

Feature Application

The registration of features with wallflower does not in itself cause any actions to be taken outside of the plugin's internal book-keeping mechanism. In order to activate the registered features, wallflower should be invoked as a jQuery method on some target set of DOM elements. For example, to cause all registered wallflower features to be applied to the entire page, the following jQuery construct could be used: $(function() { $('body').wallflower(); }); The features need not be applied to the entire page, of course; wallflower operates on whatever DOM elements are presented to it.

What wallflower does, for each target element, is to find elements matching the configured selectors of each registered feature. (Features are processed in an order that satisfies the dependencies declared at configuration time, if any.) Those elements are looked for only beneath the target elements in the jQuery object from which the plugin is invoked. In other words, in the following:

$('#help-form fieldset.question').wallflower();

the plugin would look for elements only in fieldset elements located inside an element with id "help-form".

As elements are located for each feature being processed, wallflower discovers embedded parameters in the DOM and extracts them. Those parameters are used to extend a copy of the default parameters supplied at registration time.

The wallflower plugin also accepts a parameter object when it is invoked for feature application. The form of this parameter object is, generally: { 'feature-A': { 'parameter-name': 'value', ... }, 'feature-B': false, // or true '.group-A': { 'parameter-name': 'value', ... }, '.group-B': false, // or true '*': { 'parameter-name': 'value', ... }, '*': false // or true }

Feature name, with parameters
The given set of parameters are used as overrides for parameters discovered in the DOM and parameters from registration-time defaults. In addition, the presence of a parameter object ensures that a feature will be processed during an invocation of wallflower even if it would otherwise be disabled by a group or universal disable flag.
Feature name and boolean
If the boolean is false, then wallflower will skip the named feature for this invocation. If the boolean is true, then the feature will be processed even if it would otherwise be disabled at the group-level or universally.
Group name, with parameters
The given set of parameters are used as overrides for all features configued as members of the group. Note that the group name must be preceded by a period (like "class" references in jQuery selectors). The presence of group parameters overrides the universal disable flag as well.
Group name and boolean
If the boolean is false, then all features configued in the given group are skipped for this invocation of the plugin. If the boolean is true, then the features are not skipped even with the universal disable flag.
Asterisk, with parameters
The given set of parameters is used as overrides for all processed features.
Asterisk and boolean
All features are disabled except those explicitly enabled.
Wallflower composes the final set of parameters supplied to a feature's handler function from the following sources, in this order:
  1. configuration defaults
  2. discovered parameters
  3. parameters supplied at wallflower invocation time under the "*" property
  4. parameters supplied at wallflower invocation time under the group name
  5. parameters supplied at wallflower invocation time under the feature name

Parameter Discovery

When, by using the selector string configured for a registered feature, wallflower locates an element in the DOM that should be processed by the feature's handler, the plugin first examines the element for the presence of embedded parameters. Wallflower uses the Metadata plugin to handle parameter values in most cases. (The plugin is embedded in the wallflower source, so you don't have to worry about it. On the other hand, if you're already using the Metadata plugin, you can source wallflower after Metadata and it'll notice that Metadata is already installed.)

Parameters can be incorporated into HTML markup in three ways:

  1. In the "class" attribute
  2. In an element attribute other than "class"
  3. In a child script element
Wallflower always checks all sources of parameters, but there's no particular requirement that an affected element involve any embedded parameters at all.
The "class" attribute
In order to incorporate parameters in the "class" attribute value, the names and values should be written in JSON notation, surrounded by curly braces: <input type='text' class='datepicker { minDate: 0, maxDate: 90 }'> Any numbers of parameters may be included between the curly braces.

If two or more features may collide over a given element, then the parameters can be qualified by feature name:

<input type='text' class='datepicker { datepicker: { minDate: 0, maxDate: 90 } }' >
Alternate attributes
Wallflower checks the configured attribute of affected elements, or the "data-wf" attribute if no attribute is explicitly named in the feature configuration. If a value is found, it is treated as a JSON-formatted value like parameters embedded in the "class" attribute, though outer curly braces are optional. However, if the "evalAttr" configuration property is false, then the attribute value as a whole is taken to be the parameter value, with the name being derived from the attribute name. For attribute names beginning with the prefix "data-", wallflower strips that prefix to form the parameter name.

Again, as with parameter values embedded in the "class", feature names can be used to group parameters when clarification is necessary.

Script elements
The last source of parameters that wallflower can use is a script element contained by the affected element. The markup looks like this: <div class='affected-by-wallflower'> <script type='text/plain'> parameter_1: 100, parameter_2: "something", parameter_3: "something else" </script> By marking the script element with a type of "text/plain", the browser is informed that no attempt should be made to execute the script as code.