前置き
いくつかjQueryプラグインを作成したことで、ようやく自分の中でお決まりのパターンのようなものが出来上がりつつあります。いまさら感満載ではありますが、プラグイン開発時のテンプレートの一例として、投稿しておきます。
テンプレートといってHogeとかFugaとかいうコードににしてしまうとイメージが湧きづらいので、サンプルプラグインを実装して公開することにします。プラグイン開発に慣れていない方のことも考慮して、お節介にもコメントもふんだんに盛り込んでみました。
サンプル Loggingプラグインの仕様
- テキストフィールド等のコントロールの変更を監視し、値が変更されたらコンソールに変更前と変更後の値を出力する
- プラグイン初期化時にオプションを指定できる
$('.watch-me').logging({
label: '[変更されました]',
});
- 各要素個別のオプションをdata属性にて指定できる
<input type="text" class="watch-me" data-label="「あなた、変わったわ・・・」" />
- 後から監視をオフできる
var $inputs = $('.watch-me').logging();
...
$('#stop-button').on('click', function(e) {
$inputs.logging('off');
});
テンプレート
;(function($) {
'use strict';
/*
* methods: プラグインメソッド
*
* ここで指定したメソッドはjQueryオブジェクトから呼び出すことができます。
*
* 例)
* var $inputs = $('.watch-me').logging();
*
* $('#stop-button').on('click', function(e) {
* $inputs.logging('off');
* });
*
*/
var methods = {
init: function(options) {
var settings = $.extend({
/*
* デフォルトオプションをここに記述します。
* 各要素のdata属性で上書きされるので、キーはキャメルケースで記述します。
* o greatWonderfulOption
* x great_wonderful_option
*/
label: '[changed]',
}, options);
return this.each(function() {
var $this = $(this);
var logging = new Logging($this, mergeOptions($this, settings));
// ここに初期化処理を記述します
logging.observe();
$this.data('plugin_logging', logging);
});
},
off: function() {
return this.each(function() {
var logging = $(this).data('plugin_logging');
logging.stopObserving();
});
},
};
/*
* 要素個別のdata属性をマージしたオプションを返します。
*
* 例えば greatWonderfulOption というオプションを上書きしたい場合は、
* 次のようにdataタグを記述します。
* <input type="text" class="watch-me" data-great-wonderful-option="オプション値" />
*/
var mergeOptions = function($el, settings) {
return $.extend({}, settings, $el.data());
};
/*
* jQueryプラグイン登録
*/
$.fn.logging = function(method) {
if (methods[method]) {
return methods[method].apply(this, Array.prototype.slice.call(arguments, 1));
} else if (typeof method === 'object' || !method) {
return methods.init.apply(this, arguments);
} else {
$.error('Method ' + method + ' does not exist on jQuery.logging');
}
};
/*
* プラグイン用クラス
*
* プラグインのメイン処理はここに書きます。
*
*/
var Logging = (function() {
var NAMESPACE = '.logging';
/*
* コンストラクタ
*/
var Logging = function($el, settings) {
this.$el = $el;
this.settings = settings;
};
// クラスメソッド(あれば)
// Logging.classMethod = function() {};
/*
* インスタンスメソッド
*/
$.extend(Logging.prototype, { /*親クラス.prototype(あれば)*/ }, {
observe: function() {
/*
* NAMESPACEについて
* $jquery.onでイベントリスナーを登録する際にネームスペースを指定することができます。
* 指定しておけば、ネームスペース単位でリスナーを解除できるので、
* 自分で登録したイベントだけを安全に解除できます。
* $('.watch-me').on('change.myPlugin', function(e) {...});
* $('.watch-me').off('.myPlugin'); //ネームスペース.myPluginだけをオフ
*/
this.$el.on('focus' + NAMESPACE, this._bind('onFocus'));
this.$el.on('change' + NAMESPACE, this._bind('onChange'));
},
stopObserving: function() {
this.$el.off(NAMESPACE);
},
/*
* focusやchangeなどイベントリスナーから呼び出されるメソッドについては、
* "onリスナー名"という命名にしておけば分かりやすくて良いかと思います。
*/
onFocus: function(e) {
this.originalValue = this.$el.val();
},
onChange: function(e) {
console.debug([this.settings.label, this.originalValue, '->', this.$el.val()].join(' '));
},
/*
* 指定したメソッドのthisがLoggingクラスのインスタンスになるように束縛します
*/
_bind: function(funcName) {
var that = this;
return function() { that[funcName].apply(that, arguments) };
},
});
return Logging;
})();
})(jQuery);
ソース
参考