Tag: kranthi

Introducing The 6 + 1 Model For Effective Copywriting (Better Than AIDA!)





 



 


AIDA. Attention, interest, desire, action.

It’s the classic copywriting formula, studied and used by almost every copywriter on the planet.

Well, I’m not a fan.

Not because it isn’t accurate, and not because it doesn’t work. If your writing can get attention, grab interest, create desire and prompt action, then you’re doing a lot of things right.

If your writing isn’t doing these things, however, then I don’t think AIDA will help you very much, because it doesn’t do enough to explain how to do any of these things.

The best way to learn is by example, so let’s look at a promotional failure and see how it conforms to AIDA but still doesn’t work.

Notebook and Pen
(Image source: alt1040)

Text-Message Loan Sharking?

I recently received a text message from a number I didn’t recognize. It read:

Coming up short between pay-days? You can solve the problem NOW with a $300–$1000 INSTANT–Advance! Respond YES if interested, NO–to–STOP


(Image: someToast)

Now, obviously, I didn’t text back the anonymous sender with a “Yes.� I didn’t text them back with a “No� either. I called the number to tell them that I don’t appreciate unsolicited spam marketing. But no one answered; the call went to a voicemail box that was full.

I was unimpressed before; this sealed the deal!

Let’s see how this piece of marketing stacks up on the AIDA scale:

  • A for attention
    Sure, the text message got my attention. After all, text messaging is an interruptive medium; you’re bound to get attention that way.
  • I for interest
    Okay, I’ll play along. Let’s say that I am, in fact, coming up short between pay days: the message would have my interest. So far, so good.
  • D for desire
    Also good. If I’m broke and need cash, then I’d definitely want an advance.
  • A for action
    Well, the message called for action (“Respond YES if interested�), but it didn’t lead to action. Fail.

What Was Missing? Why Didn’t It Work?

The missing element in this campaign was context: who are they, why are they contacting me, and why should I trust them?

Context is a critical component of effective messaging. Without it, action likely won’t result, even if you call for it.

The trouble with AIDA is that it implies that attention leads to interest, which then leads to desire, which in turn leads to action. But a piece of the puzzle is still missing: context.

AIDA doesn’t give you all of the ingredients that combine to result in action — which is what you ultimately want!

A Better Model: 6 + 1

This model is a little more complex, which is a good thing.

Complexity is important — critical, even. And in this case, it involves information that AIDA lacks but that is needed in order to write effective copy (unless you’re one of those people to whom it comes as naturally as speaking). Here, then, is the 6 + 1 model, with six steps plus one extra thing you’ve got to cover along the way.

Ready to dive in? Let’s get started with the first item.

Step 1: Context

The very first thing you need to do, before trying to get attention or anything else, is establish context. Answer the audience’s implicit question, “Who are you, and why are you talking to me?�

No Junk Mail
(Image: loop_oh)

Too many marketers compete for the attention of every single person, so establishing context is necessary to stand out from the crowd. Junk mail is a perfect illustration. The context of junk mail is, “You don’t know us, but we want to sell you something!� That’s why most junk mail ends up in the trash, unread.

A campaign that establishes context, on the other hand, might arrive in a personally addressed envelope and be written in the form of a letter. The context here is implied, and the proportion of people who open the envelope would be much higher. The first few sentences, naturally, would explain why the recipient is familiar with the sender and needs the product or service.

Just as the recipient’s question of “Who is this person talking to me?� is implicit, so too can be the answer. For example, if you’re reaching out to someone in response to a job offer that they’ve posted, you would send them a cover letter and CV. The combination of circumstances and the format of your letter make it clear why you’re reaching out to them.

That being said, you always want to create as strong a context as possible. So, you would start the cover letter by mentioning where you found the job posting and why you felt you should apply (you’ve always wanted to work for this company, you love the industry, etc.) This explicit context immediately puts you ahead of other applicants.

In the text-message example above, context could have been established with a link to a website where I could learn more about the company, or even an automated message at the end of the phone number, instead of a computer telling me that the voicemail box is full.

Better yet, the text message could have begun with a few words reminding me of previous interactions I might have had with the sender. For example, my wireless service provider occasionally sends me text messages about new offers and services, and they always begin with, “Dear Rogers customer…� This instantly lets me know that I am being contacted by someone I know for a specific reason. The sender is credible because it provides a service to me, so I am very likely to read its message. Of course, this works only when the sender has some sort of relationship with the recipient — but that makes for the best messaging in any case.

Context comes down to the reason why your audience is being exposed to your message. If they are subscribers to your blog, then that subscription serves as the context for any email you send them. If the content is found on your website, then the person’s search for information about your topic or service is the context. If you’re running an ad in a newspaper or magazine, then the theme of that publication is the context.

Step 2: Attention

Once context has been established, you can go ahead and grab the audience’s attention.

If you’re the writer, you’ll do so with the headline. And if you’re the designer, you will make sure that, at first glance, the presentation is eye-catching.

Plenty of resources out there will teach you how to do that, so I won’t go into detail in this article. Suffice it to say that you have to grab your audience’s attention and hold it until you can create…

Step 3: Desire

The reality of marketing in this day and age is that attention is short-lived. Where we once spoke of 15 minutes of fame, today it’s a lot closer to 15 seconds.

In the span of those 15 seconds, you have to make your audience want something, and want it badly enough to keep on reading.

If you’re writing a blog post, this would happen in your opening paragraphs, the section before the <more> tag. It’s the hook: you’ve grabbed their attention, and now you’ve got to reel them in by describing the symptoms that they’re experiencing, ideas that they may not have considered, or outcomes that they want for themselves. This will inspire them to continue reading, and then you can go into detail and describe…

Step 4: The Gap

You’ve got their attention, and created desire — at this point your prospect should be convinced that they need to take action of some kind.

Now you must drive home the idea by communicating the difference between what will happen if they do nothing and what will happen if they take advantage of your product or service. We call this establishing the gap.

You can do this by asking, “What if nothing changed? What would that mean?� Then spell it out for them.

The answer might be emotional; after all, you’re talking about the painful implications of their current situation — the prospect of the situation not changing is scary. This is an excellent time to use examples and case studies to highlight the consequences of inaction.

Step 5: Solution

You can’t leave the reader in this state; once you’ve established the gap, transition quickly into your solution. It’s important to say that you have a solution, and to tell them as much as they need to know in order to understand that it will work — but no more. Any extra detail is an opportunity to question or disagree with you, so keep information about how the solution works on a strictly need-to-know basis.

Of course, all of the usual best practices about speaking to emotional versus rational benefits, rather than features, and addressing your one ideal customer still apply. No need to rehash them here.

Step 6: Call to Action

Of course, you have to end with a call to action, which requires you to do two things:

  1. Identify the single next step that you want your audience to take when they’re done reading. Not an array of options (“Call us on the phone or visit our website or follow us on Twitter or…�), just one next action.
  2. Explicitly ask the audience to take that action. Don’t dance around the issue; if you want them to do something, say so.

Again, this is familiar territory, so I won’t go into any more detail here.

It’s tempting to think that we’re done with the model, but don’t forget the +1 part of the model. One important thing still needs to be covered.

Credibility: The Extra Step Along The Way

You can do all of the above and you’ll be well on your way to a sale, but you still won’t get it without one more ingredient, added along the way. That ingredient is credibility.

Starbucks Message
(Image: Denise Cross)

If the reader doesn’t believe what you say, or doesn’t believe that you’re in a position to say it, then they have no reason to follow through on anything you ask them to do, no matter how well you cover the other steps in your content.

To establish credibility, you have to start with understanding: showing the reader that you understand their reality intimately. After all, if you don’t really know their situation, then how would you know how to improve it?

Then show the reader why they can trust that you know what you’re talking about: appeal to their common sense (what you’re saying should make sense), demonstrate social proof (how many other people have already taken the action you want them to take?), demonstrate your expertise (your education and experience in the subject matter), and apply risk-reversal whenever possible (with guarantees and warranties).

This isn’t the sixth step, because you don’t do it all at once. Rather, you build a bit of credibility here and a bit more there, all the way through your messaging, so that by the end they believe you.

The 6 + 1 model succeeds where AIDA fails because it forces you to establish yourself as a source of authority in the reader’s eyes. While doing this through AIDA certainly is possible, the 6 + 1 formula impels you to account for the different responses that readers will have as they digest your copy. For a new copywriter, or a copywriter who is not achieving the amount of conversions that they think they should, these extra steps will be invaluable.

(al)


© Danny Iny for Smashing Magazine, 2011.


Essential jQuery Plugin Patterns





 



 


I occasionally write about implementing design patterns in JavaScript. They’re an excellent way of building upon proven approaches to solving common development problems, and I think there’s a lot of benefit to using them. But while well-known JavaScript patterns are useful, another side of development could benefit from its own set of design patterns: jQuery plugins. The official jQuery plugin authoring guide offers a great starting point for getting into writing plugins and widgets, but let’s take it further.

Plugin development has evolved over the past few years. We no longer have just one way to write plugins, but many. In reality, certain patterns might work better for a particular problem or component than others.

Some developers may wish to use the jQuery UI widget factory; it’s great for complex, flexible UI components. Some may not. Some might like to structure their plugins more like modules (similar to the module pattern) or use a more formal module format such as AMD (asynchronous module definition). Some might want their plugins to harness the power of prototypal inheritance. Some might want to use custom events or pub/sub to communicate from plugins to the rest of their app. And so on.

I began to think about plugin patterns after noticing a number of efforts to create a one-size-fits-all jQuery plugin boilerplate. While such a boilerplate is a great idea in theory, the reality is that we rarely write plugins in one fixed way, using a single pattern all the time.

Let’s assume that you’ve tried your hand at writing your own jQuery plugins at some point and you’re comfortable putting together something that works. It’s functional. It does what it needs to do, but perhaps you feel it could be structured better. Maybe it could be more flexible or could solve more issues. If this sounds familiar and you aren’t sure of the differences between many of the different jQuery plugin patterns, then you might find what I have to say helpful.

My advice won’t provide solutions to every possible pattern, but it will cover popular patterns that developers use in the wild.

Note: This post is targeted at intermediate to advanced developers. If you don’t feel you’re ready for this just yet, I’m happy to recommend the official jQuery Plugins/Authoring guide, Ben Alman’s plugin style guide and Remy Sharp’s “Signs of a Poorly Written jQuery Plugin.�

Patterns

jQuery plugins have very few defined rules, which one of the reasons for the incredible diversity in how they’re implemented. At the most basic level, you can write a plugin simply by adding a new function property to jQuery’s $.fn object, as follows:

$.fn.myPluginName = function() {
    // your plugin logic
};

This is great for compactness, but the following would be a better foundation to build on:

(function( $ ){
  $.fn.myPluginName = function() {
    // your plugin logic
  };
})( jQuery );

Here, we’ve wrapped our plugin logic in an anonymous function. To ensure that our use of the $ sign as a shorthand creates no conflicts between jQuery and other JavaScript libraries, we simply pass it to this closure, which maps it to the dollar sign, thus ensuring that it can’t be affected by anything outside of its scope of execution.

An alternative way to write this pattern would be to use $.extend, which enables you to define multiple functions at once and which sometimes make more sense semantically:

(function( $ ){
    $.extend($.fn, {
        myplugin: function(){
            // your plugin logic
        }
    });
})( jQuery );

We could do a lot more to improve on all of this; and the first complete pattern we’ll be looking at today, the lightweight pattern, covers some best practices that we can use for basic everyday plugin development and that takes into account common gotchas to look out for.

Some Quick Notes

You can find all of the patterns from this post in this GitHub repository.

While most of the patterns below will be explained, I recommend reading through the comments in the code, because they will offer more insight into why certain practices are best.

I should also mention that none of this would be possible without the previous work, input and advice of other members of the jQuery community. I’ve listed them inline with each pattern so that you can read up on their individual work if interested.

A Lightweight Start

Let’s begin our look at patterns with something basic that follows best practices (including those in the jQuery plugin-authoring guide). This pattern is ideal for developers who are either new to plugin development or who just want to achieve something simple (such as a utility plugin). This lightweight start uses the following:

  • Common best practices, such as a semi-colon before the function’s invocation; window, document, undefined passed in as arguments; and adherence to the jQuery core style guidelines.
  • A basic defaults object.
  • A simple plugin constructor for logic related to the initial creation and the assignment of the element to work with.
  • Extending the options with defaults.
  • A lightweight wrapper around the constructor, which helps to avoid issues such as multiple instantiations.
/*!
 * jQuery lightweight plugin boilerplate
 * Original author: @ajpiano
 * Further changes, comments: @addyosmani
 * Licensed under the MIT license
 */

// the semi-colon before the function invocation is a safety
// net against concatenated scripts and/or other plugins
// that are not closed properly.
;(function ( $, window, document, undefined ) {

    // undefined is used here as the undefined global
    // variable in ECMAScript 3 and is mutable (i.e. it can
    // be changed by someone else). undefined isn't really
    // being passed in so we can ensure that its value is
    // truly undefined. In ES5, undefined can no longer be
    // modified.

    // window and document are passed through as local
    // variables rather than as globals, because this (slightly)
    // quickens the resolution process and can be more
    // efficiently minified (especially when both are
    // regularly referenced in your plugin).

    // Create the defaults once
    var pluginName = 'defaultPluginName',
        defaults = {
            propertyName: "value"
        };

    // The actual plugin constructor
    function Plugin( element, options ) {
        this.element = element;

        // jQuery has an extend method that merges the
        // contents of two or more objects, storing the
        // result in the first object. The first object
        // is generally empty because we don't want to alter
        // the default options for future instances of the plugin
        this.options = $.extend( {}, defaults, options) ;

        this._defaults = defaults;
        this._name = pluginName;

        this.init();
    }

    Plugin.prototype.init = function () {
        // Place initialization logic here
        // You already have access to the DOM element and
        // the options via the instance, e.g. this.element
        // and this.options
    };

    // A really lightweight plugin wrapper around the constructor,
    // preventing against multiple instantiations
    $.fn[pluginName] = function ( options ) {
        return this.each(function () {
            if (!$.data(this, 'plugin_' + pluginName)) {
                $.data(this, 'plugin_' + pluginName,
                new Plugin( this, options ));
            }
        });
    }

})( jQuery, window, document );

Further Reading

“Complete� Widget Factory

While the authoring guide is a great introduction to plugin development, it doesn’t offer a great number of conveniences for obscuring away from common plumbing tasks that we have to deal with on a regular basis.

The jQuery UI Widget Factory is a solution to this problem that helps you build complex, stateful plugins based on object-oriented principles. It also eases communication with your plugin’s instance, obfuscating a number of the repetitive tasks that you would have to code when working with basic plugins.

In case you haven’t come across these before, stateful plugins keep track of their current state, also allowing you to change properties of the plugin after it has been initialized.

One of the great things about the Widget Factory is that the majority of the jQuery UI library actually uses it as a base for its components. This means that if you’re looking for further guidance on structure beyond this template, you won’t have to look beyond the jQuery UI repository.

Back to patterns. This jQuery UI boilerplate does the following:

  • Covers almost all supported default methods, including triggering events.
  • Includes comments for all of the methods used, so that you’re never unsure of where logic should fit in your plugin.
/*!
 * jQuery UI Widget-factory plugin boilerplate (for 1.8/9+)
 * Author: @addyosmani
 * Further changes: @peolanha
 * Licensed under the MIT license
 */

;(function ( $, window, document, undefined ) {

    // define your widget under a namespace of your choice
    //  with additional parameters e.g.
    // $.widget( "namespace.widgetname", (optional) - an
    // existing widget prototype to inherit from, an object
    // literal to become the widget's prototype ); 

    $.widget( "namespace.widgetname" , {

        //Options to be used as defaults
        options: {
            someValue: null
        },

        //Setup widget (eg. element creation, apply theming
        // , bind events etc.)
        _create: function () {

            // _create will automatically run the first time
            // this widget is called. Put the initial widget
            // setup code here, then you can access the element
            // on which the widget was called via this.element.
            // The options defined above can be accessed
            // via this.options this.element.addStuff();
        },

        // Destroy an instantiated plugin and clean up
        // modifications the widget has made to the DOM
        destroy: function () {

            // this.element.removeStuff();
            // For UI 1.8, destroy must be invoked from the
            // base widget
            $.Widget.prototype.destroy.call(this);
            // For UI 1.9, define _destroy instead and don't
            // worry about
            // calling the base widget
        },

        methodB: function ( event ) {
            //_trigger dispatches callbacks the plugin user
            // can subscribe to
            // signature: _trigger( "callbackName" , [eventObject],
            // [uiObject] )
            // eg. this._trigger( "hover", e /*where e.type ==
            // "mouseenter"*/, { hovered: $(e.target)});
            this._trigger('methodA', event, {
                key: value
            });
        },

        methodA: function ( event ) {
            this._trigger('dataChanged', event, {
                key: value
            });
        },

        // Respond to any changes the user makes to the
        // option method
        _setOption: function ( key, value ) {
            switch (key) {
            case "someValue":
                //this.options.someValue = doSomethingWith( value );
                break;
            default:
                //this.options[ key ] = value;
                break;
            }

            // For UI 1.8, _setOption must be manually invoked
            // from the base widget
            $.Widget.prototype._setOption.apply( this, arguments );
            // For UI 1.9 the _super method can be used instead
            // this._super( "_setOption", key, value );
        }
    });

})( jQuery, window, document );

Further Reading

Namespacing And Nested Namespacing

Namespacing your code is a way to avoid collisions with other objects and variables in the global namespace. They’re important because you want to safeguard your plugin from breaking in the event that another script on the page uses the same variable or plugin names as yours. As a good citizen of the global namespace, you must also do your best not to prevent other developers’ scripts from executing because of the same issues.

JavaScript doesn’t really have built-in support for namespaces as other languages do, but it does have objects that can be used to achieve a similar effect. Employing a top-level object as the name of your namespace, you can easily check for the existence of another object on the page with the same name. If such an object does not exist, then we define it; if it does exist, then we simply extend it with our plugin.

Objects (or, rather, object literals) can be used to create nested namespaces, such as namespace.subnamespace.pluginName and so on. But to keep things simple, the namespacing boilerplate below should give you everything you need to get started with these concepts.

/*!
 * jQuery namespaced 'Starter' plugin boilerplate
 * Author: @dougneiner
 * Further changes: @addyosmani
 * Licensed under the MIT license
 */

;(function ( $ ) {
    if (!$.myNamespace) {
        $.myNamespace = {};
    };

    $.myNamespace.myPluginName = function ( el, myFunctionParam, options ) {
        // To avoid scope issues, use 'base' instead of 'this'
        // to reference this class from internal events and functions.
        var base = this;

        // Access to jQuery and DOM versions of element
        base.$el = $(el);
        base.el = el;

        // Add a reverse reference to the DOM object
        base.$el.data( "myNamespace.myPluginName" , base );

        base.init = function () {
            base.myFunctionParam = myFunctionParam;

            base.options = $.extend({},
            $.myNamespace.myPluginName.defaultOptions, options);

            // Put your initialization code here
        };

        // Sample Function, Uncomment to use
        // base.functionName = function( paramaters ){
        //
        // };
        // Run initializer
        base.init();
    };

    $.myNamespace.myPluginName.defaultOptions = {
        myDefaultValue: ""
    };

    $.fn.mynamespace_myPluginName = function
        ( myFunctionParam, options ) {
        return this.each(function () {
            (new $.myNamespace.myPluginName(this,
            myFunctionParam, options));
        });
    };

})( jQuery );

Further Reading

Custom Events For Pub/Sub (With The Widget factory)

You may have used the Observer (Pub/Sub) pattern in the past to develop asynchronous JavaScript applications. The basic idea here is that elements will publish event notifications when something interesting occurs in your application. Other elements then subscribe to or listen for these events and respond accordingly. This results in the logic for your application being significantly more decoupled (which is always good).

In jQuery, we have this idea that custom events provide a built-in means to implement a publish and subscribe system that’s quite similar to the Observer pattern. So, bind('eventType') is functionally equivalent to performing subscribe('eventType'), and trigger('eventType') is roughly equivalent to publish('eventType').

Some developers might consider the jQuery event system as having too much overhead to be used as a publish and subscribe system, but it’s been architected to be both reliable and robust for most use cases. In the following jQuery UI widget factory template, we’ll implement a basic custom event-based pub/sub pattern that allows our plugin to subscribe to event notifications from the rest of our application, which publishes them.

/*!
 * jQuery custom-events plugin boilerplate
 * Author: DevPatch
 * Further changes: @addyosmani
 * Licensed under the MIT license
 */

// In this pattern, we use jQuery's custom events to add
// pub/sub (publish/subscribe) capabilities to widgets.
// Each widget would publish certain events and subscribe
// to others. This approach effectively helps to decouple
// the widgets and enables them to function independently.

;(function ( $, window, document, undefined ) {
    $.widget("ao.eventStatus", {
        options: {

        },

        _create : function() {
            var self = this;

            //self.element.addClass( "my-widget" );

            //subscribe to 'myEventStart'
            self.element.bind( "myEventStart", function( e ) {
                console.log("event start");
            });

            //subscribe to 'myEventEnd'
            self.element.bind( "myEventEnd", function( e ) {
                console.log("event end");
            });

            //unsubscribe to 'myEventStart'
            //self.element.unbind( "myEventStart", function(e){
                ///console.log("unsubscribed to this event");
            //});
        },

        destroy: function(){
            $.Widget.prototype.destroy.apply( this, arguments );
        },
    });
})( jQuery, window , document );

//Publishing event notifications
//usage:
// $(".my-widget").trigger("myEventStart");
// $(".my-widget").trigger("myEventEnd");

Further Reading

Prototypal Inheritance With The DOM-To-Object Bridge Pattern

In JavaScript, we don’t have the traditional notion of classes that you would find in other classical programming languages, but we do have prototypal inheritance. With prototypal inheritance, an object inherits from another object. And we can apply this concept to jQuery plugin development.

Alex Sexton and Scott Gonzalez have looked at this topic in detail. In sum, they found that for organized modular development, clearly separating the object that defines the logic for a plugin from the plugin-generation process itself can be beneficial. The benefit is that testing your plugin’s code becomes easier, and you can also adjust the way things work behind the scenes without altering the way that any object APIs you’ve implemented are used.

In Sexton’s previous post on this topic, he implements a bridge that enables you to attach your general logic to a particular plugin, which we’ve implemented in the template below. Another advantage of this pattern is that you don’t have to constantly repeat the same plugin initialization code, thus ensuring that the concepts behind DRY development are maintained. Some developers might also find this pattern easier to read than others.

/*!
 * jQuery prototypal inheritance plugin boilerplate
 * Author: Alex Sexton, Scott Gonzalez
 * Further changes: @addyosmani
 * Licensed under the MIT license
 */

// myObject - an object representing a concept that you want
// to model (e.g. a car)
var myObject = {
  init: function( options, elem ) {
    // Mix in the passed-in options with the default options
    this.options = $.extend( {}, this.options, options );

    // Save the element reference, both as a jQuery
    // reference and a normal reference
    this.elem  = elem;
    this.$elem = $(elem);

    // Build the DOM's initial structure
    this._build();

    // return this so that we can chain and use the bridge with less code.
    return this;
  },
  options: {
    name: "No name"
  },
  _build: function(){
    //this.$elem.html('<h1>'+this.options.name+'</h1>');
  },
  myMethod: function( msg ){
    // You have direct access to the associated and cached
    // jQuery element
    // this.$elem.append('<p>'+msg+'</p>');
  }
};

// Object.create support test, and fallback for browsers without it
if ( typeof Object.create !== 'function' ) {
    Object.create = function (o) {
        function F() {}
        F.prototype = o;
        return new F();
    };
}

// Create a plugin based on a defined object
$.plugin = function( name, object ) {
  $.fn[name] = function( options ) {
    return this.each(function() {
      if ( ! $.data( this, name ) ) {
        $.data( this, name, Object.create(object).init(
        options, this ) );
      }
    });
  };
};

// Usage:
// With myObject, we could now essentially do this:
// $.plugin('myobj', myObject);

// and at this point we could do the following
// $('#elem').myobj({name: "John"});
// var inst = $('#elem').data('myobj');
// inst.myMethod('I am a method');

Further Reading

jQuery UI Widget Factory Bridge

If you liked the idea of generating plugins based on objects in the last design pattern, then you might be interested in a method found in the jQuery UI Widget Factory called $.widget.bridge. This bridge basically serves as a middle layer between a JavaScript object that is created using $.widget and jQuery’s API, providing a more built-in solution to achieving object-based plugin definition. Effectively, we’re able to create stateful plugins using a custom constructor.

Moreover, $.widget.bridge provides access to a number of other capabilities, including the following:

  • Both public and private methods are handled as one would expect in classical OOP (i.e. public methods are exposed, while calls to private methods are not possible);
  • Automatic protection against multiple initializations;
  • Automatic generation of instances of a passed object, and storage of them within the selection’s internal $.data cache;
  • Options can be altered post-initialization.

For further information on how to use this pattern, look at the comments in the boilerplate below:

/*!
 * jQuery UI Widget factory "bridge" plugin boilerplate
 * Author: @erichynds
 * Further changes, additional comments: @addyosmani
 * Licensed under the MIT license
 */

// a "widgetName" object constructor
// required: this must accept two arguments,
// options: an object of configuration options
// element: the DOM element the instance was created on
var widgetName = function( options, element ){
  this.name = "myWidgetName";
  this.options = options;
  this.element = element;
  this._init();
}

// the "widgetName" prototype
widgetName.prototype = {

    // _create will automatically run the first time this
    // widget is called
    _create: function(){
        // creation code
    },

    // required: initialization logic for the plugin goes into _init
    // This fires when your instance is first created and when
    // attempting to initialize the widget again (by the bridge)
    // after it has already been initialized.
    _init: function(){
        // init code
    },

    // required: objects to be used with the bridge must contain an
    // 'option'. Post-initialization, the logic for changing options
    // goes here.
    option: function( key, value ){

        // optional: get/change options post initialization
        // ignore if you don't require them.

        // signature: $('#foo').bar({ cool:false });
        if( $.isPlainObject( key ) ){
            this.options = $.extend( true, this.options, key );

        // signature: $('#foo').option('cool'); - getter
        } else if ( key && typeof value === "undefined" ){
            return this.options[ key ];

        // signature: $('#foo').bar('option', 'baz', false);
        } else {
            this.options[ key ] = value;
        }

        // required: option must return the current instance.
        // When re-initializing an instance on elements, option
        // is called first and is then chained to the _init method.
        return this;
    },

    // notice no underscore is used for public methods
    publicFunction: function(){
        console.log('public function');
    },

    // underscores are used for private methods
    _privateFunction: function(){
        console.log('private function');
    }
};

// usage:

// connect the widget obj to jQuery's API under the "foo" namespace
// $.widget.bridge("foo", widgetName);

// create an instance of the widget for use
// var instance = $("#elem").foo({
//     baz: true
// });

// your widget instance exists in the elem's data
// instance.data("foo").element; // => #elem element

// bridge allows you to call public methods...
// instance.foo("publicFunction"); // => "public method"

// bridge prevents calls to internal methods
// instance.foo("_privateFunction"); // => #elem element

Further Reading

jQuery Mobile Widgets With The Widget factory

jQuery mobile is a framework that encourages the design of ubiquitous Web applications that work both on popular mobile devices and platforms and on the desktop. Rather than writing unique applications for each device or OS, you simply write the code once and it should ideally run on many of the A-, B- and C-grade browsers out there at the moment.

The fundamentals behind jQuery mobile can also be applied to plugin and widget development, as seen in some of the core jQuery mobile widgets used in the official library suite. What’s interesting here is that even though there are very small, subtle differences in writing a “mobile�-optimized widget, if you’re familiar with using the jQuery UI Widget Factory, you should be able to start writing these right away.

The mobile-optimized widget below has a number of interesting differences than the standard UI widget pattern we saw earlier:

  • $.mobile.widget is referenced as an existing widget prototype from which to inherit. For standard widgets, passing through any such prototype is unnecessary for basic development, but using this jQuery-mobile specific widget prototype provides internal access to further “optionsâ€� formatting.
  • You’ll notice in _create() a guide on how the official jQuery mobile widgets handle element selection, opting for a role-based approach that better fits the jQM mark-up. This isn’t at all to say that standard selection isn’t recommended, only that this approach might make more sense given the structure of jQM pages.
  • Guidelines are also provided in comment form for applying your plugin methods on pagecreate as well as for selecting the plugin application via data roles and data attributes.
/*!
 * (jQuery mobile) jQuery UI Widget-factory plugin boilerplate (for 1.8/9+)
 * Author: @scottjehl
 * Further changes: @addyosmani
 * Licensed under the MIT license
 */

;(function ( $, window, document, undefined ) {

    //define a widget under a namespace of your choice
    //here 'mobile' has been used in the first parameter
    $.widget( "mobile.widgetName", $.mobile.widget, {

        //Options to be used as defaults
        options: {
            foo: true,
            bar: false
        },

        _create: function() {
            // _create will automatically run the first time this
            // widget is called. Put the initial widget set-up code
            // here, then you can access the element on which
            // the widget was called via this.element
            // The options defined above can be accessed via
            // this.options

            //var m = this.element,
            //p = m.parents(":jqmData(role='page')"),
            //c = p.find(":jqmData(role='content')")
        },

        // Private methods/props start with underscores
        _dosomething: function(){ ... },

        // Public methods like these below can can be called
                // externally:
        // $("#myelem").foo( "enable", arguments );

        enable: function() { ... },

        // Destroy an instantiated plugin and clean up modifications
        // the widget has made to the DOM
        destroy: function () {
            //this.element.removeStuff();
            // For UI 1.8, destroy must be invoked from the
            // base widget
            $.Widget.prototype.destroy.call(this);
            // For UI 1.9, define _destroy instead and don't
            // worry about calling the base widget
        },

        methodB: function ( event ) {
            //_trigger dispatches callbacks the plugin user can
            // subscribe to
            //signature: _trigger( "callbackName" , [eventObject],
            //  [uiObject] )
            // eg. this._trigger( "hover", e /*where e.type ==
            // "mouseenter"*/, { hovered: $(e.target)});
            this._trigger('methodA', event, {
                key: value
            });
        },

        methodA: function ( event ) {
            this._trigger('dataChanged', event, {
                key: value
            });
        },

        //Respond to any changes the user makes to the option method
        _setOption: function ( key, value ) {
            switch (key) {
            case "someValue":
                //this.options.someValue = doSomethingWith( value );
                break;
            default:
                //this.options[ key ] = value;
                break;
            }

            // For UI 1.8, _setOption must be manually invoked from
            // the base widget
            $.Widget.prototype._setOption.apply(this, arguments);
            // For UI 1.9 the _super method can be used instead
            // this._super( "_setOption", key, value );
        }
    });

})( jQuery, window, document );

//usage: $("#myelem").foo( options );

/* Some additional notes - delete this section before using the boilerplate.

 We can also self-init this widget whenever a new page in jQuery Mobile is created. jQuery Mobile's "page" plugin dispatches a "create" event when a jQuery Mobile page (found via data-role=page attr) is first initialized.

We can listen for that event (called "pagecreate" ) and run our plugin automatically whenever a new page is created.

$(document).bind("pagecreate", function (e) {
    // In here, e.target refers to the page that was created
    // (it's the target of the pagecreate event)
    // So, we can simply find elements on this page that match a
    // selector of our choosing, and call our plugin on them.
    // Here's how we'd call our "foo" plugin on any element with a
    // data-role attribute of "foo":
    $(e.target).find("[data-role='foo']").foo(options);

    // Or, better yet, let's write the selector accounting for the configurable
    // data-attribute namespace
    $(e.target).find(":jqmData(role='foo')").foo(options);
});

That's it. Now you can simply reference the script containing your widget and pagecreate binding in a page running jQuery Mobile site, and it will automatically run like any other jQM plugin.
 */

RequireJS And The jQuery UI Widget Factory

RequireJS is a script loader that provides a clean solution for encapsulating application logic inside manageable modules. It’s able to load modules in the correct order (through its order plugin); it simplifies the process of combining scripts via its excellent optimizer; and it provides the means for defining module dependencies on a per-module basis.

James Burke has written a comprehensive set of tutorials on getting started with RequireJS. But what if you’re already familiar with it and would like to wrap your jQuery UI widgets or plugins in a RequireJS-compatible module wrapper?.

In the boilerplate pattern below, we demonstrate how a compatible widget can be defined that does the following:

  • Allows the definition of widget module dependencies, building on top of the previous jQuery UI boilerplate presented earlier;
  • Demonstrates one approach to passing in HTML template assets for creating templated widgets with jQuery (in conjunction with the jQuery tmpl plugin) (View the comments in _create().)
  • Includes a quick tip on adjustments that you can make to your widget module if you wish to later pass it through the RequireJS optimizer
/*!
 * jQuery UI Widget + RequireJS module boilerplate (for 1.8/9+)
 * Authors: @jrburke, @addyosmani
 * Licensed under the MIT license
 */

// Note from James:
//
// This assumes you are using the RequireJS+jQuery file, and
// that the following files are all in the same directory:
//
// - require-jquery.js
// - jquery-ui.custom.min.js (custom jQuery UI build with widget factory)
// - templates/
//    - asset.html
// - ao.myWidget.js 

// Then you can construct the widget like so: 

//ao.myWidget.js file:
define("ao.myWidget", ["jquery", "text!templates/asset.html", "jquery-ui.custom.min","jquery.tmpl"], function ($, assetHtml) {

    // define your widget under a namespace of your choice
    // 'ao' is used here as a demonstration
    $.widget( "ao.myWidget", { 

        // Options to be used as defaults
        options: {}, 

        // Set up widget (e.g. create element, apply theming,
        // bind events, etc.)
        _create: function () {

            // _create will automatically run the first time
            // this widget is called. Put the initial widget
            // set-up code here, then you can access the element
            // on which the widget was called via this.element.
            // The options defined above can be accessed via
            // this.options

            //this.element.addStuff();
            //this.element.addStuff();
            //this.element.tmpl(assetHtml).appendTo(this.content);
        },

        // Destroy an instantiated plugin and clean up modifications
        // that the widget has made to the DOM
        destroy: function () {
            //t his.element.removeStuff();
            // For UI 1.8, destroy must be invoked from the base
            // widget
            $.Widget.prototype.destroy.call( this );
            // For UI 1.9, define _destroy instead and don't worry
            // about calling the base widget
        },

        methodB: function ( event ) {
            // _trigger dispatches callbacks the plugin user can
            // subscribe to
            //signature: _trigger( "callbackName" , [eventObject],
            // [uiObject] )
            this._trigger('methodA', event, {
                key: value
            });
        },

        methodA: function ( event ) {
            this._trigger('dataChanged', event, {
                key: value
            });
        },

        //Respond to any changes the user makes to the option method
        _setOption: function ( key, value ) {
            switch (key) {
            case "someValue":
                //this.options.someValue = doSomethingWith( value );
                break;
            default:
                //this.options[ key ] = value;
                break;
            }

            // For UI 1.8, _setOption must be manually invoked from
            // the base widget
            $.Widget.prototype._setOption.apply( this, arguments );
            // For UI 1.9 the _super method can be used instead
            //this._super( "_setOption", key, value );
        }

        //somewhere assetHtml would be used for templating, depending
        // on your choice.
    });
}); 

// If you are going to use the RequireJS optimizer to combine files
// together, you can leave off the "ao.myWidget" argument to define:
// define(["jquery", "text!templates/asset.html", "jquery-ui.custom.min"], …

Further Reading

Globally And Per-Call Overridable Options (Best Options Pattern)

For our next pattern, we’ll look at an optimal approach to configuring options and defaults for your plugin. The way you’re probably familiar with defining plugin options is to pass through an object literal of defaults to $.extend, as demonstrated in our basic plugin boilerplate.

If, however, you’re working with a plugin with many customizable options that you would like users to be able to override either globally or on a per-call level, then you can structure things a little differently.

Instead, by referring to an options object defined within the plugin namespace explicitly (for example, $fn.pluginName.options) and merging this with any options passed through to the plugin when it is initially invoked, users have the option of either passing options through during plugin initialization or overriding options outside of the plugin (as demonstrated here).

/*!
 * jQuery 'best options' plugin boilerplate
 * Author: @cowboy
 * Further changes: @addyosmani
 * Licensed under the MIT license
 */

;(function ( $, window, document, undefined ) {

    $.fn.pluginName = function ( options ) {

        // Here's a best practice for overriding 'defaults'
        // with specified options. Note how, rather than a
        // regular defaults object being passed as the second
        // parameter, we instead refer to $.fn.pluginName.options
        // explicitly, merging it with the options passed directly
        // to the plugin. This allows us to override options both
        // globally and on a per-call level. 

        options = $.extend( {}, $.fn.pluginName.options, options );

        return this.each(function () {

            var elem = $(this);

        });
    };

    // Globally overriding options
    // Here are our publicly accessible default plugin options
    // that are available in case the user doesn't pass in all
    // of the values expected. The user is given a default
    // experience but can also override the values as necessary.
    // eg. $fn.pluginName.key ='otherval';

    $.fn.pluginName.options = {

        key: "value",
        myMethod: function ( elem, param ) {

        }
    };

})( jQuery, window, document );

Further Reading

A Highly Configurable And Mutable Plugin

Like Alex Sexton’s pattern, the following logic for our plugin isn’t nested in a jQuery plugin itself. We instead define our plugin’s logic using a constructor and an object literal defined on its prototype, using jQuery for the actual instantiation of the plugin object.

Customization is taken to the next level by employing two little tricks, one of which you’ve seen in previous patterns:

  • Options can be overridden both globally and per collection of elements;
  • Options can be customized on a per-element level through HTML5 data attributes (as shown below). This facilitates plugin behavior that can be applied to a collection of elements but then customized inline without the need to instantiate each element with a different default value.

You don’t see the latter option in the wild too often, but it can be a significantly cleaner solution (as long as you don’t mind the inline approach). If you’re wondering where this could be useful, imagine writing a draggable plugin for a large set of elements. You could go about customizing their options like this:

javascript
$('.item-a').draggable({'defaultPosition':'top-left'});
$('.item-b').draggable({'defaultPosition':'bottom-right'});
$('.item-c').draggable({'defaultPosition':'bottom-left'});
//etc

But using our patterns inline approach, the following would be possible:

javascript
$('.items').draggable();
html
<li class="item" data-plugin-options='{"defaultPosition":"top-left"}'></div>
<li class="item" data-plugin-options='{"defaultPosition":"bottom-left"}'></div>

And so on. You may well have a preference for one of these approaches, but it is another potentially useful pattern to be aware of.

/*
 * 'Highly configurable' mutable plugin boilerplate
 * Author: @markdalgleish
 * Further changes, comments: @addyosmani
 * Licensed under the MIT license
 */

// Note that with this pattern, as per Alex Sexton's, the plugin logic
// hasn't been nested in a jQuery plugin. Instead, we just use
// jQuery for its instantiation.

;(function( $, window, document, undefined ){

  // our plugin constructor
  var Plugin = function( elem, options ){
      this.elem = elem;
      this.$elem = $(elem);
      this.options = options;

      // This next line takes advantage of HTML5 data attributes
      // to support customization of the plugin on a per-element
      // basis. For example,
      // <div class=item' data-plugin-options='{"message":"Goodbye World!"}'></div>
      this.metadata = this.$elem.data( 'plugin-options' );
    };

  // the plugin prototype
  Plugin.prototype = {
    defaults: {
      message: 'Hello world!'
    },

    init: function() {
      // Introduce defaults that can be extended either
      // globally or using an object literal.
      this.config = $.extend({}, this.defaults, this.options,
      this.metadata);

      // Sample usage:
      // Set the message per instance:
      // $('#elem').plugin({ message: 'Goodbye World!'});
      // or
      // var p = new Plugin(document.getElementById('elem'),
      // { message: 'Goodbye World!'}).init()
      // or, set the global default message:
      // Plugin.defaults.message = 'Goodbye World!'

      this.sampleMethod();
      return this;
    },

    sampleMethod: function() {
      // eg. show the currently configured message
      // console.log(this.config.message);
    }
  }

  Plugin.defaults = Plugin.prototype.defaults;

  $.fn.plugin = function(options) {
    return this.each(function() {
      new Plugin(this, options).init();
    });
  };

  //optional: window.Plugin = Plugin;

})( jQuery, window , document );

Further Reading

AMD- And CommonJS-Compatible Modules

While many of the plugin and widget patterns presented above are acceptable for general use, they aren’t without their caveats. Some require jQuery or the jQuery UI Widget Factory to be present in order to function, while only a few could be easily adapted to work well as globally compatible modules both client-side and in other environments.

For this reason, a number of developers, including me, CDNjs maintainer Thomas Davis and RP Florence, have been looking at both the AMD (Asynchronous Module Definition) and CommonJS module specifications in the hopes of extending boilerplate plugin patterns to cleanly work with packages and dependencies. John Hann and Kit Cambridge have also explored work in this area.

AMD

The AMD module format (a specification for defining modules where both the module and dependencies can be asynchronously loaded) has a number of distinct advantages, including being both asynchronous and highly flexible by nature, thus removing the tight coupling one commonly finds between code and module identity. It’s considered a reliable stepping stone to the module system proposed for ES Harmony.

When working with anonymous modules, the idea of a module’s identity is DRY, making it trivial to avoid duplication of file names and code. Because the code is more portable, it can be easily moved to other locations without needing to alter the code itself. Developers can also run the same code in multiple environments just by using an AMD optimizer that works with a CommonJS environment, such as r.js.

With AMD, the two key concepts you need to be aware of are the require method and the define method, which facilitate module definition and dependency loading. The define method is used to define named or unnamed modules based on the specification, using the following signature:

define(module_id /*optional*/, [dependencies], definition function /*function for instantiating the module or object*/);

As you can tell from the inline comments, the module’s ID is an optional argument that is typically required only when non-AMD concatenation tools are being used (it could be useful in other edge cases, too). One of the benefits of opting not to use module IDs is having the flexibility to move your module around the file system without needing to change its ID. The module’s ID is equivalent to folder paths in simple packages and when not used in packages.

The dependencies argument represents an array of dependencies that are required by the module you are defining, and the third argument (factory) is a function that’s executed to instantiate your module. A barebones module could be defined as follows:

// Note: here, a module ID (myModule) is used for demonstration
// purposes only

define('myModule', ['foo', 'bar'], function ( foo, bar ) {
    // return a value that defines the module export
    // (i.e. the functionality we want to expose for consumption)
    return function () {};
});

// A more useful example, however, might be:
define('myModule', ['math', 'graph'], function ( math, graph ) {
    return {
            plot: function(x, y){
                    return graph.drawPie(math.randomGrid(x,y));
            }
    };
});

The require method, on the other hand, is typically used to load code in a top-level JavaScript file or in a module should you wish to dynamically fetch dependencies. Here is an example of its usage:

// Here, the 'exports' from the two modules loaded are passed as
// function arguments to the callback

require(['foo', 'bar'], function ( foo, bar ) {
        // rest of your code here
});

// And here's an AMD-example that shows dynamically loaded
// dependencies

define(function ( require ) {
    var isReady = false, foobar;

    require(['foo', 'bar'], function (foo, bar) {
        isReady = true;
        foobar = foo() + bar();
    });

    // We can still return a module
    return {
        isReady: isReady,
        foobar: foobar
    };
});

The above are trivial examples of just how useful AMD modules can be, but they should provide a foundation that helps you understand how they work. Many big visible applications and companies currently use AMD modules as a part of their architecture, including IBM and the BBC iPlayer. The specification has been discussed for well over a year in both the Dojo and CommonJS communities, so it’s had time to evolve and improve. For more reasons on why many developers are opting to use AMD modules in their applications, you may be interested in James Burke’s article “On Inventing JS Module Formats and Script Loaders.�

Shortly, we’ll look at writing globally compatible modules that work with AMD and other module formats and environments, something that offers even more power. Before that, we need to briefly discuss a related module format, one with a specification by CommonJS.

CommonJS

In case you’re not familiar with it, CommonJS is a volunteer working group that designs, prototypes and standardizes JavaScript APIs. To date, it’s attempted to ratify standards for modules and packages. The CommonJS module proposal specifies a simple API for declaring modules server-side; but, as John Hann correctly states, there are really only two ways to use CommonJS modules in the browser: either wrap them or wrap them.

What this means is that we can either have the browser wrap modules (which can be a slow process) or at build time (which can be fast to execute in the browser but requires a build step).

Some developers, however, feel that CommonJS is better suited to server-side development, which is one reason for the current disagreement over which format should be used as the de facto standard in the pre-Harmony age moving forward. One argument against CommonJS is that many CommonJS APIs address server-oriented features that one would simply not be able to implement at the browser level in JavaScript; for example, io>, system and js could be considered unimplementable by the nature of their functionality.

That said, knowing how to structure CommonJS modules is useful so that we can better appreciate how they fit in when defining modules that might be used everywhere. Modules that have applications on both the client and server side include validation, conversion and templating engines. The way some developers choose which format to use is to opt for CommonJS when a module can be used in a server-side environment and to opt for AMD otherwise.

Because AMD modules are capable of using plugins and can define more granular things such as constructors and functions, this makes sense. CommonJS modules are able to define objects that are tedious to work with only if you’re trying to obtain constructors from them.

From a structural perspective, a CommonJS module is a reusable piece of JavaScript that exports specific objects made available to any dependent code; there are typically no function wrappers around such modules. Plenty of great tutorials on implementing CommonJS modules are out there, but at a high level, the modules basically contain two main parts: a variable named exports, which contains the objects that a module makes available to other modules, and a require function, which modules can use to import the exports of other modules.


// A very basic module named 'foobar'
function foobar(){
        this.foo = function(){
                console.log('Hello foo');
        }

        this.bar = function(){
                console.log('Hello bar');
        }
}

exports.foobar = foobar;

// An application using 'foobar'

// Access the module relative to the path
// where both usage and module files exist
// in the same directory

var foobar = require('./foobar').foobar,
    test   = new foobar.foo();

test.bar(); // 'Hello bar'

There are a number of great JavaScript libraries for handling module loading in AMD and CommonJS formats, but my preference is RequireJS (curl.js is also quite reliable). Complete tutorials on these tools are beyond the scope of this article, but I recommend John Hann’s post “curl.js: Yet Another AMD Loader,� and James Burke’s post “
LABjs and RequireJS: Loading JavaScript Resources the Fun Way
.�

With what we’ve covered so far, wouldn’t it be great if we could define and load plugin modules compatible with AMD, CommonJS and other standards that are also compatible with different environments (client-side, server-side and beyond)? Our work on AMD and UMD (Universal Module Definition) plugins and widgets is still at a very early stage, but we’re hoping to develop solutions that can do just that.

One such pattern we’re working on at the moment appears below, which has the following features:

  • A core/base plugin is loaded into a $.core namespace, which can then be easily extended using plugin extensions via the namespacing pattern. Plugins loaded via script tags automatically populate a plugin namespace under core (i.e. $.core.plugin.methodName()).
  • The pattern can be quite nice to work with because plugin extensions can access properties and methods defined in the base or, with a little tweaking, override default behavior so that it can be extended to do more.
  • A loader isn’t necessarily required at all to make this pattern fully function.

usage.html

<script type="text/javascript" src="http://code.jquery.com/jquery-1.6.4.min.js"></script>
<script type="text/javascript" src="pluginCore.js"></script>
<script type="text/javascript" src="pluginExtension.js"></script>

<script type="text/javascript">

$(function(){

    // Our plugin 'core' is exposed under a core namespace in
    // this example, which we first cache
    var core = $.core;

    // Then use use some of the built-in core functionality to
    // highlight all divs in the page yellow
    core.highlightAll();

    // Access the plugins (extensions) loaded into the 'plugin'
    // namespace of our core module:

    // Set the first div in the page to have a green background.
    core.plugin.setGreen("div:first");
    // Here we're making use of the core's 'highlight' method
    // under the hood from a plugin loaded in after it

    // Set the last div to the 'errorColor' property defined in
    // our core module/plugin. If you review the code further down,
    // you'll see how easy it is to consume properties and methods
    // between the core and other plugins
    core.plugin.setRed('div:last');
});

</script>

pluginCore.js

// Module/Plugin core
// Note: the wrapper code you see around the module is what enables
// us to support multiple module formats and specifications by
// mapping the arguments defined to what a specific format expects
// to be present. Our actual module functionality is defined lower
// down, where a named module and exports are demonstrated.
//
// Note that dependencies can just as easily be declared if required
// and should work as demonstrated earlier with the AMD module examples.

(function ( name, definition ){
  var theModule = definition(),
      // this is considered "safe":
      hasDefine = typeof define === 'function' && define.amd,
      // hasDefine = typeof define === 'function',
      hasExports = typeof module !== 'undefined' && module.exports;

  if ( hasDefine ){ // AMD Module
    define(theModule);
  } else if ( hasExports ) { // Node.js Module
    module.exports = theModule;
  } else { // Assign to common namespaces or simply the global object (window)
    (this.jQuery || this.ender || this.$ || this)[name] = theModule;
  }
})( 'core', function () {
    var module = this;
    module.plugins = [];
    module.highlightColor = "yellow";
    module.errorColor = "red";

  // define the core module here and return the public API

  // This is the highlight method used by the core highlightAll()
  // method and all of the plugins highlighting elements different
  // colors
  module.highlight = function(el,strColor){
    if(this.jQuery){
      jQuery(el).css('background', strColor);
    }
  }
  return {
      highlightAll:function(){
        module.highlight('div', module.highlightColor);
      }
  };

});

pluginExtension.js

// Extension to module core

(function ( name, definition ) {
    var theModule = definition(),
        hasDefine = typeof define === 'function',
        hasExports = typeof module !== 'undefined' && module.exports;

    if ( hasDefine ) { // AMD Module
        define(theModule);
    } else if ( hasExports ) { // Node.js Module
        module.exports = theModule;
    } else { // Assign to common namespaces or simply the global object (window)

        // account for for flat-file/global module extensions
        var obj = null;
        var namespaces = name.split(".");
        var scope = (this.jQuery || this.ender || this.$ || this);
        for (var i = 0; i < namespaces.length; i++) {
            var packageName = namespaces[i];
            if (obj && i == namespaces.length - 1) {
                obj[packageName] = theModule;
            } else if (typeof scope[packageName] === "undefined") {
                scope[packageName] = {};
            }
            obj = scope[packageName];
        }

    }
})('core.plugin', function () {

    // Define your module here and return the public API.
    // This code could be easily adapted with the core to
    // allow for methods that overwrite and extend core functionality
    // in order to expand the highlight method to do more if you wish.
    return {
        setGreen: function ( el ) {
            highlight(el, 'green');
        },
        setRed: function ( el ) {
            highlight(el, errorColor);
        }
    };

});

While this is beyond the scope of this article, you may have noticed that different types of require methods were mentioned when we discussed AMD and CommonJS.

The concern with a similar naming convention is, of course, confusion, and the community is currently split on the merits of a global require function. John Hann’s suggestion here is that rather than call it require, which would probably fail to inform users of the difference between a global and inner require, renaming the global loader method something else might make more sense (such as the name of the library). For this reason, curl.js uses curl, and RequireJS uses requirejs.

This is probably a bigger discussion for another day, but I hope this brief walkthrough of both module types has increased your awareness of these formats and has encouraged you to further explore and experiment with them in your apps.

Further Reading

What Makes A Good jQuery Plugin?

At the end of the day, patterns are just one aspect of plugin development. And before we wrap up, here are my criteria for selecting third-party plugins, which will hopefully help developers write them.

Quality
Do your best to adhere to best practices with both the JavaScript and jQuery that you write. Are your solutions optimal? Do they follow the jQuery core style guidelines? If not, is your code at least relatively clean and readable?

Compatibility
Which versions of jQuery is your plugin compatible with? Have you tested it with the latest builds? If the plugin was written before jQuery 1.6, then it might have issues with attributes, because the way we approach them changed with that release. New versions of jQuery offer improvements and opportunities for the jQuery project to improve on what the core library offers. With this comes occasional breakages (mainly in major releases) as we move towards a better way of doing things. I’d like to see plugin authors update their code when necessary or, at a minimum, test their plugins with new versions to make sure everything works as expected.

Reliability
Your plugin should come with its own set of unit tests. Not only do these prove your plugin actually works, but they can also improve the design without breaking it for end users. I consider unit tests essential for any serious jQuery plugin that is meant for a production environment, and they’re not that hard to write. For an excellent guide to automated JavaScript testing with QUnit, you may be interested in “Automating JavaScript Testing With QUnit,� by Jorn Zaefferer.

Performance
If the plugin needs to perform tasks that require a lot of computing power or that heavily manipulates the DOM, then you should follow best practices that minimize this. Use jsPerf.com to test segments of your code so that you’re aware of how well it performs in different browsers before releasing the plugin.

Documentation
If you intend for other developers to use your plugin, ensure that it’s well documented. Document your API. What methods and options does the plugin support? Does it have any gotchas that users need to be aware of? If users cannot figure out how to use your plugin, they’ll likely look for an alternative. Also, do your best to comment the code. This is by far the best gift you could give to other developers. If someone feels they can navigate your code base well enough to fork it or improve it, then you’ve done a good job.

Likelihood of maintenance
When releasing a plugin, estimate how much time you’ll have to devote to maintenance and support. We all love to share our plugins with the community, but you need to set expectations for your ability to answer questions, address issues and make improvements. This can be done simply by stating your intentions for maintenance in the README file, and let users decide whether to make fixes themselves.

Conclusion

Today, we’ve explored several time-saving design patterns and best practices that can be employed to improve your plugin development process. Some are better suited to certain use cases than others, but I hope that the code comments that discuss the ins and outs of these variations on popular plugins and widgets were useful.

Remember, when selecting a pattern, be practical. Don’t use a plugin pattern just for the sake of it; rather, spend some time understanding the underlying structure, and establish how well it solves your problem or fits the component you’re trying to build. Choose the pattern that best suits your needs.

And that’s it. If there's a particular pattern or approach you prefer taking to writing plugins which you feel would benefit others (which hasn't been covered), please feel free to stick it in a gist and share it in the comments below. I'm sure it would be appreciated.

Until next time, happy coding!

Thanks to John Hann, Julian Aubourg, Andree Hanson and everyone else who reviewed this post for their comments and feedback.

(al) (il)


© Addy Osmani for Smashing Magazine, 2011.


Supporting Your Product: How To Provide Technical Support





 



 


Whether your product is an open-source script, a Web application or a downloadable product, you will need to provide some form of technical support. This article explores the subject based on my experience of supporting our company’s product, Perch, a small content management system (CMS) that we sell as a download for people to install in their own hosting space. Our support has been a key factor in the success of this product, not just because users love responsive support, but because we have used what we have learned from users to improve the product.

Don’t Underestimate The Importance Of Support

As Eran Galperin says in “You’re Pricing It Wrong: Software Pricing Demystified� on Smashing Magazine:

“A commercial product that comes with support will often win over customers who want that assurance that someone will be on the other end of the line should they need it.”

Support can be a key selling point, a reason for a person to choose your product over the competition. In our case with Perch, the competition is often free software, so including unlimited support with a license is a big part of why someone might choose us over a competitor. Even for products aimed at technologically literate users, knowing that someone is on hand to answer questions or fix bugs can influence the decision to buy or sign up.

Don’t Underestimate The Time This Will Take

Users will always need support. You could have a bulletproof product and the most excellent tutorials and documentation, and someone will find a way to break it or just not read the information staring them in the face. Later in this article, I’ll explain some ways to minimize support requests and the time spent in dealing with them. But you should expect to offer support and build it into the price of your product.

Your support systems should also help you track the amount of time being taken up by support, so that you can plan for future requirements. If you are a small company whose product developers are supporting the product at present, knowing the amount of time each license or user requires for support on average will enable you to project when you might need to hire additional support staff.

Methods Of Providing Technical Support

When launching your product, decide how you will support it. Depending on the product and the people using it, you might offer some or all of the following types of support:

  • Phone,
  • Email,
  • Social media,
  • Ticketing system,
  • Real-time chat.

Phone

Supporting users by phone is time-consuming, but for some types of products, it can reassure potential buyers, particularly if they are not Internet-savvy or if the product handles sensitive information (for example, financial or health data). Users might trust the product more if they know they can speak to a real person. You can take phone support further by offering a remote-desktop feature to help customers right on their computer.

We chose not to offer phone support at Perch, because the support requests we get generally require us to look at a customer’s config file, diagnostic report or template code. So, an initial phone conversation would simply raise the cost of supporting customers, because we’d have to ask them to send this information by email or some other way.

If you do provide phone support, clearly state when it is available, including time-zone information. Also, keep track of the time you spend on this and the issues that customers raise so that you can combine it with the information that you collect via email or your online help desk.


Image source: Opensourceway.

Email

A lot of companies start with email support. Simply publish an email address, and answer queries as they come in. The advantages are that you don’t need any additional software, and everyone uses email. However, it gets tricky if you are not the only person supporting the product. If all of the support staff logs into the same mailbox, two people could very easily answer the same query, or a request could get ignored because everyone thinks someone else is dealing with it.

Email is also less than ideal for tracking requests over time and for working out the amount of time you spend dealing with them. You also need to be quite disciplined at filing away “closed� requests before your inbox descends into chaos.

If email is your predominant support mechanism, then consider setting up template responses to common requests, much as you would use canned responses in a help desk system (as I’ll describe below). Don’t forget to keep improving, adding to and correcting these responses as your website or product changes. Inadvertently giving out old advice is easy when these templates get out of date.

Social Media

Support via social media has become so important that many large companies are far more responsive on Twitter than via traditional means. Social media should be a part of your support system, but it shouldn’t be the only way that you help people. Being able to quickly respond to someone who is having a problem or has a question about your product is incredibly powerful. We have set up searches in our Twitter clients, so as soon as someone mentions Perch, we can respond. If a person mentions that they are trying out our demo, we simply say, “Let us know if you have any questions!� and we leave it at that. It is important that you not appear to hound potential customers; just give them a way to ask informally about anything on their mind.

If you have staff dedicated to support on Twitter, make sure they are empowered to help people. Many large companies have dedicated Twitter support personnel who only seem able to direct people to answers on the company website, which is often more frustrating than helpful! T-Mobile in the UK handles Twitter support very well via its @TMobileUKhelp account. Its support personnel is able to deal with most of the things that the phone-support operators handle, once the customer has verified their identity via direct message.

TMobileUkHelp on Twitter

Small companies can do social media really well, often better than large companies. If a customer is using Twitter to vent their frustration, a couple of quick and helpful messages can turn them from “I’m so annoyed� to “Wow! Support for this product is amazing!� People are generally very understanding about problems as long as they can get help quickly.

A lot of support requests are hard to deal with on Twitter, though. For example, at Perch, many questions require us to see the user’s code or to ask them to try something. In these cases, you need to be able to direct them to another channel, whether a ticketing system or even an email address. Long discussions over Twitter tend not to be very helpful; so, unless I can answer the query in one or two messages, I point the user to our ticketing system or forum, where I can pick up the conversation and provide better information.

Ticketing System

I would suggest that anyone with a commercial product use some kind of ticketing system. This support system can often be combined with the methods listed above. For example, many systems can turn incoming emails into tickets, or can log phone sessions in a useful format, or have an interface where users can submit tickets directly.

Ticketing systems make the process of providing support easier when multiple staff members are involved, because you can see whether a request is being responded to and who is working on it. They also make it far easier to keep track of the support requests coming in and how much time they are taking up.

To use a real-world case study, when we launched Perch just over two years ago, we started using a hosted software-as-a-service system called Tender. Tender is a fairly lightweight system that allows users to submit tickets that are either public (visible and answerable by anyone, not just support staff) or private (visible only to support staff).

We were happy with Tender, except for a couple of issues. First, we didn’t want our ticketing system to function as a forum, so we set up a separate forum elsewhere. But this meant that people had to look in two places for answers: the forum and the ticketing system. Our documentation was also located elsewhere. Secondly, because anyone could view and respond to support queries, we often saw customers themselves replying to tickets submitted by other customers; often the advice was helpful, but sometimes it was incorrect or confusing, and customers couldn’t tell the difference between official responses and responses from well-meaning customers. There wasn’t a way to stop this from happening other than to make all tickets private.

It became obvious that Tender, while a good system, just didn’t suit the model we wanted to use for support. This, it turns out, is key when selecting a support system — far more important than the feature list. When looking for a support system, decide first how you want to support your customers, then assess each system against that model to see whether it fits.

Having decided that our initial choice of Tender wasn’t quite working out, we made a list of what we wanted in a support system:

  1. A system with tickets and public forums all in one place (plus, the ability to publish documentation on the same system would be ideal);
  2. Excellent support for multiple people responding to issues;
  3. A system that can handle HTML and code examples being posted by customers and by us as responses;
  4. Statistics to enable us to track tickets, response times and so on.

We started to research, and we asked on Twitter which support systems people liked. Zendesk quickly rose to the top of the list, and were it not for a long-standing issue with code formatting, we would probably have used Zendesk. I really liked the integration of social media in the product; however, while this was a nice to have, the problem with the code snippets was a deal-breaker.

Zendesk website

We then looked at Assistly. It is another feature-rich system, but it felt a little too oriented around email and self-service for what we wanted. It felt a little impersonal in some ways, and our decision came down to it just not fitting our model and how we wanted Perch support to look and feel.

Finally we were pointed to HelpSpot. HelpSpot doesn’t have as many features “on paper� as the other two systems we looked at, but, crucially, it supports the combination of forums, tickets and documentation that we were looking for, thus enabling us to support customers the way we wanted. After trialling version 3 of the product, which was still in beta, we decided to move our tickets, forums and documentation to a self-hosted installation of HelpSpot.

Helpspot admin area

All of the systems we looked at are good systems with excellent features. Ultimately, it came down to which best suited our model for providing support. Having figured that out before testing the systems in trial, we were able to choose more easily between them, and we are still happy with our choice a few months after having made the switch.

Real-Time Chat

Real-time chat-based support is a feature of some ticketing systems, and is also available as a standalone service (as with Olark). We do use this with Perch, although primarily for pre-sales queries rather than for actual support. Like Twitter, it can be a really good way to quickly answer a question, but for longer answers and code samples, dealing with people in the main support area is much easier.

Olark chat window on the Perch website

Real-time support on websites can be helpful for companies that offer a service. With Olark, you can see exactly where someone is on your website as you are talking to them, so guiding someone through a potentially confusing process would be simple. It does, however, require that someone be available to provide this support should users come to rely on it. With a ticketing system, people expect some delay in getting a reply.

How To Reduce Support Requests And Time Spent Dealing With Them

You will never eliminate support requests completely, but you can do a lot to minimize them and to reduce the time you take in dealing with them.

Design Support Requests Out of Your Product

With Perch, we actively try to see support requests as an indication that something needs improvement or clarification in the product or related support material. By tracking requests and seeing where patterns emerge that show people running into problems in certain places, we are able to prevent the problem from occurring or provide better support material.

For example, before logging into your Perch admin account on your own website, you need to go to your account on the Perch website and specify the domain where Perch is installed. You can actually set two domains — the live and test ones — but before you can use Perch, you need to set at least one of these.

In the past, if you hadn’t set a domain in your account, then when logging in you got a message saying, “Sorry, your license key isn’t valid for this domain.�

License key error

People who didn’t fully read their email invoice might have missed the bit about setting up domains and so would have been confused when they saw this message, and thus submitted a support ticket. In an update to Perch, we changed this process so that if an administrator hadn’t yet entered any content, we could detect that they were a new user who just needed to configure their domains and so prompted them to do so (giving them the domain that they needed to register in their account). Support tickets were no longer submitted for this issue.

New license error

Designing support requests out of the product as much as possible obviously benefits us, because the less support we need to provide per license, the more profitable our product is. But it also gives our customers a better first experience with Perch. Being confused and needing support before even logging in isn’t a great first impression.

Build Debugging or Diagnostic Information Into the Product

Perch is a product that people download and install in their own hosting space. As you can imagine, we are now experts in the many bizarre ways that shared hosting providers configure PHP! We needed a way to get information from not very technical users about the environment in which they were running Perch. To do this, we created a diagnostics report that gives us a lot of information about the server that Perch is running on, which apps are installed, what their path to Perch is, and so on. The report, coupled with the user’s query, often gives us enough information to answer the support request right away.

Perch Diagnostics Report

Building in some diagnostic information that users can find and send to you could save a lot of back and forth, especially if your product or app is self-hosted and can be deployed in a variety of systems.

Add Features to the Product

If many of the people requesting support are asking about how to do something that your product doesn’t currently do, then it would be worth thinking about how you might accommodate this as a feature. While your ideas about what your product is and is not might be pretty fixed, you need to have some flexibility. In our case, Perch is “a really little CMS,� designed for small websites. When we launched, we thought that people wouldn’t need features such as undo, create drafts, edit drafts and previewing. It soon became apparent through support that our users very much wanted these features, and so we found a way to add them without bloating the software. Use your support requests to help guide development. Once it becomes obvious that someone is asking for something that Perch doesn’t do, we will often ask them, “How do you see this working?�

Provide a Range of Support Material

People learn how to use apps in a variety of ways. I like to read documentation and play around with code. For many people — especially visual learners — actually seeing things happen is much more helpful.

We were getting support requests from people who were obviously confused by our documentation. But we also heard people say how good our documentation was! What was going on? Blaming the first group for not understanding the documentation would be tempting — but once you decide to blame the user, you miss an opportunity to help people in different ways.

To help visual learners, we started a series of video tutorials. Currently, these videos just deal with the basics of using the product, but they have made a huge difference to the number of people we have to handhold through the website-building process. Frequently, we will point someone to the tutorial and then not hear from them again until we see the first post on their newly launched website. In the past, we might have seen a number of tickets from them during that process. The lesson here is to provide material in different formats and for different levels of users: bare documentation is important for technical users and for those who like to read quickly and get on with it; step-by-step examples and videos will help others.

Use a Support System That Lets You Create Template Answers

Often we need to ask people who request support for additional information, such as the diagnostics report mentioned above. HelpSpot lets us store these answers and punch them in as responses in one click, saving us time on the initial interaction. If you can reduce the time spent saying the same things, then you will have more time to dedicate to solving problems and working on the product.


Image source: Opensourceway.

How to Phase Out Support for Old Versions of a Product

If you sell desktop, phone or self-hosted Web software, rather than software as a service, you might need to consider what to do about supporting old versions of your product?

Traditional software companies tend to give users sufficient warning that support for an old product will end on a particular date. Security patches are often made available past that date if flaws are found in the old product, but no other fixes or changes are made. For example, Microsoft’s mainstream support for Windows XP Professional ended in 2009, although “Extended� support (which includes security patches) will continue until 2014.

The most important thing is to be fair to customers and give them plenty of notice of the end of a product version’s life. Your company needs to make decisions about the status of old versions far in advance of doing anything about it, and let customers know when support for an old version might end or be limited to critical security issues.

Some Final Thoughts

A question we are often asked at Perch is, “Is the support a nightmare?� It is all too easy for software developers to view support as a necessary evil, a part of the job to deal with as quickly as possible or even to outsource. If you approach support in this way, then you are missing out on a chance to make a real difference with people. You are also missing out on product improvements that you could have made by listening carefully to customer requests.

I firmly believe that software developers should provide their own support — perhaps not all of the support, if the product is popular or gets a lot of non-technical requests on the front line, but certainly some of it. It’s only by seeing the pain points firsthand and helping users through them that you can start figuring out how to solve them — and solving problems should be what we software developers do best.

Further Reading

(al)


© Rachel Andrew for Smashing Magazine, 2011.


WordPress Essentials: The Definitive Guide To WordPress Hooks





 



 


If you’re into WordPress development, you can’t ignore hooks for long before you have to delve into them head on. Modifying WordPress core files is a big no-no, so whenever you want to change existing functionality or create new functionality, you will have to turn to hooks.

wp-hooks-guide

In this article, I would like to dispel some of the confusion around hooks, because not only are they the way to code in WordPress, but they also teach us a great design pattern for development in general. Explaining this in depth will take a bit of time, but bear with me: by the end, you’ll be able to jumble hooks around like a pro.

Why Hooks Exist

I think the most important step in grasping hooks is to understand the need for them. Let’s create a version of a WordPress function that already exists, and then evolve it a bit using the “hooks mindset.�

   function get_excerpt($text, $length = 150) {
      $excerpt = substr($text,$length)
      return $excerpt;
   }

This function takes two parameters: a string and the length at which we want to cut it. What happens if the user wants a 200-character excerpt instead of a 150-character one? They just modify the parameter when they use the function. No problem there.

If you use this function a lot, you will notice that the parameter for the text is usually the post’s content, and that you usually use 200 characters instead of the default 150. Wouldn’t it be nice if you could set up new defaults, so that you didn’t have to add the same parameters over and over again? Also, what happens if you want to add some more custom text to the end of the excerpt?

These are the kinds of problems that hooks solve. Let’s take a quick look at how.

   function get_excerpt($text, $length = 150) {

      $length = apply_filters("excerpt_length", $length);

      $excerpt = substr($text,$length)
      return $excerpt;
   }

As you can see, the default excerpt length is still 150, but we’ve also applied some filters to it. A filter allows you to write a function that modifies the value of something — in this case, the excerpt’s length. The name (or tag) of this filter is excerpt_length, and if no functions are attached to it, then its value will remain 150. Let’s see how we can now use this to modify the default value.

   function get_excerpt($text, $length = 150) {

      $length = apply_filters("excerpt_length");

      $excerpt = substr($text,$length)
      return $excerpt;
   }

   function modify_excerpt_length() {
      return 200;
   }

   add_filter("excerpt_length", "modify_excerpt_length");

First, we have defined a function that does nothing but return a number. At this point, nothing is using the function, so let’s tell WordPress that we want to hook this into the excerpt_length filter.

We’ve successfully changed the default excerpt length in WordPress, without touching the original function and without even having to write a custom excerpt function. This will be extremely useful, because if you always want excerpts that are 200 characters long, just add this as a filter and then you won’t have to specify it every time.

Suppose you want to tack on some more text, like “Read on,� to the end of the excerpt. We could modify our original function to work with a hook and then tie a function to that hook, like so:

   function get_excerpt($text, $length = 150) {

      $length = apply_filters("excerpt_length");

      $excerpt = substr($text,$length)
      return apply_filters("excerpt_content", $excerpt);
   }

   function modify_excerpt_content($excerpt) {
      return $excerpt . "Read on…";
   }
   add_filter("excerpt_content", "modify_excerpt_content");

This hook is placed at the end of the function and allows us to modify its end result. This time, we’ve also passed the output that the function would normally produce as a parameter to our hook. The function that we tie to this hook will receive this parameter.

All we are doing in our function is taking the original contents of $excerpt and appending our “Read on� text to the end. But if we choose, we could also return the text “Click the title to read this article,� which would replace the whole excerpt.

While our example is a bit redundant, since WordPress already has a better function, hopefully you’ve gotten to grips with the thinking behind hooks. Let’s look more in depth at what goes on with filters, actions, priorities, arguments and the other yummy options available.

Filters And Actions

Filters and actions are two types of hooks. As you saw in the previous section, a filter modifies the value of something. An action, rather than modifying something, calls another function to run beside it.

A commonly used action hook is wp_head. Let’s see how this works. You may have noticed a function at the bottom of your website’s head section named wp_head(). Diving into the code of this function, you can see that it contains a call to do_action(). This is similar to apply_filters(); it means to run all of the functions that are tied to the wp_head tag.

Let’s put a copyright meta tag on top of each post’s page to test how this works.

   add_action("wp_head", "my_copyright_meta");

   function my_copyright_meta() {
      if(is_singular()){
         echo "";
      }
   }

The Workflow Of Using Hooks

While hooks are better documented nowadays, they have been neglected a bit until recently, understandably so. You can find some good pointers in the Codex, but the best thing to use is Adam Brown’s hook reference, and/or look at the source code.

Say you want to add functionality to your blog that notifies authors when their work is published. To do this, you would need to do something when a post is published. So, let’s try to find a hook related to publishing.

Can we tell whether we need an action or a filter? Sure we can! When a post is published, do we want to modify its data or do a completely separate action? The answer is the latter, so we’ll need an action. Let’s go to the action reference on Adam Brown’s website, and search for “Publish.�

The first thing you’ll find is app_publish_post. Sounds good; let’s click on it. The details page doesn’t give us a lot of info (sometimes it does), so click on the “View hook in source� link next to your version of WordPress (preferably the most recent version) in the table. This website shows only a snippet of the file, and unfortunately the beginning of the documentation is cut off, so it’s difficult to tell if this is what we need. Click on “View complete file in SVN� to go to the complete file so that we can search for our hook.

In the file I am viewing, the hook can be found in the _publish_post_hook() function, which — according to the documentation above it — is a “hook to schedule pings and enclosures when a post is published,â€� so this is not really what we need.

With some more research in the action list, you’ll find the publish_post hook, and this is what we need. The first thing to do is write the function that sends your email. This function will receive the post’s ID as an argument, so you can use that to pull some information into the email. The second task is to hook this function into the action. Look at the finished code below for the details.

   function authorNotification($post_id) {
      global $wpdb;
      $post = get_post($post_id);
      $author = get_userdata($post->post_author);

      $message = "
         Hi ".$author->display_name.",
         Your post, ".$post->post_title." has just been published. Well done!
      ";
      wp_mail($author->user_email, "Your article is online", $message);
   }
   add_action('publish_post', 'authorNotification');

Notice that the function we wrote is usable in its own right. It has a very specific function, but it isn’t only usable together with hooks; you could use it in your code any time. In case you’re wondering, wp_mail() is an awesome mailer function — have a look at the WordPress Codex for more information.

This process might seem a bit complicated at first, and, to be totally honest, it does require browsing a bit of documentation and source code at first, but as you become more comfortable with this system, your time spent researching what to use and when to use it will be reduced to nearly nothing.

Priorities

The third parameter when adding your actions and filters is the priority. This basically designates the order in which attached hooks should run. We haven’t covered this so far, but attaching multiple functions to a hook is, of course, possible. If you want an email to be sent to an author when their post is published and to also automatically tweet the post, these would be written in two separate functions, each tied to the same tag (publish_post).

Priorities designate which hooked function should run first. The default value is 10, but this can be changed as needed. Priorities usually don’t make a huge difference, though. Whether the email is sent to the author before the article is tweeted or vice versa won’t make a huge difference.

In rarer cases, assigning a priority could be important. You might want to overwrite the actions of other plugins (be careful, in this case), or you might want to enforce a specific order. I recently had to overwrite functionality when I was asked to optimize a website. The website had three to four plugins, with about nine JavaScript files in total. Instead of disabling these plugins, I made my own plugin that overwrote some of the JavaScript-outputting functionality of those plugins. My plugin then added the minified JavaScript code in one file. This way, if my plugin was deactivated, all of the other plugins would work as expected.

Specifying Arguments

The fourth argument when adding filters and actions specifies how many arguments the hooked function takes. This is usually dictated by the hook itself, and you will need to look at the source to find this information.

As you know from before, your functions are run when they are called by apply_filters() or do_action(). These functions will have the tag as their first argument (i.e. the name of the hook you are plugging into) and then passed arguments as subsequent arguments.

For example, the filter default_excerpt receives two parameters, as seen in includes/post.php.

   $post->post_excerpt = apply_filters( 'default_excerpt', $post_excerpt, $post );

The arguments are well named — $post_excerpt and $post — so it’s easy to guess that the first is the excerpt text and the second is the post’s object. If you are unsure, it is usually easiest either to look further up in the source or to output them using a test function (make sure you aren’t in a production environment).

   function my_filter_test($post_excerpt, $post) {
      echo "<pre>";
         print_r($post_excerpt);
         print_r($post);
      echo "</pre>";
   }
   add_filter("default_excerpt", "my_filter_test");

Variable Hook Names

Remember when we looked at the publish_post action? In fact, this is not used anymore; it was renamed in version 2.3 to {$new_status}_{$post->post_type}. With the advent of custom post types, it was important to make the system flexible enough for them. This new hook now takes an arbitrary status and post type (they must exist for it to work, obviously).

As a result, publish_post is the correct tag to use, but in reality, you will be using {$new_status}_{$post->post_type}. A few of these are around; the naming usually suggests what you will need to name the action.

Who Is Hooked On Who?

To find out which function hooks into what, you can use the neat script below, courtesy of WP Recipes. Use this function without arguments to get a massive list of everything, or add a tag to get functions that are hooked to that one tag. This is a great one to keep in your debugging tool belt!

function list_hooked_functions($tag=false){
 global $wp_filter;
 if ($tag) {
  $hook[$tag]=$wp_filter[$tag];
  if (!is_array($hook[$tag])) {
  trigger_error("Nothing found for '$tag' hook", E_USER_WARNING);
  return;
  }
 }
 else {
  $hook=$wp_filter;
  ksort($hook);
 }
 echo '<pre>';
 foreach($hook as $tag => $priority){
  echo "<br /><strong>$tag</strong><br />";
  ksort($priority);
  foreach($priority as $priority => $function){
  echo $priority;
  foreach($function as $name => $properties) echo "\t$name<br />";
  }
 }
 echo '</pre>';
 return;
}

Creating Your Own Hooks

A ton of hooks are built into WordPress, but nothing is stopping you from creating your own using the functions we’ve looked at so far. This may be beneficial if you are building a complex plugin intended for wide release; it will make your and other developers’ jobs a lot easier!

In the example below, I have assumed we are building functionality for users to post short blurbs on your website’s wall. We’ll write a function to check for profanity and hook it to the function that adds the blurbs to the wall.

Look at the full code below. The explanation ensues.

   function post_blurb($user_id, $text) {

      $text = apply_filters("blurb_text", $text);

      if(!empty($text)) {
         $wpdb->insert('my_wall', array("user_id" => $user_id, "date" => date("Y-m-d H:i:s"), "text" => $text), array("%d", %s", "%s"));
      }
   }

   function profanity_filter($text) {
      $text_elements = explode(" ", $text);
      $profanity = array("badword", "naughtyword", "inappropriatelanguage");

      if(array_intersect($profanity, $text_elements)) {
         return false;
      }
      else {
         return $text;
      }
   }

   add_filter("blurb_text", "profanity_filter");

The first thing in the code is the designation of the function that adds the blurb. Notice that I included the apply_filters() function, which we will use to add our profanity check.

Next up is our profanity-checking function. This checks the text as its argument against an array of known naughty words. By using array_intersect(), we look for array elements that are in both arrays — these would be the profane words. If there are any, then return false; otherwise, return the original text.

The last part actually hooks this function into our blurb-adding script.

Now other developers can hook their own functions into our script. They could build a spam filter or a better profanity filter. All they would need to do is hook it in.

Mixing And Matching

The beauty of this system is that it uses functions for everything. If you want, you can use the same profanity filter for other purposes, even outside of WordPress, because it is just a simple function. Already have a profanity-filter function? Copy and paste it in; all you’ll need to do is add the one line that actually hooks it in. This makes functions easily reusable in various situations, giving you more flexibility and saving you some time as well.

That’s All

Hopefully, you now fully understand how the hooks system works in WordPress. It contains an important pattern that many of us could use even outside of WordPress.

This is one aspect of WordPress that does take some time getting used to if you’re coming to it without any previous knowledge. The biggest problem is usually that people get lost in all of the filters available or in finding their arguments and so on, but with some patience this can be overcome easily. Just start using them, and you’ll be a master in no time!

(al)


© Daniel Pataki for Smashing Magazine, 2011.


16 Pixels: For Body Copy. Anything Less Is A Costly Mistake





 



 


16 Pixels

For Body Copy. Anything Less Is
A Costly Mistake

I know what you’re thinking. “Did he just say 16 pixels? For body copy? Obnoxiously big! 12 pixels is ideal for most websites.�

I’d like to persuade you otherwise.

As usability expert Oliver Reichenstein says in “The 100% Easy-2-Read Standard�:

[16 pixels] is not big. It’s the text size browsers display by default. It’s the text size browsers were intended to display… It looks big at first, but once you use it you quickly realize why all browser makers chose this as the default text size.

In this article, I’ll explain why 16 pixels should generally be the minimum size for body copy in modern Web design. If I don’t change your mind, perhaps you could chip in at the end and let me know why.

You see, in most cases, if you’re building websites with the font size set between 10 and 15 pixels, you are costing your clients money. And I aim to prove it.

Readership = Revenue

If you’re building a website for someone — even yourself — chances are its purpose is to make money.

Perhaps it’s to sell a product directly, or to offer a service, or just to generate leads. Whatever the case, it’s a business asset, and ultimately it has to generate a return on investment. It has to fulfill a revenue goal.

So, every element should be designed to achieve that goal. Including the copy. Especially the copy — because the copy is what convinces visitors to do whatever it is you want them to do on the website.

Think about it. If you don’t explain what people should do, or why they should do it, then they certainly won’t. And the only way to tell them is with text. And text means reading.

Important Facts About Reading

There are some particular findings that are pivotal to issues such as readership and readability and comprehension, which is really what body copy is all about. If people won’t read it, or if they can’t read it or understand it, then what’s the point of having it?

  1. At age 40, only half the light gets through to the retina as it did at age 20. For 60-year-olds, it’s just 20%.
  2. Nearly 9% of Americans are visually impaired, meaning their vision cannot be completely corrected with lenses.
  3. The distance at which we can read letters is a common measure of both legibility and reading speed. The greater the distance, the higher the overall legibility and comprehension are considered to be. The biggest factor that determines how far this distance can increase is font size. Seen any billboards lately?
  4. Most people, when sitting comfortably, are about 20 to 23 inches from their computer screens. In fact, 28 inches is the recommended distance, because this is where vergence is sufficiently low to avoid eye strain. This is much further than the distance at which we read printed text — most people do not hold magazines at arm’s length!
  5. 16-pixel text on a screen is about the same size as text printed in a book or magazine; this is accounting for reading distance. Because we read books pretty close — often only a few inches away — they are typically set at about 10 points. If you were to read them at arm’s length, you’d want at least 12 points, which is about the same size as 16 pixels on most screens:
    16-pixel text displayed on a 24-inch screen, next to 12-point text printed on paper.

    16-pixel text displayed on a 15.4-inch screen, next to 12-point text printed on paper.
  6. In a 2005 survey of Web design problems, bad fonts got nearly twice as many votes as the next contender, with two-thirds of voters complaining about small font sizes. If you think the situation has improved since then, think again. I randomly sampled some new blog designs on SiteInspire and found that the average font size for body copy was a measly 12 pixels. Some designs even used a minuscule 10 pixels. And none were over a weaksauce 14 pixels. Similarly, if you randomly sampled offerings on the popular Elegant Themes and ThemeForest, you’d find that every single theme sets the main content at just 12 or 13 pixels.

Fact: Most Web Users Hate The “Normal� Font Size

With this research in mind, let me ask: how many of your client’s readers are around 40? Because they have to work twice as hard to read as 20-year-olds. If they’re closer to 60, they have to work four times as hard.

Almost 1 in 10 of your readers also has trouble with their eyes. Of the rest who don’t, most will still have to strain to read text smaller than 16 pixels, even if they don’t notice that they’re doing it. (How often do you find yourself hunching over the screen?) And that’s if they’re leaning close, which they would likely find awkward and unergonomic. Their natural sitting position will be at least an arm’s length from the screen!

In short, for the average Web user, reading most websites is not unlike taking an eye exam.

The harder your text is to read, the less of it will get read — and the less of what is read will be understood. 10 pixels is essentially pointless. 12 pixels is still much too small for most readers. Even 15 pixels will turn off visitors who might have otherwise converted.

Thus, we can conclude that if you want the maximum number of people to read, understand and act on your text, then you need to set it at a minimum size of 16 pixels.

“But Users Can Zoom�

If you code it right, people with vision issues can always use the Option and + keys to enlarge the text.

Thus spake one Web designer in a discussion I had on this very issue.

Not so. The users who will most need to adjust their settings usually don’t know how. And the users who do… well, they’ll probably just take the easier path by hitting the “Back� button. It goes without saying that we shouldn’t take our clients’ money and then design websites for them that will make their visitors uncomfortable. Our personal tastes are not more important than best practices in usability.

Web design is not about what designers like. It is about what users want and what will best achieve our client’s goals.

If the objective of a client’s website is to achieve some revenue goal, then our role as designers is to come up with something to achieve that goal as effectively as possible. Picking a font size that we know most users will struggle to read, a font size that will reduce readership, a font size that will ultimately cost conversions, is not good choice.

In print, type as small as 8 points is an ideal compromise between readability and cost, because you have to pay for every millimeter you use. On the Web, you pay nothing for using more space — provided that readers find your copy compelling, of course. What you do pay for is readers finding your compelling copy so hard to read that they click away instead of converting.

So, the question is, are you prepared to cost your clients money for the sake of what looks good to you?

16 Pixels Is Not Big

Our tastes and aesthetic preferences as designers are a lot more malleable than we think. What “looks good� to us is largely the result of what we’ve seen other designers doing and what we’ve come to expect.

Unfortunately, most of the websites we’ve seen are packed with tiny copy, because once upon a time screens were tiny, and so designers matched them with tiny text — but no one got out of the habit.

This article is set in TeX Gyre Schola at 19 pixels. I picked this size because 16 to 18 pixels looked too small to me: as I sat back comfortably in my chair, 28 inches from the screen, I found myself squinting to see it. If I’d used Georgia or Verdana, 16 pixels probably would have been fine: they were designed with a larger x-height and so display better on screen.

Now, check out the footer just below and see whether you don’t hunch forward automatically, screw up your eyes and furrow your brow. That’s 12 pixels for ya. And if you still disagree after that, tell me why in the comments.

Bnonn and his daughter

Bnonn is the author of a series of free videos on creating websites that capture readers and turn them into customers. Known in the boroughs as the Information Highwayman, he helps people sell more online by improving their copy and design. When he’s not knee-deep in the guts of someone’s home page, he is teaching his kids about steampunk, Nathan Fillion, and how to grapple a zombie without getting bit.


© D Bnonn Tennant for Smashing Magazine, 2011.


  •   
  • Copyright © 1996-2010 BlogmyQuery - BMQ. All rights reserved.
    iDream theme by Templates Next | Powered by WordPress