Выпадающий список
Создадим простую компоненту, выпадающий dropdown список. (Обратите внимание, в коде всех заметок не будет jQuery). Пусть у нас есть якорь (форма ввода), и пусть, когда она получает фокус, под ней возникает выпадающий список заранее определенных значений. При клике на элементе списка получим его значение в произвольной функции.
Код примера доступен по адресу https://github.com/mbykov/component-dropdown-example. Клонируйте его и откройте в браузере файл test/example.html
, кликните на input
.
Создадим скелет компоненты этого примера:
$ component create dropdown-example
repo (username/project): mbykov/component-dropdown-example
description: simple dropdown example
. . .
в components.json нужно указать необходимые нам компоненты:
"dependencies": {
"component/domify": "*",
"component/each": "*",
"component/classes": "*"
},
И выполняем $ make
. В файле Makefile
вы увидите, в частности (о формате makefile в заметке makefile vs. grunt):
build: components index.js dropdown.css
@component build --dev
components: component.json
@component install --dev
Это означает, что component
установит все зависимости и создаст файлыbuild/build.js и build/build.css
. (я переименовал исходный dd-example.css в dropdown.css, и соответственно исправил Makefile).
создание примера
Теперь создадим пример. Создаем директорию test
и в ней файл example.html
, суть которого
<p><input type="text" id="anchor"><p>
<script>
var anchor = document.querySelector('#anchor');
var Dropdown = require('dd-example');
var dd = new Dropdown(anchor);
</script>
А в файле index.js
компоненты добавим основное содержание:
var domify = require('domify');
var classes = require('classes');
var each = require('each');
module.exports = Dropdown;
function Dropdown(anchor) {
console.log(anchor);
return this;
}
Обратите внимание на return this
— это важно. Теперь мы можем создать цепочку методов для нашей компоненты. Каждый следующий метод получает все тот же this.
Теперь снова make, и релоад тестовой страницы (пока мы не используем watch, поэтому make вручную). В Фаейрбаге видим, что все идет как нужно, видим якорь.
Напишем собственно компоненту dropdown
.
function Dropdown(anchor) {
var _div = domify('<div></div>');
var _list = domify('<ul></ul>');
_div.appendChild(_list);
this.list = _list;
this.div = _div;
this.anchor = anchor;
anchor.parentNode.insertBefore(_div, anchor.nextSibling);
anchor.focus();
return this;
}
Что здесь происходит?
Мы создаем два объекта, _div
и _list
. Подчеркиванием мне удобно выделять DOM-объекты (underscore нам больше не нужен, а знак $ как-то не смотрится, но дело вкуса). В реальной жизни нужно, конечно, поместить html в template.html, и вызвать егоrequire('template')
. Не делаю здесь для наглядности кода.
В строках this.list = _list
сохраняем эти объекты как атрибуты объекта this, это пригодится в цепочке методов. И добавляем новый объект на страницу.
$ make
Но ничего не изменилось? Правильно, теперь нужно показать список с предопределенными значениями при клике на якорь. Добавим в _div и файл .css класс hidden, и в функцию Dropdow клик на якорь, и метод toggle():
var self = this;
anchor.onclick = function(e){
self.toggle();
classes(this.div).remove('hidden');
return false;
}
и создадим метод, который покажет значения
Dropdown.prototype.render = function(values) {
var self = this;
values.each(function(value){
var added = domify('<li></li>');
added.textContent = value;
self.list.appendChild(added);
});
return this;
}
добавим в текст примера example.html вызов метода render
c предопреденными значениями: var values = ['Асафий Аскольдович'...
dd.render(values)
Здесь нет точки с запятой после строки. Это не ошибка, на следующей строчке будет вызван следующий метод компоненты — .select().
Теперь выведем значение при клике по строке списка в произвольном колбеке к нашей компоненте (Колбек в примере — будет просто console.log).
Dropdown.prototype.select = function(cb){
var self = this;
this.list.onclick = function(e) {
var value = e.target.textContent;
anchor.value = value;
self.hide();
cb(value);
};
}
здесь нам не нужно возвращать return this
в конце функции, потому что это конец цепочки. Вызовем метод .select
в example.html
, в котором выведем значение на консоль. Voila.
заключение
Совсем уже последнее, и не имеющее прямого отношения к примеру — список выводится не под якорем, а в начале строки. Но для красоты выравняем список — это одна строчка в главной функции:
_div.style.left = getOffset(anchor).left +'px';
функцию getOffset я позаимствовал у Mathew Muellera, спасибо ему.
При создании этого примера и своей «взрослой» компоненты dropdown я ориентировался на примеры старших товарищей: component/dropdown
, stagas/dropdown
,bmcmahen/dropdown
, matthewmueller/autocomplete
. Они, правда, все используют jQuery, из-за чего я и написал свой mbykov/dropdown
— он рассчитан на json-данные, получаемые из couchdb
, поэтому имеет свои особенности.
Теперь можно использовать этот выпадающий список сколько угодно раз, с любыми предопределенными значениями, на одной странице или на многих.