5.2. 実装の詳細¶
5.2.1. 共通検索タブの実装¶
共通検索画面で使用するタブを追加するためには次のものを準備する必要があります。
- プラグインの構成情報を記述するplugin.xml
- タブ内で検索処理を行うJSSP (html+js)
- クライアントサイドで基盤部分からのイベントに応答するためのjs(csjs)
5.2.1.1. プラグインの構成情報を記述するplugin.xmlの作成¶
ここではユーザ検索(キーワード)タブのplugin.xmlを例に説明します。
<?xml version="1.0" encoding="utf-8"?> <plugin> <extension point="jp.co.intra_mart.common.search.tabs"> <search name="standard" id="jp.co.intra_mart.master.app.search.tabs.user.list_user" version="8.0.0" rank="1"> <content title="%tabtitle" csjs="im.app.search.plugins.tabs.user.keyword.Keyword" page="im_master/plugins/app/search/tabs/user/keyword/keyword" min_width="450" min_height="325" /> </search> </extension> </plugin>
【リスト:ユーザ検索(キーワード)タブのplugin.xml】
- extensionタグ
- point属性 :共通検索画面のタブを拡張する拡張ポイントを指定します。共通検索画面のタブであればこの値は同じです。
- searchタグ
- name、id、version、rank などの属性はPlugin Managerによって依存関係の管理などに使用されます。詳細はPlugin Managerのドキュメントを参照してください。
- タグ名は任意です
- content タグ
title属性:追加したタブに表示されるタイトルを指定します。%表記は国際化メッセージキーを表します。国際化に関してはPlugin Managerのマニュアルを参照してください。
csjs属性:クライアントサイドでタブの情報をハンドリングする処理を設定します。この処理はim-JSPackmanで管理可能なクラス形式である必要があります(im-JSPackmanの詳細はクライアントサイドライブラリのAPIを確認してください)。クラスのFQDNを指定します。
page属性:タブ内のUIを構築するJSSPのパスを指定します(拡張子無し)
min_height,, min_width 属性:最低限必要な表示高さ、幅をpixelで指定します。特に指定しなければ他のTabの要求サイズや実際の表示領域の大きさを勘案して自動的に決定します。このxmlファイルをPlugin Managerの管理するディレクトリに配置します。具体的には以下のパスが対象です。<(展開したwar)/WEB-INF/plugin/%plugin_id%/plugin.xml>plugin.xmlを変更した場合は、intra-martを再起動する必要があります。
5.2.1.2. タブ内で検索処理を行うJSSP(html+js)の作成¶
基本としてJSSPで検索処理の全てを実装します。通常のJSSPのように最初はinit()が読み出されます。引数には共通検索画面が受け取ったパラメータそのままのオブジェクトが渡されます。共通検索画面が受け付けるオブジェクトの形式については IM-共通マスタ 検索画面仕様書 に定義されていますので、そちらを参照してください。このファイルは 「プラグインの構成情報を記述するplugin.xmlの作成 」でcontentタグのpageプロパティと一致する場所に配置します。
5.2.1.2.1. html作成時の注意¶
使用するブラウザの種類とバージョンによって、初期処理が【図:共通検索画面の動作シーケンス】のとおりに動作しない場合があります。そのため、検索タブのhtml側で以下の実装を行う必要があります。<imart type="head"> <!--・・略・・--> // jspackmanクラスインポート Import("im.app.search.control.PageHandler"); ・・・・・・・① // 初期処理実行 Main.invoke("this"); function main(args) { pc = new im.app.search.control.PageHandler("global_instance", createPage); ・・・・・・・② pc.execute(); } function createPage() { try { // ここにpluginのメイン処理を記載する。 /*・・略・・*/ } finally { lwc.stopLoading(); window.global_instance.completeNotice(); ・・・・・・・③ } } <!--・・略・・--> </imart> <!--・・略・・-->【リスト:検索タブのhtmlのサンプル】
- 検索タブのヘッド部で、PageHandlerをimportします。
- PageHandlerのインスタンスを生成します。第2引数には、検索画面タブのメイン処理が書かれてあるメソッドを定義します。
- 検索画面のメイン処理が終わった時に、completeNoticeを呼び出します。
5.2.1.3. クライアントサイドで基盤部分からのイベントに応答するためのjs の作成¶
クライアントサイドでは基盤部分でのユーザアクションに反応して検索結果を取り扱う必要があるため、特定のタイミングで、クライアントサイドスクリプトの特定のメソッドを呼び出します。クライアントサイドスクリプトはim-JSPackmanの実装方式にしたがって定義したクラスである必要があります(plugin.xmlにクラス名を指定する事で画面基盤が動的にロードしてインスタンス化します)。下記にクライアントサイド処理で必要な処理を示します。
メソッド名 戻り値 説明 1 init(window, params) void タブのロードが終わったタイミングで呼び出されます。特に基盤側から期待する動作はありません。 intra-mart Accel Platform 2015 Spring 以前は、画面起動時にすべてのタブがロードされます。 intra-mart Accel Platform 2015 Summer 以降は、タブが選択されてからタブがロードされます。引数の説明:window: タブのIFRAMEを表すwindowオブジェクトparams : 起動引数2 onSelect( window ) Array ユーザが選択のアクションを行ったタイミングで呼び出されます。現在選択されている値を 4.2.1.3.1結果の形式について で説明している形式で、配列に詰めて返してください。単一選択時の場合には「確定」ボタンを押下したタイミング、複数選択時の場合は個別選択ボタン(右矢印のアイコン)を押下したタイミングです。引数の説明:window: タブのIFRAMEを表すwindowオブジェクト3 onSelectAll( window ) Array ユーザが全選択のアクション(右二重矢印のアイコンを押下)を行ったタイミングで呼び出されます。現在検索結果として表示している値を全て4.2.1.3.1結果の形式についてで説明している形式にして、配列に詰めて返してください。引数の説明:window: タブのIFRAMEを表すwindowオブジェクト4 onDeselect(window, items) boolean ユーザが選択解除のアクション(左矢印のアイコンを押下)をしたタイミングで呼び出されます。選択解除対象のオブジェクトが引数に渡され、全てのタブに対し呼び出されます。項目の解除処理自体は画面処理基盤側で行いますので、特に基盤側から期待する動作はありません。引数の説明:window: タブのIFRAMEを表すwindowオブジェクトitems : 選択解除されたオブジェクトの配列5 onDeselectAll(window, items) boolean ユーザが全解除のアクション(左二重矢印のアイコンを押下)をしたタイミングで呼び出されます。選択解除対象のオブジェクトが引数に渡され、全てのタブに対し呼び出されます。項目の解除処理自体は画面処理基盤側で行いますので、特に基盤側から期待する動作はありません。引数の説明:window: タブのIFRAMEを表すwindowオブジェクトitems : 選択解除されたオブジェクトの配列6 onDecide( window ) boolean ユーザが決定のボタンを押下した際に呼び出されます。基盤側から期待する動作はありません。引数の説明:window: タブのIFRAMEを表すwindowオブジェクト7 onClose( window ) boolean ユーザがタイトルバーの×ボタンを押下した際に呼び出されます。基盤側から期待する動作はありません。引数の説明:window: タブのIFRAMEを表すwindowオブジェクト【表:クライアントサイドスクリプトに必要なメソッドの一覧】
また必要なメソッドを空実装した”im.app.search.abstracts.AbstractTab”クラスが存在します(実際のファイルは <(展開したwar)/csjs/im/app/search/abstracts/AbstractTab.js>)。このクラスを継承して実装すれば不要なメソッドをオーバーライドする必要がありません。/** * @fileoverview タブをハンドリングするクラスを定義しています。<br/> */ Package("im.app.search.abstracts"); Class("im.app.search.abstracts.AbstractTab").define( im.app.search.abstracts.AbstractTab = function() { this.superclass(); /* 画面構築基盤の提供する機能へアクセスするためのオブジェクトが格納される */ this.parent; /** * 要override * タブのロードが完了した時点で呼び出される。戻り値は不要。 * @param {window} window タブ内のフレームを表すウィンドウオブジェクト * @param {Object params} 起動引数オブジェクト **/ this.init = function(window, params){ }; /** * 要override * 画面基盤側で選択ボタンが押下された場合など、現在選択中の情報が要求された場合に呼び出される。 * タブ内で現在選択されている情報を規定形式のJSONオブジェクトとして返す。 * 配列を返すことで複数一括の選択として使用できる。multipleでない場合は先頭のもののみ使用する。 * 選択されている情報がない、または無効などの場合はnullを返す。 * * @param {window} window タブ内のフレームを表すウィンドウオブジェクト **/ this.onSelect = function(window){ }; /** * 要override * 画面基盤側で全選択ボタンが押下された場合など、現在の検索結果全てが要求された場合に呼び出される。 * タブ内で現在選択されている情報を規定形式のJSONオブジェクトとして返す。 * 配列を返すことで複数一括の選択として使用できる。multipleでない場合は先頭のもののみ使用する。 * 選択されている情報がない、または無効などの場合はnullを返す。 * * @param {window} window タブ内のフレームを表すウィンドウオブジェクト **/ this.onSelectAll = function(window){ }; /** * 画面基盤側で項目が選択解除された際に呼び出される。 * ほとんどのタブに於いて処理する必要はないはず。 * 全てのタブに対して呼び出される。 * @param {window} window タブ内のフレームを表すウィンドウオブジェクト * @param {Object} items 選択解除されたオブジェクト。複数の場合は配列。typeに関係なく渡される。 **/ this.onDeselect = function(window, items){ }; /** * 画面基盤側で項目が選択全解除された際に呼び出される。 * ほとんどのタブに於いて処理する必要はないはず。 * 全てのタブに対して呼び出される。 * @param {window} window タブ内のフレームを表すウィンドウオブジェクト * @param {Object} items 選択解除されたオブジェクト。複数の場合は配列。typeに関係なく渡される。 **/ this.onDeselectAll = function(window, items){ }; /** * 画面基盤側で項目が選択が確定された際に呼び出される。 * ほとんどのタブに於いて処理する必要はないはず。 * 全てのタブに対して呼び出される。 * @param {window} window タブ内のフレームを表すウィンドウオブジェクト * @param {Object} items 選択決定されたオブジェクト。複数の場合は配列。typeに関係なく渡される。 **/ this.onDecide = function(window, items){ }; /** * 画面基盤側で閉じるボタンが押下された再に呼び出される。 * ほとんどのタブに於いて処理する必要はないはず。 * 全てのタブに対して呼び出される。 * @param {window} window タブ内のフレームを表すウィンドウオブジェクト **/ this.onClose = function(window){ }; } );【リスト: AbstractTab.js】
クライアントサイドスクリプトの配置場所は <(展開したwar)/csjs> 配下に、パッケージ名にあわせてディレクトリを作成して配置してください。
5.2.1.3.1. 結果の形式について¶
結果は以下の形式のオブジェクトを配列にして返してください。
クライアントサイドでは基盤部分でのユーザアクションに反応して検索結果を取り扱う必要があるため、特定のタイミングで、クライアントサイドスクリプトの特定のメソッドを呼び出します。クライアントサイドスクリプトはim-JSPackmanの実装方式にしたがって定義したクラスである必要があります(plugin.xmlにクラス名を指定する事で画面基盤が動的にロードしてインスタンス化します)。下記にクライアントサイド処理で必要な処理を示します。
プロパティ名 型 説明 data Object 実際にデータベースから取得したレコードの内容をオブジェクトとして設定してください。 type Array このオブジェクトの型を表します。主にプラグイン側から画面処理基盤へ型の判別ができるように提示するものです。画面処理基盤ではtypeと、keyFieldsを同じ項目が選択されていないか判断するために使用しています。keyFields Array 文字列の配列。data 内で一意性を表すキーとなるプロパティのプロパティ名を配列として設定してください。画面処理基盤側で重複選択を避ける為の情報として使用します。具体的にはdataからkeyFieldsに設定されたの名前のプロパティを取得し、同一typeかどうかを含めて比較して重複がないかを確認しています。displayName string オブジェクトを画面に表示する際に使用する表示文字列