はじめに

データベースにMySQLなど、PHPのPDOに対応したものを利用することを想定します。データベースが稼働しており、INTER-Mediatorがインストールされている状況であるとします。このとき、以下の2つのファイルを作成します。

  • ブラウザにロードするHTMLファイル(「ページファイル」と名付けます)
  • データベース接続など設定を記述したPHPファイル(「定義ファイル」と名付けます

定義ファイルの記述

定義ファイルは、PHPのファイルにします。したがって、PHPの処理が可能なサーバーに配置しないといけません。定義ファイルでは、以下のように、INTER-Mediator.phpを読み込み、IM_Entry関数をコールします。この関数の引数の指定方法は、後で記述します。サンプルで言えば、sample_form_FMS_include.phpやsample_form_MySQL_include.phpなどのファイルが、定義ファイルに相当します。定義ファイルに記述できる内容はこちら のページにまとめてあります。定義ファイルについては、『定義ファイルの詳細』もご覧ください。

<?php
require_once ('INTER-Mediator/INTER-Mediator.php');
IM_Entry( $tableDefs, $optionDefs, $dbDefs, true );
?>

ページファイルの記述

ページファイルでは、定義ファイルを、ヘッダエリアのscriptタグで読み込みます。定義ファイルは、JavaScriptのソースを返します。サンプルで言えば、sample_form_FMS.htmlや、sample_form_MySQL.htmlのファイルが、ページファイルに相当します。

<html>
<head>
<script src="sample_form_MySQL_include.php"></script>
</head>
<body>
                :                
<td><input type="text" data-im="contact@datetime"/></td>

以上の準備をすれば、ページファイル内のタグのdata-im属性に記述を加えることで、そのタグの値や他の属性に対してデータベースから取り出したデータが設定されることになります。属性の値は「contact@datetime」といった記述を行います。この記述を「ターゲット指定」と呼ぶ事にします。また、ターゲット指定のあるタグのことを「リンクノード」と呼びます。ターゲット指定の詳細は、後で説明をします。

ページの表示

以上のような準備をした上で、ブラウザより、ページファイルにアクセスをします。そうすれば、リンクノードのターゲット指定や、定義ファイルでの指定に基づいて、データベースのデータを取り込んでページを構成します。データベースの内容を表示しますが、複数のレコードがあれば繰り返して一覧表示などを行います。

INTER-MediatorによるWebページ生成

INTER-Mediatorは、WebページのDOM構造をたどり、データベースとリンクするノード(以後「リンクノード」と記述)をさがします。そして、そのリンクノードの上位のノードをたどり、「エンクロージャ」と「リピータ」となるノードを探します。リピータ自身あるいはリピータに含まれるリンクノードをすべて集めてデータベースにアクセスします。そして、レコードの数だけリピータを繰り返して、データベースの内容をページに表示します。

リンクノードでのターゲット指定

  • 任意の要素をリンクノードにすることができます。
  • data-im属性に「table@field@target」の記述で記載されいているものをリンクノードとみなします。現在はこの記述方法が推奨されます。
  • 複数の設定を行う場合、値には「table@field@target table@field@target...」のように空白で区切って記述します。

ターゲット指定について

「table@field@target」がひとまとまりのターゲット指定となります。

  • tableはテーブル名を記述します。IM_Entry関数の第一引数に指定した配列のname属性の値を記述できます。
  • fieldはフィールド名を指定します。IM_Entry関数の第一引数に指定した配列の中で、name属性に対応したテーブルアクセスの中にフィールドが含まれていれば、そのフィールドの値を利用して、リンクノードの値を変更あるいは設定します。
  • targetはノードのどの属性にフィールド値を差し込むかを指定します。

targetの指定は以下のようなルールになります。

  • 省略すると、ノードの値として設定します。
  • 「innerHTML」の場合は、ノードのinnerHTML属性にフィールドの値を設定します。
  • 「nodeText」の場合はテキストノードを作成して子ノードとして追加します。
  • 「style.STYLENAME」の場合は、STYLENAMEで指定したスタイルに値として追加します。たとえば、「style.backgroundColor」は背景色のスタイル属性に値を指定します。
  • targetの最初の文字が「#」の場合、innerHTMLないしは属性を指定していれば、既存のノードのデータに追加します。
  • targetの最初の文字が「$」の場合、既存のノードのデータに含まれる$の部分を、データベースのフィールドの値に置き換えます。

エンクロージャとリピータ

エンクロージャとリピータとなり得るノードの組み合わせを以下の表に示します。

形態 Enclosure Repeater Linked Element
TBODY TR any elements
番号リスト OL LI LI itself or inside of LI elements
箇条書き UL LI LI itself or inside of LI elements
ポップアップ、リスト SELECT OPTION OPTION itself
汎用 data-im-control="enclosure"の指定があるタグ data-im-control="repeater"の指定があるタグ any elements

テーブルの場合で説明します。たとえば、テーブルのあるセル、つまりTDタグで囲まれた中に、DIVタグ等で記述されたリンクノードがあったとします。そのリンクノードから上位のノードにたどって、TRをリピータとします。TRの1つ上位のノードはTBODYに必ずなります。そのTBODYがエンクロージャとなります。リンクノードに記述された情報からテーブルがわかり、そのテーブルへアクセスします。そして、レコードの値をリンクノードの定義に従って、ノードに反映されます。もし、レコードが複数あれば、リピータを複製して、その複製した一連のノードに対してリンクノードの処理を行います。ページファイルを作るときは、通常、TRタグによる要素が1つのテーブルを作りますが、レコードの数だけ行数が増えるということになります。なお、リピータとなるTRタグの要素は複数個あってもかまいません。レコードの数だけ複数のTRのセットが複製されて、データの反映が行われます。

Ver.5.3-devの段階で、任意のタグについて、data-im-control属性を指定することで、エンクロージャーやリピーターになることできるように機能を拡張しました。つまり、TBOD/TR、OL/LI、UL/LI、SELECT/OPTIONについては、属性の指定がなく、リンクノードが含まれていればエンクロージャー/リピーターとして機能します。それ以外のタグの組み合わせについては、data-im-control属性を指定します。なお、エンクロージャーの直下の子要素としてリピーターを記述する必要があります。

レコードがない場合の表示

レコードがあれば、リピーターを複製していくつかのオブジェクトがページに見えますが、そのままだと、レコードがない場合、リピーターが全くない状態になってしまいます。そこで、リピーターの1つのdata-im-control属性を「noresult」にするか、あるいはclass属性を「_im_for_noresult_」とします。すると、このリピータはレコードが存在すれば単に消しさられますが、レコードがないときにはこのリピータが1つだけエンクロージャーの中に配置されます。「レコードがありません」などの記述をこの方法で組み込めます。

エンクロージャやリピーターの動作をキャンセルする

リンクノードを含むテーブルは、自動的に展開してしまいます。その展開をさせないようにするには、data-im-control属性の値を「ignore_enc_rep」とします。たとえば、1つのテーブルの中に複数のコンテキストからのフィールドを展開したい場合は、次のように記述して、TRをリピータとして認識しないようにします。

<table>
<tr data-im-control="ignore_enc_rep">
    <td>
        <span data-im-control="enclosure">
            <span data-im-control="repeater">
                <input data-im="context1@field1" />
            </span>
        </span>
    </td> 
</tr>
<tr data-im-control="ignore_enc_rep">
    <td>
        <span data-im-control="enclosure">
            <span data-im-control="repeater">
                <input data-im="context2@field2" />
            </span>
        </span>
    </td>
</tr>
</table>

特殊なリピーター

data-im-control属性が「header」「separator」「footer」のタグ要素も指定できます。headerに続いて、レコードの数だけリピーターが繰り返されますが、リピーターの間にはseprartorのタグ要素が付加され、最後にfooterのタグ要素が表示されます。

更新しないHTML要素

HTMLのフォーム要素では、ターゲット指定があれば、フィールドの値を表示するとともに、通常はその値を変更すると、変更結果をデータベースに更新して上書きします。しかしながら、その要素にdata-im-control="unbind"という属性を記述すれば、フィールドの値は表示しますが、更新は行いません。データベースの中身を要素に反映させたいけど、後の処理は独自にJavaScript等で記述したいときにこの方法が使えます。

検索や並べ替えの動作と指定

INTER-Mediatorは、検索に関して以下の3つの設定個所があります。あるいは、以下のような検索条件が付与されて、データベースの読み出しが行われます。

  1. 定義ファイルのコンテキストの中のqueryの設定
  2. INTERMediatorオブジェクトのadditionalConditionプロパティ(JavaScript)
  3. リレーションによって決まる外部キーと対応キーとの対応(定義ファイルのコンテキストの中のrelationの設定)

定義ファイルのqueryでの設定は、「常に適用されたい検索条件」を与えるのに便利です。たとえば、あるフィールドの値が「3」のものだけをいつも選択するとか、消し込みのフィールドがあって消し込まれていないレコードだけをとってくるというような場合です。

一方、ユーザが入力した検索条件のようなデータは、INTERMediatorオブジェクトのadditionalConditionプロパティを使って指定ができます。テキストフィールドに入力したテキストやあるいは計算結果などを検索条件に与えたい場合は、この方法で指定をします。

そして、リレーションは、エンクロージャーとリピーターによる展開中に、さらに内包するエンクロージャーとリピーターが見つかったとき、内側のコンテキストのrelation設定を参照して、外側のレコードに対応した、つまり関連のあるレコードを取り出すための条件を与えます。

これら3つの条件は、無条件にANDで合成されます。

コンテキストのqueryの指定方法

定義ファイルのコンテキストのqueryは、キーとして、field、operator、valueを持つ配列を指定します。その指定を複数できるので、結果として、queryキーに対する値は配列の配列となります。

PDO対応のデータベースアクセスクラスを利用すると、単に「field operator 'value'」という形式での式が構築されます。値についてはquoteメソッドで処理をしてあります。従って、array('field'=>'age', 'operator'=>'>', 'value'=>'19') のような指定が一例です。文字列のワイルドカードを使う場合には、データベースエンジンに従った記述が必要です。たとえば、MySQLで前方一致させるには、array('field'=>'name','operator'=>'LIKE', 'value'=>'%田太郎') のような配列を指定します。operatorを省略すると、= とみなします。

'field' の値が '__operation__' の項目があれば、そこで区切りを入れます。そして区切りで分割したそれぞれについて、AND条件が適用された式が作られ、区切りで分割された固まりについてはOR演算となります。また、'field' の値が'__operation__' の項目の 'operator' が 'ex'なら、ORとANDを入れ替えます。'field' の値が'__operation__' の項目はいくつあってもかまいません。

'query' => array(
    array( 'field'=>'age', 'operator'=>'>', 'value'=>'19' ),
    array( 'field'=>'year', 'operator'=>'>', 'value'=>'1980' ))
生成される条件文:age > '19' AND year > '1980'
'query' => array(
    array( 'field'=>'age', 'operator'=>'>', 'value'=>'19' ),
    array( 'field'=>'year', 'operator'=>'>', 'value'=>'1980' ),
    array( 'field'=>'__operation__' ),
    array( 'field'=>'age', 'operator'=>'<', 'value'=>'39' ),
    array( 'field'=>'year', 'operator'=>'<', 'value'=>'2006' ))
生成される条件文:(age > '19' AND year > '1980') OR (age < '39' AND year < '2006')
'query' => array(
    array( 'field'=>'age', 'operator'=>'>', 'value'=>'19' ),
    array( 'field'=>'year', 'operator'=>'>', 'value'=>'1980' ),
    array( 'field'=>'__operation__', 'operator'=>'ex' ),
    array( 'field'=>'age', 'operator'=>'<', 'value'=>'39' ),
    array( 'field'=>'year', 'operator'=>'<', 'value'=>'2006' ))
生成される条件文:(age > '19' OR year > '1980') AND (age < '39' OR year <'2006')
'query' => array(
    array( 'field'=>'age', 'operator'=>'>', 'value'=>'19' ),
    array( 'field'=>'year', 'operator'=>'>', 'value'=>'1980' ),
    array( 'field'=>'__operation__', 'operator'=>'ex' ))
生成される条件文:age > '19' OR year > '1980'

つまり、2つ以上の設定があれば、それらはANDで結ばれます。もし、__operation__の設定があれば、そこを区切りとして1つの塊の中のいくつかの設定はANDで結合され、そして区切り部分にORを入れた条件式になります(論理和標準形)。__operation__の設定にexがあれば、全面的にANDとORが入れ替わります。1つの塊についてはORで結び、その塊をANDで結びます(論理積標準形)。__operation__はいくつあっても構いませんが、そのうち1つでもexがあれば、全面的にAND/ORが入れ替わります。つまり、exはあるかないかだけの設定で、位置は関係ありません。

なお、ANDとORの組み合わせしかできないのかと思われるかもしれませんが、すべての論理式が論理和標準形ないしは論理積標準形で表現できるという定理があるので、この仕様ですべての論理式が記述できると言えるかと思われます。ただし、標準形にすると条件式によっては冗長な感じになり、かえって見づらい場合もあるでしょう。その場合は、テーブルをもとにすることだけを考えず、適当な中間段階のビューを作るなどして、効率よく条件設定を行うことも検討してください。

FileMaker Serverの場合、FileMaker側の仕様の制限として、検索条件は全部ANDか全部ORかで結ぶしかできません。ANDとORを組み合わせることはできないのです。コンテキストのqueryキーの値、あるいはaddtionalConditionに「array('field'=>'__operation__', 'operator'=>'or')」を加えれば、OR演算を行います。この指定がなければAND演算になります。OR演算を指定した場合、外部キーの検索条件もORになってしまい、リレーションが正確にとれませんので、その点は十分に注意が必要です。

INTERMediatorオブジェクトのadditionalConditionプロパティに指定する検索条件

JavaScriptのプログラムで、INTERMediator.construct(true) を実行するよりも前に、例えば以下のようなプログラムを実行します。additionalConditionプロパティは配列で、最初のインデックスはコンテキスト名、つまり定義ファイルでのnameキーに対応する値を指定します。ただし、セッタを定義したプロパティであるため、値の設定には、INTERMediatorクラスのaddConditionメソッドを利用します。右辺の条件は、もちろん、該当するコンテキストにしか適用されません。オブジェクトの値については前のqueryについての説明とおおむね共通です。OR条件とAND条件がどちらも出てくるような条件も記述できます。条件が一組の場合はオブジェクトとして記述できます。2つ以上あるときはオブジェクトの配列として記述します。


INTERMediator.addCondition(コンテキスト名, {field:'age', operator:'>', value: 19});
INTERMediator.addCondition(コンテキスト名, [
    {field:'age', operator:'>', value: 19},
    {field:'year', operator:'>', value: 1999}
]);

コンテキストのrelationキーの値

こちらもqueryと同様、配列の配列という形式をとります。キーはqueryと違います。外側のエンクロージャー/リピータとその内側のエンクロージャー/リピーターがあるとします。外側はmaster、内側はdetailというコンテキスト名で定義されているとします。

array(
    array(
        'name' =>'master',
        'key' =>'id'
    ),
    array(
        'name' =>'detail',
        'relation' =>array(
            array( 'foreign-field' =>'master_id','join-field' =>'id', 'operator' =>'=' )
        )
    ), ....

外側のコンテキストの1レコードを処理すると、その内部にあるエンクロージャー/リピーターが見つかります。そのとき、コンテキスト名がdetailのrelationキーの値を参照します。そして、join-fieldキーについては、外側の1レコードに存在する値を取り出し、foreign-fieldキーの値とoperatorキーの値を使って検索条件を作ります。たとえば、外側のレコードのidフィールドの値が34だった場合、「master_id = '34'」という条件を作成し、AND条件として追加します。relationの配列は配列が複数あってもかまいません。その場合、すべての指定で生成される条件式のANDをとります。

なお、join-fieldの指定は必須です。不要と思われるかもしれませんが、必ずしも主キーとリンクしているとは限らないので指定は必須としました。

検索結果の並べ替えに関して

INTER-Mediatorは、検索結果の並べ替え関して以下の2つの設定個所があります。検索のクエリに対して、並べ替えの順序を決める基準となるフィールドを指定できます。

  1. 定義ファイルのコンテキストの中のsortの設定
  2. INTERMediatorオブジェクトのadditionalSortKeyプロパティ(JavaScript)

定義ファイルのsortでの設定は、常に適用されるソートキーです。一方、additionalSortKeyプロパティはプログラムで状況に応じて設定されるソートキーです。検索時にはこれらが合成されて、並べ替えを行います。優先順位は、additionalSortKeyプロパティの方が上位になります。また、それぞれの設定の中で、指定した順序で上位の並べ替えフィールドとなります。いずれも、配列の形式で指定をし、fieldとdirectionというキーを指定します。fieldキーに対する値は1つのフィールド名を指定します。directionに対する値はデータベースエンジンに従います。たとえば、MySQLだと、ASCあるいはDESCを指定しますが、FileMaker Serverはascendあるいはdescendを指定します。additionalSortKeyプロパティについては、addtionalConditionプロパティと同様、最初のインデックスはコンテキスト名を指定し、その後にオブジェクトあるいはオブジェクトの配列を指定します。

ページ移動ナビゲーションの構築

ページ移動のナビゲーションは、ページの中に、idが「IM_NAVIGATOR」のノードがあれば、そのノードの内容を置き換えてナビゲーションを作成します。「IM_NAVIGATOR」のidのノードがない場合には、ナビゲーションは表示されません。通常は、divタグの要素を「<div id="IM_NAVIGATOR"></div>」のように作っておくのがいいでしょう。

INTER-Mediator.constructメソッドは、ノードを見つけて自動的にページナビゲーションにしますが、それらの要素に以下のようなクラス設定をしています。つまり、ページで、これらのクラスに対してスタイルシートで定義を行えば、見栄えについては自由に設定ができます。

要素名.クラス名 設定先
.IM_NAV_panel ナビゲーションそのもの。つまり、idが「IM_NAVIGATOR」のノードに設定される
span.IM_NAV_info 文字情報を表示する部分に設定される
span.IM_NAV_button クリックできるボタンに対して設定される
span.IM_NAV_disabled クリックできないボタンに対して設定される

ナビゲーション領域の文言等は、INTERMediator.navigationLabelに配列を設定することで、任意に設定できます。配列のインデックスと対応する箇所は以下の表に示します。INTERMediator.navigationLabelに何も設定しない場合には、表の既定値が画面に見えます。

インデックス 設定対象 既定値 非表示
0 最初のレコードに戻る << インデックス0〜3
1 前のページに戻る < 無関係
2 次のページに進む > 無関係
3 最後のレコードに進む >> 無関係
4 レコード番号の直前 レコード番号 インデックス4〜7
5 レコード番号の範囲の間の文字列 - 無関係
6 レコード番号範囲と全レコード数の間の文字列 / 無関係
7 全レコード数の後の文字列 (空文字列) 無関係
8 更新ボタンの名称 更新 インデックス8
9 レコード作成などのボタンの表示の有無 作成や削除などレコード操作のボタン インデックス9
10 まとめ保存のボタン 保存 インデックス10
11 ログアウトボタンの名称 ログアウト インデックス11

INTERMediator.navigationLabelに指定する配列は12の要素を指定します。それぞれ、インデックスに要素が対応します。要素がnullだと既定値のままになります。文字列を指定すると、その文字列に置き換わります。インデックスが0、4,、8、9、10、11の要素に関しては、値をfalseにすると「非表示」の列に示したものが非表示になります。たとえば、以下の記述だと、更新ボタンのみが消えて他は既定とおりのものが表示されます。インデックス9の「レコード作成」などのボタンのカスタマイズは、コンテキスト定義にあるbutton-namesキーで行います。

INTERMediator.navigationLabel = [null, null, null, null, null, null, null, null, false];

HTMLのUIコンポーネントの扱い

テキストフィールド

INPUTタグ要素のtype属性がtextの場合、ターゲット指定の3つ目の指定は省略できます。その場合、value属性に値が設定されます。テキストを編集すれば、テキストフィールドの内容がデータベースに書き戻されます。書き戻しは、フォーカスを外した時や、あるいは入力してから5秒後に行われます。

テキストエリア

ターゲット指定の3つ目の指定は省略できます。すると、TEXTAREAタグ要素のテキストとして設定されます。テキストフィールドと同様、テキストを編集すれば、テキストフィールドの内容がデータベースに書き戻されます。書き戻しは、フォーカスを外した時や、あるいは入力してから5秒後に行われます。

ポップアップメニュー/リスト

SELECTタグの要素自体が値を持つコンポーネントです。SELECTタグ要素のターゲット指定の3つ目の項目を省略すると、SELECT要素の選択値として指定されます。また、OPTIONタグは決められたものでもかまいませんが、データベースからも値を設定できます。このとき、自動的に、SELECT/OPTIONタグがエンクロージャー/リピータとなります。OPTIONタグはSELECTタグ要素の選択値に対応するvalue属性と、実際にメニュー項目として見えるOPTIONタグ要素のテキストの2つの設定が必要になるでしょう。従って、「<option data-im="contact_way@id@value contact_way@name"></option>」のようなターゲット指定が2つあるようなタグ要素をSELECTの中に1つだけ作っておき、ターゲット指定の1つ目の名前のコンテキスト定義を定義ファイルに記述しておきます。

チェックボックス

データベースから読み出された特定のフィールドのデータがチェックボックスのINPUTタグ要素とリンクされている場合、そのタグのvalue属性を調べます。そして、データとvalue属性が一致していればチェックを入れます。データの有無ではなく、valueとの一致を調べます。また、書き戻す場合は、チェックが入ったときはvalue属性の値、チェックがなくなった場合には空文字列を書き戻します。通常、数値フィールドで、1ならチェックあり、それ以外ならチェックなしといったデータの持たせ方をするのが順当でしょう。

ラジオボタン

ラジオボタンに展開したい場合、同一のターゲット指定のINPUTタグでtype属性が「radio」のものを並べます。すると、name属性を自動的に設定し、複数レコードが繰り返されたときでも、問題なく処理できるようになります。それぞれのINPUTタグ要素のvalue属性はおのおのが自分の値を持ちます。データベースのフィールドの値とvalue属性の値を比べて同一のものが選択されます。

入力フォーム型ページの作成

アンケートの回答のような、入力フォームがあってその内容に従った新規レコードを作るだけのようなページの作り方をここで説明します。そのようなページを作るのに必要なことは以下の通りです。

  • HTMLでフォームを作るが、FORMタグは不要。必要なテキストフィールドと、登録ボタンを作成する。ただし、テキストフィールドなどは、1つのエンクロージャにまとめておく。
  • 定義ファイルに、レコードの作成が可能なコンテキストを定義する。
  • 入力フォームにしたいエンクロージャのdata-im-control属性を「post」とする。
  • HTMLのフォームの入力要素をリンクノードにします。つまり、コンテキストの名前(context)と対応するテーブルのフィールド名(field)に対して、data-im="context@field" をタグの中に記述する。
  • 「登録」ボタンはBUTTONタグで作成し、data-im-control属性に「post」を指定する。ボタン名は任意。

登録ボタンは、テーブルのヘッダやフッタに配置することもできます。登録ボタンを押した後の動作については、コンテキストに定義できる「post-」で始まる3つの項目が用意されています。ボタンを何度も押す事を避けるために、ボタンをメッセージで置き換えたり、別のページに移動したり、ページの再描画ができます。コンテキストに指定したバリデーションの設定についても機能します。

この機能を使う場合、data-im-control属性に「post」を指定したエンクロージャーの外部にあるエンクロージャーに対しては、普通にページ合成ができるので、データベースアクセスの結果と、入力フォームを混在させることもできます。また、入力フォームの内部のエンクロージャーも同様に通常通り処理されるので、マスターの内容からポップアップを構築する事ができます。

登録ボタンをクリックした後に独自のプログラムを追加したい場合は、以下のような記述の関数を定義します。メッセージ表示、ページ再合成、ページ移動が定義されていた場合、それらよりも前に、以下に定義した関数を実行します。processingBeforePostOnlyContextは、データベースへの書き込み前に実施され、返り値がfalseだとデータベース処理を行わず、ページ移動なども行いません。processingAfterPostOnlyContextはデータベース処理後に実行され、返り値は指定しません。

INTERMediatorOnPage.processingBeforePostOnlyContext = function(node){
            // any program here.
};
INTERMediatorOnPage.processingAfterPostOnlyContext = function(node){
// any program here.
};

ブラウザのバージョンを調べる仕組み

ブラウザのバージョンを調べて、一定のもの以外は表示できないようにしたいと思うこともあります。この機能を、必要に応じて利用できるようにしました。

まず、INTER-Mediator.phpと同じディレクトリにある$paramsファイルに、変数名$browserCompatibilityという変数を定義し、配列記述します。配列の記述方法は表に示します。作成例も紹介します。。

次元 指定内容 指定する値の例
第1次元 ブラウザの種類 msie, firefox, safari, chrome, opera
第2次元 配列(OSを示すキー) mac, win
バージョン記述文字列 3+, 4-
第3次元 バージョン記述文字列(第2次元が配列のとき) 3+, 4-
$browserCompatibility = array(
    'chrome' =>'1+',
    'msie' =>'7+',
    'firefox' =>'2+',
    'safari' =>array( 'win' =>'4+', 'mac' =>'3+' ),
    'opera' =>'1+',
);

「バージョン記述文字列」は、数字とプラスないしはマイナスで指定します。「3+」は3以上、「3-」は3以下のバージョンで利用できることを示します。プラスあるいはマイナスを付けないと、その数値のバージョンのみです。ブラウザ名やOSは、大文字小文字は関係ありません。

前の例だと、Safariのみ、OSごとに分岐しています。WindowsならVer.4以上、MacならVer.3以上は利用可能であることを示しています。

ブラウザの互換性をメッセージとして表示する

JavaScriptベースで動くINTER-Mediatorにとって、これがいちばん難しい仕事かもしれません。ブラウザによっては、JavaScriptが動かないこともあるかもしれないのです。こうした状況をうまく処理するために、以下のような点を考慮します。

  1. ページファイルの中の、bodyタグ要素の直下あたりに、INTER-Mediatorが一切しない場合のメッセージを付けておく。たとえば、サンプルファイルの「WebSite」のindex.htmlにあるid=nonsupportedmessageのdivタグ要素。INTER-Mediatorの動作が成功すれば、このノードを削除するか表示しないようにする。これにより、JavaScriptが一切動かない状態でも、何らかのメッセージが見えるようになる。
  2. ページファイルの構築を以下のようなプログラムにする。INTERMediatorCheckBrowser関数で前に説明した$paramsファイルの変数の定義に従って、ブラウザの互換性をチェックする。もし、対応でないならfalseを返すので、ページ構築はしない。また、その場合は、body要素の中身をいちど全部クリアして、メッセージだけを表示する。もし、対応しているならnodeで示したノードを削除する。nodeはnullあるいは未指定でも構わない。

上記の2つのうち、一方だけでもかまいませんし、両方をやってもかまいません。また、チェックは不要ということなら、単にINTERMediator.construct(true);を呼び出すだけでもいいでしょう。

<!DOCTYPE html>
<html>
    <head>
        <meta http-equiv="content-type" content="text/html;charset=UTF-8"/>
        <title>Page Title</title>
        <script type="text/javascript" src="context.php"></script>
        <script type="text/javascript">
            INTERMediatorOnPage.doAfterConstruct = function () {
                var contentNode = document.getElementById('container');
                contentNode.style.display = "block" 
            }
        </script>
    </head>
    <body>
        <div id="nonsupportmessage" style="background-color:#333333">
            <div style="text-align:center;color:yellow">
                If you see this, you must use any unsupported web browser. Or constructing the page.
            </div>
            <div style="text-align:center;color:yellow">
                この表示が見えている場合、描画処理中です。しばらくお待ちください。長時間見えている場合は、非対応ブラウザで参照しています。
            </div>
        </div>
        <div id="container" style="display: none">
            // ページコンテンツ
        </div>
    </body>
</html>