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

Пишем:

import iBemDom from 'i-bem-dom';
class myBlock extends iBemDom {
  onSetMod : { ... },
  _onSubmit () {
  },
  static live () {
  }
}
export default myBlock;

получаем:

modules.define('my-block', ['i-bem-dom'], function (iBemDom) {
  var myBlock = iBemDom.decl('my-block', {
    onSetMod : { ... },
    _onSubmit : function () {
    }
  }, {
    live : function () {
    }
  })
  provide(myBlock);
});
  1. ES6 модули как абстракция для ym;
  2. ES6 классы как абстракция для inherit (а позже, возможно, для чего угодно).

Кому-то надо? Есть желание запилить?

На мой взгляд, надо:

  1. Сделать в enb возможность препроцессить файлы перед сборкой;
  2. Написать плагин для препроцессора с бабелем (есть https://github.com/s-panferov/enb-babel, но в этом случае весь код надо будет так);
  3. Подключить в .enb/make.js препроцессор;
  4. Получить профит и возможность писать так, где удобнее писать так, не меняя остального.

В качестве исключения можно про «хайлайтеры» для vim не вспоминать ;-)

/cc @blond @tadatuta

У блоков в bem.js представлении есть методы экземпляра и статические методы, Я хочу из одного блока обращаться к другому к примеру по event mouseover я показываю popup. я вешаю обработчик на блок который ловит событие такого содержания:

_mouseover: function(e){
    columnPopup.openByModsAlign(this._align);
},

Сам же блок columnPopup он находится в зависимостях у этого блока, columnPopup есть статический метод openByModsAlign который не православным методом с помощью jquery добавляет модификатор,

openByModsAlign : function(mods) {
    $('.column-popup_align_' + mods).addClass('column-popup_visible');
    $('.column-popup_align_' + mods).removeClass('column-popup_closing');
}

Хочется использовать как в методах экземпляра конструкцию типа

openByModsAlign : function(mods) {
    this.setMod('visible');
    this.delMod('closing');
}

Как правильно заюзать метод в моем случае? То что я написал это временный костыль который на мой взгляд не верен, в рамках БЭМА

Как я понял из доки для того что бы манипулировать элементами блока, отдельный модуль написать нельзя. можно только в блоке создать модуль блока и в нем манипулировать элементами. Возможно есть какие либо новые механизмы для написания модулей для элементов блока? Просто в моей парадигме есть блок form, он имеет различные элементы control(input, checkbox, textarea, submit и т.д.) И было бы не дурно писать нужный js (для элемента) внутри папки элемента, а внутри блока form общий js (валидация и т.д.) Иначе приходиться бить все на блоки которые на мой взгляд являются элементами и логичность структуры меняется в сторону хаоса.

Всем привет!

Не подскажите как правильно найти элемент у блока page. Мой код выдает null:

modules.define('page', ['i-bem__dom', 'jquery'], function(provide, BEMDOM, $) {
    provide(BEMDOM.decl(this.name, {
        onSetMod: {
            'js': {
                'inited': function() {
                    var header = this.findBlockInside(this.elem('header'), this);
                    console.log('header =', header);
                }
            }
        }
    }));
});

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

Есть несколько блоков menu вложенных друг в друга. Обычное многоуровневое меню. Хочу чтобы верхний уровень знал только о своих непосредственных menu-item и не влиял на вложенные меню. Как найти только непосредственно вложеные блоки? И сразу еще вопрос. Хочу чтобы блок menu инициализировался по bem-событию в непосредственно вложенных в него menu-item В jsdoc нашел liveInitOnBlockInsideEvent ( event, blockName, [callback] ) protected но меня смущает что метод protected

Всем привет!

Я только учусь и все пытаюсь разобраться с i-bem.

  1. Как правильно воспроизвести такую логику: есть два блока, первый из них через JavaScript влияет на другой. Например, кнопка меню на мобильной версии сайта показывает и скрывает меню. Я хотел сделать таким образом, первому блоку передаются параметры, название блока и id, над которым будут совершаться какие-то действия:
            js: {
                toggledBlock: {
                    block: 'nav',
                    id: 'menu'
                }
            }

Дальше я пытаюсь по этим данным найти блок:

var targetID = this.params.toggledBlock.id;
var targetBlock = this.params.toggledBlock.block;
var toggledBlock = this.findBlocksOutside(targetBlock).filter(function(block) {
    return block.params.id = targetID;
});

Эти блоки у меня стоят рядом; findBlocksOutside ничего не находит, остальные методы findBlock(s)* тоже ничего не находят. У меня возник такой вопрос, почему же вообще существуют такие методы как findBlocksOutside, findBlocksInside, findBlocksOn, не противоречат они самой методологии, что блок должен знать где находится другой блок? Не проще ли иметь метод find, который просто находит необходимый блок в независимости от местаположения? Как же правильно решить задачу с меню, и как правильно применять методы findBlock*?

  1. Второй вопрос по документации по i-bem, можно ли как-то ее понять? =) Сколько я ее не читал, так я с ней и не подружился. Можно ли найти примеры использования методов i-bem? Каждый раз как я пытаюсь написать что-то на JavaScript я застапариваюсь на простых вещах. Например метод this.setMod([elem], modName, modVal), я бился несколько часов пытаясь проставить модификатор элементу:
this.setMod('elem', 'someMod', 'itsValue');

В первый раз, когда используешь этот метод, хочется написать именно таким образом, и в голову не приходит, что на месте 'elem' должен быть явно указанный элемент, this.elem('elem'). В документации при первой встречи метода setMod ничего не сказано про то, что же передается этому методу. У меня каждый раз возникают проблемы при использовании какого-то методы i-bem. Кажется из названия метода ясно как он работает, пытаешься его использовать, понимаешь, что понятия не имеешь как он работает, лезешь в документацию, в документации ничего не написано.

Также возникает вопрос, если есть методы findBlocks*, которые возвращают массив блоков, то почему нет метода, который возвращает массив элементов?

Добрый день. Разбираюсь с БЭМом. Предположим, я реализовал блок label, использую его в технологии BEMJSON, по нему формируется HTML через BEMHTML, привязывается js, все хорошо. Встала задача динамически создавать блок label на уже отображенной странице по действиям пользователя.

Насколько я понимаю, мне необходимо сформировать HTML этого блока и проинициализировать его. что- то типа createLabel(parentBlock,params)

Как правильно реализовать эту возможность?

Всем привет!

Начинаю изучать BEM, пытаюсь поработать с библотекой bem-forms. Библиотеку подключил, прописал путь до библиотеки в .bem/make.js. BEMHTML библиотеки отрабатывает, html-tag формы преобразуется из div в form. Не получается доопределить поведение формы в JavaScript. Пытаюсь сделать это следующем образом, как указано здесь.

modules.define('form', function(provide, Form) {
    provide(Form.decl({
        onSetMod: {
            'js': {
                'inited': function() {
                    console.log('form started ...');
                }
            }
        }
    }));
});

При этом поведение блока button из библиотеки bem-components таким же образом переопределить получается. Использую bem-tools и project-stub.

Пока писал, заметил, что у формы не проставляется модификатор js_inited. Как можно поправить? В BEMJSON явно указал js: true, но ничего не происходит.

P.S. И не большой вопрос, при создании нового блока, bem-tools создает файл blockName.browser.js. Что значит browser.js? Чтобы указать, что в файле клиентский код?

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

Всем доброго времени суток :)

Поискал по форуму и не нашёл ответа на свой вопрос.

Нужно инициализировать добавленные блоки через Ajax в i-bem.

С сервера планируется получать нужные блоки в виде готового html Как правильно сказать i-bem о том, что их нужно инициализировать?

Привет! Можно ли определить поведение блока с определенным модификатором с DOM-определением? Если я добавляю ['i-bem__dom'] в декларацию блока в JavaScript, то код перестает отрабатывать.

Пример BEMJSON:

{
    block: 'someblock',
    mods: {
        somemod: 'somevalue'
    },
    js: true,
    content: [
        'block content'
    ]
}

Пример JavaScript:

modules.define('someblock', ['i-bem__dom'], function(provide, BEMDOM) {
    provide(BEMDOM.decl({modName: 'somemod', modVal: 'somevalue'}, {
        onSetMod: {
            'js': {
                'inited': function() {
                    console.log('someblock inited with mod!');
                }
            }
        }
    }));
});

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

С элементами возможно работать только по средством jquery API?

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

modules.define('block1', ['i-bem__dom', 'jquery'], function(provide, BEMDOM, $) {
    {
        live: function() {
             this.liveBindTo('block1-1', 'click', function( ) {
                    // как тут правильно обратиться к другому элементу вне блока?
                   //   (block2).setMod('block2-1','current-block1-1',true);
                   // предполагал что-то вроде следующего, но скорей всего тут что-то совстем не так
                    this.findBlockOutside('block2').setMod('switched');    // Ошибка: this.findBlockOutside('block2') возвращает null, видать не дотягивается область видимости.
              });
        }
    }
});

Появилась мысль, вешать модификаторы через общий документ () page.js. С первого раза почему .js в родительском файле совсем не заработал и ошибок не выдал, решил искать другой метод, не работает значит не надо :)

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

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

      provide(BEMDOM.decl(this.name, {}));

});

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

     provide(BEMDOM.decl(this.name, {
...
         onSetMod : {
            'switched' : function(){
                    this.__base.apply(this).setMod( 'visible', true);  // Ошибка:  TypeError: undefined has no properties
            }
        },
...
     }));

});

Добился результата следующим методом, но знаю что он не рекомендуем:

onSetMod : {
       'switched' : function(){
         $('.block2').bem('block2-1').setMod( 'visible', true);
       }
  },

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

Ребят, подскажите как правильно убрать его вообще с проекта. Чтобы даже духу не было ) Без него только bem-components не будет работать?

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

bem-components 2.1.0 bem-core 2.6

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

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

Как можно достичь работы нескольких инстансов i-bem на одной страницы? Пробовал отключать _auto_init, менять BEMDOM.scope и вызывать инициализацию только на этом элементе. Не вышло - происходила инициализация блоков в том числе за пределами scope.

Делаю блок scrollspy. который должен следить, находится ли блок в видимой зоне страницы. Блок подписывается на скролл

this.bindToWin('scroll', throttle(this._onScroll, this.pause, this));

получается, куча блоков подписанных на scroll, что в итоге тормозит. Пробовал задать live обработчик, с помощью liveBindTo(BEMDOM.win, 'scroll', callback) но реакции на события нет. Как правильно подписаться на события вне блока?

Хочу использовать i-bem.js для shadowDOM компонент. Идея была такая: сбилдить js-файл со всеми нужными компонентами и подключить его внутри каждого shadowDOM блока. Но так не получается:

JavaScript всё равно исполняется в глобальном контексте и i-bem не видит компонент, спрятанных за shadowDOM. Я хотела обойти так: подгружать js-код текстом при инициализации shadowDOM и затем делать eval с подменой контекста. Но если изменить контекст с window на shadowRoot, всё ломается, потому что i-bem рассчитывает на какие-то методы глобального контекста.

Что можно всё-таки сделать, чтобы подружить i-bem и shadowDOM?

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

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

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

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

надо инициализировать в блоке block-editor Sir Trevor со всеми либами зависимостями по документации надо подключить underscore.js eventable.js sir-trevor.js и на станице прописать

<form> <textarea class="js-st-instance"></textarea> </form>

<script> new SirTrevor.Editor({ el: $('.js-st-instance') }); </script>

я сделал блок jslib с элементами jslib__underscore, jslib__eventable, jslib__sir-trevor в блоке где это надо использовать прописал

modules.define('block-editor', [ 'jquery', 'jslib__underscore', 'jslib__eventable', 'jslib__sir-trevor' ], function(provide, $, _, Eventable, SirTrevor) {
    new SirTrevor.Editor();
    console.log(Eventable);
    console.log(_);
    console.log(SirTrevor);
    console.log(123);
provide();

});

пытаюсь вывести в консоль, ничего нет, поправьте что делаю не так

Продолжаю переводить наш проект на bem-core с собственным сборщиком и шаблонизацией на twig.

Вчера убил кучу времени в попытках заставить инициализироваться блоки. Не хотели ни в какую. Сегодня решил поставить i-bemdom_init_auto.js самым-самым последним среди подключаемых js-файлов — и всё завелось. Но это несколько неудобно, потому что мы подключаем js в виде 3-4 бандл-файлов и не хочется делать ещё один для i-bemdom_init_auto.js.

Есть какие-то варианты решения проблемы?

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

    swipes: function (status) {
        if (status) {
            this.bindTo( this.elem('view'), 'mousedown', this._swipeStart );
            this.bindTo( this.elem('view'), 'mouseup', this._swipeEnd );
        }
    },

    _swipeStart: function (e) {
        console.log(e);
        this._tmpSwipeStart = e.pageX;
    },

    _swipeEnd: function (e) {
        console.log(e);
        if ((e.pageX - this._tmpSwipeStart) > 50) {
            this.previous();
        }
        if ((e.pageX - this._tmpSwipeStart) < -50) {
            this.next();
        }
    },

Событие на mouseup не срабатывает. Не могу понять в чём дело.

При сборке - js собирается в один файл.

Как общий js для всех страниц вынести в отдельную сборку? А то много дублирования происходит... И слишком раздутые файлы.

Опишу что я делаю: В каталоге проекта yii я создал подкаталог bem. Для копирования файлов сборки (js, css) я использую gulp. А вот html на php руками уже правлю.

bem-stub используется для прототипирования

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

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

Добрый день. Могу ли я делегировать определенное БЭМ событие всех блоков(без определения имени блока), которые находятся внутри блока родителя.

Вопрос к команде БЭМа.

Есть ли правила написания стиля js кода по БЭМу?

В частности интересует названия методов, хранения временных данных и т.д. В каких случаях ставятся подчёркивание _, в каких двойное подчёркивание __, а в каких без него.

Пока примерно так понял, что __ для элементов (и внутренних блоков) _ для методов а вот без подчёркиваний не понял когда лучше использовать

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

В документации описано достаточно про методы. Но как доходит до статических, то как-то вот так.

Можно более подробно узнать их назначении? Допустим я делаю поиск блока

this.__smaller = this.findBlockInside('smaller')

Как теперь обращаться и к каким методам? Если посмотреть информацию в консоли

console.log(this.__smaller)

то будет видно, что стандартные методы из декларации доступны в объекте

__proto__

и к ним можно обращаться просто

this.__smaller.goodJump()

В связи с данной ситуацией у меня появились большие сомнения о том, что понял назначение статистических методов. Только что-то далёкое, но не осознанное.

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

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

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

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

var block;

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

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

provide(BEMDOM);

});

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

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

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

из плюсов

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

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


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


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

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

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