Forum

Methodology

Toolbox

Platform

Community

Binding JS blocks to HTML

JavaScript components in i-bem.js are used for bringing a page HTML elements to life. The typical task of a JS block is to set reactions to events inside an HTML fragment.

In i-bem.js, the primary ”framework“ is the document HTML tree. Points are marked in it where interactive interface elements, the JS blocks, are connected. The binding point for a JS block is an HTML element (DOM node) whose class attribute specifies the name of the block, and the data-bem attribute specifies the block parameters.

When loading a page in the browser, blocks are initialized. This creates instances of blocks — JS objects for all the blocks mentioned in classes of the page HTML elements. A JS object bound to an HTML element handles the DOM events that occur on it and stores the states of this block instance.

This method of binding JavaScript components to HTML has the following advantages:

  • Natural degradation of the interface on clients with JavaScript disabled.
  • Progressive rendering — the ability to begin rendering interface elements before all the page data has finished loading (for example, images).

Mechanism for binding blocks

To bind a block to an HTML element (for example, <div>...</div>), it is necessary to:

  • Declare the block in i-bem. Create the ym module containing the JS implementation of the block (the declaration). To do this, pass a string with the block name as the first argument to the modules.define and BEMDOM.decl methods.
modules.define('my-block', ['i-bem__dom'], function(provide, BEMDOM){

provide(BEMDOM.decl(this.name,
    {
        /* instance methods */
    },
    {
        /* static methods */
    }
));

});

On the project level, each ym module is usually stored as a separate js file. For example, the my-block declaration might be stored in the project as my-block/my-block.js – the file my-block.js, inside the folder my-block.

  • Mark the block in the HTML tree.

    Add the class attribute with the block name to the HTML element.

    <div class="my-block">
     ...
    </div>
    
  • Allow initialization of a block instance.

    Include the i-bem class in the list of classes for an HTML element. The presence of this class will show the framework that the HTML element is connected to the JS block.

    <div class="my-block i-bem">
     ...
    </div>
    
  • Pass parameters to a block instance.

    Put block parameters in the data-bem attribute. Block parameters are written in JSON format as a hash of the format: block name : hash of parameters. The parameters will be passed to the block instance at the time of initialization.

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

The relation of blocks to HTML elements

A single HTML element doesn't have to correspond to a single block instance. The following relationships between blocks and HTML elements are possible:

One HTML element to one JS block

The simplest and most common way of binding blocks to HTML.

Example

The div HTML element with my-block placed on it. Block parameters: an empty list {}.

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

One HTML element to multiple JS blocks

The technique of placing multiple blocks on a single HTML element is called a mix in BEM methodology.

Example

The div HTML element, with the following blocks on it:

  • user with the parameter name: pushkin
  • avatar with the parameter img: http:// ...
<div class="user avatar i-bem" data-bem="{ " user="user">
 ...
</div>

One JS block to multiple HTML elements

This design is convenient if you need to coordinate the states of multiple components of a block.

To bind a block instance to multiple HTML elements, you must set the same value for the id parameter in the data-bem attribute. The value of id can be any string.

Example

An instance of the notebook block bound to the div and span HTML elements. The parameters specify the shared id — maintab.

<div class="user avatar i-bem"
    data-bem='{
        "user": { "name": "pushkin" },
        "avatar": { "img": "http://..." }
     }'>
     ...
</div>

As a result, when the blocks are initialized, a single JS object is created, with a domElem field that contains references to the jQuery objects of both DOM nodes.

For example, the ”tab“ widget, where a click on the tab title (the first HTML element) changes its content (the second HTML element). Another example is a placemark that marks a point on a map (the first element), and the related description of the point in the list next to it (the second element).

The id is used only at the time of initializing the block instance. The id value must be unique for instances of the same block in the context of a single wave of initialization.

Blocks without DOM representation

Infrastructure code that performs general interface tasks (access to the backend, or helper methods) can be formatted as a block. This allows expressing block states using modifiers, so that other blocks can subscribe to their changes.

To avoid binding these blocks to the HTML tree artificially, these blocks can be created in i-bem.js without DOM representation.

Blocks without DOM representation:

  • Do not require binding to a page's HTML code.
  • Must be explicitly initialized and destroyed.

Access to block instances without DOM representation

When creating a block instance without DOM representation, you must see to it that references to this instance are stored for blocks that need to interact with it.

See also:

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.