A variety of jQuery plugin patterns for jump starting your plugin development

Overview

jQuery Plugin Patterns Build Status

So, you've tried out jQuery Boilerplate or written a few of your own plugins before. They work to a degree and are readable, but you're interested in learning if there are better ways your plugin can be structured.

Perhaps you're just looking for something that works better with the jQuery UI Widget factory, RequireJS or has built-in support for Publish/Subscribe. This repo hopes to provide a number of alternative boilerplates for kick-starting your jQuery plugin development catered towards the intermediate to advanced developer.

This project won't seek to provide implementations for every possible pattern, but will attempt to cover popular patterns developers often use in the wild.

Patterns

  • A lightweight start: perfect as a generic template for beginners and above, uses a basic defaults object, simple constructor for assigning the element to work with and extending options with defaults and a lightweight wrapper around the constructor to avoid issues with multiple instantiations
  • Widget factory: for building complex, stateful plugins based on object-oriented principles. The majority of jQueryUI heavily relies on the widget factory as a base for components and this template covers almost all supported default methods including triggering events
  • Widget factory + RequireJS: for wrapping jQueryUI widgets inside RequireJS compatible modules. Also demonstrates very basic widget templating
  • Widget factory for jQuery mobile - demonstrating best practices for building mobile widgets, includes many of the same concepts as the widget factory boilerplate, but also JQM specific usage advice/tips in the comments
  • Namespaced pattern: to avoid collisions and improve code organization when working with components under another namespace
  • Best options: globally/Per-call overridable options for greater option customization, based on Ben Almans pluginization talk
  • Custom events (Publish/Subscribe): for better application decoupling. Uses the Widget factory, but could be applied to the generic template
  • Extend pattern: Extended options
  • Non Widget-factory widget: if you wish to stay away from the widget factory. Uses Ben Alman’s simplewidget including coverage for creation, instantiation and other best practices that may be helpful
  • Prototypal inheritance pattern: use a bridge to generate a plugin from an object (literal). Useful for code organization, readability, functionality heavily based around DOM element selection
  • Universal Module Definition pattern: create AMD and CommonJS compatible plugin modules which are compatible with a number of different script loaders. You may also be interested in the UMD project.

Further reading

More information about the patterns in this repo can be found in Learning JavaScript Design Patterns.

Contributing

If you have ideas for improvements that can be made to patterns currently in the repo, please feel free to create a new issue for discussion or send a pull request upstream. The same can be said about new patterns you wish to propose being added; for the sake of limiting confusion and complexity, I would ideally like to keep the number of overall patterns in the repo, but there are plans to separate these out into folders based on concerns.

Team

jQuery Patterns was made with love by these people and a bunch of awesome contributors.

Addy Osmani | Zeno Rocha --- | --- | --- | --- | --- | --- | --- Addy Osmani | Zeno Rocha

Credits

Thanks to @peol, @ajpiano, @mathias, @cowboy, @dougneiner and others for their previous work (or tips) in this area. Some of this work is used as a basis for further improvements.

Comments
  • Basic pattern breaks chainability

    Basic pattern breaks chainability

    Is it a good practice to break the second plugin instance if we call it like this?

    $(selector).defaultPluginName({
        start: 13,
        end: 37
    }).defaultPluginName({
        start: 37,
        end: 42
    });
    

    It will not work since we allow the plugin only to be instantiated once per element. But to remove the if statement in our plugin definition is even not the best idea, or?

    opened by yckart 7
  • Modified Plugin.prototype, showing how to add more functions.

    Modified Plugin.prototype, showing how to add more functions.

    I would like to propose a small change to this plugin, showing how to add more functions to this plugin, since the init function, in most cases will not be enough. As I understand it, adding all functions that I want to use to the plugin's prototype is the recommended way of going about it. If I am incorrect I would appreciate feedback about what is the best way to add functions that I want to use in init(). :)

    Thanks.

    opened by kahlil 3
  • Prototype object alias

    Prototype object alias

    Haven't got around to any proper work on this, but suggesting a slight change to the declaration of the Plugin constructor here. You may / may not agree, and I admit it might not be that great of an idea, however have found this structural change quite useful myself.

    Modifying structure slightly so that the Plugin constructor function is declared as a variable and adding an alias to the Plugin prototype object. This might ruffle some feathers, but adds a little more contextual meaning to extending the Plugin constructor.

    opened by aariacarterweir 3
  • this.[functionOne] is not a function

    this.[functionOne] is not a function

    Hi, could someone explain where I am going wrong. I'm trying to use the jQuery boilerplate but having trouble when adding functions and calling them:

    /*!
     * 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
                // you can add more functions like the one below and 
                // call them like so: this.yourOtherFunction(this.element, this.options).
    
                $(this.element).each(function() {
                    console.log('Main function');
    
                    this.functionOne(this.element, this.options);
                });
            }, 
    
            functionOne: function(el, options) {
                console.log('functionOne');
                
                this.functionTwo(el, options);
            },
    
            functionTwo: function(el, options) {
                console.log('functionTwo');
            }
        };
    
        // 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 );
    

    This simple calling of functions results in the following console log:

    Main function
    
    TypeError: this.functionOne is not a function
    this.functionOne(this.element, this.options);
    

    Did I miss something? Reading the comments in the script, I think I'm calling the functions correctly?

    Thanks!

    opened by lawlesscreation 2
  • Simple grammar fix to README.md

    Simple grammar fix to README.md

    "...but you're interesting in learning if there a better ways..." to "...but you're interested in learning if there are better ways..."

    opened by collin-garvey 1
  • Changes in examples

    Changes in examples

    I changed the example HTML files.

    Changes in examples:

    • Updated RequireJS to 2.1.4 version.
    • Updated jQuery to 1.9.0 version.
    • Updated jQuery UI to 1.10.0 version.
    • Added doctype in examples.
    • Removed the type attributes in script tags.
    opened by DiegoLopesLima 1
  • Dead link for

    Dead link for "Non Widget-factory widget"

    The link "Non Widget-factory widget" on your documentation page "https://github.com/jquery-boilerplate/jquery-patterns" leads to a 404 page not found. This is the linked url:

    • https://github.com/jquery-boilerplate/jquery-patterns/blob/master/patterns/jquery.simplewidget.plugin-boilerplate.js%5D

    The page (=your example) doesn't exist any more. Would be interested to see this lightweight alternative to jQuery UI widget factory.

    opened by tbreuss 0
  • Add jquery.methods.plugin-boilerplate.js to demonstrate method wiring.

    Add jquery.methods.plugin-boilerplate.js to demonstrate method wiring.

    Since we are still missing a jQuery boilerplate that demonstrates how to expose the plugin methods to the developer, similarly to the way that jQuery UI does it, I forked the jquery.basic.plugin-boilerplate. Waiting for your feedback on this.

    opened by thgreasi 2
  • Extended the documentation with a style manifesto

    Extended the documentation with a style manifesto

    I've forked and exended the documentation at hand with a style manifesto just like here: https://github.com/ieservices/idiomatic.js.

    Why not adding it? ;)

    opened by ieservices 0
  • Extending the documentation with a style manifesto

    Extending the documentation with a style manifesto

    Why not exending the documentation at hand with a style manifesto just like here: https://github.com/ieservices/idiomatic.js ?

    Well, I started to add two examples in my fork. You can pull it. I'll send you a pull request.

    opened by ieservices 0
  • Adding Ability to Call $. defaultPluginName()

    Adding Ability to Call $. defaultPluginName()

    Hi,

    I was hoping this template could be updated so that it can support the ability to be called as $. defaultPluginName() so it can return a value (string, object, boolean) along with $(selector).defaultPluginName() so it can return a chain able object.

    I'm actually trying to figure out how it's done and so for unsuccessful. I'll continue to look up how it's done to go along with this boilerplate.

    opened by RoLYroLLs 0
  • What the hell!

    What the hell!

    It would be too hard if i say, that i hate @DiegoLopesLima's pull request, however instead of replacing the old one it is might the better choice to add a new one ;-)

    opened by yckart 1
Owner
jQuery Boilerplate
jQuery Boilerplate
Grupprojekt för kurserna 'Javascript med Ramverk' och 'Agil Utveckling'

JavaScript-med-Ramverk-Laboration-3 Grupprojektet för kurserna Javascript med Ramverk och Agil Utveckling. Utvecklingsguide För information om hur utv

Svante Jonsson IT-Högskolan 3 May 18, 2022
Hemsida för personer i Sverige som kan och vill erbjuda boende till människor på flykt

Getting Started with Create React App This project was bootstrapped with Create React App. Available Scripts In the project directory, you can run: np

null 4 May 3, 2022
Kurs-repo för kursen Webbserver och Databaser

Webbserver och databaser This repository is meant for CME students to access exercises and codealongs that happen throughout the course. I hope you wi

null 14 Jan 3, 2023
This repository contains an Advanced Zoom Apps Sample. It should serve as a starting point for you to build and test your own Zoom App in development.

Advanced Zoom Apps Sample Advanced Sample covers most complex scenarios that you might be needed in apps. App has reference implementation for: Authen

Zoom 11 Dec 17, 2022
This plugin for Obsidian enables you to quickly jump to internal and external links

Obsidian Quick Jump Plugin This plugin for Obsidian enables you to quickly jump to internal and external links. This plugin is inspired by Jump to lin

Tadashi Aikawa 9 Sep 24, 2022
Use javascript and css to build a StreetFighter Ryu,walk,jump,basic punch kick,launch fireball and dragon punch.

SFRyu Use javascript and css to build a StreetFighter Ryu,walk,jump,basic punch kick,launch fireball and dragon punch. 因為小時候就很喜歡玩快打旋風,於是用Javascript,CS

null 21 Sep 1, 2022
Jump to github urls (browser addon)

Currently a Firefox addon. Find GitHub locations quickly using your browser's history. Usage Use your mouse or keyboard. Use the filter to search for

madprops 4 Nov 28, 2022
🦋 Jump to local IDE source code while click the element of browser automatically

?? Why When developing a React app, you have a lot of components in your app. Sometimes you may forget where the code is located that you want to edit

Frozen FIsh 95 Aug 17, 2022
HackMIT 2022. 2nd Place in Blockchain for Society sponsored by Jump Crypto. A revolutionary web application that leverages machine learning and blockchain technology to improve the crowdsourcing experience!

?? Wikisafe ?? Wikisafe is a revolutionary new crowdsourcing web application that innovates the process of crowdsourcing information. This application

Benson Liu 5 Dec 8, 2022
Read without losing the plot. Well Read helps you organize your notes about books you're reading, so you're never lost when starting a new volume.

Well Read Well Read is a website for tracking your reading of long book series. I made this to track how many pages I read in a session and to better

null 3 Dec 15, 2022
A lazy plugin for printing local network when starting NodeJS server. I made this so you don't have to.

lazy-net A simple, lightweight plugin for printing local network when starting Node.js or Express.js server. I made this so you don't have to. There a

Trần Quang Kha (始) 1 Feb 10, 2022
🪆 Template intended to serve as a starting point if you want to bootstrap a Figma Plugin in TypeScript.

?? Codely Figma Plugin Skeleton Template intended to serve as a starting point if you want to bootstrap a Figma Plugin in TypeScript. Take a look, pla

CodelyTV 26 Dec 22, 2022
converts nuggies to usd and usd to nuggies for a variety of restaurant chains. Also includes a rest api. Built using NextJS and TypeScript

Prices All prices are currently based on the 4-piece from the respective chain or the equivalent lowest amount of nuggies. Plan is to add multiple pri

Sean Maizel 2 Jan 14, 2022
The Raspberry Pi + OpenScan Pi Shield can be used to control two independent stepper motors and a variety of different cameras

OpenScan2 Overview: The Raspberry Pi + OpenScan Pi Shield can be used to control two independent stepper motors and a variety of different cameras (Pi

Thomas 149 Jan 3, 2023
Service Installer for VMware Tanzu is a one-click automation solution that enables VMware field engineers to easily and rapidly install, configure, and operate VMware Tanzu services across a variety of cloud infrastructures.

Service Installer for VMware Tanzu Service Installer for VMware Tanzu seeks to provide a one-click automation solution to enable our VMware engineers

VMware Tanzu 42 Dec 1, 2022
Express middleware for easy OAuth with a variety of providers.

accounted4 Express middleware for easy OAuth2 with a variety of providers. accounted4 is intended to make it easy for developers to add third-party OA

Josh Moore 3 May 7, 2022
A docker container with a wide variety of tools for debugging and setting up micro-services

Frame One Software Placeholder There are numerous times during the dev ops deployments, that a placeholder container is needed. In the past, Frame One

Frame One Software 8 May 29, 2022
A hub for web developers that offers a variety of tools to help with any developing needs.

WebDevHub - A place for developers WebDevHub is designed to be one central place for developers, that offers a variety of tools to help with any devel

Thomas Hamilton-Smith 87 Dec 11, 2022
Open Source projects are a project to improve your JavaScript knowledge with JavaScript documentation, design patterns, books, playlists.

It is a project I am trying to list the repos that have received thousands of stars on Github and deemed useful by the JavaScript community. It's a gi

Cihat Salik 22 Aug 14, 2022