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

В документации написано, что

  • синтаксис BEMHTML и BEMTREE почти идентичен.
  • BEMTREE использует синтаксис-BEM-XJST и сохраняет все особенности BEM-XJST-шаблонизаторов.

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

Есть ли возможность примиксовать компоненту с определенными модификаторами поведение элемента какого-либо блока с его собственными модификаторами? К примеру:

Использовать подобный BEMJSON

{
    block: 'promo',
    content: [
        {
            block: 'button',
            mods: { type: 'link' },
            mix: { block: 'promo', elem: 'action' },
            elemMods: { type: 'secondary' },
            text: 'Secondary action',
            url: ''
        }
    ]
}

Примечание: понимаю, что использование elemMods здесь при определенных обстоятельствах (несколько миксов) приводит к неоднозначности, однако, насколько мне известно, сделать так: mix: [ { block: 'promo', elem: 'action', type: 'secondary' } ] не выйдет.

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

<a class="button action_type_secondary promo__action">
    <span class="button__text">Secondary action</span>
</a>

Подключил блок control-group с использованием темы islands В итоге отображается криво. Вот код из bemtree

block('header').content()(function() {
    return [
        {
            block: 'logo'
        },
        {
            elem: 'nameplate',
            content: 'Project'
        },
        {
        block : 'control-group',
        content : [
            {
                block : 'input',
                mods : { theme : 'islands', size : 'l', type : 'search' },
                placeholder : 'Найти'
            },
            {
                block : 'button',
                mods : { theme : 'islands', size : 'l' },
                text : 'Поиск'
            }
    ]
}
    ];
});

Вот скриншот окна браузера https://yadi.sk/i/mDT7KiHlkkHEu Как постить на форуме изображения, чтобы они показывались сразу?

В двух блоках наблюдается проблема отсутствия css свойств именно для элементов блоков Вот структура файлов и папок

header
     __nameplate
          header__nameplate.styl
     header.styl

Свойства header.styl подключаются, а из header__nameplate.styl нет

Решил поменять имя основного класса c page на root в блоке root после этого перестало передаваться все содержимое в head.

block('root').replace()(function() {
    return {
        block: 'main', //здесь изменено имя
        title: 'TODO',
        head: [
            { elem: 'css', url: 'index.min.css' },
            { elem: 'css', url: '//fonts.googleapis.com/css?family=Open+Sans:300&subset=cyrillic'}
        ],
        scripts: [
            { elem: 'js', url: 'index.min.js' }
        ],
        mods: { theme: 'islands' }
    };
});

Хотел бы использовать идеи из Яндекс Маркета для создания собствнного аналитического сервиса. Это не магазин и не коммерческий проект. В целом мне нравятся возможности выборки и сортировки, что мне очень нужно. Есть ли какие-то ограничения для использования Яндекс Маркета в качестве прототипа? Если нет, то есть ли в свободном доступе репозитории данного сервиса или, что-то похожее?

Всем привет, можно ли блок popup привязать к input, необходимо сделать выпадающий список при поиске.

  1. Допустим есть 10-20 страниц верстки. Шапка и подвал на этих 20 страницах повторяются 1 в 1. Хочешь что-то изменить? - 20 copy&paste в bemson. Это мой текущий уровень понимания. А нет ли случаем возможности выносить повторяющиеся части страниц в отдельные bemjson-файлы, чтобы править в одном месте? Я попробовал require в bemjson - работает, но не до конца. При повторной сборке bemjson-to-bemdecl сборщик (не зная про инклуды) считает что bemjson не изменился и естественно не перегенерирует bemdecl. Кто как решает эту DRY-задачку?
  2. Нет ли какой-нибудь технологии, которая на основе bemjson+bh сформирует список зависимостей как это сделано при сборке bemjson->bemdecl->deps? Очень надоедает для каждой bh-реализации руками писать deps.js

Например я установил bem-bemtree-project-stub теперь хочу прикрутить сетку bem-grid. Как правильно стыковать данные сборки, чтобы они не ломали друг друга? Просто ставить поверх в ту же деректорию или как? Прошу не ограничиваться данными сборками. Меня интересует общий принцип соединения bem решений.

Как правильно вызвать trigger и сказать, что произошло событие menuItemClick

     this.emit('menuItemClick', {
                    domElem : elem,
                    group: this.elemParams(elem).group
       });

если блоков menu на странице несколько, а событие нужно именно конкретного блока menu

В каком месте у меня ошибка? Что-то не хочет реагировать на событие клик

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

      provide(BEMDOM.decl(
        this.name,
        {
        onElemSetMod: {
        // Будем реагировать на изменение состояния элемента item
        'item': {
            // когда у него будет меняться модификатор state,
            'state': function (elem, modName, modVal) {
                // Когда мы получили состояние объекта, нам нужно оповестить другие блоки о том, что
                // произошло. Для этого мы вызываем trigger и говорим, что произошло событие Click,
                // заодно передаём важные параметры: элемент и его идентификатор метки.
                this.emit('click', {
                    domElem : elem,
                    group: this.elemParams(elem).group
                });
            }
        }
        },

        onTriggerElemClick: function (e) {
        e.preventDefault();
        var el = e.currentTarget;
        // Потом точечно включим у того, по которому нажали.
        this.toggleMod(el, 'state', 'active');
        }
    }, {
    live: function () {
        // Вешаем слушатель на клик.
        this.liveBindTo('item', 'click', function (e) {
            this.onTriggerElemClick(e);
        });

        this.on(this.domElem, 'click', function (e, data) {

            var activeState = this.buildSelector('item', 'state', 'active').substr(1);
            this.lastSelected && this.lastSelected.removeClass(activeState);
            this.lastSelected = data.domElem;
        });
    }
    }
    ));
    });

Прошу еще раз скинуть ссылку на руководство по оформлению кода на форуме.

В библиотеке bem-components есть блоки menu и menu-item, тогда как в bem.info используется блок nav. Хотел бы узнать почему в bem.info не используются блоки меню из bem-components? А также как сгенерировать блок меню с помощью технологии bemtree? В примерах есть шаблоны для bemjson и html. Также есть код deps. Почему нет кода для bemtree?

Привет!

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

Имеем следующую структуру BEMJSON:

...
{
    block: 'info',
    content: [
        {
            block: 'text',
            mix: { block: 'info', elem: 'title' },
            content: 'Some text'
        },
        ...
    ]
}
...

info__title.bemhtml :

block('info').elem('title')(
    tag()('h1')
)

На выходе получаем (стили из info__title.styl успешно парсятся — зависимости соблюдены) :

<div class="text info__title">Some text</div>

В чем ошибка?

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

Всем привет. В проекте на project-stub'е решил использовать сетку bem-grid . Сделал следующее:

$ git clone https://github.com/bem-incubator/bem-grid.git
$ cd bem-grid
$ npm install

Добавил необходимые уровни из bem-grid в файл make.js:

{ path: 'libs/bem-grid/common.blocks', check: false },

Пример из доков:

 {
block : 'row',
content : [
       {
        elem : 'col',
        mods : { mw : 6 },
        content : 'left column'
    },
    {
        elem : 'col',
        mods : { mw : 6 },
        content : 'right column'
       }
   ]
}

не работает. mods : { mw : 6 } нет.

Отсутствует крестик у input_type_search по крайней мере в документации. Библиотеку не проверял. https://ru.bem.info/libs/bem-components/v2.3.0/desktop/input/#Поле-для-поиска-модификатор-type-в-значении-search

Uncaught SyntaxError: Unexpected end of input

У нас есть документация про технологии БЭМ платформы (BEMJSON, BEMTREE, BEMHTML, DEPS), но практически нет туториалов по использованию их всех вместе. Есть несколько исключений, но они достаточно объемные и сложноваты для восприятия.

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

Пусть у нас есть следующий файл с данными data.json:

{
    "user": "mathetes",
    "company": "WebExcel",
    "city": "Novosibirsk"
};

Как вариант, данные могут приходить из БД или через HTTP API — источник не играет роли.

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

Первым шагом необходимо из исходных сырых данных получить BEMJSON, описывающий страницу. Для этого будем использовать технологию BEMTREE. При этом договоримся, что в качестве корневого блока, на основе которого будет строиться дерево, возьмем блок page.

В результате должен получиться следующий BEMJSON:

{
    block: 'page',
    content: [
        {
            block: 'header',
            content: {
                block: 'logo'
            }
        },
        {
            block: 'main',
            content: {
                block: 'user',
                content: 'тут-содержимое-карточки-пользователя'
            }
        },
        {
            block: 'footer',
            content: '© 2015 SuperPuper'
        }
    ]
}

BEMTREE-шаблон для блока page должен построить шапку, основную часть и подвал:

block('page').content()(function() {
    return [
        { block: 'header' },
        { block: 'main' },
        { block: 'footer' }
    ];
]);

По техзаданию в шапке должен быть логотип. Тогда шаблон шапки может выглядеть так:

block('header').content()(function(){
    return { block: 'logo' };
});

В основной части нужна карточка пользователя. Так что нам потребуется доступ к данным из файла data.json. Но пока отложим этот момент и захардкодим какие-то тестовые данные:

block('main').content()(function() {
    return {
        block: 'user',
        content: [
            {
                elem: 'name',
                content: 'test name'
            },
            {
                elem: 'company',
                content: 'test company'
            },
            {
                elem: 'city',
                content: 'test city'
            }
        ]
    };
});

В подвале нужен копирайт:

block('footer').content()('© 2015 SuperPuper');

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

В самом простом случае мы можем сохранить все шаблоны в один файл, установить пакет bem-xjst и с его помощью скомпилировать бандл:

bem-xjst -i path/to/templates.js -o bundle.bemtree.js

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

Схема работы ENB подробно описана в этом документе. Главное, что нас сейчас интересует — это то, что ENB собирает файлы только тех сущностей, которые явно задекларированы.

Получить декларацию с перечислением всех нужных блоков можно двумя способами: в *.bemdecl.js перечислить все нужные блоки (и не забывать добавлять и удалять их по мере разработки и рефакторинга), либо указать только корневой блок (в нашем случае page), а блоки, которые нужны корневому и всем последующим, указывать в их собственных списках зависимостей — deps.js. Второй путь гораздо гибче: сохраняется прицип БЭМ-методологии о том, что блок сам знает о себе всё, при удалении блока автоматически будут удалены и его зависимости, а при добавлении они автоматически включатся в сборку.

Так как шаблон блока page создает блоки header, main и footer, мы явно укажем это в списке зависимостей в файле page.deps.js:

({
    shouldDeps: ['header', 'main', 'footer']
})

Если вы имели опыт работы с project-stub, где нужные файлы попадали в сборку автоматически, то необходимость указывать зависимости вручную может показаться странной. Дело в том, что там у нас на руках заранее был готовый BEMJSON-файл, по которому можно было получить список всех необходимых сущностей. А в данном случае мы планируем генерировать BEMJSON в процессе сборки на основе шаблонов. При этом шаблоны необходимо собрать заранее, а значит декларацию нужных блоков потребуется описать самостоятельно.

Отлично, теперь мы знаем как собрать шаблоны. Следующим шагом необходимо получить с их помощью BEMJSON на основе данных, а затем из BEMJSON сгенерировать HTML с помощью BEMHTML. В общем виде это выглядит так:

var data = require('path/to/data.json'),
    BEMTREE = require('path/to/bundle.bemtree.js').BEMTREE,
    BEMHTML = require('path/to/bundle.bemhtml.js').BEMHTML,
    bemjson = BEMTREE.apply(data),
    html = BEMHTML.apply(bemjson);

require('fs').writeFileSync('index.html', html);

Эти преобразования будут работать и в браузере, если подключить bundle.bemtree.js и bundle.bemhtml.js на страницу. Останется только вставить полученную HTML-строку в DOM.

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

Как видно в примере кода выше, данные мы передаем в вызов BEMTREE.apply(data). При этом мы помним, что корневым блоком должен оказаться блок page. Достичь этого можно следующим образом:

var data = require('path/to/data.json');
BEMTREE.apply({
    block: 'page',
    data: data // теперь данные попадут в контекст шаблона блока page
});

Модифицируем код шаблона так, чтобы пробросить данные для вложенных в page блоков:

block('page').content()(function() {
    this.data = this.ctx.data; // this будет общим для всех потомков page,
                               // так что они смогут использовать поле data

    return [
        { block: 'header' },
        { block: 'main' },
        { block: 'footer' }
    ];
]);

Тогда финальный вид BEMTREE-шаблона блока main окажется таким:

block('main').content()(function() {
    var data = this.data;

    return {
        block: 'user',
        content: [
            {
                elem: 'name',
                content: data.user
            },
            {
                elem: 'company',
                content: data.company
            },
            {
                elem: 'city',
                content: data.city
            }
        ]
    };
});

Из соображений унификации в качестве корневого блока удобно использовать блок root, который будет отвечать за пробрасывание данных вглубь дерева и создавать page:

block('root').replace()(function() {
    return {
        block: 'page',
        title: 'TODO',
        head: [
            { elem: 'css', url: 'index.min.css' }
        ],
        scripts: [
            { elem: 'js', url: 'index.min.js' }
        ],
        mods: { theme: 'islands' }
    };
});

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

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

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

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

Подробности и форма регистрации.

Добрый день. Вероятно, задам совсем базовый вопрос, но мне не удается запустить gemini в связке с browserstack.

Все делаю по инструкции https://ru.bem.info/tools/testing/gemini/

По пунктам.

  1. Имеется оплаченный доступ на браузерстак.
  2. Установлен компилятор.
  3. gemini установлен глобально и локально.
  4. установлен плагин gemini-browserstack
  5. файл .gemini.yml (username и acessKey естественно введены верно.)

    rootUrl: http://http://yandex.com system: plugins:

     browserstack:
       username: 111
       accessKey: 1111111111111111111111
    

    browsers:

     ie11:
       desiredCapabilities:
         os: "WINDOWS"
         os_version: "7"
         browserName: "internet explorer"
         version: "11"
    
  6. test.js полностью скопирован из примера:

    var gemini = require('gemini'); gemini.suite('yandex-search', function(suite) {

      suite.setUrl('/')
          .setCaptureElements('.main-table')
          .capture('plain')
          .capture('with text', function(actions, find) {
              actions.sendKeys(find('.input__control'), 'hello gemini');
          }); });
    

При попытке запуска команды gemini gather test выплевывается ошибка https://drive.google.com/open?id=0B0TKvOp7ysTEUllyN2c0OUxqamc

К сожалению, никаких мануалов по данному вопросу найти не удалось. Буду рад любым данным. Как конкретным ответам "сделай то-то и будет счастье", так и мануалам. Спасибо.

Добрый день. Вероятно, задам совсем базовый вопрос, но мне не удается запустить gemini в связке с browserstack.

Все делаю по инструкции https://ru.bem.info/tools/testing/gemini/

По пунктам.

  1. Имеется оплаченный доступ на браузерстак.
  2. Установлен компилятор.
  3. gemini установлен глобально и локально.
  4. установлен плагин gemini-browserstack
  5. файл .gemini.yml (username и acessKey естественно введены верно.)

    rootUrl: http://http://yandex.com system: plugins:

     browserstack:
       username: 111
       accessKey: 1111111111111111111111
    

    browsers:

     ie11:
       desiredCapabilities:
         os: "WINDOWS"
         os_version: "7"
         browserName: "internet explorer"
         version: "11"
    
  6. test.js полностью скопирован из примера:

    var gemini = require('gemini'); gemini.suite('yandex-search', function(suite) {

      suite.setUrl('/')
          .setCaptureElements('.main-table')
          .capture('plain')
          .capture('with text', function(actions, find) {
              actions.sendKeys(find('.input__control'), 'hello gemini');
          }); });
    

При попытке запуска команды gemini gather test выплевывается ошибка https://drive.google.com/open?id=0B0TKvOp7ysTEUllyN2c0OUxqamc

К сожалению, никаких мануалов по данному вопросу найти не удалось. Буду рад любым данным. Как конкретным ответам "сделай то-то и будет счастье", так и мануалам. Спасибо.

Есть у меня значит такая страктура:

blockA - подписывается как liveBindTo на change от инпута. Внутри по change эмитим событие change наверх. blockB - более высокоуровневый, работает с blockA. Делает this.liveInitOnBlockInsideEvent('change', 'blockA', function(e) { /* тут эмитим событие наверх this.emit('toggle'). Вот здесь я вылетаю каждый раз / }) blockC - еще более высокоуровневый. Работает с blockB. Делает this.liveInitOnBlockInsideEvent('toggle', 'blockB', function(e) { / И здесь тоже. */ })

По сути получается, когда я кликаю на чекбокс (blockA) и вот это вот все эмитит события на верх, оно пытается проинициализироваться на каждый следующий клик (change/toggle) хотя все блоки заинитились (blockA, blockB, blockC).

Пока залепил булевым локом на инстанс. Но ведь негоже.

Всем привет. Подскажите, пожалуйста, как правильно отреагировать на событие клик по первому блоку button в такой DOM-моделе

{
        block : 'control-group',
        content : [
              {
                       block : 'input',
                        mix: { block: 'header', elem: 'search-input' },
                       mods : { theme : 'islands', size : 'l', type : 'search' }

                },
                {
                         block : 'button',
                         mods : { theme : 'islands', size : 'l' },
                          icon : {
                                 block : 'icon',
                                  mods : { type : 'earth' }
                           }
               },
               {
                    block : 'button',
                    mods : { theme : 'islands', size : 'l', type: 'submit' },
                    text : 'Поиск'
               }
                  ]
            }

Пока, все что пробовал, дает реакцию на клик по любой кнопке.

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

В качестве примера для верстки я взял одно старое Яндексовое тестовое задание - https://yandex.ru/jobs/vacancies/dev/dev_des/

Моя реализация - https://github.com/koloskof/bem-taxi

Буду благодарен!

Пытаюсь разобраться с bemtree. Хотел бы использовать решения из bem.info для своего проекта. Скопировал нужные блоки в папку common.blocks. В папке desktop.bundles лежат файлы bemtree и html, но они выглядят как обычные js функции, а не как привычное описание блоков. Потом все это генерится в output-ru Как это использовать? Извиняюсь за бестолковые вопросы. Но больше спросить не у кого.

Добрый день,

Из описания executeJS(function(window)) - NB: Функция выполняется в контексте браузера, поэтому любые ссылки на её внешний контекст работать не будут.

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

 suite.before(
            function( actions ) {
                actions.executeJS( function( window ) {
                    window.document.cookie = 'someCookie';
                    window.location.pathname = 'somePath';
                } );
                common.beforeFunction(size)(actions);
            }
        );

А в идеале хотим сделать что то типа:

suite.before(
    function( actions ) {
        actions.executeJS(  common.someFancyCallbackUsingExternalContext()  );
    }
);

Заранее спасбо, Слава

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

Что нужно установить? Что дописать? Какие команды запустить?

Подскажите пожалуйста, если я использую bem-componentes dist, подключаю так -

<link rel="stylesheet" href="bower_components/bem-components-dist/desktop/bem-components.css">
<script src="bower_components/bem-components-dist/desktop/bem-components.js+bh.js"></script>

для того, чтобы все работало на ipad нужно ли подключать еще стили и скрипт из папки touch-pad? Что то у меня при подключении как я указала на ipod, вообще сайт перестает работать, ссылки, кнопки не нажимаются, если отключаю bem-components.js+bh.js, то работает, никак не могу понять в чем дело. Я понимаю, что трудно подсказать , так сказать в слепую, но может подскажите, проблема ли в подключении, или же нужно мне копать в другой стороне.