NXML Event Handling
- NXML マクロ コマンド
- JSP ページ、サーブレット、静的ページなど、サーバーサイドのリソース
- MCO やシステム サービスへの呼び出しを含むクライアントサイドの Java コード
- イベントの概要
- マクロを使用したイベントの処理
- サーバーサイドのイベント処理
- クライアントサイドのイベント処理
- イベントの順序付け
- キーストローク、ボタンのクリック、コンポーネント上でのマウスのホバーリングなどの物理的イベント
- ドロップダウン リストや状態を変更するチェックボックスで行われる選択など、より高度な UI イベント
- マクロ (UI を定義する XML に含まれるクライアントサイドのスクリプト)
- サーバーサイドのドキュメント
- ユーザー定義のクライアント クラスまたは MCO のメソッド
- マクロを実行する
- イベント情報をエンコードして、HTTP を使用してサーバーサイドのハンドラに送信する
- イベント オブジェクトをクライアントサイドの MCO ハンドラに渡す
<button text="my button" onCommand="buttonclick.jsp" />
onCommand イベントがサーバー上の
buttonclick.jspに発生して、自動的に次の属性を URL パラメータとして渡します。- id 属性 - ユーザー定義の ID または Nexaweb で指定された ID
- event 属性 - この例では 'onCommand'
マクロのイベントハンドラの使用
クライアントサイドのマクロスクリプトを UI ドキュメントで定義して、クライアントイベントを処理できます。以下に示す例では、次の内容が定義されます。
- changeLabelTextMacro マクロ
- ボタンの onCommand ハンドラを macro://changeLabelTextMacro.execute() として定義
<macro:macro xmlns:macro="http://nexaweb.com/macro" name="changeLabelTextMacro"> <xu:modifications document="nxml" version="1.0" xmlns:xu="http://nexaweb.com/xupdate"> <xu:set-attribute select="id(''mylabel'')"> <xu:attribute name="text" value="Some new text"/> </xu:set-attribute> </xu:modifications> </macro:macro> <button onCommand="macro://changeLabelTextMacro.execute()" text="Change mylabel text" /> <label id="mylabel" text="This is some text" />
サーバーサイドのイベント処理
次の例では、JSP ページがイベントパラメータを受け取って XUpdate ドキュメントを生成し、クライアントに返すプロセスを示します。
UI ドキュメントはハンドラを次のように指定します。
<button onCommand="changeLabelText.jsp" text="Change mylabel text" /> <label id="mylabel" text="This is some text" />
<xu:modifications document="nxml" version="1.0" xmlns:xu=http://nexaweb.com/xupdate"> <xu:set-attribute select="id('mylabel')"> <xu:attribute name="text" value="Button <%= (request.getParameter("id") + " fired event " + request.getParameter("event")) %>"/> </xu:set-attribute> </xu:modifications>
サーバーサイドでクライアントイベントを処理する際にサーバーセッションまたはサーバーサイドのドキュメントにアクセスする必要がある場合は、次を呼び出すことができます。
SessionManager smgr = ServiceManager.getSessionManager(); ServerSession nxsession = smgr.findByRequest(request);
Document uiDom = nxsession.getDocumentRegistry().getUiDocument();
クライアントサイドのイベント処理
1. 簡単な要素へのアクセスと属性の変更
この例では、UI ドキュメントは MCO を宣言してハンドラを指定します。
<mco:declarations xmlns:mco="http://nexaweb.com/mco"> <mco:mco id="eventMco" src="pkg.EventHandlers"/> </mco:declarations> <nxml> <rootPane> <flowLayout/> <button onCommand="mco://eventMco.changeLabelText()" text="Change mylabel text" /> <label id="mylabel" text="This is some text" /> </rootPane> </nxml>
このハンドラは、ユーザーによって作成されたEventHandlers.java内にあるchangeLabelTextメソッドです。
private static final XPath LABEL_XPATH = XPathFactory.createXPath("id('mylabel')"); public void changeLabelText(){ ClientSession s = getSession(); Element label = LABEL_XPATH.evaluateAsElement( s.getDocumentRegistry().getUiDocument()); Object domLock = label.getOwnerDocument().getDomSynchronizationObject(); ClientEvent event = s.getEventHandler().getClientEvent(); synchronized(domLock){ label.setAttribute("text", "some new text from " + event.getParameter("id") + ":"+ event.getParameter("event")); } }
2. 時間のかかるクライアンサイドタスクの実行
イベント ハンドラで時間のかかるタスクを行う場合、待機中のカーソルを使用してユーザーに待機するよう通知した後、別のスレッドでタスクを実行できます。次の例で は、これを実行する方法を示します。この例は、ラベルの更新を完了するまでに 5 秒かかるタスクを示しています。このタスクがクライアントで実行中であることをユーザーに知らせるために、displayService.pushGlassPane()を実行して待機中のカーソルを表示し、この間ユーザーが入力を行わないようにします。タスクが終了すると、displayService.popGlassPane() は待機中のカーソルを解除して再び入力を受け付けます。
次に、この UI ドキュメントを示します。
<button onCommand="mco://eventMco.waitOnLongTask()" text="Change mylabel text" /> <label id="mylabel" text="This is some text" />
次に、MCO ハンドラのメソッドを示します。
public void waitOnLongTask(){ final ClientSession s = getSession(); s.getDisplayService().pushGlassPane(); new Thread(new Runnable(){ public void run(){ try{ Thread.sleep(5000); onChangeLabelText(); }catch(Exception e){ e.printStackTrace(); }finally{ s.getDisplayService().popGlassPane(); } } }).start(); } }
3. onBeforeActiveLostイベントハンドラ
これは、現要素からフォーカスがロストする前に、要素に検証コードを追加する際、または他の状態を確認する際使用することができる特別なイベントです。クライアントは要素の onActiveLost を発生させる前に onBeforeActiveLost イベントハンドラを発生させます。イベントハンドラが false を返す時、イベントは消費されます。つまり、現在のフォーカス要素にフォーカスは残ります。クライアントサイドのMCO だけが、onBeforeActiveLost イベントハンドラをハンドルすることができます。なぜならマクロやサーバーサイドのハンドラはブール値を戻すことができないからです。onBeforeActiveLost ハンドラは非常に早く実行しなくてはならないことに注意して下さい。
次の例は textField の入力長さが厳密に10 文字を維持していることを示しています。こうすることにより、10文字以下もしくは以上の場合、ユーザーが textfField をクリックしたりタブから離れることができないようにします。
次の例は UI 文書を示しています :
<textField text="input 10 characters only" onBeforeActiveLost="mco://eventMco.onBeforeActiveLost()"/>
次の例は MCO ハンドラメソッドを示しています:
public boolean onBeforeActiveLost(){ ClientSession s = McoContainer.getSession(); ClientEvent event = s.getEventHandler().getClientEvent(); String id = event.getParameter("id"); Element element = s.getDocumentRegistry().getUiDocument().getElementById(id); String text = (String)element.getAttribute("text"); if ( text.length() == 10) return true; else return false; } }
イベントの順序
Nexaweb Platform は多くの異なるイベントを提供します。中にはボタンの onCommand や onMouseUp のように順番に実行されるものもあります。次ではイベント発生順序に関する一般的な情報を提供しています :
メモ: 順番に発火する可能性がある、複数のイベントをハンドリングする際、気を付けて下さい。例えば最初のハンドラにフラグを設定する、または2番目のハンドラをリダイレクトするなど。
- onBeforeActiveLost イベントはフォーカスを失う際に発生します。クライアントが onBeforeActiveLost イベントに false を戻す場合、コンポーネントはフォーカスを失わず、他のイベントは発生しません。
- ユーザが <Enter> キーを押下する際、onCommand イベントが常に最初に実行されます。
- 物理的イベントから直接発生するイベントに関しては、次の順番でイベントが発生します:
- onKeyDown (<Enter>以外のキーボードアクションの場合) または onMouseDown (マウスクリックの場合) イベントが最初に発火します。
- その後、フォーカスに変更がある際、テキストに変更のあるテキストコンポーネントがフォーカスを失った場合 onEdit イベントが先行します。
- 次に onActiveLost が発生し、onActiveGained が続きます。
- フォーカス変更後、onStateChange のような上位レベルの合成イベントが続きます。
- 次に、キーボードイベントに対し、onKeyCharが発生します。
- リリースでは、onKeyUp が キーボードに対し発生するか、マウスによる onMouseUp が発生します (ボタンのonCommandの後) 。