Базовый javascript. Урок 6. Работа с объектом Event — Transcript

Урок по базовому JavaScript с разбором объекта Event, современных событий загрузки и рекомендаций по выбору селекторов.

Key Takeaways

  • Использование DOMContentLoaded предпочтительнее window load для более быстрой инициализации скриптов.
  • Глобальные переменные могут привести к конфликтам, лучше применять ES-модули или сборщики проектов.
  • Для селекторов элементов в JavaScript надёжнее использовать дата-атрибуты или специальные классы с префиксами.
  • Аккордеон можно реализовать разными способами, важно правильно управлять состоянием открытых элементов.
  • Понимание объекта Event и его свойств помогает создавать более эффективные и интерактивные веб-приложения.

Summary

  • Объяснение объекта Event и его роли в обработке событий в JavaScript.
  • Обсуждение использования события DOMContentLoaded вместо window load для ускорения загрузки скриптов.
  • Рассмотрение проблем с глобальными переменными и рекомендация использовать ES-модули или сборщики.
  • Советы по выбору селекторов для работы с элементами: классы против дата-атрибутов.
  • Предложение использовать префиксы для классов, применяемых в JavaScript, чтобы избежать конфликтов.
  • Разбор реализации домашнего задания с аккордеоном и варианты решения задачи управления открытием ответов.
  • Объяснение важности аккуратного подхода к выборке элементов для предотвращения поломок кода.
  • Упоминание различных типов событий и их применения в интерфейсах, включая отмену стандартных действий браузера.
  • Примеры использования событий для создания интерактивных элементов, таких как контекстное меню и игры.
  • Подчёркивание важности понимания замыканий и правильной организации кода для работы с событиями.

Full Transcript — Download SRT & Markdown

00:00
Speaker A
Приветствую на шестом уроке базового джаваскрипта. Сегодня мы будем подробно говорить про ивенты, а именно про тот объект Е, который передаётся в любую функцию, которая событие обрабатывает.
00:11
Speaker A
Но для начала, по традиции, обратная связь по вопросам, которые пишут те, кто смотрит видео, и, конечно же, реализация ДЗ, которая была описана в конце прошлого ролика. Э зацепился у меня взгляд за два вопроса, которые написали к прошлому видео. Значит, первый вопрос
00:30
Speaker A
касался того, не надо ли нам уже избавиться от eventрлода. Ведь кажется, что мы, ну, действительно, прошли эту тему и что мы имеем полное право убрать такую абстракцию, как функцию page loaded. И, например, на первом же уровне этого скрипта получать,
00:46
Speaker A
допустим, переменную FК, переменную ASК и работать, ну, по замыканию с ними функции таголанса. То есть убрать один вот этот вот крупный, как мы его называем, прямоугольник.
00:58
Speaker A
И вроде как кодовая база станет попроще. Мы можем так сделать. Для этого нам надо не забыть сдвинуть скрипт из шапки вниз, например, поставить его перед закрывающим тегом bodyди. Также можно решить эту задачу, добавив в скрипт такой атрибут, как, например, defer. Но
01:15
Speaker A
мне это пока что не очень нравится по одной простой причине. Пока мы с вами не узнали про существование такой темы, как ES-модули, пока мы нашим скриптам не начали писать вот здесь вот атрибут, допустим, модуль, это всё не очень
01:30
Speaker A
хорошо, потому что мы создаём прямо реально такие глобальные переменные, которые могут привести к большим проблемам, если, допустим, вы на страницу подключите два скрипта, в которых переменные по какой-либо причине будут названы одинаково. Но бывает такое желание, да, разбить код на части. И вот
01:49
Speaker A
если мы с вами делаем это неаккуратно, неумеючи, то при подключении двух скриптов, обратите внимание, identifier fact has already been declared. То есть вот эти переменные, они, ну, как бы реально глобальные переменные. То есть это можно так писать. Это совершенно
02:07
Speaker A
нормальный код, если мы с вами как бы будем так делать чуть позже, уже изучив тему ES-модулей, когда у нас будет стоять либо скрипт, соответственно, с типом модуль, либо у нас будет работать какой-то сборщик проекта, например, Webpack.
02:19
Speaker A
Вот поэтому пока что мы не готовы отказаться от подписки на события загрузки страницы. Другой вопрос, что может быть, конечно, стоит использовать уже что-то более современное, например, не window event listener load, а, допустим, document event listener, допустим, DOMContentLoaded. И сейчас
02:41
Speaker A
это будет работать один в один визуально, да, для нас разницы нет никакой. Вот вся логика прошлого видео сохранена, но событие стало более правильным, более современным. Почему?
02:52
Speaker A
Потому что window load он достаточно такой медленный. Он ждёт, когда будут дозагружены все ресурсы, в частности картинки. А DOMContentLoaded голосит, что объектная модель документа просто построена и готова к работе. Заметьте, у нас при размещении как бы скрипта в
03:07
Speaker A
шапке никаких проблем всё равно нет. И давайте, наверное, на такой вариант ориентироваться. Это значит первый вопрос, который хотел осветить. Второй вопрос, даже точнее не вопрос, а утверждение под видео прошлого урока звучало так: не стоит использовать классы для выборки элементов. Это очень
03:26
Speaker A
опасно, потому что мы, может быть, в CSS этот класс у элемента уберём. Может быть, мы всё как-то, да, захотим другой класс задать или, ну, как бы в CSS нам нужны, точнее, будут другие стили, и мы, скажем, один класс заменим на какой-то
03:42
Speaker A
другой в разметке, и поэтому наш JS поломается. И как бы предложили использовать дата-атрибуты для зацепок к элементам, да, чтобы мы их здесь вот с помощью дата-атрибутов, с помощью такого селектора получали. Но в целом, да, комментарий как бы абсолютно верный с
03:58
Speaker A
той точки зрения, что мы должны очень аккуратно подходить к выборке элементов. И в целом, если мы используем селектор класса, то, в принципе, в этом-то ошибки, наверное, как таковой нет.
04:12
Speaker A
Ошибка возникает тогда, опасность возникает тогда, когда мы используем неудачный селектор класса для выборки элемента. То есть тот селектор класса, который мы реально можем легко подменить. Например, вот как делать точно не стоит. Допустим, мы верстаем на каком-нибудь Bootstrap, и мы не ввели
04:29
Speaker A
класс alert, а мы, например, знаем, что мы хотим это оформить, как в Bootstrap выглядит alert, допустим, как какой-нибудь там alert-success, alert-primary и так далее. За такие классы цепляться действительно будет очень серьёзной ошибкой. Почему? Потому что
04:44
Speaker A
этот класс легко меняется там, скажем, на alert-primary. Вместо alert этот div может быть кем угодно. Может быть, у нас в рубрике вопрос-ответ в паре айтема, где лежат пока что alert, появится ещё один alert какой-то. Кто знает, да,
04:58
Speaker A
как бы это классы совершенно ненадёжные, потому что они завязаны исключительно на стилистику. И вот за такие классы, да, за такие классы, как за селекторы, цепляться в джаваскрипте нельзя практически никогда. Но если мы с вами изобретаем какие-то классы, которые
05:17
Speaker A
используем только как зацепки, то, в принципе, это считается приемлемым. Я понимаю комментарий, да, я понимаю, что дата-атрибут в этом плане надёжнее, потому что верстальщик, ну, как бы какой-то сторонний, если менять нашу разметку, да или мы сами, если забыли
05:32
Speaker A
правила игры, да, дата-атрибут вряд ли когда-то изменим, имеется в виду, например, там какой-нибудь data-id, да, допустим, вот такой вот написанный. Ээ, да, вот это мы точно не поломаем, класс, может быть, случайно сотрём. Но мне кажется, что всё-таки новичкам пока в
05:47
Speaker A
классах ориентироваться проще. Вот это мой такой субъективный взгляд. То есть, если кто хочет перейти на селекторы по дата-атрибутам, я, конечно, не против, но как бы новичкам я могу предложить, знаете, такую не то чтобы золотую середину, но если хотите такой вот
06:04
Speaker A
промежуточный вариант. Можно, например, взять в каком-то проекте правило, что мы, допустим, классы, которые используем в стилях, называем обычным образом, а классы, которые используем в джаваскрипте для зацепок за элементы или классы, которыми JS манипулирует, например, мы начинаем с какого-то
06:21
Speaker A
префикса типа _. И тогда при таком правиле фактически тоже всё будет достаточно надёжно. Вот. Но это, скажем так, ответ на комментарий, да, замечание абсолютно справедливое. Но те из вас, кто только начинает свой путь в JS, кто проводит первые эксперименты с кодом, вы
06:41
Speaker A
сами решаете, создавать вам такой дополнительный пласт сложности, создавать такие дополнительные правила игры или нет. Мы в рамках нашей кодовой базы пока будем стараться оставаться, а в таком максимально лаконичном коде.
06:54
Speaker A
Но как бы замечание абсолютно верное, поэтому я решил его в видеоролик вынести. Ну а что касается реализации ДЗ, которая была обозначена в предыдущем видео, тут существует бесчисленное множество решений. Я на словах расскажу несколько планов, которые можно было бы
07:11
Speaker A
выбрать. Ну, соответственно, если мы хотим сделать аккордеон, то мы убираем класс хай, который был в материалах урока, э, поставлен у всех ансеров, да, вот в материалах урока код выглядел так.
07:23
Speaker A
Мы, соответственно, хай убираем, как это было на последней секунде прошлого видео, и у нас получается один ответ открыт. Дальше мы должны, кликая паску, понять, открыт ответ или не открыт. Если ответ открыт, мы ничего не делаем. Если ответ как бы не открыт, а закрыт, то нам
07:40
Speaker A
нужно закрыть тот ответ, который открыт, а этот, соответственно, открыть. И вот здесь как раз сосредоточено огромное количество вариантов решения этой задачи. Но, во-первых, тут надо определиться с тем, как мы будем получать открытый ответ для того, чтобы его закрыть. Это можно сделать либо
07:58
Speaker A
перенеся функцию таголанса в page loader, чтобы по замыканию фек получить, либо можно от айтема к фейку легко перейти, написав this.closest(fck).
08:08
Speaker A
Соответственно, потом можно в феке найти скрытые ответы. Можно сделать это CSS-селектором note, допустим, an note. А можно, например, заранее получить переменную ances, получить все ответы где-нибудь вот на строке номер шесть и каждый раз уже с помощью селектора фанса
08:25
Speaker A
не выдёргивать, а именно работать с этой.
08:37
Speaker A
показать вам, ну, одно из них. Я даже не буду говорить, что оно там лучшее или не лучшее. Просто вот, ну, решение как решение. Короче, значит, перво-наперво вот то, что делается безальтернативно, это нам нужно с вами понять, вообще Анса
08:51
Speaker A
открыт или не открыт. Потому что если Анса открыт, делать-то ничего не надо. Мы при клике на открытый Анса, на открытый, точнее, нак, да, для которого Анса открыт, не должны его закрывать, если делаем аккордеон. И поэтому мы с вами, наверное, напишем перво-наперво
09:04
Speaker A
вот такую проверочку. Если class list contains, есть такая функция, одна из четырёх основных, да, contains проверка наличия add добавление класса remove удаление tгle переключения. Так вот, если list contains hide, тогда и только тогда нужно что-то делать.
09:25
Speaker A
Почему? Потому что если он открыт, его закрывать не следует. Мы не должны попадать в эту ветку. Аккордеон должен остаться аккордеоном. Но пока что это работает конечно неправильно потому что при такой логике реализации мы не закрываем другой ответ, который был
09:40
Speaker A
открыт до текущего. Пока что я бы хотел заметить, что, ну, вот с помощью консоль лога даже это показать, что мы, по сути, игнорируем клики на вопрос, для которого ответ открыт. А когда нажимаем на другие то соответственно всё нормально. Ну, немножко там, да,
09:56
Speaker A
опечаточку допустил. Вот видим, что тут консоль логи идут. Тут консоль логи не идёт. Не идут, да. четвёрка в консоли висит как четвёрка. Вот. И по сути нам перед тем, как данный ответ ээ значит открыть, нужно, наверное, закрыть тот ответ, который был
10:12
Speaker A
открыт. Опять же, здесь можно сделать допущение, что такой ответ может быть в системе ровно один. Можно заложиться, конечно, на то, что их могло быть много, но давайте считать, что он ровно один.
10:22
Speaker A
Как тогда мы напишем наш код? Мы от айтема, допустим, перейдём к феку. Мы не заморачиваемся суперпроверками, то есть мы не считаем, что в closest fact может выдать нам нул.
10:37
Speaker A
Если подключим, конечно, какой-нибуд серьёзный язык типа тайpesскрипта, он будет нас доставать этим. Он будет говорить типа верстальчик программист, ты что? Closest, как и document query selector, всегда там может вернуть нам в нул. Так что давай пиши код поаккуратнее. Но как бы пока что мы
10:52
Speaker A
неразрывно связаны с этой разметкой. Мы верим, что от Айтема мы к Феку перейдём так же, как мы верили, что от ээ как бы текущего Аска мы к айтему тоже сможем прийти. Вот мы фект получили, и нам нужно с вами выбрать тот ответ, у
11:06
Speaker A
которого нет класса хай. Значит, в данном случае вот интересно, как эта тема там пересекается, не пересекается философским образом с тем, что мы обсуждали с вами в начале ролика, да, э когда комментировал обратную связь вашу к видео. Вот. Можно ли использовать
11:23
Speaker A
здесь сектор H, если это селектор, который в стилях обозначает скрытие элемента? Ну, как будто бы можно, потому что это класс, он такой, знаете, какой-то системный между джесом и CSэсом.
11:35
Speaker A
То есть JS этим классом активно пользуется, и он является, заметьте, маркером, в том числе и здесь. И добавлять новый датаатрибут параллельно с этим классом, что элемент скрыт, как будто бы лениво. То есть опять-таки это всё можно продумывать по мере, ну, как
11:47
Speaker A
бы роста сложности программы. Но вот тем, кто только начал свой путь, нужно сохранять определённую лаконичность в коде. И поэтому я тем, кто новичок, вот не рекомендую параллельно с классом хай создавать ещё одну метку. Вы просто можете замучиться ээ это делать. А
12:02
Speaker A
так-то вообще, если уж на то пошло, какую-то информационную метку можно прикрепить у элемента дом за счёт добавления даже нового свойства к объекту. Это в теории не является запрещённым чем-то. Вот. Но тем не менее, значит, перешли мы таким образом
12:17
Speaker A
к какому-то открытому ответу. Э, давайте мы назовём его, ну, допустим, как-нибудь там answer to close, да, ответ, который нужно закрыть. А, ну, как бы, да, название переменной можно любое, конечно, здесь э влепить. Вот. Стоит ли проверять, что этой переменной у нас
12:39
Speaker A
может не быть? По-хорошему, наверное, стоит. Конкретно здесь стоит. Мало ли, у нас будет такая модификация аккордеона, у которой нет м открытых ответов. Так, давайте посмотрим, где я ошибся. Я всё тут немножко перепутал. Я зс очень неудачно отсюда скопировал. Конечно, я
12:55
Speaker A
хотел написать просто item closest. Вот. Потому что айтем у нас уже есть. Это айтем, например, вот такой вот div. Мы от него переходим к феку и так далее. И вот обратите внимание, да, я всегда успешно ссылаюсь на div, который открыт.
13:09
Speaker A
Но мне кажется, перед тем, как мы дадим ему команду на удаление класса, всё-таки стоит проверить его наличие, потому что мало ли у нас аккорродеон сделан так, что в вёрстке забыли прописать, что один там, ну, скажем, Анса обязательно открыт. Тогда, видите, сюда приходит
13:22
Speaker A
значение нул. Это нужно учитывать, иначе можно нарваться на ошибку. Поэтому давайте напишем так. Если у нас есть answer to close, например, если он не равен нулу, можно ставить, да, не идентичен, можно ставить просто uns answer to close, потому что нул будет приведён ко лжи.
13:38
Speaker A
Смотрите, как вам комфортнее описать. Я напишу, наверное, такую самую классическую проверку на да операцию идентичности. И вот мы этого answer to close, соответственно, вызываем метод у его класс-листа. Метод получается, а, в нашем случае add. Добавляем ему hide. А у текущего ответа мы,
14:00
Speaker A
соответственно, уберём. Давайте посмотрим, как это будет выглядеть. Сначала визуально, потом ещё раз пробежимся по коду. Вот, пожалуйста, сделали аккордеон переключатель. Лишние ответы открыть невозможно. Открываешь, да, там третий, закрывается второй и так далее. Клик по открытому его, конечно, не закроют.
14:19
Speaker A
Вот тут, кстати, есть загадка для тех, кому не лень подумать. А почему я сделал действие именно в таком порядке?
14:26
Speaker A
Кстати, я ошибися, сделав эти действия. Да, вот надо хай дариму хай-то делать в любом случае.
14:34
Speaker A
Почему? Потому что даже если мы в ветку не попали, нам всё равно текущий ответ надо открыть. Вот поэтому это было, кстати, серьёзной неточностью, то, что ансалист of лежала внутри ветвления. Но тут есть немножко другая загадка. А почему он такой порядок действия выбрал?
14:52
Speaker A
Как считаете? А если я наверх эту штуку перенесу? Хуже станет, лучше. Могут быть какие-то побочки, не могут. В общем, это тоже на подумать. Ну что ж, вот на этом мы завершаем рассмотрение таких общих философских вопросов обратной связи и
15:08
Speaker A
того примера, который давался на ДЗ. Переходим, наконец, к нашей настоящей новой теме, к объекту EVНТ, который передаётся в любую функцию, обрабатывающую события. Пользуясь небольшой паузой видео, я набросал HML-разметку, которая будет необходима нам для демонстрации последующих примеров.
15:24
Speaker A
Вверху у нас две ссылки, потом какое-то текстовое поле ввода и три картинки с какого-то стандартного сайта, раздающего плейсхолдеры.
15:32
Speaker A
Значит, что за объект ивента и почему он важен при работе с событиями? Иногда при работе с событиями нам не хватает дополнительной информации. Например, при работе пользователя мышкой иногда нам могут быть нужны координаты клика этой мышки. При вводе данных с клавиатуры
15:50
Speaker A
могут пригодиться коды введённых клавиш и так далее. Но для начала давайте схематически разберёмся вообще, откуда объект ивента берётся, кто его присылает, как бы что нам с ним делать и так далее. Для этого попробуем провести небольшой эксперимент. Мы по
16:07
Speaker A
стандартным нашим шаблонам напишем, допустим, LED image of images и подпишем каждую картинку с помощью этого листоistнера события клик на функцию image quicket. И пока что в consol log вызовем выведем соответственно единичку просто, чтобы посмотреть, что картинки кликаются. Да, действительно,
16:30
Speaker A
картинки прокликиваются нормально. И вот порой у новичков возникает вопрос: "А вот круглые скобки есть?" Да я же сюда, наверное, что-то передать могу.
16:39
Speaker A
Например, я хочу, чтобы при клике на картинку мне сюда присылали номер кликнутой картинки. Или, например, я хочу сюда передать там какую-то свою системную переменную, которая мне нужна для понимания того, что происходит. Но вот не получится так сделать по очень
16:54
Speaker A
простой причине. Кто функцию вызывает, то это и определяет, какие аргументы в неё будут переданы.
17:02
Speaker A
Например, вот есть функция Mage Click, и вы хотите, чтобы сюда приходили какие-то два параметра.
17:08
Speaker A
Если вы сами вызываете эту функцию, вы, конечно, можете сделать так безумно легко, потому что тот, кто круглые скобки пишет, тот и определяет, что функция будет отправлена. Если же мы с вами передаём image click по ссылке, э, в Event Listener, мы передаём её вот
17:26
Speaker A
куда-то во внутреннее там пространство вот этого объекта. он где-то лист нарохранит. И когда клик на картинку происходит, запускает функцию обработчик, ведь не программист своими круглыми скобками, а запускает функцию обработчик браузер. А у браузера есть очень простая инструкция. Надо запускать
17:46
Speaker A
функцию обработчик события, э, соответственно, с одним параметром, да, в контексте этого обработчика и ровно с одним параметром, который называется соответственно ивент. Но название локальной переменной важно понимать, что может быть, конечно, любым. То есть, как вы локальную переменную не назовёте,
18:03
Speaker A
хоть е, хоть и eventт, хоть Ев, всё будет работать совершенно однотипно. Единственная ловушка здесь, возможно, заключается она в том, что раньше, да и в принципе до сих пор, доступна глобальная переменная Windows.
18:20
Speaker A
Event. Заметьте, что вшке как бы эта переменная написана как зачёркнутая. Это значит, что она как бы, что так делать нельзя.
18:30
Speaker A
Вот у этой ситуации вообще очень смешная история. Как бы в начале 2010 уже решили отказаться от глобального Windows ивента, ссылающегося на последний ивент.
18:41
Speaker A
И долгое время, по-моему, в том же самом Фаефоксе глобальная переменная ивент была недоступна. Как бы Chrome, например, делал её доступной, как и Internet и Internet и Internet Explorer, чтобы код понадёжнее работал. И в итоге как бы победили силы,
18:53
Speaker A
которые сказали: "Да фиг с вами, давайте пусть Windows evвен пока ссылается на последний совершённый ивент, а мы напишем это depricated, когда-нибудь удалим, но похоже это когда-нибудь затянется навечно". Но так, короче говоря, делать нельзя. Мы никогда в кодовой базе не ссылаемся на переменные,
19:07
Speaker A
которых не видим. Это всегда сопряжено с каким-то риском. Да, такие переменные могут быть присущие в среде, например, document, window и так далее, консоль, но не ивент ни в коем случае. То есть нормальная практика - это работа с локальной переменной, когда программист
19:23
Speaker A
сам называет переменную, как считает нужным, как ему удобнее, и работает именно с этой переменной. И вот обратите внимание, что у неё какое-то огроменное количество ключей. Trusted Alt какие-то вообще что это такое, да? антитюд, ну, как бы азимутан, да, тут как бы совершенно
19:46
Speaker A
может мозг уже поехать, видя такое количество каких-то нереальных ключей. Поэтому мы с вами сосредоточимся на самых-самых важных. Аа значит сначала поговорим про интуитивно понятные.
19:58
Speaker A
Например, координаты мыши. Я же мышкой делаю клик, правильно? А раз я делаю клик мышкой, значит, должны быть какие-то координаты. Координаты бывают разными относительно угла экрана, относительно угла самого элемента. Поэтому вы найдёте здесь много разных вещей, типа client X, Layer X,
20:14
Speaker A
Offset X, Page X и так далее. Наверное, проще всё понять, там page X и Page Y, да, отступы относительно страницы. А при этом как бы любой клик-мышкой, да, хоть правой, хоть левой кнопкой, будет, разумеется, такие координаты содержать.
20:28
Speaker A
А вот если это будет событие клавиатуры, например, там нажатие на клавишу, то, ну, как бы нажатие на клавишу сложно определить Page X.
20:35
Speaker A
Поэтому информация от события к событию может, разумеется, отличаться. Для тех, кто поопытнее, можно, конечно, объяснить эту тему так, что у нас есть общий класс ивента, от него уже идут, соответственно подвиды там поинтервент, борд ивент и так далее. Но те, кто
20:53
Speaker A
только начинают свой путь в этой сфере, вам такое объяснение будет понятно, наверное, уроков только через пять.
20:58
Speaker A
Поэтому мы постараемся подобными терминами пока что не бросаться. Опять же, какие интуитивно понятные ключи, например, Alt K. Ну, это же не так сложно. Это просто была ли зажата клавиша Alt при клике, да? Был ли зажат Ctrl при клике? Вот. То есть такие как
21:14
Speaker A
бы системные клавиши. Вот, например, есть ключик метаке, да? Были ли нажаты какие-то специальные клавиши, когда я этот клик совершал? Давайте посмотрим, что ещё бросится в глаза. Srcлемент какой-то. Таржет, кстати, интересно. Ещё из подобного набора здесь можно найти какой-то current таржет.
21:33
Speaker A
Так вот, это очень крутые свойства, кстати, например, current Targжет и Targжет. Это безумно, безумно полезные вещи, но про них мы поговорим в отдельном ролике в следующем видео, когда будем обсуждать такую тему, как всплытие событий и то, как мы можем для
21:47
Speaker A
себя, ну, из этого из этой системы извлечь выгоду. Например, подписываясь на обработку клика там не по каждой картинке, а, допустим, на весь диф обёртку и по всплытию это событие отлавливая. Это а как раз вот в следующем видео мы подробнейшим образом
22:05
Speaker A
обсудим. Эта тема очень интересная. Ну а пока что давайте возьмём что-нибудь э ещё интересное и простое. Например, смотрите, перейду к поинтер ивенту дальше от него буду листать, листать, листать, да, там, допустим, к маус ивенту, к просто к UI ивенту, потом
22:22
Speaker A
просто к ивенту. Забавный такой путь мы прошли. Это как раз затравочка на тему объекты и прототипы. Не пугайтесь этой длинной цепочки. Самое главное, что рано или поздно во всей этой цепочке мы увидим интересные методы. А, например, метод stopation - это отмена всплытия,
22:40
Speaker A
будет актуальна для следующего ролика. А ещё здесь можно найти такой метод, который называется prevent default, то есть отменить стандартную реакцию браузера на ивент. Речь идёт о том, что браузер на многие ивенты реагирует совершенно нормальным стандартным образом. Согласно тому, как этот тег
22:57
Speaker A
должен себя вести, как, да, что с элементом может браузер сделать. То есть, например, кликаю там на летнюю акцию, видите, меня по ссылке перекинуло на летнюю акцию, да? Кликаю там на базовый JavaScript, перекинула на сайт, где уроки базового джаваскрипта
23:09
Speaker A
размещены. Ну, то есть стандартная реакция браузера на клик. А есть реакция на события с картинкой. Смотрите, взял мышкой картинку потащил или взял, кликнул правой кнопкой мыши, открыл стандартное контекстное меню.
23:22
Speaker A
нам сразу дают возможность как-то при необходимости эту стандартную реакцию отменить. Давайте сделаем специальную отдельную функцию, которая будет называться не image clicked, а она будет просто называться вот так вот. Cancel event. Мы принимаем сюда event и вызываем специальный метод у ивента,
23:40
Speaker A
который называется, например, prevent default. Давайте попробуем cancel event подвесить, например, на такое событие, как mouse down на картинке, и посмотрим, произойдёт что-то или не произойдёт с картинкой. Смотрите, я не могу её тащить. Прикольно, да? А давайте ещё сделаем на контекст-меню
24:02
Speaker A
такой же cancel event. И теперь я по картинке не могу кликнуть правой кнопкой мыши. То есть, поверьте, я кликаю. Я вот, видите, пытаюсь схватить картинку и потащить, но не могу. Может быть, кто-то уже обрадовался, что о, я смогу от
24:14
Speaker A
неопытных пользователей картинки скрыть, чтобы их не скачивали. Но на самом деле, если вы хотите добиться такого правила поведения, то, конечно, имеет смысл это сделать через CSS. CSS легко, современный, позволяет достичь такого же эффекта. Это скорее просто демонстрация того, с какой лёгкостью отлетают
24:30
Speaker A
стандартные правила поведения. Если мы напишем event prevent default, э, event prevent default вот интересен тем, например, что мы можем делать это, кстати, по какому-то витвлению.
24:43
Speaker A
Единственное важное ограничение заключается в том, что это обязательно должен быть синхронный код. То есть нельзя, например, обрабатывая события маудау, контекст меню, клик и так далее, взять и поставить сначала какой-нибуд там setтай time таймуут на 100 миссекунд или запустить какую-то анимацию, только
25:01
Speaker A
потом отменить стандартную реакцию браузера. Не, браузер не дурак, он стандартную реакцию выполняет сразу. И мы можем как бы писать фы, мы можем писать даже модальные окна, такие как alert, промт и конфirm, но отменить стандартную реакцию можно только сразу,
25:17
Speaker A
только в рамках синхронного кода. И в качестве примера давайте попробуем, ну, просто так ради интереса, не то чтобы это тот UI, который нужно на сайтах реализовывать, а попробуем сделать отмену клика по ссылке. То есть пусть человек кликает по ссылке, а мы у него
25:32
Speaker A
переспрашиваем, ты уверен, что хочешь перейти туда или нет. Вот как это может выглядеть. Ну, скопируем, соответственно, выборку всех картинок.
25:41
Speaker A
Давайте сделаем переменную Links. В HTL посмотрим, какой у нас есть селектор. Селектор называется меню.
25:48
Speaker A
Селектор Dва, значит, меню А- это все ссылки в Divве. Точно также сделаем закрутку всех ссылок перебором Link of Links. И на каждую ссылку, например, пока что на клик подпишемся просто на cancel event. Соответственно, ссылки просто перестают быть кликабельными.
26:04
Speaker A
Заметьте, сколько бы раз я на них не нажимал, ничего хорошего не произойдёт. А, однако, нас интересует немножко другая задача. Мы хотим отменять ивент по какому-то условию. И давайте для этого сделаем отдельную функцию, которая будет называться, скажем, а, cancel. Или
26:21
Speaker A
даже не cancel, наверное, а confirm, да? Confirm link click. Ну, лучше, наверное, да, confirmли on link, чтобы был более такой интуитивно понятный английский.
26:34
Speaker A
Подписываюсь на тринадцатой строке на события кликай функцией. И дальше ставлю, допустим, такую проверку. If confirm, давайте напишем э ну там я не буду сейчас расписывать, короче, да, вы представляете этот текст, вы переходите на сторонний сайт, уверены ли вы, что вы
26:50
Speaker A
хотите это сделать и так далее и тому подобного. Внимание, вопрос. Надо восклицательный знак ставить или не надо?
26:57
Speaker A
Конфрм - это модальное окно с двумя кнопками. Тормозит работу всего сайта и показывает человеку две кнопочки океаме.
27:05
Speaker A
Уверены ли вы, что хотите перейти? Если человек уверен, что хочет перейти, отменять событие стандартное не надо, стандартную реакцию на события. Поэтому восклицательный знак отменяем прин дефолтм э клик только если человек нажал, что отмена, что он переходить не хочет. А если нажал окей, то пусть
27:24
Speaker A
переходит. Какое наше дело? Разумеется, такой usеer интерфейс не делают, потому что модальные окна, в принципе, никто не любит.
27:32
Speaker A
Алеёрты, конфирма, промте, это всё считается таким каким-то очень старым юам, ну, непонятным. Их невозможно нормально кастомизировать.
27:39
Speaker A
В разных браузерах отображаются по-разному. В принципе, подвешивают логику работы страницы. Поэтому это не пример того, как надо UI делать. Это пример, ну, просто для понимания, что мы можем и поветвлению затормозить, э, приват дефолтом стандартную реакцию браузера на события, но только если это
27:56
Speaker A
код как бы синхронный. То есть если ваш заказчик просит показать красивое модальное окно, э то так сделать не получится. То нужно делать какую-то фейковую ссылку, которой мы всегда отменяем прин дефолтом клик, потом показывать модальное окно и вот отдельно
28:11
Speaker A
обрабатывать клик на окей и переводить человека по ссылке уже вручную. Но это совсем другая история. А мы пока что с вами видим, как легко отменяется стандартная реакция браузера на ивент.
28:23
Speaker A
То есть очень такой полезный ключик, наверное, один из самых популярных. Теперь давайте пофантазируем, для чего нам может быть нужна другая информация.
28:32
Speaker A
Вот, например, те же самые координаты мыши, коды нажатых клавиш. Вообще можно их к чему-то применить, нельзя. Давайте просто повспоминаем какие-то элементы юзернтерфейса, с которыми мы, ну, часто имеем дело. Вот события контекстменю, клик правой кнопкой мыши. Представьте, что вы сейчас
28:51
Speaker A
оказались не на адресе там JSACE Lesson 6, а на URL адресе DRI Google. При нажатии правой кнопкой мыши на папку или на файл Google открывает своё красивое контекстное меню. А как он это делает?
29:05
Speaker A
Да легко. Я прин de дефолт, чтобы не выскакивало контекстное меню стандартное. После чего координаты клика используются для того, чтобы div, который спозиционирован либо фиксированным, либо абсолютным образом в зависимости от задачи, показать ровно там же, где возникает нормальное контекстное меню. То есть топ и left
29:24
Speaker A
должны быть там, где стоит курсор мыши. И тогда в идеальной точке это контекстное меню появится. Только это уже не настоящее контекстное меню, а какой-то див, который раньше был скрыт, а теперь его расположили именно в этом месте документа. То есть вот пример
29:37
Speaker A
использования координат мыши. Ну, конечно же, координаты мыши активнейшим образом использовались, если бы был какой-нибудь там, как раньше, функционал рисования на стене в какой-нибудь соцсети и так далее, и так далее. То есть координаты мыши вроде нужны как ээ в разных случаях. Представить себе эти
29:56
Speaker A
случаи вполне возможно, да, какую-нибудь простенькую игру на сайте делаете, там какие-нибудь там надо кликами мыши шарики взрывать, которые летят. Вот. То есть масса вариантов использования, но вот самое полезное, самое очевидное - это контекстное меню.
30:09
Speaker A
Да, контекстное меню, когда мы отменяем стандартное и рисуем какое-то более красивое. А теперь давайте посмотрим ради интереса на какой-нибудь другой ивент. Ну, например, на ивент не мышкой создаваемой, а на ивент, который создаёт ну допустим клавиатура.
30:26
Speaker A
Сейчас мы с помощью query селектора уже без Ола получим, соответственно, div с классом forм, а внутри него будет нас интересовать input, у которого name равен сам. Вот к вопросу о том, опять же, зачем нужны знания CSS и HTML. У нас
30:42
Speaker A
был CSS not в середине урока, теперь CSS селектор по атрибутам. Значит, давайте назовём эту переменную input сам и попробуем безо всяких циклов, разумеется, подписаться на события допустим а K down, ну или, может быть, там Kup, Kpress, неважно совершенно.
31:05
Speaker A
Ну, тут уже как бы cancel event, конечно, функция не сильно нам подойдёт. Нам не нужно, чтобы ивент отменяли.
31:12
Speaker A
Давайте вот функцию Mage Click я переименую в другую функцию. Я её вот так вот скопирую, переименую, допустим, назову event или log event. Кстати, можно здесь, кстати, да, вот написать просто consol log. Это тоже будет шикарнейшим образом работать, потому что
31:29
Speaker A
функция cons log вызывается ээ с одним параметром ивента. Давайте будем вводить сюда какие-то буковки теперь. И вот обратите внимание, keyboard event, где, аэ, мы заметим, что появились Kкод K, но при этом исчезли координаты. Заметьте, насколько меньше тут ключей по сравнению с мышкой. Да, у
31:52
Speaker A
мыши это была просто огромная простыня. А здесь буквально совсем чуть-чуть. Ну и как главный интересующий программиста ключик - это, конечно, код нажатой клавиши.
32:02
Speaker A
За что ещё мы можем зацепиться в рамках нашей небольшой тренировки? Я думаю, за какие-то так называемые э метаке, то есть Alt cas, Ctrl K и так далее.
32:14
Speaker A
Опять же, чтобы понять вот то, как JavaScript работает на сайтах, нужно как будто бы вспоминать самые популярные приёмы юзеер интерфейса, с которыми вы сталкиваетесь каждый день. и, может быть, пытаться реализовать что-то похожее. Ну, например, представьте, что это не просто какие-то картинки на
32:31
Speaker A
сайте, а это, допустим, иконки папок на Google диске. И человек должен уметь выделять папку, а, при клике.
32:40
Speaker A
Но если человек выделяет папку, допустим, соседнюю, с этой папки выделение снимается. Это чем-то похоже на работу аккордеона, реализованную в разборе ДЗ. Но если человек будет выделять папки, зажав Ctrl, то они будут выделяться все. Выделение новой папки не будет снимать выделение с папки
32:59
Speaker A
предыдущей. Давайте попробуем это реализовать. Я специально не стал удалить функцию Magicket, оставил её конкретно под эту задачу. Перетащим её чуть выше, чтобы было удобнее наблюдать за кодом. И вот эти вот, кстати, контекст меню и маус, ну, могу закомментировать, могу не
33:15
Speaker A
закомментировать, они нам, в принципе, ничем не мешают. Но на клик по картинке мы подпишемся с помощью функции Mage Clicket. Однако для упрощения я функцию M Clicket перенесу в зону видимости функции page loaded, да, внутрь функции page loaded. Почему? Потому что я хочу
33:33
Speaker A
видеть все картинки по замыканию. Я собираюсь с этими картинками проводить определённые манипуляции, когда буду обрабатывать клик по конкретной картиночке.
33:43
Speaker A
А значит, какой план? Давайте сначала в стилях добавим какой-нибудь класс, например, active и сделаем, ну, может быть, небольшой бордер. Можно здесь как бы даже поаккуратнее стили прописать.
33:56
Speaker A
Например, у нас есть gallery соответственно. Давайте мы пропишем, соответственно, бор, например, два пикселя, а solid red для активной картинки. А, и пропишем, значит, точно такой же бордер, только, допустим, transparent. Ну, вопрос на проверочку, на знание основ CS. Зачем я делаю прозрачную рамку, если
34:22
Speaker A
её не видно? Ну и ответ, конечно, такой, что если рамки не будет, то контент будет скакать, да, если рамки совсем не будет. Ну или нам нужно как бы решить эту задачу с помощью других свойств, например, с помощью boxй, там, Borderbox
34:35
Speaker A
и так далее. Вот. Но это сейчас нас не интересует. Просто, значит, подготовил такой класс actтив. Эээ, картинка без актива идёт у нас, заметьте, с прозрачной рамкой. И получается, что если мы делаем эту задачу в простейшем виде, э, то это совершенно неинтересно.
34:51
Speaker A
Например, при при клике по изображению мы берём с помощью Зыса, дотягиваемся до этой картинки, даже ивент нам никакой, получается, не нужен. И мы, например, класс листом нашей любимой функции Tagle переключаем вот этот самый класс active у изображения. И, конечно, у неё сейчас
35:08
Speaker A
будет появляться и исчезать красная рамка. А, но тут вот немножко не повезло с размером страницы, да. Как вы видите, рамки, наличие, отсутствия рамок увеличило размер контента, но ничего страшного. Вот картинки никак не связаны друг с другом. Не похоже на то, как
35:24
Speaker A
работают папки на Google диске, правда? Давайте думать, что ж тогда делать. Допустим, пока без вот этого Alt или Ctrl Kя. Просто клик по картинке должен снимать активность со всех других картинок.
35:40
Speaker A
Но кажется, что нам надо скопировать кодовую базу и логику работы кода с примера вопрос-ответ, да, рубрики. Там, правда, вот было неудачное допущение, что активный ответ может быть только один. А мы знаем, что дальше-то мы будем реализовывать Ctrl LK, и у нас может
35:58
Speaker A
быть много выделенных активных картинок. Поэтому тут логичным решением будет как раз-таки пробежка по всем картинкам и удаление у них получается классов active, да, у всех картинок, кроме той, на которую мы нажали.
36:14
Speaker A
А давайте попробуем сначала такую задачку решить. Делаем цикл for off. И, конечно, руки чешутся здесь. Я уже чуть было не написал images for each. Но пока что потерпим. Нам нужно, перед тем, как писать Images for each, Images Filter,
36:29
Speaker A
Images Map и так далее, нам нужно поговорить про такую тему, как колбеки. Это тоже скоро по плану будет, но опять же не сегодня. Поэтому пока что мы пишем с вами достаточно примитивные циклы.
36:43
Speaker A
Из-за этого наша кодовая база страдает. Если бы у нас были вместо Forфав forчи, например, то можно было бы всё это сделать ощутимо, лаконичнее. Но как бы всему своё время. Давайте пока что пробежимся по всем картинкам и, допустим, у каждой конкретной картинки
36:59
Speaker A
напишем listст условно remove active и для картинки, ну, текущей на двадцать пятой строке сделаем agгл. То есть, заметьте, к чему это привело. Э, немножко такое странное, да, немножко странная ситуация сейчас получилась. То есть у картинки нельзя сбросить активное
37:19
Speaker A
выделение. То есть, если я картинку выделил, то повторный клик его не сбросит. Ну, странно, не странно, кстати, если мы готовим пример, похожий на работу там папок на Google диске, то, в принципе, может и нормально, да? По папке, кликнув, ты в
37:32
Speaker A
отделение с неё не снимешь, надо кликнуть мимо. Но здесь как бы конкретно, почему так это работает? Потому что двадцать вторая строка actтив убирает, в том числе и у текущей картинки, и за счёт этого она не так. И вот, конечно, почему мы с вами
37:48
Speaker A
будем в скором времени стремиться ко всем этим методам работы с массивами, типа фильтр, forage, map и так далее, потому что очень красиво пишется код.
37:56
Speaker A
Например, images тоfilter img стрелка AMG не равно ZSO. То есть взяли все картинки, кроме текущей точка for each, img стрелка AMG effective. В одну строчку вот в такую там буквально в три раза длиннее она будет, решится эта задача. Вот. Но опять же, подчёркиваю,
38:15
Speaker A
всему своё время, это просто такая затравочка на будущее, чтобы понимали, что мы пишем код таким длинным образом не от незнания, от того, что мы не хотим как бы намешивать всё новые и новые приёмы, чтобы они не накапливались вот
38:28
Speaker A
как снежный ком в рамках одного урока. Вот поэтому я про них упоминаю, но э не тороплюсь применять. А что касается нашей задачи, да, вот пока не сходится, не складывается немножко, но это не страшно. Давайте попробуем прицепиться к ивенту и решить вот что у нас там с
38:49
Speaker A
эктивом. А, да, с активом-то что, нужно не нужно его убирать или так? Давайте всё-таки распишем сначала сценарии, посмотрим, была ли нажата, допустим, клавиша Ctrl.
39:05
Speaker A
Ну, чтобы, ну, или давайте, ладно, Ctrl Alt - это совершенно неважно. То есть, если вы не уверены, как именно называется ключик, выводите вот, скажем, в consль log этот ивент, смотрите на него, потом делаете такой же, допустим, зажав Ctrl или Alt или любую другую
39:21
Speaker A
клавишу. И вот, пожалуйста, здесь Ctrl K true. В предыдущем ивенте Ctrl Kleфse, то есть ничего не нужно угадывать. Можно читать справочники, можно находить это в консоли. Получается, витвление у нас намечается такое. был нажат Ctrl K в ивенте или Ctrl K в ивенте нажат,
39:37
Speaker A
соответственно, не был. Теперь думаем. Если Ctrl Kт, то это значит, что мы не должны снимать выделение с картинок. Мы должны только текущую картинку таглить. Давайте я даже закомментирую цикл и посмотрим на работу системы. Видите, без Ctrl K ничего не
39:55
Speaker A
работает, а с Конtrлом всё работает, как прямо на Google диске папочки выделяю. А, да, подчёркиваю, я сейчас нажал Ctrl, вы этого не видите. Понятно, как бы камера клавиатуры не касается, но вот я утверждаю, что Ctrl у меня сейчас зажат.
40:06
Speaker A
Ну и как бы работа кода, я думаю, это тоже доказывает. А вот когда Ctrl у меня не зажат, мне нужно как бы со всех других картинок убрать выделение, а текущего сделать выделенной. Ну и, честно говоря, делается-то это легко. Мы
40:19
Speaker A
должны у всех картинок активность удалить, а у текущей картинки, внимание, не затаглить активность. Мы должны просто добавить actтив безоговорочно.
40:28
Speaker A
Если я кликаю по какой-то одной картинке, actтив ей добавляю. И давайте проверять. Вот нажимаю на конкретные картинки. Всё нормально. Понятно, мы не следим пока за кликом мимо все его ээ div gallery. Можно было бы это сделать и снять выделение со всех, как тот же
40:44
Speaker A
Google делает, да, в файловой системе. Ну и Windows, там почему Google-то, да, вот как как в обычном десктопе реализовано. Ну а вот с Ctrl K, пожалуйста, все выделил, потом кликнул по одной без контрола. Всё, как обычно.
40:56
Speaker A
Вот. Согласитесь, UI уже чем-то напоминает то, что может быть актуально в админке сайта. Например, выбери сначала все картинки, потом их удали. Э, да. А всё это нам помогают сделать темы, которые мы изучали как ранее, так и сегодня.
41:12
Speaker A
Например, контекстом мы дотягиваемся до текущего изображения. В ивенте мы находим информацию о том, был ли зажат Ctrl K. По замыканию мы видим картинки внутри функции Mage Clicket. Нам нужна переменная images для удобства. То есть все темы, которые мы с вами активно
41:27
Speaker A
использовали ранее по отдельности, в этом примере вдруг сошлись вместе. Ну и в качестве домашнего задания я предлагаю добавить в этот пример ту тему, которую мы смотрели на прошлом уроке, но здесь она пока что не фигурирует. Это датаатрибуты.
41:44
Speaker A
Зачем они могут здесь вообще быть нужны? Давайте представим себе, что это действительно админка сайта. И у каждой картинки есть атрибут data ID. который является идентификатором этой картинки в системе. Соответственно, человек мышкой, например, выделяет картинки, которые хочет из Глеи удалить, и где-то внизу
42:05
Speaker A
есть кнопка удалить. Ваша задача заключается в том, чтобы в разметке поставить картинкам data ID. И человек после этого, например, выбирает картинки. И когда он нажимает на кнопку удалить, то какая-то функция принимает массив этих айдишников. В реальности такая функция массив айдишников,
42:24
Speaker A
например, может отправить на сервер. Но давайте попробуем без сервера, конечно, да. Где мы и где сервер? Нам до него ещё топать и топать. А давайте попробуем сделать вот такой хитрый ээ хитрую такую реализацию. То есть вы в этой функции выведете в консоль логом
42:43
Speaker A
картинки не картинки, точнее, а их айдишники, массив с data ID атрибутами. То есть, например, у этой data ID стоит и 105, у этой 107. Человек выделил две картинки, значит в консоль logе должно появиться 100 и 105, когда мы нажмём на
42:55
Speaker A
кнопку удалить изображение. И после этого попробуйте сделать так, чтобы картинки с объектной модели документа пропали. То есть нужно найти функцию, которая умеет удалять узел дом и каким-то образом туда эти самые картинки, которые были выделены, передать. Вот такая вот задачка. Ну и до
43:11
Speaker A
встречи на следующем уроке, на котором мы познакомимся с важнейшей темой всплытия событий. Готовьтесь, это будет не так-то просто, но тема очень важная и много что она в итоге нам упростит. M.
Topics:JavaScriptобъект EventDOMContentLoadedwindow loadселекторыдата-атрибутыаккордеонES-модулиобработка событийзамыкания

Frequently Asked Questions

Почему лучше использовать DOMContentLoaded вместо window load?

DOMContentLoaded срабатывает сразу после построения DOM, не дожидаясь загрузки всех ресурсов, что ускоряет инициализацию скриптов по сравнению с window load.

Какие проблемы возникают при использовании глобальных переменных в JavaScript?

Глобальные переменные могут привести к конфликтам, если на странице подключено несколько скриптов с одинаковыми именами переменных, что усложняет поддержку кода.

Почему рекомендуется использовать дата-атрибуты вместо классов для выбора элементов в JavaScript?

Дата-атрибуты более надёжны, так как они не зависят от стилей и вряд ли будут случайно изменены верстальщиками, в отличие от классов, которые могут меняться для оформления.

Get More with the Söz AI App

Transcribe recordings, audio files, and YouTube videos — with AI summaries, speaker detection, and unlimited transcriptions.

Or transcribe another YouTube video here →