キー操作の混乱にさよなら！TeamsのEnterキーで誤送信しない操作方法 🚀

## はじめに

この記事では、ブラウザのアドオンであるTampermonkeyを利用して、異なるチャットのプラットフォームで送信キーを統一する方法を解説します。
システムごとに送信キーが異なることで、ユーザーが誤操作を引き起こすことがあり、誤送信の問題に発展することもあります。

## 利用条件 📝
- Tampermonkey がブラウザのアドオンとしてインストールされていること

- ブラウザがTampermonkeyをサポートしている（最新版のChrome, Firefox, Safariなど）こと

## 動作原理 🔧
ユーザーが設定したJavaScriptを実行する(割り込む)ことで、ブラウザ上のキー操作をカスタマイズします。

## MS Teamsの例
以下のスクリプトは、MS Teams Web版で CTRL + ENTER でメッセージを送信するためのカスタマイズ例です。
アプリ版は、この仕組みが使えないため、残念ながら対応できません。

このスクリプトは、Tampermonkeyで使用するためのユーザースクリプトの一例です。
Microsoft Teamsでのチャット時に、CTRL + ENTERを押すことでメッセージを送信できるように、デフォルトの動作を変更します。特に、evnt.isComposingをチェックすることで、テキスト入力が進行中のイベントには影響を与えず、想定外の動作を防ぎます。また、capture: trueオプションを使ってイベントを捕捉することで、事前に指定された条件に合致した場合、イベントの伝播を止めるようにしています。

```javascript
// ==UserScript==
// @name         ms teams web ctrl+enter
// @namespace    http://tampermonkey.net/
// @version      2023-12-11
// @description  Microsoft Teams Web版でCTRL+ENTERを使ってメッセージを送信するためのカスタマイズを提供します。
// @author       https://blog.basyura.org/entry/2023/12/11/232227
// @match        https://teams.microsoft.com/v2/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=microsoft.com
// @grant        none
// ==/UserScript==

(function() {
    'use strict';

    // CTRL+ENTERキーボードイベントを処理してメッセージを送信する関数です。
    // Handles the CTRL+ENTER keyboard event to send messages.
    function handleCtrlEnter(evnt) {
        // イベントが合成の一部である場合には、関数の実行を防止します。
        // Prevents the function from executing if the event is part of a composition.
        if (evnt.isComposing) {
            return;
        }

        // イベントのターゲットがDIVで、押されたキーがEnter、
        // そしてCTRLまたはMETA（MacではCommand）が押されていないことを確認します。
        // 条件に一致する場合、イベントの伝播を停止します。
        // Checks if the event's target is a DIV, the pressed key is Enter,
        // and neither CTRL nor META (Command on Mac) is pressed.
        // If so, stops the event from propagating.
        if (evnt.target.tagName === "DIV" && evnt.code == "Enter" && !(evnt.ctrlKey || evnt.metaKey)) {
            evnt.stopPropagation();
        }
    }

    // 'keydown'イベントに対して、documentにイベントリスナーを追加します。
    // handleCtrlEnter関数がイベントを伝播する前にキャプチャすることを保証します。
    // Adds an event listener for the 'keydown' event on the document,
    // ensuring that the handleCtrlEnter function captures events before they propagate.
    document.addEventListener("keydown", handleCtrlEnter, { capture: true });
})();

```


## Directの例
別の例として、Directのキーアサインを変更するスクリプトです。
あらかじめ「Enterを押して送信する」を解除しておく必要があります。

Directはこちらのサービスです。
https://direct4b.com/ja/

```javascript
// ==UserScript==
// @name         ダイレクト Keyassign replace
// @namespace    http://tampermonkey.net/
// @version      2024-03-04
// @description  Directのキーアサインを変更する. Change the key assignment in Direct chat service.
// @author       You
// @match        （ご利用のサイトに合わせて変更してください） 例) https://www.example.jp/home/*
// @icon         https://www.google.com/s2/favicons?sz=64&domain=hg-direct.jp
// @resource     toastr.min.css https://cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/toastr.min.css
// @require      https://ajax.googleapis.com/ajax/libs/jquery/3.6.0/jquery.min.js
// @require      https://cdnjs.cloudflare.com/ajax/libs/toastr.js/latest/toastr.min.js
// @grant        GM_addStyle
// @grant        GM_getResourceText
// ==/UserScript==

(function() {
    'use strict';

    // 通知バーのスタイルを設定します。
    // Set up the style for the notification bar.
    const newCSS = GM_getResourceText("toastr.min.css");
    GM_addStyle(newCSS);

    // 新しいプレースホルダーテキストを設定します。
    // Set a new placeholder text.
    var newPlaceholder = "メッセージを入力（Ctrl + Enter で送信）";
    document.querySelector("#footer > div > div.form-control.message-text-editor.empty-contents.for-normal-message.form-send-text").setAttribute('data-placeholder', newPlaceholder);

    // キーダウンイベントにカスタムロジックを適用します。
    // Apply custom logic to keydown events.
    document.body.addEventListener('keydown', function(e) {
        // Ctrl + Rの使用を無効にして誤操作を防ぎます。
        // Disable Ctrl + R to prevent misoperation.
        if (e.ctrlKey && e.key === 'r') {
            toastr.warning("Ctrl + R は Tampermonkey で無効化されています。");
            e.preventDefault();
        }

        // Shift + Enterのデフォルト操作を無効にします。
        // Disable the default operation for Shift + Enter.
        if ((e.shiftKey && e.key === 'Enter')) {
            toastr.warning("Shift + Enter キーが押されました。");
            e.preventDefault();
            e.stopPropagation();
        }

        // Ctrl + Enterでメッセージを送信します。
        // Send message with Ctrl + Enter.
        if ((e.ctrlKey && e.key === 'Enter')) {
            toastr.success("Ctrl + Enter キーでメッセージが送信されました。");
            // 送信ボタンをクリックします。
            // Click the send button.
            document.querySelector("#footer > div > div.form-send-toolbar.dropup > div.form-send-button-group > button").click();
            e.preventDefault();
            e.stopPropagation();
        }
    }, true); // キャプチャフェーズでイベントを処理するためにtrueを指定します。
              // Specify true to handle the event in the capture phase.
})();
```

## 小ネタ: Teams の可用性ステータスを維持 😎
Teamsの可用性ステータスを強制的に「在席中」に保つスクリプトもあります。
詳細は以下のGitHubリポジトリを参照してください。

https://github.com/Bnz-0/fuk-u-teams