Classi開発者ブログ

教育プラットフォーム「Classi」を開発・運営するClassi株式会社の開発者ブログです。

IME変換中のエンターキーで送信される!への対処法[追記あり]

[2024年4月25日 追記] Safariの動作について考慮漏れがありましたので、一部追記・編集しました。

新宿にオフィスのあるClassiは、岡山在住の私のような地方在住者だけでなく、いわゆる通勤圏内に在住していてもリモートワークで働いている人が多い会社です。必然的にミーティングはいわゆるオンラインミーティングとなり、主にGoogle Meetが利用されています。

そのGoogle Meetのチャット機能、ここ1週間ぐらい「IMEで日本語に変換のために押すエンターキーで送信されてしまう」という現象が発生しています。このエントリーを読まれている時点では対応しているかも知れませんが、2024年4月22日17時時点ではその現象は続いています(Windowsでは再現しないという情報もあります)。

Google Meetのチャット欄のスクリーンショット。「にほんごのへんかん」と入力し、これから漢字変換を行う状態。
入力開始

Google Meetのチャット欄のスクリーンショット。漢字変換が行われ候補に漢字変換された「日本語の変換」と表示されている。
変換して確定のエンターキーを押すと

Google Meetのチャット欄のスクリーンショット。送信されたチャットとして「日本語の変換」が表示されている。入力欄にも「日本語の変換」が表示されている。
送信される

エンターキーに頼らない日本語入力を頑張りましたが、手癖というのは抜けないものです

この現象は、Google Meetに限らずさまざまなウェブサービスで発生しています。ChatGPTも話題になってからしばらくはこのような挙動でした。日本や東アジア圏を中心に、IMEを利用しているユーザーからのフィードバックでいずれは対応されると待つのが基本ですが、普段の業務利用も絡んでいるので対応策を整理しました。

ここからは作成したデモに基づいて進めて行きます。

isComposingDemoというデモ画面のスクリーンショット、入力を反映する場所と入力欄のどちらにも「変換中」という文字が表示されている。その下には「IME変換中の送信停止」というボタンがある

「入力欄」で日本語変換を行って確定のためにエンターキーを押すと上に反映される状態を再現しています。その後、「IME変換中の送信停止」と書かれたボタンを押すと、変換確定のエンターキーでは反映されなくなりますが、変換を行っていないときのエンターキーには反応します。

前出のicComposingDemoの画面。入力を反映する場所に「変換後のEnterは反応します」と表示されている。入力欄にはなにも表示されていない。

対応方法

基本的な対応の方針は以下です。

「イベントキャプチャでいち早くIME変換中のエンターキー入力を捕捉して伝播させないようにする」

それを実装したのが下記のコードです。

document.addEventListener('keydown', function(event) {
    if ((event.key === 'Enter' && event.isComposing) || event.keyCode === 229) {
        event.stopPropagation();
    }
},{capture: true});

「イベントキャプチャでいち早く」

addEventListenerの第3引数{capture: true}がその実装です。このオプションでcaptureを有効にすると、keyDownイベントの伝播がターゲットから親方向のバブリングではなく、ドキュメントからターゲットに向かうキャプチャとなり、まずはdocumentがkeyDownの発火対象になります。

参考)

「IME変換中のエンターキー入力を捕捉」

(event.key === 'Enter' && event.isComposing) || event.keyCode === 229の条件式がその判定です。 event.key === 'Enter'はkeyDownされたキー名、event.isComposingはIME変換中であればtrueになります。また、Safariの挙動への対応として非推奨プロパティですがevent.keyCode === 229も加えています。keyCodeの229は、IMEに関連したkeyCodeとして定義されています。この条件に合った場合、日本語変換時のエンターキーと判断し、後述のevent.stopPropagation()で子要素に対しての伝搬を中止します。

参考)

「伝播させないようにする」

event.stopPropagation()がそのメソッド名の通り伝搬を止めます。documentの段階で伝播しないようにすることで、送信のイベントが用意されているinputフィールドにエンターキーの入力が伝わらないようになっています。

参考)

ここまでが「IME変換中のエンターキーで送信される」への対応の基本です。

どうやって稼働中のウェブサービスに適用するか?

対応方法のJavaScriptがあるとして例えばGoogle Meetで困っていた場合、どうすれば良いでしょうか?フィードバックを送ったり、オープンソースであればPullRequestを送ったりという対応が思い浮かびますが、「今すぐ」の解決策は手元のブラウザに上記のJavaScriptを適用することです。

DevToolsのコンソールで実行する

上記のコードをDevToolsのコンソール画面で実行すると、コードの内容が適用されます。該当のサービスにアクセスする度に実行する必要があります。

Google Meetのチャット欄とDevToolsのコンソール画面に前述で紹介したJavaScriptのコードが記載されている。
コンソールに貼り付けた例

ブックマークレットを作成する

下記のコードは、この記事で紹介しているJavaScriptをブックマークレットで利用可能にしたものです。ブックマークとして登録しておくと、必要な時に呼び出せば以降は適用されています。こちらも該当のサービスにアクセスする度に実行する必要がありますが、ブックマークを呼び出すだけです。

javascript:(function()%20%7Bdocument.addEventListener('keydown'%2Cfunction(event)%7Bif((event.key%3D%3D%3D'Enter'%26%26event.isComposing)%7C%7Cevent.keyCode%3D%3D%3D229)%7Bevent.stopPropagation()%7D%7D%2C%7Bcapture%3A%20true%7D)%7D)()

このブックマークレットのコードは同僚の@koki_developが作成したBookmarklet.linkを利用して生成しました。

拡張機能を使う

上記のJavaScriptの作用を組み込んだ拡張機能を利用すれば、アクセスする度に行うといった面倒もなく適用できます。似たようなケースで、ChatGPT向けの「変換中のエンターキーで送信されるのを防ぐ」拡張を散見した記憶があります。

冒頭で話題にしたGoogle Meetだと、Google Meet Chat to Clipboardという拡張機能が先日配信した4.2.0で「変換中のエンターキーで送信されるのを防ぐ」機能を組みました。この記事で紹介した私作成の拡張機能ですが、データの外部送信なく、ファイルのアクセスもなく、クリップボードに入れるだけの拡張機能ですので、是非利用してみてください。

最後に

今現在(2024年4月22日17時)困っているのでGoogle Meetを題材にしましたが、欧米中心で開発されているウェブサービスにはたまにあることです。対応されるのを待つのが基本だと思いますが、クライアント(ブラウザ)で打てる手はありますよ、という紹介でした。参考になれば幸いです。

© 2020 Classi Corp.