ヘッダーをスキップ
Oracle® Fusion Middleware Oracle Application Development Framework Webユーザー・インタフェース開発者ガイド
11gリリース1 (11.1.1.7.0)
B52029-11
  目次へ移動
目次

前
 
次
 

5 イベントの処理

この章では、サーバーおよびクライアントでのイベントの処理方法について説明します。

この章では、次の項目について説明します。

5.1 イベントおよびイベント処理の概要

従来のJSFアプリケーションでは、イベント処理は通常サーバーで行われます。JSFのイベント処理はJavaBeansイベント・モデルをベースにしており、JSFアプリケーションでイベント・クラスおよびイベント・リスナー・インタフェースを使用して、コンポーネントで生成されたイベントが処理されます。

アプリケーションでのユーザー・イベントの例には、ボタンまたはリンクのクリック、メニューまたはリストからの項目の選択、入力フィールドの値の変更などがあります。ボタンのクリックなどのユーザー・アクティビティが発生すると、コンポーネントは、イベントに関する情報を格納し、イベントを生成したコンポーネントを識別するイベント・オブジェクトを作成します。イベントはイベント・キューにも追加されます。JSFライフサイクルの適切なタイミングで、登録された適切なリスナーにイベントをブロードキャストするようにJSFからコンポーネントに指示し、リスナーでは、イベントを処理するリスナー・メソッドが起動されます。リスナー・メソッドによって、ユーザー・インタフェースの変更がトリガーされる場合、またはバックエンド・アプリケーション・コードが起動される場合(あるいはその両方)があります。

標準JSFコンポーネントと同様に、コンポーネントがアクティブになると、ADF FacesコンポーネントでActionEventイベントが配信され、コンポーネントのローカル値が変更されると、ADF Facesの入力および選択コンポーネントでValueChangeEventイベントが配信されます。

たとえば、File Explorerアプリケーションでは、commandMenuItemコンポーネントを使用してユーザーがファイルまたはフォルダを新たに作成できるサブメニューが「ファイル」メニューに含まれます。ユーザーが「フォルダ」commandMenuItemをクリックすると、ActionEventイベントが起動されます。コンポーネントのactionListener属性の値として設定されているEL式がheaderManagerマネージドBeanのcreateNewDirectoryメソッドと解決されるため、このメソッドが起動されてディレクトリが新たに作成されます。


注意:

組込みイベント機能を持つADF Facesコンポーネントはformタグに含める必要があります。


ADF Facesは標準JSFイベント処理手法に準拠していますが、次の2つの主要な方法を提供することでイベント処理機能を向上させています。

5.1.1 イベントおよび部分ページ・レンダリング

標準JSFイベントとは異なり、ADF FacesイベントではAJAXスタイルの部分ポストバックがサポートされ、部分ページ・レンダリング(PPR)が行えます。フル・ページ・レンダリングのかわりに、ADF Facesのイベントおよびコンポーネントでは、リクエスト時にページの一部のみがリフレッシュされる部分ページ・レンダリングがトリガーされます。

特定のコンポーネントはイベント・ルート・コンポーネントとみなされます。イベント・ルート・コンポーネントによってページでの境界が決まるため、その境界内のコンポーネントにのみライフサイクルを実行できます(ライフサイクルのこの機能の詳細は、4.3項「最適化されたライフサイクルの使用」を参照)。イベント・ルート内でイベントが発生した場合、ページでは、ルートの子であるコンポーネントのみリフレッシュされます。イベント・ルート・コンポーネントの例はポップアップです。ポップアップ内でイベントが発生すると、ポップアップとその子のみが再レンダリングされ、ページ全体は再レンダリングされません。

イベント・ルート・コンポーネントとみなされるコンポーネントは、次のとおりです。

  • popup

  • region

  • panelCollection

  • calendar

  • editableValueHolderコンポーネント(inputTextなど)

また、特定のイベントは、特定のコンポーネントをイベント・ルート・コンポーネントとして指定します。たとえば、showDetailコンポーネントを展開または縮小する(8.9項「コンテンツの動的な表示および非表示」を参照)と送信される表示イベントは、showDetailコンポーネントがルートであることを示します。ライフサイクルはshowDetailコンポーネント(および子コンポーネントまたはこれをトリガーとするその他のコンポーネント)でのみ実行され、展開または縮小時にこのコンポーネントのみがレンダリングされます。

表5-1に、ADF Facesでのイベント・タイプと、ソース・コンポーネントがイベント・ルートかどうかを示します。

表5-1 イベントとイベントのルート・コンポーネント

イベント・タイプ コンポーネントのトリガー先 イベント・ルートか

action

すべてのコマンド・コンポーネント

false

dialog

dialog

false

disclosure

showDetailshowDetailHeader

true

disclosure

showDetailItem

true

focus

treetreeTable

true

launch

すべてのコマンド・コンポーネント

該当せず

launchPopup

inputListOfValuesinputComboboxListOfValues

true

load

document

該当せず

poll

poll

true

popupOpened

popup

該当せず

popupOpening

popup

該当せず

popupClosed

popup

該当せず

propertyChange

すべてのコンポーネント

該当せず

queryEvent

queryquickQuery

true

queryOperation

queryquickQuery

true

rangeChange

table

該当せず

regionNavigation

region

該当せず

return

すべてのコマンド・コンポーネント

true

returnPopupData

inputListOfValuesinputComboboxListOfValues

true

returnPopup

inputListOfValuesinputComboboxListOfValues

true

rowDisclosure

treetreeTable

true

selection

treetreeTabletable

true

sort

treeTabletable

true

valueChange

すべての入力および選択コンポーネント(EditableValueHolderを実装するコンポーネント)

true



ヒント:

イベント・ルートを処理したときにイベント・ルートの外部にあるコンポーネントを処理する必要がある場合は、それらのコンポーネントのpartialTrigger属性をイベント・ルート・コンポーネントのIDに設定する必要があります。


5.1.2 クライアント側イベント・モデル

サーバー側のアクションおよび値変更イベントの他に、ADF Facesコンポーネントでは、クライアント側のアクションおよび値変更イベント、その他のサーバーおよびクライアント・イベントが起動されます。サーバー・コンポーネントとクライアント・コンポーネントの両方で生成されるイベント(選択イベントなど)も、サーバー・コンポーネントでのみ生成されるイベント(起動イベントなど)も、クライアント・コンポーネントでのみ生成されるイベント(ロード・イベントなど)もあります。

デフォルトでは、ほとんどのクライアント・イベントはサーバーに伝播されます。コンポーネント状態に対する変更は、サーバーに自動的に同期されて状態の一貫性が確保され、必要に応じてイベントがサーバーに配信されてさらに処理されます。ただし、伝播されないようにイベントを構成することもできます。

また、サーバー側Javaコンポーネントにクライアント側イベント・リスナーを登録すると、RCFでJavaScriptコンポーネントが必要であるとみなされ、クライアント側コンポーネントが作成されます。

クライアント側JavaScriptイベントのソースはいくつかあります。DOMイベントやプロパティ変更イベントから自動的に導出されることもあれば、他のイベントの処理時に手動で作成することもできます。

5.2 ADF Facesサーバー・イベントの使用

ADF Facesには、多数のサーバー側イベントが用意されています。表5-2に、サーバーのADF Facesコンポーネントで生成されるイベントと、これをトリガーするコンポーネントを示します。

表5-2 ADF Facesサーバー・イベント

イベント トリガー元コンポーネント

ActionEvent

すべてのコマンド・コンポーネント

DialogEvent

dialog

DisclosureEvent

showDetailshowDetailHeadershowDetailItem

FocusEvent *

treetreeTable

LaunchEvent

すべてのコマンド・コンポーネント

LaunchPopupEvent

inputListOfValuesinputComboboxListOfValues

LoadEvent **

document

PollEvent

poll

QueryEvent

queryquickQuery

QueryOperationEvent

queryquickQuery

RangeChangeEvent

table

RegionNavigationEvent

region

ReturnEvent

すべてのコマンド・コンポーネント

ReturnPopupEvent

inputListOfValuesinputComboboxListOfValues

RowDisclosureEvent

treetreeTable

SelectionEvent

treetreeTabletable

SortEvent

treeTabletable

ValueChangeEvent

すべての入力および選択コンポーネント(EditableValueHolderを実装するコンポーネント)


* このフォーカス・イベントは、特定のサブツリーがフォーカスされると生成されます。クライアント側のキーボード・フォーカス・イベントとは異なります。

** LoadEventイベントは、初期ページが表示された後に起動されます(データ・ストリーミングの結果は後で届くことがあります)。

すべてのサーバー・イベントには、関連付けられたコンポーネントに対するイベント・リスナーがあります。そのイベントを処理するハンドラを作成し、そのハンドラ・コードをコンポーネントのリスナーと関連付ける必要があります。

たとえば、File Explorerアプリケーションの場合、ユーザーが表の行を選択すると選択イベントが起動されます。表のselectionListener属性は、TableContentView.javaマネージドBeanのtableSelectFileItemハンドラ・メソッドにバインドされているため、このメソッドがイベントに対応して起動されます。

サーバー側イベントを処理する手順:

  1. マネージドBean(イベント・リスナーを使用するページの場合はバッキングBean)に、イベント(イベント・タイプ)を唯一のパラメータとし、voidを返すpublicメソッドを作成します。例5-1に、tableSelectFileItemハンドラのコードを示します。(マネージドBeanの作成と使用の詳細は、2.6項「マネージドBeanの作成と使用」を参照してください。)

    例5-1 イベント・リスナー・メソッド

      public void tableSelectFileItem(SelectionEvent selectionEvent)
      {
        FileItem data = (FileItem)this.getContentTable().getSelectedRowData();
        setSelectedFileItem(data);
      }
    

    ヒント:

    イベント・リスナー・コードがアプリケーションの複数ページで使用されることが多い場合、すべてのページでアクセスできるイベント・リスナー実装クラスの作成を検討します。すべてのサーバー・イベント・リスナー・クラスの実装では、processEvent()メソッド(Eventはイベント・タイプ)をオーバーライドする必要があります。

    たとえば、LaunchListenerイベント・リスナーは、LaunchEventのインスタンスを単一引数とします。実装では、次のメソッド・シグネチャに示すように、イベント処理メソッドをオーバーライドする必要があります。

    public void processLaunch (LaunchEvent evt) 
    {
      // your code here
    }
    

  2. イベント・リスナー・メソッドをコンポーネントに登録するには、構造ウィンドウでイベントを起動するコンポーネントを選択します。プロパティ・インスペクタでイベント・リスナー・プロパティの隣にあるドロップダウン・メニューを使用し、「編集」を選択します。

  3. 「属性の編集」ダイアログで、ステップ1で作成したマネージドBeanとメソッドを選択します。

    例5-2に、選択イベント・リスナー・メソッドをtableコンポーネントに登録するサンプル・コードを示します。

    例5-2 イベント・リスナー・メソッドの登録

    <af:table id="folderTable" var="file"
    . . . 
              rowSelection="single"
              selectionListener="#{explorer.tableContentView.tableSelectFileItem}"
    . . .
    </af:table>
    

5.3 ADF Facesクライアント・イベントに対するJavaScriptの使用

ほとんどのコンポーネントは、クライアント側イベントに対しても動作できます。クライアント上でイベントを処理すると、サーバーとのラウンドトリップが節約されます。クライアント側イベントを使用する場合は、マネージドBeanにイベント・ハンドラ・コードを含めるかわりに、コール元のページまたはJavaScriptライブラリに含めることのできるJavaScriptを使用します。

デフォルトでは、クライアント・イベントはクライアントでのみ処理されます。ただし、ボタンがクリックされたことを示すAdfActionEventイベントのようにサーバーに配信されるイベント・タイプもあります。コンポーネントの状態に応じてサーバーに配信されるイベントもあります。たとえば、AdfValueChangeEventイベントは、autoSubmit属性がtrueに設定されている場合サーバーに配信されます。追加処理が不要な場合は、イベントのサーバーへの配信を取り消すことができます。ただし、取り消すことができないクライアント・イベントもあります。たとえば、popupOpenedイベント・タイプは、ポップアップ・ウィンドウが開くと配信されるため、このイベントのサーバーへの配信は取り消すことができません。


パフォーマンスのヒント:

イベントにサーバー処理が不要な場合は、イベントがサーバーに伝播されないよう、処理の最後にイベントを取り消すことを検討してください。詳細は、5.3.5項「イベントがサーバーに伝播されないようにする方法」を参照してください。


表5-3に、ADF Facesクライアント・コンポーネントで生成されるイベント、イベントがサーバーに送信されるかどうか、イベントが取消し可能かどうか、およびイベントをトリガーするコンポーネントをリストします。

表5-3 ADF Facesクライアント・イベント

イベント・タイプ イベント・クラス サーバーへの伝播 取消し可能 トリガー元コンポーネント

action

AdfActionEvent

はい

はい

すべてのコマンド・コンポーネント

dialog

AdfDialogEvent

はい

はい

dialog

ユーザーがダイアログでOKボタンまたは取消しボタンを選択したとき

disclosure

AdfDisclosureEvent

はい

はい

showDetailshowDetailHeadershowDetailItem

公開状態がユーザーによって切り替えられたとき


AdfFocusEvent

はい

はい

treetreeTable


AdfLaunchPopupEvent

はい

はい

inputListOfValuesinputComboboxListOfValues

inlineFrameLoad

AdfDomComponentEvent

はい

はい

inlineFrame

内部iframeがそのloadイベントを起動したとき

load

AdfComponentEvent

はい

はい

document

PPRナビゲーションが使用されている場合でも、ドキュメントのコンテンツがクライアントに表示された後。onLoad DOMイベントに常に対応するとはかぎりません。


AdfPollEvent

はい

はい

poll

popupOpened

AdfPopupOpenedEvent

いいえ

いいえ

popup

ポップアップ・ウィンドウまたはダイアログが開いた後

popupOpening

AdfPopupOpeningEvent

いいえ

はい

popup

ポップアップ・ウィンドウまたはダイアログが開く前

popupClosed

AdfPopupClosedEvent

いいえ

いいえ

popup

ポップアップ・ウィンドウまたはダイアログが閉じた後

propertyChange

AdfPropertyChangeEvent

いいえ

いいえ

すべてのコンポーネント

query

AdfQueryEvent

はい

はい

queryquickQuery

問合せアクション時(ユーザーが検索アイコンまたは検索ボタンをクリックしたとき)

queryOperation

AdfQueryOperationEvent

はい

はい

queryquickQuery


AdfReturnEvent

はい

はい

すべてのコマンド・コンポーネント


AdfReturnPopupDataEvent

はい

はい

inputListOfValuesinputComboboxListOfValues


AdfReturnPopupEvent

はい

はい

inputListOfValuesinputComboboxListOfValues

rowDisclosure

AdfRowDisclosureEvent

はい

はい

treetreeTable

行の公開状態が切り替えられたとき

selection

AdfSelectionEvent

はい

はい

treetreeTabletable

選択状態が変わったとき

sort

AdfSortEvent

はい

はい

treeTabletable

ユーザーが表のデータをソートしたとき

touchStart
touchMove
touchEnd
touchCancel

AdfComponentTouchEvent

いいえ

はい

すべて

valueChange

AdfValueChangeEvent

はい

はい

すべての入力および選択コンポーネント(EditableValueHolderを実装するコンポーネント)

入力または選択コンポーネントの値が変更されたとき


ADF Facesでは、表5-4に示すように、クライアント・キーボードおよびマウス・イベントもサポートします。

表5-4 サポートされるキーボードとマウスのイベント・タイプ

イベント・タイプ イベントが発生するタイミング

click

ユーザーがコンポーネントをクリックしたとき

dblclick

ユーザーがコンポーネントをダブルクリックしたとき

mousedown

ユーザーがコンポーネント上でマウス・ボタンを押したとき

mouseup

ユーザーがコンポーネント上でマウス・ボタンを離したとき

mousemove

ユーザーがコンポーネント上でマウスを移動したとき

mouseover

コンポーネント内にマウスが移動したとき

mouseout

コンポーネントからマウスが移動したとき

keydown

コンポーネントのフォーカス中にユーザーがキーを押したとき

keyup

コンポーネントのフォーカス中にユーザーがキーを離したとき

keypress

コンポーネントのフォーカス中にキーを押す動作が正常に完了したとき

focus

コンポーネントがキーボード・フォーカスを得たとき

blur

コンポーネントがキーボード・フォーカスを失ったとき



ベスト・プラクティス:

キーボードおよびマウス・イベントは、元のDOMイベントへのアクセスを提供し、キー・コードやマウス座標などの取得用の便利な一連の関数も提供するAdfBaseEventクラスのAdfUIInputEventサブクラスを使用して、ネイティブDOMイベントをラップします。AdfBaseEventクラスは、これらのイベントの実装方法に関するブラウザの違いも考慮します。したがって、getNativeEvent()メソッドを直接呼び出すことは避け、かわりにAdfUIInputEvent APIを使用する必要があります。


clientListenerタグによって、クライアント側イベント・ハンドラ・スクリプトをコンポーネントに登録する宣言的方法が提供されます。サポートされているクライアント・イベント・タイプが発生すると、スクリプトが起動されます。例5-3に、アクション・イベントに関連付けられているJavaScript関数の例を示します。

例5-3 clientListenerタグ

<af:commandButton id="button0"
                  text="Do something in response to an action">
  <af:clientListener method="someJSMethod" type="action"/>
</af:commandButton>

ヒント:

コンポーネントのJavaScriptプロパティのかわりにclientListenerタグを使用します。


5.3.1 クライアント側イベントの使用方法

クライアント側イベントを使用するには、まず、イベントを処理するJavaScriptを作成する必要があります。次に、clientListenerタグを使用します。

クライアント側イベントを使用する手順:

  1. JavaScriptイベント・ハンドラ関数を作成します。JavaScriptの作成の詳細は、3.3項「JavaScriptのページへの追加」を参照してください。その機能内に、次の機能を追加できます。

    • ページでクライアント・コンポーネントを検索する

      イベント・ハンドラを別のコンポーネントで動作させるには、ページでそのコンポーネントを検索する必要があります。たとえば、File Explorerアプリケーションで、ユーザーが「ヘルプ」メニューのフィードバックの送信メニュー項目を選択した場合、関連付けられたJavaScript関数はヘルプ・ポップアップ・ダイアログを開くためにそのダイアログを検索する必要があります。クライアント・コンポーネントの検索の詳細は、3.5項「ページでのクライアント・コンポーネントの検索」を参照してください。

    • イベントの元のソースを返す

      ページに同じコンポーネントが複数ある場合、JavaScript関数はイベントを発行したコンポーネントを判断することが必要な場合があります。たとえば、複数のコンポーネントが同じポップアップ・ダイアログを開くことができ、そのダイアログをコール元コンポーネントに位置合せする必要があるとします。ポップアップ・ダイアログを位置合せする場所を決定するには、AdfLaunchPopupEventのソースがわかっている必要があります。詳細は、5.3.2項「イベントの発生元を返す方法」を参照してください。

    • 子属性を追加する

      クライアント・イベント・ハンドラは、コンポーネントの特定の属性を操作することが必要な場合があります。たとえば、File Explorerアプリケーションで、ユーザーが「ヘルプ」メニューで「バージョン情報」メニュー項目を選択した場合、ユーザーがフィードバックを提供できるダイアログが起動します。このダイアログを開いて表示するために使用される関数は、他のダイアログによっても使用され、異なる方法で表示されることが必要な場合があります。したがって、関数では、ダイアログの位置合せの方法に関する情報とともに、どのダイアログを表示するかを知っておく必要があります。この情報は、クライアント属性で搬送されます。クライアント属性は、クライアントへのカスタム・サーバー側属性のマーシャリングにも使用できます。詳細は、5.3.3項「イベントのクライアント側属性の使用方法」を参照してください。

    • サーバーへの伝播を取り消す

      一部のコンポーネントは、表5-3に示したようにサーバーにクライアント側イベントを伝播します。この追加処理が不要な場合は、その伝播を取り消すことができます。詳細は、5.3.5項「イベントがサーバーに伝播されないようにする方法」を参照してください。

  2. JavaScript関数の作成後、イベント・メソッドをコールするイベント・リスナーを追加する必要があります。


    注意:

    または、ADF Facesコンポーネントのすべてのクライアント・イベントはクライアント動作としても公開されるため、JSF 2.0クライアント動作タグ(f:ajaxなど)を使用してクライアント・イベントに応答できます。詳細は、「Java EE 6 tutorial」(http://download.oracle.com/javaee/index.html)を参照してください。


    1. JavaScriptを呼び出すコンポーネントを選択し、プロパティ・インスペクタでClientComponenttrueに設定します。

    2. コンポーネント・パレットの「操作」パネルから、「クライアント・リスナー」を、選択したコンポーネントの子としてドラッグ・アンド・ドロップします。

    3. 「クライアント・リスナーの挿入」ダイアログで、メソッドを入力し、JavaScript関数のタイプを選択します。

      clientListenerタグのmethod属性で、対応するイベントが発生したときにコールするJavaScript関数を指定します。JavaScript関数は1つのパラメータ(イベント・オブジェクト)をとる必要があります。

      clientListenerタグのtype属性で、actionvalueChangeなどのタグでリスニングするクライアント・イベント・タイプを指定します。表5-3に、ADF Facesクライアント・イベントをリストしています。

      clientListenerタグのtype属性では、キーボードおよびマウスのイベントに関連するクライアント・イベント・タイプもサポートされます。表5-4に、キーボードとマウスのイベント・タイプを示しています。

      例5-4に、Explorer.js JavaScriptファイルのshowHelpFileExplorerPopup関数の起動に使用されるコードを示します。

      例5-4 JSFページのclientListenerタグ

      <af:commandMenuItem id="feedbackMenuItem"
                          text="#{explorerBundle['menuitem.feedback']}"
                          clientComponent="true">
        <af:clientListener method="Explorer.showHelpFileExplorerPopup"
                           type="action"/>
      </af:commandMenuItem>
      
    4. コンポーネント・パレットの「操作」パネルからクライアント属性をドラッグして選択したコンポーネントの子としてドロップし、必要な属性を追加します。プロパティ・インスペクタで属性の名前と値を入力します。例5-5に、showAboutFileExplorerPopup関数の属性値の設定に使用されるコードを示します。

      例5-5 属性の追加

       <af:commandMenuItem id="aboutMenuItem"
                           text="#{explorerBundle['menuitem.about']}"
                           clientComponent="true">
          <af:clientListener method="Explorer.showAboutFileExplorerPopup"
                              type="action"/>
          <af:clientAttribute name="popupCompId" value=":fe:aboutPopup"/>
          <af:clientAttribute name="align" value="end_after"/>
          <af:clientAttribute name="alignId" value="aboutMenuItem"/>
        </af:commandMenuItem>
      

      注意:

      attributeタグ(clientAttributeタグではなく)を使用して、アプリケーション固有の属性やボーナス属性をサーバー・コンポーネントに追加した場合、これらの属性は、対応するクライアント・コンポーネントに含まれません。JSFページでclientAttributeタグを使用すると、サーバーとクライアントの両方で値が使用可能になります。クライアント値のサーバーへのポストバックの詳細は、5.4項「クライアントからサーバーへのカスタム・イベントの送信」を参照してください。ボーナス属性の詳細は、3.8項「クライアント側コンポーネントに対するボーナス属性の使用」を参照してください。


5.3.2 イベントの発生元を返す方法

JavaScriptメソッドgetSource()は、クライアント・イベントの元のソースを返します。たとえば、File Explorerアプリケーションには、例5-6に示すshowAboutFileExplorerPopup関数が含まれます。この関数は、値を渡すクライアント属性を使用して、特定のポップアップ・ダイアログまたはウィンドウに配置を設定するために複数のイベントによって使用できます。関数を使用する各イベントは属性に対して異なる値を持つため、関数は、対応する属性値にアクセスできるようにイベントを起動したソースについて知っておく必要があります(クライアント属性の使用の詳細は、5.3.3項「イベントのクライアント側属性の使用方法」を参照してください)。

例5-6 クライアント・イベントのソース・コンポーネントの検出

Explorer.showAboutFileExplorerPopup = function(event)
{
  var source = event.getSource();
  var alignType = source.getProperty("align");
  var alignCompId = source.getProperty("alignId"); 
  var popupCompId = source.getProperty("popupCompId");
  
  source.show({align:alignType, alignId:alignCompId});
  
  event.cancel();
}

getSource()メソッドがコールされ、現在のフォーカス・イベントを発生したクライアント・コンポーネント(このケースではポップアップ・コンポーネント)が決まります。

5.3.3 イベントのクライアント側属性の使用方法

スクリプト・ロジックによってコンポーネントになんらかの変更を加えることが必要になる場合があります。これを行うには、イベントによって渡された属性値が必要な場合があります。たとえば、File Explorerアプリケーションには、例5-7に示すshowAboutFileExplorerPopup関数が含まれます。この関数は、値を渡すクライアント属性を使用して、特定のポップアップ・コンポーネントに配置を設定するために使用できます。属性値は、ソース・コンポーネントでgetPropertyメソッドを呼び出すことでアクセスされます。

例5-7 JavaScriptからアクセスされる属性値

Explorer.showAboutFileExplorerPopup = function(event)
{
  var source = event.getSource();
  var alignType = source.getProperty("align");
  var alignCompId = source.getProperty("alignId"); 
  var popupCompId = source.getProperty("popupCompId");
  
  var aboutPopup = event.getSource().findComponent(popupCompId);  
  aboutPopup.show({align:alignType, alignId:alignCompId});
  
  event.cancel();
}

例5-8に示すように、値はソース・コンポーネントで設定されます。

例5-8 コンポーネントでの属性の設定

<af:commandMenuItem id="aboutMenuItem"
                    text="#{explorerBundle['menuitem.about']}"
                    clientComponent="true">
  <af:clientListener method="Explorer.showAboutFileExplorerPopup"
                     type="action"/>
  <af:clientAttribute name="popupCompId" value=":aboutPopup"/>
  <af:clientAttribute name="align" value="end_after"/>
  <af:clientAttribute name="alignId" value="aboutMenuItem"/>
</af:commandMenuItem>

このように属性を使用すると、同じイベントをトリガーする異なるコンポーネントでスクリプトを再利用できます。

5.3.4 イベント実行時のUI入力のブロック方法

実行時間が長いイベントの処理中に、ユーザーがUIを操作できないようにする場合があります。たとえば、アプリケーションがボタンを使用して命令を送信し、処理の一部にユーザーのアカウントに対する請求を作成する処理が含まれているとします。ユーザーが不注意でボタンを2回押した場合、そのアカウントは2回請求されることになります。サーバーの処理が完了するまでユーザーの操作をブロックすることで、誤ったクライアント・アクティビティが発生しないようにできます。

ADF Faces JavaScript APIには、AdfBaseEvent.preventUserInput関数が含まれます。イベントの処理中にすべてのユーザー入力を阻止するためにpreventUserInput関数をコールすると、ブラウザ・ウィンドウ全体にグラス・ペインが表示され、イベントがサーバーとのラウンドトリップを完了するまでそれ以上入力できなくなります。

preventUserInput関数は、カスタム・イベント、カスタム・クライアント・スクリプトで発生したイベント、またはカスタム・クライアント・コンポーネントのピアで発生したイベントでのみ使用できます。また、イベントをサーバーに伝播する必要があります。例5-9に、JavaScriptでpreventUserInputを使用する方法を示します。

例5-9 UI入力のブロック

function queueEvent(event)
{
   event.cancel(); // cancel action event
   var source = event.getSource();
         
   var params = {};
   var type = "customListener";
   var immediate = true;
   var isPartial = true;
   var customEvent =  new AdfCustomEvent(source, type, params, immediate);
   customEvent.preventUserInput();
   customEvent.queue(isPartial);
}   

5.3.5 イベントがサーバーに伝播されないようにする方法

一部のクライアント・イベントは、クライアントでの処理が完了すると、デフォルトでサーバーに伝播されます。この伝播が行われないようにすることが必要な状況もあります。たとえば、ボタンがクリックされるとJavaScriptコードを実行するcommandButtonコンポーネントを使用している場合、サーバーにactionListenerイベント・リスナーがなければ、イベントを伝播することはリソースを無駄に消費することになります。サーバーへ伝播されないようにするには、リスナーでイベントのcancel()関数をコールします。cancel()関数がコールされると、isCanceled()関数でtrueが返されます。

例5-10に、伝播を取り消すshowAboutFileExplorerPopup関数を示します。

例5-10 クライアント・イベントのサーバーへの伝播の取消し

Explorer.showAboutFileExplorerPopup = function(event)
{
  var source = event.getSource();
  var alignType = source.getProperty("align");
  var alignCompId = source.getProperty("alignId"); 
  var popupCompId = source.getProperty("popupCompId");
  
  var aboutPopup = event.getSource().findComponent(popupCompId);  
  aboutPopup.show({align:alignType, alignId:alignCompId});
  
  event.cancel();
}

イベントを取り消すことで、行われないデフォルト処理もあります。たとえば、ポップアップ・メニューのAdfUIInputEventイベントを取り消すと、このイベントを受けて表示されるポップアップ・メニューがブラウザで表示されません。

cancel()関数コールは、イベントを取り消せない場合に無視されます。イベントは、isCancelable()関数からfalseを返すことでこれを示します(取消しできないイベントは、表5-3の「取消し可能」列に「いいえ」が表示されています)。これは一般に、イベントが、結果がすでに完了し、ブロックできないという通知であることを意味します。また、取り消された後でイベントの取消しを元に戻す方法はありません。

5.3.6 実行時の処理: クライアント側イベントの機能の仕方

一般に、イベント処理はブラウザのネイティブ・イベント・ループから取得されます。ページは、ドキュメントをバブル・アップするすべてのDOMイベントを受け取り、DOMのその部分に関連付けられているピアに渡します。ピアでは、DOMイベントをラップするリッチ・クライアントJavaScriptイベント・オブジェクトが作成され、ページに返され、イベントがキューイングされます(ピアとADF Facesアーキテクチャの詳細は、第3章「ADF Facesアーキテクチャの使用」を参照してください)。

各DOMイベントのページでの処理(この結果、通常コンポーネント・イベントがキューイングされる)後、ページのイベント・キューは、通常ブラウザのイベント・ループの最後で空になります。ただし、タイマー起動時にポーリング・イベントを発生するポーリング・コンポーネントなど、ユーザー入力とは無関係にイベントがキューイングされることがあるため、イベントをキューイングすると、ユーザー入力がなくても、イベント・キューを空にするタイマーも起動されます。

イベント・キューは先入れ先出しキューです。イベント・キューを空にするには、ページで各イベント・オブジェクトを捕捉し、イベント・ソースのbroadcast()関数に配信します。このループは、キューが空になるまで続きます。イベントのブロードキャストによって、導出された新規イベントのキューイングが間接的に引き起こされることは非常に理にかなっています(一般的です)。導出されたイベントは、同じループでブロードキャストされます。

イベントがコンポーネントにブロードキャストされると、コンポーネントで次の処理が行われます。

  1. イベントをピアのDispatchComponentEventメソッドに配信します。

  2. そのイベント・タイプ用に登録されているリスナーにイベントを配信します。

  3. イベントをバブルする必要があるかどうかを確認し、必要な場合はバブルを開始します。ほとんどのイベントがバブルされます。例外には、プロパティ変更イベント(キューイングされず、このプロセスにまったく関与しない)やマウスの移動イベント(効率を高めるため)があります。

    イベントがバブルされるとき、イベントはAdfUIComponentHandleBubbledEvent関数に配信され、ここからピアのDispatchComponentEvent関数に渡されます。クライアント・イベント・リスナーではなく、ピアがイベントを受け取ることに注意してください。

    イベントのバブルは、イベントのstopBubbling()関数をコールすることでブロックされます。その後で、isBubblingStopped()関数はtrueを返し、バブルは続行されません。取消しと同様に、このコールは元に戻せません。


    注意:

    イベントを取り消してもバブルは止まりません。イベントの取消しとバブルの停止の両方を行う場合は、両方の関数をコールする必要があります。


  4. 前述の処理でイベントが取り消されない場合は、AdfUIComponent.HandleEventメソッドをコールします。このメソッドでは、イベントでのリクエストに応じてイベントがサーバー・イベント・キューに追加されます。

5.3.7 ネーミング・コンテナの使用に関する必知事項

ADF Facesのいくつかのコンポーネントは、pageTemplatesubformtableおよびtreeなどのNamingContainerコンポーネントです。NamingContainerコンポーネントを含むページでクライアント側APIとイベントを使用する場合、ソース・コンポーネントでfindComponent()メソッドを使用する必要があります。

たとえば、例5-11に示すように、File Explorerアプリケーション内のいずれかのページのすべてのコンポーネントは最終的にpageTemplateコンポーネント内に存在するため、JavaScript関数はgetSource()およびfindComponent()メソッドを使用する必要があります。getSource()メソッドは、コンポーネントの検索に使用できるAdfUIComponentクラスにアクセスします。

例5-11 findComponent()メソッドを使用するJavaScript

function showPopup(event)
{
  event.cancel();
  var source = event.getSource();
  var popup = source.findComponent("popup");
  popup.show({align:"after_end", alignId:"button"});
}

findComponent()メソッドを使用すると、メソッドを起動したコンポーネントでローカルに検索が開始します。ネーミング・コンテナの使用の詳細は、3.5項「ページでのクライアント・コンポーネントの検索」を参照してください。

5.4 クライアントからサーバーへのカスタム・イベントの送信

clientAttributeタグでは、サーバーからクライアントへのボーナス属性の送信はサポートされますが、これらの属性のサーバーへの同期化は行われません。カスタム・データをサーバーに戻すには、AdfCustomEventクラスとserverListenerタグを使用して送信されるカスタム・イベントを使用します。

AdfCustomEvent.queue() JavaScriptメソッドによって、clientComponent属性がtrueに設定されているコンポーネントからカスタム・イベントを起動できます。カスタム・イベント・オブジェクトには、クライアント・イベント・ソースと、イベントに含まれるパラメータのマップに関する情報が含まれます。カスタム・イベントは即時配信(リクエスト値の適用フェーズ中)にも非即時配信(アプリケーションの起動フェーズ中)にも設定できます。

たとえば、File Explorerアプリケーションでは、ユーザーは左側の検索フィールドにファイル名を入力した後、[Enter]キーを押して検索を起動します。例5-12 に示すように、これは、inputTextフィールドに、[Enter]キーが押されると、JavaScript関数を起動するclientListenerが含まれているためです。

例5-12 clientListenerによってJavaScript関数が起動され、ServerLIstenerが起動される

//Code on the JSF page...
<af:inputText id="searchCriteriaName"
              value="#{explorer.navigatorManager.searchNavigator.
                                               searchCriteriaName}"
              shortDesc="#{explorerBundle['navigator.filenamesearch']}">
  <af:serverListener type="enterPressedOnSearch"
                     method="#{explorer.navigatorManager.
                                        searchNavigator.searchOnEnter}"/>
  <af:clientListener type="keyPress"
                     method="Explorer.searchNameHandleKeyPress"/>
</af:inputText>

//Code in JavaScript file...
Explorer.searchNameHandleKeyPress = function (event)
{
  if (event.getKeyCode()==AdfKeyStroke.ENTER_KEY)
  {
    var source = event.getSource();
    AdfCustomEvent.queue(source,
                         "enterPressedOnSearch", 
                         {}, 
                         false);
  } 
}

JavaScriptには、イベント・ソース、カスタム・イベント・タイプとして文字列enterPressedOnSearch、nullパラメータ・マップ、即時パラメータにFalseをとるAdfCustomEvent.queueメソッドが含まれています。

ページのinputTextにも、次のserverListenerタグが含まれています。

<af:serverListener type="enterPressedOnSearch"
                   method="#{explorer.navigatorManager.
                                      searchNavigator.searchOnEnter}"/>

タイプ値enterPressedOnSearchがJavaScriptのAdfCustomEvent.queueメソッドのパラメータの値と同じであるため、メソッド式#{explorer.navigatorManager.searchNavigator.searchOnEnter}に解決されるメソッドが起動されます。

5.4.1 クライアントからサーバーへのカスタム・イベントの送信方法

クライアントからサーバーへカスタム・イベントを送信するには、カスタム・イベント・タイプを使用してクライアント・イベントを起動し、バッキングBeanにサーバー・リスナー・メソッドを記述し、このメソッドでカスタム・イベントを処理する必要があります。次に、サーバー・リスナーをコンポーネントに登録します。

カスタム・イベントを送信する手順:

  1. イベント・ソース、カスタム・イベント・タイプおよびサーバーに送信するパラメータを指定してAdfCustomEvent.queue()メソッドを使用し、カスタム・イベントを処理するJavaScriptを作成します。

    たとえば、[Enter]キーが押されると検索機能を起動するJavaScriptでは、例5-13に示すようなイベント・ソース、カスタム・イベント・タイプとして文字列enterPressedOnSearch、nullパラメータ・マップ、即時パラメータとしてFalseをとるAdfCustomEvent.queueメソッドを使用します。

    例5-13 カスタム・イベント用のサンプルJavaScript

    Explorer.searchNameHandleKeyPress = function (event)
    {
      if (event.getKeyCode()==AdfKeyStroke.ENTER_KEY)
      {
        var source = event.getSource();
        AdfCustomEvent.queue(source,
                             "enterPressedOnSearch", 
                             {}, 
                             false);
      } 
    }
    
  2. マネージドBeanにサーバー・リスナー・メソッドを作成します。このメソッドはpublicで、oracle.adf.view.rich.render.ClientEventオブジェクトを引数とし、void型を返します。例5-14に、別のメソッドをコールして検索を実行し、ナビゲータをリフレッシュするだけのSearchNavigatorViewマネージドBeanに使用されるコードを示します。

    例5-14 カスタム・クライアント・イベント用サーバー・リスナー・メソッド

      public void searchOnEnter(ClientEvent clientEvent)
      {
        doRealSearchForFileItem();
        
        // refresh search navigator
        this.refresh();
      }
    

    注意:

    JavaからJavaScriptへの変換では、Numberschars、Java Objectsarraysおよび文字列でないCharSequencesの型情報が失われます。このため、サーバーに送信されるオブジェクトが初めはサーバーにある場合、変換が正しく行われるようにするロジックを追加します。5.4.3項「データのマーシャリングとアンマーシャリングに関する必知事項」を参照してください。


  3. コンポーネント・パレットの「操作」パネルからクライアント・リスナーをドラッグしてイベントが発生するコンポーネントの子としてドロップし、clientListenerを登録します。


    注意:

    カスタム・クライアント・イベントを発生させるコンポーネントでは、クライアント側で生成されたコンポーネントが使用可能になるよう、clientComponent属性をtrueに設定します。


  4. 「クライアント・リスナーの挿入」ダイアログで、メソッドおよびJavaScript関数のタイプを入力します。スクリプトがページに含まれていない場合はライブラリ名を必ず含めます。タイプは、カスタム・イベントの識別に使用される任意の文字列です。たとえば、File ExplorerではenterPressedOnSearchが使用されていました。

  5. コンポーネント・パレットの「操作」パネルからサーバー・リスナーをドラッグしてclientListenerタグの兄弟としてドロップし、サーバー・リスナーを登録します。

  6. 「サーバー・リスナーの挿入」ダイアログで、enterPressedOnSearchなどのこのサーバー・リスナーに対する値としてクライアント・リスナーのタイプ値に使用される文字列を入力します。

    プロパティ・インスペクタで、2で作成したメソッドに解決される式をmethod属性に入力します。

5.4.2 実行時の処理: クライアント・リスナーとサーバー・リスナーの協働の仕方

実行時、[Enter]キーを押すなど、ユーザーによってイベントが発生すると、クライアント・リスナー・スクリプトが実行されます。このスクリプトでAdfCustomEvent.queue()メソッドをコールし、指定したイベント・タイプのカスタム・イベントが入力コンポーネントのキューに置かれます。入力コンポーネントに登録されているサーバー・リスナーがカスタム・イベントを受け取り、関連付けられているBeanメソッドが実行されます。

5.4.3 データのマーシャリングとアンマーシャリングに関する必知事項

マーシャリングアンマーシャリングは、プログラミング言語のデータ・オブジェクトをバイト・ストリームに変換し、同じまたは別のプログラミング言語のネイティブ・データ・オブジェクトに戻すプロセスです。ADF Facesでは、マーシャリングとアンマーシャリングは、データを適切な形式に変換して、クライアント上のJavaScriptとサーバー側のJava間で最適に交換できるようにすることを意味します。クライアントがブラウザベースの場合、マーシャリングの2つの共通戦略はJavaScript Object Notation (JSON)とXMLです。ADF Facesは、これらの戦略の両方を、サーバーからクライアントに主にJSONとして送信される情報およびクライアントからサーバーにXMLとして送信される情報と組み合せて使用します(JSONの詳細は、http://www.json.orgを参照してください)。

JavaScriptからJavaへ情報を送信する場合、JavaScriptデータ・オブジェクトはXMLに変換され(マーシャリング)、サーバー側で解析してJavaオブジェクトに戻されます(アンマーシャリング)。たとえば、cmdというIDのcommandButtonコンポーネントを含むJSFページを考えてみます。ユーザーがcommandButtonコンポーネントをクリックしたとき、このcommandButtonによってactionEventが発生したことをクライアントからサーバーに通信する必要があります。requestParameterマップで、情報がevent + . + id (idはコンポーネントのID)という形式を使用したキーにマップされます。つまり、commandComponentrequestParameterマップ・キーは、キーevent.cmdの値として格納されているXML文字列です。

この例でマーシャリング後のXMLフラグメントは次のようになります。

<m xmlns="http:/oracle.com/richClient/comm"><k v="type"><s>action</s></k></m>

例のmは、これがマップにアンマーシャルされることを表します。kはキーであることと、値がString型であることを表します。サーバー側でXMLフラグメントが、type (java.lang.String)をキーとし、action (java.lang.String)を値とする1つのエントリのjava.util.Mapに解析されます。

アンマーシャリングされた情報は、クライアントIDごとにまとめられ、リクエスト・マップに格納されてコンポーネントのデコード時に使用されます。この例では、commandButtonがデコードされるとき、クライアントID (event.cmd)を使用してクライアント・イベントがあるかどうかが確認され、検出された場合はアクションがキューイングされます(デコード動作は、commandButtonコンポーネントのレンダラ階層で実装されます)。

表5-5に、JavaScript型と対応するJava型のマッピングを示します。

表5-5 JavaScriptとJavaの型マップ

JavaScript型 Java型

Boolean

java.lang.Boolean

Number

java.lang.Double

String

java.lang.String

Date

java.util.Date

Array

java.util.ArrayList

Object

java.util.Map


JavaからJavaScriptへのマーシャリングは、ほとんどの場合JSONを使用して行われます。JSONがJavaScriptでのオブジェクト・リテラル表記法であるため、この種のマーシャリングは明らかです。クライアント・コンポーネントのプロパティは通常JSONでエンコードされます。次に例を示します。

new AdfRichCommandButton('demoTemplate:richComand'
    {'partialSubmit':true,'useWindow':false})

2番目の引数({'partialSubmit':true,'useWindow':false})はJSONオブジェクトです。JSONがオブジェクトとして直接JavaScript環境に解析されるため、ブラウザ・エンドでの追加のアンマーシャリング処理が不要です。

表のエンコードでも、JSONを使用してプッシュ・メッセージをクライアントに渡します。エンコードされた1つのプッシュ・メッセージを含むエンベロープの例を次にしまします。

[{'rKey':'0','type':'update','data':[{'val':'Active Data Every Second: on row 0:78','prop':'value','cInd':0},{'val':'Active Data Every Second: on row 0:78','prop':'value','cInd':1}]}]

エンベロープは、メッセージを記述する1つのオブジェクトのみ持つJavaScript Arrayです。このメッセージには変更のタイプに関する情報やデータの実際の値などが含まれ、表自体を更新するためにクライアント側の対応する表で使用されます。

表5-6に、Java型と対応するJavaScript型のマッピングを示します。

表5-6 JavaとJavaScriptの型マップ

Java型 JavaScript型

java.lang.Boolean

Boolean

java.lang.Double

Number

java.lang.Integer

Number

java.lang.Float

Number

java.lang.Long

Number

java.lang.Short

Number

java.lang.Character

String

java.lang.CharSequence

String

java.util.Collection

Array

java.util.Date

Date

java.util.Map

Object

Array

Array

java.awt.Color

TrColor


変換処理中に情報が失われる可能性あることに注意してください。たとえば、次の例に示すように、カスタム・イベントを使用して数値1と文字列testを送信するとします。

AdfCustomEvent.queue(event.getSource(), "something", {first:1, second:"test"});

JavaScriptからJavaへの変換では数値はDoublesに変換されるため、サーバー側リスナーでfirstパラメータの型がjava.lang.Doubleになります。ただし、初めはサーバー側でintだったパラメータが、JavaからJavaScriptへの変換で数値になった可能性もあります。サーバーへ戻る際にDoubleに変換されます。

5.5 イベント・レスポンス内でのスクリプトの実行

ExtendedRenderKitServiceクラスを使用すると、アクション・メソッド・バインディングの起動後などのイベント・レスポンスにJavaScriptを追加できます。これは、ユーザーにデータベース接続が確立できないことを通知するアラートの送信などの簡単なメッセージの場合もあれば、プログラムからポップアップ・ダイアログを終了させるためのポップアップ・ウィンドウでのhide()などの関数のコールの場合もあります。

たとえば、File ExplorerアプリケーションでユーザーがUpOneFolderナビゲーション・ボタンをクリックしてフォルダ構造を上に移動すると、フォルダ・ペインが再描画されて、選択した親フォルダが表示されます。UpOneFolderボタン・イベントのクリックを受けてHandleUpOneFolder()メソッドがコールされます。ExtendedRenderKitServiceクラスを使用してJavaScriptがレスポンスに追加されます。

例5-15に、actionListener属性が、ボタンがクリックされたときにアクション・イベントを処理するHandleUpOneFolder()ハンドラ・メソッドにバインドされているページのUpOneFolderコードを示します。

例5-15 JavaScriptをレスポンスに追加するメソッドの起動

<af:commandToolbarButton id="upOneFolder"
. . .
        actionListener="#{explorer.headerManager.handleUpOneFolder}"/>

例5-16に、ExtendedRenderKitServiceクラスを使用するhandleUpOneFolderメソッドを示します。

例5-16 JavaScriptのレスポンスへの追加

public void handleUpOneFolder(ActionEvent actionEvent)
 {
   UIXTree folderTree = 
     feBean.getNavigatorManager().getFoldersNavigator().getFoldersTreeComponent();
   Object selectedPath = 
    feBean.getNavigatorManager().getFoldersNavigator().getFirstSelectedTreePath();
    
   if (selectedPath != null)
    {
      TreeModel model = 
        _feBean.getNavigatorManager().getFoldersNavigator().getFoldersTreeModel();
      Object oldRowKey = model.getRowKey();
      try
      {
        model.setRowKey(selectedPath);
        Object parentRowKey = model.getContainerRowKey();
        if (parentRowKey != null)
        {
          folderTree.getSelectedRowKeys().clear();
          folderTree.getSelectedRowKeys().add(parentRowKey);
          // This is an example of how to force a single attribute
          // to rerender. The method assumes that the client has an optimized
          // setter for "selectedRowKeys" of tree.
          FacesContext context =  FacesContext.getCurrentInstance();
          ExtendedRenderKitService erks =
            Service.getRenderKitService(context,
                    ExtendedRenderKitService.class);
          String clientRowKey = folderTree.getClientRowKeyManager().
            getClientRowKey(context, folderTree, parentRowKey);
          String clientId = folderTree.getClientId(context);
          StringBuilder builder = new StringBuilder();
          builder.append("AdfPage.PAGE.findComponent('");
          builder.append(clientId);
          builder.append("').setSelectedRowKeys({'");
          builder.append(clientRowKey);
          builder.append("':true});");
          erks.addScript(context, builder.toString());
        }
      }
      finally
      {
        model.setRowKey(oldRowKey);
      }
      // Only really needed if using server-side rerendering
      // of the tree selection, but performing it here saves
      // a roundtrip (just one, to fetch the table data, instead
      // of one to process the selection event only after which
      // the table data gets fetched!)
      _feBean.getNavigatorManager().getFoldersNavigator().openSelectedFolder();
    } 
    
  }

5.6 クライアントの動作タグの使用

クライアント側での動作を実装する場合、通常はJavaScriptを記述し、それをクライアント・リスナーとしてコンポーネントに登録する必要がありますが、ADF Facesのクライアント動作タグを使用すると、一般的なクライアント操作を宣言的に実行できます。JavaScriptコードを記述するかわりにこれらのタグを使用して同じ処理を実装すると、ブラウザにダウンロードする必要のあるJavaScriptコードの量が少なくなります。

ADF Facesは、クライアント・リスナーのかわりに使用できる次のクライアント動作タグを提供します。

クライアント動作タグで、サーバー側イベント配信が自動的に取り消されます。したがって、親コンポーネントのactionListenerまたはaction 属性が無視されます。これは無効にすることができません。サーバー側の機能もトリガーする場合は、クライアント側イベントを使用する(5.3項「ADF Facesクライアント・イベントに対するJavaScriptの使用」を参照)か、AdfCustomEventおよびaf:serverListenerを使用してサーバー側イベントを配信するクライアント・リスナーを追加します(5.4項「クライアントからサーバーへのカスタム・イベントの送信」を参照)。

5.6.1 scrollComponentIntoViewBehaviorタグの使用方法

ユーザーがページの特定のコンポーネントに移動できるようにする場合は、scrollComponentIntoViewBehaviorタグを使用します。このアクションは、HTMLのアンカーと似ています。たとえば、commandLinkコンポーネントを使用して、ユーザーがページの特定の部分に移動できるようにできます。richTextEditorおよびinlineFrameコンポーネントの場合は、サブコンポーネントに移動できます。たとえば、図5-1は、そのテキストに多数のセクションがあるrichTextEditorコンポーネントを示しています。エディタの下にあるコマンド・リンクを使用すると、テキストの特定部分に移動できます。

図5-1 エディタのscrollComponentIntoViewBehaviorタグ

エディタのscrollComponentIntoViewBehaviorタグ

ユーザーがスクロールしたコンポーネントにフォーカスを切り替えるためのタグを構成することもできます。

scrollComponentIntoViewBehaviorタグを使用する手順:

  1. ユーザーがクリックして、指定されたコンポーネントに移動するコマンド・コンポーネントを作成します。手順は、18.2.1項「コマンド・ボタンおよびコマンド・リンクの使用方法」を参照してください。

  2. コンポーネント・パレットの「操作」セクションから、「コンポーネントのビュー内へのスクロール動作」をコマンド・コンポーネントの子としてドラッグ・アンド・ドロップします。

  3. 「コンポーネントのビュー内へのスクロール動作の挿入」ダイアログで、ドロップダウン矢印を使用して「編集」を選択し、移動してユーザーの移動先であるコンポーネントを選択します。

  4. 移動後にコンポーネントにフォーカスを設定する場合は、プロパティ・インスペクタで、focus属性をtrueに設定します。

  5. richTextEditorまたはinlineFrameコンポーネントの場合は、オプションで、subTargetId属性の値を入力します。このIDは、richTextEditorまたはinlineFrameコンポーネントの値で定義されています。

    たとえば、図5-1に示されているscrollComponentIntoViewBehaviorタグのsubTargetId属性の値は、Introductionです。richTextEditorの値は、例5-17に示されているプロパティにバインドされています。Introductionは最初のヘッダーのIDです。

    例5-17 プロパティに定義されているsubTargetId値

    private static final String _RICH_SECTIONED_VALUE = 
      "<div>\n" + 
      "    <h2>\n" + 
      "      <a id=\"Introduction\"></a>Introduction</h2>\n" + 
      "    <p>\n" + 
      "      The ADF Table component is used to display a list of structured data. For example,\n" + 
      "      if we have a data structure called Person that has two properties - firstname and\n" + 
      "      lastname, we could use a Table with two columns - one for firstname, and the other\n" + 
      "      for lastname - to display a list of Person objects.\n" + 
      "    </p>\n" + 
      "  </div>\n" + 
      "  <div>\n" + 
      "    <h2>\n" + 
      "      <a id=\"The_Table_Model\"></a>The Table Model</h2>\n" + 
      "    <p>\n" + 
      . . .
       </div>";
    

5.7 ポーリング・イベントを使用したページの更新

ADF Facesは、pollEventを使用して指定された間隔でサーバーと通信できるpollコンポーネントを提供します。たとえば、pollコンポーネントを使用してoutputTextコンポーネントを更新したり、サーバーにハートビートを配信してユーザーがセッションでタイムアウトにならないようにすることができます。

ポーリング時刻に必要な処理を行うために使用されるpollEventのリスナーを作成する必要があります。たとえば、pollコンポーネントを使用してoutputTextコンポーネントの値を更新する場合は、データ・ソース内の値をチェックしてからコンポーネントを更新するpollEventListenerメソッドを実装します。

pollコンポーネントがそのポーリング・イベントを配信する頻度を決定する時間間隔を構成できます。経過後にページがタイムアウトになることを許可される時間も構成します。ページのポーリングはセッションがタイムアウトにならない原因となるため、これが役立つ場合があります。サーバーにリクエストが送信されるたびに、セッション・タイムアウト値がページに書き込まれ、セッションをいつタイムアウトにするかを決定します。pollコンポーネントは(時間間隔に基づいて)サーバーにリクエストを継続的に送信するため、セッションは決してタイムアウトになりません。これは、ネットワーク使用量とメモリーの両方でコストが高くなります。

この問題を回避するために、web.xml構成ファイルには、タイムアウトにする前にページを実行する必要のある時間の長さを指定するoracle.adf.view.rich.poll.TIMEOUTコンテキスト・パラメータが含まれます。キーボードやマウスのアクティビティがない場合、ページはタイムアウトに対して適格とみなされます。デフォルトのタイムアウト期間は10分に設定されています。このため、ユーザーが10分間非アクティブの(つまり、キーボードやマウスを使用していない)場合、フレームワークはポーリングを停止し、その時点から、ページは標準サーバー側セッション・タイムアウトに参加します(詳細は、第A.2.3.21項「セッション・タイムアウトの警告」を参照してください)。

アプリケーションがタイムアウトになる場合、ユーザーがマウスを移動するかキーボードを再び使用すると、新しいセッション・タイムアウト値がページに書き込まれ、ポーリングが再び開始します。

pollコンポーネントのtimeout属性を使用して、特定のページについてこの時間をオーバーライドできます。

5.7.1 pollコンポーネントの使用方法

pollコンポーネントを使用する場合、通常はポーリング・イベントの機能を処理するハンドラ・メソッドも作成します。

始める前に

属性が機能に与える影響に関する知識が役立つ場合があります。詳細は、5.7項「ポーリング・イベントを使用したページの更新」を参照してください。

pollコンポーネントを使用する手順:

  1. マネージドBeanで、ポーリング・イベントのハンドラを作成します。マネージドBeanの詳細は、2.6項「マネージドBeanの作成と使用」を参照してください。

  2. コンポーネント・パレットの「操作」パネルから「ポーリング」をドラッグ・アンド・ドロップすることでpollコンポーネントを作成します。

  3. プロパティ・インスペクタで、「共通」セクションを開いて次の設定を行います。

    • Interval: ポーリング・イベント間の時間をミリ秒単位で入力します。ポーリングを無効にするには0に設定します。

    • PollListener: 手順1のメソッドに評価されるEL式を入力します。

  4. web.xmlファイルのグローバル・タイムアウト値をオーバーライドする場合は、「その他」セクションを開き、「タイムアウト」に、ページがポーリングを停止してセッションがタイムアウトするまでの時間(ミリ秒)を設定します。