2022年10月4日

イベント: change、input、cut、copy、paste

データの更新に伴う様々なイベントについて説明します。

イベント: change

change イベントは、要素の変更が完了したときにトリガーされます。

テキスト入力の場合、フォーカスを失ったときにイベントが発生します。

たとえば、下のテキストフィールドに入力している間は、イベントは発生しません。しかし、フォーカスを他の場所(たとえばボタン)に移動すると、change イベントが発生します。

<input type="text" onchange="alert(this.value)">
<input type="button" value="Button">

他の要素(selectinput type=checkbox/radio)では、選択が変更された直後にトリガーされます。

<select onchange="alert(this.value)">
  <option value="">Select something</option>
  <option value="1">Option 1</option>
  <option value="2">Option 2</option>
  <option value="3">Option 3</option>
</select>

イベント: input

input イベントは、ユーザーによって値が変更されるたびにトリガーされます。

キーボードイベントとは異なり、キーボード操作以外の値の変更(マウスによるペーストや音声認識によるテキストの入力など)でもトリガーされます。

例えば

<input type="text" id="input"> oninput: <span id="result"></span>
<script>
  input.oninput = function() {
    result.innerHTML = input.value;
  };
</script>

<input>の変更をすべて処理したい場合、このイベントが最適です。

一方、inputイベントは、キーボード入力や値の変更を含まない操作(例:入力中に矢印キー を押す)ではトリガーされません。

oninputでは何も防止できません

input イベントは値が変更された後に発生します。

そのため、そこでevent.preventDefault()を使用することはできません。既に遅すぎます。効果はありません。

イベント: cut、copy、paste

これらのイベントは、値のカット/コピー/ペースト時に発生します。

これらはClipboardEventクラスに属し、カット/コピー/ペーストされたデータへのアクセスを提供します。

event.preventDefault()を使用してアクションを中止することもできます。そうすると、何もコピー/ペーストされません。

たとえば、以下のコードはすべてのcut/copy/pasteイベントを防止し、カット/コピー/ペーストしようとしているテキストを表示します。

<input type="text" id="input">
<script>
  input.onpaste = function(event) {
    alert("paste: " + event.clipboardData.getData('text/plain'));
    event.preventDefault();
  };

  input.oncut = input.oncopy = function(event) {
    alert(event.type + '-' + document.getSelection());
    event.preventDefault();
  };
</script>

注意:cutcopyイベントハンドラ内では、event.clipboardData.getData(...)の呼び出しは空文字列を返します。これは、技術的にはデータはまだクリップボードにないためです。event.preventDefault()を使用すると、まったくコピーされません。

そのため、上記の例ではdocument.getSelection()を使用して選択されたテキストを取得しています。ドキュメントの選択の詳細については、記事選択と範囲を参照してください。

テキストだけでなく、あらゆるものをコピー/ペーストできます。たとえば、OSのファイルマネージャーでファイルをコピーしてペーストできます。

これは、clipboardDataDataTransferインターフェースを実装しているためです。これは、ドラッグアンドドロップやコピー/ペーストによく使用されます。現時点では私たちの範囲外ですが、そのメソッドはDataTransfer仕様にあります。

また、クリップボードにアクセスするための追加の非同期APIであるnavigator.clipboardもあります。詳細については、仕様クリップボードAPIとイベントFirefoxではサポートされていませんを参照してください。

セキュリティ上の制限

クリップボードは、OSレベルの「グローバル」なものです。ユーザーはさまざまなアプリケーションを切り替えて、さまざまなものをコピー/ペーストすることができ、ブラウザページはそれらすべてを見るべきではありません。

そのため、ほとんどのブラウザでは、コピー/ペーストなどの特定のユーザーアクションの範囲内でのみ、クリップボードへのシームレスな読み取り/書き込みアクセスが許可されています。

Firefoxを除くすべてのブラウザでは、dispatchEventを使用して「カスタム」クリップボードイベントを生成することは禁止されています。そして、そのようなイベントをディスパッチできたとしても、仕様ではそのような「合成」イベントはクリップボードへのアクセスを提供してはならないと明確に述べられています。

イベントハンドラでevent.clipboardDataを保存して後でアクセスしようとしても、機能しません。

繰り返しになりますが、event.clipboardDataは、ユーザーが開始したイベントハンドラのコンテキストでのみ機能します。

一方、navigator.clipboardは、より新しいAPIであり、あらゆるコンテキストで使用できます。必要に応じて、ユーザーの許可を求めます。

概要

データ変更イベント

イベント 説明 特記事項
change 値が変更されました。 テキスト入力の場合、フォーカスを失ったときにトリガーされます。
input テキスト入力の場合、変更ごとにトリガーされます。 changeとは異なり、すぐにトリガーされます。
cut/copy/paste カット/コピー/ペースト操作。 アクションを防止できます。event.clipboardDataプロパティはクリップボードへのアクセスを提供します。Firefoxを除くすべてのブラウザはnavigator.clipboardもサポートしています。

課題

重要度: 5

銀行預金の金額と利率を入力して、所定の期間後の金額を計算できるインターフェースを作成します。

デモはこちら

入力の変更はすべてすぐに処理する必要があります。

数式は次のとおりです。

// initial: the initial money sum
// interest: e.g. 0.05 means 5% per year
// years: how many years to wait
let result = Math.round(initial * (1 + interest) ** years);

課題のためのサンドボックスを開きます。

チュートリアルマップ

コメント

コメントする前にこれを読んでください…
  • 改善点の提案がある場合は、コメントする代わりにGitHub issueまたはプルリクエストを送信してください。
  • 記事の内容が理解できない場合は、詳しく説明してください。
  • コードを数単語挿入するには<code>タグを使用し、複数行の場合は<pre>タグで囲み、10行を超える場合はサンドボックス(plnkrjsbincodepen…)を使用してください。