コラボフローカスタマイズのすゝめ

[コラボフロー Advent Calendar 2022](https://qiita.com/advent-calendar/2022/collaboflow) 1日目の記事です！
コラボフローってなんぞや？って方は **[こちらのページ](https://www.collabo-style.co.jp/about/, "コラボフローについて")** をご参照ください！

---

昨年末に会社のブログで[こんな記事](https://www.collabo-style.co.jp/developer-blog/20211228/)を書いたmikoです。

https://www.collabo-style.co.jp/developer-blog/20211228/

今日は、大人しく真面目にコラボフローのカスタマイズについてアレコレ紹介していきます。

# 🛠 コラボフローをカスタマイズする

コラボフローでは[コラボフロー JavaScript API](https://collaboflow.zendesk.com/hc/ja/sections/360000040276, "コラボフロー JavaScript API を利用する")を利用することで、
申請書の入力や操作を補助するためのカスタマイズができます。

例えば、以下のようなことができたりします。

* [特定の文字を入力できないようにする](https://collaboflow.zendesk.com/hc/ja/articles/4520589023119)
* [日付の形式（yyyy/mm/dd）を（yyyy-mm-dd）に変換する](https://collaboflow.zendesk.com/hc/ja/articles/4943303929871)
* [複数パーツの入力状態によって、独自に必須チェックを行う](https://collaboflow.zendesk.com/hc/ja/articles/360000411615)

他にも様々な[カスタマイズのサンプル](https://collaboflow.zendesk.com/hc/ja/sections/360000041875, "サンプル/Tips
")があります。

# 本題に入る前に・・・

「そろそろアドベントカレンダーの季節かぁ…」と、
記事のネタを探すために申請書のカスタマイズをしている時にあることに気づきました。

**外部ライブラリをURL指定できたら色々と楽になるし、可能性も広がるのでは？？**

よし、ならば・・・😀


# 🎉 外部ライブラリのURL指定をできるようにしました！

先月の[リリースノート](https://collaboflow.zendesk.com/hc/ja/articles/5925538632335-%E3%82%B3%E3%83%A9%E3%83%9C%E3%83%95%E3%83%AD%E3%83%BC-2-18-15-%E3%83%AA%E3%83%AA%E3%83%BC%E3%82%B9%E3%83%8E%E3%83%BC%E3%83%88#:~:text=%E3%82%AB%E3%82%B9%E3%82%BF%E3%83%9E%E3%82%A4%E3%82%BA%E3%81%AEJavaScript%E3%83%95%E3%82%A1%E3%82%A4%E3%83%AB%E3%82%92%E3%80%81URL%E3%81%A7%E6%8C%87%E5%AE%9A%E3%81%A7%E3%81%8D%E3%82%8B%E3%82%88%E3%81%86%E3%81%AB%E3%81%AA%E3%82%8A%E3%81%BE%E3%81%97%E3%81%9F%E3%80%82)をご覧になっている方は、既にご存知かと思いますが、
フォーム設定のカスタマイズ機能をアップデートしました！

そのアップデート内容はというと・・・

* URL指定でJavaScriptファイルを読み込めるようになった
* ファイルの読み込み順をドラッグアンドドロップで並び替えできるようになった

カスタマイズで手間がかかってしまっていた部分を改善しました🛠

（´-`）.｡oO（当初のリリース予定には含まれていませんでしたが、許可を貰って~~無理やりねじ込んでもらいました~~）


# 📘 コラボフローカスタマイズのすゝめ

さて、ここからが本題です！！
今回はアップデートで追加した**URL指定**を活用したサンプルコードを紹介させていただきます！

:::note warn
ここから紹介するサンプルコードは最低限の動作検証しか行っていないので、
実際に試す場合には自己責任でお願いします🙇
:::

## 📅 Day.js

[Day.js](https://day.js.org/)は「日付をJavaScriptで日付の操作って何だか面倒…。わかりづらい…。」
そんな方にオススメです！

日付の加算、減算はもちろんのこと、差分や比較、日本語表記など日付に関する操作が楽にできます。
これを利用することで、日付パーツのカスタマイズがやりやすくなります！

### 日付の入力範囲チェックサンプル

入力した日付が今月以外だったにアラートを表示するサンプルを紹介します。
👇以下が実際に動かしてみた例です。

![dayjs.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136361/fb8a3064-21b4-9c4a-50a8-4ec6a7c08c43.gif)

#### カスタマイズ設定例

フォーム設定画面のカスタマイズタブにて以下のURL指定、JavaScriptファイルをアップロードします。

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136361/23c06df2-c55e-a375-8419-9eb413410e30.png)

外部ライブラリをURL指定で利用するには「URL指定」ボタンをクリック後、
URLを入力し✅を押してから保存ボタンをクリックすればOKです。


##### 設定値

| 順番 | 指定方法 | ファイル名/URL |
|:-----------:|:------------|:------------|
| 1    | URL        | https\://cdnjs.cloudflare.com/ajax/libs/dayjs/1.11.6/dayjs.min.js   |
| 2    | URL        | https\://cdnjs.cloudflare.com/ajax/libs/dayjs/1.11.6/plugin/isBetween.min.js  |
| 3    | ファイル   | DateValidator.js     |

##### DateValidator.js

``` DateValidator.js
(function () {

    'use strict';

    // 日付比較用のプラグインを追加
    dayjs.extend(dayjs_plugin_isBetween);

    collaboflow.events.on(['request.input.fidDate.change'], function (e) {

        const parts = e.parts;
        // 日付パーツの値を取得
        const inputDate = dayjs(parts['fidDate'].value);

        // 入力された日付が不正だった場合には、入力値をクリアする
        if (!inputDate.isValid()) {
            parts['fidDate'].value = '';
            return;
        }

        // 現在の日時を取得する
        const nowDate = dayjs();

        // 現在の月の初日、末日を取得する
        const startMonthDate = nowDate.startOf('month');
        const endMonthDate = nowDate.endOf('month');

        // 入力された日付が今月以外だった場合
        if (!inputDate.isBetween(startMonthDate, endMonthDate, null, '[]')) {
            alert('今月の日付を入力してください。');
            parts['fidDate'].value = '';
            return false;
        }
    });

})();
```

``nowDate.startOf('month')``でその月の初日を取得してきたり、
``isBetween(開始日, 終了日, null, '[]')``で指定期間内かどうか判別できたりと
他の人が読んでも「そういうことね。完全に理解した。」となるはずです。

[Day.jsの公式ドキュメント](https://day.js.org/docs/en/installation/installation)には他にも使えるメソッドが紹介されています。
また、Day.js用のライブラリやプラグインを利用することで、
日本語表記に対応したり、閏年のチェックも簡単にできたりします。



## qrcode.js

次に紹介するのは[qrcode.js](https://davidshimjs.github.io/qrcodejs/)です。
名称からわかる通り、QRコードを生成することができます。

これを利用することで、特定のパーツに入力された値をQRコードに変換することができます。

### 入力値をQRコードに変換するサンプル
以下は、入力したURLをQRコードに変換しているサンプルです。

![QRCodeSample.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136361/908d2f49-c4df-6b3b-0e4c-4097ed0911b5.gif)

:::note warn
現状、印刷画面ではJavaScript APIは動作しないため、生成されたQRコードを画像パーツへドラッグアンドドロップしています。
:::

#### カスタマイズ設定例

フォーム設定画面のカスタマイズタブにて以下のURL指定、JavaScriptファイルをアップロードします。

##### 設定値
| 順番 | 指定方法 | ファイル名/URL |
|:-----------:|:------------|:------------|
| 1    | URL        | https\://cdnjs.cloudflare.com/ajax/libs/qrcodejs/1.0.0/qrcode.min.js         |
| 2    | ファイル   | QRCodeSampleCode.js     |

##### QRCodeSampleCode.js

``` QRCodeSampleCode.js
(function () {
    'use strict';

	collaboflow.events.on(['request.input.fidReferenceSiteURL.change'], function (e) {
		new QRCode(document.getElementById("qrcode"), {
			text: e.parts.fidReferenceSiteURL.value,
			width: 64,
			height: 64
		});
	});
})();
```

##### フォーム設定

![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136361/ada2a74b-0785-a1ed-c4d1-47e371d86d8a.png)

画像パーツの左隣にラベルパーツを配置し、
ラベルの内容に以下の値を入力します。

``` html
<div id="qrcode"></div>
```


もちろん、URL以外でも数値や文字列もQRコード化できます。
「文書番号をQRコード化して、それをバーコードリーダーで読み取って…」
みたいな活用もできます。

## 🖱 Mousetrap

最後に紹介するのは[Mousetrap](https://craig.is/killing/mice)です！
[Mousetrap](https://craig.is/killing/mice)は、Webページでショートカットキーを実装することができます。

つまり、申請書ごとにショートカットキーを実装することが可能になり、
例えば、キーボードで「?」キーを押下するとヘルプウィンドウが開くといったこともできます。

###  「?」キーを押下するとヘルプウィンドウが開くサンプル

👇以下が実際に動かしてみた例です。
申請書の見た目を変更せずに補足説明などを追記できます。

![MouseTrap.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136361/eadde829-71e5-3537-d40a-c2ccd4d411b5.gif)


#### カスタマイズ設定例

フォーム設定画面のカスタマイズタブにて以下のURL指定、JavaScriptファイルのアップロードします。

##### 設定値

| 順番 | 指定方法 | ファイル名/URL |
|:-----------:|:------------|:------------|
| 1    | URL        | https\://cdnjs.cloudflare.com/ajax/libs/mousetrap/1.6.5/mousetrap.min.js   |
| 2    | ファイル   | MouseTrap.js     |

##### MouseTrap.js

``` MouseTrap.js
(function () {
"use strict";
    collaboflow.events.on('request.input.show', function (data) {
        Mousetrap.bind('?', function(e) {
            const buttons = [
                {
                    text: "閉じる",
                    click: function () { $(this).dialog('close'); }
                }
            ];
            showDialog("ヘルプ", "入力内容について困ったら読んでください。<br>参考サイトには、購買対象についての製品情報が紹介されているページのURLを入力してください。", buttons);
        });
    });

    // ヘルプ用のダイアログを表示します。
    function showDialog(title, message, buttons)
    {
        const html_dialog = '<div>' + message + '</div>';
        $(html_dialog).dialog({
            title: title,
            buttons: buttons,
            close: function() { $(this).remove(); }
        });
    }
})();
```

他にも、特定のキーを押下したら、JavaScriptで実装した処理を実行したり、
他のライブラリの機能を有効化させたりといったことができます。

### 🎙 コラボフローで音声入力をするサンプル

音声入力にて項目の値をセットする、地味に便利なカスタマイズです。

以下の動画だとわかりづらいですが、
文字入力についてキー入力は一切していません。
<font color="gray">※最初は音声込みで録画していましたが、私自身が不快に感じたため削除しました🗑</font>

![voiceInput.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136361/30fe23da-4436-3060-3b43-879dd9a9915d.gif)


#### MouseTrap.js

``` MouseTrap.js
(function () {
    "use strict";
    const SpeechRecognition = window.SpeechRecognition || webkitSpeechRecognition;
    const recognition = new SpeechRecognition();
    recognition.lang = 'ja-JP';
    recognition.interimResults = true;
    recognition.continuous = true;

    collaboflow.events.on('request.input.show', function (data) {
        recognition.onresult = (event) => {
            let finalTranscript = '';
            let interimTranscript = '';
            for (let i = event.resultIndex; i < event.results.length; i++) {
                const transcript = event.results[i][0].transcript;
                if (event.results[i].isFinal) {
                    finalTranscript += transcript;
                } else {
                    interimTranscript = transcript;
                }
            }

            if (finalTranscript.length) {
                document.activeElement.value += finalTranscript;
            }
        }

        Mousetrap.bind('ctrl+1', function(e) {
            recognition.start();
        });

        Mousetrap.bind('ctrl+2', function(e) {
            recognition.stop();
        });
    });
})();
```


# おまけ

## 🎶 Rythm.js

[Rythm.js](https://okazari.github.io/Rythm.js/)はリズムに合わせて、要素が躍る面白いライブラリです！

マイク音声に反応して申請書の入力項目が荒ぶります。


最後に、欲にまみれた人間の無様な音声入力っぷりをご覧ください。
（👉右側に音声認識された内容を出力しています。）

![rythm.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/136361/2dc8d6b9-2372-69be-ed08-2c39fc4ac773.gif)

---

さて、いかがだったでしょうか！

「このライブラリを使ったら、コラボフローでこんなこともできちゃうのでは？？？」と閃いた方は、
是非「[コラボフロー Advent Calendar 2022](https://qiita.com/advent-calendar/2022/collaboflow)」に参加してください！！

それと**カスタマイズ機能のアップデートはまだこれで終わりではない**ので、
引き続き今後のアップデートを楽しみにお待ちしていてください！(￣ー￣)ﾆﾔﾘ

２日目は、[bugtrap](https://qiita.com/bugtrap)さんの「QRコード！」です！！
（今回紹介したqrcode.jsと連携できちゃうかも？！）

また、アドベントカレンダーの最終日にお会いしましょう👋