Forum

Methodology

Toolbox

Platform

Community

Block structure

JavaScript-enriched block

Prerequisites

Block i-bem and its dom element, with all their dependencies, must be included into your page js file. This happens automatically if you borrow the project structure from the project-stub repository.

HTML structure

Any BEM block can be equipped with JavaScript. To do this, you just need to place a JavaScript file into your block directory.

desktop.blocks/
    my-block/
        my-block.js

Then, just mark a block with a js flag when declaring it in BEMJSON.

{
    block: 'my-block',
    js: true
}

This gives (after running BEMHTML templates on the JSON) a corresponding DOM node marked with an i-bem class and having data-bem attribute with the block parameters.

<div class="my-block i-bem" data-bem="{'my-block':{}}">
    ...
</div>

If you are not using BEMHTML templates, instruct your templates to produce the same output or write this HTML manually.

The data-bem attribute stores block parameters in JSON, which structure is:

{
    "my-block" : {
        "paramName": "paramValue"
    }
}

The console.log example

pure.bundles/
    001-simple-block/
        blocks/
            my-block/
                my-block.js
        001-simple-block.bemjson.js
        001-simple-block.html

The first example is the most simple. It demonstrates the block structure and shows how the JavaScript starts working.

Load the example page 001-simple-block with your console tool open, and you can see the outerHTML of the my-block on the page.

The BEMJSON declaration of the example 001-simple-block.bemjson.js describes a simple page with only one my-block component.

The my-block component is represented on the 001-simple-block/blocks level with a JavaScript file. The my-block.js file is filled with a simple piece of code.

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

provide(BEMDOM.decl(this.name, {
    onSetMod: {
        'js' : {
            'inited' : function() {
                console.log(this.domElem[0].outerHTML);
            }
        }
    }
}));

});

The i-bem framework utilizes a special module system ymaps/modules, so the first line defines which modules to use for the component.

In this case it is i-bem__dom, a module represented as a dom element of i-bem block from bem-core library.

Inside you can use the BEMDOM object and its decl method to describe a block.

The block name is the first parameter.

The second is a hash of dynamic properties of the block. Every instance of the block gets a copy of them.

Aside from custom properties, the hash can also contain some special ones. You can see one of them, an onSetMod property in the example. It is used to store callbacks to run when a block gets a modifier.

BEMDOM.decl(this.name, {
    onSetMod: {
        'foo' : function() {
            // Runs when a block gets any value of `foo` modifier.
            // This also works for 'boolean' modifiers
        },
        'bar' : {
            'qux' : function() {
                // Runs when a block gets 'qux' value of 'bar' modifier
            },
            '' : function() {
                // Runs when `bar` modifier is removed from a block
            },
            '*' : function() {
                // Runs for any value of 'bar' modifier
            }
        },
        '*' : function() {
            // Runs for any modifier of the block
        }
    }
});

These callbacks get following parameters:

function(modName, modVal, currentModVal) {

    // modName
    // Modifier name is operated

    // modVal
    // Modifier value to be set. It is a `String` for modifiers with values
    // or `true`/`false` for boolean modifiers

    // currentModVal
    // Current value of the modifier

}

The first modifier any block gets is a js modifier with its inited value.

The framework core reads all the i-bem marked blocks on a page and then initializes them and sets the js_inited modifier on each block.

Thus, you can write a code to be run after the block starts functioning by defining a callback to the js_inited modifier.

In the example presented above, this code is a console.log call with the block outerHTML.

If you notice a mistake or want something to supplement the article, you can always write to us at GitHub, or correct an article using prose.io.