jQuery(3) : プラグインを作ろう

| | Comments (0) | TrackBacks (0)

jQueryの初心者がある程度jQueryを使いこなせるようになるまでを連載でお届けします。 (第1回目はこちら、 第2回目はこちら)
第3回目はjQueryのプラグインを作ってみましょう。 自分が欲しい機能がプラグインで提供されていない場合は、自分でプラグインを作成して、できればみんなのために公開してみましょう。

各項目をクリックすることで記事が表示されます。

他のライブラリとの共存

プラグインを作るのに必要な前提知識で、まだこの連載で触れていないものについてご紹介します。
jQueryでコードを書いていると"$"を多用しますが、"$"はグローバル変数のため、他のライブラリと一緒にjQuery を使用している場合は、jQueryの"$"と他のライブラリの"$"がバッティングしてしまいます。
例えば、prototypeというライブラリも"$"というグローバル変数が定義されているため、prototypeとjQueryを同時に 使う場合は、"$"がバッティングしてしまいます。
このような場合に備えてjQueryでは他のライブラリと共存できるような仕組みも用意しています。
jQueryでは"$"は"jQuery"のエイリアスになっています。 ですから他のライブラリと一緒に使う場合は"$"の変わりに"jQuery"を使えば他のライブラリと バッティングすることはありませんが、それだけでは他のライブラリの"$"がjQueryの"$"で上書きされたままに なり、他のライブラリの"$"が使用できなくなります。
jQueryでは"$.noConflict()"というグローバル関数が用意されており、これを使うと jQueryの"$"は無効化され、他のライブラリの"$"が使えるようになります。 prototypeなど"$"が定義されているライブラリとjQueryを同時に使用する場合は、必ず$.noConflict()を使ってバッティングを回避しましょう。
jQueryのコードはほとんどreadyイベントハンドラ内に書くため、readyイベントハンドラ内ではjQueryの"$"を使いたい という場合は、readyイベントハンドラのfunctionに引数として"$"を渡せば、readyイベントハンドラ内ではjQueryの"$"が使えるようになります。
まとめると以下のようになります。

<script type="text/javascript" src="/path/to/prototype.js"></script>
<script type="text/javascript" src="/path/to/jquery.js"></script>
<script type="text/javascript">
// ここで"$"を使うとjQueryの"$"が使われる。
$.noConflict();
// ここで"$"を使うとprototypeの"$"が使われる。
jQuery(document).ready(function($) {
// ここで"$"を使うとjQueryの"$"が使われる。
});
// ここで"$"を使うとprototypeの"$"が使われる。
</script>

名前空間

jQueryではグローバル関数("$.ajax()"など)は全てjQuery名前空間に定義されています。 "$.ajax()"は単に"ajax()"と定義できますが、"ajax()"と定義すると他のライブラリやスクリプトと衝突する可能性があります。
この様にグローバルな名前空間に関数を定義するのはマナーが悪い書き方です。
自分のweb内でのみ使用するスクリプトの場合は衝突についてはそれほど考える必要はないかもしれませんが、 ライブラリやプラグインなど多くの人が使うものを書く場合は、誰がどの様に使うか分らないため他と衝突しないように変数や関数を定義する必要があります。
以下の様にjQuery名前空間に関数を定義したとします。

jQuery.hello = function() {
  alert("Hello!");
};

この場合、jQueryとは関係のないスクリプトとは名前の衝突が避けられるかもしれませんが、 jQueryやjQueryのプラグインの関数と衝突する可能性があります。
jQueryのプラグインを書く際は以下の様に書くのが良いマナーです。

jQuery.myplugin.hello = function() {
  alert("Hello!");
};

プラグインでは、"jQuery.プラグイン名"名前空間にプラグインで使用する関数や変数を定義するようにします。
こうすることで、プラグイン名さえ重複しなければ名前の衝突が回避できます。

作成するプラグイン

今回作成するプラグインは連載第1回の最後に作成したストライプテーブルを作成するプラグインです。 オプションでストライプの階層を指定できるようにします。
以下に今回作成するプラグインを利用した例を示します。

ストライプの階層:
ID名前
1高橋
2岡田
3鍋島
4丸山
5島田
6富沢
7田中
8鈴木
9荒木
10

使い方は、まずテーブルのHTMLを用意します。
<table>には<thead>と<tbody>を含めます。

<table id="stripe" border="1" cellspacing="0">
<thead>
<tr><th>ID</th><th>名前</th></tr>
</thead>
<tbody>
<tr><td>1</td><td>高橋</td></tr>
<tr><td>2</td><td>岡田</td></tr>
<tr><td>3</td><td>鍋島</td></tr>
<tr><td>4</td><td>丸山</td></tr>
<tr><td>5</td><td>島田</td></tr>
<tr><td>6</td><td>富沢</td></tr>
<tr><td>7</td><td>田中</td></tr>
<tr><td>8</td><td>鈴木</td></tr>
<tr><td>9</td><td>荒木</td></tr>
<tr><td>10</td><td>林</td></tr>
</tbody>
</table>

用意したテーブルを選択し、"stripeTable()"メソッドを実行することでテーブルをストライプにします。
オプション"pattern_num"で何階層のストライプにするか指定します。何も指定しない場合は2階層のストライプにします。
"stripeTable()"メソッドを実行すると、<tbody>エレメント内の<tr>エレメントに"stripe-n"というクラスが追加されます。 nは1からpattern_numの範囲の数値が順番に入れられます。 ストライプの階層が3階層の場合(pattern_numが3の場合)は、テーブルの上の行から順番に stripe-1, stripe-2, stripe-3, stripe-1, stripe-2,・・・というふうにクラスが追加されます。
ストライプの階層分のstripe-nクラスとテーブルのCSSスタイルを定義します。

<style type="text/css">
table thead tr th {
  width: 100px
  text-align: center;
}

table tbody tr td {
  width: 100px;
}

table thead tr {
  background-color: #DDDDDD
}

table tbody tr {
  background-color: #FFFFFF
}

table tbody tr.stripe-1 {
  background-color: #FFF4F4
}

table tbody tr.stripe-2 {
  background-color: #FFE3E3
}

table tbody tr.stripe-3 {
  background-color: #FFC8C8
}

table tbody tr.stripe-4 {
  background-color: #FFA4A4
}

table tbody tr.stripe-5 {
  background-color: #FF7575
}
</style>

最後にjQueryのコードを書きます。

<script type="text/javascript" src="/path/to/jquery.js"></script>
<script type="text/javascript" src="/path/to/jquery.stripeTable.js"></script>
<script type="text/javascript">
$(document).ready(function() {
  $("#stripe").stripeTable({ pattern_num: 5 });
});
</script>

プラグインの作成

作成するプラグインの名前は"stripeTable"とします。 jQueryのプラグインのファイル名は"jquery.プラグイン名.js"とすることが慣例になっているので "jquery.stripeTable.js"というファイルにプラグインのコードを記述してください。

jQueryのプラグインを作成する場合は、プラグインの中でjQueryが使えることを前提にしても構いません。
ただし、「他のライブラリとの共存」で書いたようにプラグインの中でjQueryの"$"が使えるとは限りません。 自分だけがプラグインを使用する場合はjQueryの"$"がプラグインの中で使えるように注意すればいいかもしれませんが、 プラグインを公開する場合は、他の人にそのような事を期待してはいけません。
ですから、プラグインの中では常に"$"ではなく"jQuery"を使うようにします。
そうはいってもやはり"$"を使いたいという場合は以下の様に書けば"jQuery"の変わりに"$"が使えます。 これは仮引数"$"を受けとる関数を定義し、その関数に"jQuery"を渡すことによって、 関数内では"$"を"jQuery"の代わりに使用できるようにしています。

(function($) {
// ここでは"jQuery"の代わりに"$"が使用できる
})(jQuery);

まず、プラグインのオブジェクトを作成します。
ここではグローバルな名前空間を汚さないように、"jQuery.プラグイン名"としてオブジェクトを作成します。
"$.extend()"は引数のオブジェクトをマージする関数です。引数が1つの場合はjQueryオブジェクトに引数のオブジェクトがマージされます。

  $.extend({
    stripeTable : new function() {
      // 以降のコードはここに書く
    }
  });

オプションが指定されなかった際のデフォルト値を設定します。

      this.defaults = {
        pattern_num : 2
      };

次にストライプテーブルを作成するメソッド"construct"を書きます。
このメソッドは引数として、オプションのオブジェクトを受け取ります。
jQueryを使う人は連載第1回で説明したメソッドチェーンが使えることを期待しています。 jQueryのプラグインを書く場合はメソッドチェーンが使えるように、jQueryオブジェクトを返すようにメソッドを作成します。
"$(selector)"でエレメントを選択した場合、返されるjQueryオブジェクトは1つとは限りません。 複数のエレメントがselectorにマッチした場合はjQueryオブジェクトの配列が返されます。 そのためjQueryオブジェクトの配列にも対応できるように作成しなければなりません。
jQueryでは".each()"というjQueryオブジェクトの配列を処理するメソッドが提供されています。 また、jQueryオブジェクトのメソッド内では"this"はメソッドを呼び出したjQueryオブジェクト(あるいはjQueryオブジェクトの配列) を指します。そのため、"this.each()"を利用することでjQueryオブジェクトの配列にも対応することができます。
まとめると以下のようになります。

      this.construct = function(settings) {
        return this.each(function() {
          // 以降のコードはここに書く
        });
      };

<thead>と<tbody>が存在するか確認します。 存在しない場合は何もせずに終了します。
補足:".each()"メソッド内では"this"はjQueryオブジェクトではなく対応するDOMオブジェクトを指します。

          if (!this.tHead || !this.tBodies) return;

オプションの処理を行います。 デフォルト値として作成したdefaultsオブジェクトと、引数で受け取ったsettingsオブジェクトをマージします。 defaultsとsettingsで同じ名前のオプションはsettingsの値で上書きされます。
"pattern_num"の値が数値で1より大きいかチェックします。

          var config = $.extend({}, $.stripeTable.defaults, settings);
          if (config.pattern_num.constructor != Number || config.pattern_num <= 1) return;

<tbody>エレメント内の<tr>エレメントに"stripe-n"というクラスを追加します。 nには、1からpattern_numの範囲の数値が順番にいれられます。 ストライプの階層が3階層の場合(pattern_numが3の場合)は、テーブルの上の行から順番に stripe-1, stripe-2, stripe-3, stripe-1, stripe-2,・・・というふうにクラスを追加します。
補足:".each()"メソッド内では"this"はDOMオブジェクトを指しているため、 jQueryオブジェクトのメソッドを使用するには"$(this)"とする必要があります。

          $(this).children("tbody").children("tr").each(function(index) {
            $(this).addClass("stripe-" + ((index % config.pattern_num) + 1));
          });

以上でプラグインのオブジェクトの作成は終了です。
次にjQueryオブジェクトにメソッドを追加します。jQueryオブジェクトにメソッドを追加するには、 "jQuery.fn"にメソッドを追加するか、"jQuery.fn.extend()"関数を利用します。
ここでは、"stripteTable"という名前のメソッドを追加します。 実態は上で定義した$.stripeTable.constructです。

  $.fn.extend({
    stripeTable : $.stripeTable.construct
  });

以上のコードを全てまとめると最終的には以下のようなコードになります。

/**
*
*  StripeTable 1.0 - client-side table striping
*  Copyright (c) 2008 HDE, Inc.
*  Dual licensed under the MIT and GPL licenses:
*  http://www.opensource.org/licenses/mit-license.php
*  http://www.gnu.org/licenses/gpl.html
*
*  @description Create a striped table.
*
**/
(function($) {

  $.extend({
    stripeTable : new function() {
    
      this.defaults = {
        pattern_num : 2
      };
      
      this.construct = function(settings) {
        return this.each(function() {
          
          if (!this.tHead || !this.tBodies) return;
          
          var config = $.extend({}, $.stripeTable.defaults, settings);
          if (config.pattern_num.constructor != Number || config.pattern_num <= 1) return;
          
          $(this).children("tbody").children("tr").each(function(index) {
            $(this).addClass("stripe-" + ((index % config.pattern_num) + 1));
          });
          
        });
      };
      
    }
  });

  $.fn.extend({
    stripeTable : $.stripeTable.construct
  });

})(jQuery);

どうでしたか?最初はthisの扱いなど少し戸惑うこともあるかもしれませんが、すぐに慣れると思います。
jQueryのプラグインを作成する際に注意するべき点をまとめておきます。

  • プラグインのファイル名は"jquery.プラグイン名.js"にする
  • "$"ではなく"jQuery"を使う((function($){ })(jQuery))
  • グローバルな名前空間を汚さない(変数、関数はjQuery.プラグイン名の下に作る)
  • jQueryオブジェクトにメソッドを追加するには、jQuery.fnにメソッドを追加する($.fn.extend())
  • メソッドチェーンが使えるようにjQueryオブジェクトを返す
  • 選択したエレメントが複数の場合(jQueryオブジェクトの配列の場合)にも対応する(this.each())
  • jQueryオブジェクトのメソッド内では"this"はメソッドを呼び出したjQueryオブジェクト(または配列)を指す

プラグインを作成した場合は是非公開しましょう!!
自分が必要としているものは必ず誰か他の人も必要としています。

0 TrackBacks

Listed below are links to blogs that reference this entry: jQuery(3) : プラグインを作ろう.

TrackBack URL for this entry: http://lab.hde.co.jp/blog/mt-tb.cgi/18

Leave a comment

About this Entry

This page contains a single entry by furuya published on February 18, 2008 7:00 PM.

Tracを使ったバグ管理システム(1) : バグ管理システムとは was the previous entry in this blog.

日経225のSPF対応状況(2008年2月) is the next entry in this blog.

Find recent content on the main index or look in the archives to find all content.