本文へジャンプ

ソフトウェア > Lotus > Lotus Developer Domain > 製品別技術情報 > Lotus Notes/Domino > 

LDD Today

Web向けキーワード・マジック Part 1


Lotus Software
by Mark Polly
レベル:中級者
対 象:Notes/Domino
原文の掲載:2003年10月6日

LDD Todayの原文(US)

インデックス
@DBColumnを使った1つのキーワード・リストの作成
段階的なキーワード・リストの作成
まとめ

キーワード・リストを使用すると、ユーザーが間違ったデータを入力しないように選択肢を用意することができます。しかし、これが悩みの種になることもあります。多くのアプリケーションには複数のキーワード・リストからなる画面があり、多くの場合、リストの選択肢が前のリストの選択内容に依存しています。Notesクライアントを対象とする開発では、こうしたキーワード・リストを正しく機能させるために利用できる機能がたくさんあります。リストの選択肢は、@Dblookup式を使用して作成できます。Notesでは、フィールドの計算が上から下の順に行われるため、フォームの下の方にあるキーワード・リストを前のフィールドの選択内容に基づいて作成できます。また、Notes以外のデータベースのデータにアクセスする必要がある場合も、LotusScriptを使って簡単に選択肢を作成できます。

一方、Webを対象とする開発では、キーワード・リストについて問題がいくつか出てきます。まず、フォームに複数のキーワード・リストがあり、前の選択内容に基づいて選択肢を作成する場合は、その他の問題にも気を配らなければなりません。Dominoでキーワード・リストを再作成するには、[キーワードの変更時にフィールドを更新]と[文書の更新時に選択肢を更新]という2つのオプションを使用します。これらの機能を使用すると、サーバーのトラフィックが増加したり、画面が何度も切り替わったりするほか、ページ上のJavaScriptで問題が発生する可能性もあります。これらのオプションがアプリケーションのパフォーマンスに与える影響については、LDD Todayの「Application Performance Tuning, Part 2」を参照してください。

JavaScriptの配列を使用してリストをあらかじめ作成しておき、その配列に基づいてキーワード・リストを設定することもできます。この方法は、キーワード・リストが小さい場合にはうまくいきますが、複数のリストが必要になるとすぐに利用できなくなってしまいます。たとえば、3つのキーワード・リストがあり、2つ目のリストは1つ目のリストに基づいて、3つ目のリストは2つ目のリストに基づいてそれぞれ作成するとします。1つ目のリストには50の選択肢があり、2つ目のリストには、1つ目のキーワード・リストの各選択肢ごとに20の選択肢があります。3つ目のリストには、1つ目と2つ目のキーワード・リストの各組み合わせごとに20の選択肢があります。この場合、それぞれ50の要素、1,000 (50×20)の要素、20,000の要素を含む3つのJavaScript配列が必要になります。これらの配列をあらかじめ作成しておくのには時間がかかります。

2つ目の問題として、キーワード・リストを作成するのに、Notesの式言語では対応できないような複雑なコーディングが必要になる場合があります。LotusScriptでは、ブラウザで発生するイベントに応答する形でのコーディングはできないため、実行時にキーワード・リストを作成するのは簡単ではありません。

最後の問題として、前のキーワード・リストの選択内容に基づく選択肢を持つキーワード・リストで、リストを作成するのにリレーショナル・データベースの呼び出しが必要な場合、LotusScriptでは、リレーショナル・データベースにアクセスしてキーワード・リストを作成するためのわかりやすい方法がありません。

この2部構成の記事の第1部では、Webアプリケーションでこうしたキーワード・リストの制約を克服する方法を紹介します。ページをリフレッシュしたり巨大なJavaScript配列を作成したりすることなく、ほかのキーワード・リストの選択内容や、ユーザーが入力したデータに基づいてキーワード・リストを作成するにはどうすればよいのかを説明します。

第2部では、さらに踏み込んで、LotusScriptを使ってキーワード・リストを作成します。最終的には、同じ方法を使用して、リレーショナル・データベースに格納されているデータに基づいてキーワード・リストを作成します。


@DBColumnを使った1つのキーワード・リストの作成
この機能を実装するには、@DBColumnと、Microsoft Internet Explorerによって実装されている<iframe>タグとの組み合わせを使用します。iframeはWebページの内部フレームであり、Dominoフォームの埋め込みビューに似ています。埋め込みビューは、エンド・ユーザーにはページの一部のように見えますが、実際にはまったく別のページです。iframeも同様で、ページに埋め込まれているように見えますが、中身は別のページです。Dominoの埋め込みビューと違う点は、iframeのソース・ページは同じサーバーにあっても別のサーバーにあってもかまわないという点です。

注: 使用しているブラウザでiframeがサポートされていない場合は、新しいブラウザ・ウィンドウを画面の外で開くことで同じ方法を使用できます。このほか、標準のフレームセットを使用して、フレームの1つを隠す方法もあります。

以下の図は、入力フォームの画面です。ここでは、iframeを表示するのに、width=0、height=0、src=/bigdb.nsf/loblookup?Readformというパラメーターを使用しています。widthとheightの2つのパラメーターをこのように指定すると、幅と高さを持たないiframeが表示されることになるため、結果としてiframeをユーザーから隠すことができます。srcパラメーターは、iframeに読み込むページを指定します。この場合、実際には、サーバーからDominoフォームが読み込まれることになります。



このloblookupフォームは、サーバー上のbigデータベースにあります。このデータベースで@Dbcolumnを実行します。以下の図は、loblookupフォームを示しています。



このフォームはユーザーには表示されないため、ページがiframeに読み込まれた後に実行されるJavaScriptしか含まれていません。このJavaScriptコード全体は、次のようになります。

<script>
var LOBArray = new Array("<Computed Value>");
//delete current options
oldLOB = window.parent.document.all("LOB").options;
for(x=oldLOB.length-1; x>=0; x--){
oldLOB.options[x] = null;;
}
//set the default values
var oOption=window.parent.document.createElement("OPTION");
oldLOB.options.add(oOption);
oOption.innerText="---Select---";
oOption.value="---Select---";
oOption.selected=true;
for(x=0; x< LOBArray.length;x++){
//Set the option in the element drop down
var oOption=window.parent.document.createElement("OPTION");
oldLOB.options.add(oOption);
oOption.innerText=LOBArray[x];
oOption.value=LOBArray[x];
}
</script>

このJavaScriptコードの2行目にある<Computed Value>の式は、次のようになります。

temp := @DbColumn( "" ; "" ; "LOBs" ; 1 ) ;
val:=@If(@IsError(temp); "No LOB"; temp);
@Implode(val;"\",\"")

この式の1行目では、現在のデータベース(bigdb.nsf)で@Dblookupを実行しています。@Dbcolumnが成功した場合は、返された値が、区切り文字として「","」を使用して連結されます。たとえば、データに含まれていたのがMarketing:Finance:Public Affairsだった場合、3行目の@implode関数は、Marketing”,”Finance”,”Public Affairsを返します。これがJavaScriptコードに挿入されて、実行時には次のような行になります。

Var LOBArray = new Array(“Marketing”,”Finance”,”Public Affairs”);

これで、bigdb.nsfでの@Dbcolumnのすべての値を含む標準のJavaScript配列ができました。

JavaScriptの残りの部分では、server1で実行されるページ上のキーワード・リストに選択肢を設定する作業を行っています。5行目では、parent.document (iframeを含むページ)に配置されているLOBキーワード・リストにoldLOBオブジェクトを設定しています。

oldLOB = window.parent.document.all("LOB").options;

6〜7行目では、LOBキーワード・リストの選択肢(オプション)を削除しています。

For(x=oldLOB.length-1; x>=0; x--){
oldLOB.options[x] = null;;

10行目では、parent.documentに新しいOptionオブジェクトを作成しています。

var oOption=window.parent.document.createElement("OPTION");

11〜12行目では、作成したオプション・オブジェクトをLOBキーワード・リストに追加して、最初のオプション値を“---Select---“に設定しています。

oldLOB.options.add(oOption);
oOption.innerText="---Select---";

15〜21行目では、LOBArrayの各要素のためのオプション・オブジェクトを作成しています。

for(x=0; x< LOBArray.length;x++){
//Set the option in the element drop down
var oOption=window.parent.document.createElement("OPTION");
oldLOB.options.add(oOption);
oOption.innerText=LOBArray[x];
oOption.value=LOBArray[x];
}

このJavaScriptが実行されると、メイン・フォーム上のLOBキーワード・リストに、bigdb.nsfから収集された選択肢が設定されます。



データベースで匿名アクセスが制限されている場合は、iframeに読み込まれるページでDominoによるユーザー認証が行われます。ユーザーに対してパスワードが要求されないようにするには、サーバー間にまたがるシングル・サインオンを使用する方法が簡単です。

復習
このコードは単純に見えますが、多くのことを学ぶことができます。このサンプルを通じて学んだことを列挙すると、次のようになります。

  1. iframeにページを読み込むことによってキーワードのリフレッシュをシミュレートする方法
  2. @DBLookup式と@DBColumns式の実行方法
  3. @式とJavaScriptを組み合わせてキーワード・リストを設定する方法
以上で基本を身に付けることができたので、次に、複数のキーワード・リストの処理について見ていきます。
 
上に戻る
 
段階的なキーワード・リストの作成
先にも述べたとおり、キーワード・リストを作成するにはいくつかの方法があります。リストが小さい場合は、どの方法を使用しても問題はありませんが、リストの組み合わせが何千にも及ぶような場合は、これ以外の方法では十分ではありません。

ここでは、価格設定データベースを例にして見ていきます。このアプリケーションでは、価格が州、市、製品の順に決定されます。最初のキーワード・リストには、米国の各州に対応する50のエントリーがあります。州の選択を終えると、次に市を選択します。各州ごとに、営業所のある市が30〜40あります。したがって、州と市の組み合わせ総数は、多くても2,500程度です。州と市の選択が済んだら、次に製品を選択します。それぞれの市には、最大20の製品があります。結果として、州 - 市 - 製品の組み合わせ総数は50,000になります。

組み合わせの数が多いため、Webページが読み込まれるときにキーワード・リストを作成することはできません。また、市のリストは、ユーザーが州を選択しないと設定できません。製品のリストについても同様で、ユーザーが州と市の両方を選択してからでないと設定できません。以下はサンプル画面です。



コードの概要
では、具体的な方法について見ていきましょう。最初は、既に説明した1つのキーワード・リストの場合と同様です。最初のキーワード・リスト(州のリスト)については、先ほど説明したのと同じ方法を使って設定できます。iframeのコードは次のようになります。

<iframe id=”HidFrame” height=0 width=0 src=”/bigdb.nsf /StateLookup?ReadForm“></iframe>

ユーザーが州を選択した後、なんらかの方法を使って市のリストを作成しなければなりません。ここでは、州のフィールドでonChangeイベントを使用します。このonChangeイベントには、JavaScriptが必要です。このコードは次のようになります。

1. st = this[this.selectedIndex].text;
2. document.all('HidFrame [delete:lookupframe]').src= ‘/bigdb.nsf /CityLookup?ReadForm&state=' + st;

1行目では、ユーザーが選択した州の名前を取得しています。このコードはonChangeイベントの中にあるため、「this」は州のキーワード・フィールドを指します。2行目では、iframeのソース・パラメーターに新しいページ(CityLookup)を設定し、クエリー文字列を使ってそのページに州の名前を渡しています。ユーザーが州の名前を選択すると、ブラウザでこの行が実行されて、CityLookupページがiframeに読み込まれます。JavaScriptを使用してiframeのソース・ページを設定するには、次のように、単純にIDパラメーターをiframeに渡します。

<iframe id=”HidFrame” ….></iframe>

CityLookupページでは、前に使用したのと同じ@DblookupとJavaScriptの組み合わせを使用します。ただし今回は、「State」フィールドのクエリー文字列の式から州の値を取得するためのフィールドを追加します。

QSLst:=@Explode(@Explode(Query_String_Decoded;"&");"=");
loc:=@Member("state"; QSLst);
@If(loc>0; @Subset(@Subset(QSLst;loc+1);-1);"")

クエリー文字列から値を取得するには、さまざまな方法があります。州のフィールドの式では、そのうちの1つの方法を使用しています。まず1行目では、Query_String_Decoded値を取得し、分離記号として「&」を使用してそれを1回分割しています。その結果、&var=valueという形式の要素を持つリストが作成されます。次に、「=」を分離記号とする別の@explodeが実行されます。その結果、var:value:var:valueという形式の要素を持つリストが作成されます。2行目では、リスト内の州の位置を見つけています。最後に3行目で、リストの次の要素を取得することによって、州の値を得ることができます。

ページ上のJavaScriptは、次のようになります。

<script>
var CityArray = new Array("<Computed Value>");
//delete current options
oldCity = window.parent.document.all("City").options;
for(x=oldCity.length-1; x>=0; x--){
oldCity.options[x] = null;;
}
//set the default values
var oOption=window.parent.document.createElement("OPTION");
oldCity.options.add(oOption);
oOption.innerText="---Select---";
oOption.value="---Select---";
oOption.selected=true;
for(x=0; x< CityArray.length;x++){
//Set the option in the element drop down
var oOption=window.parent.document.createElement("OPTION");
oldCity.options.add(oOption);
oOption.innerText=CityArray[x];
oOption.value=CityArray[x];
}
</script>

2行目にある<Computed Value>の式は、次のようになります。

temp := @DbLookup( "" ; "" ; "CityState" ; “State”; 2 ) ;
val:=@If(@IsError(temp); "No City"; temp);
@Implode(val;"\",\"")

前と同じように、@Dblookupを実行して、クエリー文字列で渡された州の値に基づいて市のリストを取得しています。市のリストは、JavaScriptの配列に格納されます。一度に返される市は40だけなので、この方法でまったく問題ありません。コードの残りの部分では、配列の値を取得して、市のキーワード・リストを親文書に作成しています。

もうすぐ完成です。市のリストが用意できたので、ユーザーが市を選択するのを待って、次に製品のリストを作成します。ご想像のとおり、ここでは、市のフィールドに対して使用したのと同じプロセスをそのまま使用します。つまり、CityフィールドのonChangeイベントをコーディングして、新しいページをiframeに読み込みます。ソースURLには、クエリー文字列で市と州両方の値を渡します。iframeに読み込まれたページは、リモート・サーバーに対してDblookupを実行し、その結果を製品リストに設定します。この場合も、結果となるリストに含まれるエントリーは多くても50だけなので、JavaScriptで簡単に処理できます。

最後に、製品フィールドで同じ方法を使ってルックアップを実行すると、価格を取得できます。
 
上に戻る
 
まとめ
ここでは、ユーザーがページ上でオプションを選択してからでないと作成できないキーワード・リストをWebベースのアプリケーションで作成するための、非常に強力な方法を紹介しました。この方法の手順を要約すると、次のようになります。

  1. 非表示のiframeをページに追加します。
  2. ユーザーがキーワード・リストで選択を行ったら、JavaScriptを使用してiframeに新しいページを読み込みます。
  3. クエリー文字列からルックアップ値を取得して、それを使ってDblookupを実行します。
  4. JavaScriptを使って次のキーワード・リストを作成するか、Dblookupに基づいてフィールドに値を設定します。
次回は、エージェントを使ってキーワード・リストを作成する方法を紹介します。最終的には、リレーショナル・データベースにアクセスしてキーワード・リストを作成する方法について検討します。



著者について
Mark Pollyは、Meritage Technologies, Inc.のテクニカル・アーキテクトです。Meritageは、従業員所有の技術コンサルティング会社であり、Global 3500の企業や公共部門の組織に専門的サービスを提供しています。Lotus Notes認定開発者であるMark Pollyは、Release 1のときからLotus Notesに携わっており、1996年以降さまざまな企業に対して、Notes、Domino、およびその他の技術プロジェクトのコンサルティングを行ってきました。
 
上に戻る