Home

JS DOM and Event

Зміст

  1. Об'єктна модель документа
  2. Навігація по DOM
  3. Пошук елементів
  4. Властивості та атрибути
  5. Властивість textContent
  6. Властивість classList
  7. Властивість style
  8. Атрибути
  9. Створення та видалення елементів
  10. Оптимізація роботи з DOM
  11. Властивість innerHTML
  12. Метод insertAdjacentHTML()
  13. Підключення скриптів defer async
  14. Події addEventListener() removeEventListener()
  15. Ключове слово this
  16. Об'єкт події
  17. Дії браузера за замовчуванням - preventDefault()
  18. Події клавіатури
  19. Події елементів форм

Список основних методів

Пошук елемента

  • = document.querySelector('#menu');
  • = document.querySelector('.menu');
  • = document.querySelectorAll("li");
  • = document.querySelector('button[data-action="text"]');

Інлайн стилі

  • menu.style.textTransform = 'uppercase';

Навігації по ієрархії

  • elem.parentNode - вибере батьківський elem.
  • elem.childNodes - псевдомасив, зберігає всі дочірні елементи, включно з текстовими.
  • elem.children - псевдомасив, зберігає тільки дочірні вузли-елементи, тобто ті, що відповідають тегам.
  • elem.firstChild - вибере перший дочірній елемент всередині elem, включно з текстовими вузлами.
  • elem.firstElementChild - вибере перший дочірній вузол-елемент всередині elem.
  • elem.lastChild - вибере останній дочірній елемент всередині elem, включно з текстовими вузлами.
  • elem.lastElementChild - вибере останній дочірній вузол-елемент всередині elem.
  • elem.previousSibling - вибере елемент «зліва» від elem (його попереднього сусіда).
  • elem.previousElementSibling - вибере вузол-елемент «зліва» від elem (його попереднього сусіда).
  • elem.nextSibling - вибере елемент «праворуч» від elem (його наступного сусіда)
  • elem.nextElementSibling - вибере вузол-елемент «праворуч» від elem (його наступного сусіда).

Маніпуляції з класами

  • elem.classList.contains(cls) - повертає true або false
  • elem.classList.add(cls)
  • elem.classList.remove(cls)
  • elem.classList.toggle(cls)
  • elem.classList.replace(oldClass, newClass)

Маніпуляції з атрибутами

  • elem.hasAttribute(name)
  • elem.getAttribute(name)
  • elem.removeAttribute(name)
  • elem.attributes - об'єкт
  • elem.disabled=false;
  • elem.dataset.action // data-action="save"

Створення Видалення

  • document.createElement(tagName);
  • element.append(el1, el2, ...) - після всіх дітей елемента
  • element.prepend(el1, el2, ...) - перед усіма дітьми елемента
  • element.after(el1, el2, ...) - після елемента element
  • element.before(el1, el2, ...) - перед елемента element
  • elem.remove();

Об'єктна модель документа

Об'єктна модель документа (Document Object Model) - незалежний від мови інтерфейс для роботи з HTML-документом. Містить набір властивостей і методів, що дозволяють шукати, створювати і видаляти елементи, реагувати на дії користувача і багато іншого. Тобто з'єднує сторінку з мовою програмування.

DOM - це відображення HTML-документа, деревоподібна структура, в якій кожен вузол - це JavaScript-об'єкт з властивостями і методами, що становить частину HTML-документа. Кожен елемент в документі, весь документ в цілому, заголовок, посилання, абзац - це частини DOM цього документа, тому всі вони можуть бути змінені з JavaScript-коду.

Об'єктна модель браузера (Browser Object Model) - незалежний від мови інтерфейс для роботи з вкладкою браузера. Містить набір властивостей і методів, що дозволяють отримати доступ безпосередньо до поточної вкладки і ряду функцій браузера. Містить об'єкт роботи з історією навігації, місцем розташування та багато іншого.

js-dom.img

Навігація по DOM

document - це частина глобального об'єкта window, який доступний у скрипті, коли він виконується в браузері. Так само як alert, console.log, prompt і багато інших.

Найвищий елемент називається кореневим (root node).

Для навігації по цій ієрархії елементи мають наступні властивості:

  • elem.parentNode - вибере батьківський elem.
  • elem.childNodes - псевдомасив, зберігає всі дочірні елементи, включно з текстовими.
  • elem.children - псевдомасив, зберігає тільки дочірні вузли-елементи, тобто ті, що відповідають тегам.
  • elem.firstChild - вибере перший дочірній елемент всередині elem, включно з текстовими вузлами.
  • elem.firstElementChild - вибере перший дочірній вузол-елемент всередині elem.
  • elem.lastChild - вибере останній дочірній елемент всередині elem, включно з текстовими вузлами.
  • elem.lastElementChild - вибере останній дочірній вузол-елемент всередині elem.
  • elem.previousSibling - вибере елемент «зліва» від elem (його попереднього сусіда).
  • elem.previousElementSibling - вибере вузол-елемент «зліва» від elem (його попереднього сусіда).
  • elem.nextSibling - вибере елемент «праворуч» від elem (його наступного сусіда)
  • elem.nextElementSibling - вибере вузол-елемент «праворуч» від elem (його наступного сусіда).

Приклад codepen. Example 1

    <ul class="list">
        <li>First item</li>
        <li>Second item</li>
        <li>Third item</li>
        <li>Fourth item</li>
        <li>Fifth item</li>
    </ul>
    console.log(document);

    const body = document.body;
    console.log(body);

    const list = document.querySelector(".list");
    console.log(list);

    const firstListItem = list.firstElementChild;
    console.log(firstListItem);

    const lastListItem = list.lastElementChild;
    console.log(lastListItem);

    const listItems = list.children;
    console.log(listItems);

Пошук елементів

Отже, ми вже знаємо що DOM-елемент - це об'єкт з властивостями і методами. Саме час навчитися швидко знаходити елемент за довільним CSS-селектором. Група методів elem.querySelector* - це сучасний стандарт для пошуку елементів. Вони дозволяють знайти елемент або групу елементів за CSS-селектором будь-якої складності.

element.querySelector(selector);
  • Використовується, якщо необхідно знайти тільки один, найчастіше унікальний елемент.
  • Повертає перший знайдений елемент всередині element, що відповідає CSS-селектору selector.
  • Якщо нічого не знайдено, поверне null.
element.querySelectorAll(selector);
  • Використовується, якщо необхідно знайти колекцію елементів, тобто отримати масив посилань на елементи з однаковим селектором. Наприклад, всі елементи списку з класом menu-item
  • Повертає псевдомасив всіх елементів всередині element, які відповідають CSS-селектору selector.
  • Якщо нічого не знайдено, поверне порожній масив.

Приклад codepen

    <ul id="menu" class="menu">
        <li class="menu-item">home</li>
        <li class="menu-item">about</li>
        <li class="menu-item">gallery</li>
        <li>blog</li>
    </ul>
    const listWithId = document.querySelector('#menu');
    listWithId.style.textTransform = 'uppercase';
    listWithId.style.fontSize = '24px';
    console.log(listWithId);

    const listWithClass = document.querySelector('.menu');
    console.log(listWithClass);

    const menuItemsByTagName = document.querySelectorAll("li");
    console.log(menuItemsByTagName);

    const menuItemsByClass = document.querySelectorAll(".menu-item");
    console.log(menuItemsByClass);

    const firstMenuItem = document.querySelector(".menu-item");
    firstMenuItem.style.color = 'tomato';
    console.log(firstMenuItem);

Властивості та атрибути

Під час побудови DOM-дерева, деякі стандартні HTML-атрибути стають властивостями елементів. Подивимося на декілька властивостей, які часто використовуються.

  • value - містить поточний текстовий контент елементів форм
  • checked - зберігає стан чекбокса або радіокнопки.
  • name - зберігає значення, вказане в HTML-атрибуті name.
  • src - шлях до зображення тегу img.
    <img class="image" 
        src="https://picsum.photos/id/9/320/240" 
        alt="A laptop" 
        width="300" />
A laptop
    const image = document.querySelector(".image");
    console.log(image.src); // https://picsum.photos/id/9/320/240
    console.log(image.alt); // A laptop

    image.src = "https://picsum.photos/id/13/640/480";
    image.alt = "River bank";

(item.dataset.color = color) === (data-color="#7E0D44")

Властивість textContent

Example-2

elem.textContent повертає текстовий контент всередині елемента. Доступний для читання і запису. Неважливо, що буде передано в textContent, дані завжди будуть записані як текст.

    const titleEl = document.querySelector(".article-title");
    titleEl.textContent = 'Welcome to Bahamas!';

Властивість classList

У властивості classList зберігається об'єкт з методами для роботи з класами елемента.

  • elem.classList.contains(cls) - повертає true або false, залежно від наявності класу cls в елемента.
  • elem.classList.add(cls) - додає клас cls до списку класів елемента.
  • elem.classList.remove(cls) - видаляє клас cls зі списку класів елемента.
  • elem.classList.toggle(cls) - якщо відсутній клас cls, то додає його, якщо - присутній, навпаки - видаляє.
  • elem.classList.replace(oldClass, newClass) - замінює існуючий клас oldClass на вказаний newClass.
    HTML
    <a class="link is-active" href="">A random link</a>

    JS
    const link = document.querySelector(".link");
    console.log(link.classList);

    const hasActiveClass = link.classList.contains("is-active");
    console.log(`hasActiveClass - ${hasActiveClass}`);

    link.classList.add("special");
    console.log(link.classList);

    link.classList.remove("is-active");
    console.log(link.classList);

    link.classList.toggle("is-active");
    console.log(link.classList);

    link.classList.replace("special", "regular");
    console.log(link.classList);

Властивість style​

Використовується для читання та зміни інлайнових стилів. Повертає об'єкт CSSStyleDeclaration, який містить список усіх властивостей, визначених тільки у вбудованих стилях елемента, а не увесь CSS. Під час запису властивості записуються в camelCase, тобто background-color перетворюється на element.style.backgroundColor тощо.

    const button = document.querySelector(".btn");

    button.style.backgroundColor = "teal";
    button.style.fontSize = "24px";
    button.style.textAlign = "center";
    arrowSecond.style = "transform: rotate(60deg)"; 
    arrowSecond.style.transform = "rotate(45deg)";

На практиці стилізація елементів виконується шляхом додавання CSS-класів. Властивість style використовується для додавання будь-яких динамічних стилів, наприклад, під час анімації.

Атрибути

Доступ до атрибутів здійснюється за допомогою стандартних методів. Ці методи працюють зі значенням, яке знаходиться в HTML.

  • elem.hasAttribute(name) - перевіряє наявність атрибута, повертає true або false.
  • elem.getAttribute(name) - отримує значення атрибута і повертає його.
  • elem.setAttribute(name, value) - встановлює атрибут.
  • elem.removeAttribute(name) - видаляє атрибут.
  • elem.attributes - властивість, що повертає об'єкт усіх атрибутів елемента.
    const image = document.querySelector(".image");

    console.log(image.attributes); 
            // NamedNodeMap {0: class, 1: src, 2: alt, length: 3}
    console.log(image.hasAttribute("src")); // true
    console.log(image.getAttribute("alt")); // "Rocks and waterfall"
    image.setAttribute("alt", "Amazing nature");
    console.log(image.getAttribute("alt")); // Amazing

data-атрибути

Дозволяють додати до тегу довільний атрибут і отримати його значення в JavaScript. Цю можливість використовують для того, щоб спростити написання коду, наприклад, зв'язати дані і розмітку за унікальним ідентифікатором, вказати тип дії кнопки тощо

Для отримання значення data-атрибута використовується властивість dataset, після якого стоїть ім'я атрибута. Тобто data- відкидається, а інша частина імені записується як ім'я властивості об'єкта.

    <button type="button" data-action="save">Save</button>

    const saveBtn = document.querySelector('button[data-action="save"]');
    console.log(saveBtn.dataset.action); // "save"

Створення та видалення елементів

DOM API дозволяє не тільки вибирати або змінювати вже існуючі, але й видаляти, а також створювати нові елементи, після чого додавати їх в документ.

Створення

    document.createElement(tagName);

Елемент створюється в пам'яті, в DOM його ще немає.

Додавання

Щоб створений елемент відображався на сторінці, його необхідно додати до вже існуючого елемента в DOM-дереві.

для цього існують методи:

  • element.append(el1, el2, ...) - додає один або декілька елементів після всіх дітей елемента element.
  • element.prepend(el1, el2, ...) - додає один або декілька елементів перед усіма дітьми елемента element.
  • element.after(el1, el2, ...) - додає один або декілька елементів після елемента element.
  • element.before(el1, el2, ...) - додає один або декілька елементів перед елементом element.
    <h1>Usernames</h1>
    <ul class="usernames">
        <li>Mango</li>
    </ul>

    const list = document.querySelector(".usernames");

    const item = document.createElement("li");
    item.textContent = "Poly";
    list.append(item);

Перевірити!!!!

Якщо елемент для додавання вже знаходиться в DOM, то він видаляється зі свого старого місця і додається у нове. З цього випливає правило - один і той самий елемент не може бути одночасно у двох місцях.

Видалення

    elem.remove();

Для того, щоб видалити елемент, використовується метод remove(). Він викликається на елементі elem, який необхідно видалити.

Example

    <p class="text">Text</p>

    const text = document.querySelector('.text');
    text.remove();

Оптимізація роботи з DOM

зміна DOM-дерева - це дорога операція, тому необхідно намагатися мінімізувати кількість звернень до DOM.

Repaint - відбувається, коли зміни торкнулися стилів, що впливають на зовнішній вигляд елемента, але не на геометрію.

Reflow - відбувається, коли зміни впливають на вміст, структуру документу, положення елементів. Відбувається перерахунок позиціонування і розмірів, що призводить до повторного створення частини або всього документу.

Сторінка не може виконувати жодні інші операції у той час, коли відбувається reflow або repaint.

Причинами можуть бути:

  • Маніпуляції з DOM (додавання, видалення, зміна, перестановка елементів)
  • Зміна вмісту, зокрема тексту в полях форм
  • Розрахунок або зміна CSS-властивостей
  • Додавання і видалення таблиць стилів
  • Маніпуляції з атрибутом class
  • Маніпуляції з вікном браузера (зміни розмірів, прокручування)
  • Активація псевдокласів (наприклад, ':hover')

Властивість innerHTML

Ще один спосіб створити DOM-елементи і помістити їх в дерево - це використовувати рядки з тегами і дозволити браузеру зробити всю важку роботу. У такого підходу є свої плюси і мінуси.

Читання

Властивість innerHTML зберігає вміст елемента, включно з тегами, у вигляді рядка. Значення, що повертається, - це завжди валідний HTML-код.

    const article = document.querySelector(".article");
    console.log(article.innerHTML);

Зміна

Властивість innerHTML доступна і для читання, і для запису. Якщо записати в неї рядок з HTML-тегами, то браузер під час парсингу рядка перетворить їх у валідні елементи і додасть в DOM-дерево.

    const title = document.querySelector(".article .title");
    title.innerHTML = 'New and <span class="accent">improved</span> title';

Якщо у властивість innerHTML записати порожній рядок, то вміст елемента буде очищено. Це простий і швидкий спосіб видалення всього вмісту.

Однотипна (шаблонна) розмітка створюється із масиву даних. Прийом полягає у перебиранні цього масиву і складанні одного рядка з HTML-тегами, який потім записуємо в innerHTML елемента.

Example-5

    <ul class="list"></ul>

    const technologies = ["HTML", "CSS", "JS", "React", "Node"];
    const list = document.querySelector(".list");

    const markup = technologies
    .map((technology) => `<li class="list-item">${technology}</li>`)
    .join("");

    list.innerHTML = markup;

Додавання

Зміна elem.innerHTML повністю видалить і повторно створить всі нащадки елемента elem. Якщо елемент спочатку не був порожній, то виникнуть додаткові витрати на серіалізацію вже існуючої розмітки, а це погано.

Використовуйте властивість elem.innerHTML для додавання тільки тоді, коли елемент elem - порожній, або якщо потрібно повністю замінити його вміст.

Метод insertAdjacentHTML()

Сучасний метод для додавання рядка з HTML-тегами перед, після або всередину елемента. Вирішує проблему innerHTML з повторною серіалізацією вмісту елемента під час додавання розмітки до вже існуючої.

    elem.insertAdjacentHTML(position, string);
                

Аргумент position - це рядок, позиція щодо елемента elem. Приймає одне з чотирьох значень

  • "beforebegin" - перед elem
  • "afterbegin" - всередині elem, перед усіма дітьми
  • "beforeend" - всередині elem, після усіх дітей
  • "afterend" - після elem

"beforebegin" і "afterend" працюють тільки тоді, коли elem вже знаходиться в DOM-дереві.

Example-6

    const list = document.querySelector(".list");
    list.insertAdjacentHTML("beforeend", markup);
    list.insertAdjacentHTML("beforebegin", 
            "<h2>Popular technologies</h2>");

Підключення скриптів

Завантаження і виконання скрипта, зазначеного в тезі /script/ без будь-яких атрибутів, блокують обробку HTML-документа і побудову DOM. Це проблема.

    <script src="path-to-script.js"></script>

Коли аналізатор зустрічає такий тег, обробка HTML-документа припиняється і починається завантаження файлу скрипта, зазначеного в атрибуті src. Після завантаження скрипт виконується, і тільки потім відновлюється обробка HTML. Це називається «блокуючий» скрипт.

Атрибут defer

    <script defer src="path-to-script.js"></script>

Атрибут defer вказує браузеру завантажувати файл скрипта у фоновому режимі, паралельно обробці HTML-документа і побудові DOM. Скрипт буде виконаний тільки після того, як HTML- документ був оброблений, а DOM побудований. Такі скрипти не блокують побудову DOM-дерева і гарантовано виконуються у тому порядку, в якому вказані в HTML-документі.

Атрибут async

    <script async src="path-to-script.js"></script>

Завантаження скрипта з атрибутом async не блокує побудову DOM, але він виконується відразу після завантаження. Це означає, що такі скрипти можуть заблокувати побудову DOM, і виконуються у довільному порядку.

Події

Існує багато видів подій: миші, клавіатури, елементів форм, завантаження зображень, буфера обміну, зміни стадії CSS анімації або переходу, зміни розмірів вікна та багато інших.

Одна дія може викликати декілька подій. Наприклад, клік викликає спочатку mousedown, а потім mouseup і click.

Для того, щоб елемент реагував на дії користувача, до нього необхідно додати слухача (обробника) події. Тобто функцію, яка буде викликана, щойно подія відбулася.

Метод addEventListener()

    element.addEventListener(event, handler, options);
  • event - ім'я події, рядок, наприклад "click".
  • handler - колбек-функція, яка буде викликана під час настання події.
  • options - необов'язковий об'єкт параметрів з розширеними налаштуваннями.
    const button = document.querySelector(".my-button");

    button.addEventListener("click", () => {
      console.log("Button was clicked");
    });

    або
    const handleClick = () => {
        console.log("Button was clicked");
      };
      
      button.addEventListener("click", handleClick); 

На одному елементі може бути будь-яка кількість обробників подій, навіть подій одного типу. Колбек-функції будуть викликатися у порядку їх реєстрації в коді.

    const multiBtn = document.querySelector("#multiple");

    const firstCallback = () => {
      console.log("First callback!");
    };
    const secondCallback = () => {
      console.log("Second callback!");
    };

    multiBtn.addEventListener("click", firstCallback);
    multiBtn.addEventListener("click", secondCallback);

Метод removeEventListener()

Видаляє слухача події з елемента. Аргументи аналогічні методу addEventListener().

    element.removeEventListener(event, handler, options);

Для видалення потрібно передати посилання саме на ту колбек-функцію, яка була призначена в addEventListener(). У такому разі, для колбеків використовують окрему функцію і передають її за ім'ям (посиланням).

Ключове слово this

Якщо колбеком буде функція, яка використовує this, за замовчуванням контекст всередині неї буде посилатися на DOM-елемент, на якому висить слухач.

    const mango = {
        username: "Mango",
        showUsername() {
          console.log(this);
          console.log(`My username is: ${this.username}`);
        },
      };
      
      const btn = document.querySelector(".js-btn");
      
      // ✅ Працює
      mango.showUsername();
      
      // ❌ this буде посилатися на button, якщо 
      використовувати showUsername як callback
      btn.addEventListener("click", mango.showUsername); // не працює
      
      // ✅ Не забувайте прив'язувати контекст методів об'єкта
      btn.addEventListener("click", mango.showUsername.bind(mango)); 

Об'єкт події

Щоб обробити подію - недостатньо знати про те, що це клік або натискання клавіші, можуть знадобитися деталі. Наприклад, поточне значення текстового поля, елемент, на якому відбулася подія, вбудовані методи та інші.

Кожна подія - це об'єкт, який містить інформацію про деталі події та автоматично передається першим аргументом в обробник події. Всі події відбуваються з базового класу Event

    const handleClick = event => {
        console.log(event);
      };
      
      button.addEventListener("click", handleClick);

Ми можемо називати його як завгодно, але, як правило, його оголошують як e, evt або event.

Деякі властивості об'єкта події:

  • event.type - тип події.
  • event.currentTarget - елемент, на якому виконується обробник події.
  • event.clientX
  • event.clientY
  • event.offsetX
  • event.offsetY
  • event.screenX
  • event.screenY

Дії браузера за замовчуванням

Form

Для скасування дії браузера за замовчуванням в об'єкта події є стандартний метод preventDefault().

    const form = document.querySelector(".register-form");

    form.addEventListener("submit", (event) => {
      event.preventDefault();
      const {
        elements: { username, password }
      } = event.currentTarget;
      console.log(username.value, password.value);
    });

Події клавіатури

Існує дві основні події клавіатури: keydown і keyup.

На відміну від інших, події клавіатури обробляються на документі, а не на конкретному елементі. Об'єкти подій клавіатури походять від базового класу KeyboardEvent.

    document.addEventListener("keydown", event => {
        console.log("Keydown: ", event);
      });
      
      document.addEventListener("keyup", event => {
        console.log("Keyup: ", event);
      });

Натискаючи клавішу, спочатку відбувається keydown, після чого - keyup

На практиці переважно обробляють тільки подію keydown, оскільки вона відбувається швидше за keyup

Раніше була ще одна подія клавіатури - keypress. вона застаріла

Властивості key і code​

key повертає символ, згенерований натисканням клавіші, враховуючи стан клавіш-модифікаторів, наприклад, Shift, а також поточну мову.

Властивість code повертає код фізичної клавіші на клавіатурі і не залежить від мови.

    codepen
    document.addEventListener("keydown", event => {
        console.log("key: ", event.key);
        console.log("code: ", event.code);
      });
    document.addEventListener("keydown", logMessage);
    document.addEventListener("keyup", logMessage);

    function logMessage({ type, key, code }) {
      const markup = `<div class="log-item">
     <span class="chip">${keypressCounter}</span>
       <ul>
           <li>Event: ${type}</li>
           <li>Key: ${key}</li>
           <li>Code: ${code}</li>
       </ul>
       </div>`;

    logList.insertAdjacentHTML("afterbegin", markup);
    }

Клавіші-модифікатори

Для обробки комбінації клавіш, наприклад Ctrl + s або будь-якої іншої, на об'єкті події є властивості ctrlKey, altKey, shiftkey і metaKey, що зберігають булеве значення, яке сигналізує про те, чи була затиснута клавіша-модифікатор.

    document.addEventListener("keydown", event => {
        event.preventDefault();
      
        if ((event.ctrlKey || event.metaKey) && event.code === "KeyS") {
          console.log("«Ctrl + s» or «Command + s» combo");
        }
      });

Деякі комбінації клавіш можуть конфліктувати з поведінкою браузера за замовчуванням. Наприклад, Ctrl + d або Command + d робить закладку. Потрібно намагатися проектувати систему комбінацій сторінки таким чином, щоб вона не перетиналася із вбудованою у браузері. Але, у крайньому разі, поведінку за замовчуванням можна скасувати, викликавши метод event.preventDefault().

властивість keyCode - застаріла

Форми. Події елементів форм

Подія submit​

Відправлення форми відбувається під час кліку по кнопці з атрибутом type="submit" або натискання клавіші Enter, перебуваючи в будь-якому її текстовому полі.

Сабміт форми перезавантажує сторінку, тому не забувайте скасовувати дію за замовчуванням методом preventDefault().

    codepen                
    const registerForm = document.querySelector(".form");

    registerForm.addEventListener("submit", handleSubmit);

    function handleSubmit(event) {
      event.preventDefault();
      const form = event.target;
      const login = form.elements.login.value;
      const password = form.elements.password.value;
    
      if (login === "" || password === "") {
        return console.log("Please fill in all the fields!");
      }

      console.log(`Login: ${login}, Password: ${password}`);
      form.reset();
    }

Властивість elements DOM-елемента форми містить об'єкт з посиланнями на усі її елементи, які мають атрибут name. Тому в прикладі ми отримуємо значення полів, звертаючись до login.value і password.value.

Подія change

Відбувається після зміни елемента форми. Для текстових полів або textarea подія відбудеться не на кожному введенні символу, а після втрати фокусу, що не завжди зручно. Наприклад, доки ви набираєте щось у текстовому полі - подія відсутня, але як тільки фокус пропав, відбудеться подія change. Для інших елементів, наприклад, select, чекбоксів і радіо-кнопок, подія change спрацьовує відразу під час вибору значення.

    codepen 
    HTML
    <p>
        Selected option text: <span class="text-output">none</span>
    <p>
    <p>
        Selected option value: <span class="value-output">none</span>
    <p>

  <select class="pizza-select">
    <option value="four_meats">Four Meats</option>
    <option value="royal_cheese">Royal Cheese</option>
    <option value="vegetarian">Vegetarian</option>
    <option value="smoked_salmon">Smoked Salmon</option>
  </select>
                
    const select = document.querySelector(".pizza-select");
    const textOutput = document.querySelector(".text-output");
    const valueOutput = document.querySelector(".value-output");

    select.addEventListener("change", setOutput);

    function setOutput(event) {
      const selectedOptionValue = event.currentTarget.value;
      const selectedOptionIndex = event.currentTarget.selectedIndex;
      const selectedOptionText =
        event.currentTarget.options[selectedOptionIndex].text;

      textOutput.textContent = selectedOptionText;
      valueOutput.textContent = selectedOptionValue;
    }

Select Плюшки

    <select id="select-name" name="select" required>
        <option value="" disabled selected>Оберіть значення</option>
        <option value="value1">Значение 1</option>
        <option value="value2">Значение 2</option>
        <option value="value3">Значение 3</option>
    </select>
                
  • disabled – забороняє вибір цього пункту.
  • selected – робить його початковим.
  • required – робить його обов’язкове у формі. Тепер форма не відправиться, поки користувач не вибере значення.

Якщо ви хочете отримати значення value="value3", ви можете зробити це кількома способами:

const mySelect = document.querySelector("#select-name");
  1. Отримати вибране значення (.value):
        const selectedValue = mySelect.value;
        console.log(selectedValue);
                            
    Якщо користувач вибрав "Значение 3", то selectedValue буде "value3".
  2. Отримати конкретний
  3. Встановити вибране значення:
        mySelect.value = "value3";
        console.log(mySelect.value); // value3
                            
  4. Отримати всі варіанти (.options):
        console.log(mySelect.options.length); // 3
        for (let option of mySelect.options) {
            if (option.value === "value3") {
              console.log(option.text); // Значение 3
            }
          }
                            

Подія input​

Відбувається тільки на текстових полях і textarea, і створюється щоразу при зміні значення елемента, не чекаючи втрати фокусу. На практиці input - це найголовніша подія для роботи з текстовими полями форми.

    codepen  
    HTML
    <input type="text" class="text-input" />
    <p>Text field value: <span class="output"></span></p>

    JS
    const textInput = document.querySelector(".text-input");
    const output = document.querySelector(".output");

    textInput.addEventListener("input", (event) => {
    output.textContent = event.currentTarget.value;
    });

Подія focus і blur

Елемент отримує фокус під час кліку миші або переходу клавішею Tab. Момент отримання і втрати фокусу - дуже важливий, отримуючи фокус, ми можемо завантажити дані для автозаповнення, почати відстежувати зміни тощо. Під час втрати фокусу - перевірити введені дані.

Під час фокусування елемента відбувається подія focus, а коли фокус зникає, наприклад, користувач клікає в іншому місці екрана, відбувається подія blur.

Активувати або скасувати фокус можна програмно, викликавши в коді для елемента однойменні методи focus() і blur().

    codepen
    const textInput = document.querySelector(".text-input");
    const setFocusBtn = document.querySelector('[data-action="set"]');
    const removeFocusBtn = document.querySelector('[data-action="remove"]');

    setFocusBtn.addEventListener("click", () => {
      textInput.focus();
    });

    removeFocusBtn.addEventListener("click", () => {
      textInput.blur();
    });

    textInput.addEventListener("focus", () => {
      textInput.value = "This input has focus";
    });

    textInput.addEventListener("blur", () => {
      textInput.value = "";
    });

Фокус може бути тільки на одному елементі сторінки за одиницю часу, і поточний елемент, на якому знаходиться фокус, доступний як document.activeElement.