How to use m.js Short code - simple usage

How to use m.js

How to use m.js - m-framework.com

Using m.js, in addition to the trivial asynchronous connection, has some interesting code-running features. The module loader and their CSS are built into m.js.

About everything in order.

How to connect m.js from our CDN:

...
<script src="https://cdn.m-framework.com/js/1.1.min/m.js" async></script>
</body>

Or from a local copy obtained from GitHub:

...
<script src="/js/m.js" async></script>
</body>

The `async` attribute in the script tags is recommended by Google PageSpeed ​​Insights to speed up the page. We decided to take the issue of asynchrony seriously, and even connect the main m.js script asynchronously.

What m.js can do itself is told on a separate page.

How are modules loaded and where is the site.js, init.js, or start.js script? They are absent. And we'll explain why.

Consider a simple example with the gray scroll button at the bottom right of the window, you could already see on the pages of this site. This button scrolls the page to the top when clicked, responsible for a separate module for several lines of code.

How this module is initiated:

<a class="scroll-up"
data-m-action="scroll2"
data-m-context="#top"
data-m-auto-hide="true"></a>

As you can see, tag A has the data-m-action attribute, which determines which module to connect to. The following data-m-context tag contains a text selector for passing an argument module to which some actions can be taken. That is, m.js asynchronously connects to the body of the page a script from the /app/ sub-directory from the same place where m.js placed, defines an element after the selector with data-m-context and invokes the module function with the this context of element in this case. A and with an argument in the form of a predefined element.

It sounds a bit difficult, but let's look at the code of the simple module mentioned:

if (typeof m == 'undefined') {
var m = function () {};
m.fn = m.prototype = {};
}
m.fn.scroll2 = function(context) {

if (typeof context == 'undefined' || context === null || !(context instanceof m))
return false;

var
top = this.data.top || 0,
scroll_link = this,
scroll = function() {
var scroll_elem = parseInt(m('document').first.scrollTop) == 0 &&
parseInt(m('body').first.scrollTop) !== 0 ? m('body') : m('document');
scroll_elem.animate({
scrollTop: parseInt(m(context).first.offsetTop) + parseInt(top)
}, 300);
};

if (this.length == 0) {
return scroll();
}

this.on('click', function(e) {
e.preventDefault();
scroll();
});

if (this.attr('data-m-auto-hide') !== null) {
m('window').on('scroll', function (e) {
scroll_link.css({
visibility: parseInt(window.scrollY) <= parseInt(m(context).first.offsetTop) ? 'hidden' : 'visible',
opacity: parseInt(window.scrollY) <= parseInt(m(context).first.offsetTop) ? 0 : 1
});
});

m('window').event_fire('scroll');
}

return true;
};

Initially, in the code of each module, we are reassured in case m.js has not yet been loaded and the module script has been declared earlier (asynchrony) and we create an empty m.fn object of function m. We further extend the set of fn by our module, in which the context of this is an A tag, in which data-m-action="scroll2" was specified, and the context argument for the selector with data-m-context. The code then defines the scroll function itself, manipulates the helper attribute to hide the button, and most importantly, binds an event to click on A (ie this) and call the scroll function. The context element is used to define its position and scroll to that position.

For ease of perception, let's say that the initiator element of an event is an element with a given data-m-action and the element relative to which actions will be taken is an element behind the selector data-m-context, so the selector should be as unique and exhaustive as possible.

There are times when an action must be taken against the same initiator element. In this case, you can simply not specify data-m-context, our m.js will pass the argument to the same initiator element. This is quite convenient, for example in the modal_click module and with the image in the header of this article.

As you may guess, we strongly do not recommend using separate files to initiate modules or functions (no any init.js, site.js or else). All that is enough is to specify in the HTML attribute of the element which module should work with it.

Our JS framework has the following function which, as you can see, is called automatically:

(function() {
...
m('[data-m-action]').init();
})();

That is, for each element with the data-m-action initiator attribute, a magic init() function will be executed from the m.fn stack. It is this function that will check whether the asynchronous script named module has already been plugged into the body of the page, will try to connect it and the corresponding CSS by the same name, will try to call the module function with the necessary context this and argument. This approach significantly speeds up the page load and makes sure that only the required modules are loaded into the document without unnecessary traffic. Using nginx and HTTP/2, module delivery is cached, which greatly speeds up the site.

It should be noted separately that the same element can be an initiator for several modules (their names in this case should be written in space). Such complex behavior is rarely used and we hope that for simple tasks you will have enough ready-made standard modules.

Check out internal functions in m.js and a set of modules from /app/, which can be called via the attribute data-m-action.

Users comments


Sorry you cant to leave a comment. Try to authorize yourself via login and password or use a one of social networks below: