Ext.Element

Ext.Elementの取得

HTML文書は通常多くのHTML要素により構成されています。ブラウザがHTML文書を読み込む際に、HTML要素に含まれているタグはHTMLElementに変換されDocument Object Model (DOM)ツリーが構築されます。このDOMツリーはブラウザのグローバル変数documentに格納されます。そしてこの変数がページに読み込まれた全ての要素へ参照を保持することになります。

このdocumentオブジェクトはgetElementByIdというとても重要なメソッドを提供してくれます。このメソッドはどのブラウザにおいてもdocument内のHTMLElementを取得してくれます。しかし、実際のDOM操作についてはブラウザ間での差異が非常に多いため細心の注意が必要となってきます。Ext CoreではHTMLElementをラッピングしかつクロスブラウザ対応を施したExt.Elementというクラスを提供しています。

Ext.ElementはExt Coreライブラリの中で最多のメソッドを持つクラスです。これらのメソッドは以下のように分類することができます:

CSSとスタイル
(例: setStyle, addClass)
Domの参照と移動
(例: query, select, findParent)
Domの操作
(例: createChild, remove)
サイズ
(例: getHeight, getWidth)

Ext.getメソッドによりHTMLElementをラップするExt.Elementのインスタンスを生成することができます。例えば、取得したい要素が'myElementId'というidを持っている場合、下記のようにして取得することができます:

var el = Ext.get('myElementId');

Firebugを使って下記のコードを実行してみてください。この場合「生の」JavaScriptオブジェクトを見ていることになるためPublicメソッドだけでなくPrivateメソッドも表示されていることに注意してください。各メソッドの詳しい内容についてはAPIドキュメントを参照してください。

var el = Ext.get('myElementId');
console.dir(el);

console.dirというメソッドはFirebugが提供するAPIでオブジェクトの中身を見やすい形で表示してくれます。このメソッドは更にオブジェクトに含まれる子オブジェクトのプロパティについても同様の形式で表示してくれます。プロパティは黒字で表示され、メソッド/関数は緑、コンストラクタおよびクラスについては赤字で表示されます。

ではmyElementIdというidを持つ上記の段落を操作してみましょう(Firebugで実行してみてください)。

var el = Ext.get('myElementId');
el.addClass('error');

上記コードを実行すると上の段落の文字の色が赤に変わるはずです。このページは「error」クラスを持つ要素の文字の色を赤にするCSSルールが予め定義されているからです。CSSルールは以下のようになっています:

.error {
	color: red;
}

2つ後のセクションで要素のCSSおよびスタイリング操作について詳しく説明します。

Flyweightについて

Flyweightパターンは一つのグローバルオブジェクトを生成し、そのオブジェクトを繰り返し利用することによりメモリーの利用量を最小化するためのデザインパターンです。Extは最初に読み込まれたときにFlyweightとして利用するためのグローバルなExt.Elementを生成します。このグローバルオブジェクトはDOM内の任意のノードにアクセスするために利用することができます。このFlyweightオブジェクトにアクセスするにはExt.flyメソッドを利用しますが、Extを使い始めの頃にはExt.getとExt.flyのどちらを使うか悩んでしまうことが多いようです:

Ext.Elementへの参照を後で利用するために保持しておく必要がある場合についてはかならずExt.getメソッドを利用してください。逆にElementへの参照を保持しておく必要がない場合、プログラム全体で共有されているFlyweightを利用できます。このFlyweightオブジェクトにアクセスするにはExt.fly(elementId)メソッドを利用してください。

では、上でerrorクラスを追加した段落から同じクラスを取り除いてみましょう。

Ext.fly('myElementId').removeClass('error');

このコードが実行されると、Ext.Elementオブジェクトを新たに生成することなく、予め作成されていた共有Flyweightオブジェクトを利用して処理を行います。Ext.flyはワンライナー(一行コード)のような単純な処理に適したメソッドです。逆に後で利用する変数にFlyweightオブジェクトを格納するようなことは絶対に避けてください。なぜならFlyweightオブジェクトはコードの他の部分によって変更される可能性が常にあるからです。例えば、次の例を見て下さい:

var el = Ext.fly('foo');
Ext.fly('bar').frame();
el.addClass('error');

frameメソッドはExt.Elementのアニメーション効果パッケージに含まれているハイライト効果のためのメソッドです。さて、この場合どういう結果になるでしょうか?

答えは、"bar"というidを持つ要素がハイライトされ、そのすぐ後にCSSのerrorクラスが追加され文字の色が赤に変わります。"foo"というidを持つ要素には何も変化が起きません。なぜなら、elという変数はグローバルなFlyweightオブジェクトへを参照しており、そのFlyweightオブジェクトは"bar"にframeメソッドを適用したときに上書きされているからです。もしこの動作が理解できないのであれば、再度このセクションを読み直してください。Ext.flyメソッドを利用するためには、この動作の仕組みをしっかりと理解しておく必要があります。

CSSクラスとスタイル

ここまでHTML要素について、またその要素がドキュメントとどう関係しているのか、そしてExt Coreのメソッドがこういったデータをどうやって取得するのかということを学習してきました。 では、ドキュメントのレイアウトはどうでしょうか?ドキュメントのレイアウトやスタイルはどうやって操作すればいいのでしょうか?答えはCascading Style Sheets (CSS) によるスタイル指定を利用することです。CSSはページのレイアウトやその他の見た目に関する情報を操作するための言語です。Ext CoreではCSSクラスの変更やスタイル指定を直接変更することにより、ドキュメント内のHTML要素のスタイルの変更を容易にしています。

<style type="text/css">
myCls {
	color: #F00;
}
</style>

...

<div type="myCls">Hello</div>
上記の例では、'myCls'というCSSクラスがdivタグに設定され、'Hello'という文字の色を赤(#F00)に設定しています。

ではここで先ほど出てきたFirebugのもう一つの素晴らしいツールを見てみましょう。ページ上の任意の場所で右クリックして「要素を調査(Inspect Element)」を選択してください。するとFirebugにページのDOMツリーと選択した要素がハイライトして表示されます。そのDOMツリーが表示されているパネルの右隣のパネルを見ると、選択した要素に適用されている全てのスタイルが表示されているはずです。
この時点でまだFirebugの使い方がよく分からないようであれば、一旦このマニュアルを休んで、Firebugの使い方を勉強してみてください。FirebugはWebアプリケーション開発のための必須ツールです。FirebugによるHTML要素の確認は既存のサイトのスタイルを変更したり、あるいは新しいサイトを作成したりデバッグしたりするときに大変便利です。 では、CSS操作のためにExt Coreが提供している機能をみていきましょう。

DOMナビゲーション

Webアプリケーションを開発していると、何らかの処理を行っているDOMツリーの任意の地点からツリーの別の場所に移動するといった必要が常に発生します。Ext CoreではDOMツリー内を自由自在に移動するためのクロスブラウザー対応のメソッドを提供しています。そして、CSSを利用すればより複雑な移動操作を比較的簡単に行うことができます。この分野にといてCSS3セレクターは非常に強力なツールとなりえます。 下記のHTMLをご覧下さい:

<style type="text/css">
    .red {
        color: #F00;
    }
</style>	
...
<div id='elId'>
    <ul>
        <li>a-one</li>
        <li>a-two</li>
        <li>a-three</li>
        <li>a-four</li>
    </ul>
    <ul>
        <li>b-one</li>
        <li>b-two</li>
        <li>b-three</li>                
    </ul>
</div>
このHTML内のリスト要素に対して1つおきに文字の色を赤にする必要があったとします。Ext Coreでは下記のワンライナーでこれを実現することが可能です。
Ext.fly('elId').select('li:nth-child(2n)').addClass('red');
以下がその結果です:

では、Ext CoreのDOMナビゲーション用APIの他の機能について見ていきましょう:

DOM操作

Ext.Element

動的なHTMLページにおいて最も頻繁に実行される処理はDOMツリーの中における要素の生成や削除処理です。実際にはブラウザ間の実装方法の差異により、これらの処理は難しいものとなっています。Ext Coreではこれらのブラウザ間の差異を吸収するだけでなく、最大限効率化された処理を可能とするための強力なAPI群を提供しています。これらのDOM操作用APIにより、DOMツリーの任意の地点(任意のノードから相対位置で)に新しいノードを追加したり削除したりすることが簡単に行えます。では、次のHTMLを元に実際の例を見てきましょう:

<div id='elId'>
	<p>paragraph one</p>
	<p>paragraph two</p>
	<p>paragraph three</p>
</div>
上記HTMLを実際に表示すると下のようになります:

まずはじめに新しいノードを生成し、'elId'ノードの最初の子ノードとして挿入してみましょう:
Ext.fly('elId').insertFirst({
	tag: 'p',
	html: 'Hi I am the new first child'
});
ノードが挿入されました:

簡単ですよね!では、Ext Coreが提供するより強力なAPIを見ていきましょう:

Ext.DomHelperコンフィグオプション

上の例で下記のようなコードが出てきました:
.insertFirst({
	tag: 'p',
	html: 'Hi I am the new first child'
});

このinserFirstの引数は一体何なのかと思われたかもしれません。これは、Ext.DomHelperというクラス(後述)に渡されるコンフィグオプションそのものであり、どういったHTMLを生成するのかということを示しています。Ext.DomHelperのコンフィグオプションでは、生成する子ノードについて様々なプロパティを設定することができます(例:HTMLの一部をそのまま書いたり、CSSクラス、url、src、idといったDOMノードの属性情報そのものを指定できます)。以下にExt.DomHelperのコンフィグオプションを引数として利用可能なExt.Elementのメソッドの例を挙げておきます:

HTMLフラグメント

HTMLフラグメントはその名前の通り、HTMLの「破片」です。Ext CoreではこのHTMLフラグメントを使ったDOM操作用のAPIを提供しています。ブラウザ間の差異や実行速度についても心配ありません。例えば、次の例を見てください:

<div id='elId'>
    <li>one</li>
    <li>two</li>
    <li>three</li>
    <li>four</li>    
</div>

上記のHTMLに対して下のコードを実行した場合どういう結果になると思いますか?

	
Ext.fly('elId').insertHtml('beforeBegin', '<p>Hi</p>')

コード実行後のHTMLを見てみましょう:

<p>Hi</p>	
<div id='elId'>
    <li>one</li>
    <li>two</li>
    <li>three</li>
    <li>four</li>    
</div>
どうですか?'beforeBegin'という引数を与えることによって、もう一つの引数として渡したHTMLフラグメントの挿入位置を指定することができました。では、次のコードはどうでしょう?:
Ext.fly('elId').insertHtml('afterBegin', '<p>Hi</p>')
結果は...:
<div id='elId'>
    <p>Hi</p>	
    <li>one</li>
    <li>two</li>
    <li>three</li>
    <li>four</li>    
</div>
今後は'beforeEnd'と指定してみましょう:
Ext.fly('elId').insertHtml('beforeEnd', '<p>Hi</p>')
結果は...:
<div id='elId'>    
    <li>one</li>
    <li>two</li>
    <li>three</li>
    <li>four</li>
    <p>Hi</p>	
</div>
最後に'afterEnd'を指定してみます:
Ext.fly('elId').insertHtml('afterEnd', '<p>Hi</p>')
結果は...:
<div id='elId'>    
    <li>one</li>
    <li>two</li>
    <li>three</li>
    <li>four</li>    
</div>
<p>Hi</p>
HTMLフラグメントは以下のメソッドで利用することが可能です:

Ajax

Ext Coreには強力なAjax用のAPIが含まれています。Ajax用APIについては後のセクションで詳細にカバーしますが、Ext.Elementにおいて利用できるAjaxのメソッドについて簡単に説明します:

イベント処理

イベント処理はブラウザ間の差異に大きく悩まされるテーマの一つです。ブラウザーが提供しているイベント処理関数を利用する場合、イベントの追加・削除に必要なメソッドがそもそもブラウザー間で違うだけでなく、その他の雑多な一貫性の無さに悩まされることになります。Ext Coreでは開発者が直面するこれらの差異を吸収することによりクロスブラウザー対応のイベント処理を実現しています。

Ext Coreではイベント処理において一貫したインターフェースを提供することにより開発者をクロスブラウザー問題から解放するだけでなく、機能豊富なイベントモデルを提供しています。Ext.ElementがDOMノードそのものをラッピングする存在であるのに対して、イベントをラッピングするExt.EventObjectというクラスがExt Coreでは提供されています。Ext.EventObjectはマウスボタンのクリックやキーボードの押下、イベントプロパゲーションの仕組み、デフォルトアクションのキャンセルといったブラウザ間で異なる処理を正規化し、統一したインターフェースを提供します。

イベントハンドラー関数をページ上のExt.Elementに結びつけるにはonというメソッドを使います。 Ext.Element.onメソッドは、Ext.Element.addListenerの省略形ですが、書き間違い防止、短く読みやすいコードといった観点からこちらの利用が推奨されます。第1引数は観察対象(subscribe)とするイベント名、そして第2引数にイベントハンドラー関数を渡します。

Ext.fly('myEl').on('click', function(e, t) {
	// myElへのクリックイベントの際の処理
	// eは何が起きたかを表すExt.EventObjectのインスタンス
	// tはイベントが発生したExt.Element
});
Ext Coreでは全てのDOMイベントを正規化して扱っています。イベントに結びつけられるイベントハンドラー関数は常に、EventObjectのインスタンスとイベントが発生したHTMLElementを引数として受け取ることになります。

では、イベント処理のためのメソッドを見ていきましょう:

イベント処理(応用編)

Ext Coreはイベントの委譲、バッファー、遅延実行といったより高度なイベント処理を行うための便利なメソッドが容易されています。

サイズの取扱い

ページ上の特定の要素の寸法を再設定したりその情報を取得したり、といったことは頻繁に行う操作の1つです。ここでもExt Coreはブラウザ間の差異を吸収したサイズを取り扱うためのAPIを提供しています。またほとんどのセッターメソッド(setXXX())において、アニメーション効果のための引数を取ることができるようになっています(単にtrueを渡せばデフォルトの効果、コンフィグオプションを渡せばカスタマイズした効果を実現できます)。では、詳しく見ていきましょう:

// デフォルトのアニメーション効果と共に高さを200pxに設定
Ext.fly('elId').setHeight(200, true);

// カスタマイズしたアニメーション効果と共に高さを150pxに設定
Ext.fly('elId').setHeight(150, {
    duration : .5, // アニメーション効果の持続時間を0.5秒に設定
    // 中身の文字を"finished"に変更
    callback: function(){ this.update("finished"); } 
});
ここでFirebugを開いて適当な要素を右クリックして「要素を調査(Inspect Element)」を選択してみてください。Firebugの右側のパネルの「レイアウト」タブを選択すると下のような図が表示されるはずです:

ここには選択した要素の寸法に関する全ての情報が表示されていて開発時には大変役に立ちます。上の図(ちょっと小さいですが)ではこの要素は、幅が895px、高さが1669px、パディング、ボーダー、マージンを四辺の全てで0pxということが分かります。これらの情報は全てExt.Elementのメソッドを使って取得することができます。
var dimSz = Ext.get('dim-sizing');
var padding = dimSz.getPadding('lrtb'); // 値は0
var border = dimSz.getBorderWidth('lrtb'); // 値は0
var height = dimSz.getHeight(); // 値は1691
var width = dimSz.getWidth(); // 値は895
上記コードをFirebugにコピーして実行してみてください。さらにセッターメソッドを使って実際に幅や高さを変更し、Firebugのレイアウトタブがどう変わるか観察してみてください(注意:もし同じ値にならない場合は、ブラウザそのもののサイズを変更してみてください)。

では残りのメソッドを見てきましょう:

位置の取扱い

Ext Coreでは要素の位置についても全てのブラウザーにおいて簡単に取り扱うための様々なAPIを提供しています。前述のサイズを取り扱うAPIと同じように、ほとんどのセッターメソッドにおいてアニメーション効果を設定することができます。では、実際の例を見てみましょう:

// カスタムアニメーション効果とともにX座標を75pxに設定
Ext.fly('elId').setX(75, {
    duration : .5, // アニメーション効果の持続時間を0.5秒に設定
    // 中身の文字を"finished"に変更
    callback: function(){ this.update("finished"); }
});

アニメーション機能

Ext Coreにはアニメーションプラグインが用意されていて、複数のアニメーション効果についても予め提供されています。また、このプラグインはExt.Elementで利用可能なメソッドとして設定されているため、例えば下記のようなことも簡単にできてしまいます:

Ext.fly('slideEl').slideOut('r');
上のコードをFirebugのコンソールにコピーして実行してみてください。上記以外にも基本的なアニメーション効果についてはほぼ全てExt Coreで予めカバーしています。Ext Coreのアニメーション効果は全てオブジェクトリテラルによる柔軟な設定が可能となっていますので、デフォルトの動作を変えたいときにでも簡単に対応可能です。例えば、アニメーションが終了した時点で何らかのコールバック関数を呼びたいときには下のようにするだけです:
Ext.fly('slideEl').slideOut('r', {
	callback : function(){
		alert('Finished sliding the element out');
	}
});
Ext Coreが提供する強力なアニメーション機能の一端がお分かり頂けたでしょうか?

Ext Coreのアニメーションでは8方向のアンカーをサポートしています。つまり、アニメーションの開始または終了箇所として8つの異なる場所を指定することができるというわけです。
アンカー値 説明
tl 左上のコーナー
t 上辺の中央
tr 右上のコーナー
l 左辺の中央
r 右辺の中央
bl 左下のコーナー
b 下辺の中央
br 右下のコーナー
では各メソッドについてh詳しく見ていきましょう:

その他

以下のメソッドは上記分類にあてはまりませんが、大変便利なメソッドです: