FileMakerで作るメディア管理のサムネイルタイルビュー。第三回、 今回 javascript を使います。あとリレーションをひとつ作成してようやく少し実用に近づきます。
メディア管理でサムネイルのタイルビューを実現するためにテストファイルを作成してチクチク育てています。
今回その3では、操作に対するフィードバックを返したり、タイル上で選択したレコードの情報を表示するなど、実用に近づく措置を施しました。
このテストファイルをダウンロードできます。
Download
tileview_test_3.fmp12.zip
タイルビューテストその3の機能
今回テストファイルその3では、次の機能を搭載しました。
レイアウトにレコード情報を配置
タイルビューレイアウトの右側に個別レコードの情報スペースを設けました。
Webビューア内でタイルをクリックすることで右側スペースにそのレコードが表示されます。FileMakerの通常のレイアウトでは当たり前の挙動ですが、タイルビューレイアウトでも可能となりました。
「クリックされたそれは、それ自身と同一である」という宇宙真理的アイデンティティの哲学的事象を実現する画期的な出来事ですね。
Active – Webビューアからレコードを特定
通常レイアウト(list view)ではセルフポータルの行をクリックするとそのレコードに移動します。クリックされたそれはそのレコード自身と同一であり、アクティブレコードと認識されると同時にレコード移動します。
WebビューアはHTMLを表示しているだけなので、クリックしたところで FileMaker のレコードと何の関係もありません。通常と同じような挙動のためには、アクティブレコードみたいな振る舞いをさせる必要があります。
ここだけ今だけ自分だけ、それを「アクティブ化」あるいは「アクティブ機能」あるいは「疑似アクティブ」と呼ぶことにします。
アクティブ機能により、普通のレイアウトで当たり前の挙動をWebビューアで実現できます。
ダブルクリックでプレビュー
前回その2では “preview” というリンクテキストをクリックしてプレビューを表示しました。とても不自然でしたね。今回はより自然に、サムネのダブルクリックで実現しました。
ダブルクリックで開き、ダブルクリックで閉じます。
Select – チェックして選択
一般の画像管理アプリではシフトキーやコマンドキーを押しながらタイルをクリックすると複数の選択ができます。ここではそれは出来ませんので、代わりにセレクトのチェックボックを入れました。チェックすることで複数選択を代替します。
Webビューアでチェックすれば見栄えが少し変わり、現在選択中であることをフィードバックします。そしてもちろんチェックしたことをFileMakerに伝えています。
逆に、右側のレコード表示部分から(つまりFileMakerから) select の操作を行えば、Webビューアにすぐに反映されます。
この双方向の挙動こそが javascript を使う恩恵です。
次に仕組み編に行きますが、その前にここの筆者から言い訳があります。
筆者からの言い訳
前回タイルテストその2 ではURLスキーマを使った操作を行いました。 HTMLしか知らない素人にとって理解しやすいやり方でした。しかし、Webビューア → FMスクリプト という一方通行の対話にすぎず、Webビューアへの対話ができませんし見栄えのフィードバックもhoverくらいしか返せません。
javascript を使うと Webビューア ↔ FileMaker の双方向のやり取りが可能になるし、操作に対するフィードバック(スタイルの変更)も即時に行えます。
タイルビューを実用に近づけるためには javascript の使用は必須です。しかし問題がありました。ここの筆者が javascript をさっぱりわからないことです。
そこで、筆者はその2を書いた直後に一夜漬けで javascript を学び、その3に挑みました。
ここに書いている javascript について、過度の信用は禁物です。また、出来の悪いコードを嘲り罵ることも避けましょう。コードの出来の悪さに気づいたら、優しく教えてくれることが望ましいです。
仕組みの概要
何をしたか、何を利用したか、ざっくり概要です。
セルフリレーションを追加
Webビューアの横にレコード詳細のスペースを設けたレイアウトについてです。
まず GLB_id というフィールドを追加しました。これはグローバルなフィールドです。
リレーションではテーブルオカレンスを複製し、GLB_id と ID を繋げました。
GLB_id に ID を転記するとリレーションが成立し、mainData_id テーブルでただ一つのレコードが特定されます。レイアウトの右側に表示しているのは、実は mainData_id テーブルのポータルでした。
FileMaker.PerforemScript
FileMaker v19から javascript を標準で使えるようになり、二つのできることが追加されました。FileMaker.PerformScript は、WebビューアからFileMakerスクリプトを実行せよと命じます。
構文は FileMaker.PerformScript( 'スクリプト名' , 引数 )
です。
前回使ったURLスキーマもFIleMakerスクリプトを引数付きで実行できました。同じです。ですが、URLスキーマではできない処理を関数の中で追加していけるのでこっちが有利です。前回張り切って作ったURLスキーマですが、今回はすべてFileMaker.PerformScript で置き換えました。
Webビューアでjavascriptを実行
FileMaker v19から javascript を標準で使えるようになり、二つのできることが追加されました。スクリプトステップ Webビューアでjavascriptを実行 は、FileMakerからWebビューアの関数を実行せよと命じます。
このスクリプトステップでは、引数をいくつでもくっ付けることができます。
オブジェクト名は、Webビューアのオブジェクト名、関数名に動かしたい関数名を書き、引数を追加していきます。
FileMaker.PerformScript と Webビューアでjavascriptを実行 によって、FileMaker ↔ Webビューア 双方向のやり取りが可能となりました。
元々 javascript にはスタイルを即時変更できる機能もあるので、やり取りのフィードバックをスタイルの変更で見せることができます。
では、具体的に機能の詳細を解説していきます。
解説 – Active
WebビューアからクリックするとそのレコードのIDが記録され、擬似的にアクティブレコードのような振る舞いをします。
この”アクティブ機能”には二つの動作が含まれます。
- Webビューア内のクリックでレコードを特定する
- 取得した ID を GLB_id に転記する
- クリックされたらフィードバックして見栄えを変える
あ。三つだったか。三つ目はWebビューアの挙動です。
1 Webビューア内のクリックでレコードを特定する
1 Webビューア内のクリックでレコードを特定するは、具体的には ID を取得します。どうやってIDを取得するかというと、テンプレートの構造と javascript によってです。
SngleContentテンプレート
レコード単位のHTML(contentフィールド)を作るためのテンプレート singleContent_template があります。構造や、一部ちょっとした javascript が書かれています。
レコード毎のHTMLでは、全体を <article></article> で囲っています。このタグの中に javascript をひとつ仕込みました。
<article onClick='jsActive(<!-- ID -->);'>
(実際には article に id や class もありますが省略しています)
onclick=jsActive(ID)
onclick=関数 は「クリックしたら関数〜を実行してね」です。
ここでは、関数 “jsActive”を実行してね、引数はIDでね。になります。
(テンプレートの<!-- ID -->
はHTMLに変換される時点で実際のIDで置換されています)
関数 jsActive
関数 jsActive を実行してねと命じた以上、jsActive という関数を作っとかないといけません。作りましょう。
HTMLテンプレートでは</body>の直前にスクリプトを配置することになっています。そして開発用に script フィールドがあって、そこに書いていけば置換計算で最終HTMLになるという案配です。
jsActive は二段構えになっていますが、今はそのうち1個だけ説明します。
function jsActive(value){ FileMaker.PerformScript( 'Active', value ); }
function で宣言して jsActive(value) を作ります。
上の onClick='jsActive(<!-- ID -
->);'
の通り、引数に ID を渡していますから value は実際の ID です。
関数部分は、FileMaker.PerformScript( ‘Active’ , value )ということで、「Active というFileMakerのスクリプトを実行してね。引数はIDだよ」と命じています。
2 取得した ID を GLB_id に転記する
スクリプト Active
FileMaker.PerformScript( ‘Active’ , ID )で実行してねと命じた以上、スクリプト Active を作っておきましょう。
基本かつ要の行為、GLB_id に ID を転記する を行います。すでに ID をスクリプト引数で受け取っていますから、一旦変数 $id に入れて GLB_id フィールドに記載します。たったこれだけです。リレーションを組んでいますから、これだけを行えばセルフテーブルで一つのレコードが特定されます。
フィールド設定 [ mainData::GLB_id ; $id ]
これだけでもいいのですが、汎用性を高めるために $id の値を得るための条件分岐しておきます。
if [ isEmpty ( Get ( スクリプト引数 ) ) ] 変数を設定 [ $id ; 値: mainData::ID ] else 変数を設定 [ $id ; 値: Get ( スクリプト引数 ) ] end if フィールド設定 [ mainData::GLB_id ; $id ]
スクリプト引数がない場合にも対処しておきます。スクリプト引数があればそれを、なければ現在レコードのIDを $id にセットします。
これがスクリプト Active で、「それはこれだよ」を実現する最初のステップです。今後レコード操作のほとんどのスクリプトで最初に使用されることになります。
さて、以上が基本的なアクティブ機能ですが、続きがあります。
Webビューアでクリックして疑似アクティブレコードになった<article></article>に対して、アクティブであることを見た目で表現します。
3 クリックされたらフィードバックして見栄えを変える
関数 jsActive 後半
javascript ではスタイルを変更したり class を付けたり外したり、それを即時に反映させることができます。ここでは class の変更で対処しようと思います。
これをもう一度ご覧ください。クリックして疑似アクティブ化したタイル部分に薄藤色の背景色が付いています。
classList
class を付けたり外したりするのは javascript では classList です。追加なら エレメント.classList.add(‘クラス名’) です。削除なら classList.remove、トグル.toggle もあります。
さて、疑似アクティブ化した <article> にクラスを付けたり外したりするわけですが、「クリックした <article> に class=”active”を追加し、それ以外のすべてから”active”を削除する」ということをやる必要があります。アクティブレコードは常にただ一つだから。
関数「jsActive」の説明で「jsActive は二段構えになっていますが」と書いたとおり、割愛した二段目の記述があります。Webビューアのフィードバックを表現する部分です。
function jsActive(value){ // FMスクリプトActiveを実行 FileMaker.PerformScript( 'Active', value ); // クリックした要素にclassを追加し、それ以外から削除する const items = document.getElementsByClassName('content'); for (let i = 0; i < items.length; i++) { items[i].addEventListener('click', function () { // クリックされた要素に 'active' クラスを追加 this.classList.add('active'); // 他の要素から 'active' クラスを削除 for (let j = 0; j < items.length; j++) { if (j !== i) { items[j].classList.remove('active'); } } }); } };
難しすぎて、ChatGPT のお世話になってしまいました。
クリックした要素を見つけるのにループ、クリックした要素以外を見つけるのにループをしています。
一応期待通りの動きをしてくれましたが、あまり納得していないんですよ。なんかちょっと思ってたのと違うというか。多分原因はこちらの目的を明確にしきれてなかったんですね。最初のクリックした要素を見つけるのにループなんかせずByIdでいいんちゃうの?とか、いろいろ改良の余地ありそうですが今のところはこれで。
以上、疑似アクティブ機能についての詳細な解説でした。
解説 – Select
複数アイテムを選択することを代替するセレクト機能の実態は、フィールド「select」に 1 を入れたり外したりする行為です。
上図は通常のメインテーブルのレイアウトです。select フィールドに1や0が入っているのが確認できますね。1なら選択しているという設定です。
実際の運用ではトグルボタンを用意して見た目を整えたりします。select=1ならボタンに色を付けて選択中を表現することも簡単。そう、FileMakerならね。何を言ってるんだか。いや、まじで FileMaker のグラフィック機能の簡単さは素晴らしいと思うんですよ。
普通のレイアウト上では簡単にこういうことが出来ますが、これをWebビューアでも実現したい。
しました。チェックを入れるとselectに 1 が入り、枠が付きます。
動作を分解するとこういうことをしています。
- Webビューアのチェック操作で select フィールドに1か0を入れる
- Webビューアのチェック状態をスタイルに反映
そしてもう一つ別の動きも作りました。FileMaker側での操作をWebビューアに反映させます。
- FileMaker からSelect ONOFF 操作をWebビューアに反映させる
1. Webビューアからのチェック操作で select に 1か0
レコード単位の構造を作る singleContent_template に input タグを追加しました。
<input type="checkbox" />
この中に小さな js を挟み込みます。 Active と同じ、onclick です。
<input type="checkbox" onClick="jsSelect('<!-- ID -->');" />
ほんとうはもうちょっと複雑で、正直に書くとテンプレートの該当部分はこうです。
<input type="checkbox" id="C<!-- ID -->" onClick="jsSelect('<!-- ID -->');" <!-- checked --> />
やや枝葉ですが先に説明を済ませておきますね。
id="C<!-- ID -->"
は、この input タグにIDを設定しています。C+レコードID をセットしたので Cxxx という形になります。
<!-- checked -->
は、HTML作成時のデフォルト用で、select フィールドが 1 なら “checked” の文字が入るようにしています。
onclick=jsSelect(ID)
そして、onClick="jsSelect('<!-- ID -->');"
が関数を実行させます。
クリックされたら関数 jsSelect を実行してね、IDを引数にね。と命じています。input 内に書きましたが、単にクリックに反応させているだけです。
関数 jsSelect
関数 jsSelect を実行してねと命じた以上、jsSelect という関数を作っておかねばなりません。
scriptフィールドに新たに jsSelect を記述します。
function jsSelect( value ){
// FMスクリプトを実行
let script = 'Select' ;
FileMaker.PerformScript( script, value );
};
この関数、本当は二段構えになっていますが今は前半だけ書いています。アクティブの時と同じく、FileMaker.PerformScript でスクリプト Select を実行してねと命じています。
FMスクリプト Select
スクリプト Select を実行してねと命じた以上、スクリプト Select を作っておきます。
このスクリプトも本当はもう少し先があるのですが、ここでは前半まで。ご覧の通り、最後の一行以外は「Active」そのものです。まずアクティブありき、そんで、最後に select フィールドに 1 を入れたり外したりしています(トグル)
2. Webビューアのチェック状態をスタイルに反映
チェックボックスのオンオフ操作に対するフィードバックをスタイルに反映させましょう。javascript では classList で class を付けたり外したりできます。
テンプレート singleContent_template では、<article> に content というクラスが割り当てあられています。
<article id="ID-XX" class="content">
select にチェックを入れたら select というクラスを追加したり外したりすることにしましょう。
jsSelect の続き
jsSelect についての中で「本当は二段構えになっていますが」と書きました。続きの二段目をを含めて全部書くと本当はこうでした。
function jsSelect( value ){
// FMスクリプトを実行
let script = 'Select' ;
FileMaker.PerformScript( script, value );
// id 要素にクラス select を付けたり外したりする
let articleID = 'ID-' + value;
let content = document.getElementById( articleID );
content.classList.toggle('select') ;
};
Webビューアのスタイルを変更する部分です。
レコードのタイル<article>には、テンプレートで IDが仕込んであります。
<article id="ID-<!-- ID -->" class="content">
レコードのIDが 196 だとすると “ID-196” というのが article の ID 書式です。レコード各々の article に個別のIDが入ってますから、getElementById が使えます。IDを狙って直接 toggle でクラス “select” の付け外しができます。
3. FileMaker からSelect ONOFF 操作をWebビューアに反映させる
一方、タイルビューレイアウトに配置したレコード表示用のポータルがあります。このポータルからも当然 select オンオフ操作を行えますので、Webビューアにその結果を伝えたい。
最初に挙げたビデオをもう一度貼りますが、こういう挙動を実現します。
FileMaker → Webビューア 方向のアプローチです。
スクリプト Select の続き
FMスクリプトのSelectですが、こちらもさきほど「本当はもう少し先があるのですが」と書いたとおり続きがあります。
最初に条件分岐でポータルからの操作の場合に限っています。
次に selectフィールドの値を変数に仕舞っています。
そして FileMaker → Webビューア方向の指令、Webビューアでjavascriptを実行スクリプトステップの登場です。
Webビューアでjavascript ‘refSelect’ を実行
Webビューアでjavascriptを実行 ステップでは、Webビューア内に書かれた関数を実行させることができます。関数名と、必要に応じて引数を追加できます。
ここでは、refSelect という関数を実行してね。と命じています。引数として、レコードIDとselectフィールドの値をセットしています。
関数 refSelect
関数 refSelect を実行してね。と命じた以上、関数 refSelect を作っておきます。
この関数は、select の付け外しと input checkbok のチェックの付け外しを行います。FIleMakerのレコードに合わせることが目的ですので、 Webビューア主体でトグル動作の jsSelect とは別に用意しました。
// ポータルからのselectに応える function refSelect( id, select ) { // id 要素にクラス select を付けたり外したりする let articleID = 'ID-' + id; let cID = 'C' + id; let cont = document.getElementById( articleID ); let cBox = document.getElementById(cID); if( select == 1 ){ cont.classList.add('select') ; cBox.checked = true; }else { cont.classList.remove('select') ; cBox.checked = false; } };
refSelect( id, select ) … 引数が2個あるので、カンマで区切って受け取ってます。
articleのID と input type=”checkbox” のIDを作って、 getElementById でターゲットを特定、そして select が1であるかそうでないかで条件分岐して、
・クラス「select」 の追加または削除と、
・チェックボックスのチェックの付け外し
を操作します。
以上、セレクト機能の解説でした。
解説 – ダブルクリックプレビュー
前回その2で非常に不満だった 「リンクテキスト”preview”のクリックでシングルビュー(プレビュー)が開く」の動作を改善します。自然に、サムネのダブルクリックで開くようにしましょう。
javascript に「ダブルクリックしたら〜」の命令文がすでにあるので使います。onDblClick です。
onDblClick=関数名
と書いて関数を実行させます。
onDbleClick
テンプレート singleContent_template に書かれたサムネイル部分の構造はこうなってます。
<div class="thumbnail">
<!-- imgTag -->
</div>
divタグの中に onDblClick を仕込みます。
<div class="thumbnail" onDblClick="jsOpenSingleView('<!-- ID -->');">
<!-- imgTag -->
</div>
コメントアウト形式で書かれた部分は、最終的なHTMLで適切な値と置き換えられます。
onDblClick="jsOpenSingleView('<!-- ID -->');
は、
「ダブルクリックしたら関数 jsOpenSingleView(ID)を実行してね」と命じています。
関数 jsOpenSingleView()
jsOpenSingleView() を実行してね。と命じた以上、jsOpenSingleView という関数を作っておかねばなりません。
function jsOpenSingleView( value ){
let script = 'openSingleView' ;
FileMaker.PerformScript( script, value );
};
onDblClick=jsOpenSingleView(<!– ID –>); と書いた通り、レコードのIDがそのまま value に入った状態です。
そしてFileMaker.PerformScript で ‘openSingleView’ を実行してね、IDを引数につけとくから。と、命じています。
FMスクリプト openSingleView
実行してねと命じた以上、スクリプト openSingleViewを作っておきましょう。
opneSingleView は、プレビューを開くスクリプトです。
8行目まではすべてレコード操作の基礎「Active」そのものです。「クリックしたらそのレコードがアクティブ」これなしでは何も始まりません。
「プレビューで開く」を指定するのは最後の1行「関連レコードへ移動」です。関連の基礎となるテーブルをセルフテーブル( mainData_id )に指定しているので、検索せずとも該当レコードが勝手に開きます。
さらに、「関連レコードのみを表示」のチェックを外してますから対象レコードがそのまま生きている状態です。即ち、プレビュー画面のまま「前のレコード」「次のレコード」と、移動できます。
以上、ダブルクリックでプレビューでした。この機能には相互のやり取りとかスタイルの変更とか一切ありません。
以上、ダブルクリックでプレビューを開くの解説でした。
次の展開
今回、疑似アクティブを基本に、ダブルクリックとセレクトを実現しました。
次の展開ではリレーションを見直す事になると思います。現在のポータル配置は、Webビューア主体の疑似アクティブレコードただ一つを表示しているにすぎません。ポータルからレコード移動ができて、それをWebビューアに反映させる仕組みが欲しいところです。
ゆっくり考えます。
タイルビューのシリーズ、これまでの投稿こちら。
FileMakerでサムネイル画像のタイルビューを作った その1 ビューした
FileMakerでサムネイル画像のタイルビューを作った その2 クリックでプレビュー
この後の投稿はこちら
FileMakerでサムネイル画像のタイルビューを作った その4
FileMakerでサムネイル画像のタイルビューを作った その5
尚、タイルビューはメディア管理で使ってこそ意味あります。別件のメディア管理を育てるシリーズはこちら。