From a62682e188b5a05f5ed1567283a9a4173fb5153c Mon Sep 17 00:00:00 2001 From: Ilya Kantor Date: Sat, 21 Feb 2015 00:59:02 +0300 Subject: [PATCH] renovations --- .../2-coding-style/code-style.svg | 4 +- .../1-table-template/solution.view/index.html | 10 +- .../1-table-template/source.view/index.html | 3 +- .../1-table-template/task.md | 2 +- .../3-menu-template/solution.md | 7 +- .../3-menu-template/solution.view/index.html | 27 +- .../3-menu-template/solution.view/menu.css | 12 +- .../3-menu-template/solution.view/menu.js | 45 ++- .../3-menu-template/source.view/index.html | 15 +- .../3-menu-template/source.view/menu.css | 12 +- .../3-menu-template/source.view/menu.js | 32 +- .../4-template-lodash/3-menu-template/task.md | 18 +- 2-ui/5-widgets/4-template-lodash/article.md | 99 +++--- .../template-error-sourceurl.view/index.html | 8 +- .../5-custom-events/1-voter-events/index.html | 94 ----- .../1-voter-events/solution.view/index.html | 66 +--- .../1-voter-events/solution.view/voter.js | 36 ++ .../5-custom-events/1-voter-events/task.md | 15 +- .../2-selectable-list-evented/solution.md | 8 - .../solution.view/index.html | 69 +--- .../solution.view/listSelect.js | 81 +++++ .../solution.view/style.css | 7 + .../2-selectable-list-evented/task.md | 4 +- .../solution.view/customselect.css | 33 +- .../solution.view/customselect.js | 53 ++- .../3-custom-select/solution.view/index.html | 22 +- .../source.view/customselect.css | 50 +++ .../source.view/customselect.js | 1 + .../3-custom-select/source.view/index.html | 29 +- .../5-custom-events/3-custom-select/task.md | 4 +- 2-ui/5-widgets/5-custom-events/article.md | 329 +++--------------- .../menu-callback.view/index.html | 30 +- .../menu-callback.view/menu.css | 24 ++ .../menu-callback.view/menu.js | 53 +-- .../menu-callback.view/style.css | 20 -- .../menu-event.view/eventMixin.js | 48 --- .../menu-event.view/index.html | 29 +- .../5-custom-events/menu-event.view/menu.css | 24 ++ .../5-custom-events/menu-event.view/menu.js | 53 +-- .../5-custom-events/menu-event.view/style.css | 20 -- .../1-date-selector/solution.view/index.html | 2 +- .../1-date-selector/source.view/index.html | 2 +- .../2-draggable-windows/index.html | 2 +- .../solution.view/index.html | 2 +- .../source.view/index.html | 2 +- .../3-window-manager/solution.view/index.html | 2 +- .../solution.view/index.html | 2 +- .../source.view/index.html | 2 +- .../solution.view/index.html | 2 +- 49 files changed, 620 insertions(+), 894 deletions(-) delete mode 100755 2-ui/5-widgets/5-custom-events/1-voter-events/index.html create mode 100644 2-ui/5-widgets/5-custom-events/1-voter-events/solution.view/voter.js create mode 100644 2-ui/5-widgets/5-custom-events/2-selectable-list-evented/solution.view/listSelect.js create mode 100644 2-ui/5-widgets/5-custom-events/2-selectable-list-evented/solution.view/style.css create mode 100644 2-ui/5-widgets/5-custom-events/3-custom-select/source.view/customselect.css create mode 100644 2-ui/5-widgets/5-custom-events/3-custom-select/source.view/customselect.js create mode 100644 2-ui/5-widgets/5-custom-events/menu-callback.view/menu.css delete mode 100755 2-ui/5-widgets/5-custom-events/menu-callback.view/style.css delete mode 100755 2-ui/5-widgets/5-custom-events/menu-event.view/eventMixin.js create mode 100644 2-ui/5-widgets/5-custom-events/menu-event.view/menu.css delete mode 100755 2-ui/5-widgets/5-custom-events/menu-event.view/style.css diff --git a/1-js/3-writing-js/2-coding-style/code-style.svg b/1-js/3-writing-js/2-coding-style/code-style.svg index 71e1ce4a..64fa7c07 100644 --- a/1-js/3-writing-js/2-coding-style/code-style.svg +++ b/1-js/3-writing-js/2-coding-style/code-style.svg @@ -1,8 +1,8 @@ - + code-style.svg - Created with Sketch. + Created with bin/sketchtool. diff --git a/2-ui/5-widgets/4-template-lodash/1-table-template/solution.view/index.html b/2-ui/5-widgets/4-template-lodash/1-table-template/solution.view/index.html index 11e61c9f..e24e7ea1 100755 --- a/2-ui/5-widgets/4-template-lodash/1-table-template/solution.view/index.html +++ b/2-ui/5-widgets/4-template-lodash/1-table-template/solution.view/index.html @@ -2,8 +2,7 @@ - - + - - - -
- - 0 - + -
- - - - - - diff --git a/2-ui/5-widgets/5-custom-events/1-voter-events/solution.view/index.html b/2-ui/5-widgets/5-custom-events/1-voter-events/solution.view/index.html index ba822a6a..6b80f167 100755 --- a/2-ui/5-widgets/5-custom-events/1-voter-events/solution.view/index.html +++ b/2-ui/5-widgets/5-custom-events/1-voter-events/solution.view/index.html @@ -2,7 +2,6 @@ - + + @@ -24,67 +25,14 @@ diff --git a/2-ui/5-widgets/5-custom-events/1-voter-events/solution.view/voter.js b/2-ui/5-widgets/5-custom-events/1-voter-events/solution.view/voter.js new file mode 100644 index 00000000..81a9bfde --- /dev/null +++ b/2-ui/5-widgets/5-custom-events/1-voter-events/solution.view/voter.js @@ -0,0 +1,36 @@ +function Voter(options) { + var elem = options.elem; + + var voteElem = elem.querySelector('.vote'); + + elem.onclick = function(event) { + // сам обработчик не меняет голос, он вызывает функцию + if (event.target.closest('.down')) { + voteDecrease(); + } else if (event.target.closest('.up')) { + voteIncrease(); + } + } + + elem.onmousedown = function() { + return false; + }; + + // ----------- методы ------------- + + function voteDecrease() { + setVote(+voteElem.innerHTML - 1); + } + + function voteIncrease() { + setVote(+voteElem.innerHTML + 1); + } + + function setVote(vote) { + voteElem.innerHTML = +vote; + var widgetEvent = new CustomEvent("change", { bubbles: true, detail: +vote }); + elem.dispatchEvent(widgetEvent); + }; + + this.setVote = setVote; +} diff --git a/2-ui/5-widgets/5-custom-events/1-voter-events/task.md b/2-ui/5-widgets/5-custom-events/1-voter-events/task.md index e55c538b..07a130d9 100644 --- a/2-ui/5-widgets/5-custom-events/1-voter-events/task.md +++ b/2-ui/5-widgets/5-custom-events/1-voter-events/task.md @@ -2,24 +2,25 @@ [importance 5] -Добавьте событие в голосовалку, созданную в задаче [](/task/voter), используя jQuery-механизм генерации событий на объекте. +Добавьте событие в голосовалку, созданную в задаче [](/task/voter), используя механизм генерации событий на объекте. -Пусть каждое изменение голоса сопровождается событием `change`: +Пусть каждое изменение голоса сопровождается событием `change` со свойством `detail`, содержащим обновлённое значение: ```js var voter = new Voter({ - elem: $('#voter'), - value: 5 + elem: document.getElementById('voter') }); -$(voter).on('change', function(e) { - alert(e.value); +voter.setVote(5); + +document.getElementById('voter').addEventListener('change', function(e) { + alert(e.detail); // новое значение голоса }); ``` Все изменения голоса должны производиться централизованно, через метод `setVote`, который и генерирует событие. Результат использования кода выше (планируемый): -[iframe border=1 height=60 src="index.html"]. +[iframe border=1 height=60 src="solution"] Исходный документ возьмите из решения задачи [](/task/voter). \ No newline at end of file diff --git a/2-ui/5-widgets/5-custom-events/2-selectable-list-evented/solution.md b/2-ui/5-widgets/5-custom-events/2-selectable-list-evented/solution.md index f09f45fe..e69de29b 100644 --- a/2-ui/5-widgets/5-custom-events/2-selectable-list-evented/solution.md +++ b/2-ui/5-widgets/5-custom-events/2-selectable-list-evented/solution.md @@ -1,8 +0,0 @@ - - -Обратите внимание: - \ No newline at end of file diff --git a/2-ui/5-widgets/5-custom-events/2-selectable-list-evented/solution.view/index.html b/2-ui/5-widgets/5-custom-events/2-selectable-list-evented/solution.view/index.html index 649ca116..a8153c03 100755 --- a/2-ui/5-widgets/5-custom-events/2-selectable-list-evented/solution.view/index.html +++ b/2-ui/5-widgets/5-custom-events/2-selectable-list-evented/solution.view/index.html @@ -2,22 +2,18 @@ - - + + + Клик на элементе выделяет только его.
-Shift+Клик добавляет/убирает элемент из выделенных.
+Ctrl(Cmd)+Клик добавляет/убирает элемент из выделенных.
+Shift+Клик добавляет промежуток от последнего кликнутого к выделению.
-
-
Выберите
-
    + +
    • Плотоядные
    • Травоядные
    • Всеядные
    • -
+
diff --git a/2-ui/5-widgets/5-custom-events/3-custom-select/source.view/customselect.css b/2-ui/5-widgets/5-custom-events/3-custom-select/source.view/customselect.css new file mode 100644 index 00000000..ff8ae390 --- /dev/null +++ b/2-ui/5-widgets/5-custom-events/3-custom-select/source.view/customselect.css @@ -0,0 +1,50 @@ +.customselect { + width: 200px; + font-size: 14px; + display: inline-block; +} + +.customselect .title { + height: 20px; + border: 2px groove #ADD8E6; + background: white; + width: 200px; + box-sizing: border-box; + padding: 2px; + line-height: 14px; + cursor: pointer; + text-align: left; +} + +.customselect li { + padding: 2px; + cursor: pointer; +} + +.customselect li:nth-child(even) { + background-color: #f0f8ff; +} + +.customselect li:hover { + background-color: #7fffd4; +} + +.customselect ul { + list-style: none; + margin: 0; + padding: 0; + display: none; + + position: absolute; + z-index: 1000; + background: white; + width: 200px; + border-bottom: 1px solid #add8e6; + border-left: 1px solid #add8e6; + border-right: 1px solid #add8e6; + box-sizing: border-box; +} + +.customselect.open ul { + display: block; +} diff --git a/2-ui/5-widgets/5-custom-events/3-custom-select/source.view/customselect.js b/2-ui/5-widgets/5-custom-events/3-custom-select/source.view/customselect.js new file mode 100644 index 00000000..c6fb05b4 --- /dev/null +++ b/2-ui/5-widgets/5-custom-events/3-custom-select/source.view/customselect.js @@ -0,0 +1 @@ +// ваш код CustomSelect \ No newline at end of file diff --git a/2-ui/5-widgets/5-custom-events/3-custom-select/source.view/index.html b/2-ui/5-widgets/5-custom-events/3-custom-select/source.view/index.html index 826163f7..5119c7ee 100755 --- a/2-ui/5-widgets/5-custom-events/3-custom-select/source.view/index.html +++ b/2-ui/5-widgets/5-custom-events/3-custom-select/source.view/index.html @@ -2,54 +2,51 @@ Селект - + +
Последний результат: ...
- -
-
Выберите
-
    + +
    • Птицы
    • Рыбы
    • Звери
    • Динозавры
    • Одноклеточные
    • -
+
-
Выберите
-
    + +
    • Плотоядные
    • Травоядные
    • Всеядные
    • -
+
- + \ No newline at end of file diff --git a/2-ui/5-widgets/5-custom-events/3-custom-select/task.md b/2-ui/5-widgets/5-custom-events/3-custom-select/task.md index 785c9f8b..49aac1a2 100644 --- a/2-ui/5-widgets/5-custom-events/3-custom-select/task.md +++ b/2-ui/5-widgets/5-custom-events/3-custom-select/task.md @@ -8,12 +8,12 @@ Например: -[iframe src="solution" border="1" height="200" newwin] +[iframe src="solution" height="200"] В примере выше два селекта, чтобы можно было проверить процесс открытия-закрытия. diff --git a/2-ui/5-widgets/5-custom-events/article.md b/2-ui/5-widgets/5-custom-events/article.md index 87b3a24f..ddbdd7c9 100644 --- a/2-ui/5-widgets/5-custom-events/article.md +++ b/2-ui/5-widgets/5-custom-events/article.md @@ -1,6 +1,6 @@ # Коллбэки и события на компонентах -Компоненты, хоть и каждый сам по себе, обычно интегрированы друг с другом. +Компоненты, хоть и каждый сам по себе, обычно как-то общаются с остальной частью страницы Есть несколько способов, при помощи которых компоненты сообщают друг другу о важных событиях, которые в них произошли. @@ -15,8 +15,8 @@ ```js var menu = new Menu({ title: "Сладости", - template: _.template($('#menu-template').html()), - listTemplate: _.template($('#menu-list-template').html()), + template: _.template(document.getElementById('menu-template').innerHTML), + listTemplate: _.template(document.getElementById('menu-list-template').innerHTML, items: { "donut": "Пончик", "cake": "Пирожное", @@ -34,321 +34,84 @@ function showSelected(href) { */!* ``` -В коде меню нужно будет вызывать её, как-то так: +В коде меню нужно будет вызывать её, например так: ```js ... - function onItemClick(e) { - e.preventDefault(); -*!* - var onselect = options.onselect; - if (onselect) { - onselect(e.currentTarget.getAttribute('href').slice(1)); - } -*/!* + function select(link) { + options.onselect(link.getAttribute('href').slice(1)); + ... } ... ``` -Демо: +Полный пример: [codetabs src="menu-callback" height="180"] ## Свои события -Оповещение через коллбэки -- это примерный аналог назначения обработчика через `onсвойство` для DOM-элементов. +Как мы уже знаем, в современных браузерах DOM-элементы могут [генерировать поизвольные события](/dispatch-events) при помощи встроенных методов, а в IE8- это возможно с использованием фреймворка, к примеру, jQuery. -Да, он работает, но чтобы можно было назначать сколько угодно обработчиков в любой момент, нужна полноценная поддержка событий, то есть аналог `addEventListener`. +Воспользуемся ими, чтобы корневой элемент меню генерировал событие, которое мы назовём `select`, при выборе элемента, и передавал в объект события выбранное значение. -Поддержка событий для компонентов будет выглядеть так: +Для этого модифицируем функцию `select`: + +```js +function Menu(options) { + ... + + function select(link) { +*!* + var widgetEvent = new CustomEvent("select", { + bubbles: true, + // detail - стандартное свойство CustomEvent для произвольных данных + detail: link.getAttribute('href').slice(1) + }); + elem.dispatchEvent(widgetEvent); +*/!* + } + + ... +} +``` + +Код, который заинтересован в том, чтобы узнавать, что выбрано в меню, подписывается на событие `select` его корневого элемента: ```js var menu = new Menu(...); -// любой код может подписаться на событие "select" -menu.on("select", function(item) { - // при выборе пункта меню сработает этот обработчик - alert("Выбран элемент " + item); +var elem = menu.getElem(); + +elem.addEventListener('select', function(event) { + alert(event.detail); }); ``` -Код, который заинтересован в том, чтобы узнавать, что происходит с меню, подписывается на нужные события вызовом `menu.on(имя события, обработчик)`. +Вместо `detail` можно было бы выбрать и другое название свойства, но тогда нужно позаботиться о том, чтобы оно не конфликтовало со стандартными. Кроме того, в конструкторе `CustomEvent` разрешено только `detail`, другое свойство понадобилось бы присваивать в отдельной строке. -Далее `Menu` при наступлении события вызывает обработчик методом `trigger`, при необходимости передавая ему важные данные в качестве аргументов, вот так: +Полный пример: -```js -function Menu(options) { - var self = this; - -*!* - // ... при клике на item - сгенерировать событие (trigger) - function onItemClick(e) { - e.preventDefault(); - - self.trigger("select", e.currentTarget.getAttribute('href').slice(1)); - } -*/!* - -} -``` - -Обратим внимание -- события будут генерироваться не на элементе `