📜 ⬆️ ⬇️

jQuery.BEM - a declarative approach to working with the imposition of the BEM method

Already a lot has been said about BEM, what is good and what is bad, and we will not repeat today. Below is a story about how to work with BEM DOM from jQuery in small projects where conscience and time do not allow you to fasten bem-tools, bem-bl and bemhtml, but you still want to work with a convenient layout system, leaving behind long selectors in js files.

I invite those interested under the cat, for details and examples of use.


Methodology


BEM (abbr. Block Element Modifier) ​​is a special way of organizing HTML layout, which greatly facilitates the development and support of more or less large sites and web applications.

I will not completely introduce you to the course on the matter of methodology, recently it has become very popular and there are plenty of materials from which to gather information. But if it turned out that you still have not heard about BEM and its benefits, I recommend to take a look:
')


To the uninitiated, I double recommend you to watch the lecture, firstly: you don’t need to read anything, there’s a video, secondly: everything is explained better than the first option and the brain sets off with a bang.

Why another implementation?


Not to say that there are so many such gizmos, the only close analogue is the i-bem framework from the bem-bl library, but making it work outside the native habitat will be quite problematic.

Yandex bem-tools, bem-bl and all the fuss with the builders and templating engines is undoubtedly cool. But until we have grown to a project with a couple of hundred templates, all this will be more likely to interfere. Suppose we have a small online store at hand, in some lightweight PHP framework. Here, all this is gun shooting at sparrows, however, there will always be a favorite customer nearby who will always want to change something.

The methodology has already proven itself in the convenience of scaling, and jQuery.BEM is the best opportunity to work with BEM layout from JavaScript without the use of thick, complex technologies. All you need is jQuery, the jQuery.BEM plugin and the BEM custom page.

I’m not claiming that jQuery.BEM is the best implementation of this action, it can easily lose the same i-bem in performance due to difficult DOM travels, but it’s the best and most convenient at the moment.

Work with elements


Suppose we have several blocks of goods:

<div class="b-product"> <div class="b-product__name">Coffe</div> <div class="b-product__price">$2</div> </div> <div class="b-product"> <div class="b-product__name">Tea</div> <div class="b-product__price">$1</div> </div> 


We need to perform some action with the children of the first block:

 $('.b-product').first().children('.b-product__name'); // jQuery $('.b-product').first().elem('name'); // jQuery.BEM 


With jQuery.BEM, the record is shorter. The difference in a couple of bytes is, of course, a dubious advantage, but in production .elem () makes life easier if the block, for example, needs to be suddenly renamed.

Work with modifiers


Add a modifier

 <div class="b-product">...</div> 

 $('.b-product').setMod('theme', 'premium'); //  .b-product.b-product_theme_premium $('.b-product').setMod('premium'); //  .b-product.b-product_premium_yes 


Remove the modifier

 <div class="b-product b-product_theme_premium">...</div> 

 $('.b-product').delMod('theme', 'discount'); //   -    .b-product.b-product_theme_premium $('.b-product').delMod('theme', 'premium'); //   .b-product_theme_premium $('.b-product').delMod('theme'); //   theme    


We get the modifier

 <div class="b-product b-product_theme_premium">...</div> 

 $('.b-product').getMod('theme'); //  "premium" $('.b-product').getMod('discount'); //  null 


Check the modifier

 <div class="b-product b-product_theme_premium">...</div> 

 $('.b-product').hasMod('theme'); // true $('.b-product').hasMod('theme', 'premium'); // true $('.b-product').hasMod('theme', 'discount'); // false 


Filter the blocks by modifier

 <div class="b-product b-product_theme_premium">...</div> <div class="b-product">...</div> 

 $('.b-product').byMod('theme', 'premium'); //  $('.b-product.b-product_theme_premium') $('.b-product').byMod('theme'); //  $('.b-product.b-product_theme_premium') $('.b-product').byNotMod('theme'); //  $('.b-product').not('.b-product_theme_premium') 


Block declarations



In addition to the class naming system, the BEM killer features are declarations. They allow great ease to work with the logic of the blocks, at least just visually separating them from each other.

 bem.decl('b-product', { onInit: function($this) { //   price  size   large   DOM   // $this   —  jQuery  $this.elem('price').setMod('size', 'large'); }, title: { onMouseover: function($this) { //   b-product  state   hover $this.up().setMod('state', 'hover'); //  -   this._customFunction(); }, _customFunction: function() { console.log('I am helper function'); } }, price: { onSetmod: function($this, e, modKey, modVal) { //         price console.log('Modifier set:', modKey, modVal); }, onDelmod($this, e, modKey, modVal) { // } } }); 


You can only declare blocks or elements with certain modifiers, as well as individual elements of the block:

 bem.decl({ block: 'b-product', mod: 'theme:premium'}, { // }); bem.decl({ block: 'b-product', elem: 'price' }, { // }); 


All events are popup and are posted on the document method $ (document) .on (...), so you do not need to redefine the declaration when the DOM changes on the client side.

Blocks can communicate with each other by events, the function starting with “on ...” hangs a handler on the object, so you can make $ ('. B-block'). Elem ('title'). Trigger ('on ... ');

Syntax Override


By default, syntax parameters follow the original BEM. If you need to get rid of the need to use prefixes (b-, l-, g-, etc) or change the separator of the block and element from "__" to something more convenient, use:

 bem.setConfig({ namePrefix: '', //  ,   elemPrefix: '-', //   modPrefix: '_', //   modDlmtr: '-' //     }); 


Now the class names in our HTML should look a bit different.

 .block .block-element .block-element_modifier-value 


Finally


The plugin, under the MIT license, is available on GitHub . I would be glad if he would make life easier for someone and bring benefits. Always glad to reasoned criticism and questions.

Source: https://habr.com/ru/post/196368/


All Articles