Войти с помощью github

Всем привет!

Хочу нести в массы БЭМ методологию и только bem-core в качестве front-end фреймворка (в основном из-за i-bem). Отсюда вопросы: 1) Есть ли готовые сборки bem-core? Если нет, думаю, собрать bem-core в один JS файлик и распространять как bower-пакетик, периодически синкая с bem-core. 2) Также хочу заменить ymodules на AMD, т.к. ни один пакетный менеджер не имеет поддержки ymodules. Думаю использовать webpack, у него тоже есть поддержка асинхронного инита. Может уже есть такое? 3) Есть ли примеры использования i-bem без enb и вот этого всего? Если нет — буду писать.)

Так получилось, что блок изначально есть на странице, но внутри элемента с display: none. И если блок в этот момент проинициализируется, то он неправильно всё посчитает.

Я решил сделать так:

{
    beforeSetMod: {
            js: {
                inited: function() {
                    if (this.domElem.is(':hidden')) {
                            return false;
                    }
                }
            }
        },
}

а когда внешний элемент меняет свою видимость, то делаю

BEMDOM.init($elem);

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

Возможно я что-то делаю совсем не так и проблему нужно решать по другому?

В руководстве по миграции https://ru.bem.info/libs/bem-core/v2.6.0/migration/#Деструктор написано, что «Вызывать base для того, чтобы у блоков работал базовый деструктор, определенный в i-bemdom, больше не нужно.»

Однако в блоке input в bem-components родительский деструктор вызывается явно. https://github.com/bem/bem-components/blob/v2/desktop.blocks/input/input.js#L49-L57

Вопрос — когда такое делать необходимо?

Всем привет! У меня php сайтик на самописном mvc - фреймворке, сейчас хочу использовать методологию БЭМ для своего представления.

Сделал следующее:

Логинимся на наш сервер ( не локальный)
Перехожу в htdocs cd htdocs Версия git (у меня 2.4.2) git version Версия php (5.5.26) php -v Клонирую на сайт git clone --depth 1 -b php-bem-bh git@github.com:bem/project-stub.git ls-php-bem-bh Иду в эту директорию cd ls-php-bem-bh Чищу от остальных коммитов — опционально rm -rf .git; git init; git add ./; git commit -m "initial" Устанавливаю последнюю версию Node.js Перед установкой необходимо убедиться в наличии libexecinfo. Ставится он так: cd /usr/ports/devel/libexecinfo sudo make install Устанавливаем Node.js cd /usr/ports/www/node sudo make DISABLE_VULNERABILITIES=yes install clean Проверяю, (должно отобразится Hello World) node console.log('Hello World');

Для того, чтобы выйти из интерактивной оболочки, необходимо просто нажать Ctrl + C. Ctrl + C (2 раза) Затем устанавливаю менеджер пакетов npm Перехожу в директорию, в которой находился до перехода в текущую директорию cd Устанавливаю curl -L https://npmjs.org/install.sh | sudo sh Проверяю npm -v

Иду в директорию с проектом cd htdocs/ls-php-bem-bh стягиваю npm и bower зависимости (нужны только для сборки и станка верстальщика) npm install стягиваем bem/bh-php (можно и через composer: composer require bem/bh) git clone --depth 1 https://github.com/bem/bh-php.git ./vendor/bem/bh Собираю проект с помощью ENB:

Конфигурация процесса сборки хранится в файле .enb/make.js. На ее основе ENB подключает все технологии, которые составляют реализацию блоков: шаблоны, зависимости, CSS-правила и JavaScript-функциональность. ./node_modules/.bin/enb make -n смотрим файлы:ls ./desktop.bundles/index/ | grep php Для удобства разработки запускаем сервер: ( переназначаем порт с помощью аргумента –p ) node_modules/.bin/enb server

второй вариант если порт 8080 занят

./node_modules/.bin/enb server -p 3333 На нашем сервере запускаю инструмент для разработки, который при обновлении страницы в браузере будет автоматически пересобирать только ту часть проекта, которую затронули ваши изменения. Результат доступен по ссылке:

http://мой сайт.com:8080/desktop.bundles/index/index.html

или

http://мой сайт.com:3333/desktop.bundles/index/index.html

У меня такие вопросы:

  1. Как написано здесь https://ru.bem.info/forum/175/ В libs должны лежать бибилиотеки, в т.ч. библиотеки (с суффиксом -php) с bh.php шаблонами. Что-то я немогу их найти, где конкретно искать, и что я сделал не так?
  2. В папке desktop.bundles/index тоже ничего не вижу с расширением php
  3. Что мне нужно удалить, какие файлы и с каким расширением создавать?
  4. как мне передавать данные из своих контроллеров, если структура сайта следующая (упрощенный вариант):

index.php /app |----myapplication.php |----/core |----/config |----/controllers |----/helpers |----/filters |----/models |----/view |----------/contetnt |----------/layout ну и соответственно наш Бэм проект /ls-php-bem-bh |------------------/.bem |------------------/.enb |------------------/.git |------------------/common.blocks |------------------/node_modules |------------------/desktop.blocks |------------------/libs |------------------/desktop.bundles |---------------------------------------/.bem |---------------------------------------/index |-----------------------------------------------index.bemjson.js |-----------------------------------------------index.bemhtml.js |-----------------------------------------------index.html

Существует несколько способов подключения bem-библиотек на свой проект.

Здесь я рассмотрю варианты подключения заранее собранных версий, их 4:

  1. Подключить напрямую с CDN Яндекса
  2. Установить собранные библиотеки через bower
  3. Самостоятельно собрать из исходников
  4. Воспользоваться альфа-версией кастомного билдера

Каждый вариант отличается только первым шагом, дальнейшее использование совпадает.

Подключить напрямую с CDN Яндекса

Это самый простой способ. Достаточно подключить необходимые файлы (см. раздел «Состав») в HTML и готово:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>bem-components dist</title>
    <link rel="stylesheet" href="https://yastatic.net/bem-components/latest/desktop/bem-components.css">
</head>
<body class="page page_theme_islands">
    <!-- write your code here -->
    <script src="https://yastatic.net/bem-components/latest/desktop/bem-components.js+bh.js"></script>
</body>
</html>

Более полный вариант базовой HTML-разметки, включающий поддержку IE8 и определение наличия JS в браузере см. в конце поста.

Установить собранные библиотеки через bower

При условии, что bower у вас уже установлен, достаточно выполнить bower i bem/bem-components-dist#v2 (либо bower i bem/bem-core-dist#v2).

Далее просто прописать путь к необходимым файлам в HTML:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>bem-components dist</title>
    <link rel="stylesheet" href="bower_components/bem-components-dist/desktop/bem-components.css">
</head>
<body class="page page_theme_islands">
    <!-- write your code here -->
    <script src="bower_components/bem-components-dist/desktop/bem-components.js+bh.js"></script>
</body>
</html>

Самостоятельно собрать из исходников

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

git clone https://github.com/bem/bem-components.git
cd bem-components
npm i
npm run dist

В результате в корне bem-components появится папка dist со всеми необходимыми файлами.

Подключение не отличается от предыдущего варианта.

Воспользоваться альфа-версией кастомного билдера

Важно! На данный момент билдер не тестируется и в целом работоспособность сервиса никак не гарантируется. Используйте на собственный страх и риск.

В качестве эксперимента поднята веб-морда, позволяющая собрать код только для необходимых на проекте блоков.

Чтобы получить бандлы, нужно отметить нужные блоки. В ответ будут сгенерированы ссылки на скачивание.

Как работать с подключенными библиотеками

Тут снова возникает несколько вариантов.

Общая часть состоит в том, чтобы найти нужные блоки на bem.info.

Допустим, нужен блок select. Среди примеров нужно найти тот, который больше всего подходит.

Далее 3 варианта:

  1. Просто скопировать нужный HTML из примера и поправить его под свои нужды (для этого нужно нажать на HTML в шапке примера). Этот вариант максимально простой, но очевидно, что при обновлении шаблонов в последующих версиях библиотеки апдейт потребует ручного внесения изменений в каждый обновленный блок.
  2. Воспользоваться шаблонизацией на клиенте (dist включает предсобранные шаблоны BEMHTML и BH на выбор).

Для этого вместо готового HTML-кода следует брать из документации с примерами BEMJSON (кнопка рядом). Получится что-то типа:

<!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8">
    <title>bem-components as a library</title>
    <link rel="stylesheet" href="https://yastatic.net/bem-components/latest/desktop/bem-components.css">
</head>
<body class="page page_theme_islands">
<script src="https://yastatic.net/bem-components/latest/desktop/bem-components.js+bemhtml.js"></script>
<script>
modules.require(['i-bem__dom', 'BEMHTML', 'jquery'], function(BEMDOM, BEMHTML, $) {
    var html = BEMHTML.apply({
        block : 'select',
        mods : { mode : 'check', theme : 'islands', size : 'm' },
        name : 'select1',
        val : [2, 3],
        text : 'Программа конференции',
        options : [
            { val : 1, text : 'Доклад' },
            { val : 2, text : 'Мастер-класс' },
            { val : 3, text : 'Круглый стол' }
        ]
    });

    BEMDOM.append($('.page'), html);
});
</script>
</body>
</html>

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

А третий вариант — это выполнять {BEMHTML,BH}.apply() на ноде и отдавать браузеру уже готовый HTML:

var BEMHTML = require('./dist/desktop/bem-components.bemhtml.js').BEMHTML;

BEMHTML.apply({
    block : 'select',
    mods : { mode : 'check', theme : 'islands', size : 'm' },
    name : 'select1',
    val : [2, 3],
    text : 'Программа конференции',
    options : [
        { val : 1, text : 'Доклад' },
        { val : 2, text : 'Мастер-класс' },
        { val : 3, text : 'Круглый стол' }
    ]
}); // вернется HTML-строка

Разумеется, все три варианта можно произвольно комбинировать.

Как еще можно пользоваться dist-ом

Т.к. файлы теперь доступны с CDN, можно использовать их на разнообраных песочницах вроде jsfiddle: https://jsfiddle.net/bmu7bkne/4/ или http://jsfiddle.net/bmu7bkne/

Состав

bem-core

Доступны отдельные наборы файлов для двух платформ:

  • desktop
  • touch

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

И аналогичные dev-версии (с сохранием форматирования и комментариев):

  • bem-core.dev.css
  • bem-core.dev.js
  • bem-core.dev.bemhtml.js
  • bem-core.dev.bh.js
  • bem-core.dev.js+bemhtml.js
  • bem-core.dev.js+bh.js

    bem-components

На данный момент доступны отдельные наборы файлов для трех платформ:

  • desktop
  • touch-pad
  • touch-phone

Однако каких-либо отличий в коде между touch-pad и touch-phone нет, поэтому планируется их объединение.

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

  • bem-components.css # стили
  • bem-components.ie.css # стили для IE8 (подробнее)
  • bem-components.js # JS
  • bem-components.bemhtml.js # BEMHTML-шаблоны
  • bem-components.bh.js # BH-шаблоны
  • bem-components.js+bemhtml.js
  • bem-components.js+bh.js

И аналогичные dev-версии (с сохранием форматирования и комментариев):

  • bem-components.dev.css
  • bem-components.dev.ie.css
  • bem-components.dev.js
  • bem-components.dev.bemhtml.js
  • bem-components.dev.bh.js
  • bem-components.dev.js+bemhtml.js
  • bem-components.dev.js+bh.js

Схема подключения с CDN: //yastatic.net/название-библиотеки/версия/платформа/имя-файла. Например, //yastatic.net/bem-components/latest/desktop/bem-components.dev.js+bh.js.

Полный вариант базовой HTML-разметки

<!DOCTYPE html>
<html class="ua_js_no">
<head>
    <!--[if lt IE 9]><script src="https://yastatic.net/es5-shims/0.0.1/es5-shims.min.js"></script><![endif]-->
    <meta charset="utf-8"/><meta http-equiv="X-UA-Compatible" content="IE=edge"/>
    <title>bem-components dist</title>
    <script>(function(e,c){e[c]=e[c].replace(/(ua_js_)no/g,"$1yes");})(document.documentElement,"className");(function(d,n){d.documentElement.className+=" ua_svg_"+(d[n]&&d[n]("http://www.w3.org/2000/svg","svg").createSVGRect?"yes":"no");})(document,"createElementNS");</script>
    <!--[if gt IE 8]><!--><link rel="stylesheet" href="https://yastatic.net/bem-components/latest/desktop/bem-components.css"/>
    <!--<![endif]--><!--[if lte IE 8]><link rel="stylesheet" href="https://yastatic.net/bem-components/latest/desktop/bem-components.ie.css"/><![endif]-->
</head>
<body class="page page_theme_islands">
<!-- write your code here -->
<script src="https://yastatic.net/bem-components/latest/desktop/bem-components.js+bh.js"></script>
</body>
</html>

Безопасно ли собирать bem-core и bem-components технологиями deps и bemhtml вместо deps-old и bemhtml-old соответственно?

Продолжаю погружение. Давно мучает вопрос, что именно делает enb-magic-platform. Какова его роль в bem-core/bem-components. Должен ли я его хотеть для своей библиотеки.

8 Осел ругается на js файл на любой странице проекта

(function() {

var origDefine = modules.define;

modules.define = function(name, deps, decl) {
    origDefine.apply(modules, arguments);

    name !== 'i-bem__dom_init' && arguments.length > 2 && ~deps.indexOf('i-bem__dom') &&
        modules.define('i-bem__dom_init', [name], function(provide, _, prev) {
            provide(prev);
        });
};

})();

Говорит что объект не поддерживает этот метод на этой строке

name !== 'i-bem__dom_init' && arguments.length > 2 && ~deps.indexOf('i-bem__dom') &&
        modules.define('i-bem__dom_init', [name], function(provide, _, prev)

Что бы это могло бы быть?

В методологии БЭМ главным краеугольным камнем является то что нету наследования. Я начал пробовать собирать БЭМ, с руковоства -> Собираем статическую страницу на БЭМ Сделав пункт - "Описание страницы в BEMJSON-файле" страничка собралась, запустилась по адресу - http://localhost:8080/desktop.bundles/hello/hello.html Здорово! =) Я открыл инспектор кода, и увидел 0_0 наследование - .input_theme_islands .input__box { position: relative; display: block; -webkit-touch-callout: none; -webkit-user-select: none; -moz-user-select: none; -ms-user-select: none; user-select: none; } http://screencast.com/t/wI61OvqVln6F

Я так понял, что MSIE 8 еще поддерживается в bem-core. Пустая страница. из блока page и 1 обычного блока без доп.технологий падает в IE Собранный js можно посмотреть в gist

bem-components 2.1.0 bem-core 2.6

upd: Самое главное не написал. Ошибка: Объект не поддерживает это свойство или метод строка 4589 символ 5

    name !== 'i-bem__dom_init' && arguments.length > 2 && ~deps.indexOf('i-bem__dom') &&
        modules.define('i-bem__dom_init', [name], function(provide, _, prev) {
            provide(prev);
        });
};

https://ru.bem.info/libs/bem-core/v2.6.0/desktop/i-bem/#Простое-наследование

Для доступа к методам родителя служит специальное поле контекста this.__base

По факту this.__base() делает инициализацию baseBlock. А методы базового блока стали методами текущего объявленного.

Хочу сказать спасибо @tadatuta за ревью кода моего компонента меню представленного на конкурс. Замечания были очень полезные.

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

Мой компонент построен на блоках menu, menu-item, button и прочих из библиотеки bem-components. Для реализации второго уровня в меню, я воспользовался элементом group блока menu задав ему абсолютное позиционирование и overflow-y: auto. Однако, код метода _scrollToItem не был рассчитан на такое рассположение пунктов меню и мне понадобилось переопределить его: я скопировал код метода из библиотеки, сделал автоматическое определение контейнера со скроллом и изменил функцию анимации. Так же мне не понравилось, что вызов метода _scrollToItem происходит при наведении мышью. Пришлось переопределять метод _onItemHover. Потом выяснилось, что клавиатурная навигация для переключения выбранного пункта меню устанавливает ему модификатор hovered (этому я посвящу отдельный пост). Методы _onKeyDown и _onItemClick тоже пришлось переопределять.

Всю эту красоту я оформил, как модификатор menu_fix_scroll, чтобы не ломать блок menu в других местах и разместил его как модификатор моего блока kg-menu_fix_scroll. Этот модификатор указан как зависимость самого блока kg-menu.

Вот тут я подошёл к вопросам:

  • правильно ли я решил, что доопределения библиотечного блока, которые необходимы только моему блоку и нигде более правильно разместить внутри моего блока?
  • критично ли, что kg-menu_fix_scroll.js фактически описывает menu_fix_scroll?
  • есть ли другие более изящные пути решения такой проблемы?

Сейчас я делаю поле типа autocomplete в рамках компонента поиска. Есть мысль сделать его на базе dropdown, определив новый модификатор dropdown_switcher_input. Снова возникают вопросы означенные выше.

Вариант 1. В блок dropdown добавить модификатор _switcher_input. (Будет странно смотреться, как не совсем самостоятельная сущность. Скорее всего не получится выделить общие правила для отображения попапа, оставив только метод аналогичный onSwitcherClick) Использовать его в блоке autocomplete (или даже в модификаторе _type_autocomplete блока input). Затем всё это использовать это в моём блоке поиска.

Вариант 2. Определять модификатор dropdown_switcher_input внутри autocomplete / input_type_autocomplete.

Вариант 3. Не использовать код dropdown и реализовать autocomplete / input_type_autocomplete самостоятельно.

Вариант 4. Только что придумал вариант, похожий на правильный ответ. Наследовать autocomplete (input_type_autocomplete врядли получится?) от dropdown.

Люблю в проектах использовать UIKit. Где хранить сторонние JS/CSS и как их подключать в BEMJSON? Также для UIKit нужен заранее подключенный jQuery, он есть в bem-core, возможно ли инициализировать без дополнительного скачивания.

this.__popup = this.findBlockInside('popup', 'popup');
this.__popup.on({ modName : 'visible', modVal : true }, function() {
  this.bindToDoc('keydown', this._onKeyDown, this);
}, this);

Есть способ сделать тоже самое лаконичнее и эстетичнее?

Возникла проблема с this. Каждый с ней сталкивался, когда приходилось что-то делать с фильтрами или чем-то другим. Приходилось кэшировать в переменную self Или, например, каждый раз при смене модификатора элемента приходилось писать что-то типо этого

this.setMod( this.elem('right'), 'size', 'xxxxl' );

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

modules.define('scroller', ['i-bem__dom', 'jquery'], function(provide, BEMDOM, $) {

var block;

function elem(name) {
    return block.elem(name);
}

BEMDOM.decl(this.name, {
    onSetMod: {
        'js' : {
            'inited' : function() {
                block = this;
            }
        }
    },
}, {});

provide(BEMDOM);

});

После чего к блоку всегда можно обращаться через block а к элементу через elem('name').

например установка модификатора для элемента теперь будет выглядеть так:

block.setMod( elem('right'), 'size', 'xxxxl' );

из плюсов

  • однозначность block
  • более короткая запись для доступа к элементам elem('name')
  • 4 строчки кода

П.Н. Данное решение актуально для bem-core@v2, в bem-core@v3 - решение будет лучше из коробки.


@tatudata ниже объяснил, почему так нельзя. В ответах есть другие предложения.


Что есть в ответах

Добавлена реализация короткой записи модификации элементов вида:

this.el('body')
       .setMod('size', 'xxx')
       .setMod('color', 'gray);

Давно хочу спросить: как, используя bem-core и bem-components собрать статичный html, который можно будет использовать на любой платформе. Т.е. я хочу, например, чтобы блоки page и ua были собраны из всех слоёв переопределения (touch, desktop).

Дело в том, что библиотеки не поддерживают работу этих слоёв одновременно, и более того - не собираются.

Как быть, что делать?

Поскольку мы не ищем лёгких путей, то у нас на проекте до сих пор i-bem какой-то дремучей версии и свой собственный сборщик.

Мне всё это несколько надоело и я пробую мигрировать на bem-core. Сразу сейчас прикручивать enb и вот это всё — неподъёмная задача, поэтому цепляю bem-core из бовера. И вот тут напоролся на то, что в https://github.com/bem/bem-core/blob/v2/bower.json не прописаны вообще никакие зависимости, в частности ymaps/modules.

Собственно вопрос в том, есть ли способ подключить ymodules в бовере более прямой, чем указать гит-путь?

"dependencies": {
  "modules": "git@github.com:ymaps/modules.git#0.1.0",
}

Хочу прояснить для себя пару моментов по YM модульной системе, о которых не рассказывается в документации, буду крайне признателен:

1) В commonJS и AMD модульных системах при попытке обратиться к модулю, например, require('myModule', function(myModule){...});, если этого модуля нету на странице(если это браузер), то модульная система сама подгрузит с сервера файл этого модуля. Может ли YM сделать тоже самое?(Методом проб этого дообиться не удалось).

2) На habrahabr в статье про YM прочел, что есть специальный модуль loader у YM для подгрузки скриптов, но я так и не понял:

2.1) а кто будет подгружать на страницу сам этот модуль loader? Самому вручную добавлять этот модуль на страницу сразу после тега