На картинке ниже в общих чертах показано, что доступно для JavaScript в браузерном окружении:
Document Object Model, сокращённо DOM – объектная модель документа, которая представляет все содержимое страницы в виде объектов, которые можно менять.
DOM - описывает структуру документа, манипуляции с контентом и события
Объектная модель браузера (Browser Object Model, BOM) – это дополнительные объекты, предоставляемые браузером (окружением), чтобы работать со всем, кроме документа
В соответствии с объектной моделью документа («Document Object Model», коротко DOM), каждый HTML-тег является объектом. Вложенные теги являются «детьми» родительского элемента. Текст, который находится внутри тега, также является объектом.
<!DOCTYPE HTML>
<html>
<head>
<title>О лосях</title>
</head>
<body>
Правда о лосях.
</body>
</html>Пробелы, комментарии и переводы строки – это полноправные символы, как буквы и цифры. Они образуют текстовые узлы и становятся частью дерева DOM.
<!DOCTYPE HTML>
<html><head><title>О лосях</title></head><body>Правда о лосях.</body></html>Если браузер сталкивается с некорректно написанным HTML-кодом, он автоматически корректирует его при построении DOM.
<ul>
<li>Мама
<li>и
<li>Папа
</ul>
<ul>
<li>Мама</li>
<li>и</li>
<li>Папа</li>
</ul>const unsigned short ELEMENT_NODE = 1;
const unsigned short ATTRIBUTE_NODE = 2;
const unsigned short TEXT_NODE = 3;
const unsigned short CDATA_SECTION_NODE = 4;
const unsigned short ENTITY_REFERENCE_NODE = 5; // legacy
const unsigned short ENTITY_NODE = 6; // legacy
const unsigned short PROCESSING_INSTRUCTION_NODE = 7;
const unsigned short COMMENT_NODE = 8;
const unsigned short DOCUMENT_NODE = 9;
const unsigned short DOCUMENT_TYPE_NODE = 10;
const unsigned short DOCUMENT_FRAGMENT_NODE = 11;
const unsigned short NOTATION_NODE = 12; // legacy
DOCUMENT_NODE - document – «входная точка» в DOM.
ELEMENT_NODE - HTML-теги, основные строительные блоки.
TEXT_NODE - текстовые узлы – содержат текст.
ATTRIBUTE_NODE - аттрибуты элементов
Дочерние узлы (или дети) – элементы, которые являются непосредственными детьми узла. Другими словами, элементы, которые лежат непосредственно внутри данного. Например,<head> и <body> являются детьми элемента <html>.
Потомки – все элементы, которые лежат внутри данного, включая детей, их детей и т.д.
<body>
<section>
<div>Начало <span>hello</span></div>
<ul>
<li>
<b>Информация</b>
</li>
</ul>
</section>
</body>section - Дочерние узлы - div, ul
section - Потомки div, span, ul, li, b
Коллекция childNodes содержит список всех детей, включая текстовые узлы.
Свойства firstChild и lastChild обеспечивают быстрый доступ к первому и последнему дочернему элементу.
nextSibling - следующий узел того же родителя (следующий сосед)
previousSibling - предыдущий узел того же родителя (следующий сосед)
children – коллекция детей, которые являются элементами.
firstElementChild, lastElementChild – первый и последний дочерний элемент.
previousElementSibling, nextElementSibling – соседи-элементы.
parentElement – родитель-элемент.
https://htmlacademy.ru/blog/js/collections-js
https://learn.javascript.ru/searching-elements-dom#zhivye-kollektsii
children - возвращает HTMLCollection
childNodes - возвращает NodeList
Живые(динамические, HTMLCollection) и неживые(статические, NodeList) коллекции в JavaScript
То есть либо реагируют на любое изменение DOM, либо нет.
<ul>
<li class="list">Список 1</li>
<li class="list">Список 2</li>
<li class="list">Список 3</li>
<li class="list">Список 4</li>
</ul>const elements = document.querySelectorAll('.list')
elements.forEach((element) => {
element.classList.add('red');
})
for (const element of elements) {
element.classList.add('green');
}
for (const key in elements) {
console.log(key)
}
[...elements].forEach((element) => {
element.classList.add('red');
})
Array.from(elements).forEach((element) => {
element.classList.add('blue');
});
for (let i = 0; i < elements.length; i++) {
console.log(elements[i])
}
[].forEach.call(elements, function(ele) {
...
});<div id="elem" class="my-class">
<div name="xgggg" id="elem-content">Element</div>
</div>const byId = document.getElementById('elem');
const tagName = document.getElementsByTagName('div');
const className = document.getElementsByClassName('my-class');
const byName = document.getElementsByName('xgggg');<ul>
<li>Этот</li>
<li>тест</li>
</ul>
<ul>
<li>полностью</li>
<li>пройден</li>
</ul>let elements = document.querySelectorAll('ul > li:last-child');
let element = document.querySelector('ul > li:last-child');<article class="article">
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Suscipit commodi, adipisci ex tenetur eius alias vitae dicta tempora, <small>minus rerum laudantium magni</small> reprehenderit eum perferendis! Molestias cupiditate ratione fugiat sapiente.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Suscipit commodi, adipisci ex tenetur eius alias vitae dicta tempora, minus rerum laudantium magni reprehenderit <small>eum perferendis</small>! Molestias cupiditate ratione fugiat sapiente.</p>
<p class="current">Lorem ipsum dolor sit amet, consectetur adipisicing elit. Suscipit commodi, adipisci ex tenetur eius alias vitae dicta tempora, minus rerum laudantium magni reprehenderit eum perferendis! Molestias cupiditate ratione fugiat sapiente.</p>
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Suscipit commodi, adipisci ex tenetur eius alias vitae dicta tempora, minus rerum laudantium magni reprehenderit eum perferendis! Molestias cupiditate ratione fugiat sapiente.</p>
</article>const article = document.querySelector('.article');
const articleParagraphs = article.querySelectorAll('p')
articleParagraphs.forEach((paragraph) => {
paragraph.querySelector('small')?.classList.add('red');
})
const article = document.querySelector('.article');
// const paragraph = article.querySelector('p')
// const small = article.querySelector('small')
const paragraph = article.firstElementChild
paragraph.nextElementSibling.classList.add('red');Предки элемента – родитель, родитель родителя, его родитель и так далее. Вместе они образуют цепочку иерархии от элемента до вершины.
<h2 class="test">Test</h2>
<div class="contents">
<ul class="book">
<li class="chapter">Глава 1</li>
<li class="chapter">Глава 2</li>
</ul>
</div>const chapter = document.querySelector('.chapter');
chapter.closest('.book') // UL
chapter.closest('.contents') // DIV
chapter.closest('.test') // nullhttps://developer.mozilla.org/en-US/docs/Web/HTML/Element/input
Атрибуты – это то, что написано в HTML.
Свойства – это то, что находится в DOM-объектах.
<input type="text" value="">let input = document.querySelector('input');
input.setAttribute('id', 'main');
console.log(input.id) // main
input.id = 'newId';
input.getAttribute('id') // newId (обновлено)
input.setAttribute('value', 'новое значение');
console.log(input.value) // 'новое значение'
input.value = 'newValue';
console.log(input.getAttribute('value')) // 'новое значение'- elem.hasAttribute(name) – проверить на наличие.
- elem.getAttribute(name) – получить значение.
- elem.setAttribute(name, value) – установить значение.
- elem.removeAttribute(name) – удалить атрибут.
- elem.toggleAttribute(name, force) - переключить
- elem.attributes – это коллекция всех атрибутов.
<form>
<label>
<input type="radio" name="choice" value="1" checked>
Человек
</label>
<label>
<input type="radio" name="choice" value="2">
Робот
</label>
</form>const choise = document.querySelector('input[name="choice"][checked]').value;
const example = document.querySelectorAll('form input')
example.forEach((radio) => {
console.log(radio.checked);
})
const choise2 = document.querySelector('input[name="choice"]:checked').value;
const radio1 = document.querySelectorAll('form input')[0]
const radio2 = document.querySelectorAll('form input')[1]
radio2.setAttribute('checked', true);<!-- example.com -->
<a href="#footer">Перейти</a>const link = document.querySelector('a');
link.href // https://example.com/#footer
link.getAttribute('href') // #footer<div class="order" data-order-state="new">
A new order.
</div>const order = document.querySelector('.order')
order.dataset.orderState // new
order.dataset.orderState = "pending"innerHTML — свойство, которое используется для установки или получения разметки элемента.
innerHTML удобно использовать, чтобы быстро очистить содержимое элемента.
<div class="content">
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit, sed do eiusmod tempor incididunt ut <strong>labore et dolore magna aliqua</strong>. Ut enim ad minim veniam,</p>
</div>const content = document.querySelector('.content');
content.innerHTML //
content.innerHTML = 'hello world <s>old text</s>'
content.innerHTML = ''Свойство innerHTML не рекомендуется использовать для вставки пользовательских (или непроверенных) данных, так как это потенциальная уязвимость XSS.
innerText — это свойство, которое позволяет задавать или получать текстовое содержимое элемента и его потомков. Метод умеет считывать стили и не возвращает содержимое скрытых элементов.
<p>Lorem <span style="display: none;">ipsum dolor sit amet, consectetur</span> adipisicing elit, sed do eiusmod tempor incididunt ut <strong>labore et dolore magna aliqua</strong>. Ut enim ad minim veniam</p>const paragraph = document.querySelector('p');
paragraph.innerTexttextContent — это свойство, также как и innerText, позволяет получить текстовый контент элемента и его потомков. Но в отличие от innerText свойство возвращает полный текст, включая то, что содержится в тегах <script> и <style>.
<p>Lorem <span style="display: none;">ipsum dolor sit amet, consectetur</span> adipisicing elit, sed do eiusmod tempor incididunt ut <strong>labore et dolore magna aliqua</strong>. Ut enim ad minim veniam</p>const paragraph = document.querySelector('p');
paragraph.textContent
paragraph.textContent = "<div>hello</div> asdasd"Свойство textContent предназначено для получения и записи только текста, если попытаться записать в него HTML-теги, браузер их не поймёт.
Свойство nodeType позволяет узнать тип DOM-узла. Его значение – числовое: 1 для элементов, 3 для текстовых узлов, и т.д. Только для чтения.
Для элементов это свойство возвращает название тега (записывается в верхнем регистре, за исключением XML-режима).
Внутреннее HTML-содержимое узла-элемента. Можно изменять.
Полный HTML узла-элемента. Запись в elem.outerHTML не меняет elem. Вместо этого она заменяет его во внешнем контексте.
Содержимое узла-неэлемента (текст, комментарий).
Текст внутри элемента: HTML за вычетом всех <тегов>.
hidden
Когда значение установлено в true, делает то же самое, что и CSS display:none.
<article class="article" style="font-size:20px;">
<p>Lorem ipsum dolor sit amet, consectetur adipisicing elit. Suscipit commodi, adipisci ex tenetur eius alias vitae dicta tempora, <small>minus rerum laudantium magni</small> reprehenderit eum perferendis! Molestias cupiditate ratione fugiat sapiente.</p>
</article>const article = document.querySelector('.article');
article.classList.add("class") – добавить класс.
article.classList.remove("class") – удалить класс.
article.classList.toggle("class") – добавить класс, если его нет, иначе удалить.
article.classList.contains("class") – проверка наличия класса, возвращает `true/false`const article = document.querySelector('.article');
article.style.backgroundColor = "red"
article.style.cssText = `color: red !important;
background-color: yellow;
width: 100px;
text-align: center;
`;Не забудьте добавить к значениям единицы измерения.
article.style.margin = 20px;
const title = 'Название'
const description = 'Описание'
const div = document.createElement('div');
div.className = 'item';
div.innerHTML =
`<a class="card-link" href="#">
<h3>${title}</h3>
<p>${description}</p>
</a>`;
const email = document.createElement('input');
email.setAttribute('type', 'text');
email.setAttribute('name', 'fio');
email.setAttribute('required', 'required');
const logo = document.createElement('img');
logo.className = "logo"
logo.src = "logo.png"
let textNode = document.createTextNode('А вот и я');div.append(logo)
div.append(email)
div.append(textNode)
document.body.append(div);- node.append(...nodes or strings) – добавляет узлы или строки в конец node,
- node.prepend(...nodes or strings) – вставляет узлы или строки в начало node,
- node.before(...nodes or strings) - вставляет узлы или строки до node,
- node.after(...nodes or strings) - вставляет узлы или строки после node,
- node.replaceWith(...nodes or strings) - заменяет node заданными узлами или строками.
- node.remove()
elem.insertAdjacentHTML(where, html)
- "beforebegin" – вставить html непосредственно перед elem,
- "afterbegin" – вставить html в начало elem,
- "beforeend" – вставить html в конец elem,
- "afterend" – вставить html непосредственно после elem.
<div class="container">
<article>
<img src="/example.png" alt="">
<h2>Example 1</h2>
<div>Descr 1</div>
</article>
</div>const cards = [
{
title: 'Title 1',
img: '1.jpg',
description: 'description 1'
},
{
title: 'Title 2',
img: '2.jpg',
description: 'description 2'
},
];
const container = document.querySelector('.container');
const contentString =
cards.map( ({title, img, description}) => `
<article>
<img src="${img}" alt="${title}">
<h2>${title}</h2>
<div>${description}</div>
</article>
`).join('')
container.insertAdjacentHTML('beforeend', contentString);
cards.forEach((item) => {
const article = document.createElement('article')
const img = document.createElement('img')
img.src = item.img
const h2 = document.createElement('h2')
h2.textContent = item.title
const div = document.createElement('div')
div.textContent = item.description
article.append(img)
article.append(h2)
article.append(div)
container.append(article);
})-
поиск элемента
-
изменение свойств у элемента (это может быть добавление/удаление класса, добавление/удаление атрибута, изменение содержимого элемента и так далее)
-
поиск элемента
-
innerHTML = "" если нужно
-
создание элементов ( есди нужно, установка значения атрибутов)
-
добавление элементов в DOM
Размеры и прокрутка элементов
https://learn.javascript.ru/size-and-scroll
Размеры и прокрутка окна
https://learn.javascript.ru/size-and-scroll-window
Координаты
https://learn.javascript.ru/coordinates
Классы DOM-узлов
Каждый DOM-узел принадлежит соответствующему встроенному классу.
Корнем иерархии является EventTarget, от него наследует Node и остальные DOM-узлы.
EventTarget – это корневой «абстрактный» класс для всего.
Объекты этого класса никогда не создаются. Он служит основой, благодаря которой все DOM-узлы поддерживают так называемые «события».
- click – происходит, когда кликнули на элемент левой кнопкой мыши (на устройствах с сенсорными экранами оно происходит при касании).
- contextmenu – происходит, когда кликнули на элемент правой кнопкой мыши.
- mouseover / mouseout – когда мышь наводится на / покидает элемент.
- mousedown / mouseup – когда нажали / отжали кнопку мыши на элементе.
- mousemove – при движении мыши.
- submit – пользователь отправил форму
<form>. - focus – пользователь фокусируется на элементе, например нажимает на
<input>. - blur – когда элемент теряет фокус.
- change - Событие change срабатывает по окончании изменения элемента.
- input - срабатывает каждый раз при изменении значения.
- keydown и keyup – когда пользователь нажимает / отпускает клавишу.
- DOMContentLoaded – когда HTML загружен и обработан, DOM документа полностью построен и доступен.
- scroll - позволяет реагировать на прокрутку страницы или элемента.
- resize - позволяет реагировать на изменение размеров страницы или элемента.
- transitionend – когда CSS-анимация завершена
addEventListener(event, handler, [options]);
- event - Имя события, например "click".
- handler - Ссылка на функцию-обработчик.
- options - Дополнительный объект со свойствами:
- once: true - если true, тогда обработчик будет автоматически удалён после выполнения.
- capture: фаза, на которой должен сработать обработчик, что options может быть false/true, это то же самое, что {capture: false/true}.
- passive: если true, то указывает, что обработчик никогда не вызовет preventDefault()
addEventListener(event, handler, {
once: true,
capture: true,
passive: true
});
<div class="article">
<p>Lorem ipsum dolor sit amet</p>
<button class="js-remove">Удалить</button>
</div>const button = document.querySelector('.js-remove');
button.addEventListener('click', (e) => {
console.log(e)
})
function handlerRemove(e)
{
console.log(e)
}
button.addEventListener('click', handlerRemove)
button.removeEventListener('click', handlerRemove)
function handlerProperty(e)
{
console.log(e)
}
button.onclick = (e) => {
}
button.onclick = handlerPropertyhttps://ru.reactjs.org/docs/handling-events.html
https://vuejs.org/guide/essentials/event-handling.html#method-handlers
Когда на элементе происходит событие, обработчики сначала срабатывают на нём, потом на его родителе, затем выше и так далее, вверх по цепочке предков.
<form>FORM
<div>DIV
<p>P</p>
</div>
</form>// example 1
document.querySelector('form').addEventListener('click', () => alert('form'))
document.querySelector('div').addEventListener('click', () => alert('div'))
document.querySelector('p').addEventListener('click', () => alert('p'))
// example 2
document.querySelector('form').addEventListener('click', (event) => {
alert("target = " + event.target.tagName + ", event.currentTarget=" + event.currentTarget.tagName);
})
document.querySelector('form').addEventListener('click', function(event) {
alert("target = " + event.target.tagName + ", this=" + this.tagName);
})
//example 3
document.querySelector('form').addEventListener('click', (event) => {
console.log("target = " + event.target.tagName + ", event.currentTarget=" + event.currentTarget.tagName)
})
document.querySelector('div').addEventListener('click', (event) => {
console.log("target = " + event.target.tagName + ", event.currentTarget=" + event.currentTarget.tagName)
})
document.querySelector('p').addEventListener('click', (event) => {
console.log("target = " + event.target.tagName + ", event.currentTarget=" + event.currentTarget.tagName)
})Всегда можно узнать, на каком конкретно элементе произошло событие.
event.target - самый глубокий элемент, который вызывает событие, называется целевым элементом, и он доступен через event.target.
event.currentTarget(this) - Элемент, на котором сработал обработчик. Значение – обычно такое же, как и у this, но если обработчик является функцией-стрелкой или при помощи bind привязан другой объект в качестве this, то мы можем получить элемент из event.currentTarget.
event.type - Тип события, в данном случае "click".
Отличия event.target от event.currentTarget(this): event.target – это «целевой» элемент, на котором произошло событие, в процессе всплытия он неизменен. this – это «текущий» элемент, до которого дошло всплытие, на нём сейчас выполняется обработчик
Всплытие идёт с «целевого» элемента прямо наверх. По умолчанию событие будет всплывать до элемента <html>, а затем до объекта document, а иногда даже до window, вызывая все обработчики на своём пути.
Но любой промежуточный обработчик может решить, что событие полностью обработано, и остановить всплытие.
Для этого нужно вызвать метод event.stopPropagation().
<form>FORM
<div>DIV
<p>P</p>
</div>
</form>document.querySelector('form').addEventListener('click', (event) => {
alert(3)
})
document.querySelector('div').addEventListener('click', (event) => {
alert(2)
})
document.querySelector('p').addEventListener('click', (event) => {
event.stopPropagation()
alert(1)
})Если у элемента есть несколько обработчиков на одно событие, то даже при прекращении всплытия все они будут выполнены.
То есть, event.stopPropagation() препятствует продвижению события дальше, но на текущем элементе все обработчики будут вызваны.
Для того, чтобы полностью остановить обработку, существует метод event.stopImmediatePropagation(). Он не только предотвращает всплытие, но и останавливает обработку событий на текущем элементе.
Стандарт DOM Events описывает 3 фазы прохода события:
- Фаза погружения (capturing phase) – событие сначала идёт сверху вниз.
- Фаза цели (target phase) – событие достигло целевого(исходного) элемента.
- Фаза всплытия (bubbling stage) – событие начинает всплывать.
<form>FORM
<div>DIV
<p>P</p>
</div>
</form>for(let elem of document.querySelectorAll('*')) {
elem.addEventListener("click", e => alert(`Погружение: ${elem.tagName}`), true);
elem.addEventListener("click", e => alert(`Всплытие: ${elem.tagName}`));
}addEventListener(..., ..., true) - { capture: true }
При наступлении события – самый глубоко вложенный элемент, на котором оно произошло, помечается как «целевой» (event.target).
Затем событие сначала двигается вниз от корня документа к event.target, по пути вызывая обработчики, поставленные через addEventListener(...., true), где true – это сокращение для {capture: true}.
Далее событие двигается от event.target вверх к корню документа, по пути вызывая обработчики, поставленные через on<event> и addEventListener без третьего аргумента или с третьим аргументом равным false.
Каждый обработчик имеет доступ к свойствам события event:
- event.target – самый глубокий элемент, на котором произошло событие.
- event.currentTarget (=this) – элемент, на котором в данный момент сработал обработчик (тот, на котором «висит» конкретный обработчик)
- event.eventPhase – на какой фазе он сработал (погружение=1, фаза цели=2, всплытие=3).
Любой обработчик может остановить событие вызовом event.stopPropagation(), но делать это не рекомендуется, так как в дальнейшем это событие может понадобиться, иногда для самых неожиданных вещей.
Идея в том, что если у нас есть много элементов, события на которых нужно обрабатывать похожим образом, то вместо того, чтобы назначать обработчик каждому, мы ставим один обработчик на их общего предка.
<table>
<tr>
<th colspan="3">Квадрат <em>Bagua</em>: Направление, Элемент, Цвет, Значение</th>
</tr>
<tr>
<td>...<strong>Северо-Запад</strong>...</td>
<td>text 4</td>
<td>text 3</td>
</tr>
<tr>
<td>text 1<strong>Северо-Запад</strong>...</td>
<td>text 2 <small> text 3 <strong>111</strong></small></td>
<td><p>lorem 1</p></td>
</tr>
</table>let selectedTd;
document.querySelector('table').addEventListener('click', handler)
function handler(event)
{
let target = event.target; // где был клик?
if (target.tagName != 'TD') return; // не на TD? тогда не интересует
if (selectedTd) { // убрать существующую подсветку, если есть
selectedTd.classList.remove('highlight');
}
selectedTd = target;
selectedTd.classList.add('highlight'); // подсветить новый td
}
function handler(event)
{
let td = event.target.closest('td');
if (!td) return;
if (selectedTd) { // убрать существующую подсветку, если есть
selectedTd.classList.remove('highlight');
}
selectedTd = td;
selectedTd.classList.add('highlight'); // подсветить новый td
}<button data-toggle-id="subscribe-mail">
Показать форму подписки
</button>
<form id="subscribe-mail" hidden>
Ваша почта: <input type="email">
</form>document.addEventListener('click', function(event) {
let id = event.target.dataset.toggleId;
if (!id) return;
let elem = document.getElementById(id);
elem.hidden = !elem.hidden;
});- Упрощает процесс инициализации и экономит память: не нужно вешать много обработчиков.
- Меньше кода: при добавлении и удалении элементов не нужно ставить или снимать обработчики.
- Удобство изменений DOM: можно массово добавлять или удалять элементы путём изменения innerHTML и ему подобных.
- Во-первых, событие должно всплывать. Некоторые события этого не делают. Также, низкоуровневые обработчики не должны вызывать event.stopPropagation().
- Во-вторых, делегирование создаёт дополнительную нагрузку на браузер, ведь обработчик запускается, когда событие происходит в любом месте контейнера, не обязательно на элементах, которые нам интересны. Но обычно эта нагрузка настолько пустяковая, что её даже не стоит принимать во внимание.
- Основной способ – это воспользоваться объектом event. Для отмены действия браузера существует стандартный метод event.preventDefault().
- Если же обработчик назначен через on<событие> (не через addEventListener), то также можно вернуть false из обработчика.
<ul id="menu" class="menu">
<li><a href="/html">HTML</a></li>
<li><a href="/javascript">JavaScript</a></li>
<li><a href="/css">CSS</a></li>
</ul>menu.onclick = function(event) {
if (event.target.nodeName != 'A') return;
let href = event.target.getAttribute('href');
alert( href ); // может быть подгрузка с сервера, генерация интерфейса и т.п.
return false; // отменить действие браузера (переход по ссылке)
};
document.querySelectorAll('#menu a').forEach((item) => {
item.addEventListener('click', (event) => {
event.preventDefault()
let href = event.target.getAttribute('href');
alert( href );
})
})Некоторые события естественным образом вытекают друг из друга. Если мы отменим первое событие, то последующие не возникнут.
mousedown/mouseup - Кнопка мыши нажата/отпущена над элементом.
mouseover/mouseout - Курсор мыши появляется над элементом и уходит с него.
mousemove - Каждое движение мыши над элементом генерирует это событие.
click - Вызывается при mousedown , а затем mouseup над одним и тем же элементом, если использовалась левая кнопка мыши.
dblclick - Вызывается двойным кликом на элементе.
Например, клик мышью вначале вызывает mousedown, когда кнопка нажата, затем mouseup и click, когда она отпущена.
Необязательная опция passive: true для addEventListener сигнализирует браузеру, что обработчик не собирается выполнять preventDefault().
addEventListener(event, handler, {
once: true,
capture: true,
passive: true
});
Есть некоторые события, как touchmove на мобильных устройствах (когда пользователь перемещает палец по экрану), которое по умолчанию начинает прокрутку, но мы можем отменить это действие, используя preventDefault() в обработчике.
Поэтому, когда браузер обнаружит такое событие, он должен для начала запустить все обработчики и после, если preventDefault не вызывается нигде, он может начать прокрутку. Это может вызвать ненужные задержки в пользовательском интерфейсе.
Опция passive: true сообщает браузеру, что обработчик не собирается отменять прокрутку. Тогда браузер начинает её немедленно, обеспечивая максимально плавный интерфейс, параллельно обрабатывая событие.
Свойство event.defaultPrevented установлено в true, если действие по умолчанию было предотвращено, и false, если нет.
вместо event.stopPropagation(), можно исп. в опре. сценариях event.defaultPrevented
<button id="elem">Правый клик здесь вызывает контекстное меню кнопки</button>elem.oncontextmenu = function(event) {
event.preventDefault();
alert("Контекстное меню кнопки");
};
document.oncontextmenu = function(event) {
event.preventDefault();
alert("Контекстное меню документа");
};
elem.oncontextmenu = function(event) {
event.preventDefault();
event.stopPropagation();
alert("Контекстное меню кнопки");
};
document.oncontextmenu = function(event) {
event.preventDefault();
alert("Контекстное меню документа");
};было ли отменено действие по умолчанию?
elem.oncontextmenu = function(event) {
event.preventDefault();
alert("Контекстное меню кнопки");
};
document.oncontextmenu = function(event) {
if (event.defaultPrevented) return;
event.preventDefault();
alert("Контекстное меню документа");
};Встроенные классы для событий формируют иерархию аналогично классам для DOM-элементов. Её корнем является встроенный класс Event.
Событие встроенного класса Event можно создать так:
let event = new Event(type[, options]);
type – тип события, строка, например "click" или же любой придуманный нами – "my-event".
options – объект с тремя необязательными свойствами:
- bubbles: true/false – если true, тогда событие всплывает.
- cancelable: true/false – если true, тогда можно отменить действие по умолчанию.
- composed: true/false – если true, тогда событие будет всплывать наружу за пределы Shadow DOM.
Метод dispatchEvent
После того, как объект события создан, мы должны запустить его на элементе, вызвав метод elem.dispatchEvent(event).
UI Event:
- UIEvent
- FocusEvent
- MouseEvent
- WheelEvent
- KeyboardEvent
Технически CustomEvent абсолютно идентичен Event за исключением одной небольшой детали.
У второго аргумента-объекта есть дополнительное свойство detail, в котором можно указывать информацию для передачи в событие.
<h1 id="elem">Привет для Васи!</h1>elem.addEventListener("hello", function(event) {
alert(event.detail.name);
});
elem.dispatchEvent(new CustomEvent("hello", {
detail: { name: "Вася" }
}));Вложенные события обрабатываются синхронно, обычно события обрабатываются асинхронно.
<button id="menusss">Меню (нажми меня)</button>menusss.addEventListener('click', () => {
setTimeout(() => {
console.log(1)
}, 5000)
})
menusss.addEventListener('click', () => {
setTimeout(() => {
console.log(2)
}, 2000)
})menusss.addEventListener('click', () => {
console.log(1)
menusss.dispatchEvent(new CustomEvent("customClick"));
console.log(2)
})
menusss.addEventListener('customClick', () => {
console.log(3)
})Событие change срабатывает по окончании изменения элемента.
Для текстовых <input> это означает, что событие происходит при потере фокуса.
Для других элементов: select, input type=checkbox/radio событие запускается сразу после изменения значения:
<select onchange="alert(this.value)">
<option value="">Выберите что-нибудь</option>
<option value="1">Вариант 1</option>
<option value="2">Вариант 2</option>
<option value="3">Вариант 3</option>
</select>Событие input срабатывает каждый раз при изменении значения.
<input type="text" id="input"> oninput: <span id="result"></span>input.oninput = function() {
result.textContent = input.value;
};Есть два основных способа отправить форму:
- Первый – нажать кнопку
<input type="submit">, <button type="submit">. - Второй – нажать Enter, находясь на каком-нибудь поле
Оба действия сгенерируют событие submit на форме. Обработчик может проверить данные, и если есть ошибки, показать их и вызвать event.preventDefault(), тогда форма не будет отправлена на сервер.
<form action="/" method="GET">
<input type="text" name="first_name">
<input type="text" name="last_name">
<button type="submit">Send</button>
</form>const form = document.querySelector('form')
form.addEventListener("submit", (event) => {
event.preventDefault();
const formData = new FormData(form);
for (const [key, value] of formData){
console.log(key);
console.log(value);
}
const userData = Object.fromEntries(formData)
/*
{
first_name: 'John',
last_name: 'Do',
}
*/
})
document.querySelector("form").addEventListener("submit", async (event) => {
event.preventDefault();
const form = event.currentTarget;
const resource = form.action;
const options = {
headers: {
'Content-Type': 'application/json';
},
method: form.method,
};
options.body = JSON.stringify(Object.fromEntries(new FormData(form)));
const r = await fetch(resource, options);
if (!r.ok) {
return;
}
});Метод form.submit() позволяет инициировать отправку формы из JavaScript. Мы можем использовать его для динамического создания и отправки наших собственных форм на сервер.
При этом событие submit не генерируется. Предполагается, что если программист вызывает метод form.submit(), то он уже выполнил всю соответствующую обработку.
DOMContentLoaded – браузер полностью загрузил HTML, было построено DOM-дерево, но внешние ресурсы, такие как картинки <img> и стили, могут быть ещё не загружены.
load – браузер загрузил HTML и внешние ресурсы (картинки, стили и т.д.).
beforeunload/unload – пользователь покидает страницу.
document.addEventListener("DOMContentLoaded", ready);
function ready()
{
}добавить элементы






