Случайны выбор дневника Раскрыть/свернуть полный список возможностей


Найдено 10769 сообщений
Cообщения с меткой

html - Самое интересное в блогах

Следующие 30  »
rss_rss_hh_new

Библиотека, облегчающая разработку форм на сайтах (v3)

Суббота, 23 Июля 2016 г. 18:51 (ссылка)

Привет, Хабр!



Как-то, год назад я писал о своей небольшой библиотеке, которая облегчает разработку форм на сайтах. Недавно я выпустил 3-ю версию, которая, по-сути, была переписана с нуля, чтобы стать правильней и удобней. Но в своей статье я не буду повторять README и ДЕМО, а лучше покажу на практике, каким образом она помогает писать меньше кода.





Но прежде, хотелось бы дать немного информации о новой версии. В ней, я избавился от зависимости malsup jquery.form для отправки файлов, и один большой репозитарий я разделил на несколько мелких самостоятельных репозитариев, сохранив, при этом, общую сборку "всё-в-одном":




  • поддержка дополнительных событий форм (form-extra-events);

  • полифил HTML5 form-атрибутов (form-association-polyfill);

  • поддержка отправки файлов через iframe для старых браузеров (jquery-iframe-ajax);

  • и, собственно, сама библиотека (paulzi-form).





Дополнительные события форм



Во второй версии библиотеки я столкнулся с проблемой необходимости соблюдения определённого порядка подключения скриптов. Например, раньше нельзя было подключать данный скрипт перед стандартным скриптом валидации Yii2, дело в том, что на событие submit навешиваются все скрипты, которые так или иначе должны обработать отправку, в частности произвести валидацию, и нет никакой гарантии что кто-то это событие не прервёт вызовом preventDefault(). Поэтому, в случае неверного порядка подключения, сначала происходила блокировка формы, а затем валидация, и, если были ошибки валидации, повторно отправить форму было уже нельзя. form-extra-events решает эту проблему, он предоставляет несколько новых типов событий формы, одно из которых гарантирует то, что форма отправляется, и этот процесс уже нельзя прервать. Кроме того, генерируются события начала и завершения отправки формы, что используется во всех остальных возможностях библиотеки.



Сайт-прототип



Для демонстрации полезности библиотеки, я набросал прототип типичного интернет-магазина на Bootstrap:

http://paulzi.ru/paulzi-form-site/

Из скриптов используем только jQuery, bootstrap и paulzi-form.all.js. В данном прототипе мы не используем ни строчки JS-кода написанного специально для сайта-прототипа.





Html5 form-атрибуты



В чём может пригодиться HTML5 form-атрибуты? Например, в корзине предполагается несколько действий над выбранными товарами — добавить в избранное, отправить на Email, скачать. Конечно, можно было бы сделать единый action, а в параметрах передавать, что конкретно нужно сделать. Но это некрасиво, т. к. порождает использование switch($action), вместо того, чтобы сразу направить на конкретный action (например, в Yii2). А если вы откроете модальное окно, то увидите, что кнопку отправки пришлось сделать вне самой формы, тем не менее она продолжает функционировать, так как ей был указан атрибут form. А самое главное, данные атрибуты сильно выручают в ситуациях, когда в большой форме нужно сделать маленькую форму, что стандарт HTML запрещает.



Не отправлять пустые поля



Теперь, обратим внимание на фильтр в каталоге. Если отметить галочкой «Intel Core i5» и отправить данную форму, то даже если другие поля не заполнены, мы всё равно получим длинную простыню из параметров после перехода:

?proce_from=&proce_to=&tdp_from=&tdp_from=&line[]=i5



Используя библиотеку, если добавить к форме атрибут data-submit-empty="false" незаполненные поля не будут отправляться, и в результате получится более человекопонятный URL:



?line[]=i5





Блокировка повторной отправки



Рассмотрим форму заказа обратного звонка. Если вы сделаете двойной щелчок по кнопке отправки формы, форма у вас отправится дважды, и вам придёт два письма. Это неправильно, поэтому скрипт по-умолчанию блокирует возможность повторной отправки формы, до тех пор, пока запрос не выполнится. Пример корректной работы можно увидеть в форме «Написать нам». Регулируется это поведение путём установки атрибута data-lock="false"



Индикация состояния отправки



Иногда, процесс отправки формы может занимать длительное время (отправка файла, процессороёмкий обработчик, медленный интернет), и если никак не отобразить, что форма отправляется, пользователь рано или поздно подумает, что либо он не нажал кнопку, либо что-то зависло, и нажмёт кнопку повторно. Пример такой формы — форма «Написать нам». В библиотеке предусмотрено несколько вариантов, в прототипе я использовал атрибуты data-loading-text и data-loading-icon, которые изменяют текст кнопки и добавляют иконку. Также к форме и кнопке добавляются классы form-loading и btn-loading, это позволяет застилизовать состояние через CSS.



AJAX-отправка формы



Ну и самое главное, это возможность отправки формы через AJAX. Действительно, у нас в прототипе есть две формы в модальных окнах, логично при нажатии на кнопку отправки не осуществлять переходы между страницами, а просто закрыть модальное окно и вывести сообщение об успехе. И тут всё очень легко — добавляем атрибут data-via="ajax", и вуаля, форма отправляется через AJAX. И мало того, те, кто хоть раз занимался передачей через AJAX файлов знает, что сделать это не так просто, т. к. поддержка отправки файлов появилось только начиная с XMLHttpRequrest 2. Для этого часто подключают сторонние библиотеки, которые часто требуют написания на серверной части особых обработчиков, хранить файлы во временной папке, а потом при отправке формы в отдельном запросе их оттуда забирать. В нашем же случае, об этом практически не надо задумываться — всё идёт также, как если бы форма отправлялась стандартным способом. При необходимости можно легко вывести процент отправленных данных, подцепившись на событие uploadprogress.



Обработка AJAX-ответов



Посмотрим на пример посложнее — кнопка добавления в корзину на странице каталога. При нажатии на неё надо не просто выполнить запрос и вывести сообщение — нужно обновить краткий список содержимого корзины при наведении и обновить счётчик количества товаров в ней. Этот момент тоже учтён, и я постарался сделать максимально гибкий обработчик AJAX-ответов. Рассмотрим ответ, который приходит при нажатии на «В корзину» в прототипе:

ответ на запрос
43


Товар добавлен в корзину!



AMD K6

10 шт.



Intel Celeron

12 шт.



Intel Core i7

1 шт.



Итого:

117 000

https://habrahabr.ru/post/306278/

Метки:   Комментарии (0)КомментироватьВ цитатник или сообщество
rss_rss_hh_new

Уведомления в браузере и пример того, как их можно использовать с пользой

Четверг, 21 Июля 2016 г. 15:39 (ссылка)





Вероятно, вы все уже слышали про технологию «Веб-push» в составе Push API и Notifications API. Я уверен, что среди вас есть те, кто возлагает надежды на эту технологию, как на новый канал коммуникации с пользователем. И я не исключаю возможность, что данную статью будут читать основатели тех немногочисленных стартапов, которые всерьёз занялись окучиванием технологии «Веб-push» для рекламы и маркетинга. Сегодня я вам расскажу, о том как можно использовать данную технологию.



Современные веб стандарты подарили нам возможность посылать пользователю уведомления. Это такие всплывающие сообщения в правом нижнем углу экрана, хотя местоположение зависит от используемого браузера, а повлиять на расположение сообщения разработчик напрямую не может. И вот эти сообщения всплывают значит и показывают какую-то информацию. Информацию заведомо нужную пользователю, так как нельзя распространить эти уведомления на аудиторию, которая на них не подписана. И всё вроде бы логично, но пользователи упорно жмут кнопку «Отказаться», когда им предлагают подписаться на получение таких уведомлений. Попробуем разобраться почему так происходит.



Технология «веб-push» буксует на одном месте и это очевидно. Помимо раздражающего фактора наличия самого уведомления, которое стремительным, ослепительно белым аэропланом врывается на поверхность рабочего стола, есть ещё одна причина. Это использование технологии не по назначению. Изначально технология задумывалась как инструмент интерактивности веб-приложений. Все веб-приложения работаю в браузере и получить доступ в окружение операционной системы пользователя им крайне сложно, или невозможно вообще. Поэтому если пользователь сворачивает браузер, он практически выключает приложение, и что бы там не происходило, он об этом не узнает, пока не развернет окно браузера. Технология уведомлений позволяет обратить внимание пользователя на приложение даже когда браузер свернут. Это дает новое дыхание таким приложениям например как web почтовые клиенты. Но некоторым людям захотелось использовать этот канал связи для интернет-маркетинга и рекламы. Предполагается, что пользователи добровольно будут подписываться на такого рода рассылки.



Но так или иначе технология существует и её надо осваивать. Настал тот момент, когда я решил встроить уведомления на сайт. Как оказалось, технология (Web Push API и Notification API) достаточно простая и естественно появилось желание поэкспериментировать. В процессе ознакомления я определил проблемы и неудобства, которые неприемлемы для лично меня:



Со стороны пользователя


  • неадекватная система подписки/отписки на уведомления

  • нет доступа к истории уведомлений

  • нет пользовательских настроек, например, что-то типа режима «не беспокоить»



Со стороны отправителя уведомлений


  • отсутствие контроля за уведомлениями и базой пользователей

  • отсутствие статистики по активности клики/просмотры



Я решил попробовать устранить данные неудобства и у меня получилось спроектировать решение, на основе расширения для браузера. Архитектура клиент-серверная и расширение выступает в роли клиента. Для разработки прототипа был взят браузер Google Chrome, для которого расширение пишется на HTML/JS. Панель управления выполнена на PHP. Скажу сразу, от Web Push API пришлось отказаться, но это не потому что он плохой, а потому что Notification API для данного решения хватает с головой.



Собственно, для начала было сделано расширение для браузера, которое умеет бегать на сервер и спрашивать есть ли для него сообщения (ссылка на код расширения в конце статьи). Если сообщения есть, то в зависимости от настроек пользователя, появляются уведомления на рабочем столе. Так же пользователь может получить доступ к списку активных уведомлений в любое время нажав на иконку расширения в браузере. Есть опция «Не беспокоить», которая позволяет отключать уведомления, но оставляет возможность пользователю получить доступ к пришедшим уведомлениям через кнопку расширения. Так же вне зависимости от настроек на кнопке расширения присутствует индикация наличия непрочитанных сообщений.



Установка расширения выполнена в inline стиле, благодаря чему подписка на уведомления сводится к двум кликам мышкой. Необходимо разместить кнопку, при нажатии на которую пользователю будет предложено установить расширение. Данную кнопку можно разместить в любом месте сайта. Также кнопку подписки можно прятать если расширение уже установлено. Вот пример посадочной страницы подписки на уведомления, который я сделал для приложения Пример посадочной страницы подписки



Расширение можно удалить стандартным способом, т.е. так же, как и любое другое расширение для браузера, но для удобства, дополнительно добавлена кнопка для удаления. На случай самоликвидации отправителя, существует способ удаленно деинсталлировать расширение со всех устройств пользователей, послав в заголовке сообщения секретную команду, где вы ещё такое найдёте :).

if (obj[i]['title']=='666') {
chrome.management.uninstallSelf();
}


Что касается серверной части, то тут мы имеем небольшую админку написанную на PHP для внесения уведомлений в БД и шлюз для приема запросов от пользователей и соответственно выдачу уведомлений из БД. Этот же шлюз используется для сбора статистики и пишет всё в ту же БД.







Вот пример того как сервер отдает JSON для уведомлений (установлен лимит в 3 сообщения).

//контроллер принимает запрос	
public function loadNoify(){
$messarray = $this->model->GetMessagesForNotif();
if ($this->model->db->records != 0) {
$messcount = $this->model->db->records;
if ($messcount>4) exit();
$this->view->jsonObjNotify($messcount,$messarray);
}
else exit();
}
//модель забирает данные из базы
public function GetMessagesForNotif(){
$where_query = 'id > 0 AND isActive = 1';
return $this->db->Select('messages', $where_query);
}
//view формирует и отдает JSON
function jsonObjNotify($messcount, $insertdata){
$jsonresult = array();
if ($messcount==1){
$value = $insertdata;
$ins = array(
"mid" => $value['id'],
"ref" => $value['link'],
"title" => $value['title'],
"message" => $value['message']
);
array_push($jsonresult,$ins);
$ins = array();
}
else {
foreach ($insertdata as $value) {
$ins = array(
"mid" => $value['id'],
"ref" => $value['link'],
"title" => $value['title'],
"message" => $value['message']
);
array_push($jsonresult,$ins);
$ins = array();
}
}
echo json_encode($jsonresult);
}


А вот так формирую JSON для отображения в расширении. Тут по отдаем HTML снипет:

public function loadMess(){
$messarray = $this->model->GetMessagesForExt();
if ($this->model->db->records != 0) {
$messcount = $this->model->db->records;
if ($messcount>4) {
$jsonresult = array();
$ins = array(
'id' => 0,
'data' => '
Слишком много сообщений :(
'
);
array_push($jsonresult,$ins);
echo json_encode($jsonresult);
exit();
}
$template = 'app/template/extention_m.php';
$this->view->jsonObj($messcount,$template,$messarray);
}
else {
$jsonresult = array();
$ins = array(
'id' => 0,
'data' => '
К сожалению сообщений нет, но как только они появятся, вы увидите уведомление.
'
);
array_push($jsonresult,$ins);
echo json_encode($jsonresult);
}
}


Формируем HTML снипет extention_m.php:

$data.='
'.$value["title"].'
'.$value["message"].' подробнее...
';


Осталось рассказать про статистику. Я много делать не стал. В свою базу добавляю по минимуму. С остальным хорошо справляется Google Analytics. Просто при публикации расширения я указал Google Analytics ID и могу получать всю информацию о просмотрах и переходах по ссылкам, которые содержатся в уведомлениях.



Вот таким способом мне удалось оптимизировать технологию веб-push уведомлений и сделать её более удобной (по крайней мере для себя). Учитывая широкие возможности браузерных расширений, в данное приложение можно добавить более богатый функционал.



В завершение, как доказательство возможности применения Notification API в реальных задачах, хочу сказать, что мной написано два действительно важных приложения, одно из которых может оповещать о температуре в серверной, а второе присылает уведомления, если на маршрутизатор ядра логинится кто-то из админов.



Здесь само расширение для браузера Chrome , о котором говрится в статье.



P.S. Важно! Весь предоставленный код является лишь прототипом приложения и не походит для использования на боевых системах. Код не оптимизирован и не проверялся на безопасность. Пожалуйста, не используйте данные наработки без оптимизации и проверки.

Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/306146/

Метки:   Комментарии (0)КомментироватьВ цитатник или сообщество
Cosmeya

ДОПОЛНИТЕЛЬНЫЕ СИМВОЛЫ №3 с кодами. Переработка

Четверг, 21 Июля 2016 г. 08:56 (ссылка)

Это цитата сообщения Планула Оригинальное сообщение







♼ ♽ ♻ ♲ ♺ ♹ ♸ ♷ ♶ ♵ ♴ ♳


<<<<<<< далее >>>>>>>
Метки:   Комментарии (0)КомментироватьВ цитатник или сообщество
Cosmeya

Что такое Юникод?

Четверг, 21 Июля 2016 г. 08:31 (ссылка)
liveinternet.ru/users/48026...393827452/


Юникод (англ. Unicode) - это универсальный стандарт кодирования символов, который позволяет предоставить знаки всех языков мира.
В отличие от ASCII, один символ кодируется двумя байтами, что позволяет использовать 65 536 символов, против 256.
Как известно, один байт - это целое число от нуля до 255. В свою очередь, байт состоит из восьми бит, которые хранят числовые значения в двоичном виде, где каждая следующая единица текущего бита является в два раза большим значением предыдущего бита. Таким образом, два байта могут хранить в себе число от нуля до 65 535, что и позволяет использовать 65 536 символов (ноль + 65 535, ноль - это тоже число, он не является ничем).
Символы Юникода разделены на секции. Первые 128 символов повторяют таблицу ASCII.
Метки:   Комментарии (0)КомментироватьВ цитатник или сообщество
rss_rss_hh_new

Кэш, хэш и няш-меш

Вторник, 19 Июля 2016 г. 20:25 (ссылка)

Предыстория



Июльский субботний вечер подходил к концу. Нарубив дров на шашлык, я повесил USB-модем на багету, скомандовал sudo wvdial, развернул браузер и обновил вкладку с открытым гитхабом. Вернее, попытался обновить. Скорость не радовала, и в итоге страница-то обновилась, но явно не хватало какого-то из стилевых файлов; и дело было не в блокировке, поскольку аналогичные проблемы я наблюдал и с другими сайтами, и зачастую они решались просто многократным обновлением страницы. Во всём был виноват перегруз 3G-сети.



Стоп! А как же кэш?



Недолгое гугление привело на официальный гугловский мануал. Целиком пересказывать его не буду; скорее всего, дело было в том, что браузер прилежно ждал, когда сервер передаст ETags, а ответ сервера затерялся в переполненных триджунглях.



Через пару дней, возвращаясь душным днём из кафе, я придумал рацпредложение, которое решает эту (и несколько других проблем), которое и излагаю в данной статье.



Суть предложения



Добавить ко всем тэгам для подключения подчинённой статики (стилей, скриптов, изображений) атрибут checksum, который бы хранил хэш (например, SHA-1, как в git) требуемого файла:





Найдя в теле веб-страницы подобный тэг, браузер смотрит, есть ли объект с таким хэшем в кэше, и если есть, то не отправлять никаких запросов вообще: и так понятно, что файл — ровно тот, который требуется. Файлы в кэше браузера лучше сразу хранить с именами, соответствующими их хэшам, как это делает тот же git.



Обратная совместимость предлагаемого решения очевидна.



Какие проблемы это решает?



Пресловутая угадайка: актуален ли файл в кэше?




  • Больше не нужно отправлять запрос и сличать полученные ETags.

  • Даже если файл в кэше вроде как устарел, но хэш совпадает — его можно смело использовать.

  • Чистка кэша как средство решения проблем частично теряет актуальность.



Дилемма: jQuery со своего домена или с CDN?



Владельцам малых сайтов часто приходится выбирать: либо подключать jQuery и/или подобные ей библиотеки с CDN (гугловского, например), или со своего домена.

В первом случае уменьшается время загрузки сайта (в том числе первичной, т.е. при первом заходе посетителя на сайт) за счёт того, что файл с серверов Гугла с большой долей вероятности уже есть в кэше браузера. Но, например, разработчики WordPress придерживаются второго варианта, ставя во главу угла автономность. И в условиях, когда CDN падают, блокируются и т.д., их можно понять.

Теперь от такой проблемы можно будет избавиться навсегда: не всё ли равно, откуда получен файл, если его содержимое — это ровно то, что нужно html-странице, и она это удостоверяет? Можно смело указывать свой домен, и если библиотека есть в кэше (неважно, загруженная с этого сайта, другого "малого" сайта или из какого-нибудь CDN) — она подхватится.



Смешанный HTTPS/HTTP-контент



Одна из причин запрета загрузки HTTP-ресурсов на HTTPS-страницах — возможность подмены HTTP-контента. Теперь это больше не преграда: браузер может получить требуемый контент и сверить его хэш с хэшем, переданным по HTTP. Отмена запрета на смешанный контент (при наличии и совпадении хэша) позволит ускорить распространение HTTPS.



Косвенное определение истории по времени загрузки статики



Известно, что владелец некоторого сайта evilsite.org может (с некоторой долей вероятности) определить, был ли посетитель на другом сайте goodsite.org, запросив, например, изображение goodsite.org/favicon.ico. Если время загрузки иконки ничтожно мало — то она в кэше, следовательно, посетитель был на сайте goodsite.org. Теперь эта атака усложнится: околонулевое время отклика будет лишь обозначать, что посетитель был на сайте с таким же фавиконом. Это, конечно, не решает проблему целиком, но всё же несколько усложняет жизнь определяющему.



На что это не влияет?




  • На html-страницы

  • На изображения, стили и скрипты, открываемые по непосредственной ссылке, а не служащие вспомогательными элементами страницы.

  • На изображения, стили и скрипты, которые не предполагаются неизменными, например, когда подключается самая новая версия некоторой библиотеки с CDN этой библиотеки.



Идеология



Как обычно (математик я, что уж тут поделать) сформулируем аксиомы, которые вкладываются в предложение:




  1. Все передаваемые файлы делятся на главные (в основном html-страницы) и подчинённые (скрипты, изображения, стили и т.д.).

    В идеологии, заложенной в стандарты HTTP-кэширования, все файлы равноправны. Это, конечно, толерантно, но не отвечает современным реалиям.

  2. Неважно, откуда получен подчинённый файл. Важно, что его содержимое удовлетворяет нужды главного.

    В существующей идеологии даже сама аббревиатура URI — Uniform Resource Identifier — предполагает, что идентификатором ресурса является его адрес в сети. Но, увы, для подчинённых файлов это несколько не соответствует действительности.



Перспективы



Обещанный няш-меш



Зная хэш требуемого вспомогательно файла, можно почти смело запрашивать его у кого угодно; основная опасность: если опрашиваемый узел действительно имеет требуемый файл, то он знает его содержимое и, скорее всего, как минимум один URI-адрес, по которому требуемый файл может (или мог) быть получен. Имеем два варианта использования предлагаемой технологии с учётом этой угрозы с целью плавного подхода к няш-меш сети:



Доверенные устройства



Например, в офисе работают программисты, ЭВМ которых объединены в локальную сеть. Программист Вася приходит рано утром, открывает гитхаб и получает в кэш стили от нового дизайна, который выкатили ночью (у нас — ночь, там — день). Когда в офис приходит программист Петя и тоже загружает html-код гитхабовской странички, его ЭВМ спрашивает у всех ЭВМ в сети: "А нет ли у вас файла с таким-то хэшем?" "Лови!" — отвечает Васина ЭВМ, экономя тем самым трафик.

Потом наступает перерыв, Вася и Петя лезут смотреть котиков и пересылают фотографии друг другу. Но каждый котик скачивается через канал офиса только один раз...



Анонимный разделяемый кэш



Аня едет в трамвае с работы и читает новости… например, на Яндекс-Новостях. Встретив очередной тэг , Анин телефон со случайного MAC-адреса спрашивает всех, кого видит: "Ребят, а ни у кого нет файла с таким-то хэшем?". Если ответ получен в разумное время — профит, Аня сэкономила недешёвый мобильный трафик. Важно почаще менять MAC-адрес на случайный да не "орать", когда в поле видимости слишком мало узлов и спрашивающего можно идентифицировать визуально.

Разумность времени ответа определяется исходя из стоимости трафика.



Дальнейший переход к няш-мешу



Фотография в соцсети может быть представлена как блоб, содержаший хэш и адрес собственно изображения (возможно, в нескольких различных размерах), а также список комментариев и лайков. Этот блоб тоже можно рассматривать как вспомогательный файл, кэшировать и передавать друг другу.

Более того, альбом фотографий тоже легко превращается в блоб: список хэшей изображений + список хэшей блобов-фотографий (первое нужно, чтобы при добавлении лайка/комментария показывать фотографии сразу, а метаинформацию — по мере её получения).

Останется только реализовать электронную подпись и поля вида "замещает блоб такой-то" — и готова няш-меш-социалочка.



Компактизация хэша



В идеале при записи хэша следует использовать не шестнадцатеричную систему счисления, а систему с бОльшим основанием (раз уж мы взялись экономить трафик). Ещё одна идея — атрибут magnet, содержащий magnet-ссылку. Дёшево, сердито, стандартизировано и позволяет указывать также несколько классических адресов источников, что бывает немаловажно в случае ковровых блокировок и в случаях, когда браузеру известно, что трафик к различным серверам тарифицируется по-разному.



Поведение при несовпадении



Возможна ситуация, когда хэш полученного файла не совпал с требуемым. В таком случае разумно бы было предусмотреть мета-тэги, указывающие браузеру, следует ли такой файл использовать (по умолчанию — нет) и следует ли сообщить об инциденте серверу (по умолчанию — нет).



Файлы-альтернативы



В некоторых случаях можно использовать любой из нескольких файлов с разными хэшами. Например, на сайте используется минифицированная jQuery, но если в кэше браузера есть неминифицированная — что мешает использовать её?



Превентивное кэширование



Многие устройства работают в двух режимах: когда интернет условно-безлимитен (например, мобильный телефон в вай-фай сети) и когда интернет ограничен (лимит по трафику или узкий канал). Браузер или расширение к нему может, пользуясь безлимитным подключением, заранее скачивать популярные библиотеки (наподобие jQuery и плагинов к ней), также по мере необходимости их обновлять. Это ли не мечта многих, чтобы jQuery была включена в браузер?



Заключение



Выдвигаемое рацпредложение актуально, так как борьба за оптимизацию загрузки сайтов идёт полным ходом. Более всего выиграют малые и средние сайты за счёт разделяемых библиотек (и, может быть, некоторых часто используемых изображений) в кэше. Уменьшится потребление трафика мобильными устройствами, что важно с учётом ограниченной пропускной способности каналов сотового интернета. Крупные сайты также могут уменьшить нагрузку на свои серверы в случае, если будут внедрены mesh-технологии.

Таким образом, поддержка предлагаемой технологии выгодна и вебмастерам, чьи сайты будут грузиться быстрее, и производителям браузеров, которые тоже будут быстрее отображать страницы, и провайдерам, у которых уменьшится потребление полосы (пусть и не столь значительно, но от провайдеров активных действий и не требуется).



P.S.

Мне было бы очень приятно услышать мнение Mithgol, Shpankov и BarakAdama.



P.P.S.

Хабр всезнающий, в какое спортлото отправлять рацпредложение?


Original source: habrahabr.ru (comments, light).

https://habrahabr.ru/post/305898/

Комментарии (0)КомментироватьВ цитатник или сообщество
Планула

Cимволы (текстовые значки) HTML. СОЛНЕЧНАЯ СИСТЕМА

Понедельник, 18 Июля 2016 г. 15:46 (ссылка)





Cимволы (текстовые значки) HTML.


















































1343830455-1693435-1-www.hqtexture.com (700x137, 85Kb)


СОЛНЕЧНАЯ СИСТЕМА

З В Е З Д А

С
О
Л
Н
Ц
Е

символ

числовой код

клавиша Alt +число

описание

&#9728; 9728 Закрашенное солнце с лучами
&#9788; 9788 Незакрашенное солнце с лучами
&#9737; 9737 Солнце
&#9925; 9925; Солнце за облаками





Cимволы (текстовые значки) HTML,
которые не видит мой браузер




















































Символ


картинка в PNG
(cимвол)


числовой код


юникод


описание

🌞 Солнце-с-лицом (50x50, 6Kb) &#127774; U+1F31E солнце с лицом
🌣 белое-солнце (50x50, 5Kb) &#127779; U+1F323 Белое солнце
🌥 белое-солнце-за-тучами (90x50, 7Kb) &#127781; U+1F325 Белое солнце за тучами
🌤 белое-солнце-и-небольшое-облочко (84x50, 7Kb) &#127780; U+1F324 Белое солнце и небольшое облачко
🌦 белое-солнце-за-тучами-с-дождём (50x48, 5Kb) &#127782; U+1F326 Белое солнце за тучами с дождём




Cимволы (текстовые значки) HTML похожие на солнце




























Символ


числовой код


юникод


описание

&#9881; U+2699
Шестерня
&#10050; U+2742 Восьмиконечная звезда с незакрашенным центром внутри закрашенного круга












Далее

Метки:   Комментарии (0)КомментироватьВ цитатник или сообщество
rss_rss_hh_new

[Перевод] Как “думать на AngularJS”, если вы используете jQuery

Пятница, 15 Июля 2016 г. 18:12 (ссылка)

1.Не изменяйте конструкцию страницы с помощью DOM манипуляций.

В jQuery вы верстаете страницу, а затем делаете ее динамической. Это потому, что jQuery был предназначен для проектирования системы улучшения характеристик и невероятно вырос из этой простой предпосылки.

Но на angularjs, вы должны начать с нуля свою задумку. Вместо того, чтобы начать думать «у меня часть DOM и я хочу сделать X», вы должны начать с того, что вы хотите достичь, затем думать о разработке приложения, и, наконец, интересоваться разработкой представления.



2.Не дополняйте jQuery c AngularJS.

Аналогично, не начинайте с идеи, что jQuery делает X, Y, и Z, так я буду только добавлять angularjs в главенствующей роли для моделей и контроллеров. Это действительно заманчиво когда вы только начинаете, поэтому я всегда рекомендую, чтобы новые разработчики angularjs не использовали jQuery для всего, по крайней мере, пока они не привыкнут делать вещи «угловым путем».



Я видел много разработчиков, здесь и в рассылке, которые создают сложные решения с плагинами jQuery длинной в 150-200 строк кода, которые склеивают в angularjs с запутанными коллекциями каллбэков и $apply, но они, в конечном счете, заставляют код работать!

Проблема в том, что в большинстве случаев jQuery плагин можно переписать на angularjs, в части кода, где все вдруг становится понятным и простым.



Суть такова: когда разрабатываете, сначала «думайте на angularjs»; если вы не можете придумать решение, спросите у коллег, если после всего, вы не найдете решения, то не стесняйтесь обратиться за помощью к jQuery. Но не позволяйте jQuery стать костылем, или вы не мастер в angularjs.



3.Всегда думайте с точки зрения архитектуры.

Помните, что одностраничные приложения — это приложения. Они — не веб-страницы. Поэтому мы должны думать одновременно как серверный разработчик и как клиентский разработчик. Мы должны думать о том, как разделить наше приложение на отдельные, расширяемые, тестируемые компоненты.

Как ты это делаешь? Как вы «думаете на angularjs»? — вот некоторые общие принципы, противопоставленные jQuery.

Представление – это протокол.

В jQuery мы программно изменяем представление. Мы могли бы создать выпадающее меню с помощью ul так:




В jQuery, в нашей логике приложения, мы хотели активировать его с чем-то вроде:

$('.main-menu').dropdownMenu();


Когда мы просто смотрим на представление, не сразу видно его роль в приложении. Для небольших приложений это нормально. Но для нетривиальных приложений код быстро становится запутанным и его трудно поддерживать.

На angularjs наше объявление ul будет выглядеть следующим образом:


    ...



Этот код делает то же самое, но в angularjs версии понятно, что должно произойти в шаблоне. Всякий раз, когда новый член команды разработчиков приходит на борт, он может посмотреть на это и быстро понять назначение директивы dropdownMenu по ее названию. Ее представление нам сказало, что должно было случиться. Намного чище.



Новые разработчики angularjs часто задают такой вопрос: как мне найти все ссылки на конкретный вид и добавить директиву на них? Разработчик всегда изумлен, когда мы отвечаем: никак. Но почему вы не сделаете это, как половину-jQuery и половину-angularjs — это не сулит ничего хорошего.



Проблема здесь в том, что разработчик пытается «сделать на jQuery» в контексте angularjs. Это никогда не будет работать хорошо. Вне директивы (подробнее об этом ниже), вы никогда, никогда, никогда не измените DOM. И директивы применяются в этом представлении, цель ясна.



Помните: не проектируйте, а потом верстайте. Необходимо разработать, а потом проектировать.

Привязка данных

Это, безусловно, одна из самых удивительных особенностей angularjs, которая удаляет много DOM манипуляций, которые нужно было бы сделать, я уже упоминал об этом в предыдущем разделе. В angularjs автоматически обновляется ваше представление, так что вам не придется делать это! В jQuery мы реагируем на события и обновляем контент. Что-то вроде:

$.ajax({
url: '/myEndpoint.json',
success: function ( data, status ) {
$('ul#log').append('
  • Data Received!
  • ');
    }
    });


    В коде это выглядит так:





    Помимо проблем смешивания, мы также имеем те же проблемы, означающие намерение, которое я упоминал ранее. Но главное, нам пришлось вручную ссылаться и обновлять узел DOM. И если мы хотим удалить запись из журнала, надо кодить через DOM для этого тоже. Как мы тестируем логику только через DOM? А что, если мы хотим изменить представление?

    Это немного грязно и мелочно, на AngularJS мы можем сделать это:

    $http( '/myEndpoint.json' ).then( function ( response ) {
    $scope.log.push( { msg: 'Data Received!' } );
    });


    И наше представление станет таким:


    • {{ entry.msg }}




    Но, впрочем, код может быть и таким:



    {{ entry.msg }}




    И теперь вместо того, чтобы использовать неупорядоченный список, мы используем контейнеры. И нам никогда не придется менять код контроллера! Но что еще более важно, независимо от того, где и как лог обновляется, представление изменится. Автоматически. Аккуратно!



    Хотя я не показал это здесь, привязка данных является двунаправленной. Так эти сообщения лога могут также быть доступны для редактирования в представлении, просто делаю это:




    И будет много радости.

    Отдельные модели уровня.

    В jQuery, DOM — вроде как модель. Но на angularjs, у нас есть различные уровни модели, которыми мы можем управлять в любом случае, как мы хотим, совершенно независимо от представления. Это помогает вышеуказанной привязке данных, поддерживает разделение обязанностей и вводит гораздо большую тестируемость. Другие ответы упомянули этот момент, поэтому закончим разговор об этом.

    Разделение обязанностей.

    И все вышеперечисленное объедняется в всеобщей теме: держите ваши обязанности разделенными. Ваше представление действует как протокол о том, что должно произойти (по большей части); модель представляет ваши данные, у вас есть слой сервиса для выполнения многоразовых заданий, вы делаете DOM манипуляции и увеличиваете ваше представление директивами; и склеиваете все это вместе с контроллерами. Это также упоминалось в других ответах, и единственное, что я хотел бы добавить, касается тестирования, о котором я расскажу в другом разделе.

    Внедрение зависимости.

    Внедрение зависимости (di) поможет нам с разделением обязанностей. Если вы пришли из серверных языков (из java в PHP) вы, наверное, уже знакомы с этим понятием, но если вы на стороне клиента, пришли с jQuery, это понятие может показаться глупым и лишним. Но это не так. :-)

    С широкой точки зрения, di означает, что вы можете объявить компоненты очень свободно и потом просто попросите его экземпляр, и он будет предоставлен. Вы не должны знать о порядке загрузки, или о местоположении файлов, или что-нибудь подобное. Питание может не сразу быть видно, но я приведу только один (общий) пример: тестирование.

    Допустим, в нашем приложении, мы требуем службу, которая реализует серверные хранилища через RESTAPI и, в зависимости от состояния приложения, и локального хранилища.



    При выполнении тестов на контроллеры мы не хотим общаться с сервером — мы тестируем контроллер в конце. Мы можем просто добавить макет сервиса с таким же названием, как наш первоначальный компонент, и инжектор будет гарантировать, что контроллер получает подделку автоматически — контроллер и не заметит разницы.



    Говоря о тестировании…



    4.Разработка через тестирование – всегда.

    Это действительно часть 3 раздела по архитектуре, а это так важно, что я ставлю его во главе своего раздела.



    Из всего множества jQuery плагинов, которые вы видели, использовали, или написали, сколько из них имели сопутствующие тесты? Не очень много, потому что jQuery не очень склонна к этому. Но angularjs склонен.



    В jQuery, единственный способ для теста — это создать самостоятельно образец/демо-страницу, чтобы показать что наши тесты могут выполнять манипуляции DOM. Значит, мы должны разработать компоненты по отдельности, а затем интегрировать их в наше приложение. Как неудобно! Так много времени, когда разрабатываем с jQuery, мы выбираем итеративный путь, а не тестирование. И кто может обвинить нас?



    Но ведь у нас есть разделение обязанностей, мы можем сделать тестирование итерационно на angularjs! Например, скажем, мы хотим с помощью супер-простой директивы указывать в меню на наш нынешний маршрут. Мы можем заявить, что мы хотим, на наш взгляд:

    Hello


    Хорошо, теперь мы можем написать тест:

    it( 'should add "active" when the route changes', inject(function() {
    var elm = $compile( 'Hello' )( $scope );
    $location.path('/not-matching');
    expect( elm.hasClass('active') ).toBeFalsey();
    $location.path( '/hello' );
    expect( elm.hasClass('active') ).toBeTruthy();
    }));


    Мы запускаем наш тест и убеждаемся, что это не удается. Так что теперь мы можем написать наши директивы:

    .directive( 'whenActive', function ( $location ) {
    return {
    scope: true,
    link: function ( scope, element, attrs ) {
    scope.$on( '$routeChangeSuccess', function () {
    if ( $location.path() == element.attr( 'href' ) ) {
    element.addClass( 'active' );
    }
    else {
    element.removeClass( 'active' );
    }
    });
    }
    };
    });


    Теперь наш тест проходит, и наше меню выполняется позапросу. Наша разработка как итерационная и тестируемая вместе.



    5.Теоретически, директивы не упакованы jQuery.

    Вы часто будете слышать «только манипуляции DOM в директиве». Это необходимость. Относитесь к ней с уважением!

    Но давайте углубимся немного глубже…



    Некоторые директивы просто украшают то, что уже в представлении (думаю, ngClass) и поэтому иногда делаем манипуляций с DOM, а потом, в основном, выполняем. Но если директива как «виджет» и есть шаблон, необходимо также соблюдать разделение обязанностей. То есть, шаблон тоже должен оставаться в значительной степени независимым от его реализации в ссылке и функции контроллера.



    Angularjs поставляется с полным набором инструментов, чтобы сделать это очень легко; с ngClass можно динамически обновлять классы; ngBind позволяет проводить двустороннюю привязку данных; ngShow и ngHide программно показать или скрыть элемент; и многое другое, в том числе то, что мы сочиняем сами. Другими словами, мы можем сделать все преобразования, без манипуляций с DOM. Чем меньше манипуляций с DOM, тем легче директивы для теста, тем легче их стиль, тем легче они будут меняться в будущем, и более многоразовый и распространять их.



    Я вижу много новых разработчиков angularjs, использующих директивы как место, чтобы бросить кучу jQuery. Другими словами, они думают, что «раз я не могу манипулировать DOM в контроллере, я возьму этот код поставлю его в директиву». Хотя это конечно намного лучше, часто все равно неправильно.



    Логгер мы запрограммировали в главе 3. Даже если мы предположим, что в директиве, мы все же хотим сделать «угловой путь». Он по-прежнему не принимает никаких манипуляций с DOM! Есть много моментов, когда необходимы манипуляции с DOM, но это намного реже, чем вы думаете! Прежде чем делать манипуляции с DOM в вашем приложении, спросите себя, вам действительно нужно это? Может быть способ лучше.



    Вот быстрый пример, который показывает картину, которую я вижу чаще всего. Мы хотим сделать кнопку переключаемой. (Примечание: этот пример немного надуманный и нужно немного подробнее представлять более сложные случаи, которые решаются точно таким же способом.)

    .directive( 'myDirective', function () {
    return {
    template: 'Toggle me!',
    link: function ( scope, element, attrs ) {
    var on = false;
    $(element).click( function () {
    if ( on ) {
    $(element).removeClass( 'active' );
    }
    else {
    $(element).addClass( 'active' );
    }
    on = !on;
    });
    }
    };
    });


    Здесь есть несколько неправильных моментов.

    Во-первых, jQuery и не надо было. Мы ничего не делали здесь, чтобы был нужен jQuery во всем!

    Во-вторых, даже если у нас уже есть jQuery на странице, нет никаких причин, чтобы использовать его здесь, мы можем просто использовать angular.element и компонент по-прежнему будет работать при перетаскивании в проект, который не имеет jQuery.

    В-третьих, даже если предположить, что jQuery был необходим для работы этой директивы, jqLite (angular.element) всегда будет использовать jQuery, если он был загружен! Поэтому мы не должны использовать $ — мы можем просто использовать angular.element.

    В-четвертых, тесно связанный с третьим, элементы jqLite не нужно было оборачивать в $ — элемент, который передается в функцию по ссылке, может быть уже элемент с jQuery!

    И в-пятых, момент, который мы уже упоминали в предыдущих разделах, почему мы смешиваем элементы шаблона в нашей логике?

    Эта директива может быть переписана (даже для очень сложных случаев!) гораздо проще, вот так:

    .directive( 'myDirective', function () {
    return {
    scope: true,
    template: 'Toggle me!',
    link: function ( scope, element, attrs ) {
    scope.on = false;
    scope.toggle = function () {
    scope.on = !scope.on;
    };
    }
    };
    });


    Опять же, наполнение шаблона, так вы (или ваши пользователи) можете легко поменять его на то, что соответствует любому нужному стилю, а логика никогда не должна быть задета. Повторное использование — бум!



    И тогда все эти прочие преимущества, как тестирование — это просто! Независимо от того, что в шаблоне, внутреннего API директивы не касаются, так что рефакторинг — это легко. Вы можете изменить шаблон так, как вы хотите, не прикасаясь к директиве. И неважно, что вы измените, ваши тесты пока проходят.



    Так что директивы — не просто коллекции jQuery функций, какие они? Директивы –это расширения HTML-кода. Если HTML не делает что-то нужное, вы напишите директиву, чтобы она сделала это для вас, а затем будете использовать её так, как будто это было частью HTML.



    Иначе говоря, если angularjs не сделает что-нибудь из коробки, думаю, команда бы выполнила это с ngClick и ngClass вместе.



    Итог.

    Даже не используйте jQuery. Даже не включайте его. Оно будет тормозить вас. И когда вы приходите к проблеме, если вы думаете, что знаете, как решить проблему в jQuery, прежде чем тянуться за $, попробуйте подумать, как это сделать в рамках в в angularjs. Если Вы не знаете — спросите! 19 раз или 20, будет лучше, если вы сделаете приложение без jQuery, ведь оно, в результате, принесет больше работы для вас.
    Original source: habrahabr.ru (comments, light).

    https://habrahabr.ru/post/305734/

    Метки:   Комментарии (0)КомментироватьВ цитатник или сообщество
    милена70

    Htmlbook Рецепты CSS

    Пятница, 16 Июля 2016 г. 00:59 (ссылка)



     







    Вёрстка




    Изображения




    Добавление картинок




    Рамка вокруг изображений




    Читать далее...
    Метки:   Комментарии (0)КомментироватьВ цитатник или сообщество
    Ралиона

    HTML для чайников

    Четверг, 14 Июля 2016 г. 19:41 (ссылка)
    site-do.ru/html/

    Метки:   Комментарии (0)КомментироватьВ цитатник или сообщество
    rss_rss_hh_new

    [Перевод] Сражаясь с БЭМ: 10 основных ошибок и как их избежать

    Вторник, 13 Июля 2016 г. 02:19 (ссылка)

    Не важно, узнали ли вы о БЭМ только сейчас, или следите за ним с самого начала, вы, возможно, уже оценили столь полезную методологию. Если вы не знаете, что такое БЭМ, я рекомендую прочитать вам об этом на сайте БЭМ перед тем, как продолжить чтение этой статьи, потому что я буду использовать термины, которые предполагают базовое понимание этой CSS методологии.

    image

    Эта статья нацелена на людей, которые уже используют БЭМ и желают использовать его более эффективно, а также на тех, кто хочет узнать о нем больше.



    Сейчас у меня нет никаких сомнений о способе называть вещи. Единственное, что отталкивало меня на протяжении длительного времени, — это уродливый синтаксис. Дизайнер внутри меня не хотел загромождать мою шикарную разметку ужасными двойными подчеркиваниями и дефисами.



    Разработчик во мне смотрел на это прагматично. И, в конечном счете, модульный способ построения пользовательского интерфейса перевесил правую сторону моего мозга, которая утверждала: "Но он недостаточно хорош!". В таких случаях, я предпочитаю функциональность над внешней формой. В любом случае, хватит пустых разговоров. Представляю вашему вниманию 10 проблем, с которыми я поборолся и несколько советов, как разрешить их.



    1. "Что делать с "внучатыми" селекторами (и не только)?"



    Для ясности, внучатый селектор используется, когда вам нужно обратиться к элементу, вложенному на два уровня. Эти плохие мальчики — проклятье моей жизни, и я уверен, что это одна из причин, по которой у людей появляется немедленное отвращение к БЭМ. Приведу пример:







    Title text here






    description

    Lorem ipsum dolor sit amet, consectetur


    Adipiscing elit.
    Pellentesque amet






    Как вы могли заметить, имена могут быстро выйти из под контроля и, чем больше вложенности, тем безобразнее становится имя класса элемента. Я использовал короткий блок с названием c-card и короткие имена body, text, link, но попробуйте представить, что получится, если первоначальный блочный элемент будет назван c-drop-down-menu.



    Я считаю, что двойное нижнее подчеркивание должно появляться только однажды, в имени селектора. БЭМ расшифровывается как Блок_Элемент--Модификатор, а не Блок__Элемент__Элемент--Модификатор. Также избегайте многоуровневого наименования элементов. Если у вас получаются уровни пра-пра-пра-правнуков, то, вероятно, вам стоит пересмотреть структуру компонентов.



    Именование БЭМ не привязано строго к DOM, так что не имеет значения на скольких уровнях находится вложенный элемент. Соглашение об именах в первую очередь помогает вам увидеть отношения с блоком на верхнем уровне — в нашем случае, c-card.



    Как бы я рассматривал один и тот же карточный компонент:





    Title text here






    description

    Lorem ipsum dolor sit amet, consectetur


    Adipiscing elit.
    Pellentesque amet






    Это значит, что все вложенные элементы будут затронуты только карточным блоком. Также, мы бы могли переместить текст и изображения в c-card__header или даже внести новый элемент c-card__footer при этом не ломая семантической структуры.



    2. "Какие наименования использовать?"



    К этому времени вы возможно заметили использование c- в моих примерах. Этот префикс расшифровывается как "компонент (component)" и лежит в основе всех имен моих БЭМ классов. Идея позаимствована из техники наименований Гарри Роберта, которая улучшает читаемость кода.



    Система, которую я принял, и множество префиксов, которые будут встречаться в примерах в этой статье:












































    Тип Префикс Примеры Описание
    Компонент (Component) c- c-card, c-checklist Формируют основу приложения и содержат всю косметику для отдельных компонентов.
    Модуль макета (Layout module) l- l-grid, l-container У этих модулей нет никакой косметики, используются только для позиционирования компонентов c- и для построения макета приложения.
    Помощники (Helpers) h- h-show, h-hide Эти классы имеют одну функцию, часто используют !important для повышения их специфичности. (В основном используются для позиционирования или видимости.)
    Состояния (States) is-, has- is-visible, has-loaded Показывают различные состояния, которые могут быть у компонентов c-. Более детальное описание можно найти ниже в 6 проблеме.
    JavaScript хуки js- js-tab-switcher Они указывают на то, что поведение JavaScript привязано к компоненту. Стили с ними не ассоциируются; используются только для облегчения манипуляций со скриптами.


    Я обнаружил, что подобные имена невероятно улучшили читаемость моего кода. Даже если у меня не получится подсадить вас на БЭМ, то этот прием определенно стоит запомнить.



    Вы бы могли также взять и другие префиксы, такие как qa- для тестов на качество (quality-assurance), ss- для различных хуков на стороне сервера (server-side) и т.д. Но список выше — уже хорошее начало, и ввести новые имена вы можете после того, как освоитесь с этой техникой.



    Вы увидите хороший пример использования этого стиля наименований в следующей проблеме.



    3. "Как мне называть врапперы (wrappers)?"



    Некоторые компоненты требуют родительского враппера (или контейнера), который задает макет дочерним элементам. В этих случаях, я всегда пытаюсь абстрагировать макет в модуль макета, такой как l-grid и добавлять каждый компонент как содержимое l-grid__item.



    В нашем карточном примере, если бы мы хотели расположить список из четырех c-cardов, я бы использовал следующую разметку:







    • […]


      […]






    • […]


      […]






    • […]


      […]






    • […]


      […]





    Теперь у вас должно быть твердое представление о том, как расположение модулей и имена компонентов должны сочетаться вместе.



    Не бойтесь использовать немного более продвинутой разметки, дабы потом у вас не было головной боли. Никому не станет лучше от того, что вы сократите пару

    тегов!

    В некоторых ситуациях, это не возможно. Если, например, ваша сетка не собирается вас слушаться, или вы просто хотите какое-нибудь имя со смыслом для вашего родительского элемента, то что вам делать? Я, как правило, выбираю слово container или list, в зависимости от ситуации. Применяя это к нашему карточному примеру, я бы мог использовать

    […]
    или
      […]
    , в зависимости от используемого случая. Главное — соответствовать вашему соглашению об именовании.

    4. "Кросскомпонентные… Компоненты?"



    Еще одна часто встречающаяся проблема — компоненты, чьи стили или позиционирование затрагиваются родительским контейнером. Различные решения этой проблемы детально описаны у Simurai. Я вам расскажу только о том подходе, который я считаю самым эффективным.



    Вкратце, давайте предположим, что мы хотим добавить c-button в наш card__body из предыдущего примера. Эта кнопка уже является его компонентом и оформлена так:





    Если у вас нет никаких различий между обычным компонентом кнопки, то тогда проблем нет, мы просто переместим ее вот так:





    Title text here






    Lorem ipsum dolor sit amet, consectetur


    Adipiscing elit. Pellentesque.









    Однако, что происходит, когда присутствуют небольшие различия в стилях — например, мы хотим ее немного уменьшить, закруглить углы, но только тогда, когда она является частью компонента c-card?



    Кросскомпонентный класс показался мне наиболее надежным решением:





    Title text here






    Lorem ipsum dolor sit amet, consectetur


    Adipiscing elit. Pellentesque.








    Это то, что известно на сайте БЭМ, как "микс (mix)". Однако, я изменил свое отношение к этому подходу, следуя некоторым замечательным комментариям от Esteban Lussich.



    В примере выше, класс c-card__c-button пытается изменить одно или несколько существующих свойств c-button, но зависит от источника вызова (или даже от специфики), для успешного применения. Класс c-card__c-button будет работать только в том случае, если он определен после блока c-button, который может быстро выйти из под контроля, если вы будете строить больше таких кросскомпонентов. (Полагаться на !important, конечно, можно, но я бы не стал!).



    Оформление по настоящему модульного UI элемента должно быть полностью независимо от родительского контейнера — оно должно выглядеть одинаково независимо от того, где вы его расположите. Добавление класса из другого компонента для задания стиля, как это делает способ с "миксами", нарушает открытые/закрытые принципы компонентно-ориентированного дизайна — т.е., не должно быть никакой зависимости от другого модуля для эстетики.



    Лучше всего, это использовать модификатор для этих небольших косметических различий, потому что вы легко сможете использовать их снова по мере роста вашего проекта.





    Даже если вы не используете эти дополнительные классы снова, по крайней мере, вы не будете привязаны к родительскому контейнеру или к исходному порядку для применения изменений.



    Другой способ — пойти к вашему дизайнеру и сказать ему, что кнопки должны быть совместимы с остальными, и избегать этой проблемы вообще.



    5. "Модификатор или новый компонент?"



    Одна из самых больших проблем — решить, где компонент заканчивается, и начинается новый. В примере с c-card, вы бы могли создать другой компонент, названный c-panel с очень похожими атрибутами стилей, но с очень заметными различиями.



    Но что определяет необходимость использования двух компонентов, c-panel и c-card, или простого модификатора для c-card, который применяет уникальные стили.



    Можно легко переполнить проект модулями и сделать все в виде компонентов. Я рекомендую начать с модификаторов, если вам покажется, что управление каким-либо компонентным CSS файлом становится слишком сложным, то, возможно, наступило время разделить некоторые модификаторы. Хороший показатель, когда вам приходится сбрасывать все у блока CSS для стилизации нового модификатора — это, как по мне, самое время для создания нового компонента.



    Лучше всего, если вы работаете в команде других разработчиков или дизайнеров, узнать их мнение. Соберите их на несколько минут и обсудите с ними. Несмотря на то, что этот ответ скорее выглядит как отмазка, для больших приложений очень важно понимать, какие модули доступны и что собой представляет компонент.



    6. "Как управлять состояниями?"



    Это довольно распространенная проблема, особенно, когда вы стилизуете компонент в активном или открытом состоянии. Давайте скажем, что наши карточки пребывают в активном состоянии; так вот, когда мы нажимаем на них, они выделяются красивой обводкой. Что насчет названия этого класса?



    У вас два варианта: или использовать хук автономного состояния, или использовать БЭМ-подобное именование модификатора на уровне компонента:





    […]




    […]


    Не смотря на то, что мне нравится идея использовать имя БЭМ для единообразия, преимущество автономного класса в том, что он позволяет использовать JavaScript для применения универсальных хуков состояния к любому компоненту. Когда вам приходится применять определенный класс состояния, основанный на модификаторе с помощью скрипта, это становится более проблематичным. Это, конечно, возможно, но требует написания дополнительного JavaScript кода.



    Имеет смысл придерживаться стандартного набора хуков состояния. Крис Пирс собрал хороший список, который я рекомендую посмотреть.



    7. "Когда лучше не добавлять новый класс к элементу"



    Я могу понять людей, которые перегружены огромным числом классов, требуемых для построения сложной части пользовательского интерфейса, особенно, если они не присваивали класс каждому тегу.



    Обычно я прикрепляю классы ко всему, что должно быть стилизовано, по разному, в контексте компонента. Я часто оставляю теги p без класса, если компонент не требует, чтобы они выглядели по-особенному в этом контексте.



    Согласен, это будет обозначать то, что ваша разметка будет содержать множество классов. Но, в конечном счете, ваши компоненты будут способны жить независимо и смогут перемещаться без побочных эффектов.



    Ввиду глобального характера CSS, присвоение класса ко всему дает нам полный контроль над рендером. Первоначальный дискомфорт стоит преимуществ полностью модульной системы.



    8. "Как вкладывать компоненты?"



    Допустим. что мы хотим отобразить чек-лист в нашем компоненте c-card. Пример того, как не стоит это делать:





    Title text here





    I would like to buy:




















    У нас тут есть несколько проблем. Первая — двухуровневый селектор, о котором мы узнали в первом разделе. Второе — все стили, примененные к c-card__checklist__item, относятся только к этому конкретному случаю, из-за чего их нельзя использовать снова.



    Я предпочитаю разбить список на модуль разметки, предметы чек-листа на их собственные компоненты, что позволяет использовать их самостоятельно в другом месте. Это позволяет вернуться нашему префиксу l- к игре:





    Title text here





    I would like to buy:






























    Это спасает вас от необходимости повторять эти стили, а также значит, что мы можем использовать l-list и c-checkbox в других местах нашего приложения. Это требует немного больше разметки, но взамен мы получаем читаемость, инкапсуляцию и возможность повторного использования. Возможно, вы заметили, что это — основные темы!



    9. "Не появятся ли у компонентов миллион классов?"



    Некоторые считают, что множество классов на элемент — плохо, и, безусловно, можно добавить --модификаторы. Лично мне это не кажется проблемой, потому что это делает код более читаемым, и я точно знаю, что он должен делать.



    Пример из четырех классов, с помощью которых стилизуется кнопка:





    Я понимаю, что этот синтаксис немного уродлив, но он понятный.



    Однако, если от этого у вас начинает болеть голова, вы можете взглянуть на технику Сергея Зароуски. Фактически, мы будем использовать .className [class^="className"], [class*=" className"] в таблице стилей для имитации дополнительной функциональности в CSS. Если этот синтаксис кажется вам знакомым, то это потому, что Icomoon использует похожий способ для управления селекторами иконок.



    С этой техникой, ваш вывод может выглядеть примерно так:





    Я не знаю, намного ли снижение производительности при использовании class^= и class*= больше, чем при использовании индивидуальных классов, но в теории, это классная альтернатива. Для себя мне хватает варианта с несколькими классами, но мне кажется, что этот способ определенно заслуживает упоминания для тех, кто предпочитает альтернативу.



    10. "Можем ли мы изменить реакцию типа компонента?"



    Эту проблему поставил мне Arie Thulank, и к которой я пытался найти 100% решение.



    Примером может быть выпадающее меню, которое превращается в набор вкладок в заданный момент, или закадровая боковая навигация, которая превращается в панель меню.



    По сути, у одного компонента могут быть два разных состояния, продиктованных медиа-запросом.



    Для этих двух примеров я склоняюсь к тому, чтобы просто сделать компонент c-navigation, так как изменение в заданный момент — это то, что он делает. Но это заставило меня задуматься, что на счет списков изображений, которые превращаются в карусель на больших экранах? Это проблемный случай для меня, и, так как он хорошо документирован и прокомментирован, я думаю, что в идеале стоит создать отдельный одноразовый компонент для этого типа интерфейса, с понятным названием (таким как c-image-list-to-carousel).



    Гарри Робертс упоминал об отзывчивых префиксах, одном из способов управлять этим. Его подход предназначен больше для изменений в макете и написания стилей, а не сдвигая все компоненты, но не вижу причин, по которым мы не можем применить эту технику здесь. Таким образом, вы можете назвать классы так:





      В дальнейшем это будет жить в ваших медиа-запросах для соответствующих размеров экрана.

      Совет: Вам придется отключать @ с помощью обратной косой черты, как тут:



      .c-image-list\@small-screen {
      /* стили тут */
      }


      У меня не было причин для создания таких компонентов, но этот способ выглядит очень дружелюбным по отношению к разработчику. Другому человеку должно быть достаточно просто понять ваши намерения. Но я не пропагандирую такие имена, как small-screen и large-screen — они использованы только для улучшения читаемости.



      Заключение



      БЭМ оказался спасением для меня в моем стремлении к созданию модульных приложений компонентным способом. Я использую его уже почти 3 года, и проблемы, перечисленные выше, были камнями преткновения на моем пути. Я надеюсь, что эта статья покажется вам полезной, и, если вы еще не пользуетесь БЭМ, я очень сильно рекомендую вам начать это делать.



      Обо всех ошибках (грамматических, лексических и т.д.) пишите в комментарии, буду рад их исправить. Спасибо за внимание


      Original source: habrahabr.ru (comments, light).

      https://habrahabr.ru/post/305548/

      Метки:   Комментарии (0)КомментироватьВ цитатник или сообщество

      Следующие 30  »

      <html - Самое интересное в блогах

      Страницы: [1] 2 3 ..
      .. 10

      LiveInternet.Ru Ссылки: на главную|почта|знакомства|одноклассники|фото|открытки|тесты|чат
      О проекте: помощь|контакты|разместить рекламу|версия для pda