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

Доброго дня! Встал вопрос обернуть часть текста в отдельный тег strong, примерно как тут:

<h2 class="promo-title">
<strong class="bem">БЭМ</strong> 
предлагает 
<em class="promo-highlight">единые</em> 
правила написания кода
</h2>

Как описать такую конструкцию в bemjson?

Где-то попадалась статья (или пост), не могу сейчас найти.

Задача: "подмешать" к основному блоку функционал другого.

В простейшем варианте (то, что заработало) получается во время инициализации первого сказать примерно так:

var second_block_object = this.domElem.bem('second_block');

-- тогда имею почти то, что нужно: объект второго блока, ассоциированный с dom-узлом.

Но хотелось бы уметь указывать необходимость примеси из шаблонов и оттуда же передавать параметры второму блоку (js()({ ... })). К сожалению, через mix таким образом подцепить нужный блок не удаётся. Как это делается правильно? (Как-то ведь делается?.. Вроде бы видел даже примеры...)

Добрый день! Сразу говорю, документацию не читал, в философии не разбирался. Вопрос только один. Существует достаточно много js библиотек для построения интерфейса. У некоторых из них (ext.js, smartclient, webix, qooxdoo и пр.), есть возможность писать представление прямо в javascript по способу, очень похожему, который описан в bemjson. Это я считаю очень удобно, код получается чистым. А у некоторых из них сделано все это не очень красиво: аля jquery ui. Т.е цепляемся к определенным dom элементам по css селектору и прописываем в js свойства. Такой метод конечно хорош для простого сайта, но для полноценной SPA - не очень приятно. Например кнопки тулбара одна библиотека хранит в json, а сам тулбар цепляется к dom элементу, другая требует чтобы обязательно див элементы на эти кнопки и т.п.. В результате получается бардак. За примером далеко ходить не надо, посмотрите easyui, jQWidgets, kendo UI и тп. Я хочу писать подобные вещи без строчки html кода. Сможет ли bem превратить json код в что-то аля:

<body>
   <input id = ‘spinner’ class="easyui-numberspinner" 
</body>
<script>
$('# spinner’). numberspinner ({increment:10});
</script>

Есть задача менять (добавлять, удалять) пункты меню в выпадающем списке (menu в select).

Сойчас решаю проблему полной перегенерацией блока. Примерно так: BEMDOM.update(..., BEMHTML.apply(...)). Пока встречается не очень часто, но как-то всё же не красиво, да хотелось бы иметь способ на будущее.

Похожий способ, но тоже не очень вариант: в select есть доступ к вложенному menu (свойство _menu) методом setContent заменять содержимое на сгенерированный html.

Можно ли придумать способ, чтоб это было похоже на оперирование с элементами массива или через интерфейс inset/append/remove? Ну хоть как-то вообще?

Привет. Начал использовать full-bem-stack ибо удобно. Столкнулся с не пониманием уровня детализации и инкапсуляции блока. Скажем, есть у нас стандартный слайдер со слайдами. .b-slider, .-b-slider__slide Каждый слайд состоит из картинки, фонового цвета, заголовка, текста и кнопки.

Как будет правильно создать блок слайдера?

{ 
    block: 'slider', 
    content: [ 
        { 
            elem: 'slide', 
            content: /* здесь выносим все элементы типа slider__slide-title, slider__slide-img т так далее */ 
        } 
    ]
} ```

или лучше для каждого элемента .b-slider__slide задавать аттрибуты, которые дальше превращать в нужную структуру элементов в шаблонизаторе bemhtml ?

P.S. Как в редакторе добавит код в <code> ?

Как можно реализовать вот такой прилипающий footer Ryan Fait's HTML5 CSS Sticky Footer на БЭМ?
Проблема в том, что блок должен обернуть содержимое body в тэг-обёртку и кроме того добавить определённые стили в и , что насколько я понимаю противоречит принципу независимости блоков. Можно вроде как добавить в и миксы, но как-то это на мой взгляд не совсем красиво ... да и насчёт миксов не уверен - недостаточно компетентен в БЭМ - методологии.

Коллеги!

Для описания БЭМ-дерева мы используем bemjson (или bemtree, который позволяет создавать полный bemjson страницы по частям, что по сути — то же самое, верно?) Однако, по своей природе json — довольно многословный формат представления данных, а html (jsx) более лаконичный.

Есть какие-то трансляторы jsx -> bemjson? Наверняка, кто-то думал в эту сторону, имеет ли это практичный смысл?

Добрый день! Какие есть практики создания статичных, кэшируемых частей сайта, что бы генерировать только изменяемые части/подставлять данные? Или это не так уж и затратно каждый раз заново генерировать страницу?

От создателей легендарного bemmet очередная штука, позволяющая писать меньше букв — bem-indent-syntax.

Demo вместо тысячи слов.

PS: Если наберется 10 звезд на github, сделаю плагин для Sublime ;)

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

БЭМ (frontend) <-- REST Api --> Express (backend).

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

Для вёрстки планирую использовать project stub. Но как правильно подойти к этому моменту?

Опишу вообще как я вижу процесс в абстракции: В проекте лежит каталог bem(project-stub).

Там я верстаю страницы и показываю их заказчику, он радуется. Далее я собранные bemtree + bemhtml подключаю в продакшине. И работаю уже непосредственно с разработанным REST Api + bemtree + bemhtml. В общем стоит задача минифицировать время между вёрсткой демо страниц и продакшин.

Какие здесь подводные камни имеются и реализуемо ли это? Как настроить сборку?

Буду благодарен за ответы :)

Здравствуйте, имеется ли возможность прицепить какой нибудь обработчик к стандартному сборщику для нарезки блоков на отдельные файлы? если да то как првильней реализовать данную фичу?

Предистория:

Сейчас работаю с Modx и там имеется возможность создавать блоки кода - Чанки (блоки по методологии БЭМа) и шаблон страниц (Bundles). Но чанки могут в себе подключать другие чанки как в БЭМе блоки. само подключение выглядит следующим образом [[$intro? &name=George&messageCount=12]]

Задача в следующем:

делать 2 версии верстки при билде. 1я это чистая верстка для демонстрации и тд. 2я это возможность нарезать блоки на чанки и определять в них разные плейсхолдеры

Пример

BEMJSON:

{
 block:"list",
 tag: "ul",
 block_rplc:"[[!Wayfinder?  &outerTpl=`list` &RowTpl=`list__item` &activeClass=`list__item--active`]]",
 content_rplc: "[[+wf.wrapper]]",
 content:[
 {
  element:"item",
  tag:"li",
  class_add:"[[+wf.class]]",
  content_rplc: "[[+wf.linktext]]",
  content:"item1",
 },{
  element:"item",
  tag:"li",
  content:"item2",
 },{
  element:"item",
  tag:"li",
  content:"item3",
 } 
]
}

Реализован по БЭМ:

<ul class="list">
 <li class="list__item">item1</li>
 <li class="list__item">item2</li>
 <li class="list__item">item3</li>
</ul>

после нарезки получим 2 чанка list.html

<ul class="list">[[+wf.wrapper]]</ul>

list__item.html

<li class="list__item [[+wf.class]]">[[+wf.linktext]]</li>

а в бандле вместо блока list должны получить следующее:

[[!Wayfinder?  &outerTpl=`list` &RowTpl=`list__item` &activeClass=`list__item--active`]]

Предполагаемое решение:

В BEMJSON при декларировании блоков писать дополнительные поля, которые при сборке используем для нарезки блоков.

Всем привет и доброго дня! Читаю документацию и пробую поймать элементарное событие с потомка. Получается чуть менее, чем никак(((

Делаю так:

Кусок bemjson

{
    block : 'test',
    js : true,
    content : {
        block : 'test2',
        js : true,
        content : 'test2 content'
    }
}

Модули:

modules.define('test', ['i-bem__dom', 'test2'], function(provide, BEMDOM, test2) {
    BEMDOM.decl('test', {
        onSetMod : {
            'js': {
                'inited' : function() {
                    test2.on(this.domElem, 'click', this._onClick);
                }
            }
        },
        _onClick : function(e) {
            console.log('hi test');
        }
    });

    provide(BEMDOM);
});

modules.define('test2', ['i-bem__dom'], function(provide, BEMDOM) {
    BEMDOM.decl('test2', {
        onSetMod : {
            'js' : {
                'inited': function() {
                    this.bindTo('click', this._onClick);
                }
            }
        },
        _onClick : function(e) {
            this.emit('click');
            console.log('hi test2');
        }
    });

    provide(BEMDOM);
});

Депсы

test2.deps.js

[{
    mustDeps : [
        { block : 'i-bem', elem : 'dom' },
        { block : 'test2' }
    ]
}]

test.deps.js

[{
    mustDeps : [
        { block : 'i-bem', elem : 'dom' }
    ]
}]

Блоки инциализируются. Ошибок нет. При клике на блоке test2 в консоль падает только 'hi test2'.

Второе. Пробовал через this.findBlockInside('child').on('click', this._onFilterClick, this) задействует только первый дочерний блок... Это правильное его поведение?

Третье. Что это за штука такая: BEMDOM.blocks['blockname'].on(......... Можно где по ней найти документацию? Она поддерживается?

Четвёртое. В коментах тут встречал, что есть ещё каналы. Почитал про них здесь: https://ru.bem.info/libs/bem-core/v2.8.0/desktop/events/#Элемент-channels-блока-events

Это вроде замены findBlockOutside(???).on() или можно использовать повсеместно? Или я вообще неправильно понял назначение каналов?

Сейчас, у нас, если блок имеет логику на priv его можно встроить только в priv'ах же

Предлагаемое решение: регистрировать декларации блоков в неком хранилище в BEMPRIV, а вызываться они должны автоматически неявно на этапе XJST В этих привах не должно создаваться BEMJSON'а, только маппинги данных и какая-нибудь хитрая логика.

XJT/BEMS - Xtendable (almost)-json RawData --> BEMJSON Transformation based on Block Elem Mod State concept (BEMS — not BEViS, 42th BEM concept fork)

https://gist.github.com/a-x-/39242cb6ee00231900f0

Планирую написать сайт на БЭМ и django. Взаимодействие будет реализовано как написал Владимир тут https://ru.bem.info/forum/483/#comment-120414533

  1. Наружу торчит какой-нибудь балансер (например, nginx).
  2. За ним стоит node.js сервер, который ходит в джангу за данными (rowData). Это может быть как один запрос так и агрегация нескольких запросов по http или через unix-socket. Помимо Django нода может собирать данные из любых других необходимых источников (сторонних API, etc). Соответственно Django ничего не знает про view-часть и служит универсальным источником данных для десктопа, телефонной веб-версии или мобильного приложения.
  3. Полученный от Django ответ rowData отдается первому слою преобразования (например, с помощью BEMTREE и на выходе получается BEMJSON — т.е. это по-прежнему данные, но уже знающие про view.
  4. Далее BEMJSON передается в BEMHTML/BH и на выходе получается HTML.

Но я не хочу переносить какую-либо бизнес логику в nodejs. Nodejs будет лишь принимать запросы и проксировать их в django. Django будет возвращать данные только в JSON. При этом помимо самих данных бэкенд будет предоставлять дополнительные данные для БЭМ стека. Например, имя бандла, который должен принять эти данные и сформировать HTML.

Таким образом, можно будет воспользоваться всеми преимущесвами построения интерфейса на БЭМ, но при этом оставить всю бизнес-логику в django, не дублировать логику (DRY)

На стороне django будут реализованы все необходимые урлы, вьюхи. Вьюхи полагаю будут в основном на django-rest-framework + доп. данные для БЭМ. А вот на стороне nodejs будет простейший proxy сервер на express. Proxy сервер будет принимать запросы от браузера, проксировать их в django и получать в ответ JSON-данные. В этих данных будут дополнительные поля для БЭМ (возможно лучше передавать эти данные в заголовках ответа), например, имя бандла. А далее эти данные передаем в BEMTREE шаблон нужного бандла, получаем bemjson, далее этот bemjson передаем в BEMHTML шаблон и на выходе получаем html-код страницы, которуый передаем в браузер.

Это все в теории, хотелось бы услышать комментарии по данной реализации. Какие подводные камни могут ожидать?

Еще хотелось бы помощи в реализации proxy-сервера на nodejs. Пробовал использовать https://www.npmjs.com/package/http-proxy но так и не понял как его доработать, чтоб возвращать в браузер не json-ответ от django, а подменять его сформированным в БЭМ html. Может у кого есть примеры подобных реализаций? Поделитесь опытом.

Парни поделитесь удачным на ваш взгляд клиент-сервер решением обработки ошибок форм? Ajax+js или все на сервере удобнее? @voischev https://twitter.com/voischev/status/703501615681179650

Идеально Model -> JSON Schema -> BEMTREE -> BEMJSON в качестве JSON Schema хорошо подойдет OpenAPI-Specification. Потрогать ее можно тут editor.swagger.io (без БЭМ терминов).

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

Это мое личное мнение, хочется узнать опыт сообщества.

В основе каждой страницы сайта лежит блок page. Как можно дополнить этот блок, чтоб добавить для него дополнительные теги?

Интересует возможность добавить ряд статичных meta-тегов в head, прописать favicon (может быть еще что то). Идея в том, чтобы задать все это в одном месте, а не прописывать в bemjson-е каждого бандла. Подобные вещи реализуются в BEMHTML-шаблонах. Но блок page уже имеет свой шаблон и нужно как то его дополнить, но при этом не сломать. Хотелось бы пример подобной реализации.

Спасибо!

Скопировал себе на проект эти табы https://github.com/bem-contrib/hackaton/tree/master/common.blocks/tabs

BEMJSON:

{
            block : 'tabs',
            mods : { theme : 'islands', type : 'button', size : 'm' },
            tabs : [
                {
                    title : 'First',
                    content : 'First tab content'
                },
                {
                    title : 'Second',
                    content : 'Second tab content'
                },
                {
                    title : 'Third',
                    content : 'Third tab content',
                    checked : true
                }
            ]
        }

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

Здравствуйте! Пытаюсь разобраться с БЭМ, в частности, сейчас пытаюсь понять, как правильно реализовать компоненты MDL в BEMJSON. Например, компонент tabs (ссылка). Если ориентироваться на семантику, лучше всего, наверное, как-то так:

 {
     block : 'tabs',
     content : [
         {
             elem : 'tab',
             name: 'Tab 1',
             content : 'Tab 1 content'
         }
     ]
 }

Но в готовой вёрстке элементов у блока больше: для названий вкладок дополнительно есть mdl-tabs__tab-bar и mdl-tabs__tab. Можно создать эти элементы из поля name в шаблонизаторе, тогда получается, конечный пользователь ничего не должен знать о существовании этих элементов и их не надо добавлять в документацию. Так можно делать? Если нет, то как сделать лучше всего: неужели в BEMJSON должны быть все элементы, в т.ч. относящиеся к реализации?

Проверил возможность использовать БЭМ-стек в песочницах. Учитывая наличие dist-поставки bem-core-dist и bem-components-dist препятствий для этого быть не должно.

Мотивация

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

Эксперимент

Для эксперимента взял блок hello из статьи Собираем статическую страницу на БЭМ. Вот что получилось:

Шаблоны заворачиваем в модуль:

bemhtml

modules.define('BEMHTML', [], function (provide, BEMHTML) {
  BEMHTML.compile(function() {
    block('hello')(
      js()(true),
      tag()('form')
    );
  });
  provide(BEMHTML);
} );

bh

modules.define('BH', [], function (provide, bh) {
  bh.match('hello', function (ctx) {
    ctx.js(true);
    ctx.tag('form');
  } );
  provide(bh);
} );

Для возможности использовать bemjson реализовал блок:

/**
 * @module bemjson
 */
modules.define(
  'bemjson', ['i-bem__dom', 'BEMHTML'],
  function(provide, BEMDOM, BEMHTML) {

    /**
     * @exports
     * @class bemjson
     * @bem
     */
    provide(BEMDOM.decl(this.name, /** @lends bemjson.prototype */ {
      onSetMod: {
        js: {
          inited: function() {
            BEMDOM.replace(this.domElem, BEMHTML.apply(JSON.parse(this.domElem.text())));
          }
        }
      }
    }));
  }
);

Пример использования:

<script type="text/bemjson" class="bemjson i-bem" data-bem="{&quot;bemjson&quot;: {}}">
{
 "block": "hello",
 "content": ""
}
</script>

Результаты

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

К сожалению в IE8 не работает хотя все необходимые ресурсы (shim, ie.css) для этого подключены в Plunker и CodePen кроме JSFiddle, ошибка:

'modules' is undefined

Вопросы

  • Какие есть варианты оформить bemjson отдельным файлом в Plunker?
  • Может быть кто-то знает более подходящею песочницу для экспериментов с БЭМ-стеком?
  • Тестирование, приветствуется.

UPD: v2

  • Каким образом можно оформить bemhtml в песочнице?

Пишу к примеру { tag: 'script', attrs : { src : '?a&b', defer : true }, } На выходе <script src="?a&amp;b" defer></script> Экранирование вообще не нужно. Как это исправить?

Как пример на входе attrs: {onchange: 'mapLayerCheck(this, "route")'}

и на выходе onchange="mapLayerCheck(this, &quot;route&quot;)"/>

К примеру, если пишу mix : [{block : 'buttons', elem : 'smallButton', mods : {red: true}}] то подмешиваются 2 класса buttons__smallButton и buttons__smallButton_red А нужно чтобы подмешивался только buttons__smallButton_red. Как это сделать?

Создал слайдер (блок slider) с поддержкой входных параметров (this.params) и слайд-шоу. При установке двух и более экземпляров на страницу, происходит (по-видимому) смешивание их параметров, или их переопределение. Перелистывание слайдов всегда производится с учетом ширины (width) и скорости перелистывания (duration) последнего экземпляра. То же касается величины задержки (delay) при слайд-шоу.

Помогите, пожалуйста, разобраться, в чем таится ошибка.

Ссылки:

Есть такой код:

{
    block: 'donut-pie',
    tag: 'svg',
    attrs: {
        width: '45px',
        height: '45px'
    }
}

Все классно отрисовывается, а в консоль кидает: Uncaught TypeError: domNode.className.match is not a function.

Если сделать так:

{
    block: 'donut-pie',
    content: {
        tag: 'svg',
        attrs: {
            width: '45px',
            height: '45px'
        }
    }
}

Так ошибки нет. Почему?

Как это прописать в bemjson?

<!--[if lte IE 8]>

<![endif]-->

Как я понимаю за компиляцию bemjson в html отвечает эта команда https://github.com/bem/project-stub/blob/bem-core/.enb/make.js#L62 А в технологии bemjson-to-html такой опции нет и все компилится в одну строку

Такая идея, наверное, уже не у одного меня возникла.

Сделать шаблонизатор типа BN (Bem Node) который перегоняет bemjson в DOM дерево не посредством компиляции html строки, а через document.createElement()

  • Есть у кого какие мысли?
  • Что из этого может получится?

Поиграться можно тут http://bem.github.io/bem-xjst/

Пара типов данных

({
    block: 'block1'
});

или

({
    block: 'block1',
    mods: { a: 'b' }
});

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

Вариант 1 (как бы правильный)

block('block1')(
    def()(function() {
        this.mods.bla = 'bla';
        this.ctx.content = '1';
        return applyNext();
    })
);

block('block1').mod('bla', 'bla')(
    def()(function() {
        this.mods.ololo = true;
        this.ctx.content = 'bla';
        return applyNext();
    })
);

вариант 2

block('block1')(
    def()(function() {
        this.mods = { bla: 'bla' };
        this.ctx.content = '1';
        return applyNext();
    })
);

block('block1').mod('bla', 'bla')(
    def()(function() {
        this.mods.ololo = true;
        this.ctx.content = 'bla';
        return applyNext();
    })
);

Вариант 3

block('block1')(
    def()(function() {
        this.ctx.mods = { bla: 'bla' };
        this.ctx.content = '1';
        return applyNext();
    })
);

block('block1').mod('bla', 'bla')(
    def()(function() {
        this.mods.ololo = true;
        this.ctx.content = 'bla';
        return applyNext();
    })
);

Вариант 4! Причем работает как нужно есть есть mods в bemjson

block('block1')(
    def()(function() {
        this.ctx.mods.bla = 'bla';
        this.ctx.content = '1';
        return applyNext();
    })
);

block('block1').mod('bla', 'bla')(
    def()(function() {
        this.mods.ololo = true;
        this.ctx.content = 'bla';
        return applyNext();
    })
);

Еще их вариации

Что интересно даже

block('block1')(
    def()(function() {
        this.mods = this.extend(this.mods, { bla: 'bla' });
        this.ctx.content = '1';
        return applyNext();
    })
);

block('block1').mod('bla', 'bla')(
    def()(function() {
        this.mods.ololo = true;
        this.ctx.content = 'bla';
        return applyNext();
    })
);

Не работает как нужно. Ожидаю что как бы я не записал модификаторы (через создание нового объекта или через ссылку. через this.mods или через this.ctx.mods) то отработают шаблоны по ним и классы будут в результате шаблонизации.

Вероятно дело в том что когда в mods пишешь новый объект ссылки теряются по этому то шаблон BEMHTML не отрабатывает то класс не проставляется в результате шаблонизации. Не доконца ясна в таком случае ситуация с this.mods и this.ctx.mods

Как это объясняется вами? И что делать? Что будет делаться если будет?

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

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

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