FileMakerWebDirectの独自ログインフォームでEnter/Returnキー処理の実装

去年 ( 2017 ) のアドベントカレンダーでは、割と手を抜いた記事 ( [FileMakerServerのAdminConsoleでfailed_to_load_the_bootstrap_javascriptエラー](https://qiita.com/Hi_Noguchi/items/af0c8e66ac4c0b1d87da) ) 一本だけにしてしまっていたので、今年はもうちょっと手の込んだものにします。


# 前書き
皆さん、 FileMaker WebDirect 使ってますでしょうか。使っていない方が多かったとしても、みんな使ってますよねーっていう前提で話を進めていきます！

WebDirect では、使えるスクリプトステップの種類・スクリプトトリガの種類が少なくて、「FileMaker Pro だったらこれくらいのこと簡単に実現できるのに～」と悔しく歯噛みする場面によく遭遇するのではないでしょうか。遭遇しなかったとしても、みんな遭遇しますよねーっていう前提で話を進めていきます！

今回は、以下のような機能を実装します。

* 独自に作成したログイン画面で、
* ID / PASSWORD を入力し、
* ID or PASSWORD のフォーム入力欄内で Enter/Return キーを押したときに、
* 下部に設置した login ボタンを押したものと同じ挙動を実現する。
* ただし、 ID or PASSWORD のいずれか片方が空欄である場合、空欄のフォーム欄へカーソルキーを移動させる。

実際の Web アプリケーションではよくあるものです。 login ボタンなんて押さずに、パスワードを入力し終えた流れで Enter/Return キーを押すものですよね。


# 完成形のデモ
では、まず、完成形のデモを Gif アニメーションで見てみましょう。

![done.gif](https://qiita-image-store.s3.amazonaws.com/0/37739/5a67b48f-5a41-6401-40e3-c36589e6bd1c.gif)

前書きに書いておいた想定通りのものであったと思います。といっても Gif だと、本当に Enter/Return キーを押したのかどうかはちょっと分かりづらいですが……まあ login ボタンは押していないですよね、ということで。

では、以下、実際の開発にあたっての内容に触れて参ります。


# 環境
* ​FileMaker Server 17 ( Windows Server 2016 )
* FileMaker Pro 17 ( Windows 10 Pro )


# 開発
## テーブルとフィールド

今回、デモ用に用意したテーブルとフィールドは以下の通りです。実際に全部のテーブルを使うことはないのですが……（ login_logs, user_logins は実運用するなら必要だよねということで作っただけ ）

### logins
* id
* created_at
* updated_at
* email
* password

### login_logs
* id
* created_at
* updated_at

### users
* id
* created_at
* updated_at
* name

### user_logins
* id
* created_at
* updated_at
* user_id
* login_id

### login_view
* g_email
* g_password

テーブル一覧と、代表して logins テーブルのフィールド一覧との、二種類のキャプチャ画像を置いておきます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/37739/69d2657f-90e1-e714-be8d-51a1f20d778b.png)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/37739/c038e30e-bdc3-ab5f-9599-bd4f277223d0.png)





## レイアウトモードで見てみる

まずは、レイアウトモードで見てみましょう。レイアウトテーマは「ユニバーサル」に設定しました。

### ログイン画面

ID, PASSWORD の入力画面です。 ID については、ここでは email とし、グローバルフィールドで g_email, g_password を設置しています。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/37739/6911eee1-28ea-1ce7-55e8-544aa233bc06.png)


### ログイン完了画面

ログインし終えたら、以下の画面に遷移してきます。ユーザーの情報が表示されるものです。何ということもない、シンプルなものですね。ログアウト機能などは今回のスコープ外としておきます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/37739/c86964d8-52d6-debe-babc-ebc5f0edcdd9.png)



## スクリプトを作成する
### ファイルが開かれた時に最初に走る処理
WebDirect なので、メニューバーとツールバーは隠してしまっておきたいですね。以下のようにします。細かい解説はしません。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/37739/84af565c-561e-b1c0-4318-9030efc3253a.png)
![image.png](https://qiita-image-store.s3.amazonaws.com/0/37739/6fd9c0f8-81d4-ba34-c5e3-f49dd0bcba34.png)


### ログイン処理
続いて login ボタンを押した時に走る処理を作ります。もちろん実際は本当にログイン処理が作られるべきなのですが、今回はこれもスコープ外にして、単にレイアウトを切り替えるだけ、という手抜きスクリプトにしておきます。

### Enter/Return キーがトリガになって実行される処理
最初に Enter/Return キーがトリガになって実行される処理を書いておきましょう。
要件は、

* ID / PASSWORD 両方のフィールドが空欄の場合……
    * ID フィールドへ移動
* ID のみが空欄の場合……
    * ID フィールドへ移動
* PASSWORD のみが空欄の場合……
    * PASSWORD フィールドへ移動
* ID / PASSWORD 両方のフィールドが入力されている場合……
    * ログイン処理の実行

ということになります。

これをそのままスクリプトに書き起こすと、

![image.png](https://qiita-image-store.s3.amazonaws.com/0/37739/1b57e3ad-f145-c647-2cf3-de1a799315ab.png)

のようになりますが、上から評価されるということを考えると、もっとシンプルにリファクタリングできます。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/37739/4edff4a5-bf75-83a8-e6af-52cd12d7ef6e.png)

とにかく g_email の値が空欄であれば、 g_email へ来てくれ、ということですね。


## スクリプトトリガを割り当てる
### WebDirect で動くスクリプトトリガ
いよいよここからが本題ですね。まず、WebDirect で動くスクリプトトリガの種類を見てみます。

[公式のスクリプトトリガリファレンスページ](https://fmhelp.filemaker.com/help/17/fmp/ja/index.html#page/FMP_Help%2Fscript-triggers-reference.html%23) から、今回、関係する OnObject*** 系のスクリプトトリガのサポートについてを表にまとめました。

種類 | サポート | 備考
--- | --- | ---
OnObjectEnter | 一部  | WebDirect では、Web ビューアに割り当てられた場合、このスクリプトトリガはアクティブになりません。
OnObjectKeystroke | いいえ | 
OnObjectModify | 一部 | WebDirect はフィールド内のキー操作をモニタするための OnObjectModify スクリプトトリガの使用をサポートしません。
OnObjectValidate | はい | 
OnObjectSave | はい | 
OnObjectExit | 一部 | WebDirect では、Web ビューアに割り当てられた場合、このスクリプトトリガはアクティブになりません。

これを見ると、Enter/Return キーを拾いやすく FileMakerPro であればこれを用いるであろうはずの OnObjectKyestroke が、何と残念なことに、サポート外ということが分かりました。

代わりのトリガを選ばなくてはなりませんが、いずれも Enter/Return キー判定ができそうにありません。

無理矢理にでもやるとすると Enter/Return キーが入力された ＝ 改行コードが入力された、と解釈して、フィールド内に改行コードが含まれていたら……という条件で判定するか？🤔

### インスペクタで「次のオブジェクトへの移動に使用するキー」を設定
ここで気がつく方もいらっしゃるかもしれません。そう。今の FileMaker では、「次のオブジェクトへの移動に使用するキー」のカスタマイズができるようになっているのです。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/37739/f4768613-434d-a459-a140-df89f7b4fc70.png)

レイアウトモードにして、 g_email, g_password それぞれのオブジェクトに対して、 Return, Enter にチェックをつけてあげましょう。すると Enter/Return キーで、お互いに移動し合うようになってくれます。

![enter.gif](https://qiita-image-store.s3.amazonaws.com/0/37739/9205e636-8f96-f091-123c-4932d66e98d6.gif)

つまり、フィールドに値が入力されて／されず、Enter/Return キーが押されたら、別のフィールドに移動するわけですから、そのタイミングでトリガが走ってくれれば良いわけですね。

### OnObjectValidate の設定
今回は OnObjectValidate を選びます。 OnObjectSave でなくて Validate を選んだのは、実運用上では、入力内容の Validation は当然おこないますよね（全角入力されたら半角へ強制置換するなど）という理由からです。

![image.png](https://qiita-image-store.s3.amazonaws.com/0/37739/40f766f4-7a6e-4ce4-eb7c-037177e2df3d.png)


### 完成

というわけで、完成です！　Enter/Return キーで、ログイン処理が走るようになりました。

![done.gif](https://qiita-image-store.s3.amazonaws.com/0/37739/5a67b48f-5a41-6401-40e3-c36589e6bd1c.gif)

動作はサクサクと軽く動いてくれます。フィールド内の改行コードを探し出して……とかやるより、よっぽど健全かなという印象です。

細かいことを言うと、この実装方式だと、正確には、画面内の関係ないところをどこタップしても処理が走るようになっているので login ボタンが有名無実化しています。このログイン画面では、シンプルに入力欄二つと login ボタンが置いてあるだけのレイアウトなのでそれでも問題ないですが、もうちょっと複雑なレイアウトだと、別の実装方式を検討しないとならないかもしれません。

一つのやり方として、ご参考まで。


## ……と思いきや、うまくいっていない点
一箇所、うまくいっていない点があります。それは、

* ID / PASSWORD 両方のフィールドが空欄の場合……
    * ID フィールドへ移動
* ID のみが空欄の場合……
    * ID フィールドへ移動
* PASSWORD のみが空欄の場合……
    * PASSWORD フィールドへ移動

の制御です。今回、スクリプト内の「フィールドへ移動」と「次のオブジェクトへの移動に使用するキー」とがかちあってしまって、片一方にしか値がない場合でもお互い行き来し続けてしまいます。

![enter_bug.gif](https://qiita-image-store.s3.amazonaws.com/0/37739/1f9c669c-b3a1-bf60-e398-bd6f12270175.gif)

本来、この状態だと、 password に居続けてくれないといけないのですが……
以下、試してみたことと、キャプチャの再掲。

* 1, 2 行目の変数設定において、グローバルフィールドの値は正しく取れている
* 5, 7 行目の「フィールドへ移動」の後に、「フィールド設定」でそれぞれに異なる値を入れてみると、正しく分岐できている
* 5, 7 行目の「フィールドへ移動」のオプションに「選択／実行」をつけても、ダメ
* Enter/Return キーを押すのではなく、カーソルをはずすことによって OnObjectValidate を走らせると、5, 7 行目の後に、勝手に「レコード確定」が走って、カーソルのフォーカスが外れる
* 念のためリファクタリング前のスクリプトでも試してみたけれど、ダメ

![image.png](https://qiita-image-store.s3.amazonaws.com/0/37739/4edff4a5-bf75-83a8-e6af-52cd12d7ef6e.png)

また、スクリプトトリガの種類を変えてみることについて、

* OnObjectSave に指定し直してみても、ダメ

でした。

ちょっと今回、アドベントカレンダーに間に合わせるための時間作りで限界なので、もう少し検証してみて、また後日記事修正か追記かしようかと思います。