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ライブラリの中で最多のメソッドを持つクラスです。これらのメソッドは以下のように分類することができます:
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パターンは一つのグローバルオブジェクトを生成し、そのオブジェクトを繰り返し利用することによりメモリーの利用量を最小化するためのデザインパターンです。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メソッドを利用するためには、この動作の仕組みをしっかりと理解しておく必要があります。
var el1 = Ext.get('elId'); // elementのidが引数 var el2 = Ext.get(el1); // Ext.Elementが引数 var el3 = Ext.get(el1.dom); // HTMLElementが引数
// エレメントに対して単純なアクションを実行。 Ext.fly('elId').hide();
// idをもとにDomノードを取得 var elDom = Ext.getDom('elId'); // DomノードをもとにDomノードを取得 var elDom1 = Ext.getDom(elDom); // 変数がExt.ElementかDomノードか不明なときには // Ext.getDomを使ってください function(el){ var dom = Ext.getDom(el); // Domノードに対する処理 }
ここまで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が提供している機能をみていきましょう。
Ext.fly('elId').addClass('myCls'); // 'myClass'というCSSクラスを'elId'というidを持つHTML要素に追加
// 'myCls'というCSSクラスを'elId'というidを持つHTML要素に追加して、隣接する要素から'myCls'を // 削除する Ext.fly('elId').radioClass('myCls');
Ext.fly('elId').removeClass('myCls'); // HTML要素から'myCls'を削除
Ext.fly('elId').toggleClass('myCls'); // 'myCls'が追加 Ext.fly('elId').toggleClass('myCls'); // 'myCls'が削除 Ext.fly('elId').toggleClass('myCls'); // 'myCls'が再度追加
if (Ext.fly('elId').hasClass('myCls')) { // 'myCls'が適用されていた場合の処理 }
Ext.fly('elId').replaceClass('myClsA', 'myClsB');
var color = Ext.fly('elId').getStyle('color'); var zIndx = Ext.fly('elId').getStyle('z-index'); var fntFmly = Ext.fly('elId').getStyle('font-family'); // ... etc
Ext.fly('elId').setStyle('color', '#FFFFFF'); Ext.fly('elId').setStyle('z-index', 10); Ext.fly('elId').setStyle({ display : 'block', overflow : 'hidden', cursor : 'pointer' }); // 色の変化にアニメーション効果を伴わせる Ext.fly('elId').setStyle('color', '#FFFFFF', true); // 色の変化にアニメーション効果(持続時間0.75秒)を伴わせる Ext.fly('elId').setStyle('color', '#FFFFFF', {duration: .75}); // ... etc
Ext.fly('elId').getColor('background-color'); Ext.fly('elId').getColor('color'); Ext.fly('elId').getColor('border-color'); // ... etc
Ext.fly('elId').setOpacity(.5); Ext.fly('elId').setOpacity(.45, true); // アニメーション効果 // アニメーション効果(0.5秒の持続時間) Ext.fly('elId').setOpacity(.45, {duration: .5});
Ext.fly('elId').clearOpacity();
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');以下がその結果です:
var el = Ext.get('elId'); if (el.is('p.myCls')) { // 何らかの処理 }
Ext.fly('elId').findParent('div'); // 'elId'の親ノードでdivタグを持つノードを返す Ext.fly('elId').findParent('div', 4); // 'elId'から4階層上までの親ノードを検索 Ext.fly('elId').findParent('div', null, true); // 戻り値をExt.Elementとして返す
Ext.fly('elId').findParentNode('div');
Ext.fly('elId').up('div'); Ext.fly('elId').up('div', 5); // 5階層上までの親ノードを検索
// 検索結果をCompositeElementとして返す Ext.fly('elId').select('div:nth-child(2)'); // 検索結果をExt.Elementの配列として返す Ext.fly('elId').select('div:nth-child(2)', true); // ドキュメント全体を検索 Ext.select('div:nth-child(2)');
Ext.query('div:nth-child(2)'); // セレクタにマッチするDOMノードの配列を返す
Ext.fly('elId').child('p.highlight'); // Ext.Elementを返す Ext.fly('elId').child('p.highlight', true); // DOMノードを返す
Ext.fly('elId').down('span'); // Ext.Elementを返す Ext.fly('elId').down('span', true); // DOMノードを返す
// 親ノードをExt.Elementとして返す Ext.fly('elId').parent(); // 親ノードをDOMノードとして返す Ext.fly('elId').parent("", true); // divタグの親ノードを探してExt.Elementとして返す Ext.fly('elId').parent("div");
// 次の隣接ノードをExt.Elementとして返す Ext.fly('elId').next(); // 次の隣接ノードをDOMノードとして返す Ext.fly('elId').next("", true); // divタグの隣接ノードをこのエレメントの後方に探してExt.Elementとして返す Ext.fly('elId').next("div");
// 前の隣接ノードをExt.Elementとして返す Ext.fly('elId').prev(); // 前の隣接ノードをDOMノードとして返す Ext.fly('elId').prev("", true); // divタグの隣接ノードをこのエレメントの前方に探してExt.Elementとして返す Ext.fly('elId').prev("div");
// 最初の子ノードをExt.Elementとして返す Ext.fly('elId').first(); // 最初の子ノードをDOMノードとして返す Ext.fly('elId').first("", true); // divタグを持つ最初の子ノードをこのエレメント内をを探してExt.Elementとして返す Ext.fly('elId').first("div");
// 最後の子ノードをExt.Elementとして返す Ext.fly('elId').last(); // 最後の子ノードをDOMノードとして返す Ext.fly('elId').last("", true); // divタグを持つ最後の子ノードをこのエレメント内をを探してExt.Elementとして返す Ext.fly('elId').last("div");
動的な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を実際に表示すると下のようになります:
Ext.fly('elId').insertFirst({ tag: 'p', html: 'Hi I am the new first child' });ノードが挿入されました:
var el = Ext.get('elId1'); // 'elId2'というidを持つDOMノードを追加 Ext.fly('elId').appendChild('elId2'); // elというExt.Elementを追加 Ext.fly('elId').appendChild(el); // 配列内のidを持つDOMノードを追加 Ext.fly('elId').appendChild(['elId2','elId3']); // DOMノードを追加 Ext.fly('elId').appendChild(el.dom); // Ext.selectの結果のCompositeElementを追加 Ext.fly('elId').appendChild(Ext.select('div'));
var el = Ext.get('elId1'); Ext.fly('elId').appendTo('elId2'); // 'elId2'というidをもつDOMノードに追加 Ext.fly('elId').appendTo(el); // elというExt.Elementに追加
var el = Ext.get('elId1'); // 'elId2'というidを持つDOMノードの直前に挿入 Ext.fly('elId').insertBefore('elId2'); // elというExt.Elementの直前に挿入 Ext.fly('elId').insertBefore(el);
var el = Ext.get('elId1'); // 'elId2'というidを持つDOMノードの直後に挿入 Ext.fly('elId').insertAfter('elId2'); // elというExt.Elementの直後に挿入 Ext.fly('elId').insertAfter(el);
var el = Ext.get('elId1'); // 'elId2'というidを持つDOMノードを一番目の子ノードとして挿入 Ext.fly('elId').insertFirst('elId2'); // elというExt.Elementを一番目の子ノードとして挿入 Ext.fly('elId').insertFirst(el); // Ext.DomHelperにより新しいノードを生成し、一番目の子ノードとして挿入 Ext.fly('elId').insertFirst({ tag: 'p', cls: 'myCls', html: 'Hi I am the new first child' });
var el = Ext.get('elId1'); // 'elId2'というidを持つDOMノードを'elId'というidを持つDOMノードで置換 Ext.fly('elId').replace('elId2'); // elというExt.Elementを'elId'というidを持つDOMノードで置換 Ext.fly('elId').replace(el);
var el = Ext.get('elId1'); Ext.fly('elId').replaceWith('elId2'); // 'elId'というidを持つDOMノードを'elId2'で置換 Ext.fly('elId').replaceWith(el); // 'elId'というidを持つDOMノードをelというExt.Elementで置換 // Ext.DomHelperにより新しいノードを生成し、'elId'というidを持つDOMノードを置換 Ext.fly('elId').replaceWith({ tag: 'p', cls: 'myCls', html: 'Hi I have replaced elId' });
Ext.fly('elId').remove(); // 'elId'というidを持つDOMノードをDOMツリーから削除
Ext.removeNode(node); // node (HTMLElement) がDOMから削除されます
.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のメソッドの例を挙げておきます:
var el = Ext.get('elId'); var dhConfig = { tag: 'p', cls: 'myCls', html: 'Hi I have replaced elId' }; // 'elId'というidを持つDOMノードに新しいノードを生成・挿入 el.createChild(dhConfig); // elの最初の子ノードの直前に新しいノードを生成・挿入 el.createChild(dhConfig, el.first());
Ext.fly('elId').wrap(); // 'elId'というidを持つDOMノードをdivタグでラッピングする // 'elId'というidを持つDOMノードを新しく生成したDOMノードでラッピングする Ext.fly('elId').wrap({ tag: 'p', cls: 'myCls', html: 'Hi I have replaced elId' });
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フラグメントは以下のメソッドで利用することが可能です:
Ext.fly('elId').insertHtml( 'beforeBegin', '<p><a href="anotherpage.html'>click me</a></p>' ); // DOMノードを返す Ext.fly('elId').insertHtml( 'beforeBegin', '<p><a href="anotherpage.html'>click me</a></p>', true ); // Ext.Elementを返す
Ext Coreには強力なAjax用のAPIが含まれています。Ajax用APIについては後のセクションで詳細にカバーしますが、Ext.Elementにおいて利用できるAjaxのメソッドについて簡単に説明します:
Ext.fly('elId').load({url: 'serverSide.php'})
var updr = Ext.fly('elId').getUpdater(); updr.update({ url: 'http://myserver.com/index.php', params: { param1: "foo", param2: "bar" } });
イベント処理はブラウザ間の差異に大きく悩まされるテーマの一つです。ブラウザーが提供しているイベント処理関数を利用する場合、イベントの追加・削除に必要なメソッドがそもそもブラウザー間で違うだけでなく、その他の雑多な一貫性の無さに悩まされることになります。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を引数として受け取ることになります。
では、イベント処理のためのメソッドを見ていきましょう:
var el = Ext.get('elId'); el.on('click', function(e,t) { // eは正規化されたイベントオブジェクト(Ext.EventObject) // tはクリックされたExt.Element // thisもtを参照しています });
var el = Ext.get('elId'); el.un('click', this.handlerFn); // or el.removeListener('click', this.handlerFn);
// eは一般的なイベントオブジェクトではなく、Ext.EventObjectのインスタンス function handleClick(e){ e.preventDefault(); var target = e.getTarget(); ... } var myDiv = Ext.get('myDiv'); myDiv.on("click", handleClick); //あるいは Ext.EventManager.on('myDiv', 'click', handleClick); Ext.EventManager.addListener('myDiv', 'click', handleClick);
Ext Coreはイベントの委譲、バッファー、遅延実行といったより高度なイベント処理を行うための便利なメソッドが容易されています。
「あるグループに属する複数の要素それぞれにイベントハンドラー関数を登録するのではなく、そのグループを内包する要素(コンテナ要素)に1つのイベントハンドラー関数を結び付け、イベントバブルの仕組みを利用してコンテナ要素にイベント処理を集約・一元化する」ということになります。 これはbodyタグにたった1つのグローバルなイベントハンドラー関数を結びつけるという意味ではありません。確かにページ上で発生するイベントは最終的にbodyタグまで登っていきますが、そこまでやってしまうと逆に実行速度に悪い影響を与えてしまうことになります。このテクニックは例えばドロップダウンリストやカレンダーのような多数の要素によって構成されるグループに対して非常に有効です。では、例を見ていきましょう:
<ul id='actions'> <li id='btn-edit'></li> <li id='btn-delete'></li> <li id='btn-cancel'></li> </ul>次のようにイベントハンドラー関数を全てのリストアイテムに結びつけるのではなく:
Ext.fly('btn-edit').on('click, function(e,t) { // イベントを処理 }); Ext.fly('btn-delete').on('click, function(e,t) { // イベントを処理 }); Ext.fly('btn-cancel').on('click, function(e,t) { // イベントを処理 });イベント委譲のテクニックを利用するためには、コンテナ要素に必要な処理を組み込んだイベントハンドラー関数を結びつけます:
Ext.fly('actions').on('click, function(e,t) { switch(t.id) { case ''btn-edit': // イベント処理 break; case 'btn-delete': // イベント処理 break; case 'btn-cancel': // イベント処理 break; } });イベントはDOMツリーを上位層に登っていくため、リストアイテム上で発生したイベントはすべて'actions'というイベントハンドラー関数を結びつけたdivタグに到達することになります。イベントハンドラー関数の中ではswitch文を使ってイベントの発生源別の処理を実行します。この方法であればイベントハンドラー関数は1つのままでリストアイテムの数が増えても比較的簡単に対応が可能です。
el.on('click', function(e,t) { // クリックイベントを処理 }, this, { // CSSクラス'clickable'を持つ子ノードにイベントターゲットを絞り込み delegate: '.clickable' });
el.on('click', function(e,t) { // クリック時の処理 }, this, { single: true // イベントハンドラー関数の呼び出し後に削除 });
el.on('click', function(e,t) { // クリック時の処理 }, this, { buffer: 1000 // クリックイベントが実際に発生してから1000ミリ秒(1秒)後に // イベントハンドラー関数を実行する });
el.on('click', function(e,t) { // クリック時の処理 }, this, { delay: 1000 // クリックイベントが実際に発生してから1000ミリ秒(1秒)後に // イベントハンドラー関数を実行する(キャンセルなし) });
el.on('click', function(e,t) { // クリック時の処理 }, this, { // イベントが最初のdivタグに届いたときに実行 target: el.up('div') });
// マウスが要素に入ったときの処理 function enter(e,t){ t.toggleClass('red'); } // マウスが要素から出たときの処理 function leave(e,t){ t.toggleClass('red'); } // hoverを呼び出し el.hover(enter, leave);
el.removeAllListeners();
ページ上の特定の要素の寸法を再設定したりその情報を取得したり、といったことは頻繁に行う操作の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の右側のパネルの「レイアウト」タブを選択すると下のような図が表示されるはずです:
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のレイアウトタブがどう変わるか観察してみてください(注意:もし同じ値にならない場合は、ブラウザそのもののサイズを変更してみてください)。
var ht = Ext.fly('elId').getHeight();
var wd = Ext.fly('elId').getWidth();
Ext.fly('elId').setHeight();
Ext.fly('elId').setWidth();
var bdr_wd = Ext.fly('elId').getBorderWidth('lr');
var padding = Ext.fly('elId').getPadding('lr');
Ext.fly('elId').clip();
Ext.fly('elId').unclip();
if (Ext.isBorderBox) {
// 何らかの処理
}
Ext Coreでは要素の位置についても全てのブラウザーにおいて簡単に取り扱うための様々なAPIを提供しています。前述のサイズを取り扱うAPIと同じように、ほとんどのセッターメソッドにおいてアニメーション効果を設定することができます。では、実際の例を見てみましょう:
// カスタムアニメーション効果とともにX座標を75pxに設定 Ext.fly('elId').setX(75, { duration : .5, // アニメーション効果の持続時間を0.5秒に設定 // 中身の文字を"finished"に変更 callback: function(){ this.update("finished"); } });
var elX = Ext.fly('elId').getX() var elY = Ext.fly('elId').getY()
var elXY = Ext.fly('elId').getXY() // elXYは配列
Ext.fly('elId').setX(10) Ext.fly('elId').setY(10)
Ext.fly('elId').setXY([20,10])
var elOffsets = Ext.fly('elId').getOffsetsTo(anotherEl);
var elLeft = Ext.fly('elId').getLeft(); var elRight = Ext.fly('elId').getRight();
var elTop = Ext.fly('elId').getTop(); var elBottom = Ext.fly('elId').getBottom();
Ext.fly('elId').setLeft(25) Ext.fly('elId').setRight(15)
Ext.fly('elId').setTop(12) Ext.fly('elId').setBottom(15)
Ext.fly('elId').setLocation(15,32)
Ext.fly('elId').moveTo(12,17)
Ext.fly('elId').position("relative")
Ext.fly('elId').clearPositioning() Ext.fly('elId').clearPositioning("top")
var pos = Ext.fly('elId').getPositioning()
Ext.fly('elId').setPositioning({ left: 'static', right: 'auto' })
// {left:translX, top: translY} var points = Ext.fly('elId').translatePoints(15,18);
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が提供する強力なアニメーション機能の一端がお分かり頂けたでしょうか?
| アンカー値 | 説明 |
|---|---|
| tl | 左上のコーナー |
| t | 上辺の中央 |
| tr | 右上のコーナー |
| l | 左辺の中央 |
| r | 右辺の中央 |
| bl | 左下のコーナー |
| b | 下辺の中央 |
| br | 右下のコーナー |
// デフォルトは上辺中央からスライドしながら登場 el.slideIn(); // デフォルトは下辺中央にスライドしながら退場 el.slideOut(); // 上記デフォルトの動作を明示的にコンフィグオプションで表した場合 el.slideIn('t', { easing: 'easeOut', duration: .5 }); el.slideOut('t', { easing: 'easeOut', duration: .5, remove: false, useDisplay: false });
// デフォルト el.puff(); // 上記デフォルトの動作を明示的にコンフィグオプションで表した場合 el.puff({ easing: 'easeOut', duration: .5, remove: false, useDisplay: false });
// デフォルト el.switchOff(); // 上記デフォルトの動作を明示的にコンフィグオプションで表した場合 el.switchOff({ easing: 'easeIn', duration: .3, remove: false, useDisplay: false });
// デフォルトは背景色を黄色に変更 el.highlight(); // 上記デフォルトの動作を明示的にコンフィグオプションで表した場合 el.highlight("ffff9c", { // 色の設定が可能なCSSプロパティであればどれでもOK attr: "background-color", endColor: (現在の色) または "ffffff", easing: 'easeIn', duration: 1 });
// デフォルトは薄青色の波紋が1つ el.frame(); // 上記デフォルトの動作を明示的にコンフィグオプションで表した場合 el.frame("C3DAF9", 1, { duration: 1 // それぞれの波紋の拡散時間 // 注意:"easing"はこのメソッドでは利用できません });
el.pause(1);
// fadeInのデフォルトはopacity(不透明度)を0から100%に変化 el.fadeIn(); el.fadeOut(); // 上記デフォルトの動作を明示的にコンフィグオプションで表した場合 el.fadeIn({ endOpacity: 1, // 0から1の間の数値 easing: 'easeOut', duration: .5 }); el.fadeOut({ endOpacity: 0, // 0から1の間の数値 easing: 'easeOut', duration: .5, remove: false, useDisplay: false });
// 高さと幅をそれぞれ100pxに変更 el.scale(100, 100); // 上記デフォルトの動作を明示的にコンフィグオプションで表した場合 // 高さと幅にnullを渡すと現在の値がデフォルトで設定されます el.scale( 100, 100, { easing: 'easeOut', duration: .35 } );
// 水平方向に200pxスライドさせ、同時に高さと透明度を変化させる el.shift({ x: 200, height: 50, opacity: .8 }); // 上記デフォルトの動作を明示的にコンフィグオプションで表した場合 el.shift({ width: [element's width], height: 50 x: 200 y: [element's y position], opacity: .8 easing: 'easeOut', duration: .35 });
// デフォルトはフェードアウトしながら下辺中央にスライドアウト el.ghost(); // 上記デフォルトの動作を明示的にコンフィグオプションで表した場合 el.ghost('b', { easing: 'easeOut', duration: .5, remove: false, useDisplay: false });
var el = Ext.get('complexEl') el.animate({ borderWidth: {to: 3, from: 0}, opacity: {to: .3, from: 1}, height: {to: 50, from: el.getHeight()}, width: {to: 300, from: el.getWidth()} });
以下のメソッドは上記分類にあてはまりませんが、大変便利なメソッドです:
el.focus();
el.blur();
el.getValue(); el.getValue(true); // "value"の値を数値に変換
if (Ext.isBorderBox) { }
el.getAttributeNS("","name");