Upgrade to Pro — share decks privately, control downloads, hide ads and more …

jQuery Plugins: Beginner to Advanced

Doug Neiner
October 28, 2011

jQuery Plugins: Beginner to Advanced

You may think that jQuery plugins are just pieces of code that other developers release and you use. However, jQuery plugins are an incredible way to structure your website and web application code to be as reusable as possible. In this workshop you will learn how to write your first jQuery plugin, how to add more advanced options and functionality to your plugins, how to minimize configuration by writing contextual code, and finally, how to write advanced widgets using the jQuery UI Widget Factory. No prior plugin knowledge is required for this course, but a basic understanding of jQuery is required.

Doug Neiner

October 28, 2011
Tweet

More Decks by Doug Neiner

Other Decks in Programming

Transcript

  1. WRITING JQUERY PLUGINS DOUG NEINER
    WRITING JQUERY PLUGINS
    BEGINNER ADVANCED
    TO

    View Slide

  2. WRITING JQUERY PLUGINS DOUG NEINER
    dougneiner
    [email protected]
    dcneiner
    Doug Neiner
    Doug Neiner

    View Slide

  3. WRITING JQUERY PLUGINS DOUG NEINER
    I

    View Slide

  4. WRITING JQUERY PLUGINS DOUG NEINER
    Crystal
    Ruby, Olivia,
    Cody
    Not pictured:
    Ditto the cat
    Jasper the dog
    My Family

    View Slide

  5. WRITING JQUERY PLUGINS DOUG NEINER
    BASIC PLUGINS
    Lecture #1

    View Slide

  6. WRITING JQUERY PLUGINS DOUG NEINER
    WHAT IS A JQUERY PLUGIN?
    • An awesome library approved by the jQuery team
    and used by millions?
    • Code you found useful and decided to release to
    the public?
    • Something other people write, and you use?

    View Slide

  7. WRITING JQUERY PLUGINS DOUG NEINER
    WHAT IS A JQUERY PLUGIN?
    • A jQuery plugin is any reusable piece of JavaScript
    code that depends on jQuery.
    • Many jQuery plugins extend $.fn to provide
    functionality to jQuery result sets.
    • It is simply another method of code organization.
    • You should be writing and using your plugins in
    your projects now!

    View Slide

  8. WRITING JQUERY PLUGINS DOUG NEINER
    STEP 1: PROTECT THE $
    // Out here, $ may not be equal to jQuery
    ( function ( $ ) {
    ! // In here, $ is equal to jQuery
    }( jQuery ));
    IIFE: IMMEDIATELY INVOKING FUNCTION EXPRESSION

    View Slide

  9. WRITING JQUERY PLUGINS DOUG NEINER
    STEP 2: ADD THE PLUGIN METHOD
    ( function ( $ ) {
    $.fn.myPlugin = function () {
    };
    }( jQuery ));
    BE SURE TO PICK A UNIQUE NAME TO AVOID CONFLICTS

    View Slide

  10. WRITING JQUERY PLUGINS DOUG NEINER
    JQUERY MAGIC
    • In order to run this:
    $( "div.findSomething" ).doSomething();
    • This method would be defined:
    $.fn.doSomething
    • Its not magic, its the prototype of jQuery
    • $.fn is just an alias for the prototype

    View Slide

  11. WRITING JQUERY PLUGINS DOUG NEINER
    STEP 3: RETURN THIS
    ( function ( $ ) {
    $.fn.myPlugin = function () {
    ! return this.each( function ( i, el ) {
    ! });
    };
    }( jQuery ));
    CHAINING DEPENDS ON YOU HONORING THE SYSTEM

    View Slide

  12. WRITING JQUERY PLUGINS DOUG NEINER
    MORE MAGIC: CHAINING
    • this is already a jQuery object
    • End the plugin by returning this to support
    chaining
    • 90% of the time, you want to support chaining
    • $( "#el" ).show().yourPlugin().delay( 900 ).slideUp();
    • For the other 10%, there is only one situation where
    you shouldn't support chaining:
    • If your plugin method needs to return a value, it cannot chain

    View Slide

  13. WRITING JQUERY PLUGINS DOUG NEINER
    STEP 3A: ADD CODE
    ( function ( $ ) {
    $.fn.myPlugin = function () {
    ! return this.each( function ( i, el ) {
    ! ! // Your code goes here
    ! ! // this == el, so $( el ) to use jQuery methods
    ! ! $( el ).addClass( "button" )
    ! ! .append( "" );
    ! });
    };
    }( jQuery ));

    View Slide

  14. WRITING JQUERY PLUGINS DOUG NEINER
    WAIT! EACH ISN'T ALWAYS NEEDED
    ( function ( $ ) {
    $.fn.myPlugin = function () {
    ! return this.addClass( "button" )
    ! ! .append( "" );
    };
    }( jQuery ));
    IMPLICIT ITERATION IS RESPONSIBLE FOR THIS

    View Slide

  15. WRITING JQUERY PLUGINS DOUG NEINER
    STEP 3B: ADD MORE CODE
    ( function ( $ ) {
    $.fn.myPlugin = function () {
    ! return this.each( function ( i, el ) {
    ! ! var $el = $( el );
    ! ! if ( !$el.hasClass( "button" ) {
    ! ! ! $el.addClass( "button" )
    ! ! ! .append( "" );
    ! ! }
    ! });
    };
    }( jQuery ));

    View Slide

  16. WRITING JQUERY PLUGINS DOUG NEINER
    STEP 4A: ADDING OPTIONS
    ( function ( $ ) {
    $.fn.myPlugin = function () {
    ! return this.each( function ( i, el ) {
    ! ! var $el = $( el );
    ! ! if ( !$el.hasClass( "button" ) {
    ! ! ! $el.addClass( "button" )
    ! ! ! .append( "" );
    ! ! }
    ! });
    };
    $.fn.myPlugin.defaults = {
    ! buttonClass: "button",
    ! iconMarkup: ""
    };
    }( jQuery ));

    View Slide

  17. WRITING JQUERY PLUGINS DOUG NEINER
    STEP 4B: MERGING OPTIONS
    ( function ( $ ) {
    $.fn.myPlugin = function ( options ) {
    ! options = $.extend( {}, $.fn.myPlugin.defaults, options );
    ! return this.each( function ( i, el ) {
    ! ! var $el = $( el );
    ! ! if ( !$el.hasClass( "button" ) {
    ! ! ! $el.addClass( "button" )
    ! ! ! .append( "" );
    ! ! }
    ! });
    };
    $.fn.myPlugin.defaults = {
    ! buttonClass: "button",
    ! iconMarkup: ""
    };

    View Slide

  18. WRITING JQUERY PLUGINS DOUG NEINER
    STEP 4C: USING OPTIONS
    ( function ( $ ) {
    $.fn.myPlugin = function ( options ) {
    ! options = $.extend( {}, $.fn.myPlugin.defaults, options );
    ! return this.each( function ( i, el ) {
    ! ! var $el = $( el );
    ! ! if ( !$el.hasClass( options.buttonClass ) {
    ! ! ! $el.addClass( options.buttonClass )
    ! ! ! .append( options.iconMarkup );
    ! ! }
    ! });
    };
    $.fn.myPlugin.defaults = {
    ! buttonClass: "button",
    ! iconMarkup: ""
    };
    }( jQuery ));

    View Slide

  19. WRITING JQUERY PLUGINS DOUG NEINER
    BASIC PLUGIN REVIEW
    1. Protect $ by wrapping the plugin in an IIFE
    2. Add your method to $.fn
    3. Be sure to return this
    4. Add options to further abstract the code

    View Slide

  20. WRITING JQUERY PLUGINS DOUG NEINER
    WHAT ABOUT $.EXTEND…
    // Some plugins use this form of adding to $.fn
    $.extend( $.fn, {
    myPlugin: function () {
    return this;
    }
    });
    1. Good if you plan to add a ton of plugin methods
    2. Don't add a ton of plugin methods

    View Slide

  21. WRITING JQUERY PLUGINS DOUG NEINER
    CRAFTING AN API
    // Though less common, some times adding additional
    // parameters (in addition to options) is a smart decision
    $.fn.myPlugin = function ( required, options ) { … });
    $.fn.option = function ( key, value ) { … });
    .option(); // Returns all the options (Breaks the chain)
    .option( key ); // Returns just the key (Breaks the chain)
    .option( key, value ); // Sets the value
    .option( { "key": val, "key2": val }); // Sets multiple values
    IN THE END, ITS UP TO YOU: BUT FOLLOWING
    CONVENTIONS MAKES IT EASIER TO RELEASE LATER

    View Slide

  22. WRITING JQUERY PLUGINS DOUG NEINER
    BASIC PLUGINS
    Code Assignment #1

    View Slide

  23. WRITING JQUERY PLUGINS DOUG NEINER
    WRITE A SIMPLE JQUERY PLUGIN
    • Ideas
    • Abstract a complex animation
    • Make a plugin that enhances markup for a form
    • Make a plugin that checks if a form is valid

    View Slide

  24. WRITING JQUERY PLUGINS DOUG NEINER
    ( function ( $ ) {
    $.fn.myPlugin = function ( options ) {
    ! options = $.extend( {}, $.fn.myPlugin.defaults, options );
    !
    ! return this.each( function ( i, el ) {
    ! ! var $el = $( el );
    ! ! if ( !$el.hasClass( options.buttonClass ) {
    ! ! ! $el.addClass( options.buttonClass )
    ! ! ! .append( options.iconMarkup );
    ! ! }
    ! });
    };
    $.fn.myPlugin.defaults = {
    ! buttonClass: "button",
    ! iconMarkup: ""
    };
    }( jQuery ));

    View Slide

  25. WRITING JQUERY PLUGINS DOUG NEINER
    EFFECTIVE OPTIONS
    Lecture #2

    View Slide

  26. WRITING JQUERY PLUGINS DOUG NEINER
    VALUE OF A PLUGIN
    • A plugin is only as powerful as its API, and the
    options your support.
    • More options != more power
    • Too many options can bloat your plugin, so add
    them carefully and with a lot of thought.

    View Slide

  27. WRITING JQUERY PLUGINS DOUG NEINER
    TYPES OF OPTIONS
    • Plain value options
    • Strings and Numbers
    • DOM Selection options
    • String selector, DOM object, jQuery Object
    • Callbacks
    • Fire after certain events
    • Rich Callbacks
    • The plugin depends on the callback for functionality

    View Slide

  28. WRITING JQUERY PLUGINS DOUG NEINER
    PLAIN VALUE
    options = {
    animSpeed: 5000, // Defaults to 5 seconds
    defaultText: "RIA Unleashed is awesome!"
    }
    DEFAULT
    USE IN PLUGIN
    $( el ).slideDown( options.animSpeed, function () {
    this.innerHTML = options.defaultText;
    });

    View Slide

  29. WRITING JQUERY PLUGINS DOUG NEINER
    DOM SELECTION
    defaults = {
    listItems: "ul li",
    listItems: liObj,
    listItems: $( "ul li" )
    };
    DEFAULT
    USE IN PLUGIN
    var items = options.listItems;
    if ( items && !items.jquery ) {
    items = $( items );
    }

    View Slide

  30. WRITING JQUERY PLUGINS DOUG NEINER
    CALLBACKS
    defaults = {
    onClick: null
    };
    DEFAULT
    USE IN PLUGIN
    $( el ).click( function ( e ) {
    e.preventDefault();
    // Do something
    if ( $.isFunction( options.onClick ) ) {
    options.onClick.apply( this, arguments );
    }
    });

    View Slide

  31. WRITING JQUERY PLUGINS DOUG NEINER
    CALLBACKS (ALT)
    defaults = {
    onClick: $.noop // $.noop == function () { }
    };
    DEFAULT
    USE IN PLUGIN
    $( el ).click( function ( e ) {
    e.preventDefault();
    // Do something
    options.onClick.apply( this, arguments );
    });

    View Slide

  32. WRITING JQUERY PLUGINS DOUG NEINER
    RICH CALLBACKS
    defaults = {
    renderItem: function ( text, type ) {
    return "" + text + "";
    }
    };
    DEFAULT
    USE IN PLUGIN
    $.each( keys, function ( key, text ) {
    var html = options.renderItem( item, key );
    // Do something
    });

    View Slide

  33. WRITING JQUERY PLUGINS DOUG NEINER
    WIDGETS
    Lecture #3

    View Slide

  34. WRITING JQUERY PLUGINS DOUG NEINER
    LIMITATIONS OF BASIC PLUGINS
    • They don't maintain state very well
    • Very difficult to influence after the plugin has run
    • They don't tend to be able to be destroyed
    • They cannot be 'inherited' to adjust function

    View Slide

  35. WRITING JQUERY PLUGINS DOUG NEINER
    THE WIDGET FACTORY
    • Part of jQuery UI: jquery.ui.widget.js
    • If you are using jQuery UI, you already can use it
    • Can be included in your own plugins (only 1.14KB
    minified and gzipped) for projects not use jQuery UI
    • Provides a rich API for stateful plugins (widgets)
    • Provides a unified API – allows users to use your
    plugin easier

    View Slide

  36. WRITING JQUERY PLUGINS DOUG NEINER
    DEFINING A WIDGET
    $.widget( "namespace.pluginName", {
    options: {
    key: "value"
    },
    … methods go here …
    });

    View Slide

  37. WRITING JQUERY PLUGINS DOUG NEINER
    WHAT WE GET FOR FREE
    // Our widget object:
    $.namespace.pluginName;
    // A jQuery plugin for creating/interacting with our widget
    $.fn.pluginName;
    // A custom selector (Though use sparingly)
    $( ":namespace-pluginName" );

    View Slide

  38. WRITING JQUERY PLUGINS DOUG NEINER
    THE WIDGET API
    // First call, with options, creates the widget
    $( "div" ).pluginName( { key: "value" } );
    // Subsequent calls modify or call methods on the widget
    // Set an option
    $( "div" ).pluginName( "option", "key", "newValue" );
    // Get an option
    $( "div" ).pluginName( "option", "key" );
    // Run a method
    $( "div" ).pluginName( "myMethod", "parameter1" );
    // Destroy the widget
    $( "div" ).pluginName( "destroy" );

    View Slide

  39. WRITING JQUERY PLUGINS DOUG NEINER
    BASIC LIFE CYCLE
    • _create()
    • _init()
    • _setOptions & _setOption
    called as options are changed
    • destroy()
    Called directly or when element is removed

    View Slide

  40. WRITING JQUERY PLUGINS DOUG NEINER
    SPECIAL PROPERTIES
    • this.element
    the jQuery wrapped DOM element the widget was created on.
    • this.options
    Allows you to quickly access the options on the widget
    • this.widgetName
    The "pluginName" portion of your widget
    • this.widgetEventPrefix
    Also the "pluginName" portion of your widget
    • this.widgetBaseClass
    "namespace-pluginName" - just like the declaration but with a
    dash instead of a dot.

    View Slide

  41. WRITING JQUERY PLUGINS DOUG NEINER
    SETUP AND TEARDOWN
    $.widget( "namespace.pluginName", {
    options: {
    key: "value"
    },
    // No "super" version of this worth calling
    _create: function () {
    this.element.addClass( this.widgetBaseClass );
    },
    … methods go here …
    destroy: function () {
    this.element.removeClass( this.widgetBaseClass );
    $.Widget.prototype.destroy.apply( this, arguments );
    }
    });

    View Slide

  42. WRITING JQUERY PLUGINS DOUG NEINER
    CALLING "SUPER"
    // In jQuery UI 1.8.x, this is how you call a "super" method
    methodName: function () {
    $.Widget.prototype.methodName.apply( this, arguments );
    }

    View Slide

  43. WRITING JQUERY PLUGINS DOUG NEINER
    OPTIONS
    $( "div" ).pluginName( "option", hash OR key, value );
    EVERY OPTION SHOULD BE CHANGEABLE AT RUN TIME
    _setOptions: function ( values ) {
    $.Widget.prototype._setOptions.apply( this, arguments );
    // Do something once after options are set
    },
    _setOption: function ( key, value ) {
    $.Widget.prototype._setOption.apply( this, arguments );
    if ( key === "visible" ) {
    // Do something specific
    }
    }

    View Slide

  44. WRITING JQUERY PLUGINS DOUG NEINER
    PUBLIC AND "PRIVATE" METHODS
    • Any method starting with an `_` underscore, cannot
    be called using the .pluginName( "method") syntax
    • Methods without an underscore can be called using
    that syntax

    View Slide

  45. WRITING JQUERY PLUGINS DOUG NEINER
    EVENT BINDING
    this.element.bind( "click." + this.widgetName, function () {
    // Do something
    });
    this.element.delegate(
    "ul li",
    "click." + this.widgetName,
    function () {
    // Do something
    });
    this.element.bind( "click." + this.widgetName, function () {
    // Do something
    });

    View Slide

  46. WRITING JQUERY PLUGINS DOUG NEINER
    WIDGETS I
    Code Assignment #2

    View Slide

  47. WRITING JQUERY PLUGINS DOUG NEINER
    50% complete Submit
    Question text here Yes No
    Question text here Yes No
    Question text here Yes No
    Question text here Yes No
    Question text here Yes No
    Question text here Yes No
    Question text here Yes No
    Question text here Yes No

    View Slide

  48. WRITING JQUERY PLUGINS DOUG NEINER
    $.widget( "namespace.pluginName", {
    options: {
    key: "value"
    },
    // No "super" version of this worth calling
    _create: function () {
    this.element.addClass( this.widgetBaseClass );
    },
    … methods go here …
    destroy: function () {
    this.element.removeClass( this.widgetBaseClass );
    $.Widget.prototype.destroy.apply( this, arguments );
    }
    });

    View Slide

  49. WRITING JQUERY PLUGINS DOUG NEINER
    dougneiner
    [email protected]
    dcneiner
    Doug Neiner
    Doug Neiner

    View Slide