# 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 на сервер.