ABOUT ME

-

Today
-
Yesterday
-
Total
-
  • 객체지향 형식 jquery 플러그인 만들기
    개발/jQuery 2011. 5. 21. 18:15


    Building an Object-Oriented jQuery Plugin

    Written by Hector Virgen
    Published on October 4, 2009
    Last updated on August 23, 2010

    Update: Jamie Talbot has written an excellent article that improves this method and is definitely worth a read.

    So you've been using jQuery as your Javascript framework and now you need to write a plugin. If you come from an Object-Oriented background like me, you may feel that jQuery's plugins leave a lot to be desired.

    The basic formula to create a jQuery plugin is to extend the plugin namespace with a single method:

    1 #myplugin.js
    2  
    3 jQuery.fn.myplugin = function()
    4 {
    5    // Do some cool stuff here
    6 }

    While that seems all fine and dandy for simple plugins, you may need to create more robust plugins that do many things, often in a non-linear fashion.

    Some plugins get around this by adding tons of methods to jQuery's plugin namespace.

    1 $('#test').plugin();
    2 $('#test').pluginAdd('stuff');
    3 $('#test').pluginRemove('other stuff');
    4 $('#test').pluginDoSomethingCool();

    I personally don't like that approach because it pollutes the jQuery plugin namespace with lots of methods. I personally like to stick to just one plugin method per plugin.

    Other plugins use the first parameter of the plugin to call methods:

    1 $('#test').plugin();
    2 $('#test').plugin('add', 'stuff');
    3 $('#test').plugin('remove', 'other stuff');
    4 $('#test').plugin('doSomethingCool');

    I think this approach is a little awkward, especially if the plugin accepts an options object the first time it is created. This approachs means you would have to either write a switch of all the methods you want to expose, or blindly accept any string as a method name.

    To get around these hurdles, I've created a basic template for jQuery plugins that provides access to an Object-Oriented interface if needed while still maintaining jQuery's simplicity of a single method in the plugin namespace.

    The first thing you need to do is wrap all your plugin code in an anonymous function. This will help keep things nice and tidy without creating global variables.

    1 #myplugin.js
    2  
    3 (function($){
    4    // Your plugin code goes here
    5 })(jQuery);

    Next, create your plugin as a class, where the first parameter is a single DOM element.

    01 #myplugin.js
    02  
    03 (function($){
    04    var MyPlugin = function(element)
    05    {
    06        var elem = $(element);
    07        var obj = this;
    08  
    09        // Public method
    10        this.publicMethod = function()
    11        {
    12            console.log('publicMethod() called!');
    13        };
    14    };
    15 })(jQuery);

    To make your new object-oriented class available as a jQuery plugin, write a simple wrapper function in the plugin namespace:

    01 #myplugin.js
    02  
    03 (function($){
    04    var MyPlugin = function(element)
    05    {
    06        var elem = $(element);
    07        var obj = this;
    08  
    09        // Public method
    10        this.publicMethod = function()
    11        {
    12            console.log('publicMethod() called!');
    13        };
    14    };
    15  
    16    $.fn.myplugin = function()
    17    {
    18        return this.each(function()
    19        {
    20            var myplugin = new MyPlugin(this);
    21        });
    22    };
    23 })(jQuery);

    Now, when you call $(element).myplugin(), the jQuery plugin instantiates an instance of MyPlugin, passing the element as the first argument.

    But now there's a problem of how to get the object "myplugin" once it's been created. For this, I usually store the object in the elements data. This provides easy access to the object while allowing you to prevent accidental double instantiation in the event that the plugin was called again on the same element.

    01 #myplugin.js
    02  
    03 (function($){
    04    var MyPlugin = function(element)
    05    {
    06        var elem = $(element);
    07        var obj = this;
    08  
    09        // Public method
    10        this.publicMethod = function()
    11        {
    12            console.log('publicMethod() called!');
    13        };
    14    };
    15  
    16    $.fn.myplugin = function()
    17    {
    18        return this.each(function()
    19        {
    20            var element = $(this);
    21            
    22            // Return early if this element already has a plugin instance
    23            if (element.data('myplugin')) return;
    24  
    25            var myplugin = new MyPlugin(this);
    26  
    27            // Store plugin object in this element's data
    28            element.data('myplugin', myplugin);
    29        });
    30    };
    31 })(jQuery);

    Now you have easy access to the object should you need to run methods on it.

    1 $('#test').myplugin();
    2 var myplugin = $('#test').data('myplugin');
    3 myplugin.publicMethod(); // prints "publicMethod() called!" to console

    If you need to get fancy and add options parameter or other required parameters, just pass them from the jQuery plugin to your plugin's constructor:

    01 #myplugin.js
    02  
    03 (function($){
    04    var MyPlugin = function(element, options)
    05    {
    06        var elem = $(element);
    07        var obj = this;
    08  
    09        // Merge options with defaults
    10        var settings = $.extend({
    11            param: 'defaultValue'
    12        }, options || {});
    13  
    14        // Public method
    15        this.publicMethod = function()
    16        {
    17            console.log('publicMethod() called!');
    18        };
    19    };
    20  
    21    $.fn.myplugin = function(options)
    22    {
    23        return this.each(function()
    24        {
    25            var element = $(this);
    26            
    27            // Return early if this element already has a plugin instance
    28            if (element.data('myplugin')) return;
    29  
    30            // pass options to plugin constructor
    31            var myplugin = new MyPlugin(this, options);
    32  
    33            // Store plugin object in this element's data
    34            element.data('myplugin', myplugin);
    35        });
    36    };
    37 })(jQuery);

    You may also want to expose some of your object's methods while keeping others private. To make a private method, create a local function within your object using the var keyword:

    01 #myplugin.js
    02  
    03 (function($){
    04    var MyPlugin = function(element, options)
    05    {
    06        var elem = $(element);
    07        var obj = this;
    08        var settings = $.extend({
    09            param: 'defaultValue'
    10        }, options || {});
    11         
    12        // Public method - can be called from client code
    13        this.publicMethod = function()
    14        {
    15            console.log('public method called!');
    16        };
    17  
    18        // Private method - can only be called from within this object
    19        var privateMethod = function()
    20        {
    21            console.log('private method called!');
    22        };
    23    };
    24  
    25    $.fn.myplugin = function(options)
    26    {
    27        return this.each(function()
    28        {
    29            var element = $(this);
    30            
    31            // Return early if this element already has a plugin instance
    32            if (element.data('myplugin')) return;
    33  
    34            // pass options to plugin constructor
    35            var myplugin = new MyPlugin(this, options);
    36  
    37            // Store plugin object in this element's data
    38            element.data('myplugin', myplugin);
    39        });
    40    };
    41 })(jQuery);

    To see an example of a plugin I wrote that uses this template, check out my Tagger plugin.


    '개발 > jQuery' 카테고리의 다른 글

    checkbox를 radio 버튼처럼 사용하기  (0) 2011.10.19
    참고할만한 사이트  (0) 2011.05.27
    dropdown 메뉴 기본  (0) 2011.05.02
    checkbox 설정  (0) 2011.04.23
    jQuery UI로 달력과 날짜입력기(DatePicker)를 붙여보기.  (0) 2010.09.26
Designed by Tistory.