イベントの使用

Ext JS のコンポーネントとクラスは、そのライフサイクルの様々な時点で幅広いイベントを発火します。イベントによって、アプリケーションでの変化に対してコードが反応できるようになります。Ext JS の重要な概念の一つです。

イベントとは何ですか?

イベントとは、クラスで何かが起きると発火するものです。例えば、 Ext.Component が画面に描画されると、Ext JS はレンダリングが完了した後にイベントを発火します。単純なlisteners オブジェクトを設定すれば、そのイベントをリッスンできます。

Editor Preview Open in Fiddle
Ext.create('Ext.Panel', {
    html: 'My Panel',
    renderTo: Ext.getBody(),
    listeners: {
        afterrender: function() {
            Ext.Msg.alert('We have been rendered');
        }
    }
});

この例では、Preview(プレビュー)ボタンをクリックすると、パネルが画面に描画され、次に定義したアラートメッセージが表示されます。あるクラスが発火するすべてのイベントは、そのクラスの API ページに一覧があります。例えば、 Ext.panel.Panel には 現在45のイベントがあります。

イベントのリスニング

Ext.Component-event-afterrender は場合によっては便利ですが、他のイベントをより頻繁に使うかもしれません。例えば、 Ext.button.Button はクリックされたときに、 click イベントを発火します。

Editor Preview Open in Fiddle
Ext.create('Ext.Button', {
    text: 'Click Me',
    renderTo: Ext.getBody(),
    listeners: {
        click: function() {
            Ext.Msg.alert('I was clicked!');
        }
    }
});

コンポーネントには必要に応じてイベントリスナを含めることができます。次の例はユーザーを混乱させますが、mouseover のリスナ内に this.hide() を呼び出して、ボタンを非表示にしています。次にその1秒後にボタンを再び表示します。this.hide() が呼び出された後、ボタンは非表示になり、hide イベントが発火します。hide イベントは、hide リスナをトリガーーし、1秒待って再びボタンを表示させます。

Editor Preview Open in Fiddle
Ext.create('Ext.Button', {
    renderTo: Ext.getBody(),
    text: 'My Button',
    listeners: {
        mouseover: function() {
            this.hide();
        },
        hide: function() {
            // Waits 1 second (1000ms), then shows the button again
            Ext.defer(function() {
                this.show();
            }, 1000, this);
        }
    }
 });

イベントリスナはイベントが発生するたびに呼び出されているので、必要なだけボタンの表示と非表示を続けることができます。

後でリスナを追加する

前の例では、クラスをインスタンス化する時に、コンポーネントにリスナを渡しました。しかし、既にインスタンスがある場合、on 関数を利用してリスナを追加できます。

Editor Preview Open in Fiddle
var button = Ext.create('Ext.Button', {
    renderTo: Ext.getBody(),
    text: 'My Button'
});

button.on('click', function() {
    Ext.Msg.alert('Event listener attached by .on');
});

リスナ設定を使用することと同じように、.on メソッドを使って複数のリスナを指定することもできます。次は、mouseover イベントでボタンの表示を設定した前の例を再現します。

Editor Preview Open in Fiddle
var button = Ext.create('Ext.Button', {
    renderTo: Ext.getBody(),
    text: 'My Button'
});

button.on({
    mouseover: function() {
        this.hide();
    },
    hide: function() {
        Ext.defer(function() {
            this.show();
        }, 1000, this);
    }
});

リスナの削除

いつでもリスナを追加できるのと同様に、削除することもできます。今回は、un 関数を使用します。リスナを削除するには、その関数への参照が必要です。前の例では、リスナのオブジェクト、または on の呼び出しに関数を渡しました。今回は、関数を事前に作成し、そのカスタム関数を含む doSomething という変数にリンクさせます。最初に新しい doSomething 関数を listeners オブジェクトに渡しているので、コードが以前のように開始します。最後に Ext-method-defer 関数が追加されているので、最初の3秒間にボタンをクリックするとアラートが表示されますが、3秒経過するとリスナが削除されるため、何も起こりません。

Editor Preview Open in Fiddle
var doSomething = function() {
    Ext.Msg.alert('listener called');
};

var button = Ext.create('Ext.Button', {
    renderTo: Ext.getBody(),
    text: 'My Button',
    listeners: {
        click: doSomething,
    }
});

Ext.defer(function() {
    button.un('click', doSomething);
}, 3000);

スコープリスナオプション

スコープはハンドラ関数内の this の値を設定します。デフォルトでは、これはイベントを発火したクラスのインスタンスに設定されます。通常はこれが求められる機能性ですが、常にそうだというわけではありません。この機能性により、本ガイドの2つ前の例でボタンを非表示にするときに、this.hide() を呼び出すことができます。次の例では、ボタンとパネルを生成します。その後、ハンドラをパネルのスコープで実行している時に、ボタンの click イベントをリッスンします。これを行うためには、ハンドラ関数の代わりにオブジェクトを渡す必要があります。そのオブジェクトには、関数とスコープが含まれています。

Editor Preview Open in Fiddle
var panel = Ext.create('Ext.Panel', {
    html: 'Panel HTML'
});

var button = Ext.create('Ext.Button', {
    renderTo: Ext.getBody(),
    text: 'Click Me'
});

button.on({
    click: {
        scope: panel,
        fn: function() {
            Ext.Msg.alert(this.getXType());
        }
    }
});

この例を実行すると、click ハンドラの this の値がパネルの参照になります。これが示すように、スコープされたコンポーネントの xtype をアラートします。ボタンがクリックされると、パネルの xtype がアラートされるのが分かります。

イベントを1回だけリッスンする

あるイベントを1回だけリッスンしたい場合もあるかもしれません。イベントは何回も発火するかもしれませんが、今回は1回リッスンしたいだけです。以下のコードがこの状況を例しています。

Editor Preview Open in Fiddle
var button = Ext.create('Ext.Button', {
    renderTo: Ext.getBody(),
    text: 'Click Me',
    listeners: {
        click: {
            single: true,
            fn: function() {
                Ext.Msg.alert('I will say this only once');
            }
        }
    }
});

Buffer 設定の使用

短い間に連続して発火するイベントに対して buffer 設定を使用することによって、

リスナが呼び出される回数を減らすことができます。ここでは、何回クリックしても、ボタンの click リスナは2秒に1回だけ呼び出されます。

Editor Preview Open in Fiddle
var button = Ext.create('Ext.Button', {
    renderTo: Ext.getBody(),
    text: 'Click Me',
    listeners: {
        click: {
            buffer: 200,
            fn: function() {
                Ext.Msg.alert('I say this only once every 2 seconds');
            }
        }
    }
});

カスタムイベントの発火

自分で定義したイベントを発火させるには、イベント名で fireEvent を呼び出します。次の例では、myEvent と呼ばれるイベントを発火させ、ボタン自体の番号と、1〜100のランダムな数字の2つの引数を渡します。

Editor Preview Open in Fiddle
var button = Ext.create('Ext.Button', {
    renderTo: Ext.getBody(),
    text: "Just wait 2 seconds",
    listeners: {
        myEvent: function(button, points) {
            Ext.Msg.alert('myEvent fired! You score ' + points + ' points');
        }
    }
});

Ext.defer(function() {
    var number = Math.ceil(Math.random() * 100);

    button.fireEvent('myEvent', button, number);
}, 2000);

再び Ext.defer を使用して、カスタムイベントを発火する関数を、この場合は2秒遅らせています。イベントが発火したとき、myEvent リスナはそれを拾い上げて、渡された引数を表示します。

DOM イベントのリッスン

Ext JS コンポーネントがすべて、イベントを発火するわけではありません。しかし、コンテナの要素をターゲットにすると、コンポーネントがリッスンできる様々なネイティブなイベントにアタッチできます。この例では、Ext.container.Container をターゲットにしています。コンテナには click イベントはありません。1つ追加してみましょう。

Editor Preview Open in Fiddle
var container = Ext.create('Ext.Container', {
    renderTo: Ext.getBody(),
    html: 'Click Me!',
    listeners: {
        click: function(){
            Ext.Msg.alert('I have been clicked!')  
        }
    }
});

container.getEl().on('click', function(){ 
    this.fireEvent('click', container); 
}, container);

2つ目のブロックのコードがないと、コンテナの click リスナは発火しません。コンテナの要素をターゲットとし、click リスナをアタッチして、コンテナのイベント機能を拡張しました。

イベント正規化

イベント正規化によって、Ext JS 5 のアプリケーションはタッチスクリーンデバイス上で動作できます。この正規化は、バックグランドで動作し、標準のマウスイベントを対応するタッチイベントとポインタイベントに単純に変換します。

ポインタイベントは、w3c 標準で、入力デバイス(マウス、タッチ、スタイラスなど)に関わらず、画面の特定の座標をターゲットするイベントを扱います。

コードがマウスイベントのリスナをリクエストすると、フレームワークが必要に応じてよく似たタッチやポインタイベントをアタッチします。例えば、アプリケーションが mousedown リスナをアタッチするには、次を行います。

myElement.on('mousedown', someFunction);

タッチイベントをサポートするデバイスの場合には、イベントシステムがこれを touchstart に変換します。

myElement.on('touchstart', someFunction);

または、ポインタイベントをサポートするデバイスの場合には、これを pointerdown に変換します。

myElement.on('pointerdown', someFunction);

この変換は既に準備されているので、コードを追加しなくても、タブレットやタッチスクリーンのサポートを実現できます。

ほとんどの場合、フレームワークがマウス、タッチ、ポインタの入力をシームレスに切り替えることができます。しかし、いくつかのマウス操作(例えば、mouseover)は簡単にタッチ操作に変換できません。このようなイベントは個別に扱う必要がありますが、次のセクションで説明します。

ジェスチャー

標準 DOM イベントに加え、要素は合成された "gesture” イベントも発火します。Sencha Touch のイベントシステムは、Ext JS 5 の新しいイベントシステムの基盤となっているので、Sencha Touch のユーザーは、既にこの概念に馴染みがあるでしょう。

ブラウザから見ると、ポインタ、タッチ、マウスの各イベントには、主に3つのタイプ(Start、Move、End)があります。

イベント タッチ ポインタ マウス
Start touchstart pointerdown mousedown
Move touchmove pointermove mousemove
Stop touchend pointerup

これらのイベントのシーケンスとタイミングを解釈した後、dragswipelongpresspinchrotatetap などの複雑なイベントを合成します。次の例のように、Ext JS アプリケーションは他のイベントと同じようにジェスチャーイベントをリッスンできます。

Ext.get('myElement').on('longpress', handlerFunction);

オリジナルの Sencha Touch ジェスチャーシステムは、主にタッチイベントを念頭に設計されました。ジェスチャーシステムにポインタとマウスイベントの完全サポートを追加することによって、Ext JS 5 ではどのような入力に対してもジェスチャーが反応できます。これは、すべてのジェスチャーがタッチ入力でトリガーできるだけではなく、すべてのシングルポイントのジェスチャー(タップ、スワイプなど)もマウスを使用してトリガーできることを意味します。その結果、入力方法に関わらず、複数デバイスでシームレスに動作するジェスチャーシステムができました。

Last updated