Ext JS で作る AJAX アプリケーション

RIA 開発のための JavaScript フレームワーク

Ext JS は数ある JavaScript ライブラリの一つですが、その再利用性の高いオブジェクトおよびUI部品は AJAX アプリケーションの開発を容易にしてくれます。この記事では、Ext JS についての簡単な紹介と、Ext JS の基盤となっている JavaScript によるオブジェクト指向的な設計方法の概要、そして RIA 開発におけるUI 部分への Ext JS フレームワークの適用方法について説明します。

John Fronckowiak, President, IDC Consulting Inc.

John FronckowiakJohn Fronckowiak は、IDC Consulting Inc. の創業者兼社長であり、大人と卒業生のための学校である Medaille College で情報システムの准教授も務めています。また、Web アプリケーション開発、プログラミング、データベースの設計と開発、そしてネットワーキングに関する複数の著書もあります。



2008年 7月 01日

この記事の「リスト 5」についての解説記事を「Ext JS 入門者の最初の壁」(直鳥 裕樹 著、developerWorks、2008年8月) で読むことができます。

現在数多くの Web 開発フレームワークが存在していますが、開発者にとってどのフレームワークが利用するに値するのか、時間の無駄にならないか、その判断が大変難しくなっています。その中で、Web開発者が採用を真剣に検討すべきツールとして JavaScript によるフレームワークの一つである「Ext JS」を紹介します。Ext JS は再利用性が高いオブジェクトや UI 部品を多数備え、AJAX アプリケーションの開発を容易にする強力な JavaScript ライブラリです。Ext JS は Jack Slocum 氏による Yahoo! User Interface(YUI)の拡張機能群として始まりましたが、バージョン 2.0 のリリースにより、Ext JS は数ある JavaScript ライブラリの中でも一番強力でかつかつシンプルなライブラリの一つに進化しています。

Ext JS 概要

Ext JS は当初 YUI ライブラリの機能を拡張するためのプロジェクトとして開始されました。YUI ライブラリの重要なポイントであるクロスブラウザ対応は現在の Ext JS にも引き継がれています。クロスブラウザサポートがあることにより、開発者はブラウザによる違いを気にすることなくアプリケーション開発に専念できます。

Ext JS は動作速度も速く、また、全てオブジェクト指向による設計であるため、拡張も容易です。もちろん、JavaScript で記述されているので Ext JS のライブラリをダウンロードしてアプリケーションに組み込むだけで、すぐに利用することが可能です。

ライセンス

初めて利用するフレームワークについては、そのフレームワークが採用しているライセンスとその利用条件について事前に確認してください。Ext JS では複数の選択肢を提供しています:

  • オープンソースライセンス: GPLv3(訳者注:原文にあるLGPLではありません)に定められた利用条件に基づくオープンソースライセンスです。開発するアプリケーションが GPLv3 あるいは GPLv3 と同等の利用条件を満たすオープンソースプロジェクトの場合は、このライセンスを利用してください(訳者注:原文にある「個人利用、教育利用、非商用利用」であっても、GPLv3 の利用条件を満たさない場合が有ると思うので、無条件には言い切れないと思うのですが・・・)
  • 商用ライセンス: オープンソースライセンスで要求されるの様々な制限を回避したい、あるいはその他の理由で別のライセンスが必要な場合、あるいは単に Ext JS の開発チームを支援したいといった場合については商用ライセンスを購入することができます。文末の「参考文献」に商用ライセンスの価格ページへのリンクがありますのでご覧ください。
  • OEM / 再販ライセンス: Ext JS を組み込んだ別の開発用ライブラリやフレームを開発・販売する際に適用されるライセンスです。

対応 Web ブラウザ

Ext JS はほぼ全ての主要な Web ブラウザをサポートしています:

  • Windows® Internet Explorer® バージョン 6 以降
  • Mozilla Firefox バージョン 1.5 以降(PC および Mac).
  • Apple Safari バージョン 2 以降
  • Opera バージョン 9 以降(PC および Mac).

デザインパターンと Ext JS

Ext JS を利用する開発者は Ext JS のよく考え抜かれた設計と実装によって多くのメリットを享受することができます。Ext JS におけるオブジェクトの関係性や挙動は従来のオブジェクト指向プログラミングのデザインパターンに大きく影響を受けていて、Ext JS の開発者によるとその開発段階において「Head First Design Patterns (Freeman 他)」(訳者注:邦訳「Head First デザインパターン」)に大きな影響を受けたそうです。実際に Ext JS のソースコードを覗けば、「Singleton」のような生成に関するパターン、「Flyweight」のような構造に関するパターン、「Observer」のような振る舞いに関するパターンを見ることができます。


Ext JS による RIA の開発

Ext JS は RIA を開発するのになくてはならないメッセージボックス、コンボボックス、データグリッド、ツールバーなどの多くの UI 部品があらかじめ用意されています。それらに加えて、レイアウトマネージャーと呼ばれる機能を使い、それらの UI 部品をページ上にどう配置するのかということも柔軟に指定できます。さらにフォームやウィンドウを操作するための機能も多数用意されています。

下記のリスト 1 に一般的な Ext JS のファイルのインクルード順を示しています(Web サーバー上の「lib/ext」下に Ext JS の「.js」ファイルを配置したと仮定)が、他の JavaScript ライブラリと一緒に使う場合はインクルードする順番が変わることがあります。

リスト 1. Ext JS のインクルード順
<script type ="text/javascript" src="lib/ext/ext-base.js"></script>
<script type ="text/javascript" src="lib/ext/ext-all.js"></script>

「ext-all.js」ファイルをインクルードすると Ext JS の全ての機能を組み込むことになります。開発するアプリケーションが一部の機能しか利用しない場合は、該当する機能だけを組み込んで利用することも可能です。

Ext JS の統合

Ext JS は、例えば PHP、Java™ 言語、Microsoft® .NET、Ruby on Rails、ColdFusionなど、Web 開発でよく使われる他のサーバー・サイドのフレームワークと併用することができます。

Ext JS を他の JavaScript ライブラリと一緒に利用する場合は、Ext JS に同梱されている「INCLUDE_ORIDER.txt」に記載されている順番でインクルードするようにしてください。

UI 部品

Ext JS フレームワークの大きな魅力は、フォーム、ダイアログボックス、タブ、ツリー、あるいはグリッドなどの数多くの UI 部品があらかじめ用意されているところにあります。

フォーム

Ext JS では多機能なフォームを作成するための様々なツールが用意されています。Ext JS によるフォームの例を図 1 に、そのソースコードをリスト 2 に記載します。

図 1. Ext JS フォーム例
Ext JS フォーム例
リスト 2. Ext JS によるフォーム例(ソースコード)
var top = new Ext.FormPanel({
    labelAlign: 'top',
    frame:true,
    title: 'Multi Column, Nested Layouts and Anchoring',
    bodyStyle:'padding:5px 5px 0',
    width: 600,
    items: [{
        layout:'column',
        items:[{
            columnWidth:.5,
            layout: 'form',
            items: [{
                xtype:'textfield',
                fieldLabel: 'First Name',
                name: 'first',
                anchor:'95%'
            }, {
                xtype:'textfield',
                fieldLabel: 'Company',
                name: 'company',
                anchor:'95%'
            }]
        },{
            columnWidth:.5,
            layout: 'form',
            items: [{
            xtype:'textfield',
            fieldLabel: 'Last Name',
            name: 'last',
            anchor:'95%'
        },{
            xtype:'textfield',
            fieldLabel: 'Email',
            name: 'email',
            vtype:'email',
            anchor:'95%'
        }]
    }]
    },{
        xtype:'htmleditor',
        id:'bio',
        fieldLabel:'Biography',
        height:200,
        anchor:'98%'
    }],

        buttons: [{
        text: 'Save'
    },{
        text: 'Cancel'
    }]
});

    top.render(document.body);

ダイアログボックスとタブ

図 2 にあるように、Ext JS ではユーザーからの入力を待つためのダイアログボックスを生成できるだけでなく、ダイアログボックスの中の限られた面積を最大限活かすためのタブを利用したUIを生成することも可能です。図 2 のソースコードをリスト 3 に記載します。

図2. Ext JS によるタブ付きダイアログボックス例
図2. Ext JS によるタブ付きダイアログボックス例
リスト 3. Ext JS によるタブ付きダイアログボックス例(ソースコード)
var LayoutExample = function(){
// everything in this space is private and only accessible in the HelloWorld block

// define some private variables
var dialog, showBtn;

var toggleTheme = function(){
    Ext.get(document.body, true).toggleClass('xtheme-gray');
};
// return a public interface
return {
    init : function(){
    showBtn = Ext.get('show-dialog-btn');
    // attach to click event
    showBtn.on('click', this.showDialog, this);       
},

showDialog : function(){
    if(!dialog){ // lazy initialize the dialog and only create it once
      dialog = new Ext.LayoutDialog("hello-dlg", { 
      modal:true,
      width:600,
      height:400,
      shadow:true,
      minWidth:300,
      minHeight:300,
      proxyDrag: true,
      west: {
        split:true,
        initialSize: 150,
        minSize: 100,
        maxSize: 250,
        titlebar: true,
        collapsible: true,
        animate: true
      },
      center: {
        autoScroll:true,
        tabPosition: 'top',
        closeOnTab: true,
        alwaysShowTabs: true
      }
  });
  dialog.addKeyListener(27, dialog.hide, dialog);
  dialog.addButton('Submit', dialog.hide, dialog);
  dialog.addButton('Close', dialog.hide, dialog);

  var layout = dialog.getLayout();
  layout.beginUpdate();
  layout.add('west', new Ext.ContentPanel('west', {title: 'West'}));
  layout.add('center', new Ext.ContentPanel('center', {title: 'The First Tab'}));
  // generate some other tabs
  layout.add('center', new Ext.ContentPanel(Ext.id(), {
    autoCreate:true, title: 'Another Tab', background:true}));
  layout.add('center', new Ext.ContentPanel(Ext.id(), {
    autoCreate:true, title: 'Third Tab', closable:true, background:true}));
  layout.endUpdate();
}
dialog.show(showBtn.dom);
}
};
}();

// using onDocumentReady instead of window.onload initializes the application
// when the DOM is ready, without waiting for images and other resources to load
Ext.EventManager.onDocumentReady(LayoutExample.init, LayoutExample, true);

ツリーの生成

Ext JS では図 3 のような Windows のエクスプローラー的なツリーコントロールも用意しています。Ext JS のツリーコントロールではドラッグ&ドロップ機能も完全にサポートしています。図 3 のソースコードをリスト 4 に記載します。

図 3. Ext JS によるツリーコントロール例
Ext JS によるツリーコントロール例
リスト 4. Ext JS によるツリーコントロール例(ソースコード)
var TreeTest = function(){
// shorthand
  var Tree = Ext.tree;

  return {
    init : function(){
      // yui-ext tree
      var tree = new Tree.TreePanel({
          el:'tree',
          animate:true, 
          autoScroll:true,
          loader: new Tree.TreeLoader({dataUrl:'get-nodes.php'}),
          enableDD:true,
          containerScroll: true,
          dropConfig: {appendOnly:true}
      });

      // add a tree sorter in folder mode
      new Tree.TreeSorter(tree, {folderSort:true});

      // set the root node
      var root = new Tree.AsyncTreeNode({
        text: 'Ext JS', 
        draggable:false, // disable root node dragging
        id:'source'
      });
      tree.setRootNode(root);

      // render the tree
      tree.render();

      root.expand(false, /*no anim*/ false);

      //-------------------------------------------------------------

      // YUI tree            
      var tree2 = new Tree.TreePanel({
          el:'tree2',
          animate:true,
          autoScroll:true,
          loader: new Ext.tree.TreeLoader({
            dataUrl:'get-nodes.php',
            baseParams: {lib:'yui'} // custom http params
          }),
          containerScroll: true,
          enableDD:true,
          dropConfig: {appendOnly:true}
      });

      // add a tree sorter in folder mode
      new Tree.TreeSorter(tree2, {folderSort:true});

      // add the root node
      var root2 = new Tree.AsyncTreeNode({
          text: 'My Files', 
          draggable:false, 
          id:'yui'
      });
      tree2.setRootNode(root2);
      tree2.render();

      root2.expand(false, /*no anim*/ false);
    }
  };
}();

Ext.EventManager.onDocumentReady(TreeTest.init, TreeTest, true);

グリッド

この記事の「リスト 5」についての解説記事を「Ext JS 入門者の最初の壁」(直鳥 裕樹 著、developerWorks、2008年8月) で読むことができます。

グリッドコントロールは Ext JS の UI 部品の中においても一番便利なものかもしれません。グリッドコントロールはサーバー側のデータを読み込んで表示するだけではなく、XML や配列といった構造化されたデータ形式もサポートしています。図 4 にあるように、Ext JS のグリッドコントロールはソートやページ送り機能についてもサポートしています。また、このサンプルコードでは、Ext JS の AJAX 機能を使って ExtJS.com のフォーラムから最新の投稿を取得する、といった操作も行っています。図 4 のソースコードをリスト 5 に記載します。

図 4. Ext JS によるグリッドコントロール例
Ext JS によるグリッドコントロール例
リスト 5. Ext JS によるグリッドコントロール例(ソースコード)
Ext.onReady(function(){

  // create the Data Store
  var store = new Ext.data.Store({
  // load using script tags for cross domain, if the data in on the same domain as
  // this page, an HttpProxy would be better
  proxy: new Ext.data.ScriptTagProxy({
    url: 'http://extjs.com/forum/topics-browse-remote.php'
  }),

  // create reader that reads the Topic records
  reader: new Ext.data.JsonReader({
    root: 'topics',
    totalProperty: 'totalCount',
    id: 'threadid',
    fields: [
      'title', 'forumtitle', 'forumid', 'author',
      {name: 'replycount', type: 'int'},
      {name: 'lastpost', mapping: 'lastpost', type: 'date', 
          dateFormat: 'timestamp'},
      'lastposter', 'excerpt'
    ]
  }),

  // turn on remote sorting
  remoteSort: true
});
store.setDefaultSort('lastpost', 'desc');

// pluggable renders
function renderTopic(value, p, record){
  return String.format(
  '<b><a href="http://extjs.com/forum/showthread.php?t={2}" 
      target="_blank">{0}</a></b>
      <a href="http://extjs.com/forum/forumdisplay.php?f={3}" 
      target="_blank">{1} Forum</a>',
    value, record.data.forumtitle, record.id, record.data.forumid);
}
function renderLast(value, p, r){
return String.format('{0}<br/>by {1}', value.dateFormat('M j, Y, g:i a'), 
                     r.data['lastposter']);
}

// the column model has information about grid columns
// dataIndex maps the column to the specific data field in
// the data store
var cm = new Ext.grid.ColumnModel([{
    id: 'topic',
    header: "Topic",
    dataIndex: 'title',
    width: 420,
    renderer: renderTopic
  },{
    header: "Author",
    dataIndex: 'author',
    width: 100,
    hidden: true
  },{
    header: "Replies",
    dataIndex: 'replycount',
    width: 70,
    align: 'right'
  },{
    id: 'last',
    header: "Last Post",
    dataIndex: 'lastpost',
    width: 150,
    renderer: renderLast
}]);

// by default columns are sortable
cm.defaultSortable = true;

var grid = new Ext.grid.GridPanel({
    el:'topic-grid',
    width:700,
    height:500,
    title:'ExtJS.com - Browse Forums',
    store: store,
    cm: cm,
    trackMouseOver:false,
    sm: new Ext.grid.RowSelectionModel({selectRow:Ext.emptyFn}),
    loadMask: true,
    viewConfig: {
      forceFit:true,
      enableRowBody:true,
      showPreview:true,
      getRowClass : function(record, rowIndex, p, store){
        if(this.showPreview){
        p.body = '<p>'+record.data.excerpt+'</p>';
          return 'x-grid3-row-expanded';
      }
      return 'x-grid3-row-collapsed';
    }
},
bbar: new Ext.PagingToolbar({
  pageSize: 25,
  store: store,
  displayInfo: true,
  displayMsg: 'Displaying topics {0} - {1} of {2}',
  emptyMsg: "No topics to display",
  items:[
    '-', {
    pressed: true,
    enableToggle:true,
    text: 'Show Preview',
    cls: 'x-btn-text-icon details',
    toggleHandler: toggleDetails
  }]
})
});

// render it
grid.render();

// trigger the data store load
store.load({params:{start:0, limit:25}});

function toggleDetails(btn, pressed) {
    var view = grid.getView();
    view.showPreview = pressed;
    view.refresh();
}
});

Ext JS と AJAX

Ext JS フレームワークでは AJAX による開発をサポートしています。AJAX アプリケーションの機能を表す典型的な例として、ユーザーからの入力に非同期で反応し、ページの全部ではなく一部を更新するといったものがありますが、リスト 6 に Ext JS による実装例を記載します(テキスト入力フィールドと、そこに入力されたデータをサーバーに送信するボタンだけの HTML です)

リスト 6. Ext JS による AJAX 例
<script type =”text/javascript”>
Ext.onReady(function(){
  Ext.get('okButton').on('click', function(){
    var msg = Ext.get("msg");
    msg.load({
      url: [server url], // <-- replace with your url
        params: "name=" + Ext.get('name').dom.value,
        text: "Updating..."
    });
    msg.show();
  });
});
</script>
  
<div id="msg" style="visibility: hidden"></div>
Name: <input type="text" id="name" /><br />
<input type="button" id="okButton" value="OK" />

OK ボタンがクリックされると、Ext JS の Updater クラス(訳者注:原文の「UpdateManage」ではなく「Updater」が正しいクラス名です)により AJAX コールが行われます。これは、HttpRequest を直接使った一般的な AJAX コールと比較してずっと簡単になっています。

Ext JS とサーバー側 Web フレームワークとのインテグレーション

Ext JS は、PHP、Java、.NET、Ruby on Rails、ColdFusion といった一般的に利用されているサーバー側の Web フレームワークと合わせて利用可能です。個別のフレームワークとのインテグレーション方法については、「参考文献」を参照してください。

Ext JS の開発ツール

Ext JS の開発環境は Eclipse、Aptana、Komodo といった有力な IDE 上に構築することが可能です。その他の IDE における Ext JS のサポートについては「参考文献」を参照してください。

developerWorks の Ajax リソース・センター
Ajax resource center にアクセスしてください。ここは、Ajax アプリケーションを開発するための無料のツールやコード、そして情報が用意されたワンストップ・ショップです。また、Ajax のエキスパートである Jack Herrington がホストする活発な Ajax コミュニティー・フォーラムは、あなたが今まさに探している答えを持っているかもしれない開発者仲間と交流する手段となります。

結論

多くの Web 開発フレームワークがアプリケーション開発を簡単にしスピードアップするという目標を掲げながらも失敗してきました。その中において Ext JS は、その簡単に利用できる開発モデルにより目標を達成することに成功しているようです。Ext JS の最新のリリース、バージョン 2.1(訳者注:2.0 ではなく、2.1 が現在最新)を見れば、Ext JS は今後も RIA 開発の基盤としての進化していくことに注力していることがはっきりと伝わってきます。

この記事では、Ext JS フレームワークの主な機能について紹介しましたが、まだまだ紹介しきれていない機能が沢山あります。ぜひ、読者自身で Ext JS についてもっと深く調べてみてください。まずは、ExtJS.com とサンプル集から始めてみてはいかがでしょうか!

参考文献

学ぶために

製品や技術を入手するために

議論するために

  • Ext JS フォーラム: Ext JS コミュニティーに加わってください。
  • Ext JS ブログ: Ext JS に関する最新のニュースと情報を入手するには、まずこのブログを調べてください。
  • developerWorks blogs: developerWorks blogs から developerWorks コミュニティーに加わってください。

コメント

developerWorks: サイン・イン

必須フィールドは(*)で示されます。


IBM ID が必要ですか?
IBM IDをお忘れですか?


パスワードをお忘れですか?
パスワードの変更

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


お客様が developerWorks に初めてサインインすると、お客様のプロフィールが作成されます。会社名を非表示とする選択を行わない限り、プロフィール内の情報(名前、国/地域や会社名)は公開され、投稿するコンテンツと一緒に表示されますが、いつでもこれらの情報を更新できます。

送信されたすべての情報は安全です。

ディスプレイ・ネームを選択してください



developerWorks に初めてサインインするとプロフィールが作成されますので、その際にディスプレイ・ネームを選択する必要があります。ディスプレイ・ネームは、お客様が developerWorks に投稿するコンテンツと一緒に表示されます。

ディスプレイ・ネームは、3文字から31文字の範囲で指定し、かつ developerWorks コミュニティーでユニークである必要があります。また、プライバシー上の理由でお客様の電子メール・アドレスは使用しないでください。

必須フィールドは(*)で示されます。

3文字から31文字の範囲で指定し

「送信する」をクリックすることにより、お客様は developerWorks のご使用条件に同意したことになります。 ご使用条件を読む

 


送信されたすべての情報は安全です。


static.content.url=http://www.ibm.com/developerworks/js/artrating/
SITE_ID=60
Zone=Web development
ArticleID=323682
ArticleTitle=Ext JS で作る AJAX アプリケーション
publish-date=07012008