Coder Social home page Coder Social logo

jquery-boilerplate's Introduction

jQuery Boilerplate Build Status Bower Version

A jump-start for jQuery plugins development

So, you've tried your hand at writing jQuery plugins and you're comfortable putting together something that probably works. Awesome! Thing is, you think there might be better ways you could be writing them - you've seen them done a number of different ways in the wild, but aren't really sure what the differences between these patterns are or how to get started with them.

This project won't seek to provide a perfect solution to every possible pattern, but will attempt to cover a simple template for beginners and above. By using 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.

Usage

  1. Include jQuery:

    <script src="http://ajax.googleapis.com/ajax/libs/jquery/2.1.4/jquery.min.js"></script>
  2. Include plugin's code:

    <script src="dist/jquery.boilerplate.min.js"></script>
  3. Call the plugin:

    $("#element").defaultPluginName({
    	propertyName: "a custom value"
    });

Structure

The basic structure of the project is given in the following way:

├── demo/
│   └── index.html
├── dist/
│   ├── jquery.boilerplate.js
│   └── jquery.boilerplate.min.js
├── src/
│   ├── jquery.boilerplate.coffee
│   └── jquery.boilerplate.js
├── .editorconfig
├── .gitignore
├── .jshintrc
├── .travis.yml
├── Gruntfile.js
└── package.json

Contains a simple HTML file to demonstrate your plugin.

This is where the generated files are stored once Grunt runs.

Contains the files responsible for your plugin, you can choose between JavaScript or CoffeeScript.

This file is for unifying the coding style for different editors and IDEs.

Check editorconfig.org if you haven't heard about this project yet.

List of files that we don't want Git to track.

Check this Git Ignoring Files Guide for more details.

List of rules used by JSHint to detect errors and potential problems in JavaScript.

Check jshint.com if you haven't heard about this project yet.

Definitions for continous integration using Travis.

Check travis-ci.org if you haven't heard about this project yet.

Contains all automated tasks using Grunt.

Check gruntjs.com if you haven't heard about this project yet.

Specify all dependencies loaded via Node.JS.

Check NPM for more details.

Guides

How did we get here?

Have you got in this repo and still not sure about using this boilerplate?

Well, extending jQuery with plugins and methods is very powerful and can save you and your peers a lot of development time by abstracting your most clever functions into plugins.

This awesome guide, adapted from jQuery Plugins/Authoring, will outline the basics, best practices, and common pitfalls to watch out for as you begin writing your plugin.

How to publish plugins?

Also, check our guide on How to publish a plugin in jQuery Plugin Registry!

Note: The jQuery Plugin Registry is in read-only mode. New plugin releases will not be processed. jQuery recommends moving to npm, using "jquery-plugin" as the keyword in your package.json. See how to publish into npm registry.

Team

jQuery Boilerplate was made with love by these guys and a bunch of awesome contributors.

Zeno Rocha | Addy Osmani | Helder Santana --- | --- | --- | --- | --- | --- | --- Zeno Rocha | Addy Osmani | Helder Santana

Contributing

Check CONTRIBUTING.md for more information.

History

Check Releases for detailed changelog.

License

MIT License © Zeno Rocha

jquery-boilerplate's People

Contributors

almirfilho avatar arthurvr avatar audreyfeldroy avatar brenopolanski avatar carlesso avatar ctrlmaniac avatar heldr avatar highergroundstudio avatar joscha avatar kane-thornwyrd avatar leobalter avatar linclark avatar marcobiedermann avatar marteinn avatar nicolai86 avatar nvartolomei avatar pandawood avatar radiovisual avatar sindresorhus avatar vodkabears avatar zenorocha avatar

Stargazers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

Watchers

 avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar  avatar

jquery-boilerplate's Issues

How to call plugin w/o an element

I'm trying to create a plugin that can be called without an element.

I understand I should use $.extend to do that, but I don't see how to do it with the boilerplate as written.. it's already using extend but my plugin isn't available as a $.myPluginName() and I don't quite follow where I need to change to make sure it's extending the default $ object

Events Triggers Example

I think that an example of event trigger could be useful. E.g. onInit, onStart, onEnd, onComplete, etc...

A more advanced jQuery Boilerplate

I've been using the jQuery Boilerplate for my plugins a lot but although it reduces the amount of code you have to write I think it can be abstracted just a little bit more to make it more comfortable to re-use, particularly as a jQuery plugin (inception). Here's my current "advanced boilerplate":

Here's a detailed gist with a demo to show how this works: https://gist.github.com/elclanrs/5668451

/**
 * Advanced jQuery Plugin Boilerplate
 */
(function($) {

  $.newPlugin = function(pluginName, defaults, methods, global) {

    function Plugin(element, options) {
      this.opts = $.extend({}, defaults, options);
      this.el = element;
      this._name = pluginName;
      this._init();
    }

    Plugin.prototype._init = $.noop;

    Plugin.prototype[pluginName] = function(method) {
      if (!method) return this._init();
      try { return this[method].apply(this, [].slice.call(arguments, 1)); }
      catch(e) {} finally { return this; }
    };

    $.extend(Plugin.prototype, methods);

    if (global) $[pluginName] = global;

    $.fn[pluginName] = function() {
      var args = arguments;

      return this.each(function() {
        var instance = $.data(this, 'plugin_'+ pluginName);

        if (!instance || typeof args[0] == 'object') {
          return $.data(this, 'plugin_'+ pluginName, new Plugin(this, args[0]));
        }
        return instance[pluginName].apply(instance, args);
      });
    };
  };

}(jQuery));

Help for a newb

Hello,

I'm working on writing my first jQuery plugin and using your boilerplate.

Basically, it's a simple collapsibles plugin that lets an element toggle a container anywhere on the page by targeting its ID. It also handles collapsible groups and provides an option to close the collapsible on a document click. It still lacks a couple features I want to add in.

My issue:

I've got it working, but...
I wanted to separate all the real work into event functions, but I haven't had any luck doing so. I contribute it to my lack of knowledge of JS state and how the jQuery plugin loop works.

My other questions is on performance.

I know this is a small plugin and probably wouldn't have any impact, but how would I make it so every object isn't having to create a new instance of those functions? That's why I wanted to separate the bulk of the work to an outer object that my plugin would just extend and have access to those event functions.

I doubt I'm explaining it right, but I hope you understand.

Thanks for any help.

;(function ( $, window, undefined ) { 

    // Create the defaults once
    var pluginName = 'collapsible',
        document = window.document,
        defaults = {
            event: "click",
            clickClose: false,
            ajax: false
        };

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

        this.options = $.extend( {}, defaults, options);

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

        this.init();
    }

    // All the plugin's logic + functions + crap
    Plugin.prototype = {
        init: function () {
            // Get options for individual element
            var elementSettings = $(this.element).data('collapsibleOptions'),
                O = $.extend(this.options, elementSettings),
                C = $(this.element),
                T = $(O.target);

            // Add group data to element
            if ( O.group ){
                C.data('group', O.group);
            }

            // Events
            C.on('collapse', function(){
                C.removeClass('is-selected');
                T.removeClass('is-expanded');
            })
            .on('expand', function(){
                C.addClass('is-selected');
                T.addClass('is-expanded');

                //if is search toggle
                if(O.target == '#searchForm'){
                    $('#q').focus();
                }
                //NEED TO ADD IF AJAX
            })
            .on(O.event, function(e){
                if( C.hasClass('is-selected') ){
                    C.trigger('collapse');
                }else{
                    // Hide open group memebers and open clicked
                    if( x = $('.is-selected').filter( function(){return $(this).data('group') == O.group} ) ){
                        $(x).trigger('collapse');
                    }
                    C.trigger('expand');
                }
                //the click must not go through!
                return false;
            });

            // Target Events
            T.on('mouseenter', function(){
                $.data(this, 'hover', true);
            })
            .on('mouseleave', function(){
                $.data(this, 'hover', false);
            });

            // Close when clicking outside target container
            if ( O.clickClose ){
                $(document).on('click', function(){
                    if ( ! T.data('hover') ){
                        C.trigger('collapse');    
                    }                    
                })
            }
        }
    };

    // 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));

Small quibble with semantics

Hi Zeno and Addy,

A small quibble about sematics for you to consider.

Currently we have

    this.options = $.extend( {}, defaults, options );

Arguably, for wholesome goodness, this should be

    this.settings = $.extend( {}, defaults, options );

Because these are three different concepts:

  • defaults are the collection of sensible, or usual, or 'base' settings provided by the plugin,
  • options are optional user-provided overrides to these defaults, and
  • settings is the mode for this invocation, the amalgam of options over defaults.

Thus settings is the state of the plugin right now, which is different than options which arguably (sensibly?) come from the user. This nomenclature makes for neat conceptual packages.

Another reason settings is better: it's possible that not all this.settings are exposed and mutable. Calling it this.options, as we have now, implies across-the-board setting mutability.

Therefore I suggest this.settings is a better name than this.options for the amalgamated runtime state of the plugin.

How to access "this" from events?

I am having some scope issues. Let's say that I want to bind an internal function to a click event. How do I access "this" from inside the binded function?

$('something').bind('click', function() {
    // how do I access this.options or this.someFunction() from here?
});

Is this possible?

Boilerplate min not working unless I change a little bit the code

Boilerplate minified is not working for me unless I change a little bit the code. What I'm doing wrong?

Original code:

    $.fn.pluginName = function(options) {

        return this.each(function() {
            if (undefined == $(this).data('pluginName')) {
                var plugin = new $.pluginName(this, options);
                $(this).data('pluginName', plugin);
            }
        });

    }

Working code:

    $.fn.pluginName = function(options) {

        if (undefined == $(this).data('pluginName')) {
            var plugin = new $.pluginName(this, options);
            $(this).data('pluginName', plugin);
        }

    }

qUnit

Set up qunit as a submodule and have a basic test index somewhere (kinda like what jquery itself does)

using boilerplate also as function wrapper

Hi there,

I start to use boilerplate in my upcoming projects, but @ first i would write an function helper for often used functions who are not supported by jquery themselve.

The first thing i saw was that if i want to use the plugin boilerplate for an helper class it wont work because of the instance function. (return this.each)

After a little bit of additional code i was able to use the boilerplate standard also to instance the plugin into an variable like this:

var helper = new $.fn.myPlugin();
var helper.myFunction() //global function

So maybe you want to use my code to extend your boilerplate.
Here are my code changes:

$.fn[pluginName] = function ( options ) {
    if($.isEmptyObject(this)){
        return new Plugin( this, options );
    }else{
        return this.each(function () {
            if (!$.data(this, 'plugin_' + pluginName)) {
                $.data(this, 'plugin_' + pluginName, new Plugin( this, options ));
            }
        });
    }
};

Translate

Starting with:

  • Portuguese
  • French
  • German

And also create an easy way to provide translation in this code.

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.

How to not expose methods, ie privates?

I dig the boiler plate lots of good concepts, but there is one ting I couldn't quite figure out.

Adding all the methods to prototype exposes them on your Plugin obj. When writing these plugins there are plenty of times I do not want a method/function to be public via the reference in data().

How do you guys handle creating private methods, preferably ones that still retain the scope of 'this' being the Plugin instance?

JSHint check failed

when executing bundle exec rake it stops in jshint task and does not execute the other ones.

the error message is: JSHint check failed

This is not a jQuery Plugin Boilerplate

Part of what it means for a jQuery plugin to be a jQuery plugin is that it meets certain user expectations. The most basic part of this contract is that the plugin's main method exists on the jQuery prototype (jQuery.fn) and will iterate the collection of elements passed to it, performing the action to each DOM element in the jQuery object, and typically returning a jQuery object for chaining.

Object-oriented, stateful "plugins" are obviously a desirable endpoint, but the pattern you're advocating here is simply a pattern for creating constructors that happen to accept jQuery objects as parameters and then return an instance of the object you've constructed. It's a perfectly valid approach, but I don't think it's one that really embraces the spirit of what it means to be a "jQuery Plugin." Having public and private methods is not a win that is unique to this pattern - it's a given.

Furthermore, your claims that somehow this approach somehow saves on memory and improves performance compared to the traditional pattern (which meets most users' expectations) are unsubstantiated. When you do jQuery.fn.whatever = function() {}, a new "instance" of that function is not created over and over again, it is a prototype method. And if you have an object-oriented plugin that you do want to have multiple instances of on the page, then well, that's exactly what you want - multiple instances is not a "bad thing."

I know this isn't a specific "issue," per se, but I briefly commented on Twitter but @zenorocha asked me to bring the discussion here so others with feedback can share those thoughts here.

Should `grunt` work immediately after `yo jquery-boilerplate`?

I trying to understand the basics, but I thought one could run grunt right after grabbing the jquery-boilerplate since there is a Gruntfile.js there. I'm not exactly sure why one would run grunt though. Also, I'm not sure if this is the place to comment/ask?

How to extend the plugin?

Actually I'm very beginner to plugin development and trying to write a plugin.

Now, I'm stumbled that how should I start writing?

Suppose, I've set up defaults values like this:

defaults = {
myProperty: undefined
};

And now I can use it like this:

.myPluginName({myProperty:10})

Now, I tried to console the myProperty value within the $.fn method which outputs "undefined":

$.fn[ pluginName ] = function ( options ) {
this.each(function(){
console.log(defaults.myProperty);//logs undefined
});
return this;
};

And now if I use inside Plugin function then outputs "10" which is what I want:

function Plugin ( element, options ) {
this.element = element;
this.settings = $.extend( {}, defaults, options );
this._defaults = defaults;
this._name = pluginName;
console.log(this.settings.myProperty);//logs 10
this.init();
}

So, actually, how should I start writing a plugin?

How to instantiate the plugin?

Sorry, my friends, but I will write my question in portuguese. This is the first time i will send a issue, so if has something wrong with my question, please tell me.

No site em português do jqueryboilerplate (br.jqueryboilerplate.com) existe a informação de que o aplicativo "Não adere às sugestões feitas pela documentação do jQuery em relação ao Plugins/Authoring e fazendo isso provê melhor performance e uso de memória por não criar múltiplas instâncias de si mesmo".

Eu criei um plugin para modal que é acionado a partir de um botão. Fiz o plugin baseado nesta documentação Plugins/Authoring e tive este problema de múltiplas instâncias. Encontrei o jqueryboilerplate(v3-0) e tentei remodelar meu plugin baseado nele, mas estou com uma dúvida básica: como devo fazer a chamada ao plugin?

$(function(){
$('button.modal').click(function() {
???
});
});

multiple element

I'd like to call my plugin created following this boilerplate in this way:

$('.box').sameheight();

but in this case the plugin is initialized three times (in the dom the rule .box matches three elements), and the function init() is called three times.

the expected behavior would be that this.element in the function init() would return an array of jquery objects. am I wrong?

Code style tooling?

Instead of having to care about code styling ourselves, we should have tooling to do so. jscs, for example. IMHO we need a jscs grunt task and the necessary configurations for the jQuery style guide.

how to pass element to event callback function

Hey guys,
thanks for the amazing work!

My code is exactly the same as the default plugin boilerplate
I just replace the init function

init: function() {
    $(this.element).find('button').on('click',function(e){
        e.preventDefault();
        console.log(this.element);
        console.log(this.options);
    }); 
}

of course the logs return undefined
do u have any recommendation / good practice to access element and options in the scope of the callback function
Thanks for your help

Remove closure wrapper from CoffeeScript version

The first comment in the CoffeeScript version says:

Note that when compiling with coffeescript, the plugin is wrapped in another anonymous function.

So why add another one then?

To localise window and document and $, you can just declare them at the top. This gets exactly the same job done – localising the variables for performance/minification – in a way that is cleaner and more straightforward.

Assign methods to the prototype object, instead of overwriting the prototype with a new object.

Assign methods to the prototype object, instead of overwriting the prototype with a new object. Overwriting the prototype makes inheritance impossible: by resetting the prototype you'll overwrite the base!

See this shamelessly plugged example from airbnb javascript styleguide.

Now the boilerplate has this structure, which overwrites inheritance :/

Jedi.prototype = {
  fight: function fight() {
    console.log('fighting');
  },

  block: function block() {
    console.log('blocking');
  }
};

A suggestion would be to use this practice instead,

Jedi.prototype.fight = function fight() {
  console.log('fighting');
};

Jedi.prototype.block = function block() {
  console.log('blocking');
};

Build

Include building tools (like a makefile with minification built-in and jslint/jshint testing)

Move parens inside function invocation

JSLint and JSHint both prefer

(function($) {
  ...
}(jQuery));

to

(function($) {
  ...
})(jQuery);

I'm not entirely sure of the reasoning, but I prefer my boilerplate pass my JSHint checks. (And if you know of a good reason not to do this, I'll gladly change my JSHint checks :) )

Grunt

Create a new branch called nodejs and use grunt to automatize tasks.

Code convetion [singlequotes/doublequotes]

Is there a sense behind the decision to mix single- & doublequotes?

var pluginName = "defaultPluginName",
    defaults = {
        propertyName: "value"
    };
if (!$.data(this, 'plugin_' + pluginName)) {
    $.data(this, 'plugin_' + pluginName, new Plugin( this, options ));
}

Multiple instances on one page

I'm writing a custom paginator plugin, and I'm wondering how to handle multiple instances on the same page. For example:

$('#element1').paginator({ somestuff: 'test' });
$('#element2').paginator({ somestuff: 'test' });

Currently, element1 doesn't do anything because element2 is instantiated. If I comment out element2, element1 works just fine.

destroy method

The boilerplate lack of destroy/clean method once you've built your plugin, developpers need a proper way to remove it

If I pass a function to the plugin as parameter,it can not be executed in init()?

I write my plugin:

var pluginName = 'Yinput',
defaults = {
'defaultfn':'fn'
};

……

Plugin.prototype.init = function () {
var o=this.options;
o.defaultfn();
};

then I init a instance :

$('.container').Yinput({
'defaultfn':function(){
$(this).fadeOut();
}
});

however it could tell me wrong ,how can I solve this problem ,execute function paramter?

Add comment for _defaults and _name variables

It could be useful to get a small comment above this code :

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

Is it to ensure we access a protected defaults and plugin name variables which are not modifiable from outside the plugin (after the plugin initialization)?

Recommend Projects

  • React photo React

    A declarative, efficient, and flexible JavaScript library for building user interfaces.

  • Vue.js photo Vue.js

    🖖 Vue.js is a progressive, incrementally-adoptable JavaScript framework for building UI on the web.

  • Typescript photo Typescript

    TypeScript is a superset of JavaScript that compiles to clean JavaScript output.

  • TensorFlow photo TensorFlow

    An Open Source Machine Learning Framework for Everyone

  • Django photo Django

    The Web framework for perfectionists with deadlines.

  • D3 photo D3

    Bring data to life with SVG, Canvas and HTML. 📊📈🎉

Recommend Topics

  • javascript

    JavaScript (JS) is a lightweight interpreted programming language with first-class functions.

  • web

    Some thing interesting about web. New door for the world.

  • server

    A server is a program made to process requests and deliver data to clients.

  • Machine learning

    Machine learning is a way of modeling and interpreting data that allows a piece of software to respond intelligently.

  • Game

    Some thing interesting about game, make everyone happy.

Recommend Org

  • Facebook photo Facebook

    We are working to build community through open source technology. NB: members must have two-factor auth.

  • Microsoft photo Microsoft

    Open source projects and samples from Microsoft.

  • Google photo Google

    Google ❤️ Open Source for everyone.

  • D3 photo D3

    Data-Driven Documents codes.