видим в alert е то что введено в поле поиска
Продвинутая работа с событиями в JavaScript
Учебник JavaScript
Практика
Работа с DOM
Практика
Некоторые продвинутые вещи
Рекомендованное ES6
Некоторые видео могут забегать вперед, тк к этому месту учебника мы прошли еще не весь ES6. Просто пропускайте такие видео, посмотрите потом.
Регулярки
Разное
Работа с канвасом
Практика
Контекст
Drag-and-Drop
Практика по ООП
Ваша задача: посмотрите, попробуйте повторить.
Практика
Promise ES6
Библиотека jQuery
Тк. jQuery устаревает, объявляю эти уроки не обязательными и выношу в конец учебника (так по уровню уроки середины учебника, если что). В перспективе переедет в отдельный учебник по jq.
В данном уроке мы с вами разберем все способы работы с событиями в JavaScript.
События через атрибуты
Напомню еще раз этот способ на примере: сейчас по клику на кнопку сработает функция func, которая выводит на экран alert:
Поэтому давайте посмотрим, что еще нам может предложить JavaScript при работе с событиями.
События через работу с атрибутами
Если мы сделаем так: elem.onclick = func, то привяжем к элементу elem функцию func. Посмотрите пример и под ним мы обсудим все нюансы этого способа:
Теперь я должен открыть вам страшную тайну JavaScript: если функция написана без круглых скобок, например func, то она возвращает свой исходный код, а если с круглыми скобками, например func(), то возвращает результат работы функции.
Я уверен, что прочитав это, вы не до конца поймете то, что я хотел вам донести, поэтому запустите пример и еще раз перечитайте предыдущий абзац. Вот пример:
Кстати, результатом функции func() будет undefined, так как у нее нет команды return. Напомню код функции, о которой идет речь:
Мы еще поговорим подробнее о все этих нюансах, пока запомните эти вещи, которые я рассказал, пусть даже без полного понимания. Оно со временем придет.
Достоинства и недостатки такого способа
Давайте теперь обсудим достоинства и недостатки этого способа.
Достоинства
Достоинства такие: теперь, если мы захотим задать одновременно одно событие всем инпутам на странице, нет нужды вручную прописывать каждому из них атрибут с событием. Можно просто получить все инпуты, перебрать их циклом и каждому привязать событие.
Давайте сделаем это. Получим все инпуты с помощью getElementsByTagName и в цикле привяжем каждому такое событие: пусть по клику каждый инпут выдает алертом текст ‘!’:
Теперь нажатие на любой инпут будет приводить к тому, что будет срабатывать функция func, которая алертом выводит ‘!’.
Использование this
Давайте усложним задачу и сделаем так, чтобы alert выводил содержимое атрибута value того инпута, на который кликнули мышкой.
Во-первых, потому, что функцию func здесь нужно писать без круглых скобок, иначе будет не исходный код, а результат работы функции.
Во-вторых, this указывает на разные элементы в зависимости от контекста (в зависимости от места, где он написан). И в нашем случае он не будет ссылаться на нужный нам элемент (то есть на тот, на который мы кликнули). Про контекст выполнения поговорим чуть позже, пока просто знайте, что он есть.
Напоминаю правильный вариант:
Недостатки
В следующем примере мы пытаемся привязать к событию onclick сразу две функции func1 и func2. Однако по клику на элемент сработает только вторая функция, так как она затрет первую:
В принципе, эту проблему легко обойти, если ввести еще и третью функцию func3. Привяжем к атрибуту onclick только func3, а она пусть вызывает func1 и func2 у себя внутри:
Как вы видите, этот недостаток не слишком существенный и его легко обойти. Только что вводится лишняя функция, что немного неудобно.
Работа с addEventListener
Давайте сделаем так, чтобы по клику на кнопку вызывалась функция func:
Работа с this для addEventListener
Давайте посмотрим на примере: привяжем к кнопке событие onclick, которое будет запускать функцию func. Эта функция будет выводить на экран value нашей кнопки:
С одной кнопкой не очень интересно проверять работу this. Давайте сделаем две кнопки, привязав в ним одну и ту же функцию func. В этом случае функция func будет выводить value той кнопки, на которую мы кликнули:
Ну, а сейчас получим массив кнопок с помощью getElementsByTagName и каждой из них привяжем функцию func.
В this будет лежать ссылка на ту кнопку, на которую вы нажали, и функция func выведет на экран именно ее value:
Удаление привязки через removeEventListener
Сейчас мы с вами займемся тем, что будем удалять привязанные к событию функции. Что у нас будет получаться: если, к примеру, к событию onclick привязаны функции func1 и func2, то мы сможем отвязать функцию func1, не затрагивая func2 и наоборот.
Давайте привяжем к элементу 3 функции: func1, func2 и func3, которые будут выводить на экран числа 1, 2 и 3:
А теперь сразу же после привязки отвяжем функции func1 и func2. Это делается с помощью метода removeEventListener, которая принимает те же параметры, что и addEventListener:
Понятно, что по сути мы сделали бессмысленную операцию: привязали функции и сразу же отвязали. Давайте усложним пример и будем удалять привязку внутри самих функций.
Пусть при первом клике на кнопку сработают все 3 функции и при этом func1 и func2 отвяжутся от элемента. И при следующих кликах будет срабатывать только функция func3, которую мы не отвязываем.
А в следующем примере мы ко всем кнопкам привяжем функцию func, которая будет выводить содержимое атрибута value той кнопки, на которую вы нажмете. А после этого функция func будет отвязываться от этой кнопки с помощью removeEventListener. И получится что каждая кнопка будет реагировать только на первое нажатие по ней (запустите код и проверьте это):
Что вам делать дальше:
Приступайте к решению задач по следующей ссылке: задачи к уроку.
Взаимодействие с пользователем: alert, prompt, confirm
Материал на этой странице устарел, поэтому скрыт из оглавления сайта.
Более новая информация по этой теме находится на странице https://learn.javascript.ru/alert-prompt-confirm.
alert
alert выводит на экран окно с сообщением и приостанавливает выполнение скрипта, пока пользователь не нажмёт «ОК».
Окно сообщения, которое выводится, является модальным окном. Слово «модальное» означает, что посетитель не может взаимодействовать со страницей, нажимать другие кнопки и т.п., пока не разберётся с окном. В данном случае – пока не нажмёт на «OK».
prompt
Функция prompt принимает два аргумента:
Пользователь должен либо что-то ввести и нажать OK, либо отменить ввод кликом на CANCEL или нажатием Esc на клавиатуре.
Единственный браузер, который не возвращает null при отмене ввода – это Safari. При отсутствии ввода он возвращает пустую строку. Предположительно, это ошибка в браузере.
Запустите этот код в IE, чтобы понять о чём речь:
Поэтому рекомендуется всегда указывать второй аргумент:
confirm
confirm выводит окно с вопросом question с двумя кнопками: OK и CANCEL.
Результатом будет true при нажатии OK и false – при CANCEL( Esc ).
Особенности встроенных функций
Конкретное место, где выводится модальное окно с вопросом – обычно это центр браузера, и внешний вид окна выбирает браузер. Разработчик не может на это влиять.
С одной стороны – это недостаток, так как нельзя вывести окно в своём, особо красивом, дизайне.
С другой стороны, преимущество этих функций по сравнению с другими, более сложными методами взаимодействия, которые мы изучим в дальнейшем – как раз в том, что они очень просты.
Это самый простой способ вывести сообщение или получить информацию от посетителя. Поэтому их используют в тех случаях, когда простота важна, а всякие «красивости» особой роли не играют.
Взаимодействие: alert, prompt, confirm
alert
С этой функцией мы уже знакомы. Она показывает сообщение и ждёт, пока пользователь нажмёт кнопку «ОК».
Это небольшое окно с сообщением называется модальным окном. Понятие модальное означает, что пользователь не может взаимодействовать с интерфейсом остальной части страницы, нажимать на другие кнопки и т.д. до тех пор, пока взаимодействует с окном. В данном случае – пока не будет нажата кнопка «OK».
prompt
Функция prompt принимает два аргумента:
Этот код отобразит модальное окно с текстом, полем для ввода текста и кнопками OK/Отмена.
title Текст для отображения в окне. default Необязательный второй параметр, который устанавливает начальное значение в поле для текста в окне.
Квадратные скобки вокруг default в описанном выше синтаксисе означают, что параметр факультативный, необязательный.
Второй параметр является необязательным, но если не указать его, то Internet Explorer вставит строку «undefined» в поле для ввода.
Запустите код в Internet Explorer и посмотрите на результат:
Чтобы prompt хорошо выглядел в IE, рекомендуется всегда указывать второй параметр:
confirm
Функция confirm отображает модальное окно с текстом вопроса question и двумя кнопками: OK и Отмена.
Итого
Мы рассмотрели 3 функции браузера для взаимодействия с пользователем:
Все эти методы являются модальными: останавливают выполнение скриптов и не позволяют пользователю взаимодействовать с остальной частью страницы до тех пор, пока окно не будет закрыто.
На все указанные методы распространяются два ограничения:
Такова цена простоты. Есть другие способы показать более приятные глазу окна с богатой функциональностью для взаимодействия с пользователем, но если «навороты» не имеют значения, то данные методы работают отлично.
Организация поиска по веб-странице на JavaScript (без jQuery)
Пару дней назад получил тестовое задание от компании на вакансию Front-end dev. Конечно же, задание состояло из нескольких пунктов. Но сейчас речь пойдет только об одном из них — организация поиска по странице. Т.е. банальный поиск по введенному в поле тексту (аналог Ctrl+F в браузере). Особенность задания была в том, что использование каких-либо JS фреймворков или библиотек запрещено. Все писать на родном native JavaScript.
(Для наглядности далее буду сопровождать всю статью скринами и кодом, чтоб мне и вам было понятнее, о чем речь в конкретный момент)
Поиск готового решения
Первая мысль: кто-то уже точно такое писал, надо нагуглить и скопипастить. Так я и сделал. За час я нашел два неплохих скрипта, которые по сути работали одинаково, но были написаны по-разному. Выбрал тот, в коде которого лучше разобрался и вставил к себе на старничку.
Если кому интересно, код брал тут.
Почему скрипт работал некорректно?
Все просто. Скрипт работает следующим образом. Сперва в переменную записываем все содержимое тега body, затем ищем совпадения с регулярным выражением (задает пользователь при вводе в текстовое поле) и затем заменяем все совпадения на следующий код:
А затем заменяем текущий тег body на новый полученный. Разметка обновляется, меняются стили и на экране подсвечиваются желтым все найденные результаты.
Вы уже наверняка поняли, в чем проблема, но я все же объясню подробней. Представьте, что в поле поиска ввели слово «div». Как вы понимаете, внутри body есть множество других тегов, в том числе и div. И если мы всем к «div» применим стили, указанные выше, то это уже будет не блок, а непонятно что, так как конструкция ломается. В итоге после перезаписи разметки мы получим полностью сломанную веб-страницу. Выглядит это так.
Было до поиска: Просмореть полностью
Стало после поиска: Просмореть полностью
Как видите, страница полностью ломается. Короче говоря, скрипт оказался нерабочим, и я решил написать свой с нуля, чему и посвящается эта статья.
Итак пишем скрипт с нуля
Как все у меня выглядит.
Сейчас нас интересует форма с поиском. Обвел ее красной линией.
Давайте немного разберемся. Я это реализовал следующим образом (пока чистый HTML). Форма с тремя тегами.
Первый — для ввода текста;
Второй — для для отмены поиска (снять выделение);
Третий — для поиска (выделить найденные результаты).
Итак, у нас есть поле для ввода и 2 кнопки. JavaScript буду писать в файле js.js. Предпложим, что его вы уже создали и подключили.
Первое, что сделаем: пропишем вызовы функции при нажатии на кнопку поиска и кнопку отмены. Выглядеть будет так:
Давайте немного поясню что тут и зачем нужно.
Полю с текстом даем id=«text-to-find» (по этому id будем обращатсья к элементу из js).
Кнопке отмены даем такие атрибуты: type=«button» onclick=«javascript: FindOnPage(‘text-to-find’,false); return false;»
— Тип: button
— При нажатии вызывается функция FindOnPage(‘text-to-find’,false); и передает id поля с текстом, false
Кнопке поиска даем такие атрибуты: type=«button» onclick=«javascript: FindOnPage(‘text-to-find’,true); return false;»
— Тип: submit (не кнопка потому, что тут можно юзать Enter после ввода в поле, а так можете и button использовать)
— При нажатии вызывается функция FindOnPage(‘text-to-find’,true); и передает id поля с текстом, true
Вы наверняка заметили еще 1 атрибут: true/false. Его будем использовать для определения, на какую именно кнопку нажали (отменить поиск или начать поиск). Если жмем на отмену, то передаем false. Если жмем на поиск, то передаем true.
Окей, двигаемся дальше. Переходим к JavaScript
Будем считать, что вы уже создали и подключили js файл к DOM.
Прежде, чем начнем писать код, давайте отвлечемся и сперва обсудим, как все должно работать. Т.е. по сути пропишем план действий. Итак, нам надо, чтоб при вводе текста в поле шел поиск по странице, но нельзя затрагивать теги и атрибуты. Т.е. только текстовые объекты. Как этого достичь — уверен есть много способов. Но сейчас будем использовать регулярные выражения.
Итак, следующее регулярное выражение будет искать только текст след. вида: «>… текст.
Введение в браузерные события
Событие – это сигнал от браузера о том, что что-то произошло. Все DOM-узлы подают такие сигналы (хотя события бывают и не только в DOM).
Вот список самых часто используемых DOM-событий, пока просто для ознакомления:
События мыши:
События на элементах управления:
Клавиатурные события:
События документа:
CSS events:
Существует множество других событий. Мы подробно разберём их в последующих главах.
Обработчики событий
Событию можно назначить обработчик, то есть функцию, которая сработает, как только событие произошло.
Именно благодаря обработчикам JavaScript-код может реагировать на действия пользователя.
Есть несколько способов назначить событию обработчик. Сейчас мы их рассмотрим, начиная с самого простого.
Использование атрибута HTML
Атрибут HTML-тега – не самое удобное место для написания большого количества кода, поэтому лучше создать отдельную JavaScript-функцию и вызвать её там.
Следующий пример по клику запускает функцию countRabbits() :
Использование свойства DOM-объекта
К примеру, elem.onclick :
Если обработчик задан через атрибут, то браузер читает HTML-разметку, создаёт новую функцию из содержимого атрибута и записывает в свойство.
Этот способ, по сути, аналогичен предыдущему.
Обработчик всегда хранится в свойстве DOM-объекта, а атрибут – лишь один из способов его инициализации.
Эти два примера кода работают одинаково:
В примере ниже назначение через JavaScript перезапишет обработчик из атрибута:
Кстати, обработчиком можно назначить и уже существующую функцию:
Доступ к элементу через this
Внутри обработчика события this ссылается на текущий элемент, то есть на тот, на котором, как говорят, «висит» (т.е. назначен) обработчик.
В коде ниже button выводит своё содержимое, используя this.innerHTML :
Частые ошибки
Если вы только начинаете работать с событиями, обратите внимание на следующие моменты.
…А вот в разметке, в отличие от свойства, скобки нужны:
Так что разметка генерирует такое свойство:
Используйте именно функции, а не строки.
Назначение обработчика строкой elem.onclick = «alert(1)» также сработает. Это сделано из соображений совместимости, но делать так не рекомендуется.
Не используйте setAttribute для обработчиков.
Такой вызов работать не будет:
Регистр DOM-свойства имеет значение.
addEventListener
Например, одна часть кода хочет при клике на кнопку делать её подсвеченной, а другая – выдавать сообщение.
Мы хотим назначить два обработчика для этого. Но новое DOM-свойство перезапишет предыдущее:
Синтаксис добавления обработчика:
Для удаления обработчика следует использовать removeEventListener :
Для удаления нужно передать именно ту функцию-обработчик которая была назначена.
Вот так не сработает:
Обработчик не будет удалён, т.к. в removeEventListener передана не та же функция, а другая, с одинаковым кодом, но это не важно.
Метод addEventListener позволяет добавлять несколько обработчиков на одно событие одного элемента, например:
Так что addEventListener более универсален. Хотя заметим, что таких событий меньшинство, это скорее исключение, чем правило.
Объект события
Чтобы хорошо обработать событие, могут понадобиться детали того, что произошло. Не просто «клик» или «нажатие клавиши», а также – какие координаты указателя мыши, какая клавиша нажата и так далее.
Когда происходит событие, браузер создаёт объект события, записывает в него детали и передаёт его в качестве аргумента функции-обработчику.
Пример ниже демонстрирует получение координат мыши из объекта события:
Некоторые свойства объекта event :
Есть также и ряд других свойств, в зависимости от типа событий, которые мы разберём в дальнейших главах.
Объект-обработчик: handleEvent
Мы также можем использовать класс для этого:
Метод handleEvent не обязательно должен выполнять всю работу сам. Он может вызывать другие методы, которые заточены под обработку конкретных типов событий, вот так:
Теперь обработка событий разделена по методам, что упрощает поддержку кода.
Итого
Есть три способа назначения обработчиков событий:
HTML-атрибуты используются редко потому, что JavaScript в HTML-теге выглядит немного странно. К тому же много кода там не напишешь.
DOM-свойства вполне можно использовать, но мы не можем назначить больше одного обработчика на один тип события. Во многих случаях с этим ограничением можно мириться.
Не важно, как вы назначаете обработчик – он получает объект события первым аргументом. Этот объект содержит подробности о том, что произошло.
Мы изучим больше о событиях и их типах в следующих главах.