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

Адепты bem-components, подскажите, пожалуйста: в попап select'а поместил ещё input (для поиска по элементам menu). Что нужно переопределить, чтобы весь функционал сохранился, кроме закрытия попапа по клику на этот input? P.S. Нутром чую, что дело в _onDocPointerPress и _isEventInPopup.

https://github.com/bem/bem-components/blob/v6.0.0/common.blocks/select/select.js#L247-L268

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

Делаю примерно так:

var lazyBlock = this.findChildBlock(SomeLazyBlock);
this._events(lazyBlock).on('someEvent', this.onSomeEvent);

Но во время findChildBlock оно уже автоматически инициализируется, так?

Существует ли способ сохранить неинициализированное состояние и при этом реагировать на события?

Не могу разобраться по описанию в разделе Декларация блока, как примешивать блок (отдельный специально подготовленный миксин?) к элементу или модификатору. Ткните меня, пож., в примеры использования declMixin? В bem-core, bem-components что-то не вижу ничего.

Что-то я сломался на этом месте.

Вот есть у меня, скажем, блок input из bem-components. К нему примиксован элемент моего блока. Скажем, my-block__control.

{
    block: 'input',
    mix: { block: 'my-block', elem: 'control }
}

Из my-block легко получить этот input: const input = this.findChildElem('control').findMixedBlock(Input).

Но можно ли аналогичным образом теперь из input получить элемент control? Например, input'ов много, я вешаю обработчик onchange на них, и этот обработчик должен взаимодействовать с миксованным элементом control. Каким-то из методов поиска можно к нему обратиться? Хочется что-то вроде такого: input.findMixed*({ block: 'my-block', elem: 'control' })

Или только заранее формировать соответствия блоков и элементов и по ним уже ориентироваться?

Есть примерно следующая структура вложенных блоков:

{
    block : 'box',
    mods : {
        root : true,
        id : 'layoutBox',
    },
    content : {
        block : 'box',
        mods : {
            id : 'appBox',
        },
        // Имеем некоторую вложенность блоков `box`: layoutBox->appBox->ReportLayout->Report->ReportDisplay; Т.е.:
        // ...
        content : {
            block : 'ReportDisplay',
            mix : {
                block : 'box',
                mods : {
                    id : 'ReportDisplay',
                },
            },
            content : {
                // Some content...
            },
        },
    },
}

При удалении блока ReportDisplay (при помощи BEMDOM.destruct(ReportDisplay.domElem)) по цепочке parentNode (в jquery) до верхнего уровня (layoutBox) всплывает событие на delMod('js'), в результате чего блок отписывается от событий, зарегистрированных на window (ранее подписываемся так: this._domEvents(BEMDOM.win).on('resize',...)).

Стек выглядит примерно так:

    (i-bem-dom__events.js:155) this._storage[e] = null; // e='resize' -- Это собственно удаление подписанного события в _unbindByEvent.
    // ...
    (i-bem-dom__events.js:139) objects.each(this._storage, this._unbindByEvent, this); // this._storage={resize:{uniq161:{...}}}
    (i-bem-dom__events.js:253) params.bindToArbitraryDomElem && ctxStorage[storageKey] &&
                            ctxStorage[storageKey].un();
    (i-bem-dom__events_type_bem.js:85) fn.call(fnCtx || instance, originalEvent, data); // fnCtx=null, instance=layoutBox, originalEvent={bemTarget:ctx,data:undefined,target:ctx,type:'modchange'_isDefaultPrevented:false_isPropagationStopped:false}, data={modName:'js', modVal:'',oldModVal:'inited'}
    (jquery:5205) ret = ( ( jQuery.event.special[ handleObj.origType ] || {} ).handle ||     //  handleObj.origType='__bem__box_js_'
                        handleObj.handler ).apply( matched.elem, args ); //  matched.elem=layoutBox.domElem[0], args=[jQuery.Event{type:'__bem__box_js_'},{modName:'js', modVal:'',oldModVal:'inited'},{fns:{uniq151:true},propagationStoppedDomNode:null},{bemTarget:ctx,data:undefined,target:ctx,type:'modchange'_isDefaultPrevented:false_isPropagationStopped:false}]
    (jquery.js:5014) jQuery.event.dispatch.apply( elem, arguments ); // elem=layoutBox.domElem[0], ...
    (jquery:8201) handle.apply( cur, data ); // cur=layoutBox.domElem[0], data=[jQuery.Event{type:'__bem__box_js_'},{modName:'js', modVal:'',oldModVal:'inited'},{fns:{uniq151:true},propagationStoppedDomNode:null},{bemTarget:ctx,data:undefined,target:ctx,type:'modchange'_isDefaultPrevented:false_isPropagationStopped:false}]
    (jquery.js:8262) jQuery.event.trigger(type, data, this); // type='__bem__box_js_', data=[{modName:'js', modVal:'',oldModVal:'inited'},{fns:{uniq151:true},propagationStoppedDomNode:null},{bemTarget:ctx,data:undefined,target:ctx,type:'modchange'_isDefaultPrevented:false_isPropagationStopped:false}], this=ctx
    (jquery.js:8269) ctx.domElem.trigger(event, [data, { fns : {}, propagationStoppedDomNode : null }, originalEvent]); // event='__bem__box_js_', data={modName:'js',modVal:'',oldModVal:'inited'}, originalEvent:{bemTarget:ctx,data:undefined,target:ctx,type:'modchange'_isDefaultPrevented:false_isPropagationStopped:false}
    // ...
    (i-bem-dom.js:676) bemEvents.emit(this, e, data); // e={modName:'js',modVal:''}, data={modName:'js', modVal:'',oldModVal:'inited'}
    (i-bem-dom.js:733) this._emit({ modName : 'js', modVal : '' }, eventData); // eventData={modName:'js',modVal:'',oldModVal:'inited'}
    (i-bem.vanilla.js:324) this._afterSetMod('js', '', 'inited');
    (i-bem.vanilla.js:382) this.setMod('js', '');
    (i-bem.vanilla.js:247) this.delMod('js');
    (i-bem-dom.js:244) entity._delInitedMod();
    (i-bem-dom.js:1004) removeDomNodeFromEntity(entity, domNode);
    // ...
    (i-bem-dom.js:1029) this._destruct(ctx, excludeSelf, true);
    BEMDOM.destruct(ReportDisplay.domElem);

Полностью слепок вершины стека из DevTools, от destruct до _unbindByEvent).

_unbindByEvent (i-bem-dom__events.js:155)
each (objects.vanilla.js:56)
un (i-bem-dom__events.js:139)
(anonymous) (i-bem-dom__events.js:254)
inherit._createEventManager (i-bem-dom__events_type_bem.js:85)
dispatch (jquery.js:5206)
jQuery.event.add.elemData.handle (jquery.js:5014)
trigger (jquery.js:8201)
(anonymous) (jquery.js:8269)
each (jquery.js:362)
each (jquery.js:157)
trigger (jquery.js:8268)
emit (i-bem-dom__events_type_bem.js:119)
_emit (i-bem-dom.js:676)
_afterSetMod (i-bem-dom.js:733)
setMod (i-bem.vanilla.js:324)
delMod (i-bem.vanilla.js:382)
_delInitedMod (i-bem.vanilla.js:247)
removeDomNodeFromEntity (i-bem-dom.js:244)
(anonymous) (i-bem-dom.js:1004)
each (objects.vanilla.js:56)
(anonymous) (i-bem-dom.js:1000)
each (jquery.js:362)
each (jquery.js:157)
_destruct (i-bem-dom.js:993)
destruct (i-bem-dom.js:1029)

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

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

Хелп? Что это может быть?

Версии библиотек:

  • bem-core@4.2.1
  • jquery@3.2.1

Всем доброго времени суток. Появилась необходимость доопределить js для блока Attach. А именно, при выборе картинки рисовать preview аватара. Код:

/* desktop.blocks/attach/attach.js */
modules.define('attach', function(provide, Attach) {
    provide(Attach.decl({ modName: 'type', modVal: 'avatar' }, {
        onSetMod: {
            'js': {
                'inited': function() {
                    this.__base.apply(this, arguments);
                    console.log('attach_type_avatar inited...');
                }
            }
        },
        _updateFileElem: function() {
            this.__base.apply(this, arguments);
            console.log('_updateFileElem');
            //Do something...
        },
        _clear: function() {
            this.__base.apply(this, arguments);
            console.log('_clear');
            //Do something...
        }
    }));
});

Методы срабатывают, "Супер-колл" работает, Функциональность блока не ломается, только после выбора файла, всплывает ошибка:

Uncaught TypeError: Cannot read property '_emitChange' of undefined at Object._onChange (profile_settings.min.js:7695) at n.fn.init. (profile_settings.min.js:1643) at Function._liveClassTrigger (profile_settings.min.js:1618) at HTMLBodyElement.f (jquery.min.js:2) at HTMLBodyElement.dispatch (jquery.min.js:3) at HTMLBodyElement.r.handle (jquery.min.js:3)

Конкретно в этом месте:

_onChange : function() {
        this.elem('no-file').detach();
        this.getVal()?
            this
                ._updateFileElem()
                ._emitChange() :
            this._clear();
}

Как побороть ошибку? Доопределяю кнопки таким же образом - нет никаких ошибок.

Имеем input[type=file] на котором событие change (сделано по БЭМ, естествен) Хотим: загрузить данный файл с помощью AJAX еще до сабмита формы.

inputFiles._domEvents().on('change', function(e) {
  console.log(e);  // Есть bemTarget._val который  содержит путь к файлу, но console.log(e.bemTarget._val) возвращает пустую строку
  console.log(e.files);  // undefined
});
// inputFiles = findChildBlock({ block: Input, modName: 'type', modVal: 'file' })

Подскажите, как это реализовать?

Добрый день!

Каскадные select'ы встречаются довольно часто в разных формах. Законченного решения мне найти не удалось, ни на форуме ни в документации. Помогите, пожалуйста разобраться на конкретном примере. Как реализовать каскадные блоки select в технологии js по следующему сценарию:

  1. Допустим, мы имеем 3 select-блока с модификатором disabled (до инициализации), например: country, city, street.

  2. После автоматической (domReady) инициализации, первый select-блок (country) выполняет обращение к API, получает данные в json-формате, заполняется пунктами, на основании полученного массива данных и в случае успеха, с первого блока снимается модификатор disabled.

  3. Выбираем пункт country, получаем значение выбранного пункта, формируем запрос к API, получаем ответ, заполняем пункты второго блока (city), снимаем модификатор disabled со второго блока.

  4. Выбираем пункт city, получаем значение выбранного пункта, формируем запрос к API, получаем ответ, заполняем пункты третьего блока (street), снимаем модификатор disabled со третьего блока.

  5. При изменении значения, для нижестоящих по иерархии (country - city - street) блоков, процедура повторяется.

Заранее спасибо!

Суть такова:

  • есть блок spin, у которого есть методы show и hide
  • есть родитель, который хочет управлять этим блоком Как из родительского блока получить доступ к методам spin?

У блока есть множество одноименных элементов, клик по которым необходимо обрабатывать. Подписываюсь на клик так: this._domEvents("item").on("click", this._onClick);

В методе _onClick необходимо получить бэм-элемент, по которому был клик. Как правильно это сделать средствами БЭМ и возможно ли вообще такое? Пока сделал костыльное решение, которое конечно работает, но не кажется корректным:

_onClick: function(e) {
    var elems = this._elems("item");
    var elem;
    for (var i = 0; i < elems.size(); i++) {
        if(elems.get(i).domElem[0] === e.currentTarget) {
            elem = elems.get(i);
            break;
        }
    }
}

http://take.ms/3MHjg - как тут создать bem-объект из jQuery - объекта? http://take.ms/m2Jly - как можно найти ближайшего родителя, parent in jQuery?

Какие причины могут быть для того, чтобы блок не инициализировался? В bemhtml указал block('name').js()(true);, добавился класс i-bem и атрибут data-bem, но вот класса name_js_inited нет и соответственно JS не выполняется.

Поиска помощи и фидбека пост.

Работа с формами, обрабатываемыми на клиенте, начала доставлять немало боли, особенно на фоне аналогичного опыта с Angular/Vue.js.

Появилась мысль облегчить решение таких задач. Основная идея была в том, чтобы сделать подход к формам более декларативным. Упростить добавление типового контрола в форму. Сделать возможность легко мапить форму на неплоские модели данных. Ну и это должно более-менее безболезненно встраиваться в существующее приложение (что-нибудь вроде bem-core + bem-components) без тотального переписывания всего и вся.

Прикручивание того же Vue.js в качестве дополнения, (если не замены) i-bem выглядело прикольно, но как-то не зашло, ибо появляются намёки на неконсистентность методологий.

Оставалось одно — свой велосипед. Важное требование — максимально простое решение. И никаких angular-like дайджестов. Идея с сеттерами во Vue ок, но лень всё это писать, можно проще.

В итоге пришёл даже не к какой-то программной единице, решающей проблемы, а, скорее, к подходу к их решению.

Идея в том, чтобы выделить три очевидных составляющих:

  • Контроллер состояний.
  • «Форма».
  • Компоненты «формы».

Контроллер состояний хранит стейты и общается с компонентами. Компоненты — это блоки, непосредственно работающие с данными. Инпут — компонент. Он может и отражать изменения данных, и сам их инициировать. Блок с текстом также может быть компонентом, отображающим какую-то часть стейта. Форма описывает стейт и привязывает компоненты к нему. Причём привязывается на уровне BEMHTML, пробрасывая в компонент имя стейта и путь к нужным данным в нём. Никаких поисков компонентов для установки значений или подписки на их события в форме нет.

В качестве шины событий с данными — каналы (events__channels). Именно каналы. У каждого стейта свой канал. В каждом канале два типа событий: read и write. В идеале компоненты подписываются на первое и генерируют второе. Контроллер состояний — наоборот. В данных события летит путь (dot-separated), по которому произошло изменение и новое значение. Компонент подписывается на все read-события своего стейта. Он сам решает, на какие реагировать, а какие дропать (по пути изменения в стейте). Два типа событий заметно всё упрощают за счёт того, что в общем случае компоненты не общаются между собой. Всё общение между компонентами происходит через контроллер стейтов.

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

https://github.com/gwer/e-state

В example.blocks есть форма (my-form), обёртка для инпутов (my-input) и составной контрол (editable-list). В данном случае составной контрол сделан проксирующим: не имеет собственного стейта и лишь правильно привязывает свои контролы к стейту внешней формы. Но можно писать и аналогичные контролы с собственным стейтом. Единственное, что следует помнить — если форма имеет несколько экземпляров, привязанных к разным стейтам, имя стейта для такой формы должно быть уникально для каждого экземпляра (например, генерить на основе this.generateId()).

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

Клиентский JS формы:

eState.init(this.stateName, {
    f1: '1111',
    f2: '2222',
    nested: {
        first: '',
        second: '',
    }
})

Разметка формы:

{
    block: 'my-input',
    js: {
        stateName,
        model: 'f1',
    },
},
{
    block: 'my-input',
    js: {
        stateName,
        model: 'f2',
    },
},
{
    block: 'my-input',
    js: {
        stateName,
        model: 'f2',
    },
},
{
    block: 'my-input',
    js: {
        stateName,
        model: 'nested.first',
    },
},
{
    block: 'my-input',
    js: {
        stateName,
        model: 'nested.second',
    },
},

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

Написать аналогичные обёртки для основных контролов — не должно быть проблемой. Компоненты могут быть более сложными. Можно завязывать их на несколько путей в стейте и вешать на эти пути любую логику. Сейчас примеры представляют собой эдакий аналог ng-model, но можно без проблем сделать, например, аналоги ng-bind, ng-show/ng-hide.

Так вот, к чему всё это. Наверняка кто-то уже подходил к этой проблеме. Есть ли похожие подходы или решения? Какие незамеченные мной проблемы есть у описанного подхода? Может, есть идеи, как это можно улучшить?

Привет, уважаемые дамы и господа! дайте совет где я не прав

modules.define('form', ['i-bem-dom'], function(provide, bemDom) {

provide(bemDom.declBlock(this.name, {
    onSetMod: {
        js: {
            inited: function() {
            }
        }
    }
},{
    getVal: function(){
        return this.domElem.serialize();
    }
}));

});

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

modules.define('post', ['i-bem-dom', 'form'], function(provide, bemDom, Form) {

provide(bemDom.declBlock(this.name, {
    onSetMod: {
        js: {
            inited: function() {
               var data = Form.getVal();
            }
        }
    }
}));

});

и вопрос номер два, можно ли как то искать блоки findChildBlock('input') как то так или нет обязательно требовать блок как модуль и его указывать ?

спасибо за ответы, не судите строго :%

Всем привет!! Подскажите существует ли список где можно увидеть все методы и события блока i-bem и i-bem-dom? Тяжело перелопачивать руководство, и крайне не удобно.

Добрый вечер!

Начал проект на свежей версии bem-core. Предыдущая была - 3.2.0, в связи с этим возникло много вопросов, и этот - самый проблемный. У меня прекрасно ищутся элементы:

this.findChildElem({elem: 'row', modName: 'error', modVal: true})

Но вот при попытке найти аналогичным образом блок

this.findChildBlock({block: 'input', modName: 'email', modVal: true})

Мне валится ошибка: Block must be a class or description (block, modName, modVal) of the block to find.

На странице https://ru.bem.info/platform/i-bem/dom/ пример вообще достаточно странный:

modules.define('attach', ['i-bem-dom', 'button'], function(provide, bemDom, Button) {

provide(bemDom.declBlock(this.name, {
    onSetMod: {
        'js': {
            'inited' : function(modName, modVal) {
                this._button = this.findChildBlock(Button);
            }
        }
    }
}));

});

Из него вообще не понятно, как мне найти внутри блока 'attach', например, блок 'button' такого вида:

{ block: 'button', modName: 'foo', modVal: 'bar' }

Подскажите, пожалуйста, что я делаю не так?

Здравствуйте. В стандартной сборке bem уже есть jquery, на данный момент там версия 3.1.0. Провайдим, пользуемся, всё отлично, спасибо. НО: Вопрос следующего характера: как "bem-правильно" выплюнуть jquery в глоб. пространство, чтобы jquery было доступно из консоли в браузере ( сейчас ни jQuery, ни $ не видит) ?

Спасибо!

Добрый вечер! Помогите, пожалуйста, со следующей проблемой. Имею такой bemjson:

module.exports = {
    block: 'page',
    title: 'Authorization',
    head : [
        { elem : 'meta', attrs : { name : 'description', content : '' } },
        { elem : 'css', url : 'index/index.css' }
    ],
    scripts: [{ elem : 'js', url : 'index/index.js' }],
    content: {
        block: 'wrapper',
        content: {
            block: 'auth'
        }
    }
}

Вот такой шаблон:

block('auth')(
    js()(true),

    content()(() => {
        return 'Hello, world!'
    })
)

И вот такое вот js объявление блока:

modules.define('auth', ['i-bem__dom'], function(provide, BEMDOM) {
    provide(BEMDOM.decl(
        this.name,
        {
            onSetMod: {
                'js': {
                    'inited': function() {
                        console.log('auth inited');
                    }
                }
            }
        }
    ))
});

Не происходит инициализация блока 'auth'. Не могу понять, где ошибка: имя блока в шаблоне и декларации совпадают, js в шаблоне включен, в зависимостях page'а автоматическая инициализация тоже прописана. В результирующий js декларация попала, js на страницу - тоже. В консоль никаких ошибок не валится. Класс i-bem в html-разметке тоже присутствует:

<div class="auth i-bem" data-bem="{&quot;auth&quot;:{}}">Hello, world!</div>

Есть ли возможно получить js файл с фреймворком i-bem.js ? Гуглил, искал, но не нашел. Только какие-то исходники разделенные на атомы или наоборот смешанные с js компонентов и так далее, а нужен файлик только с i-bem (не последней версии, нужен тот, где обращение к элементам идет так: this.findBlockInside('block');)

Добрый день! В i-bem.js можно обратиться к блоку в трех направлениях - родитель, дочерний, на себе. А как можно обратиться к соседнему (братскому) блоку в i-bem.js?? Пробовал через общего родителя, не получается. Видимо не правильно обращаюсь, либо всплытие только линейное, и братский блок не отлавливает событие сплывшее на родителе. Пожалуйста помогите разобраться

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

не сочтите за оффтоп, но хотелось бы услышать ваше мнение. 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" для его стилизации.

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

Добрый день! Есть такая конструкция:

<div class="block1">
<div  class="block1__element i-bem" data-bem='{"block1__element":{"id":1}}'>содержимое первого элемента</div>
<div  class="block1__element i-bem" data-bem='{"block1__element":{"id":2}}'>содержимое второго элемента</div>
<div  class="block1__element i-bem" data-bem='{"block1__element":{"id":3}}'>содержимое третьего элемента</div>
</div>

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

Видится мне это так, но не уверен:

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

  • определить высоту активного элемента(будем считать что модификатор ему присвоили как активный те он достиг верхней границы)

  • получить params.id только для элемента с активным модификатором.

Не могу понять, как правильно найти блок content.

Имеется div:

<body>
 <div class="content i-bem content_js_inited" data-bem="{&quot;content&quot;:{}}"><div class="content__wrap"></div></div>
<div class="modal modal_theme_islands modal_has-close popup i-bem modal_js_inited popup_js_inited modal_has-animation" data-bem="{&quot;modal&quot;:{},&quot;popup&quot;:{&quot;zIndexGroupLevel&quot;:20}}" role="dialog" style="z-index: 21001;" aria-hidden="true"><div class="modal__table"><div class="modal__cell"><div class="modal__content"><div class="info_modal info_modal_size_s"><div class="info_modal__content">Пароль неверный</div><div class="modal_button modal__close"><button class="button button_theme_islands button_type_app app i-bem app_js_inited button_js_inited" data-bem="{&quot;button&quot;:{},&quot;app&quot;:{&quot;controller&quot;:&quot;zfclogin&quot;,&quot;action&quot;:&quot;auth&quot;}}" role="button"><span class="button__text">Ок</span></button></div></div></div></div></div></div>
</body>

То есть, у нас вызвалось модальное окно, в нём есть метод: modal_has-close и внутри модалки, есть кнопка - button, к которой примексован блок 'app'.

При нажатии, выполняется закрытие окна и по сути, выполняется метод app:

modules.define(
    'app',
    ['i-bem__dom', 'location', 'jquery', 'control', 'CryptoJSAes'],

    function(provide, BEMDOM, location, $, Control, CryptoJSAes) {

        provide(BEMDOM.decl({ block : this.name, baseBlock : Control }, {
            onSetMod: {
                'js' : {
                    'inited' : function() {
                        this._content = this.findBlockOutside('content');
                        this.bindTo('pointerclick', this._onAppLoad);
                    }
                }
            },

            _onAppLoad: function() {
              this._content._onGetLoad({'loader' : true});
            },
        }));
    }
);

То есть, при клике на примексованный app к кнопке, выполняется функция _onAppLoad. В inited ищеться блок 'content' и выполняется функция _onGetLoad. findBlockOutside, не выполниться, в сферу того, что 'content' изнутри блока app, но изнутри app у нас modal только. Идёт вопрос, как найти блок 'content' и выполнить исходя из найденного блока - функцию?

Добрый день, столкнулся с такой проблемой:

Имеется блок form

<form class="form form_type_register info-modal i-bem form_js_inited info-modal_js_inited" data-bem="{&quot;form&quot;:{&quot;controller&quot;:&quot;zfclogin&quot;,&quot;action&quot;:&quot;register&quot;},&quot;info-modal&quot;:{}}">
    <div class="form__content">
        <div class="form__label">
            <div class="form__label_text">Почта:</div>
            <div class="form__label_input form__label_email">
                <span class="input input_theme_islands input_size_m input_type_text input_width_available input_has-error i-bem input_js_inited" data-bem="{&quot;input&quot;:{}}">
                    <div class="input__box">
                        <input class="input__control" name="email" autocomplete="off" type="text">
                        <span class="input__icon"></span>
                    </div>
                </span>
            </div>
        </div>
        <div class="form__label">
            <div class="form__label_text">Пароль:</div>
            <div class="form__label_input">
                <span class="input input_theme_islands input_size_m input_type_password input_width_available input_has-error i-bem input_js_inited" data-bem="{&quot;input&quot;:{}}">
                    <div class="input__box">
                        <input class="input__control" name="password" autocomplete="off" type="password">
                        <span class="input__icon"></span>
                    </div>
                </span>
            </div>
        </div>
        <div class="form__label">
            <div class="form__label_text">Повтор:</div>
            <div class="form__label_input">
                <span class="input input_theme_islands input_size_m input_type_password input_width_available input_has-error i-bem input_js_inited" data-bem="{&quot;input&quot;:{}}">
                    <div class="input__box">
                        <input class="input__control" name="passwordVerify" autocomplete="off" type="password">
                        <span class="input__icon"></span>
                    </div>
                </span>
            </div>
        </div>
        <div class="form__button">
            <button class="button button_theme_islands button_size_l button_type_submit button_view_dark button_width_available button__control i-bem" role="button" type="submit" data-bem="{&quot;button&quot;:{}}">
                <div class="button__text">Завершить</div>
            </button>
        </div>
    </div>
</form>

С набором label и input.

Так вот, на кнопку submit навешивается дейтсвие bindTo('submit') и выполнятся функция:

_onGetRegisterMethod:function() {
  var data = {"email":"error","password":"error"}
  for(var data in json) {
                    if(this.elem('label_'+data)) {
                        this.elem('label_'+data).addClass('form_error');
                    }
                }
}

То есть, в

<div class="form__label_input form__label_email">...</div>

добавляется класс form_error. Вопрос в том, как именно в блок input, где элемент __icon добавить к примеру, текст, чтобы имеено в нужной блоке form__label_input form__label_n был добавлен текст в блок input__icon.

раньше было так:

this.block = this.findBlockInside('block');

в bem4 приходится делать так:

this.block = this.findChildBlock(bemDom.declBlock('block', {}));

Можно ли сделать так же просто, как было раньше?

Что-то не могу сделать такую простую вещь, как забиндиться на onChange (а он есть?) radio-group из bem-components и получить значение?

Суть следующая: при изменении значения в группе радиокнопок b1__options нужно проверять значение, и если оно, например, равно 3, то делаем setMod(disabled) элементу b1__elem.

Собственно, застрял на этапе получения значения getVal().

Вот это никак не реагирует:

this._events(this._radioGroup).on('change', this._radioChange);
this._events(this._radioGroup).on('click', this._radioClick);
this._domEvents(this._radioGroup).on('change', this._radioChangeDom);

Отсюда пара вопросов:

  1. Есть ли change?
  2. Почему не происходит BEM-событие?

А при DOM-событии клика вылетает ошибка (Uncaught TypeError: this._radioGroup.getValue is not a function):

this._domEvents(this._radioGroup).on('click', this._radioClickDom);

Глянуть можно тут: https://github.com/rteamx/project-stub/commit/eed20a6634a587c127d8ae8f39f56cac882123dd

Ребята, помогите собрать JS-блока.

Цель: 1) Получить реализацию блока в технологии JS 2) Получить минимум знаний по JS в методологии БЭМ, для дальнейшего +/-самообучения

Исходные данные:

  • Блок sitemap, элемент button__icon_close
  • Блок button с миксом menu__button, блок расположен вне блока sitemap
  • Знание JS - ноль.
  • Знание ООП - поверхностное на уровне новичек, язык с#
  • Структура файлов:

BEMJSON:

{
    block: 'sitemap',
    js : true,
    content: [
            {
                block: 'button',
                mix : { block : 'sitemap', elem : 'button' },
                attrs : { title : 'Закрыть меню' },
                icon: {
                    elem: 'icon',
                    tag: 'span',
                    elemMods: {close: true}
                }
            } 
    ]
},
{
    block: 'button',
    mix: {block: 'menu', elem: 'button', theme: 'menu'},
    url: '#',
    title: 'Открыть меню сайта',
    content: 'Меню',
    tabIndex: 2
}

Поиск решения:

Первое что попробовал - вывести лог при клике.

modules.define(
    'sitemap',
    ['i-bem-dom'],
    function(provide, BEMDOM) {

    provide(BEMDOM.decl(this.name, {
        onSetMod : {
            js : {
                inited : function () {
                    this.bindTo('click', function () {
                        console.log('click');
                    })
                }
            }
        }
    }));
});

Консоль браузера сразу заругалась:

jQuery.Deferred exception: i.decl is not a function TypeError: i.decl is not a function
    at Object.<anonymous> (http://localhost:63342/osipbove-bem-project/desktop.bundles/index/index.min.js:35:58)
    at http://localhost:63342/osipbove-bem-project/desktop.bundles/index/index.min.js:1:1662
    at c (http://localhost:63342/osipbove-bem-project/desktop.bundles/index/index.min.js:1:1009)
    at R (http://localhost:63342/osipbove-bem-project/desktop.bundles/index/index.min.js:1:1792)
    at http://localhost:63342/osipbove-bem-project/desktop.bundles/index/index.min.js:1:1641
    at HTMLDocument.<anonymous> (http://localhost:63342/osipbove-bem-project/desktop.bundles/index/index.min.js:2:8353)
    at j (https://yastatic.net/jquery/3.1.0/jquery.min.js:2:29568)
    at k (https://yastatic.net/jquery/3.1.0/jquery.min.js:2:29882) undefined
r.Deferred.exceptionHook @ jquery.min.js:2
k @ jquery.min.js:2
jquery.min.js:2 Uncaught TypeError: i.decl is not a function
    at Object.<anonymous> (index.min.js:35)
    at index.min.js:1
    at c (index.min.js:1)
    at R (index.min.js:1)
    at index.min.js:1
    at HTMLDocument.<anonymous> (index.min.js:2)
    at j (jquery.min.js:2)
    at k (jquery.min.js:2)

в шапке модуля меняю i-bem-dom на i-bem__dom, консоль без ошибок, как и без ожидаемого console.log

Пока в ступоре, и вопросов немного: 1) В чем может быть ошибка, этого простого кода? 2) Как подписаться на событие click блока button, который вне блока sitemap?

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

Если просто делать

bemDom.prepend(
    ctx,
    activeSlide.domElem
 );

то при смене модификатора у этого клона, меняется модификатор и у блока с которого происходило клонирование))

Доброго вечера! После долгих мучений, закончил первый сверстанный проект на связке gulp+bem. Встал простой вопрос с интеграцией файла js. Алгоритм действий такой: -Сверстал финальную страничку сайта-каталога (header, content, footer все в одной верстке) -Получил на выходе 3 файлика+папку с фотками и шрифтами, с этим вопросов нет

В файле js тянутся некоторые библиотки и при сборке они попали естественно в готовый файлик js. В итоге получился огромный файл, но суть проблемы в том, что я не везде использую некоторые фишки и по сути половина кода просто грузится в пустую. Как с этим бороться ? Интегрирую в Битрикс.

У меня где-то с полгода назад возникла идея о создании интерактивного туториала. Сейчас решил поделиться этой идеей.

Суть игры/туториала

Погружение людей в БЭМ, начиная с самых высоких абстракций. А именно с готовых блоков.

Процесс

Уровень 1

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

Для прикола можно сделать кнопку: "Землятресение!". Если человек плохо собрал дом - всё развалится.

Уровень 2

Человек делает JS логику на i-bem по взаимодействию элементов на странице (по готовым API)

Уровень 3

Знакомим человека с шаблонизаторами

Уровень 4

Знакомим человека со сброщиками

Уровень 5 и т.д.

Что это даст?

Системный подход к обучению + всегда можно узнать на каком уровне человек ;)


Написал в общих чертах, но мысль, кажется донёс. Делитесь в комментариях своими соображениями и идеями :)