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

Добрый вечер

Пытаюсь вывести данные из JSON, как сказано здесь - https://ru.bem.info/forum/716/

Ничего не выходит, помогите найти ошибку

Вывожу вот так - http://joxi.ru/V2VL9x3SxLX34r

Выдаёт ошибку TypeError: Cannot read property 'apply' of undefined http://joxi.ru/1A5xBqGsnO6Nd2

В переменную BEMTREE почему-то ничего не приходит.

Проверил в вышеобозначенном файле page.bemtree.js через console.log() значения этих четырёх переменных:

  • PATH
  • pathToBundle
  • BEMTREE
  • BEMHTML

Все имеют значение, кроме BEMTREE имеющей undefined

Сборку свою текущую загрузил сюда - https://yadi.sk/d/6WCDVmYN3MqEBL

Добрый вечер

Использую project stub

Ранее всю разметку писал в index.bemjson.js, сейчас же решил оставить там основную разметку, а контент и шаблонизацию вынести для каждого блока в bemhtml/bemtree в common.blocks

И, вроде бы, всё почти сложилось, сами сущности расширяются, в итоговом html в браузере я вижу все блоки, которые должны были сформироваться. Но вот стили применились только к элементам, описанным в bemjson. А блоки, описанные через bemtree оказались проигнорированы в контексте css

Я вычистил из проекта лишнее и залил сюда - https://yadi.sk/d/NeU8Hc033MSDX2

Помогите плиз разобраться в чём дело, почему не применяются стили к topmenu__wrapper?

Добрый день Разрабатываю на project stub относительно большой проект (вёрстка):

  • несколько страниц
  • все страницы разные в контексте блоков, общие только шапка и подвал
  • на разных страницах свои особенные скрипты, которых нет на других страницах
  • разрабатывал страницы отдельно на отдельно взятых project stub заготовках
  • css блоков и bemhtml для каждой страницы клал в common.blocks

Теперь нужно всё это (все странички из разных project stub заготовок) собрать воедино, но пока не пойму как. Мне нужна примерно следующая картина в файловой структуре: common.blocks -- common ---- header ------ header.css ------ header.bemhtml.js ---- footer -- catalog ---- filter ---- heading -- index -- contacts desktop.bundles -- index -- catalog ---- catalog.html ---- catalog.bemjson.js ---- catalog.min.css ---- ... -- contacts

Как это реализовать? Где указать условия каким блокам со стилями из каких каталогов в какую страничку подгружаться? Потому что если я сейчас из разных заготовок стили солью в одну папку, у меня к каждой странице будут подгружаться все стили. Т.е. в contacts будет попадать что предназначалось для catalog и т.д.

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

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

Пока не сел кодить, хотел бы спросить знатоков, есть ли какие то очевидные препятствия реализации?

Допустим есть блок menu с элементами menu__item. Как обернуть все menu__item в блок wrapper, используя bemhtml, чтобы не писать это в BEMJSON ручками.

Имеем:

    {
        block: 'menu',
        content: [
            { elem: 'item', content: 'item 1' },
            { elem: 'item', content: 'item 2' }
        ]
    }

Хотим:

    {
        block: 'menu',
        content: [
            {
                block: 'wrapper',
                content: [
                    {    block: 'menu', elem: 'item', content: 'item 1' },
                    { block: 'menu', elem: 'item', content: 'item 2' }
                ]
            }
        ]
    }

Такое возможно?

Добрый день. Нужна оценка корректности БЭМ нейминга на данной странице: http://portfoliome.ru/demo/portland/ Верное ли наименование классов, использование миксов и тд?

Приветствую всех!

Помоги мне советом пожалуйста, как правильно при использовании bem-express мне использовать уровни при рендере для тач допустим?

Спасибо! Все будет bem :D

Собрали проект на project-stub, с использованием bemjson и bemhtml . Теперь пытаюсь все это прицепить это к php через bh.php . Есть ли возможность на лету портировать bemhtml шаблоны в php, чтоб в дальнейшем использовать их у себя на сайте?

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

block('select').mod('nicescroll', true)(
    block('menu')(
        addMods()(function(){
            return {
                nicescroll : true,
            };
        })
    ),
    // ...

Эффект нулевой.

Как?????????????

UPD: Ага. В bem-components так:

block('select').elem('menu')(
    replace()(function() {
        // ...

Т.е., наверное, могу ловить elem('menu') как-то. Щас попробую.

UPD-UPD: Ничего не придумал, кроме:

    block('select').mod('nicescroll', true).elem('menu').replace()(function(){
        var ctx = applyNext();
        ctx = ctx.replace(/\b(class="menu)\b/, '$1 menu_nicescroll');
        return ctx;
    }),

Но ведь это же неправильно!!!

Нет возможности перехватывать определение block('select').mod('nicescroll', true).block('menu') до рендеринга?

Здравствуйте. Есть блок с названием 'secondary-menu-bottom'. У него есть блок 'menu' с массивом 'items' и контент из одного item. Задача: Необходимо в шаблоне "смапить" массив items, до первого item-a, который уже существует в content. ApplyNext() почему то отказывается работать в связке c map. Если убрать map и оставить ApplyNext() - ошибок не будет. И аналогично с комментированием ApplyNext() - map сделает своё дело Ошибка: TypeError: Cannot read property 'map' of undefined

/ secondary-menu-bottom.bemjson.js /

module.exports = {
    block: 'secondary-menu-bottom',
    content: {
        block: 'menu',
        content: [
            {
                elem: 'item',
                content: include('desktop.blocks/more/more.bemjson.js')
            }
        ],
        items: [
            {
                url: '/',
                title: 'Все рецепты'
            },
            {
                url: '/',
                title: 'Салаты и закуски'
            }
        ]
    }
};

/ secondary-menu-bottom.bemhtml.js /

block('secondary-menu-bottom').extend()({ _inSecondaryMenuBottom: true });

block('menu').match(function() { return this._inSecondaryMenuBottom; })(
    content()(function() {
        return [
            this.ctx.items.map(function(item) {
                return {
                    elem: 'item',
                    content: { block: 'link', url: item.url, content: item.title }
                };
            }),
            applyNext()
        ]
    })
);

Всем привет!

У меня наверное дурная мысль!

Как заинлайнить стили в хтмл применяя стэк БЭМ?

Обоснование данной задачи: Поисковые системы рекомендуют инлайнить стили для рендера верхней части страницы. Для увеличения скорости отображения видимой части страницы клиенту.

Читаю документацию по шаблонизатору, застопорился на первом примере.


Пример. Подпредикат блока link:

block('link')

Входные данные:

[
    // на этот блок предикат вернет `true` и шаблон будет применён
    { block: 'link' },

    // на все следующие сущности предикат вернет `false` и шаблон не будет применён
    { block: 'para' },
    'link',
    { block: 'link', elem: 'text' }
]

Конкретного описания к подпридекату block не добавлено, но выше говорится:

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

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

Вопрос: где я ошибся?

Расскажите, пожалуйста, более подробно про шаблонизацию на клиенте, используя project-stub Подключаю к странице файл index.bemhtml.js, в котором содержится шаблон button, значит на клиент все подгрузилось. Затем пишу блок test test.js

    modules.define('test', ['BEMHTML', 'i-bem-dom'], function(provide, bemHtml, bemDom) {
        provide(bemDom.declBlock(this.name, {
            onSetMod: {
                js: {
                    inited: function() {
                        var html = bemHtml.apply({
                            block: 'button',
                            content: 'test'
                        });
                        console.log(html); // Возвращает пустой результат
                    }
                }
            }
        }));
    });

test.deps.js

    ({
        mustDeps: [
            { block: 'button' }
        ]
    })

Использовал bem-bemtree-static-project-stub и все работало, то есть получается весь мой ступор в файле enb/make.js

Опишу примерно задачу.

Мы получаем ajax данные в виде обычного json (сервер php). Например это список постов, соответственно у нас есть блок post, описанный в bemhtml. Вопрос - как преобразовать голые json-данные в BEM-дерево на клиенте? Схема насколько я понимаю должна быть JSON --> BEMTREE --> BEMHTML --> HTML, но разобраться пока не могу.

Поставил project-stub из merged ветки. В нём есть 3 места где закомментировано использование bemtree. Соответственно раскомментировал, но bemtree-файлы почему-то не подхватываются.

/desktop.bundles/index/index.html 75ms
23:25:20.359 - build started
23:25:20.366 - [rebuild] [desktop.bundles/index/index.bemjson.js] file-provider
23:25:20.367 - [isValid] [desktop.bundles/index/index.bemdecl.js] bemjson-to-bemdecl
23:25:20.370 - [rebuild] [desktop.bundles/index/index.levels] levels
23:25:20.372 - [isValid] [desktop.bundles/index/index.deps.js] deps
23:25:20.374 - [rebuild] [desktop.bundles/index/index.files] files
23:25:20.374 - [rebuild] [desktop.bundles/index/index.dirs] files
23:25:20.375 - [isValid] [desktop.bundles/index/index.bemhtml.js] bemhtml
23:25:20.375 - [isValid] [desktop.bundles/index/index.html] bemjson-to-html
23:25:20.375 - build finished - 23ms

Даже упоминания нет. Соответственно вопрос - что делать?

Допустим, у меня есть блок навигации, который генерит нужную разметку. Я хотела бы использовать его в шапке и в подвале, но чтобы и там, и там он был элементом: .header__nav и .footer__nav. Сейчас чтобы использовать генерацию разметки я сначала подключаю его как самостоятельный блок ({ block: 'nav'}), а затем, например, с помощью миксов добавляю контекст: mix: { block: 'header', elem: 'nav'}. Вопрос: можно ли как-то делать наоборот, то есть объявлять элемент блока, а потом к нему примиксовывать блок для генерации разметки? Другой возможный вариант использования — SVG-иконки, когда, например, элемент .socials__icon одновременно является инлайновым SVG-изображением. Хочется объявлять элемент блока, а потом указывать какой шаблон использовать для разметки, и, таким образом, избавиться от необходимости привязывать контекст миксинами. Как это можно сделать?

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

Я вижу следующие варианты:

  • Вариант "в лоб" - копипастить структуру страницы (bemjson) из бандла в бандл и менять только область контента. Вообще не вариант т.к. при большом размере проекта не дай бог поменяется структура (например добавили на страницу 3-ю колонку) и придётся бегать по всем bemjson-ам и везде менять структуру.

  • Сделать layout в виде блока, а структуру основной области контента пихать в поле content: блока. Это уже вариант, но слабенький, т.к. непонятно тогда зачем вообще bemjson. Весь layout тогда будет в шаблоне блока и в bemjson-е не виден. Плюс непонятно как например для этого варианта ещё и добавить что-то в сайдбар. Вернее понятно - заводим ещё поле в блоке и затем в шаблоне layout-а разруливаем, но это как-то тоже кривенько. Ну т.е. bemjson будет типа:

{ 
  block: 'layout',
  content: { block: 'login-form' },
  sidebar: { block: 'sidebar-widget' }
}

Т.е. фактически выродится, а всё мясо будет фактически внутри шаблона блока layout.

Может есть какие-то ещё варианты? Ну и интересно вообще кто и как подобные штуки разруливает.

Не нашёл способ передать собственный идентификатор в компонент popup группы dropdown из bem-components.

Имеется в виду установка того идентификатора, который используется для связи popup и dropdown_switcher_button.

Как ни пытаюсь, в коде всё равно присутствует ... id="uniq14912161426251"

Максимум, чего удаётся добиться, это <popup ... data-bem='{"popup":{},"dropdown":{"id":"appUserNameDropdown"}}'>, но id всё равно uniq....

Как???

UPD

Так понял, это xjst'шный generateId(), безусловно дёргаемый в dropdown для получения своёства id, который в свою очередь дёргает this.identify(this.ctx), который вроде должен подхватывать свойство this.ctx.uniqueID (как я пробовал сначала), но на самом деле нет. (Такое ощущение, что до того identify, что находится в составе bem-core, дело даже не доходит, если это возможно...)

UPD

Ну да, конечно, там (bem-xjst/lib/bemhtml/bundle.js) свой indentify, вот такой:

exports.identify = function identify(obj, onlyGet) {
  if (!obj)
    return getUniq();
  if (onlyGet || obj[uniqExpando])
    return obj[uniqExpando];

  var u = getUniq();
  obj[uniqExpando] = u;
  return u;
};

который вообще никуда не смотрит.

Т.е., выходит, расширять dropdown (popup?), чтобы переопределять нужные методы/свойства? Как правильно?

Добрый день. Ребята, я начинающий разработчик, просьба сильно не ругать (документацию честно читаю, стараюсь разобраться). Столкнулся с определенной проблемой, подскажите направление, чтобы разобрался дальше самостоятельно. Суть вопроса, чисто теоретически: В проекте на первой страничке хочу сделать универсальную шапку (header), содержащую контейнер (container) , который содержит 3 блока (logo, nav и text-area). Контейнер буду использовать для позиционирования блоков. По задумке, вариантов контекста блока (text-area) будет несколько и на разных страничках буду их подключать по текущему смыслу к контейнеру, путем микширования, если я правильно понимаю. Но, я где-то должен описать все варианты структур данного блока, пока не имею ввиду его оформление, сам контекст.

Вопрос: не могу понять, в index.bemjson.js описать блок могу, текущую разметку 1 варианта получу, но где описать остальные варианты структуры этого блока?

Добрый день! Не понимаю почему в первом случае микс успешно работает, а если добавлять условие через модификатор, то уже нет. Что не так делаю?

https://clck.ru/AsfzY

Добрый день! Задумала сделать обобщенный блок меню, с различными модификаторами, меняющими внешний вид как блока, так и элементов в нем. Наткнулась на ситуацию, когда больший вес для шаблонизатора имеет последнее указанное правило и он не хочет проверять оба сразу. Как быть?

https://goo.gl/wza4HK

Добрый день! Начинаю изучать БЭМ (методологию и инструменты). В процессе практики возник следующий вопрос. Как на последний элемент в наборе навесить класс. Есть меню с пунктами. Для последнего пункта нужен класс для особого оформления. Как это сделать в шаблонизаторе разобраться не могу. Подскажите, пожалуйста!

https://jsfiddle.net/8a6j3njg/

Добрый день! Столкнулся с тем, что добавление модификатора type: 'password' никак не отражается на разметке блока. Имею такой bemjson:

{
    block: 'input',
    mods: {width: 'available', 'has-clear': true, type: 'password'},
    name: 'password', 
    placeholder: 'Password',
    tabIndex: 2
}

На выходе получаю такой html:

<span class="input input_width_available input_has-clear input_type_password i-bem input_js_inited" data-bem="{&quot;input&quot;:{}}">
    <span class="input__box">
        <input class="input__control i-bem input__control_js_inited" name="password" tabindex="2" placeholder="Password">
    </span>
</span>

Полез смотреть в код элемента 'control' в файле input__control.bemhtml.js, и там вижу следующий код:

block('input').elem('control')(
    tag()('input'),

    addAttrs()(function() {
        var input = this._input,
            attrs = {
                id : input.id,
                name : input.name,
                value : input.val,
                maxlength : input.maxLength,
                tabindex : input.tabIndex,
                placeholder : input.placeholder
            };

        input.autocomplete === false && (attrs.autocomplete = 'off');
        this.mods.disabled && (attrs.disabled = 'disabled');

        return attrs;
    })
);

Я полагал, что код, написанный в input_type_password.bemhtml.js

block('input').mod('type', 'password').elem('control').attrs()(function() {
    return this.extend(applyNext(), { type : 'password' });
});

докинет в контекст выполнения шаблона поле 'type' со значением 'password', и это поле мы дернем в шаблоне элемента 'control' как-нибудь так:

attrs = {
    ...
    type: this.type
}

Объясните, пожалуйста, обращение к этому свойству просто забыли написать или я неправильно понимаю процесс работы шаблонизатора? И если второе, то как мне сделать так, чтобы этот атрибут всё-таки попал в разметку?

Добрый! Есть таск

function less() {
  return bundler('*.bundles/*')
    .pipe(builder({
      less: bundle => {
        bundle.src('less')
          .pipe(gulpLess())
          .pipe(postcss([
            postcssImport(),
            postcssUrl({ url: 'inline' }),
            autoprefixer({browsers: prefixes}),
            postcssReporter()
          ]))
          .pipe(concat(bundle.name + '.min.css'))
          .pipe(gulpif(isProd, csso()))
      }
    }))
    .on('error', console.error)
    .pipe(debug())
    .pipe(gulp.dest(file => path.dirname(file.path)));
}

Крашится

TypeError: Cannot read property 'block' of undefined
    at data.forEach.dep (/home/arsen/dev/nodeprojects/njs_nian/node_modules/@bem/deps/lib/formats/deps.js/parser.js:29:37)
    at Array.forEach (native)
    at depsData.forEach.record (/home/arsen/dev/nodeprojects/njs_nian/node_modules/@bem/deps/lib/formats/deps.js/parser.js:27:14)
    at Array.forEach (native)
    at parse (/home/arsen/dev/nodeprojects/njs_nian/node_modules/@bem/deps/lib/formats/deps.js/parser.js:23:14)
    at Promise (/home/arsen/dev/nodeprojects/njs_nian/node_modules/@bem/deps/lib/parse.js:11:25)
    at /home/arsen/dev/nodeprojects/njs_nian/node_modules/@bem/deps/lib/parse.js:9:16

Есть каталог common.blocks в корне, там button, внутри .js файл, .browser.js, .less, .deps.js и Page, в нем те же технологии

Билдер

const builder = Builder({
  levels: [
    'common.blocks',
    'desktop.blocks'
  ],
  techMap: {
    bemhtml: ['bemhtml.js'],
    js: ['js'],
    less: ['less']
  }
});

Что я делаю не так? Хотелось бы поподробнее узнать о библиотеках

const Builder = require('gulp-bem-bundle-builder');
const bundler = require('gulp-bem-bundler-fs');

И можно ли с помощью них полноценно собирать БЭМ проекты на gulp?

Добрый день. Подскажите:

  1. как подружить bem и golang?
  2. как правильно передавать данные с сервера на клиента?

Очень понравилась идея независимых блоков, но возник ряд вопросв: 1) Мне нравится Django, я хочу применять БЭМ в проектах на этом фреймворке, натыкался на пост https://ru.bem.info/forum/483/ , есть ли способы это сделать проще, уже 2017 год.. 2) Непонятно, как организовать взаимодействие компонентов, типа нажал на кнопку "Купить", отреагировала корзина.. Смотрел вебинары, советуют через посредника делать, в общем блоке, но если я перенесу кнопку, и она окажется вне этого посредника, все может поломаться.. 3) Куда складывать библиотеки, типа всяких jqtree и прочих? Как отдельный блок? 4) Как обстоят дела с Angular2? 5) Как сделать так, чтобы с каждой динамической страницей Django, полученной через рендер шаблона, на клиент отдавалась статика, необходимая только для действительно необходимых компонентов Спасибо.

Всем привет. К примеру есть такой вот bemjson

{
    block: 'b1',
    content: [
        {
            block: 'b2',
            mix: {block: 'b1', elem: 'e1'},
            content: [
                {
                    elem: 'e1',
                    content: 'title'
                },
                {
                    elem: 'e2',
                    content: 'description'
                }
            ]
        },
        {
            block: 'b2',
            mix: {block: 'b1', elem: 'e1'},
            content: [
                {
                    elem: 'e1',
                    content: 'title'
                },
                {
                    elem: 'e2',
                    content: 'description'
                }
            ]
        }
    ]
}
Допустим блок b1 это какой-то список, b2 это элемент списка который может использоваться еще где-то на странице но не в виде элемента списка а просто в виде блока. Но вот дилемма, если примиксовать к b2 элемент блока b1e1 и задать ему bemhtml в котором бы говорилось что b1e1 должен иметь тег li то этот код не срабатывает. Напрямую в bemjson писать не хочется tag. Пробовал прописывать всякого рода зависимости, блока b2 от блока b1, блока b2 от элемента e1 блока b1 и блока b1 от элемента e1. Как будет правильно поступать в данной ситуации?

Уважаемые бэмчане,

не сочтите за оффтоп, но хотелось бы услышать ваше мнение. Angular2 и Vue, например, имитируют scoped css через присваивание уникального атрибута всем тегам и добавление его же к селекторам в css. Возникла идея сделать эти трансформации приближенными к бэм методологии. Представьте, что у нашей компоненты шаблон и стили такие:

<section class='product'>
    <header class='title'>
        Foo 
        <span class='hint'></span>
    </header>    
</section>

.product { /* ... */ }
.product .title { /* ... */ }
.product .title .hint { /* ... */ }

Тогда пропустив шаблон и стили через наш преобразователь получим следующее:

<section class='product_ABC product'>
    <header class='product_ABC__title title'>
        Foo 
        <span class='product_ABC__title_hint hint'></span>
    </header>    
</section>
.product_ABC { /* ... */ }
.product_ABC__title { /* ... */ }
.product_ABC__title_hint { /* ... */ }

Принцип прост, по возможности заменить и сделать стили плоскими. Сохранить изначальный селектор Элементов и пройтись по шаблону Добавив новые имена классов. Изначально селекторы всегда вида: BLOCK(…modifiers) ELEMENT(…modifiers) … . Модификаторы мы не изменяем. В следующем примере селектор плоским сделать мы не можем, так как он зависит от состояния родителя:

.product.active .title {}

.product_ABC.active .product_ABC__title { }

Плюсы данного подхода:

  • Разработка блока/компоненты не зависит от инструментария, как Css Modules, например
  • Все стили после сборки под селекторами с уникальной солью - нет коллизий
  • Все селекторы максимально плоские - хорошо для производительности
  • Минимальная специфичность селекторов - хорошо для переопределения
  • Все изначальные классы в html остаются не тронуты - если вдруг нам нужно искать элементы из js, добавлять модификаторы, или определять новые стили по этим селекторам.

Недостатки:

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

Дополнительно:

  • Можно от соли отказаться, и гарантировать уникальность блоков самому, тогда селекторы всегда будут детерминированны.
  • Можно ввести некоторые соглашения об именах на случай каких либо "edge case".
  • Можно от имени блока отказаться и генерировать его другим способом, а в стилях использовать ":host" для его стилизации.

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