Technology

テクノロジー

EXTJS のツリーパネルにおける Ajax 利用

株式会社環
2009年11月27日 / 10:00
 
 
■はじめに
前回のコラムでは、クラス継承を使った独自のツリーパネルの作成までを行っていきましたが、今回はAjax利用の方法などをご紹介させて頂きます。

なお、Ajaxを使ったサンプルのご紹介の関係上、サーバ側コードもサンプル掲載させて頂きますが、サーバ側コードはPHP5.2.xで記載しておりますので、サンプルの動作をご確認される際には、同等程度の環境が必要となる点、ご了承ください。

■前回までのサンプルコード
さて、まずは前回までのサンプルコードを以下に示します。
今回のコラムの内容を読む前に、まずはこのコードで動作するところまでご確認ください。
――――――――――――――HTMLコード―――――――――――――
<html>
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  <title>ツリーパネルクラスサンプル</title>
 
  <link rel="stylesheet" type="text/css" href="extjs/resources/css/ext-all.css">
 
  <script type="text/javascript" src="extjs/adapter/ext/ext-base.js"></script>
  <script type="text/javascript" src="extjs/ext-all-debug.js"></script>
 
  <script type="text/javascript" src="./src_6_1.js"></script>
  <script type="text/javascript">
    Ext.BLANK_IMAGE_URL = 'extjs/resources/images/default/s.gif';
   
    Ext.onReady( function()
    {
  var treePanel = new Ext.ux.UserTreePanel( {
   applyTo:  'p'
  } );
 } );
  </script>
</head>

<body>

<br><br><br>
<div id="p" style="width: 400px; margin: 0 20em;">
</div>

</body>
</html>
――――――――――――――――――――――――――――――――

――――――――――――――JavaScriptコード―――――――――――――
Ext.namespace( 'Ext.ux.UserTreePanel' );
Ext.ux.UserTreePanel = Ext.extend( Ext.tree.TreePanel,
{
 
 title: 'ツリーパネルクラス-サンプル',
 width: 400,
 
 
 //*****************************************************************
 //initComponentのオーバーライド
 //*****************************************************************
 initComponent: function()
 {
  //
  //ノードを作成して、それをルートノードとして設定する。
  //
  this.root = new Ext.tree.TreeNode( {
   text:      'Ext JS',
   draggable: false,
   id:        'root',
   expanded:  true
  } );
  
  
  //
  //forによる繰り返し処理を行い、ルートノードに子ノードをリーフと
  //して追加していく。
  //
  for( var i = 1; i <= 3; i++ ){
   this.root.appendChild( {
    id:   'child' + i,
    text: 'Children node ' + i,
    leaf: true
   } );
  }
  
  
  //
  //親クラスのinitComponentを呼び出す
  //
  Ext.ux.UserTreePanel.superclass.initComponent.call( this );
 }
} );
――――――――――――――――――――――――――――――――

■ノードアイコンの変更
ノードやリーフには、EXTJSがデフォルトで用意しているアイコンが表示されます。これらのアイコンは、以下のようにすることで変更することが可能です。先ほどのサンプルを改造しながら変更していきたいと思います。

まず以下のようなCSSファイルを用意します。ファイル名は、「css_6_1.css」とします。
なお画像ファイルは任意のものを用意してください。
また、HTMLファイルが存在するディレクトリに「img」ディレクトリを作り、その中に任意の画像ファイルを保存します。
.icon-node { background:transparent url(../img/node.gif) no-repeat !important; }
.icon-leaf { background:transparent url(../img/leaf.gif) no-repeat !important; }


なお、ここでのファイル名は、任意で用意して頂いたファイル名に置き換えてください。

このファイルをHTMLファイルで読み込むように以下の記述を追加します。
<link rel="stylesheet" type="text/css" href="extjs/resources/css/ext-all.css">
 
<link rel="stylesheet" type="text/css" href="css_6_1.css"> ―>この1行を追加
 
<script type="text/javascript" src="extjs/adapter/ext/ext-base.js"></script>
<script type="text/javascript" src="extjs/ext-all-debug.js"></script>
 
<script type="text/javascript" src="./src_6_1.js"></script>


最後にJavaScript中の記載で用意したアイコンを使用するように指定します。

//*****************************************************************
//initComponentのオーバーライド
//*****************************************************************
initComponent: function()
{
        //
        //ノードを作成して、それをルートノードとして設定する。
        //
        this.root = new Ext.tree.TreeNode( {
                text:      'Ext JS',
                draggable: false,
                id:        'root',
                expanded: true,
                iconCls:   'icon-node'       //→この部分を追加
        } );
       
       
        //
        //forによる繰り返し処理を行い、ルートノードに子ノードをリーフと
        //して追加していく。
        //
        for( var i = 1; i <= 3; i++ ){
                this.root.appendChild( {
                        id:      'child' + i,
                        text:    'Children node ' + i,
                        leaf:    true,
                        iconCls: 'icon-leaf'    //→この部分を追加
                } );
        }
      ・
}

「iconCls」パラメータに、CSSにて定義したクラス名を指定することにより、以下のように表示アイコンを変更することができます。

ツリーパネルクラス1
ツリーパネルクラス1

■ノードクリック時のイベント追加
今度は、今までのサンプルにさらに手を加えて、ノードやリーフをクリックした際にイベントを発生させ、そのイベントによる処理を追加しています。JavaScriptファイル中を以下のように変更します。
――――――――――――――JavaScriptコード―――――――――――――
Ext.namespace( 'Ext.ux.UserTreePanel' );
Ext.ux.UserTreePanel = Ext.extend( Ext.tree.TreePanel,
{
 
 title: 'ツリーパネルクラス-サンプル',
 width: 400,
 
 
 //*****************************************************************
 //initComponentのオーバーライド
 //*****************************************************************
 initComponent: function()
 {
  //
  //ノードを作成して、それをルートノードとして設定する。
  //
  this.root = new Ext.tree.TreeNode( {
   text:      'Ext JS',
   draggable: false,
   id:        'root',
   expanded:  true
  } );
  
  
  //
  //ルートノードにクリックイベントを追加
  //
  this.root.on( 'click', this.onClickNode, this );
  
  
  //
  //forによる繰り返し処理を行い、ルートノードに子ノードをリーフと
  //して追加していく。
  //
  for( var i = 1; i <= 3; i++ ){
   //子ノード追加
   var childNode = this.root.appendChild( {
    id:   'child' + i,
    text: 'Children node ' + i,
    leaf: true
   } );
   
   //子ノードにクリックイベント追加
   childNode.on( 'click', this.onClickNode, this );
  }
  
  
  //
  //親クラスのinitComponentを呼び出す
  //
  Ext.ux.UserTreePanel.superclass.initComponent.call( this );
 },
 
 
 
 //*****************************************************************
 //ノードのクリックハンドラ
 //*****************************************************************
 onClickNode: function(node, e)
 {
  var msg = 'クリックしたのは「' +node.text + '」です。';
  alert( msg );
 }
} );
――――――――――――――――――――――――――――――――

イベントハンドラの登録方法はいくつか方法がありますが、今回は比較的分かりやすいと思われるon()メソッドを使用しています。
this.root.on( 'click', this.onClickNode, this );
   ・
   ・
   ・
childNode.on( 'click', this.onClickNode, this );
 

さて、イベントハンドラ側ですが、二つの引数を受け取ります。
第一引数はクリックされたノードのインスタンス、第二引数は、イベント発生時における詳細な情報が格納されたイベントオブジェクトです。
onClickNode: function(node, e)
{
var msg = 'クリックしたのは「' + node.text + '」です。';
alert( msg );
}


このコード変更により、ノードクリック時に以下のようなウィンドウが表示されるようになるかと思います。

ツリーパネルクラス2
ツリーパネルクラス2
■Ajaxによる動的なノード取得
今度は、Ajaxによるサーバ側と通信を行い、動的にノード追加をしていきます。
動的なノード取得のためにEXTJSでは、Ext.tree.TreeLoaderクラスが用意されていますので、こちらを使用していきます。
今回からサーバ側コードが必要となりますのでそちらのサンプルを示していきます。なお、サーバ側コードはPHPにて記載しております。では、以下にサンプルコードを示します。
――――――――――――――HTMLコード―――――――――――――
<html>
<head>
  <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
  <title>ツリーパネルクラスサンプル</title>
 
  <link rel="stylesheet" type="text/css" href="extjs/resources/css/ext-all.css">
 
  <script type="text/javascript" src="extjs/adapter/ext/ext-base.js"></script>
  <script type="text/javascript" src="extjs/ext-all-debug.js"></script>
 
  <script type="text/javascript" src="./src_6_4.js"></script>
  <script type="text/javascript">
    Ext.BLANK_IMAGE_URL = 'extjs/resources/images/default/s.gif';
   
    Ext.onReady( function()
    {
  var treePanel = new Ext.ux.UserTreePanel( {
   applyTo:  'p'
  } );
 } );
  </script>
</head>


<body>

<br><br><br>
<div id="p" style="margin: 0 auto;">
</div>


</body>
</html>
――――――――――――――――――――――――――――――――

――――――――――――――JavaScriptコード―――――――――――――
Ext.namespace( 'Ext.ux.UserTreePanel' );
Ext.ux.UserTreePanel = Ext.extend( Ext.tree.TreePanel,
{
 
 title:  'ツリーパネルクラス-サンプル',
 width:  400,
 height: 300,
 
 
 //*****************************************************************
 //initComponentのオーバーライド
 //*****************************************************************
 initComponent: function()
 {
  //
  //ローダーを設定
  //
  this.loader = new Ext.tree.TreeLoader( {
   url: 'http://www.example.com/src_6_4.php'
  } );
  
  
  
  //
  //ノードを作成して、それをルートノードとして設定する。
  //
  this.root = new Ext.tree.AsyncTreeNode( {
   text:      'Ext JS',
   draggable: false,
   id:        'root',
   expanded:  false
  } );
  
  
  //
  //ルートノードにクリックイベントを追加
  //
  this.root.on( 'click', this.onClickNode, this );
  
  
  //
  //子ノードが追加された際のイベントハンドラを追加
  //
  this.on( 'append', this.onAppendNode, this );
  
  
  //
  //親クラスのinitComponentを呼び出す
  //
  Ext.ux.UserTreePanel.superclass.initComponent.call( this );
 },
 
 
 //*****************************************************************
 //ノードのクリックハンドラ
 //*****************************************************************
 onClickNode: function(node, e)
 {
  var msg = 'クリックしたのは「' +node.text + '」です。';
  alert( msg );
 },
 
 
 //*****************************************************************
 //ノードが追加された際のハンドラ
 //*****************************************************************
 onAppendNode: function(tree, parentNode, node, index)
 {
  //
  //追加された子ノードのイベントハンドラを登録
  //
  node.on( 'click', this.onClickNode, this );
 }
} );
――――――――――――――――――――――――――――――――

――――――――――――――サーバ側PHPコード―――――――――――――
<?php


$nodeList = array(
 array('id' => 'child1', 'text' => 'children 1', 'leaf' => true),
 array('id' => 'child2', 'text' => 'children 2', 'leaf' => true),
 array('id' => 'child3', 'text' => 'children 3', 'leaf' => true)
);


sleep( 2 );
echo json_encode( $nodeList );


?>
――――――――――――――――――――――――――――――――

まずクライアント側コード、つまりJavaScript側から見ていきます。
今回は、Ajaxにて子ノードを取得するために、UserTreePanelでTreeLoaderクラスを使うための設定を行っています。
//
//ローダーを設定
//
this.loader = new Ext.tree.TreeLoader( {
url: 'http://www.example.com/src_6_4.php'
} );


設定しているURLですが、これがAjaxによる問い合わせ先URLとなりますので、環境に合わせて適宜書き換えてご利用ください。

つぎにルートノードの設定ですが、こちらはAsyncTreeNodeクラスを使うように変更しています。これはその名の示す通り、非同期タイプのTreeNodeとなります。このクラスのノードの場合、子ノードを表示するためにノード展開をすると、ツリーパネルクラスのloaderに設定しているツリーローダーを使ってサーバ側に問い合わせに行きます。
また、今回は、利用者自身の手でノードを展開した際に問い合わせに行きたいので「expanded」パラメータをfalseに設定しています。
//
//ノードを作成して、それをルートノードとして設定する。
//
this.root = new Ext.tree.AsyncTreeNode( {
text:      'Ext JS',
draggable: false,
id:        'root',
expanded: false
} );


さらに子ノードが追加された際のイベントを利用して、追加された子ノードに対してクリックイベントのハンドラを設定しています。
//*****************************************************************
//ノードが追加された際のハンドラ
//*****************************************************************
onAppendNode: function(tree, parentNode, node, index)
{
//
//追加された子ノードのイベントハンドラを登録
//
node.on( 'click', this.onClickNode, this );
}


今度はサーバ側のPHPコードですが、こちらは非常に単純なコードとなっています。
追加したいノードの各パラメータ名から連想配列を作成し、応答しているだけのコードとなります。
ただし、返答する際に、json_encode()関数を使ってJSON形式に変換しています。
また、sleep()関数を使って2秒ほどのウェイトを入れているのは、実際にサーバ側に取得を行っている様子を確認するためのものです。(このウェイトがないと処理が一瞬で終わってしまうため)

■最後に
今回のコラムでは、CSSによるアイコン変更、イベント処理の追加、Ajaxを使った動的なノード追加など、少し複雑なことを行ってみました。
まだまだ紹介しきれていない事柄がありますので、ぜひともマニュアルを参照していろいろな機能を試されることをお勧めします。

on()メソッドの第一引数はイベント名となります。今回使用している「click」イベント以外にも数多くのイベントがありますので、他のイベントに関してはマニュアルをご参照ください。
第二引数には、そのイベントにより呼び出されるハンドラ関数(メソッド)を指定します。
第三引数は、イベントハンドラ(今回のサンプルにおけるonClickNode()メソッド)中で、this変数で参照可能なオブジェクトを設定します。今回は、UserTreePanel自身のインスタンスを参照できるようにしています。

記事提供:株式会社環
【関連記事】
EXTJS で用意されているウィジェット利用(ツリーパネル−導入編)
EXTJS で用意されているウィジェット利用(タブパネル編)
環、アクセス解析ツール「シビラ」に「ドメイン・組織名分析」を追加。
EXTJS で用意されているウィジェット利用(パネル編)
EXTJS 俯瞰

New Topics

Special Ad

ウマいもの情報てんこ盛り「えん食べ」
ウマいもの情報てんこ盛り「えん食べ」 「えん食べ」は、エンジョイして食べる、エンターテイメントとして食べものを楽しむための、ニュース、コラム、レシピ、動画などを提供します。 てんこ盛りをエンジョイするのは こちらから

Hot Topics

IT Job

Interviews / Specials

Popular

Access Ranking

Partner Sites