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

戻る
戻る
 
次へ
次へ
 

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.4項「最適化されたライフサイクルの使用」を参照)、ページのそれらのコンポーネントのみがリフレッシュされます。

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

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

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

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

action

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

false

dialog

dialog

false

disclosure

showDetailshowDetailHeader

true

disclosure

showDetailItem

true

focus

treetreeTable

true

launch

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

NA

launchPopup

inputListOfValuesinputComboboxListOfValues

true

load

document

NA

poll

poll

true

popupOpened

popup

NA

popupOpening

popup

NA

popupClosed

popup

NA

propertyChange

すべてのコンポーネント

NA

queryEvent

queryquickQuery

true

queryOperation

queryquickQuery

true

rangeChange

table

NA

regionNavigation

region

NA

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を実装するコンポーネント)


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

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

たとえば、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はコール元ページにもJavaScriptライブラリにも含めることができます。

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


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

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

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

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

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

action

AdfActionEvent

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

dialog

AdfDialogEvent

dialog

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

disclosure

AdfDisclosureEvent

showDetailshowDetailHeadershowDetailItem

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


AdfFocusEvent

treetreeTable


AdfLaunchPopupEvent

inputListOfValuesinputComboboxListOfValues

load

AdfComponentEvent

document

ドキュメントでロードが完了したとき


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

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

valueChange

AdfValueChangeEvent

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

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


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タグを使用します。

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

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

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

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

click

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

dblclick

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

mousedown

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

mouseup

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

mousemove

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

mouseover

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

mouseout

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

keydown

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

keyup

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

keypress

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

focus

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

blur

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



注意:

キーボードとマウスのイベントは、AdfBaseEventクラスのAdfUIInputEventサブクラスを使用してネイティブDOMイベントをラップします。このクラスでは、DOM本来のイベントへのアクセスが提供されます。キー・コード、マウス座標などを取得するための簡易関数も幅広く提供されます。AdfBaseEventクラスでは、これらのイベントの実装方法のブラウザ間の違いも考慮します。このため、開発者は、getNativeEvent()メソッドを直接使用するのではなく、AdfUIInputEvent APIを使用することを強くお薦めします。

クライアント側イベントを使用するには、まず、イベントを処理するJavaScriptを作成する必要があります。JavaScriptの作成の詳細は、3.3項「JavaScriptのページへの追加」を参照してください。この機能内で次の点を追加できます。

JavaScript関数の作成後、イベント・メソッドをコールするイベント・リスナーを追加する必要があります。詳細は、5.3.5項「イベント・ハンドラ実行のトリガー方法」を参照してください。

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

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

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

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.2 イベントのクライアント側属性の使用

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

例5-5 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-6に示すように、値はソース・コンポーネントで設定されます。JSFページのコンポーネントの設定の詳細は、5.3.5項「イベント・ハンドラ実行のトリガー方法」を参照してください。

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

<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.3 イベント実行時のUI入力のブロック方法

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

ADF Faces JavaScript APIには、AdfBaseEvent.preventUserInput関数が含まれています。イベントの処理中にすべてのユーザー入力を阻止するには、preventUserInput関数をコールします。この関数をコールすると、ブラウザ・ウィンドウ全体がガラス・ペインで覆われ、イベントがサーバーへのラウンドトリップを完了するまで入力できなくなります。

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

例5-7 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.4 イベントがサーバーに伝播されないようにする方法

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

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

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

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.5 イベント・ハンドラ実行のトリガー方法

JavaScriptメソッドの記述後、JSFページでclientListenerタグを使用してコンポーネント(このコンポーネントのイベントがメソッドの実行をトリガーする)にJavaScriptメソッドをアタッチします。

クライアント・リスナーを使用してメソッド実行をトリガーする手順:

  1. JavaScriptを起動するコンポーネントを選択し、プロパティ・インスペクタでClientComponent属性をtrueに設定します。

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

  3. 「クライアント・リスナーの挿入」ダイアログでメソッドを入力し、JavaScript関数のタイプを選択します。スクリプトがページに含まれていない場合はライブラリ名を必ず含めます。サポートされているクライアントのイベント・タイプのリストは、表5-3および表5-4を参照してください。

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

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

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

    例5-10 属性の追加

     <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.7項「クライアント側コンポーネントに対するボーナス属性の使用」を参照してください。

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()メソッドを使用する必要があります。

たとえば、File Explorerアプリケーション内のページのコンポーネントはすべて最終的にはpageTemplateコンポーネント内にあるため、例5-11に示すように、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との間で最も適切にやりとりできるようデータを適切な形式に変換することです。クライアントがブラウザベースの場合、JavaScript Object Notation(JSON)およびXMLの2つが一般的なマーシャリング方法です。ADF Facesでは両方の方法を組み合せて使用します。情報は、サーバーからクライアントへは主にJSONで、クライアントからサーバーへはXMLで送信されます(JSONの詳細は、http://www.json.orgを参照してください)。

JavaScriptからJavaへ情報を送信する場合、JavaScriptデータ・オブジェクトはXMLに変換され(マーシャリング)、サーバー側で解析してJavaオブジェクトに戻されます(アンマーシャリング)。たとえば、cmdというIDのcommandButtonコンポーネントを含むJSFページを考えてみます。ユーザーがcommandButtonコンポーネントをクリックしたとき、このcommandButtonによってactionEventが発生したことをクライアントからサーバーに通信する必要があります。requestParameterマップで、情報がevent + . + ididはコンポーネントの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フラグメントが、typejava.lang.String)をキーとし、actionjava.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コードの量が少なくなります。

クライアント・リスナーのかわりに使用できるクライアント動作を次に示します。

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

5.6.1 showPrintablePageBehaviorタグの使用方法

ユーザーがコンテンツを印刷できるコンポーネント内のコマンド・コンポーネントには、showPrintablePageBehaviorタグを使用します。コマンド・コンポーネントがアクティブになると、印刷可能なページを取得するリクエストがサーバーに送信されます。コマンド・コンポーネントがアクティブになると通常発生するアクション・イベントは送信されません。ADF Facesでページの印刷可能版が、新規のブラウザまたはブラウザ・ウィンドウの新規のタブに表示されます。印刷可能なページには、スクロール・バーおよびボタン、タブ、メニューなどのナビゲーション・アイテムはレンダリングされません。

showPrintablePageBehaviorタグを使用する手順:

  1. レイアウト・コンポーネントのいずれかで、印刷するコンテンツを含むファセットにコマンド・コンポーネントを作成します。手順は、18.2.1項「コマンド・ボタンおよびコマンド・リンクの使用方法」を参照してください。


    注意:

    ユーザーがページ全体を印刷できるようにレイアウト・コンポーネントの外にshowPrintablePageBehaviorコンポーネントを挿入できますが、印刷結果がレイアウトとおおまかにしか一致せず、一部のコンテンツが表示されない場合があります。そのため、ユーザーがファセットの全コンテンツを印刷できるようにするには、ユーザーが通常印刷するコンテンツを含むファセットにshowPrintablePageBehaviorコンポーネントを配置することが重要です。複数のファセットで印刷をサポートする必要がある場合は、各ファセットにコマンド・コンポーネントを1つとshowPrintablePageBehaviorタグを挿入します。すべてのコンテンツを印刷するには、ユーザーは一度に1つのファセットで印刷コマンドを実行する必要があります。

  2. コンポーネント・パレットの「操作」セクションを開き、印刷可能ページ表示動作をコマンド・コンポーネントの子としてドラッグ・アンド・ドロップします。

5.6.2 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>";