ПоискПочтаКалендарьДеньгиМой КругФоткиНародОткрытки
Войти


Чтобы получить доступ ко всем возможностям Я.ру, создайте страницу или , если у вас она уже есть.
userpic

премодерируемый клуб  

Присоединившись к клубу, вы сможете вывешивать фотки в галерее и создавать новые темы для обсуждения. Обсуждаемые темы клуба будут появляться на странице «Что нового».
Вступить в клуб
О клубе
6 февраля 2009 года, 23:25
Блок, Элемент, Модификатор (БЭМ)

Попытка завоевать мир сделать лучший Web Framework, действительно облегчающий разработку и поддержку сайта. А так же систематизировать подходы к вёрстке и описать удобную схему вёрстки сайтов, как больших, так и маленьких.

записи по месяцам · меткам · типам

выделить все / снять выделение

Показать
toivonens написала
изменено 1 февраля, в 12:01
userpic
Новое в мире БЭМ за последнее время

Социальщина

Мы сделали группу в Facebook, присылайте заявки.

Актуальные задачи

В трекере библиотеки bem-bl всегда есть задачи. Сейчас важно перевести существующую документацию на английский, вот список тасков: https://github.com/bem/bem-bl/issues?labels=RU-EN+translation&sort=created&direction=desc&state=open&page=1

Workflow работы такой:

  1. Вы делаете себе fork репозитория bem-bl
    Инструкция про Fork
  2. Правите (или создаёте) документацию на английском (в ветке master)
    Английское описание блоков, элементов и модификаторах лежит в файлах *.en.title.txt
    и *.en.wiki этих блоков, элементов и модификаторов.
  3. Пушите изменения в свой fork
  4. Делаете Pull Request, чтобы ваши изменения были приняты в основном репозитории
    Инструкция про Pull Request'ы

Вакансия

У нас в команде есть вакансия разработчика интерфейсов. Но сначала надо сделать Pull Request.

toivonens поделилась ссылкой
21 ноября 2011 года, 16:54
userpic
Что такое БЭМ?

Большая статья о том, что такое БЭМ. С картинками.
Отныне изучение БЭМ рекомендуется начинать с прочтения этой статьи.

toivonens написала
18 ноября 2011 года, 18:56
userpic
Использование вертикального меню b-menu-vert

Блок b-menu-vert - это меню с вертикальной ориентацией.

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

Простое вертикальное меню

В простейшем случае в BEMJSON достаточно объявить блок и перечислить его элементы item в свойстве content:

{
  block: 'b-menu-vert',
  content: [
    {
      elem: 'item',
      content: 'Index'
    },
    {
      elem: 'item',
      content: 'Contacts'
    },
    ...
  ]
}
( Вcё многообразие вариантов использования )

 В получившемся HTML появляются не только узлы для блока и явно заданных элементов item, но и разметка для элементов layout и layout-unit. Эти элементы отвечают за геометрическую отрисовку блока.

В качестве контента элементов item в простых случаях используются ссылки:

{
  block: 'b-menu-vert',
  content: [
    {
      elem: 'item',
      content: {
        block: 'b-link',
        url: 'http://yandex.com',
        content: 'Index'
      }
    },
    {
      elem: 'item',
      content: {
        block: 'b-link',
        url: 'http://google.com',
        content: 'Backyard'
      }
    },
    ...
  ]
}

Кроме того, у одного из элементов item может быть модификатор { state : 'current' }, отмечающий выделенный пункт меню. Модификатор используется как для визуального выделения пункта при помощи CSS-правил для этого модификатора, так и для описания функционального поведения.

{
  block: 'b-menu-vert',
  content: [
    {
      elem: 'item',
      elemMods: { state: 'current' },
      content: {
        block: 'b-link',
        url: 'http://yandex.com',
        content: 'Index'
      }
    },
    {
      elem: 'item',
      content: {
        block: 'b-link',
        url: 'http://google.com',
        content: 'Backyard'
      }
    },
    ...
  ]
}

 

В BEMJSON описании меню может быть указано свойство title, задающее элемент title для заголовка меню:

{
  block: 'b-menu-vert',
  title: {
    elem: 'title',
    content: 'Menu title'
  },
  content: [
    {
      elem: 'item',
      elemMods: { state: 'current' },
      content: {
        block: 'b-link',
        url: 'http://yandex.com',
        content: 'Index'
      }
    },
    {
      elem: 'item',
      content: {
        block: 'b-link',
        url: 'http://google.com',
        content: 'Backyard'
      }
    },
    ...
  ]
}

 

Предусмотрена и возможность создания пустого элемента списка для отделения одних пунктов меню от других. За это отвечает элемент separator.
На уровне переопределения проекта можно задать CSS-правила для такого элемента. Чаще всего его представляют в виде горизонтальной черты.

{
  block: 'b-menu-vert',
  content: [
    {
      elem: 'item',
      elemMods: { state: 'current' },
      content: {
        block: 'b-link',
        url: 'http://yandex.com',
        content: 'Index'
      }
    },
    {
      elem: 'separator'
    },
    {
      elem: 'item',
      content: {
        block: 'b-link',
        url: 'http://google.com',
        content: 'Backyard'
      }
    },
    ...
  ]
}

Пример простого меню со ссылками содержится и в рпепозитории библиотеки bem-bl.

Вертикальное js-меню с псевдо-ссылками

Если вместо ссылок нужно использовать псевдо-ссылки, BEMJSON меню должен отличаться содержанием элементов item:

{
  block: 'b-menu-vert',
  content: [
    {
      elem: 'item',
      elemMods: { 'state' : 'current' },
      content: {
        block: 'b-link',
        mods : { 'pseudo' : 'yes' },
        url: '/',
        content: 'First point'
      }
    },
    {
      elem: 'item',
      content: {
        block: 'b-link',
        mods : { 'pseudo' : 'yes'},
        url: '/',
        content: 'Second point'
      }
    },
    ...
  ]
}

Кроме внешнего вида, js-меню отличается и клиентской функциональностью: оно способно по клику левой кнопкой мыши переключать соответствующий пункт меню в состояние { state : 'current' } и генерировать на js-объекте, соответствующем блоку, событие о факте переключения пункта меню.
Для использования этой функциональности необходимо определить, где у меню будут расположены элементы item-selector, реагирующие на клик. Эти элементы нарочно сделаны несовпадающими с элементами item, потому что чаще всего сам пункт меню больше по размеру, чем его активная область.
Элемент item-selector можно использовать как сам по себе, так и примешивая его к другим элементам или блокам. В данном случае можно сделать mix с псевдо-ссылками:

{
  block: 'b-menu-vert',
  content: [
    {
      elem: 'item',
      elemMods: { 'state' : 'current' },
      content: {
        block: 'b-link',
        mods : { 'pseudo' : 'yes' },
        mix: [{ block: 'b-menu-vert', elem: 'item-selector'}],
        url: '/',
        content: 'First point'
      }
    },
    {
      elem: 'item',
      content: {
        block: 'b-link',
        mods : { 'pseudo' : 'yes'},
        mix: [{ block: 'b-menu-vert', elem: 'item-selector'}],
        url: '/',
        content: 'Second point'
      }
    },
    ...
  ]
}

 

Пример простого вертикального js-меню есть в папке блока в библиотеке bem-bl.

Вертикальное js-меню со сложным контентом

Пункты меню могут содержать не один, а несколько блоков. В библиотеке bem-bl есть пример такого меню. Его пункты помимо ссылок содержат иконки.

Поскольку реакция на клик необходима для всего содержания пункта меню, элемент item-selector используется в таком случае в явном виде, являясь контейнером для содержания пункта меню. В этом случае он представлен в DOM-дереве узлом span:

{
  elem: 'item',
  content: {
    elem: 'item-selector',
    content: [
      {
        block: 'b-link',
        mods : { 'pseudo' : 'yes', 'inner' : 'yes' },
        mix: [{ block: 'b-menu-vert', elem: 'item-selector'}],
        url: '/',
        content: [
          {
            block: 'b-icon',
            url: 'http://yandex.st/lego/_/Kx6F6RQnQFitm0qRxX7vpvfP0K0.png',
            alt: 'Yandex favicon'
          },
          {
            elem: 'inner',
            content: 'Second point'
          }
        ]
      },
      ' One more element here'
    ]
  }
}

 

Раскрывающееся вертикальное js-меню

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

Так же, как и элемент item-selector, элемент trigger может использоваться не явно, а через mix.

{
  block: 'b-menu-vert',
  content: [
    {
      elem: 'item',
      elemMods: { state: 'current' },
      content: 'Videos'
    },
    {
      elem: 'item',
      content: {
        block: 'b-link',
        mods: { pseudo: 'yes', inner: 'yes'},
        mix: [{ block: 'b-menu-vert', elem: 'trigger'],
        content: [
          {
            block: 'b-icon',
            mix: [{ block: 'b-menu-vert', elem: 'trigger-icon' }],
            alt: 'trigger'
          },
          {
            elem: 'inner',
            content: 'Images'
          }
        ]
      },
      'item-content': {
        elem: 'item-content',
        content: {
          block: 'b-menu-vert',
          mods: { 'type' : 'submenu' },
          content: [
            {
              elem: 'item',
              content: 'Any size'
            },
            {
              elem: 'item',
              content: 'Large'
            },
            {
              elem: 'item',
              content: 'Medium'
            }
          ]
        }
      }
    },
    {
      elem: 'item',
      content: {
        block: 'b-link',
        url: '/',
        content: 'News'
      }
    }
  ]
}

 

Кроме элемента item-selector здесь используется свойство item-content, описывающее элемент item-content с содержанием, которое показывается или скрывается в зависимости от кликов по элементу item-selector.

Элемент trigger-icon используется только для обозначения иконки. На уровне переопределения соответствующего примера в bem-bl реализованы CSS-правила, показывающие одну иконку для триггера с открытым состоянием и другую для триггера с закрытым состоянием.

По умолчанию элемент trigger не содержит модификатора state, а элемент item-content не содержит модификатора visibility. В этом состоянии содержание элемента item-content не видно.
При клике на элементе trigger левой кнопкой мыши он приобретает модификатор { state : 'opened' }. Элемент item-content в это же время приобретает модификатор { visibility : 'visible' } и становится виден на странице.

Если нужно сразу показать вложенное меню раскрытым, эти модификаторы следует явно задать в BEMJSON-описании блока:

{
  block: 'b-link',
  mods: { pseudo: 'yes', inner: 'yes'},
  mix: [{ block: 'b-menu-vert', elem: 'trigger', elemMods: { state: 'opened' }}],
  content: [
    ...
}




'item-content': {
  elem: 'item-content',
  elemMods: { visibility: 'visible'},
  content: ...

 

В библиотеке bem-bl также есть пример меню с неоднократной вложенностью триггеров.

Вложенные меню

BEMJSON позволяет вкладывать одни блоки в другие. Содержанием пункта меню может быть другое меню, и тогда естественным образом образуется вложенность.
Такое использование меню создаст в DOM-дереве два блока (и два узла ul), которые будут вести себя соответственно.

Если есть необходимость визуально представить меню как вложенное, но функционально - как один блок (например, со сквозным поведением активного пункта меню), нужно воспользоваться элементом submenu.

Элемент submenu должен содержаться в элементе item-content и включать в себя описание элементов item для "подменю".

Пример для вложенного меню в библиотеке bem-bl демонстрирует такое BEMJSON-описание.

Сквозные вложенные меню работают и с триггером, BEMJSON для такого случая можно посмотреть в соответствующем примере.

toivonens написала
16 ноября 2011 года, 14:16
userpic
JavaScript реализация горизонтального меню

JavaScript реализация блока b-menu-horiz обеспечивает следующее поведение:

  • при клике на определённую область (блок) содержащий этот блок пункт меню становится активным, то есть приобретает модификатор { state : 'current' }.
  • факт изменения активного пункта меню отражается на уровне событий, чтобы на
    этот факт можно было реагироать.

Точно такая же функциональность нужна и для вертикального меню. Поэтому она реализована в блоке-хелпере i-menu (абстрактное меню).

( Как реализовано JavaScript-меню )

Для начала рекомендуется ознакомиться с базовыми понятиями JavaScript-реализации в библиотеке bem-bl: bem.github.com/.../i-bem.ru.html.

JavaScript-реализация блока b-menu-horiz в этом случае сводится к декларации блока с указанием базы:

BEM.DOM.decl({ name: 'b-menu-horiz', baseBlock: 'i-menu' });

Такая запись означает, что все методы и свойства JavaScript-объекта блока будут унаследованы от i-menu.

JavaScript блока i-menu

Блок i-menu задекларирован как блок, имеющий DOM-представление:

BEM.DOM.decl('i-menu',
...
)

У блока есть динамические и статические методы и свойства.

Наличие статического метода live блока означает, что bem-объект (JavaScript объект в памяти браузера) создаётся не сразу при общей инициализации блоков на странице, а при возникновении определённых условий.

live : function() {
    this.liveBindTo('item-selector', 'leftclick', function(e) {
        this.onItemSelectorClick(e);
    });
}

В теле метода использован метод liveBindTo, позволяющий инициализировать блок при возникновении события. В данном случае - при возникновении события leftclick на любом из элементов item-selector блока.
Использование события leftclick (вместо click) позволяет реагировать только на клик левой кнопкой мыши. Такая возможность предоставляется специалиным плагином для jQuery, реализованным в элементе i-jqueryleftclick.
Callback-функция, переданная в метод, будет исполняться при каждом клике.

Метод onItemSelectorClick относится к конкретному инстансу блока и, соответственно, реализован как динамический метод блока:

onItemSelectorClick : function(e) {

    var item = this._getItemByEvent(e);
    this.setMod(item, 'state', 'current');

}

В результате работы этого метода соответствующий пункт меню приобретает модификатор { state : 'current' }.

Для вычисления соответствующего пункта меню используется метод _getItemByEvent:

_getItemByEvent : function(e) {
    return e.data.domElem.closest(this.buildSelector('item'));
}

Поскольку клик случается не на элементе item, его нужно вычислять относительно элемента, на котором возникло событие.
Необходимость слушать событие не на элементе item, а на содержащемся в нём элементе item-selector продиктована тем, что элемент item чаще всего больше, чем область, которая должна реагировать на клик. Кроме того, использование специального элемента для реакции на клик позволяет при необходимости сделать так, что эта реакция будет лишь у одного из блоков, содержащихся в пункте меню.

При переключении какого-либо пункта меню в активное состояние на bem-объекте блока возникает событие trigger. Код, обеспечивающий это, записан в декларативном стиле в свойстве onElemSetMod блока:

onElemSetMod : {

    'item' : {

        'state': {

            'current' : function(elem, modName, modVal, oldModVal) {

                if (oldModVal == 'disabled') return false;

                var prev = this.elem('item', 'state', 'current');
                this
                    .delMod(prev, 'state')
                    .trigger('current', {
                        prev    : prev,
                        current : elem
                    });
            }
        }
    }
}

Эта функция исполняется при любой попытке приобретения элементом item модификатора state в значении current (не только при клике). Например, если существует какой-то другой блок, который в ходе своей работы меняет текущий пункт меню, функция исполнится.

Функция возвращает false в том случае, если данный элемент находится в состоянии disabled (это тоже значение модификатора state). Возвращение функцией значения false отменяет установку модификатора. То есть неактивный пункт меню не может стать выделенным.

В результате работы функции при каждом переключении активного пункта меню на блоке возникает событие trigger с данными о предыдущем и текущем активном пункте меню. Это событие может слушать другой блок, и по факту возникновения этого события выполнять какие-либо действия.
Например, при клике на пункты меню можно загружать информацию по AJAX и менять контент в другой части страницы.

Дополнительная информация по JavaScript-реализациям в библиотеке bem-bl:

toivonens написала
изменено 23 декабря 2011 года, в 12:48
userpic
Использование и реализация блока b-menu-horiz

Блок b-menu-horiz создаёт HTML-разметку для горизонтального меню. Кроме того, у блока есть JavaScript-функциональность, позволяющая создавать скрипты с реакцией на выбор пункта меню.

Сложность HTML-разметки меню зависит от модификатора, с которым используется блок.

Реализован модификатор блока layout с тремя возможными значениями:

  • normal
  • complex
  • simple

Без модификатоора layout блок использоваться не может.

( Как использовать разные горизонтальные меню )

Простое горизонтальное меню

Входные данные для блока с любым из этих модификаторов похожи: нужно описать блок, модификатор layout, в качестве свойства content блока перечислить пункты меню, которые выражаются элементами item:

{
  block: 'b-menu-horiz',
  mods: { layout: 'normal' },
  content: [
    {
      elem: 'item',
      content: 'Home'
    },
    {
      elem: 'item',
      content: 'Office'
    },
    ...
  ]
}

Содержанием элементов меню может быть что угодно: ссылки на страницы, псевдо-ссылки, иконки и вообще любые блоки. В примере выше каждый пункт меню - это просто строка текста.

Такое же меню со ссылками будет выглядеть следующим образом:

{
  block: 'b-menu-horiz',
  mods: { layout: 'normal' },
  content: [
    {
      elem: 'item',
      content: {
        block: 'b-link', url: '/', content: 'Home'
      }
    },
    {
      elem: 'item',
      content: {
        block: 'b-link', url: '/office', content: 'Office'
      }
    },
    ...
  ]
}

Кроме того, у одного из пунктов меню может быть указан модификатор { state: 'current' }, этот модификатор помечает текущий пункт меню.
На своём уровне переопределения можно реализовать для такого модификатора CSS-правила, по которым текущий пункт меню будет визуально отличаться от остальных.

У меню также может быть необязательное свойство title, содержащее описание элемента title - заголовка меню.
Для меню с заголовком BEMJSON будет такой:

{
  block: 'b-menu-horiz',
  mods: { layout: 'normal' },
  title: {
    elem: 'title', content: 'Navigation:'
  },
  content: [
    {
      elem: 'item',
      elemMods: { state: 'current' },
      content: {
        block: 'b-link', url: '/', content: 'Home'
      }
    },
    {
      elem: 'item',
      content: {
        block: 'b-link', url: '/office', content: 'Office'
      }
    },
    ...
  ]
}

Горизонтальное меню с клиентской функциональностью

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

{
  block: 'b-menu-horiz',
  mods: { layout: 'normal' },
  title: {
    elem: 'title', content: 'Navigation:'
  },
  content: [
    {
      elem: 'item',
      elemMods: { state: 'current' },
      content: {
        block: 'b-link',
        mods: { 'pseudo': 'yes' },
        url: '/',
        content: 'Home'
      }
    },
    {
      elem: 'item',
      content: {
        block: 'b-link',
        mods: { 'pseudo': 'yes' },
        url: '/office',
        content: 'Office'
      }
    },
    ...
  ]
}

Приведённый выше BEMJSON блока обеспечит нужный внешний вид.
Кроме этого нужно, чтобы у меню были области, реагирующие на клик. В данном случае они совпадают с псевдо-ссылками, поэтому можно применить смешивание блоков (mix) :

{
  block: 'b-menu-horiz',
  mods: { layout: 'normal' },
  title: {
    elem: 'title', content: 'Navigation:'
  },
  content: [
    {
      elem: 'item',
      elemMods: { state: 'current' },
      content: {
        block: 'b-link',
        mods: { 'pseudo': 'yes' },
        mix: [{ block: 'b-menu-horiz', elem : 'item-selector' }],
        url: '/',
        content: 'Home'
      }
    },
    {
      elem: 'item',
      content: {
        block: 'b-link',
        mods: { 'pseudo': 'yes' },
        mix: [{ block: 'b-menu-horiz', elem : 'item-selector' }],
        url: '/office',
        content: 'Office'
      }
    },
    ...
  ]
}

JavaScript код блока реализован так, что активный пункт меню переключается при клике левой кнопкой мыши на соответствующем элементе item-selector.

При явном использовании этот элемент представлен в DOM в виде span, в который можно положить блоки, составляющие пункт меню. Если же содержание пункта меню состоит всего из одного блока (как в примере с псевдо-ссылками), для экономии разметки разумно применять mix.

Кроме того, что соответствующий элемент item в результате клика приобретает модификатор { state : 'current' }, на bem-объекте блока возникает событие current, сопровождающееся данными о текущем и предыдущем активных пунктах.
В своём JavaScript-приложении можно реагировать на это событие.

В HTML по умолчанию блок представлен как имеющий JavaScript-реализацию (он смешан с блоком i-bem и имеет соответствующие параметры в атрибуте onclick). Но если в блоке отсутствуют элементы item-selector, bem-объект блока не создаётся.
Примешивание блока i-bem можно устранить, если указать свойство js блока как false:

Меню без подмешивания блока i-bem

{
  block: 'b-menu-horiz',
  js: false,
  mods: { layout: 'normal' },
  content: [
    {
      elem: 'item',
      content: {
        block: 'b-link', url: '/', content: 'Home'
      }
    },
    {
      elem: 'item',
      content: {
        block: 'b-link', url: '/office', content: 'Office'
      }
    },
    ...
  ]
}

Горизонтальное меню с табличной разметкой

Использование блока с модификатором { layout: 'complex' } принципиально ничем не отличается. Для блока в такой модификации создаётся разметка на основе таблицы. Такое решение может потребоваться при некоторых дизайнах.

Аскетичное горизонтальное меню

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

Для вывода такого меню подходит реализация с модификатором { layout : 'simple' }:

{
  block: 'b-menu-horiz',
  mods: { layout: 'simple' },
  separator: ' | ',
  content: [
    {
      elem: 'item',
      elemMods: { state: 'current' },
      content: 'Home'
    },
    {
      elem: 'item',
      content: {
      block: 'b-link',
      url: '/',
      content: 'Products'
    },
    ...
  ]
}

BEMJSON меню отличается наличием свойства separator - того самого специального символа, который разделяет пункты меню.
Активный пункт меню в данном примере представлен в виде простого текста в теге span.

Примеры всех описанных здесь применений блока b-menu-horiz можно найти в директории блока в репозитории библиотеки bem-bl: bem.github.com/bem-bl/.../b-menu-horiz/examples.

bessarabov написал
25 октября 2011 года, 16:22
userpic
Конспект мастер-класса "Тема для WordPress в БЭМ" на YaC

У меня есть мечта. Вообще у меня их много, но сейчас я хочу поделится одной
из них. Так вот, моя мечта в том, чтобы научится работать с BEM.

На YaC я был на мастер классах, но там я понял недостаточно чтобы
использовать BEM.

На днях у меня  был очередной подход к этой Методологии — я повторил
своими руками почти все что показал  tadatuta  в своем мастер-классе на
конференции YaC.

У меня так получается, что я гораздо лучше понимаю что-нибудь, когда я про
это рассказываю, поэтому я записал все свои действия. В итоге у меня получился
небольшой текст про BEM с самого начала. Этот текст почти полностью
повторяет все что показал tadatuta.

( Под катом мой конспект. )

Мой рабочий компьютер — это linux машина. На десктопе я использую
Ubuntu 10.04 LTS и я считаю это очень удобным и правильным. В большинстве
док рассказывается как работать с BEM с мака, с линукса все очень похоже,
но есть небольшие различия.

Я поставил перед собой следующие цель создать самое элементарное приложение
на BEM. В своем докладе  tadatuta  рассказывал о создании темы для wordpress.
Но поднимать веб сервер с wordpress на своей машине я не стал. Ограничился
тем что у меня просто создаются php файлы.

Установка необходимых штук



Для работы BEM нужен node.js, на убунту он ставится очень просто:


$ sudo add-apt-repository ppa:chris-lea/node.js
$ sudo apt-get update
$ sudo apt-get install nodejs


Проверяю что эта балалайка работает. Создаю файл hello.js со следующим
содержанием:


    var http = require('http');
    http.createServer(function (req, res) {
      console.log('Request');
      res.writeHead(200, {'Content-Type': 'text/plain'});
      res.end('Hello World\n');
    }).listen(1337, "127.0.0.1");
    console.log('Server running at http://127.0.0.1:1337/');


Запускаю:

$ node hello.js


Захожу браузером, все работает. Зашибенно. =)=)

Судя по шпаргалке к мастерклассу
нужно использовать пакетный менеджер nodejs - http://npmjs.org/
Использовать какой-либо другой пакетный менеджер кроме как нативного
дебиановского мне не кажется хорошей идеей, но я тем не менее делаю:


$ curl http://npmjs.org/install.sh | sudo sh
$ echo 'export NODE_PATH="'$(npm root -g):$NODE_PATH'"'>>  ~/.bashrc && . ~/.bashrc
$ sudo npm install -g bem xjst ometajs borschik node-inherit cssp csso


В системе появилась команда 'bem', и она работает:


$ bem
$ bem --help


Еще в проекте используется uglifyjs. Чуть-чуть забегаю вперед скажу, что он
у меня не заработал, но ставится на убунту он так:


$ sudo add-apt-repository ppa:chris-lea/uglifyjs
$ sudo apt-get update
$ sudo apt-get install uglifyjs


Поехали! Начал фигичать.



Создаю папку для проекта:


$ mkdir ~/bemtest
$ cd ~/bemtest


Забираю нужные файлы:

$ git clone https://github.com/tadatuta/BEM-on-YaC.git bempress


После получения этого репозитория с github проект выглядит так:


.
`-- bempress
    |-- bem
    |   `-- techs
    |       `-- php.js
    |-- make-page
    `-- README.md


README.md — понятно, чуть-чуть описания. Для тех кто не знаком с
github, расширение md - это сокращение от markdown, в этом файле можно
использовать специальный синтаксис.
make-page — файл для сборки страниц. У меня почему-то не заработал uglifyjs,
поэтому последнюю строку в этом файле я закоментил.

Дальше заходим в папку — это вот то действие, которое на Яке Володя не
сделал, поэтому не сразу все получилось.


$ cd bempress


Магическая команда:


$ bem create level pages


На самом деле она выполняет очень простое действие - просто создает папку
pages и пустой файл pages/.bem/level.js. После выполнения этого действия
структура проекта выглядит так:


.
|-- bem
|   `-- techs
|       `-- php.js
|-- make-page
|-- pages
|   `-- .bem
|       `-- level.js
`-- README.md


В папке pages будут находится файлы, которые описывают страницы. Создадим
вот это описание:


$ bem create block index -l pages -t bemjson.js


Это создаст пустой файл pages/index/index.bemjson.js и проект будет
выглядеть так:


.
|-- bem
|   `-- techs
|       `-- php.js
|-- make-page
|-- pages
|   |-- .bem
|   |   `-- level.js
|   `-- index
|       `-- index.bemjson.js
`-- README.md


Дальше в этот файл впишем следующее описание страницы:


({ 
    block: 'page',
    content: [
    { block: 'header' },
    { block: 'content' },
    { block: 'footer' },
    ]
})


В этом описании мы используем 3 блока: header, content, footer, но пока у
нас их нет. Самое время создать:


$ bem create block header content footer -l blocks -t php -t css


Это создает папочку blocks и шаблоны файлов указанных блоков. Структура
проекта:


.
|-- bem
|   `-- techs
|       `-- php.js
|-- blocks
|   |-- content
|   |   |-- content.css
|   |   `-- content.php
|   |-- footer
|   |   |-- footer.css
|   |   `-- footer.php
|   `-- header
|       |-- header.css
|       `-- header.php
|-- make-page
|-- pages
|   |-- .bem
|   |   `-- level.js
|   `-- index
|       `-- index.bemjson.js
`-- README.md


Файлы *.php пустые, а в css файлах уже есть заготовка, типа такой:


.header
{
    /* ... */
}


В файлы *.php пишем какой-нибудь текст. В качестве примера в каждый из этих
файлов я просто написал его имя, а в css файлы тоже пишем что-то
экспериментальное. Дальше - самый интересный этап. Нужно все это собрать.

Для этого для начала создаем папку куда все это сложится:

$ mkdir ../wp-content/themes/yac/ -p


И собираем страницу index (еще раз скажу что в файле make-page я закоментил
вызов uglifyjs, так как он у меня не работал):


$ ./make-page index


Па-пам! Команда ничего не выдала - все удачно собралось. Проект выглядит
так:


.
|-- bempress
|   |-- bem
|   |   `-- techs
|   |       `-- php.js
|   |-- blocks
|   |   |-- content
|   |   |   |-- content.css
|   |   |   `-- content.php
|   |   |-- footer
|   |   |   |-- footer.css
|   |   |   `-- footer.php
|   |   `-- header
|   |       |-- header.css
|   |       `-- header.php
|   |-- make-page
|   |-- pages
|   |   |-- .bem
|   |   |   `-- level.js
|   |   `-- index
|   |       |-- index.bemdecl.js
|   |       |-- index.bemjson.js
|   |       `-- index.deps.js
|   `-- README.md
`-- wp-content
    `-- themes
        `-- yac
            |-- index.php
            |-- _script.js
            |-- __style.css
            |-- _style.css
            |-- style.css
            |-- __style.ie.css
            |-- _style.ie.css
            `-- style.ie.css



В папке bempress/pages/index/ появилось 2 файла index.bemdecl.js и
index.deps.js, а так же в папке wp-content/themes/yac/ появилось много
файлов.

index.php содержит в себе всю html часть, которая содержится в файлах
header.php, content.php и footer.php и в моем случае выглядит так:


header
content
footer


А файл style.css содержит в себе пожатый css и выглядит так:

.header{color:#00f}.content{color:red}.footer{color:silver}


Можно поиграться поменять php и css файлы, а потом пересобрать страницу
index и насладится результатом.

Так же очень просто создать еще одну страницу.


$ cd bempress/
$ bem create block 404 -l pages -t bemjson.js


Это команда создает пустой файл pages/404/404.bemjson.js.


.
|-- bem
|   `-- techs
|       `-- php.js
|-- blocks
|   |-- content
|   |   |-- content.css
|   |   `-- content.php
|   |-- footer
|   |   |-- footer.css
|   |   `-- footer.php
|   `-- header
|       |-- header.css
|       `-- header.php
|-- make-page
|-- pages
|   |-- 404
|   |   `-- 404.bemjson.js
|   |-- .bem
|   |   `-- level.js
|   `-- index
|       |-- index.bemdecl.js
|       |-- index.bemjson.js
|       `-- index.deps.js
`-- README.md


Пишем туда нечто похожее на index страницу:


({
    block: 'page',
    content: [
    { block: 'header' },
    { block: 'footer' },
    ]   
})


И собираем страницу:


$ ./make-page 404



.
|-- bempress
|   |-- bem
|   |   `-- techs
|   |       `-- php.js
|   |-- blocks
|   |   |-- content
|   |   |   |-- content.css
|   |   |   `-- content.php
|   |   |-- footer
|   |   |   |-- footer.css
|   |   |   `-- footer.php
|   |   `-- header
|   |       |-- header.css
|   |       `-- header.php
|   |-- make-page
|   |-- pages
|   |   |-- 404
|   |   |   |-- 404.bemdecl.js
|   |   |   |-- 404.bemjson.js
|   |   |   `-- 404.deps.js
|   |   |-- .bem
|   |   |   `-- level.js
|   |   `-- index
|   |       |-- index.bemdecl.js
|   |       |-- index.bemjson.js
|   |       `-- index.deps.js
|   `-- README.md
`-- wp-content
    `-- themes
        `-- yac
            |-- 404.php
            |-- index.php
            |-- _script.js
            |-- __style.css
            |-- _style.css
            |-- style.css
            |-- __style.ie.css
            |-- _style.ie.css
            `-- style.ie.css


Файл wp-content/themes/yac/404.php выглядит вполне ожидаемо:


header
footer


На этом этот подход к BEM для меня закончился. На github есть небольшая
библиотека блоков и в следующем подходе я планирую подключить эту библиотеку
к этому мега проекту, но пока мне совсем непонятно как это делать.

Спасибо что дочитали до этого места =)=)
toivonens написала
24 октября 2011 года, 17:45
userpic
Реализация и использование блока i-jquery

Блок i-jquery помогает подключить jQuery на страницу и упорядочивает хранение js-кода плагинов.

На уровне blocks-common блок i-jquery состоит из нескольких элементов, которые содержат плагины к jQuery. Декларация этих элементов обеспечивает подключение этих плагинов в страничный js.
Более подробно об этих элементах можно посмотреть в блоке github.com/.../i-jquery.

На уровне blocks-desktop есть дополнительный элемент core.

BEMHTML-реализация этого элемента позволяет подключать на страницы нужную версию библиотеки jQuery.

({
    block: 'b-page',
    title: 'Страница про ссылку',
    head: [
        ...
        { block: 'i-jquery', elem: 'core' },
        ...
    ],

Таким образом, для того, чтобы поддерживаемая версия jQuery оказалась на страницах, нужно использовать такой bemjson:

({
block: 'b-page',
title: 'Страница про ссылку',
head: [
...
{ block: 'i-jquery', elem: 'core' },
...
],

Этот шаблон не продуцирует DOM-представление элемента. Он декларирует использование на странице элемента js, блока b-page, подключающего js с jQuery.

Если мы решим перейти на новую версию библиотеки, просто изменим этот шаблон. И тогда у всех проектов, подключавших jQuery не вручную, а через блок i-jquery, своевременно изменится версия.

Можно перезаписать этот шаблон bemhtml-шаблоном на своём уровне переопределения (для всего проекта или только для некоторых страниц). В этом случае, используя те же самые входные данные, можно получать более подходящий проекту результат.
В директории элемента core в виде кода модификаторов элемента размещены совместимые с библиотекой версии jQuery в минимизированном состоянии. При помощи переопределения bemhtml-шаблона такими файлами можно пользоваться для оффлайн-разработки:

block i-jquery, elem core, default: {
    local(
        this._mode = '',
        this.ctx = {
            block: 'b-page',
            elem: 'js',
            url: '/bem-bl/blocks-desktop/i-jquery/__core/_version/i-jquery__core_version_1.6.2.js'
        }
    ) this.apply()
}
lento4ka написала
21 октября 2011 года, 14:10
userpic
Использование и реализация блока b-layout-table

Блок b-layout-table — таблица со 100% шириной, для создания раскладки.

BEMHTML шаблон блока выводит таблицу, строки и ячейки со всеми необходимыми атрибутами.

block b-layout-table {
    tag: 'table'
    elem row, tag: 'tr'
    this.elem === 'cell' || this.elem === 'gap' {
        tag: 'td'
        attrs: {

            var ctx = this.ctx,
                a = {},
                props = ['colspan', 'rowspan'], p;

            while(p = props.shift()) ctx[p] && (a[p] = ctx[p]);

            return a;
        }
    }
}

Ячейки блока могут быть представлены либо елементом cell, либо элементом gap.
Элемент cell предназначен для вложения контента, а элемент gap служит распоркой.

Давайте рассмотрим BEMJSON блока:

{
    block: 'b-layout-table',
    mods: { layout: '58-40'},
    content: [
        {
            elem: 'row',
            content: [
                {
                    elem: 'gap',
                    rowspan: '2'
                },
                {
                    elem: 'cell',
                    content: {
                        elem: 'inner',
                        content: 'Left cell'
                    }
                },
                {
                    elem: 'cell',
                    elemMods: { position: 'r'},
                    content: 'Right cell'
                }
            ]
        },
        {
            elem: 'row',
            content: [
                {
                    elem: 'cell',
                    colspan: '2',
                    content: 'Second row and one cell'
                }
            ]
        }
    ]
}

По умолчанию в блоке не задаются ширины ячейкам. Доопределить блок своими стилями можно следующим образом: добавляем модификатор блоку — mods: { layout: '58-40'} и ячейке — elemMods: { position: 'r'}.
Элементом inner оборачиваем контент ячеек, что позволяет задать нужные нам отступы. Далее, используя каскад, задаем нужные нам CSS свойства.

Вот такой CSS получится к BEMJSON, приведенному выше:

.b-layout-table_layout_58-40 .b-layout-table__cell_position_r
{
    width: 40%;
}

.b-layout-table_layout_58-40 .b-layout-table__gap
{
    width: 2%;
    padding-left: 20px;
}

.b-layout-table_layout_58-40 .b-layout-table__inner
{
    margin-right: 0.8em;
}

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

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

toivonens написала
20 октября 2011 года, 11:12
userpic
Материалы мастер-классов по БЭМ с YAC2011 на Vimeo

Видео мастер-классов про БЭМ, проходивших в 3м Зале на конференции YAC 2011, выложены на Vimeo.  Можно смотреть на iOS: через браузер и через приложение.

  1. Владимир Гриненко. Тема для WordPress в БЭМ.
    http://vimeo.com/30838628
  2. Лена Глухова, Варя Степанова. Дом из готовых кирпичей. Использование библиотеки bem-bl.
    http://vimeo.com/30819387
  3. Сергей Бережной. BEMHTML. Not yet another шаблонизатор.
    http://vimeo.com/30814503
  4. Варя Степанова. JavaScript в БЭМ-терминах.
    http://vimeo.com/30817887
toivonens написала
19 октября 2011 года, 16:51
userpic
Видео доклада "BEMHTML. Not yet another шаблонизатор" (Питер)

Видео доклада "BEMHTML. Not yet another шаблонизатор" со встречи разработчиков в Политехе (Питер).

Материал аналогичен одноимённому докладу на конференции YAC2011, но отличается большой секцией вопросов и ответов.

Это же видео опубликовано в коллекции БЭМ на Яндекс.Видео.

 

Что получается:    изменить 
Подписаться на комментарии к записи

Получать уведомления о всех ответах в этом обсуждении.

 
Отписаться от комментарев к записи

Получать уведомления только о тех ответах в этом обсуждении, которые адресованы лично вам.

 
К сожалению, комментарий не удалось отправить. Попробуйте ещё раз.я в курсе