見出し画像

JavaScriptイベント 注意するポイント



イベントハンドラとイベントリスナ

イベントハンドラやイベントリスナで設定する

・イベントハンドラは1つのイベントしか設定できない
・イベントリスナは2つ以上のイベントを設定できる
・設定済のイベントハンドラ/イベントリスナを削除できる

イベントハンドラの例

var button = document.getElementById("btn");
button.onclick = function() {
    alert("Hello");
};


イベントハンドラを削除: nullを代入

var button = document.getElementById("btn");
button.onclick = function() {
    alert("Hello");
};

button.onclick = null;


イベントリスナの例

var button = document.getElementById("btn");
function btnClick() {
    alert("Hello");
}

button.addEventListener("click", btnClick, true);


イベントリスナは複数設定できる

var button = document.getElementById("btn");

function btnClick() {
    alert("Hello");
}

function logMessage() {
    console.log("Button was clicked!");
}

// Add multiple event listeners to the same button
button.addEventListener("click", btnClick, true);
button.addEventListener("click", logMessage, true);


イベントリスナを削除: removeEventListenerを使う

var button = document.getElementById("btn");
function btnClick() {
    alert("Hello");
}

button.addEventListener("click", btnClick, true);



button.removeEventListener("click", btnClick, true);



正しいイベントリスナの書き方

addEventListener("イベント名", 関数名, true/false)

なので、
 onclickではなくclick
 foo() ではなくfoo

xxxx.addEventListener("click", foo, true);


間違いの例

xxxx.addEventListener("onclick", foo(), true);

間違い:
"onclick" はイベントハンドラ名
foo() は関数が呼び出される。イベントリスナとして関数そのものを渡す必要があるので、fooと書く


正しい書き方:xxxx.addEventListener("click", foo, true);

xxxx.addEventListener("onclick", foo, true);

間違い:
"onclick" はイベントハンドラ名


正しい書き方:xxxx.addEventListener("click", foo, true);

xxxx.addEventListener("click", foo(), true);

間違い:
foo()ではなくfooと書く


正しい書き方:xxxx.addEventListener("click", foo, true);



イベントリスナのイベントの伝播:
子要素と親要素のイベントの伝播を指定

第3引数にtrue, falseを設定し、 
 親要素と子要素のイベントの発生順を変えられる


・falseを指定した(または指定がない場合はデフォルト)場合、

  親要素をクリックしたら親要素のイベントだけ発生する
  子要素をクリックしたら子要素-親要素の順でイベント発生

・trueを指定した場合、
   親要素をクリックしたら親要素のイベントだけ発生する  
   子要素をクリックしたら親要素-子要素の順でイベント発生

イベントの伝播: addEventListener の第三引数に false を設定する


バブリングフェーズ(false)

子要素から親要素への方向でイベントが伝播する
(addEventListener の第三引数に何も指定しないとデフォルトでfalse)

1) ターゲット要素で発生
2) 最終的にはドキュメントのルート(document)

に向かってイベントが起動する

バブリングフェーズ(false)の例

INNERをクリックした場合:"INNER" "OUTER"

OUTERをクリックした場合:"OUTER"

<div id="outer">
    OUTER
    <p id="inner">
     INNER
    </p>
</div>

var outer = document.getElementById("outer");
outer.addEventListener("click", function() {
    console.log("OUTER");
}, false);


var inner = document.getElementById("inner");
inner.addEventListener("click", function() {
    console.log("INNER");
}, false);



イベントの伝播: addEventListener の第三引数に true を設定する

キャプチャフェーズ(true)

親要素から子要素への方向でイベントが伝播する

つまり、
1) 最上位の親要素(例えば document オブジェクト)
2) イベントのターゲット(イベントが発生した要素)

に向かってイベントが起動する

キャプチャフェーズ(true)の例

INNERをクリックした場合: "OUTER" "INNER"

OUTERをクリックした場合:"OUTER"

<div id="outer">
    OUTER
    <p id="inner">
     INNER
    </p>
</div>

var outer = document.getElementById("outer");
outer.addEventListener("click", function() {
    console.log("OUTER");
}, true);


var inner = document.getElementById("inner");
inner.addEventListener("click", function() {
    console.log("INNER");
}, true);




JavaScriptイベント

フォームに関するイベント

focus 
  入力フィールドをクリック or Tab で移動
blur 
  フォーカスが外れる(クリック or Tab 移動)
input 
  入力フィールドに文字を入力(リアルタイム)
change 
  セレクトの値を変更し
、フォーカスが外れたとき
select 
  テキストをクリックして選択されたとき
contextmenu 
  右クリックでコンテキストメニューが開いたとき
invalid 
  入力値が不正(例: required のフィールドが未入力)
submit 
  フォームが送信されたとき(ボタン or Enter)



<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<title>Form Events Example</title>
<script>
document.addEventListener('DOMContentLoaded', function () {
    const form = document.getElementById('form');
    const input = document.getElementById('input');
    const select = document.getElementById('select');

    // Focus event
    input.addEventListener('focus', function () {
        console.log('Input field is focused');
    });

    // Blur event
    input.addEventListener('blur', function () {
        console.log('Input field has lost focus');
    });

    // Input event
    input.addEventListener('input', function () {
        console.log('User typed in the input field: ' + input.value);
    });

    // Change event
    select.addEventListener('change', function () {
        console.log('Selection changed to: ' + select.value);
    });

    // Context menu event
    input.addEventListener('contextmenu', function (event) {
        console.log('Context menu opened on input field');
        event.preventDefault();  // Prevent the context menu from opening
    });

    // Invalid event
    input.addEventListener('invalid', function () {
        console.log('Invalid input detected');
    });

    // Select event
    input.addEventListener('select', function () {
        console.log('Text selected in input field');
    });

    // Submit event
    form.addEventListener('submit', function (event) {
        event.preventDefault(); // Prevent actual form submission
        console.log('Form submitted');
    });
});
</script>
</head>
<body>
<form id="form">
    <label for="input">Enter text:</label>
    <input type="text" id="input" required>
    <label for="select">Choose option:</label>
    <select id="select">
        <option value="option1">Option 1</option>
        <option value="option2">Option 2</option>
        <option value="option3">Option 3</option>
    </select>
    <button type="submit">Submit</button>
</form>
</body>
</html>


focus / blur の例
テキストフィールドにクリックして選択した瞬間、テキストフィールドから外した瞬間に出力

<input type="text" id="textInput" placeholder="ここに入力">
<script>
document.getElementById("textInput").addEventListener("focus", () => {
    console.log("🔵 入力フィールドがフォーカスされました");
});
document.getElementById("textInput").addEventListener("blur", () => {
    console.log("⚫ フォーカスが外れました");
});
</script>


input / change / select 
テキストフィールドに文字を入力した時、


selectの値を変更した時、


文字を選択した時、

<input type="text" id="textInput" placeholder="ここに入力">
<select id="dropdown">
    <option value="1">選択肢 1</option>
    <option value="2">選択肢 2</option>
</select>
<script>
document.getElementById("textInput").addEventListener("input", () => {
    console.log("✏️ 文字が入力されました");
});
document.getElementById("dropdown").addEventListener("change", () => {
    console.log("🔄 選択肢が変更されました");
});
document.getElementById("textInput").addEventListener("select", () => {
    console.log("📌 テキストが選択されました");
});
</script>


特定の要素内で右クリックメニューを開く

<input type="text" id="textInput" placeholder="ここに入力">
<script>
document.getElementById("textInput").addEventListener("contextmenu", () => {
    console.log("🖱️ 右クリックメニューが開かれました");
});
</script>







キーボードに関するイベント

keydown  
  キーを押したとき
keyup   
  
キーから手を離したとき
keypress  
  
キーを押している間





KeyboardEventのプロパティ(キーボードイベントの入力情報)
 code キーコードを取得
    key  キーの値を取得


<label for="input">Type here:</label>
<input type="text" id="input">

<script>
document.addEventListener('DOMContentLoaded', function () {
    const input = document.getElementById('input');

    // Keydown event
    input.addEventListener('keydown', function (event) {
        console.log('Key down: ' + event.key);
    });

    // Keypress event
    input.addEventListener('keypress', function (event) {
        console.log('Key press: ' + event.key);
    });

    // Keyup event
    input.addEventListener('keyup', function (event) {
        console.log('Key up: ' + event.key);
    });
});
</script>



押されたキーコード: event.code
押されたキーの値: event.key

<label for="input">Type here:</label>
<input type="text" id="input">

<script>
document.addEventListener('DOMContentLoaded', function () {
    const input = document.getElementById('input');

    // Keydown event
    input.addEventListener('keydown', function (event) {
        console.log('押されたキー: ' + event.code);
        console.log('押されたキーの値: ' + event.key);
    });

});
</script>



マウス操作に関するイベント

クリック系
  
click(1回クリック)
  dblclick(2回連続クリック)

マウスボタン系
  mousedown → マウスを押した瞬間に発生(離す前)
  mouseup → マウスを押してから離したときに発生

マウス移動系
  mousemove → マウスを動かすたびに発生
  mouseover → エリアにマウスが入ったときに1回だけ発生
  mouseout → エリアから出たときに1回だけ発生


ホイール&スクロール
  mousewheel
マウスホイールを回したとき
         (現在は wheel イベント推奨)
  scroll → スクロールバーを動かしたときに発生

ドラッグ&ドロップ
  dragstart → ドラッグを開始した瞬間

  drag → ドラッグ中に連続発生
  dragend → ドラッグをやめたとき
  dragenter → ドロップエリアにドラッグされた要素が入ったとき
  dragover → ドロップエリア内でマウスが動いている間
  dragleave → ドロップエリアから外れたとき
  drop → 要素をドロップしたときに発生(event.preventDefault() が必要)

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <title>Mouse and Drag Event Description Example</title>
    <style>
        #eventArea {
            width: 300px;
            height: 300px;
            border: 2px dashed #ccc;
            margin: 20px;
            position: relative;
            overflow: auto;
            padding: 10px;
        }
        #dragArea {
            width: 100%;
            height: 100px;
            background-color: #f0f0f0;
            border: 1px solid #000;
            color: #333;
            line-height: 100px;
            text-align: center;
            margin-top: 20px;
        }
    </style>
</head>
<body>

<div id="eventArea">
    <p>Interact with mouse or drag files here.</p>
    <div id="dragArea">Drag files over this area!</div>
</div>

<script>
    const eventArea = document.getElementById('eventArea');
    const dragArea = document.getElementById('dragArea');

    const logEvent = (event) => {
        console.log(event.type + ' event detected at (' + event.clientX + ', ' + event.clientY + ')');
    };

    // Mouse events
    eventArea.addEventListener('click', () => logEvent('Click: Single mouse button press and release'));
    eventArea.addEventListener('dblclick', () => logEvent('DoubleClick: Two clicks in quick succession on the same element'));
    eventArea.addEventListener('mousedown', () => logEvent('MouseDown: Mouse button is pressed on an element'));
    eventArea.addEventListener('mouseup', () => logEvent('MouseUp: Mouse button is released over an element'));
    eventArea.addEventListener('mousemove', () => logEvent('MouseMove: Mouse is moved over an element'));
    eventArea.addEventListener('mouseover', () => logEvent('MouseOver: Mouse pointer enters the element area'));
    eventArea.addEventListener('mouseout', () => logEvent('MouseOut: Mouse pointer leaves the element area'));
    eventArea.addEventListener('mousewheel', () => logEvent('MouseWheel: Wheel or similar device is rotated'));
    eventArea.addEventListener('scroll', () => logEvent('Scroll: Element is scrolled'), true);  // Use capture for scrolling

    // Drag events
    dragArea.addEventListener('drag', () => logEvent('Drag: Element or text selection is being dragged'));
    dragArea.addEventListener('dragstart', () => logEvent('DragStart: The user starts dragging an element or text selection'));
    dragArea.addEventListener('dragend', () => logEvent('DragEnd: A drag operation is being ended (by releasing a mouse button or hitting the escape key)'));
    dragArea.addEventListener('dragenter', () => logEvent('DragEnter: Dragged element enters a valid drop target'));
    dragArea.addEventListener('dragover', (event) => {
        event.preventDefault();  // Necessary for enabling drop
        logEvent('DragOver: An element or text selection is being dragged over a valid drop target');
    });
    dragArea.addEventListener('dragleave', () => logEvent('DragLeave: Dragged element leaves a valid drop target'));
    dragArea.addEventListener('drop', (event) => {
        event.preventDefault();
        logEvent('Drop: An element is dropped on a valid drop target');
    });

    // Allow drop
    dragArea.addEventListener('dragover', (event) => {
        event.preventDefault();  // Allow drop
    });
</script>

</body>
</html>



クリック / ダブルクリックした時

<button id="btn">クリックしてください</button>
<script>
document.getElementById("btn").addEventListener("click", () => {
    console.log("🖱️ ボタンがクリックされました");
});
document.getElementById("btn").addEventListener("dblclick", () => {
    console.log("🔁 ボタンがダブルクリックされました");
});
</script>


マウスボタンを押した/離した

<button id="btn">ボタンを押してみてください</button>
<script>
document.getElementById("btn").addEventListener("mousedown", () => {
    console.log("👆 マウスボタンを押しました");
});
document.getElementById("btn").addEventListener("mouseup", () => {
    console.log("☝️ マウスボタンを離しました");
});
</script>



マウスが要素内に入った時、離れた時、要素内でマウスを動かした時

<div id="box" style="width:200px; height:100px; background-color:lightgray;">マウスを動かしてみて</div>

<script>
document.getElementById("box").addEventListener("mousemove", () => {
    console.log("🖱️ マウスが動いています");
});
document.getElementById("box").addEventListener("mouseover", () => {
    console.log("🔵 マウスがエリアに入りました");
});
document.getElementById("box").addEventListener("mouseout", () => {
    console.log("🔴 マウスがエリアから出ました");
});
</script>



マウスでカーソルを動かした時

<div id="scrollBox" style="width:200px; height:100px; overflow:auto; border:1px solid black;">
    <div style="height:500px;">スクロールしてみてください</div>
</div>
<script>
document.getElementById("scrollBox").addEventListener("scroll", () => {
    console.log("📜 スクロール中...");
});
</script>




ドラッグ操作

<div id="dragItem" draggable="true" style="width:100px; height:50px; background-color:lightblue;">ドラッグ</div>
<div id="dropZone" style="width:200px; height:100px; background-color:lightgray; margin-top:20px;">ここにドロップ</div>

<script>
const dragItem = document.getElementById("dragItem");
const dropZone = document.getElementById("dropZone");

dragItem.addEventListener("dragstart", () => {
    console.log("🏁 ドラッグ開始");
});
dragItem.addEventListener("dragend", () => {
    console.log("🏁 ドラッグ終了");
});
dropZone.addEventListener("dragenter", () => {
    console.log("⬆️ ドロップエリアに入った");
});
dropZone.addEventListener("dragover", (event) => {
    event.preventDefault(); // これがないと drop イベントが発生しない
    console.log("🎯 ドラッグ中...");
});
dropZone.addEventListener("dragleave", () => {
    console.log("⬇️ ドロップエリアを離れた");
});
dropZone.addEventListener("drop", () => {
    console.log("✅ 要素がドロップされた");
});
</script>




タッチ操作に関するイベント

touchstart
  ユーザーが指一本以上でタッチスクリーンに触れた時
touchmove
  ユーザーがタッチスクリーン上で指を動かしている間
touchend
  ユーザーがタッチスクリーンから指を離した時

<!DOCTYPE html>
<html lang="en">
<head>
    <meta charset="UTF-8">
    <meta name="viewport" content="width=device-width, initial-scale=1.0">
    <title>Touch Events Example</title>
    <style>
        #touchArea {
            width: 300px;
            height: 300px;
            background-color: #f4f4f4;
            border: 2px solid #ccc;
            margin: 20px;
            display: flex;
            align-items: center;
            justify-content: center;
            text-align: center;
        }
    </style>
</head>
<body>
    <div id="touchArea">
        Touch here
    </div>

    <script>
        const touchArea = document.getElementById('touchArea');

        touchArea.addEventListener('touchstart', function(event) {
            console.log('Touch started at position (' + event.touches[0].pageX + ', ' + event.touches[0].pageY + ')');
        });

        touchArea.addEventListener('touchmove', function(event) {
            // Prevent the window from scrolling
            event.preventDefault();
            console.log('Touch moved to position (' + event.touches[0].pageX + ', ' + event.touches[0].pageY + ')');
        }, { passive: false });

        touchArea.addEventListener('touchend', function(event) {
            console.log('Touch ended');
        });
    </script>
</body>
</html>




フォームを送信/リセットするメソッド

submit()


reset()


<button type="button" id="submitBtn">Submit Form</button>
<button type="button" id="resetBtn">Reset Form</button>



// エレメントを取得
var form = document.getElementById('myForm');
var submitBtn = document.getElementById('submitBtn');
var resetBtn = document.getElementById('resetBtn');

// submitボタンのクリックイベントハンドラ
submitBtn.addEventListener('click', function() {
    form.submit(); // フォームを送信
});

// resetボタンのクリックイベントハンドラ
resetBtn.addEventListener('click', function() {
    form.reset(); // フォームをリセット
});



e.preventDefault() を使用してフォーム送信を制御する

デフォルトのイベントの処理を発生させないようにする

<form id="myForm">
    <label for="username">ユーザー名:</label>
    <input type="text" id="username" name="username" required>
    <button type="submit">送信</button>
</form>

<div id="result"></div>



 
document.getElementById('myForm').addEventListener('submit', function(event) {
    event.preventDefault(); // フォームのデフォルトの送信動作を防ぐ

    const username = document.getElementById('username').value;
    // 結果を表示するための領域を取得
    const resultDiv = document.getElementById('result');

    // 入力されたユーザー名を表示(ここではサーバーへの送信は行わない)
    resultDiv.textContent = '送信されたユーザー名: ' + username;

    // 実際のアプリケーションではここで AJAX リクエストを使ってサーバーにデータを送信することができる
});
 





document.formsプロパティ

1)
document.forms[インデックス]


2)
document.forms.フォーム名


3)
document.forms["フォーム名"]

<form name="loginForm">
    <input type="text" name="username">
    <input type="password" name="password">
    <input type="submit" value="Login">
</form>


// document.forms[インデックス]
document.forms[0]

// document.forms.フォーム名
document.forms.loginForm;

// document.forms["フォーム名"]
document.forms["loginForm"];

form内のinputのアクセス

document.forms.loginForm.username
document.forms.loginForm.password




要素.onload
window.onload
DOMContentLoaded の読み込み


起動が早い順:
1) DOMContentLoaded

HTMLドキュメントが完全に読み込まれて解析された時点で起動す
(画像やスタイルシートは読み込まれなくても起動する)

2) 要素.onload
指定された単一の要素がロードされた後に起動

3) window.onload
ページ全体(すべての依存リソースを含む)がロードされた後に起動

document.addEventListener('DOMContentLoaded', function() {
    console.log('DOMが完全に読み込まれました。');
});





var image = document.getElementById('myImage');
image.onload = function() {
    console.log('画像が読み込まれました。');
};






window.onload = function() {
    console.log('すべてのリソースが読み込まれました。');
};







イベントの非同期処理を実現する方法

複数の処理を一時停止せずに進行し、別の処理が完了するのを待たずに後続の処理を実行する



非同期処理を使う方法:
コールバック関数
Promise
async / await
・setTimeout
・Ajax通信

コールバック関数

function fetchData(callback) {
    setTimeout(() => {
        callback('データが取得されました');
    }, 1000); // 1秒後にコールバックを実行
}

fetchData((data) => {
    console.log(data); // データが取得されました
});


Promise

.then()、.catch()、および .finally() メソッドを使う

function fetchData() {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve('データが取得されました');
        }, 1000);
    });
}

fetchData()
    .then(data => console.log(data)) // データが取得されました
    .catch(error => console.error(error))
    .finally(() => console.log('非同期処理が完了しました'));


async / await

async function fetchData() {
    return new Promise((resolve, reject) => {
        setTimeout(() => {
            resolve('データが取得されました');
        }, 1000);
    });
}

async function run() {
    try {
        const data = await fetchData();
        console.log(data); // データが取得されました
    } catch (error) {
        console.error(error);
    } finally {
        console.log('非同期処理が完了しました');
    }
}

run();


setTimeout

指定した時間が経過した後に関数を一度だけ実行するための関数
指定された遅延時間(ミリ秒)後に、関数が非同期的に実行される

1000ミリ秒 = 1秒

setTimeout(() => {
  console.log("This will be logged after 2 seconds");
}, 2000);



Ajax通信

ページ全体を再読み込みせずに、非同期でデータをサーバーとやり取りする技術

下記を使って実現する
XMLHttpRequest
fetch API
jQuery Ajax

fetch APIを使った例

fetch("https://jsonplaceholder.typicode.com/posts")
  .then(response => {
    if (!response.ok) {
      throw new Error("Network response was not ok");
    }
    return response.json();
  })
  .then(data => console.log(data))
  .catch(error => console.error("Fetch error:", error));



innerHTMLは += で連結できる
= を使うと上書きされる



<div id="example">Hello</div>


const div = document.getElementById("example");
div.innerHTML = "Goodbye"; // これにより "Hello" は "Goodbye" に置き換わる


<div id="example">Hello</div>


const div = document.getElementById("example");
div.innerHTML += ", World!"; // "Hello"", World!" を追加し、"Hello, World!" 


document.createAttributeとdocument.setAttributeの違いは


setAttribute は属性を設定
createAttributeは新しい要素を作成する

<div id="example">Hello, world!</div>


var div = document.getElementById("example");

// document.createAttribute (非推奨)
var newAttr = document.createAttribute("data-info");
newAttr.value = "some info";
div.setAttributeNode(newAttr);

// element.setAttribute (推奨)
div.setAttribute("data-role", "page");

console.log(div.getAttribute("data-info"));  // some info
console.log(div.getAttribute("data-role"));  // page


いいなと思ったら応援しよう!