# jQuery 2 ## События. Delegated events, `on`, `trigger`, propagation. При динамическом (используя **DOM** `createElement` или `$("<tag>")`) создании элементов возникает следующая проблема - обработчики событий, назначенные *до* создания элемента какой-то группе элементов по селектору **не** работают для новосозданных элементов. **Рассмотрим пример:** ```html <body> <button>first button</button> </body> ``` ```javascript $(document).ready(function(){ $("button").click(function(){ alert("click"); }); var otherButton = $("<button>"); otherButton.html("second button"); $(document.body).append(otherButton); }); ``` В примере выше мы создаем обработчик для *всех* кнопок. На момент назначения обработчика кнопка существует только одна. Далее динамически создается еще одна кнопка `otherButton` с текстом `second button` и добавляется в `body`. Этой кнопке обработчик `click` *не* назначен, так как её *не существовало* на момент назначения. https://repl.it/E8Fc/0 ### Delegated events, `on`. #### `on` Практически все события типа `click`, `keydown` являются сокращениями для `on`. Например `click` из примера выше аналогичен следующему коду: ```javascript $("button").on("click",function(){ alert("click"); }); ``` #### Делегированные события Для назначения событий и для будущих элементов (такие события называются **Delegated events**) используется `on` для родительского элемента с указанием селектора дочерних элементов. После этого добавления дочерних элементов отслеживается и обработчики работают и для новых элементов: ```javascript $(document.body).on("click", "button", function(){ alert("click"); }); ``` Вместо назначения обработчика `click` для всех элементов `button` выше мы указываем в каком элементе (`document.body`) для каких дочерних элементов (`"button"`) назначить обработчик события `"click"` *отныне и навсегда*, т. е. создать делегированное событие. https://repl.it/E8Fc/1 ### Инициируем событие, `trigger` На каждое событие может быть назначено *более одного* обработчика: ```javascript $(document.body).on("click", "button", function(){ alert("click"); }); $(document.body).on("click", "button", function(){ alert("click 2"); }); ``` В таком случае срабатывают оба обработчика *в порядке определения*. Для запуска обработчиков события используйте `trigger`: ```javascript $("button").trigger("click"); ``` Таким образом можете имитировать любые события, или запустить сложную цепочку обработчиков, если она не выделена у вас в отдельную функцию. Так же это полезный прием для автоматизации чужих сайтов, если применить это, например, с **TamperMonkey**. https://repl.it/E8Fc/4 ### Управление обработкой события Можно назначать события элементам, вложенным друг в друга, например `click` кнопке и элементу, в котором кнопка находится: ```javascript $(document.body).on("click", function(){ alert("body click"); }); ``` Обратите внимание, что тут создается *обычное*, а не *делегированное* событие, так как второй параметр - не селектор вложенных элементов, а обработчик события. Так работает `on`. При клике на кнопку так же происходит клик на элемент `body`, в котором эта кнопка находится. Это называется **всплытием события**. Подобное поведение не всегда нужно, рассмотрим функции, с помощью которых мы можем изменить эту логику. https://repl.it/E8Fc/5 #### `stopPropagation` Это функция-метод объекта события, который передается в качестве первого параметра в обработчик события. Используя его вы можете прервать всплытие события: ```javascript $(document.body).on("click", "button", function(evt){ evt.stopPropagation(); alert("click"); }); ``` После `stopPropagation()` событие *не* будет инициировано и обработано в вышележащих элементах (`body` в нашем примере) https://repl.it/E8Fc/6 #### `stopImmediatePropagation` Работает так же, однако прерывает обработку не только событий в вышележащих элементах, но и в следующих обработчиках *этого* элемента: ```javascript $(document.body).on("click", "button", function(evt){ evt.stopImmediatePropagation(); alert("click"); }); ``` https://repl.it/E8Fc/7 #### `preventDefault` Для отмены стандартного поведения браузера на событие (например переход по ссылке при клике на ней) существует функция объекта-события `preventDefault`: ```javascript $("a").click(function(evt){ evt.preventDefault(); //ссылки не работают }) ``` #### `false` Так же работает и false как результат функции: ```javascript $("a").click(function(evt){ return false; //ссылки не работают }) ``` Однако `return false;` работает только для `on` событий. Если вы добавляете обработчик через `addEventListener`, `return false;` не сработает. ```javascript document.getElementById("eventListener").addEventListener("click", function(evt){ return false; }); ``` Поэтому `preventDefault` является более предпочтительным способом, который работает **всегда**. ## jQuery UI **jQuery UI** - библиотека виджетов (и не только), которая используется в связке с jQuery. Часть виджетов являются не очень актуальными в силу появления возможностей HTML5. ### Что это, зачем и как подключить https://developers.google.com/speed/libraries/#jquery-ui ```html <!-- jQuery --> <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script> <!-- jQueryUI --> <link rel="stylesheet" href="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/themes/smoothness/jquery-ui.css"> <script src="https://ajax.googleapis.com/ajax/libs/jqueryui/1.12.1/jquery-ui.min.js"></script> ``` Теперь мы можем использовать библиотеку. http://jqueryui.com ### jQuery UI как стандарт реализации API плагинов jQuery jQuery UI плагины работают стандартным для jQuery способом: как функция-метод, принадлежащая jQuery-объектам, найденным по селектору: ```javascript $( "#draggable" ).draggable(); ``` В этом примере плагин `draggable` применяется к элементу с id="draggable". http://jqueryui.com/draggable/ #### Инициализация При инициализации плагину могут передаваться определенные настройки с помощью ассоциативного массива: ```javascript $( "#draggable" ).draggable({ axis: "y" }); $( "#draggable2" ).draggable({ axis: "x" }); $( "#draggable3" ).draggable({ containment: "#containment-wrapper", scroll: false }); $( "#draggable4" ).draggable({ containment: "parent" }); ``` или же с параметрами по умолчанию: ```javascript $( "#draggable" ).draggable(); ``` Набор параметров и их описание ищите в документации к плагину. #### Методы Методы плагина позволяют оперировать с плагином в процессе его использования. Метод передается *строкой* в качестве первого параметра функции-плагина: ```javascript var options = $( "#draggable" ).draggable( "option" ); ``` Пример выше вызывает метод `option`, результат в форме ассоциативного массива сохраняется в переменной `options`. Для задания настроек: ```javascript $( "#draggable" ).draggable( "option", { disabled: true } ); ``` Вторым параметром идет ассоциативный массив с настройками для обновления внутри плагина. Обычно набор опций при инициализации совпадает с набором опций метода `option`. Для удаления плагина обычно существует метод `destroy`: ```javascript $( "#draggable" ).draggable( "destroy" ); ``` Документация для ознакомления: http://api.jqueryui.com/draggable/ ## Chaining jQuery позволяет объединять несколько вызовов методов в *цепочки* следующим образом: ```javascript $(this).css({"font-size": "2em"}).html("clicked") ``` https://repl.it/E8Fc/10 В этом примере две операции объединены через точку. Это реализуется с помощью `return this`. ## AJAX/AJAJ **Asynchronous Javascript And XML** - изначально задумка M$, для получения возможности обращаться к серверам незаметно для пользователя из JS-кода. Представлена одним дополнительным объектом (XMLHttpRequest). jQuery предоставляет свою обертку над этим объектом, которая более удобна в использовании: ```javascript $.get( "URL", function( data ) { alert(data); }); ``` Эта технология может передавать не только XML, но и любые другие данные; таким образом не совсем корректно называть её AJAX. В JS удобно работать с JSON, посему можно назвать это AJAJ. **Задание:** прочитать данные и представить в виде ассоциативного массива из источника: [JSON](https://raw.githubusercontent.com/David-Haim/CountriesToCitiesJSON/master/countriesToCities.json) ### GET и POST Существует два основных HTTP метода - **GET** и **POST**. #### GET **GET** в целом аналогичен обычному посещению страницы или получению статического файла. Есть возможность отправить данные на сервер только с помощью **cookies** или параметров **GET**, которые идут после знака ? в конце **URL**: https://www.google.com.ua/search?client=opera&q=get+url&sourceid=opera&ie=UTF-8&oe=UTF-8 - `=` отделяет параметр от значения - `&` отделяет пары параметр-значения друг от друга - ` ` (пробел) заменяется на `+`. - и кое-что еще, погуглите. #### POST Двунаправленное общение браузера с сервером обычно предполагает метод **POST** или иной. Метод **POST** позволяет отправлять данные в *теле запроса* а не в URL (как метод GET). Таким образом обычно отправляются данные форм, файлы и так далее. Мы будем использовать **POST** для отправки JSON на сервер.