ウィジェット作成のための前準備
    当然ですが jQuery UI  のプラグインなのだから、作成には jQuery エンジンだけでなくjQuery UI  ライブラリが必要となります。
    
  手順A | CDN  で手軽にロードする
      学習目的やちょっとしたテクニカル調査といった場合は、わざわざファイルをダウンロードするのも大げさなので、CDN   (コンテンツ・デリバリ・ネットワーク)を利用させてもらうのが妥当です。
    
    jQuery UI  オフィシャルページのフッター部分に必要なURLがすべて記載されているので、これらをアナタが作成する   HTML ファイルにコピペすれば準備完了です。
    このような感じでHTML  ファイルのヘッダに記述すればOK
        | 1 2 3 4 5 6 7 8 9 | <!DOCTYPEhtml>
 <html>
 <head>
 <!-- <meta charset="UTF-8"> -->
 <title>jQuery UI Widget Sample</title>
 <linkrel="stylesheet"href="//code.jquery.com/ui/1.10.0/themes/base/jquery-ui.css">
 <scriptsrc="//code.jquery.com/jquery-1.9.0.js"></script>
 <scriptsrc="//code.jquery.com/ui/1.10.0/jquery-ui.js"></script>
 </head>
 | 
    
    
  手順B |  必要なコンポーネントのみ選択してダウンロード
      CDN   を利用すれば実ファイルを手元に置くことなく URL  を HTML 内で指定するだけで使用することができます。また、とりあえず jQuery UI  コンポーネントフルセットをダウンロードしておけば、余計な考慮などをせずに間違いなく全ての機能を使用することができます。しかし本来なら必要のないコンポーネントも含めてダウンロードしてしまうのは、Web  コンテンツ作成において必ずしもスマートな手法とは言えません。ページの読み込み速度を1ミリ秒でも速くするために、不要なコードは1バイトでも削るべきです。
    jQuery UI  のダウンロードページは必要な機能のみを選択して、それのみが実装されたファイルを生成することができます。
    今回のところは $.widget のみが使用出来れば良いので、Core   UI widgetの p  にのみチェックをけてダウンロードします。
    
    バージョンは1.10.0を選択します。
    
    ダウンロードした zip  ファイルを解凍すると、こんな感じになっています。jQuery UI が対応している jQuery  の最新版もセットになっています。
    
    参考までに、今回のように Core UI widget  のみを選択した場合とフルセットでダウンロードした場合のファイルサイズは以下のようになりました。
        | jQuery UI -  ファイルサイズ比較 | 
    |  | Core UI Widget  のみ | フルセット | 
        | 通常版 | 15 KB | 433 KB | 
    | Minified版 | 7 KB | 227 KB | 
    
      ノーマルな jQuery  プラグイン(※以下、ノーマルプラグイン)と   jQuery UI Widget とでは記述ルールにかなりの違いがあります。簡単なコードで双方の構造を比較してみます。
    ノーマルプラグインの書き方
        | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 | ;(function($) {
     //このPluginの名前   - (1)
     $.fn.myPlugin = function(options) {
         //要素をいったん変数に退避   - (2)
         varelements = this;
           //  渡されたオプションとデフォルトをマージ - (3)
         varopts = $.extend({}, $.fn.myPlugin.defaults, options);
           //  要素をひとつずつ処理 - (4)
         elements.each(function() {
             ・・・
         });
           // method chain用に要素を返す   - (5)
         returnthis;
     };
       //  プラグインのデフォルトオプション - (6)
     $.fn.myPlugin.defaults = {
         param: 'value',
         ・・・
     };
 })(jQuery);
 | 
    
    大まかな構造はこんな感じです。
    1.        $.fn オブジェクトをプラグイン名(※カスタム   jQuery メソッド)で拡張
    2.        this にはプラグイン呼び出し時に指定された要素が格納されており、これを変数に退避しておく ※thisをそのまま使用しても構いません
    3.        プラグイン内で定義したデフォルトのオプションと呼び出し時に渡されたオプション値をマージする
    4.        指定された要素全てに処理が適用されるように、each() を使って1つずつに同様の処理を行う
    5.        method chain が途切れないように、最後にreturn   this を書く
    6.        プラグイン内にデフォルトオプションを定義する
    ノーマルプラグインの作り方に関しては、以下の記事にて詳しく解説しています。
    o     jQueryプラグインの作り方について詳しく
    では jQuery UI Widget  の方はどうでしょうか。
    jQuery UI Widget  の書き方
        | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 | ;(function($) {
     //  このウィジェットの名前(名前空間つき) ※1
     $.widget('ui.myPlugin', {
           //ウィジェットのデフォルトオプション
         options: {
             key1 : 'value'
         },
           //  一番最初に呼ばれる内部関数
         _create: function() {
             //  セットアップ処理
             ・・・
         },
           // _create()後に呼ばれる内部関数
         _init: function() {
             ・・・
         },
         
         //  オプションパラメータ変更時に呼ばれる内部関数
         _setOption: function(key, value) {
             //  変更したパラメータに応じて任意の処理を行う
             switch(key) {
                 case'key1':
                 break;
             }
             $._super('_setOption', this, arguments);
         },
         
         //  インスタンスを破棄
         destroy: function() {
             ・・・
             $._super('destroy', this, arguments);
         }
     });
 })(jQuery);
 | 
    
    もはや別物と言ってよいくらいにノーマルプラグインとは異なった構造化がなされています。
    では実際にサンプルコードを書きながら一つずつ解説していきます。
      まずは最小規模なモノからはじめます。
    
  ウィジェットの定義
          | 1 2 3 4 | //  プラグインの定義
 $.widget('ui.captionator', {
   //  オプション、メソッドの定義
 });
 | 
    
    jQuery UI Widget  は $.widget() というファクトリーメソッドを用いて作成します。第一引数に作成したいウィジェット名を名前空間付きで渡します。名前空間を付けないとエラーとなって作成できません。そして第二引数にウィジェットが持つオプションやメソッドといった機能を定義したオブジェクトを渡します。
    おっと匿名関数でウィジェット全体をラップするのを忘れずに!
        | 1 2 3 4 5 6 | ;(function($) {
   //  プラグインの定義
   $.widget('ui.captionator', {
     //  オプション、メソッドの定義
   });
 })(jQuery);
 | 
    
    ノーマルプラグインと同様に jQuery UI Widget  においても全体を匿名関数でラップして堅牢な作りにします。1行目冒頭のセミコロンも忘れずに。
      
  初期化メソッド
      jQuery UI Widget  には _create と _init という2種類の初期化メソッドが予め用意されており、これらはウィジェットのインスタンス生成時に1回ずつ自動で呼び出されます。
    jquery.captionator1.js
        | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | ;(function($) {
   //  プラグインの定義
   $.widget('ui.captionator', {
     //  初期化処理として一番最初に呼び出される
     _create: function() {
       varself = this,  //   ウィジェットインスタンスを変数に待避 - (※1)
         element = self.element; //  要素を変数に待避 - (※2)
       alert(element.attr('alt'));
     },
     // _create  の次に呼び出される
     _init: function() {
       varself = this,
         element = self.element;
       alert(element.attr('title'));
     }
   });
 })(jQuery);
 | 
    
    まず最初に this を変数に待避していますが(※1)、$.widget()  第二引数の中での this はウィジェットオブジェクト自身となります。ノーマルプラグインの場合だと   this には指定された要素が格納されていましたが、 jQuery UI Widget においては this.element に格納されています。
        | 1 2 3 4 5 | $('#hoge').myPlugin();
 ・・・
 _create: function() {
   this.element; // => $('#hoge')
 },
 | 
    
    では jQuery  セレクタで複数要素を選択した場合は?
    ノーマルプラグインでは選択された要素は全て this に配列形式で格納されており、each()  を使ってそれらに対して1つずつ処理を適用していくというフローとなっていました。
    jQuery UI Widget  において要素が複数選択されていた場合は、一つ一つの要素に対して _create  と _init が実行され、 this.element   には処理対象となる要素のみが格納されます。
        | 1 2 3 4 5 | $('#hoge, #foo').myPlugin();
 ・・・
 _create: function() {
   this.element; //  一回目は$('#hoge')、二回目は$('#foo')が格納される
 },
 | 
    
    このあたりは自前でループ処理を書くといった複数要素に対する配慮を気にしなくて良い作りになっており、作り手はより機能の作り込みに取り組むことが出来る優れた構造と言えます。
    
  メソッドチェーンについて
      ノーマルプラグインではメソッドチェーンを保つために、コードの最後にreturn   this; を記述してjQueryオブジェクトを返すというセオリーが有りました。
    一方 jQuery UI Widget  ではこの辺りを内部的に処理してくれるので、return this を明記する必要はありません。
    sample1.html
        | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | <!DOCTYPEhtml>
 <html>
 <head>
 <!-- <meta charset="UTF-8"> -->
 <title>#1 | jQuery UI Widget</title>
 ・・・
 <scriptsrc="js/jquery.captionator1.js"></script>
 <script>
 $(function() {
   $('img').captionator();
   $('img').captionator().fadeOut(); //  メソッドチェーンも正常に動きます
 });
 </script>
 </head>
 <body>
 ・・・
   <divclass="center">
     <imgsrc="../common/img/myLogo.jpg"height="251"width="251"alt="wakamsha logo."title="本名は山田直樹です。"/>
   </div>
   </body>
 </html>
 | 
    
    o     View   demo (sample #1)
      オプションを渡すことで、ウィジェットの利便性を何倍にも高めることができます。当然ウィジェット側にもオプションのデフォルト値を定義するわけですが、ノーマルプラグインと違って $.widget()  の第二引数内に options という名前で定義し、その中に必要なパラメータを設定します。
    jquery.captionator2.js
        | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 | ;(function($) {
   //  プラグインの定義
   $.widget('ui.captionator', {
     options: {
       backgroundColor: '#fff'
     },
     //  初期化処理として一番最初に呼び出される
     _create: function() {
       varself = this,  //   ウィジェットインスタンスを変数に待避 - (※1)
         element = self.element, //  要素を変数に待避 - (※2)
         opts = self.options;  //  マージ済みのオプションを変数に待避 - (※3)
         element.addClass('polaroid')
         .css('backgroundColor', opts.backgroundColor);
     }
   });
 })(jQuery);
 | 
    
    デフォルトオプションは上記のようにして定義します。ノーマルプラグインの場合だと、ユーザーが指定したオプションとデフォルトの値をマージする処理も自前で記述する必要がありましたが、 jQuery UI Widget  ではコレに関しても内部で自動的に処理してくれます。
        | 1 2 3 4 5 | //  オプションを指定
 $('img').captionator({ backgroundColor: '#aeee00'});
   //  指定しない
 $('img').captionator();
 | 
    
    o     View   demo (sample #2)
    また、オプションの値は以下の式で取得することができます。
        | 1 | $('img').captionator('option', 'backgroundColor'); // => #aeee00
 | 
    
    パブリックメソッドとプライベートメソッド
    jQuery UI Widget  にはウィジェット内部からのみアクセス可能なプライベートメソッドと、外部からもアクセス可能なパブリックメソッドが用意されています。
    ここまでに出てきた _create  と _init にはどちらもメソッド名の最初に_(アンダースコア)が付けられているのでプライベートメソッドとして定義され、付いていないモノに対してはパブリックメソッドとして定義されます。
    以下はイメージ画像にキャプションを自動で生成して付与するというウィジェットのコードです。
    jquery.captionator3.js
        | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 | ;(function($) {
   //  プラグインの定義
   $.widget('ui.captionator', {
     //  デフォルト値
     options: {
       location: 'bottom',
       color: '#fff',
       backgroundColor: '#000'
     },
     _captionClassName: 'ui-caption',
       //  初期化処理として一番最初に呼び出される
     _create: function() {
       varself = this,  //   ウィジェットインスタンスを変数に待避 - (※1)
         element = self.element, //  要素を変数に待避 - (※2)
         opts = self.options;  //  マージ済みのオプションを変数に待避 - (※3)
         element.addClass('polaroid').wrap('<div class="ui-caption-container"/>');
       varcontainer = element.parent().width(element.width()),
         cap = $('<span/>').text(element.attr('alt'))
           .addClass(this._captionClassName)
           .css({
             backgroundColor: opts.backgroundColor,
             color: opts.color,
             width: element.width()
           }).insertAfter(element),
         capWidth = element.width() - parseInt(cap.css('padding')) * 2,
         capHeight = cap.outerHeight();
       cap.css({
         width: capWidth,
         top: self._setTopCoordinate(opts.location, element, capHeight),
         left: (element.outerWidth() - element.width()) / 2
       });
     },
     
     //  キャプションのtop値を算出
     _setTopCoordinate: function(value, element, capHeight) {
       varoffset = (element.outerHeight() - element.height()) / 2;
       return(value === 'top') ? 0 : element.outerHeight() - offset - capHeight;
     },
       //  キャプションのパラメータ値を取得
     getCaptionAttr: function(keys) {
       varvals = [],
         cap = this.element.next();
       for(vari=0, len=keys.length; i<len; i++) {
         vals.push($(cap).css(keys[i]));
       }
       returnvals;
     }
   });
 })(jQuery);
 | 
    
    _setTopCoordinate() はプライベート、getCaptionAttr() はパブリックとしてそれぞれ定義しています。パブリックメソッドを外部から呼び出すには以下のように記述します。
    sample3.html (※JS部分のみ)
        | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 | $(function() {
   $('img').captionator({
     backgroundColor: '#aeee00'
   });
     $('#getCapParamBtn').click(function(e) {
     varkeys = newArray('width', 'height', 'backgroundColor', 'color'),
       vals = $('img').captionator('getCaptionAttr', keys),
       $valueList = $('#valueList');
     for(vari=0, len=vals.length; i<len; i++) {
       $valueList.append($('<li/>').text(vals[i]));
     }
   });
 });
 | 
    
    jQuery UI Widget  でインスタンス化した後、第一引数にパブリックメソッド名、第二引数以降にそのメソッドに必要な引数を指定することで、パブリックメソッドを呼び出すことができます。また、コレに関しても自動的にjQUeryオブジェクトを返してくれるので、メソッドチェーンは保たれます。
    o     View   demo (sample #3)
    
  ※補足その1 |  プライベートメソッドを外部から呼び出す裏ワザ
      以下のような記述でプライベートメソッドを外部から呼び出すという裏ワザがかつてありましたが、この方法は jQuery   UI 1.10.0 以降使えなくなりました。
        | 1 | $('img').data('captionator')._setTopCoordinate();
 | 
    
    裏ワザとはいえ、外部から呼び出せてしまってはプライベートメソッドの意味がないですし、そもそもなぜ今まで呼び出せていたのかが不思議なくらいです
    destroy  メソッド
    破壊という名の通り内部で保持されたインスタンスが破棄され、パブリックメソッドといったウィジェットの API  が全て使用できなくなります。
    sample4.html (※JS部分のみ)
        | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 | $(function() {
   $('img').captionator({
     backgroundColor: '#aeee00'
   });
     $('#getCapParamBtn').click(function(e) {
     varkeys = newArray('width', 'height', 'backgroundColor', 'color'),
       vals = $('img').captionator('getCaptionAttr', keys),
       $valueList = $('#valueList');
     for(vari=0, len=vals.length; i<len; i++) {
       $valueList.append($('<li/>').text(vals[i]));
     }
   });
     $('#destroyBtn').click(function(e) {
     e.preventDefault();
     $('img').captionator('destroy');
   });
 });
 | 
    
    先の sample #3  にdestroy を呼び出す処理を追加しただけのものです。#getCapParamBtn をクリックする度にキャプションのスタイルを取得するというパブリックメソッドを呼び出す処理がありますが、   destroy メソッドを呼び出して実行すると、この処理が一切呼び出されなくなります。
    o     View   demo (sample #4)
    disable  と enable
    disable メソッドを呼び出すと、   jQuery UI Widget の実行対象となった要素に以下の2つのクラスが追加されます。
    1.        "名前空間"-"ウィジェット名"-"disabled"
    2.        "名前空間"-"ウィジェット名"-"state-disabled"
    enable はこれら2つのクラスを要素から排除します。あくまでもクラスを付け外しするだけであって、APIが一時的に無効化されるといったことにはなりません。そのため以下のサンプルでは   disable 時のクラスが付与されているかを評価してから処理を行うと記述しています。
    sample5.html (※JS部分のみ)
        | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 | $(function() {
   $('img').captionator({
     backgroundColor: '#aeee00'
   });
     $('#getCapParamBtn').click(function(e) {
     vardisabledClassName = $('img').captionator('getDisabledClassName');
     if($('img').hasClass(disabledClassName)) {
       console.log(disabledClassName);
       returnfalse;
     }
     varkeys = newArray('width', 'height', 'backgroundColor', 'color'),
       vals = $('img').captionator('getCaptionAttr', keys),
       $valueList = $('#valueList');
     for(vari=0, len=vals.length; i<len; i++) {
       $valueList.append($('<li/>').text(vals[i]));
     }
   });
     $('#destroyBtn').click(function(e) {
     e.preventDefault();
     $('img').captionator('destroy');
   });
     $('.btn-condition').click(function(e) {
     e.preventDefault();
     $('img').captionator($(this).text().toLowerCase());
   });
 });
 | 
    
    o     View   demo (sample #5)
    
  ※補足その2 |  いろいろなプロパティ
      名前空間というのが再び出て来ましたが、jQuery UI Widget  にはオプションや名前空間をはじめとした色々なプロパティが参照できます。
        | 1 2 3 4 5 6 | $.widget('ui.captionator', {
   ・・・
   this.namespace;     // => ui  名前空間
   this.widgetName;    // => captionator  ウィジェット名
   this.widgetEventPrefix;   // => captionator  イベント名に付く接頭辞
 });
 | 
    
    オプション値を更新する
    インスタンス化した要素に対し、個々のオプション値が新たに渡される(※更新)と、内部で _setOption メソッドが呼び出されます。
    jquery.captionator6.js
        | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 | ;(function($) {
   //  プラグインの定義
   $.widget('ui.captionator', {
     //  デフォルト値
     options: {
       location: 'bottom',
       color: '#fff',
       backgroundColor: '#000'
     },
     
     ・・・・・・
       //  オプションの値が変更されると呼び出される
     _setOption: function(key, value) {
       varelement = this.element,
         cap = element.next();
       cap.css(key, value);
       this._super('_setOption', this, arguments);
     }
   });
 })(jQuery);
 | 
    
    メソッドには変更されたオプションの key  と value が渡され、実装者はコレを使って任意の処理を記述することができます。
    o     View   demo (sample #6)
    イベントを定義する
    イベントに関する機能も随分とお手軽に操作できるように作りこまれています。まずイベントの発火方法ですが、発火させたい箇所に以下の一行を記述します。
        | 1 | this._trigger(callbackName, [event], [uiObject]);
 | 
    
    引数は以下の3つです。
    callbackName
    発火させるイベントの名前です。好きなのを付けられます。
    event
    イベントオブジェクトです。 イベントタイプの値はwidgetEventPrefix とイベント名を全て小文字にして結合したものになります。
    uiObject
    発火対象となるオブジェクトを格納します。
    イベントが発火されると、options  内の callbackName に対応する関数が呼び出されます。
    jquery.captionator7.js
        | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 | ;(function($) {
   //  プラグインの定義
   $.widget('ui.captionator', {
     //  デフォルト値
     options: {
       location: 'bottom',
       color: '#fff',
       backgroundColor: '#000',
       changed: function(e, cap) {
         console.log(e, cap)
       }
     },
       ・・・・・・
       //  オプションの値が変更されると呼び出される
     _setOption: function(key, value) {
       varelement = this.element,
         cap = element.next();
       cap.css(key, value);
       this._super('_setOption', this, arguments);
         //  オプションの値変更後にイベントを発火
       this._trigger('changed', event, cap);
     }
   });
 })(jQuery);
 | 
    
    呼び出される関数はオプション内に設定されているので、呼び出し側からここで実行する処理を更に設定することができます。
    sample7.html (※JS部分のみ)
        | 1 2 3 4 5 6 7 8 9 10 | $(function() {
   $('img').captionator({
     backgroundColor: '#aeee00',
     changed: function(e, cap) {
       alert(e.type);
     }
   });
     ・・・・・・
 });
 | 
    
    o     View   demo (sample #7)
      ゼロから大規模なウィジェットを作ったり、要件の仕様に適した必要最低限の機能のみを持つ軽量なウィジェットを作るのもアリですが、jQuery UI  には既に数多くのウィジェットが標準コンポーネントとして用意されています。これらを拡張して独自のUIコンポーネントを作ることで、より少ないコストで開発を進めることが出来ます。
    jquery.customDialog.js
        | 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 | ;(function($) {
   //  プラグインの定義 -   オーバーライド
   $.widget('ui.customDialog', $.ui.dialog, {
     //  デフォルトのオプションをオーバーライド
     options: {
       width: 500,
       height: 250,
       autoOpen: false
     },
     // createメソッドをオーバーライド
     _create: function() {
       //  継承元の_createメソッドを呼び出す
       this._super('_create', this, arguments);
         //  コンテンツを入れ替える
       this.element.find('p').text('Hi! My name is Wakamsha. I am a Web depeloper.   My favourite languages are HTML5, CSS3, JavaScript etc...');
     },
       // openメソッドをオーバーライド
     open: function() {
       //  継承元のopenメソッドを呼び出す
       this._super('open', this, arguments);
       //  非表示にしてフェードイン表示させる
       this.element.hide().slideDown(1000);
     },
     
     // closeメソッドをオーバーライド
     close: function() {
       if(confirm('Is it closing time?')) {
         this._super('close', this, arguments);
       }
     }
   });
 })(jQuery);
 | 
    
    $.widget()  の第二引数に機能オブジェクトでなく継承したいウィジェットを指定します。以降はオーバーライドしたいメソッドを定義して任意の機能を記述していくだけですが、ただ単に自分のコードだけを書いていては継承元にあったオリジナルの処理が実行されないままになってしまいます。そこで13行目と30行目にあるように _suer() を使って継承元のメソッドを呼び出すようにします。コレを忘れてしまうと正常に動作しなくなるので必ずつけるようにします。
    o     View   demo (sample #8)
    
  ※補足3 |  バージョンによって異なる呼び出し方
      上記のサンプルでは継承元のメソッドを呼び出すのに _super()  を使っていましたが、これは jQuery UI 1.9 から実装された機能です。したがって 1.8x までのバージョンを使う必要がある場合は、以下のように書かなくてはなりません。
        | 1 2 3 | //  継承元の_createメソッドを呼び出す
 $.ui.dialog.prototype._create.apply(this, arguments); // ※1.8までの書き方
 this._super('_create', this, arguments);    // 1.9以降の書き方
 | 
    
    おわりに
    とりあえず思いつくままに jQuery UI Widget  の基本的な内容を書き連ねてきました。これで全て網羅できたかどうか定かではありませんが、余程のことがない限りは当記事の内容を元に作ることは可能かと思います。