目次


jQuery を扱う

第 1 回 中級レベルの jQuery: プラグインを使用して jQuery 関数を作成および拡張する

Comments

コンテンツシリーズ

このコンテンツは全#シリーズのパート#です: jQuery を扱う

このシリーズの続きに乞うご期待。

このコンテンツはシリーズの一部分です:jQuery を扱う

このシリーズの続きに乞うご期待。

はじめに

jQuery JavaScript ライブラリーに関する最初の連載 (「参考文献」を参照) を書いてから今に至るこの 6 ヶ月の間、jQuery の世界ではさまざまな出来事がありました。jQuery を支持してきた者にとっておそらく最も嬉しかった出来事は、Microsoft® が Visual Studio スイートに jQuery を採用し、これを現時点での唯一の JavaScript ライブラリーとして組み込むという決定に至ったことでしょう。これは極めて強力な支持の表明であり、Web アプリケーションの主要な JavaScript ライブラリーとしての jQuery の地位をさらに強固なものにしました。jQuery の人気が伸びていることを示すもう 1 つの証拠は、Google Trends の最近のグラフです。以前の記事に記載したグラフには、jQuery の人気が他の JavaScript ライブラリーを引き離し始めていることが示されていました。それから 6 ヶ月後、その差はさらに顕著になっています。図 2 と図 1 の Google Trends グラフを見比べてみてください (12 月の株式市場のような落ち込みは無視してください)。

図 1. よく使われる JavaScript ライブラリーに関する Google Trends (2008年6月)
よく使われる JavaScript ライブラリーに関する Google Trends (2008年6月)
よく使われる JavaScript ライブラリーに関する Google Trends (2008年6月)
図 2. よく使われる JavaScript ライブラリーに関する Google Trends (2009年1月)
よく使われる JavaScript ライブラリーに関する Google Trends (2009年1月)
よく使われる JavaScript ライブラリーに関する Google Trends (2009年1月)

この 5 回からなる連載記事では「ワンランク・ステップアップ」を目指し、jQuery を扱う上での中級レベルのトピックをさらにいくつか取り上げます。この連載で話題にするのは、プラグインとプラグイン開発、jQuery UI パッケージ、jQuery ウィジェットの作成方法に関してさらに掘り下げたトピック、より高度な Ajax (Asynchronous JavaScript + XML) 手法、そして最後に JavaScript や他のライブラリーと jQuery とのパフォーマンスの比較を行って連載を締めくくります。

連載 1 回目となるこの記事で話題にするのは、jQuery で使用されているプラグイン構造です。他の JavaScript ライブラリーよりも急速に jQuery が成長した第一の理由は、おそらくプラグインにあります。プラグインはサード・パーティーの開発者たちの支持を得てきたことから、これまで jQuery に機能を追加する何百ものプラグインが開発されています。その名前に示されているように、プラグインとは文字通り、jQuery に「プラグイン」するウィジェットまたはコード・モジュールのことで、プラグインが拡張する関数は jQuery のコア・ダウンロードに組み込まれます。プラグイン・コミュニティーは今まで何百というプラグインを作成してきましたが、この数は決して誇張ではありません。Web サイトで直面している問題が何であろうと、探し求めている (またはクライアントが要求している) ウィジェットが何であろうと、jQuery のプラグイン・ライブラリーのなかに既存のソリューションが見つかるはずです。さらに何よりも嬉しいことに、すべてのプラグインは無料でダウンロードして自分の Web サイトで使えます。

プラグインはユーザー・インターフェースのウィジェットに限られているわけではありません。プラグインには jQuery 構文の拡張や追加の Ajax 関数、さらには開発プロセスを改善するために必要になるかもしれない独創的な機能を組み込むこともできます。なかでも特に優れたプラグインでは、すでに組み込み JavaScript 機能のいくつか (スレッド化機能や setTimeout()setInterval() など) が jQuery 構文に変換されています。このプラグインによって、開発者は作業しやすく、管理も簡単な完全たる jQuery 環境を手にできるようになっています。

プラグイン

jQuery プラグイン構造には多くの利点があります。まずこの構造では、jQuery コアの外部にあるウィジェットと関数のなかから、必要なものだけを使用することができます。この点は、Web アプリケーションの場合には重要です。というのも、プラグインを追加するには、ダウンロードも追加で必要になり、その分、トラフィックも増えます。そこで、必要なプラグインだけを使用できるようにすることで、開発者が Web トラフィックをより賢く管理できるようになるからです。2 つ目の利点として、意欲的なサード・パーティーの開発者にとって、プラグイン構造では jQuery のコア・コードに自分のアイデアを押し込もうとしなくても、jQuery 関数を改善する独自のプラグインを作成することによって興味深いウィジェットを作り上げることができます。このことから、jQuery を使用してライブラリーを拡張する全員の独創力を結集して、新しい構想と新しいウィジェットをほぼ限りなく成長させていく可能性がもたらされます。クローズドエンド型の構造ではこれとは逆に、jQuery チームがプラグインのそれぞれを精査して承認しなければならないことが、創造性のボトルネックとなるはずです。3 つ目の利点として挙げられるのは、jQuery チームが作成したこのプラグイン・アーキテクチャーは、プラグインを作成する開発者とプラグインを使用する開発者の双方にとって非常に使いやすいことです。この点は、プラグインの爆発的な成長に大きく寄与しています。一方、これらの利点のすべてには 1 つのマイナス面があります。それは、同じ分野の開発者にレビューをしてもらう方法以外に、プラグインの公式なテスト構造がないことです。したがって、jQuery コアは徹底的にテストされたと保証されている一方で、プラグインを使用することにした場合には、そのプラグインをテストしたサード・パーティーを信じるしかありません。ミッション・クリティカルな Web アプリケーションの場合には必ず、この点を考慮してください。

プラグインを使用するために必要な作業は、JavaScript ファイル (jQuery ファイル自体を含め) の場合とほとんど同じように、プラグインをページに組み込むだけです。つまり、プラグインをページで使用しなければならない場合は、jQuery 本体のすぐ後にプラグインを追加すればよいことになります (リスト 1 を参照)。

リスト 1. プラグインを組み込む方法
<script src="jquery-1.2.6.min.js" type="text/javascript"></script>
<script src="jquery.alphanumeric.plus.js" type="text/javascript"></script>
<script src="jquery.blockUI.js" type="text/javascript"></script>

この記事では、プラグインの作成方法についての詳細や、プラグインがどのように機能するかについて詳しく説明することはしません。これらの詳細内容は、今後の記事で説明するつもりです。そこでは、独自のプラグインを新しく作成して、実際の jQuery プラグイン・リポジトリーに配置する手順を説明します。代わりに今回の記事では、私のお気に入りのプラグインをいくつか紹介したいと思います。私が日頃重宝にしているプラグインを紹介するためだけでなく、jQuery プラグイン・リポジトリーにはどのようなプラグインが用意されているかについて把握してもらいたいからです。読者の皆さんがプラグインに興味を持って、自分自身で調べてみようという気になることを願っています。

それでは早速、私のお気に入りのプラグインに話を進めます。

rightClick、extendedClick、wheel

Web アプリケーションの最大の目標の 1 つは、ユーザーが本物のデスクトップ・アプリケーションで作業していると思うようにユーザーを「騙す」ことです。「騙す」という言葉を使っていますが、実にそのとおりの意味で、Web アプリケーションはデスクトップ・アプリケーションのルック・アンド・フィールをできるだけ模倣しようとしています。例えば、ユーザーが通常デスクトップ・アプリケーションを使用する場合、ある特定の場所にツールバーが表示されることを期待しているとしたら、Web アプリケーションでも同じ場所にツールバーを配置しようとします。それによってユーザーはデスクトップ・アプリケーションから Web アプリケーションに移行しやすくなり、その結果、Web アプリケーションが成功する可能性も大きくなります。

その一方で、大体において、これまで Web アプリケーションの 1 つの分野はデスクトップ・アプリケーションとそれほど一致していませんでした。それは、マウス・イベントへの応答です。それはどういう意味かと尋ねる人もなかにはいるでしょう。Web アプリケーションでマウスをクリックすると、Web アプリケーションは正常に機能するからです。それもその通りで、ほとんどの Web アプリケーションはマウスの左クリックを何の問題もなく処理します。正直な話、Web サイトでマウスの左ボタンだけを使うことに慣れているユーザーはあまりにも多いため、Web アプリケーションは Apple アプリケーションのように、1 つのボタンしか使用しなくなっています。しかし、あらゆる Windows® アプリケーションでは 2 つのマウス・ボタンが使用されています (3 つ目のボタンを使用するアプリケーションまであります)。マウスの左ボタンがコマンドを起動し、右ボタンが操作の選択肢を表示するという仕組みです。ユーザーはこのようなマウスの使い方に慣れ親しんでいるというのに、どうして多くの Web アプリケーションではマウスの右ボタンを無視しているのでしょうか。さらに付け加えると、Web アプリケーションは CTRL キーや Shift キーを同時に押しながらのクリック、そしてマウス・ホイールまで無視しています。Web アプリケーションがこれほど多くのマウスのアクションを無視するとなれば、真の意味でデスクトップ・アプリケーションを模倣することはできません。真の Web アプリケーションであれば、マウスに考えられるあらゆる用途を十分に活用するはずです。

マウスの右クリックを無視する Web アプリケーションと、そうではない Web アプリケーションの違い、そしてマウスのボタン操作の処理を追加することによって Web サイトの機能をどのように拡張できるかを知るには、Gmail と Yahoo!メールとを比較してみてください。Gmail のファンには言いにくいのですが、私が思うに、この点においては Yahoo!メールのほうが勝っています。Gmail では、マウスの右クリックは他の Web ページでの場合と同じように処理されます。例えば Gmail でメッセージを右クリックすると、「戻る」、「要素を調査」、「すべて選択」などの選択肢を含んだメニューが表示されますが、これらのアクションはメッセージの操作とどう関係するのでしょうか。もちろん、何の関係もありません。つまり、このページではマウスの右ボタンは使いものにならないということです。その一方、Yahoo!メールではマウスの右クリックがどのように処理されるかと言えば、Yahoo!メールでメッセージを右クリックすると、「開く」、「印刷」、「送信者に返信」、「削除」などの操作を含んだメニューが表示されます。これらの操作は、メール・アプリケーションに通常付きものの操作です。このような操作を含んだメニューを表示することによって、デスクトップ上にあるようなメール・アプリケーションを模倣した、完全な Web アプリケーションとなります (Outlook でメッセージを右クリックして、Yahoo!メールと Gmail のどちらのメニューに似ているかを確認してみてください)。図 3 と図 4 に、右クリックで表示されるメニューの違いを示します。

図 3. Yahoo!メールで右クリックした場合
Yahoo!メールで右クリックした場合
図 4. Gmail で右クリックした場合
Gmail で右クリックした場合

Web アプリケーションでのマウスのクリック問題を解決する jQuery プラグインとして最初に紹介するのは、その名もぴったりの rightClick プラグインです。このプラグインはマウスの右クリックだけでなく、マウスの右ボタンの押下と解放操作も取り込みます。さらに rightClick は、それぞれのブラウザーに固有の右クリック・コンテキスト・メニューを無効にすることもできます。例えば FireFox で表示される右クリック・メニュー (図 4) を無効にして、このメニューが表示されなくなるようにすることで、ブラウザーのデフォルトの振る舞いと競合することのない独自のカスタム右クリック・メニューを作成できます。

リスト 2. rightClick プラグイン
// set up the div that will capture our events
<div id=rightClickSample></div>

// when the right mouse is clicked on this div, increase the width
// by 10 pixels.  Also, do not show the browser-specific pop-up
// menu
// This, of course, should be in the $(document).ready function

$("#rightClickSample").rightClick(function(e){
   $(this).width($(this).width()+10);
});

$("#rightClickSample").noContext();

Web アプリケーションでのマウス操作を拡張できる 2 つ目のプラグインは、Ctrl、Alt、そして Shift キーの操作を取り込む機能を追加するプラグインです。一部のアプリケーション (Adobe Photoshop など) はこれらのキーを常に使用するため、マウスを使いながらキーで操作するほうが快適だというユーザーもいます。しかし、この 3 つのキーを jQuery コア・コードで使用するとなると簡単な話ではなく、追加のコードが必要になってきます。そこで、すでに作成されたテスト済みのプラグインを使用するという手があります。

extendedClick プラグインが提供する各種の関数は、マウスと一緒に押せるさまざまなヘルパー・キーの組み合わせを表します。ご想像の通り、これらの関数には ctrlclick()shiftclick()altclick()ctrlaltclick()ctrlshiftclick()altshiftclick()ctrlaltshiftclick() などがありますが、残念ながらこれらの関数と組み合わせられるのはマウスの左ボタンだけです。右クリックの例で説明したように、マウスのもう片方のボタンを無視するのは賢明な策とは言えません。しかし今のところ、右クリックにヘルパー・キーを組み合わせるプラグインは存在しないので、このようなプラグインを作成して extendedClick プラグインとマージし、新しいプラグインを作成するという作業は、意欲的な開発者にお任せします。

右クリックの例に代わって、今度は Shift キーを押しながらマウスの左ボタンをクリックすると div が 10 ピクセル分増え、Ctrl キーを押しながらマウスの左ボタンをクリックすると 10 ピクセル分減る例を記載します。

リスト 3. extendedClick プラグイン
// set up the div that will capture our events
<div id=extendedClickSample></div>

// when the left mouse is clicked with the shift key held down,
// grow the div by 10 pixels
$("#extendedClickSample").shiftclick(function(e){
   $(this).width($(this).width()+10);
});
   
// when the left mouse is clicked with the ctrl key held down,
// shrink the div by 10 pixels
$("#extendedClickSample").ctrlclick(function(e){
   $(this).width($(this).width()-10);
});

デスクトップ・アプリケーションと Web アプリケーションとのギャップを埋める最後のプラグインは、マウスのホイールに対処するプラグインです。請け合いますが、(HTML 入力要素を除き) マウスのホイールを使用できる Web サイトにアクセスしたことのあるユーザーはほとんどいないはずです。だからといって、アプリケーションでマウスのホイールを使用するのが不可能だというわけではありません。アプリケーションでマウスのホイールを使用する一例は、写真をアップロードできる Web サイトで、マウスのホイール操作によってズームイン、ズームアウトできるようにすることです。このような操作はデスクトップ・アプリケーションではすでに可能になっていますが、大抵の Web アプリケーションではおそらく対応できないはずです。

マウス・ホイール操作の例として、上記と同じ div のサイズの増減を、今度はマウス・ホイールによって制御できるようにします。マウスのホイールを上に回転させると div のサイズが大きくなり、下に回転させると小さくなるという仕組みです。ホイール付きマウスをお持ちでないとしたら、このプラグインは完璧に動作すると見なしてもらって構いません。

リスト 4. マウス・ホイール・プラグイン
// set up the div that will capture our events
<div id=wheelSample></div>

// attach an event handler for the wheel to this div
// notice that we use the e.delta to determine how many "notches" the wheel
// was moved.  One notch is either 1 (if up), or -1 (if down).  So, as
// a result, we can simply add it to the current width, letting the
// sign of the delta grow or shrink the div.
$("#wheelSample").wheel(function(e){
   $(this).width($(this).width()+10*(e.delta));
});

ここで紹介した 3 つのプラグインは、Web アプリケーションのルック・アンド・フィールをデスクトップ・アプリケーションのようにする上で、非常に重要だと思います。この 3 つのプラグインによって、Web アプリケーションとの対話動作がマウスの左クリックだけに限定されることなく、通常のデスクトップ・アプリケーションと同じように Web アプリケーションがマウスによるあらゆる形の対話動作を取り込むことができるようになります。さらに、今後数年間にわたり、開発者に既存のデスクトップ・アプリケーションを Web アプリケーションに変換するという任務が課せられる機会は次第に増えてくるはずです。これらのプラグインを使って、ユーザーがデスクトップで使用していたすべてのマウス操作を Web でも提供することにより、デスクトップ・アプリケーションから Web アプリケーションへの移行は容易になります。

blockUI

blockUI は、モーダル・ダイアログの作成機能を提供するプラグインの 1 つです。ここで読者の皆さんは、JavaScript では alert()confirm() などの実に見事なモーダル・ダイアログをすでに提供していると思っていることでしょう。これらの既存のモーダル・ダイアログが開発者にとって素晴らしいものであること、そしてユーザーに絶大な人気があることは否定できません。優れた設計の Web サイトで見栄えがすることも事実です。その一方で、開発者にはさらに優れた方法が用意されています。その方法では実際にユーザーから情報を収集し、実際にモーダル・ダイアログが Web アプリケーションに属しているかのように見せることができます。alert/confirm のファンはご連慮なく、次のセクションまで読み飛ばしてください。

皮肉は抜きにして、モーダル・ダイアログという点から見ると alert/confirm 関数には大きな欠点がいくつかあります。何よりもまず、これらの関数で可能なのは情報の表示だけで、confirm 関数での「OK」または「キャンセル」の他に情報を収集することはできません。それよりも理想的なのは、柔軟性があり、必要な要素を追加できるポップアップ・ダイアログ・ウィンドウ、つまり他のプログラミング言語で使い慣れているようなダイアログ・ウィンドウです。この問題に対処するプラグインとして私が気に入っているのが blockUI で、このプラグインは扱いやすく、同じ 1 つの Web アプリケーションで多数のダイアログを極めて柔軟に操作できます。その上、多種多様なダイアログも操作できます。

この記事に付属のサンプル・コード (「ダウンロード」を参照) に blockUI を使ったモーダル・ダイアログを作成してあります。コードとオプションの詳細に入る前に、このモーダル・ダイアログがどのように表示されるかを見てください。

図 5. blockUI の例
blockUI の例
blockUI の例

図 5 を見るとわかるように、モーダル・ダイアログはページ上に表示されます。ページの他の部分に対する入力はダイアログの下にある半透明の層によってブロックされます。この効果的なブロックにより、ユーザーがこのダイアログの他には Web アプリケーションと対話できないようにしています。このコードで使用しているブロック手段は IFrame ですが、それは大して重要ではありません。このプラグインの作成者が、IFrame によるブロックを各種のブラウザーでテストして、機能することを確認しているからです。

ダイアログを作成する際の最初のステップは、ダイアログのメッセージを指定することです。メッセージには何を指定することもできます。例えば、ユーザーに対して (alert() 関数を複製して) テキストを表示したり、あるいは HTMLを表示したりすることもできます。さらには (太字、色などで) 装飾したメッセージを作成することもできます。ただし、このプラグインで最も価値のある点は、メッセージとして div を提供し、任意のレイアウト、そして必要な数の入力、ボタン、情報をいくらでも使用して事実上、独自のダイアログを作成できることです。

リスト 5. blockUI プラグイン
// this will create a dialog with our default text,
// effectively replicating the 
// alert() function
$.blockUI({message: "This is a sample dialog"});

// however, we can add any HTML we want to the message, making it look closer
// to our own Web site
// $.blockUI({message: "<h2>Sample Dialog</h2><p style='color:green;'>
              This is our message</p>"});

// perhaps most importantly, we can add a div to the message, allowing
// us to create our own dialog, with the look, feel, message, and input we want
<div id=loginMessage style="display:none;cursor:default;">
      <p><h2>Login</h2>
      <p>Username: <input type=text id=user>
      <p>Password: <input type=text id=pass>
      <p><input type=button value="OK" id=ok> 
      <input type=button value="Cancel" id=cancel>
</div>

// and the jQuery code to show this is pretty much the same
$.blockUI({ message:$("#loginMessage")});

読者が早速、自分のサイトに blockUI を適用する前に、このプラグインに残っている 2 つの小さな問題について説明しておきます。まず 1 つは、このコードではまだダイアログを閉じるところまでカバーしていないことです。皆さんにとって、この点は取るに足らない問題でしょう。もう 1 つの問題は、リスト 5 のコード・スニペットで作成したダイアログのすべては、デフォルトの blockUI ルック・アンド・フィールに設定されることです。このままでは、望ましいとは言えません。このプラグインの最大の売りの 1 つは、ダイアログに独自のルック・アンド・フィールを作成できることだったはずです。blockUI には CSS コードのスニペットが付属しているので、このスニペットを独自の CSS ファイルに取り込んでください。そうすれば、ダイアログの外観を自由に変更できるようになるので、必要に応じてカスタマイズできるようになります。ただし、blockUI の CSS 属性を無効にする前に、プラグインに対してプラグイン自体のデフォルトではなく、CSS ファイルを検索するように指示することも忘れないでください。リスト 6 のコード・スニペットに、私がサンプル・コードで使っているコードを記載します。これを見ると、ダイアログを閉じる方法、独自の CSS を使用する方法、そして CSS で使用できるオプションがわかります。

リスト 6. blockUI プラグインの詳細
// These two functions tell the BlockUI that
// you want to use your own CSS
// code to define how the dialogs will work.  The first line
// tells it you want to use your own CSS for the dialog,
// the second line tells it you want your own CSS 
// for the semi-transparent
// layer between the page and the dialog.
$.blockUI.defaults.css = {};
$.blockUI.defaults.overlayCSS = {};

// when the show button is pressed, we'll display the dialog.
// we want to display our own custom DIV.  However, note here
// that we want to override the CSS-defined height and width.
// After all, it would be difficult for an entire site to have
// predefined widths and heights if every dialog is slightly
// different.
$("#show").click(function(){
   $.blockUI({ message:$("#waitMessage"), css: {width:'500px', height:'160px'} });
});

// When the cancel button is pressed on the DIV dialog,
// we can close the dialog
$("#cancel").click(function(){
   $.unblockUI();
});

// the CSS you can override to make it look good on your site
div.blockOverlay
{
    -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=50)"; 
    filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=50); 
    -moz-opacity:.70;
    opacity:.70;
    background-color: #228518;
}

div.blockMsg
{
    width:  20%;
    top:    20%;
    left:   30%;
    text-align: center;
    background-color: #fff;
    border: 3px solid #044600;
    -moz-border-radius: 10px;
    -webkit-border-radius: 10px;
    -ms-filter: "progid:DXImageTransform.Microsoft.Alpha(Opacity=100)";
    filter: progid:DXImageTransform.Microsoft.Alpha(Opacity=100);
    -moz-opacity:1;
    opacity:1;
    padding: 15px;
    color: #000;
}

私の経験では、このプラグインはさまざまな状況で重宝しました。例えば JavaScript で confirm() 関数を置き換える必要がある場合、このプラグインは極めて短時間で実装することができます。どれだけ見栄えが良くなるかは言うまでもありません。それよりも込み入った状況では、E メール・アプリケーションでファイルをアップロードするためのダイアログとして使用したり、画像表示アプリケーションで写真のライトボックスとして使用したこともあります。また、このプラグインを Ajax 呼び出しと組み合わせれば、ページの取得に時間がかかるという情報を画面に重ねて表示することで、ページを何度もロードしようとするのを防ぐことができます。さらにこのプラグインは実質上、情報を表示する画面領域を広げることになります。最後に付け加える点として、alert/confirm 関数の制約を排除するこのプラグインは、デスクトップ・アプリケーションの場合と同じようにダイアログを考慮しながらソフトウェアを設計することを可能にします。

printArea

printArea プラグインは Web アプリケーションの物足りない部分を補ってくれますが、このプラグインは、かなり役に立ちます。このプラグインの基本となる動作は、特定の HTML 要素だけを出力できるようにする動作です。window.print() ボタンを呼び出して、後は最善の結果を期待するだけの Web アプリケーションでは、このプラグインは他に代えられない強力な出力手段となります。異なるインターネット・ブラウザーを操作したことのある誰もが言うように、異なるブラウザーで同じページを出力した場合、その出力がまったく同じになることはほとんどありません。さらに、テキスト・エリア内のテキストだけを出力するとなると問題が持ち上がります。今まで、テキストのみの出力は極めて困難だったからです。

前述の通り、このプラグインではページ上の特定の要素だけを出力し、残りは出力されないようにできます。私はこのプラグインを E メール・アプリケーションで使用して、ユーザーがテキスト・エリア内に含まれるメッセージを出力できるようにしました。また、レポートを表示するページで、レポートにページ上のさまざまなボタンやグラフィックが出力されないようにするために使用したこともあります。ユーザーにお馴染みの例としては、航空券の出力も挙げられます。Web ページ上の航空券には通常、大量の情報とグラフィックが表示されますが、このプラグインによって、バー・コードとそのフライトに搭乗するための基本情報だけが記載された航空券を出力できるというわけです。

リスト 7. printArea プラグイン
<p>An advertisement that you don't want printed out.
<p>Another advertisement that you don't want printed out.
<div id=printable>
<table width=40% cellpadding=3 cellspacing=0 border=1>
<tr><th>Name</th><th>Age</th><th>Height</th></tr>
<tr><td>John Q</td><td>23</td><td>6'1"</td></tr>
<tr><td>Jane Q</td><td>23</td><td>5'1"</td></tr>
<tr><td>Jimmy R</td><td>23</td><td>5'6"</td></tr>
</table>
</div>
<p><input type=button id=printButton value="Print">
<p>All the annoying disclaimer text you don't want printed out.
		
// Capture the click on the "Print" button.  Then, you can call the printArea()
// function on the "printable" div we used to wrap the portion of the page we want
// printed.  The only thing that will get printed to the printer will
// be the table, and all the annoying text won't be.
$("#printButton").click(function(){
   $("#printable").printArea();
});

このプラグインでは、ページ上にある要素の出力を、実にわかりやすく簡単な方法で制御することができます。さらに、このプラグインが優れている点として、Internet Explorer と Firefox の両方で同じく有効に機能します。そのため、この両方のブラウザーでページの出力方法を制御する手段として使用すれば、大きな頭痛の種を取り除くことができます。唯一の欠点は、ユーザーがプラグインの Print ボタン、または制御可能なページの領域をクリックしなければ機能しないことです。ユーザーがブラウザーの Print ボタンをクリックした場合には、問題のある古い出力機能に戻ってしまいます。さらに厄介なことに、ブラウザーの Print ボタンの実行を停止することも、このボタンの使用について警告することもできません。したがって、プラグインの Print ボタンをクリックするだけの賢さをユーザーが持ち合わせていることを当てにしなければなりません。代わりの手段は当然、ユーザーをこの方程式から外し、単に特定の条件で自動的に出力するようにすることです。

AlphaNumericPlus

ユーザー・インターフェースの設計では一般的に、ユーザーに対する期待を低くしてコードを作成します。その好例は、フォームのテキスト・フィールドの操作です。電話番号を入力するようにフィールドをセットアップしたとしても、誰かしらが文字を入力することはわかっています。

このような誤った入力は、3 つの個所で防ぐことができます。まず 1 つは入力がデータベースに書き込まれる前に、サーバー・サイドで不正な入力がないかどうかをチェックすることです。その場合には、すべての入力フィールドをチェックして入力が有効なフィールドとそうでないフィールドとを判断し、入力が有効でない場合にはクライアントにメッセージを返す Java™ コードや PHP コードを作成することができます。エラー・チェックの第 2 レベルは、JavaScript によるクライアント・サイドでのチェックです。クライアント・サイドで入力条件をチェックすることにより、ネットワーク・トラフィックが軽減され、ユーザーへのレスポンスがより速く返されるようになります。そしてエラー・チェックの最終レベルでは、「ユーザーに対する低い期待」という設計パターンを最大限に活用します。つまり、最初からユーザーに不正な情報を入力させないようにするということです。上記で述べた例では、なぜ電話番号の代わりに文字をサーバーに送信したり、フォームをサブミットする前に JavaScript で文字があるかどうかをチェックしたりするのでしょうか。最善のソリューションは、単にユーザーに一切の文字を入力させないことです。

このプラグインがベースとしているのは、Web アプリケーションのテキスト・フィールドは、ふさわしいと判断される入力だけを受け入れるようにするという発想です。したがって、フィールドに数字だけを含める場合には、テキスト・フィールドに数字だけを受け入れさせます。フィールドに文字だけを含める場合には、文字だけを受け入れさせます。この概念に従って作成されているのが、以下のプラグインです。

リスト 8. AlphaNumeric プラグイン
<p>Alpha-only: <input type=text width=20 id=alphaOnly>
<p>Numeric-only: <input type=text width=20 id=numericOnly>

// This code will prevent unworthy characters from being entered
// into our text fields, assuring valid input
$("#alphaOnly").alpha();
$("#numericOnly").numeric();

標準 AlphaNumeric プラグインは上記のとおりですが、私はこのプラグインを独自の目的に合わせて拡張しました。ここからは、その追加内容について説明します (これらの追加内容は、この記事のダウンロードに含まれています)。私は、文字または数字のみを入力するように制御できるとしたら、プラグインを拡張して $、%、または & などの特殊文字も組み込めるはずだと考えました。この前提に従えば、フォームでのテキスト・フィールドの用途に応じた特定のルールをテキスト・フィールドに追加できるはずです。例えば、E メール・アドレス用に使用されているテキスト・フィールドは、標準の数字と文字だけではなく、E メール・アドレスで有効な文字のすべてを許容しなければなりません。つまり、E メール・アドレスのフィールドにはアンダーバー (_)、ハイフン (-)、アットマーク (@)、ピリオド (.) を使用できるということです。これ以外の特殊文字は無効で、E メール・アドレスに含まれているとエラーが発生するため、これらの特殊文字については入力をブロックします。これによって E メール・アドレスの有効性が 100% 保証されるかと言えば、実はそうでもありません。ユーザーが「a@a@.com」のような途方もないアドレスを入力する可能性はまだ残っているからですが、とりあえずは特定の特殊文字を許容することが最初のステップとなります。

標準 AlphaNumeric プラグインに加えた内容は、10 進数、通貨、E メール・アドレス、電話番号、時刻、日付を処理するためのものです。リスト 9 に、このコードを記載します。

リスト 9. AlphaNumericPlus プラグイン
// will only allow numerals and the . 
// and , characters (because I'm thinking international 
// here, and some countries use a , for a decimal)
$("#decimalOnly").decimal();
// same as the above, but it adds support for the "%"
$("#percentOnly").percent();
// as described above, only allows valid e-mail characters
$("#emailOnly").email();
// allows only numbers and the ( and ) and - characters
$("#phoneOnly").phone();
// allows only numbers and the : character
$("#clockOnly").clock();
// allows only numbers and the / and - characters
$("#dateOnly").date();
// this is the only one that's slightly different, in that
// it requires you to pass in the valid currency symbol, so you can
// pass in a pound sign or euro if you're using this overseas
$("#currencyOnly").currency("$");

上記の AlphaNumericPlus プラグインは、ユーザーによる無効な入力を防ぐための第 1 レベルの防御策です。ある特定の場合において、無効な文字を許可しないことによって、エラーの可能性を最小限にするだけでなく、ユーザーに対して即座に、有効な情報を入力していないと注意を促す仕組みとなっています。例えば、ユーザーが電話番号のフィールドに文字を入力しようとしても何も表示されないため、ユーザーはすぐにエラーであることがわかります。多くの場合、すべての入力が終わってからエラーをすべて修正するよりも、この素早い応答のほうがユーザーには感謝されます。

第 2 レベルの防御策は、フォームをサブミットした時点でのクライアント・サイドでのチェックです。この例の場合、電話番号が正しい桁数になっているかどうかなど、データがすべて有効なフォーマットであることをチェックすることができます。そして最終レベルでは、サーバー・サイドでのチェックによってフォーマットが有効であることをダブルチェックすると同時に、入力された情報をデータベースの既存の情報に照らし合わせてチェックを行います。このようにこのプラグインを最前線で機能させて、3 つの方面から上手く攻めることが最善のソリューションです。完璧ではないものの (すべての文字が有効であっても、無効なフォーマットを入力することはできるため)、ユーザーに素早いフィードバックを提供できることは確かです。

Calculation

Calculation プラグインも、特定の状況で重宝するプラグインです。ほとんどの優れたプラグインと同様、このプラグインには少数の機能しかありませんが、その役割をしっかりと果たします。その名が示すように、Calculation プラグインはフィールド内の数値を計算して合計、平均値、最大値、あるいは最小値を出します。さらに、フィールドの数字を解析することも可能です。このプラグインが極めて柔軟な理由は、あらゆるタイプの要素から数値を合計できるところにあります。例えば、DIV、INPUT TEXT、および SPAN が含まれる要素の配列をプラグインに渡すと、プラグインはそれぞれのフィールドに含まれる数字を探し、すべての数字を数値に変換して合計を返します。この機能は特定の状況で役に立ち、すべての数値演算をエラー・チェックするという頭の痛い作業から救ってくれます。

ただし、このプラグインには注意する点が 1 つあります。それは、プラグインのすべてが jQuery オブジェクト自体を返すという標準プラグインの決まりを破ることです。この記事で説明する他のあらゆるプラグイン、そして私が扱ったことのある他のあらゆるプラグインでは、関数が jQuery オブジェクトを返します。つまり、「鎖を切る」ことはありません。しかし Calculation プラグインはこの決まりには従わず、数値を返すことによって鎖を断ち切るため、このプラグインを呼び出した後には jQuery 関数を連結できなくなります。

Calculation プラグインについて、やや高度で複雑な例を見てみましょう。図 4 に示すウィジェットには、ユーザーがパーセントの値を入力できる一連のフィールドがあります。ウィジェットはすべてのフィールドの合計が 100% であるかどうかをチェックし、合計が 100% でない場合には、エラーとしてパーセントの合計を赤で表示します。このようなウィジェットは、出資の配分をユーザーに入力するように求める資金計画のページでよく見掛けるものです。

図 6. 401k 出資ウィジェット
401k 出資ウィジェット
401k 出資ウィジェット
リスト 10. Calculation プラグイン
// Set up the table that contains the widget.
// Note that we add a class to it called
// "percentSimple", which will be used in the jQuery 
// code, as well as adding a unique
// ID to the table "sortTable1".
// Also note that each text field that will have a percent 
// typed into it has the
// class of "percent" added to it.
// Finally, note in the table footer a field called "percentTotal"
<p><table width=300 class="percentSimple" cellpadding=0 cellspacing=0 id=sortTable1>
<tbody>
  <tr><td class="left">
    S&P 500 Index
  </td>
  <td>
    <input type=text class="percent textfield"> %
  </td>
  </tr>
  .......
<tfoot>
  <tr><td>
    Total
  </td>
  <td>
    <span class=percentTotal></span> %
  </td>
  </tr>
</tfoot>
  
// take advantage of our previous plug-in and limit the percent fields
// to just numbers
$(".percent").numeric();

// capture any keyup events from all the "percent" fields
// when these occur, we are going to recalculate the total percent
$("table.percentSimple input.percent").keyup(function(){
    // figure out which table this occurred in (in case there's more than 
    // 1 widget on a page
    var table = $(this).parents().filter("table.percentSimple");
    var ID = table.attr("id");
    // Find the sum of all the "percent" fields, by using
    // our calculation plug-in
    var sum = $("#" + ID + " input.percent").sum();
    // cache the span called "percentTotal"
    var totalField = $("#" + ID + " .percentTotal");
    // update the total in the "percentTotal" field
    totalField.html(sum);
    // if the sum != 100%, then we'll attach an error to it
    if (sum != 100 && sum != 0)
    {
       totalField.addClass("error");
    }
    else
    {
       totalField.removeClass("error");
    }
});

このように、Calculation プラグインの使用方法は限られていますが、正しく使えば非常に効率的で時間の節約となります。私は max/min、average、sum 関数しか組み込んだことがありませんが、極めて意欲的な開発者が Microsoft Excel アプリケーションで使っている関数をすべて組み込んだ 1 つのスプレッドシート・プラグインに仕上げることは想像に難くありません。このスプレッドシート・プラグインが標準偏差、支払額、将来の値などを出すための関数 (私は金融を扱っているため、これらの関数が最もわかりやすいとうだけです) を提供したとしたらどうでしょう。さらに、基本的なスプレッドシートの関数をページに提供する Web サイトや、ユーザーが複雑な式を入力することなくスプレッドシート風の独自のページを作成できる Web サイトでスプレッドシート・プラグインを使用した場合を想像してみてください。

Timeout/Interval

私が JavaScript でもどかしく感じることの 1 つは、一般的なスレッド設計との互換性がないという点です。Swing の Java ユーザー・インターフェースからJavaScript Web アプリケーションに移行したときに、JavaScript では Java コードで一般的に見られるマルチスレッド・インターフェースを複製できないことがわかりました。代わりに JavaScript では setTimeout() メソッドと setInterval() メソッドを使用します。これらのメソッドは、私が Java コードで使い慣れたスレッド設計に似ていますが、まったく同じというわけではありません。setTimeout() メソッドは引数に、コールバック・メソッドを表すストリングと、タイムアウト値を表すミリ秒単位の数値を取ります。もう一方の setInterval() メソッドも同じ引数を取りますが、このメソッドはタイムアウトを呼び出し間隔として、コールバック・メソッドを繰り返し呼び出します。

JavaScript のスレッド設計を Java のスレッド設計と比較すると、Java のスレッド設計では、1 つのスレッド・オブジェクトを作成して、そのオブジェクトで start()stop() を呼び出すことによってスレッドが実行するタイミングを制御し、run() メソッドをクラス定義の中で直接定義します。このことから、2 つのスレッド設計の違いは明らかです。JavaScript のスレッド設計ではスレッドを簡単に開始できますが、停止するのは難しいことがあります。なぜなら、JavaScript のスレッド設計は ID を頼りにタイムアウト/インターバルを停止するからです。これらの ID は、setTimeout/setInterval 関数から返されます。以下のコードを見てください。

リスト 11. JavaScript のスレッド
// creates a thread with ID of threadID,
// which will call myCallBack()
// every 1 second (1000 ms = 1 sec)
var threadID = setInterval('myCallBack', 1000);

// will stop the thread from calling myCallBack()
clearInterval(threadID);

リスト 11 のコードは、あまり実用的とは言えません。このコードでは、スレッドが実行する前からオフにされるため、スレッドは 1 回も実行されないからです。setInterval() を呼び出し、その次の行で clearInterval() を呼び出していますが、setInterval() 呼び出しの後に一時停止がないことから、実質的には何も起こりません。これに対するソリューションは、リスト 12 のとおりです。

リスト 12. もう 1 つの JavaScript のスレッド
$(document).ready(function() {
  // store the ID as a global variable
  var threadID;

  // creates a thread with ID of threadID, which will call myCallBack()
  // every 1 second (1000 ms = 1 sec)
  threadID = setInterval('myCallBack', 1000);

  // will stop the thread from calling myCallBack()
  $("#hypotheticalStopButton").click(function(){
    clearInterval(threadID);
  });

上記のコードなら、threadID が JavaScript コードのどこからでも参照できるグローバル変数として保存されるため、上手くいくはずです。このソリューションはこうした単純な例には有効ですが、Web アプリケーションにさらに多くのスレッドが導入されて Web アプリケーションとの対話が難しくなってきた場合にはどうなるでしょうか。かなりの数のグローバル変数を使用しつつも、さまざまなタイミングで適切なスレッドが停止/開始されることを願うといった JavaScript コードでは、管理するのが難しくなるはずです。この問題に加え、Web アプリケーションではよくあるように、関数をきっかり 10 回呼び出さなければならない場合もあります。この場合、グローバル変数をさらに追加する必要があるだけでなく、スレッド作成のなかでインライン関数を作成することはできないため、スタンドアロン関数を参照せざるを得なくなります。このように、ページ上のスレッドが複雑になるにつれて、複雑さは一気に増していきます。

Timers プラグインでは、JavaScript で Web アプリケーションのスレッドを操作する際の問題を単純化するために、スレッドの操作方法を一変させ、(私の見解としては) Java コードに近づけています。threadIDsetInterval() 関数から返されることに頼る代わりに、Timers プラグインはスレッド名をその作成時に選択できるように設計を変更します。そのため、コードの別の場所で使うためにすべてのスレッド ID を保存するという必要はもうありません。この微妙な変更が、その他の有益な変更に加え、JavaScript でのスレッドの操作を遙かに簡単にしています。リスト 13 のコードは、Timers プラグインと連動するようにリスト 12 のサンプル・コードが変更されたものです。このコードのほうが遙かに操作しやすいと思う私の意見に賛成ですか?

リスト 13. タイマーを使用した JavaScript のスレッド
// attach an event to the start button,
// kicking off the thread
$("#start").click(function(){

// using the Timer plug-in, we attach a thread to a page element
// we call the "everyTime" function, which is analagous to the
// setInterval function.
// This function takes several arguments:
// - the timeout interval
// - the name of the thread, notice how we can choose the name here
//   and not have to worry about storing the value anywhere
// - the function to call each interval, notice how we can define
//   the inline function here, without creating an extra function
//   elsewhere, simplifying development of the thread.
// - (optional) how many times to run it before stoppping, so if
//    you put a 10 there, it would run it 10 times and then stop
// - (optional) a true/false of whether to start the next interval
//   if the previous one isn't completed yet
 $("#timerSample").everyTime(500, 'growSquareThread', function(){
 var t = $(this);
 t.height(t.height()+5);
 t.width(t.width()+5);
 });
});

// attach an event to the stop button.  Notice how we can simply
// call a stop with the name of the thread, without worrying
// about the threadID
$("#stop").click(function(){
  $("#timerSample").stopTime("growSquareThread");
});

Timers プラグインが JavaScript でのスレッドの操作を容易にすることは明らかです。一見するとわずかな変更にしか見えないかもしれませんが、その内容を調べると、このプラグインによってコードが一段と簡潔になることが理解できるはずです。第一に、スレッドをまとめて 1 箇所で定義できます。つまり、開始メカニズム、遅延、ループを行う回数、そして繰り返し処理ごとに実行するコードをすべて 1 箇所に定義するということです。これによって従来の JavaScript スレッドよりも操作しやすくなるだけでなく、あえて言うなら、Java スレッドよりも簡単になります。Timers プラグインでは、スレッドそのものが必要なものをすべて、コード・ブロックの中に完備しています。コードのどこかしらにある関数を参照する必要はもうありません。グローバル変数に含まれる threadID を追跡する必要も、スレッドが完了した繰り返し処理の回数を複雑なコードで追跡する必要もありません。スレッドを停止するのも簡単で、スレッドの停止トリガーがスレッドの作成時に指定されたスレッド名を使用すればよいだけの話です。threadID について知る必要さえなくなります。

まとめ

以上でプラグインに関する記事は終わりですが、jQuery で使用できるプラグインすべての調査が終わったわけでは決してありません。jQuery プラグイン・サイトに用意された 200 から 400 あるプラグインのうち、この記事で紹介したのはたった 8 つだけであり、ほんの一部を抜粋したに過ぎません。しかし、私はいずれもデスクトップ・アプリケーションと Web アプリケーションとのギャップを埋める上で役立つ重要なプラグインだと考えています。これらのプラグインは、現在 JavaScript と jQuery の間にあるギャップを埋めようと試みています。この 8 つのプラグインから学んだ内容、そして自分の作業にこれらのプラグインをどのように役立てられるかを考えてから、他の何百ものプラグインに考えられる利用方法を検討してください。ある程度の時間を割いて jQuery サイトのプラグイン・リポジトリーをブラウズするだけでも、是非ともお薦めです。私も jQuery サイトをブラウズしてプラグインのそれぞれに目を通すなかで、この記事で取り上げたプラグインのいくつかを見つけました。優れたプラグインを見つけるもう 1 つの有力な方法は、自分の作業での要件に突き合わせることです。これからはまず、「この要件を満たす既存のプラグインはあるかどうか」を考えるところから始めてください。結局のところ、誰かがすでに仕上げた作業をわざわざ繰り返す必要はないからです。

最後に、この記事で取り上げたプラグインが Web アプリケーションをどのように改善するのかをまとめておくと、まず、3 つのマウス・クリック・プラグインは、Web アプリケーションが単純なマウスの左クリックだけでなく、マウスから受け取る可能性のあるすべての対話動作を捕捉できるようにします。このような対話動作の捕捉はデスクトップ・アプリケーションではすでに行われているため、マウス・クリック・プラグインは今まで Web アプリケーションに足りなかったユーザー・インターフェースの穴を埋めることになります。続いて説明した blockUI は、Web サイトの外観に合わせたダイアログ・ウィンドウの作成を可能にし、独自のダイアログ・ウィンドウを設計できるようにするプラグインです。これまで Web アプリケーションで使用できるダイアログ・ウィンドウは、alert()confirm() だけに制限されていたので、このプラグインの機能は、Web サイトのユーザーとの対話性を大幅に改善することになります。その次に説明したのは、printArea プラグインです。このプラグインでは、Web ページの特定の部分だけを出力し、他の部分はすべて出力から除外することができます。これも同じく、今までデスクトップ・アプリケーションにはあって、Web アプリケーションにはなかった機能です。計算と英数字に対応した 2 つのプラグインは、特定のウィジェットを簡単に作成できるようにしました。この 2 つのプラグインはコードのエラーを減らし、ユーザーに対するより素早い応答メカニズムを提供することになります。そして最後に、JavaScript でのスレッド操作方法を新しくする Timer プラグインについて説明しました。

この記事で紹介したプラグインすべてに共通する根底のテーマは、Web アプリケーションはデスクトップ・アプリケーションに比べ、ルック・アンド・フィールとコーディングの方法で制約が多くありますが、実際にはそうしたギャップのすべてを埋めるコードを作成する手段があるということです。jQuery では、プラグインを使用することによって、これらのギャップを埋めることができます。今回紹介したプラグインが Web アプリケーションの振る舞いを確実にデスクトップ・アプリケーションと同じようにするまでには、まだ長い道のりがあります。しかし、目指している最終目的地はそこなのです。


ダウンロード可能なリソース


関連トピック


コメント

コメントを登録するにはサインインあるいは登録してください。

static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=Web development
ArticleID=376209
ArticleTitle=jQuery を扱う: 第 1 回 中級レベルの jQuery: プラグインを使用して jQuery 関数を作成および拡張する
publish-date=02172009