reactive-web: Lift をシンプルに

イベント

Reactive-web での処理の大部分は、ブラウザのイベントに関連したものです。ここで言うイベントとは、ある要素に対してブラウザが発火できる任意のイベントを意味します。たとえば、マウスの操作やキーボード入力などです。通常、これらのイベントにはダイレクトに反応したいものです。また、要素のプロパティは、イベントを介してサーバーに伝播されます。

DomEvent

DomEvent は、ブラウザによってトリガされたイベントオブジェクトを表すシンプルなトレイトです。このトレイトを継承する case クラスと case オブジェクトは、さまざまな DOM イベントとその状態を表します。ブラウザがイベントを発火したとき、reactive-web はコードに対し、対応する DomEvent インスタンスを発火することができます。

DomEventSource

続いて、DomEventSource について説明しましょう。DomEventSource は、イベントデータをエンコードした値を発火する JsEventStream をラップしています。そのため、サーバーに対する ajax 呼び出しを行わなくても、クライアントサイドでイベントを処理できます。また、DomEventSource には、DomEvent インスタンスを発火する EventStream インスタンス (lazy val で、JsEventStreamtoServer を呼び出すことによって実装) があります。DomEventSource は、JsEventStream を発火するイベントハンドラ属性を生成する機能を提供します。

DomEventSource は、型パラメータとしてイベントの型を指定してインスタンス化するだけで作成できます。

new DomEventSource[Focus]

また、DomEventSource コンパニオンオブジェクトにはさまざまな簡易メソッドが含まれているので、DomEventSource.click などのように記述することができます。

Elem があったら、これを EventStreamapply メソッドに渡して、イベントハンドラ属性を持った新しい Elem を取得することができます。また、DomEventSourceNodeSeq=>NodeSeq を継承しているので、Lift の CSS セレクタまたはバインディングで使用することができます。次に例を示します。

<!-- テンプレート内 -->
<button>Delete!</button>
// スニペットクラス内
def render = {
  val click = DomEventSource.click
  for(_ <- click.eventStream)
    confirm("Are you sure you want to delete it?"){
      case true => // 削除する
    }
  "button" #> click
}

以下にメンバの一部を示します。

jsEventStream
ブラウザの JavaScript イベントストリームのプロキシとなる JsEventStream
eventStream
遅延インスタンス化される EventStream で、jsEventStreams の値を DomEvent としてサーバーに伝播します。
addEventData
このイベントに応答して発火すべき追加の JsEventStream、および発火すべき値を計算する JsExp を提供します。

なお、DomEventSourceForwardableJsForwardable を継承しているので、これらに用意されている簡易演算子を使ってさまざまな reactive オブジェクトを結び付けることができます。