後から状態が変化したり、振る舞いを操作したりするような複雑なプラグインをかくときのプラグインの初期化やメソッドの呼び出し方法についていろいろ調べてみて、こんな感じかなということでメモ。
(function($, window, undefined) {
"use strict";
var _slice = [].slice;
var _toString = {}.toString;
var PluginName = (function() {
function PluginName() {
this._init.apply(this, arguments);
}
PluginName.dataName = 'pluginname';
PluginName.defaultOptions = {
optionA: 'aaa',
optionB: 'bbb'
};
PluginName.prototype = {
constructor: PluginName,
_init: function($element, options) {
console.log('initialize!!');
},
methodA: function(a, b, c) {
console.log('methodA', a, b, c);
}
};
return PluginName;
})();
var methods = {
init: function(options) {
options = $.extend(true, {}, PluginName.defaultOptions, options);
this.each(function() {
var $element = $(this);
$element.data(PluginName.dataName, new PluginName($element, options));
});
},
methodA: function() {
var args = arguments;
this.each(function() {
var context = $(this).data(PluginName.dataName);
context.methodA.apply(context, args);
});
}
};
$.fn.pluginName = function() {
var args = _slice.call(arguments);
//First argument may be Object or method name String.
var first = args[0];
//The rest is an array of an argument passed when a method is called.
var rest = args.length > 1 ? _slice.call(arguments, 1) : [];
//If no argument is passed, invoke 'init' method with no argument.
if (!first) {
methods.init.call(this);
}
//If Object is passed as first argument, invoke 'init' method with it.
//Sometimes there are more than one argument.
else if($.isPlainObject(first)) {
methods.init.apply(this, args);
}
//If first argument is String, a method will be invoked.
//The rest is passed as arguments.
else if(_toString.call(first) === '[object String]' && (first in methods)) {
methods[first].apply(this, rest);
}
//Otherwise, an error will be thrown.
else {
$.error('Failed to invoke a method or to initialise plugin.');
}
return this;
};
})(jQuery, window);
$(function() {
//initialize
$('#someDiv').pluginName(); //-> 'initialize!!'
//invoke a method
$('#someDiv').pluginName('methodA', "a", "b", "c"); //->'methodA a b c'
});
実際の操作はnewで初期化したオブジェクトで行い、メソッドの呼び出しはプラグイン呼び出し時に文字列を渡して行う。外部から呼び出せるメソッドはmethods変数のメソッドに中継させる形。