A very easy, clean and extensible way to build interactive web-based user interfaces.


Keywords
reactive, proxy, javascript, dom
License
MIT
Install
npm install m2d2@2.2.1

Documentation

M2D2

MIT Licence Open Source Love npm version npm downloads

Extensions: Alerts | Language | Storage | XHR | Upload | WebSocket

A class to easily place data in DOM and update them immediately upon change. It has no dependencies. It is similar to Angular, Vue, ReactJS and alike frameworks and shares some similarities with JQuery.

The main goal of this framework is to keep the HTML and JS pure and clean, without having to either setup rules in the HTML (like in Angular), use HTML templates inside Javascript like in React, or use mixed templates like Vue.

If you know Javascript and HTML you pretty much know 98% of M2D2 already. Because of that, it has a small learning curve, so you don't need to spend hours trying to understand how the framework works or how you can apply it to your work.

This framework can work together with any other as it is just pure Javascript. Although, once you use it, you will like how clean your code can be.

Is M2D2 for you?

These are some reasons why you may be interested in using M2D2:

  • I deploy mainly for modern browsers (no Internet Explorer, for example)
  • I like to keep my HTML and my Javascript codes clean and simple
  • I like Javascript, but I would like to update the HTML in an easier way
  • I have used JQuery, but I want to make my code to react to value changes automatically
  • I don't want to spend too much time in learning a new framework
  • I really don't like to have all my code in a single file
  • I have some JQuery or Javascript libraries that I would like to use
  • I don't want very complicated codes to achieve simple things

If you checked one or more of the above boxes, M2D2 will suit you well.

Framework/Library comparison:

M2D2 JQuery Angular ReactJS Vue
Size 19Kb 88Kb 60Kb 166Kb 181Kb
Easy to learn Yes Yes No No No
Clean and standard HTML Yes Yes No Yes No
Clean Javascript Yes Yes Yes No Yes
Good for small projects Yes Yes No Yes Yes
Good for large projects Yes No Yes Yes Yes
Observe object changes Yes No Yes Yes Yes
Large community No Yes Yes Yes Yes

Repositories (synchronized):

Hello World


// When DOM is ready...
m2d2.ready($ => {
    // Place text in #myid :
    $(myid, "Hello World");
    
    // Then, change it into something else:
    myid.text = "Hola Mundo";
});

To better understand how M2D2 works, let's imagine you have this object:

const user_data = {
    user_id : 1289943,
    first_name : "Beth",
    middle_name : "Eleonor",
    last_name : "Wilson",
    age : 35,
    emails : [
        "beth900@example.com",
        "beth.wilson@example.com"
    ]
}

Now, we want to place that information in this HTML:

<div id="user">
    <div><span>ID:</span><span class="user_id"></span></div>
    <div><span>First Name:</span><span class="first_name"></span></div>
    <div><span>Middle Name:</span><span class="middle_name"></span></div>
    <div><span>Last Name:</span><span class="last_name"></span></div>
    <div><span>Age:</span><span class="age"></span></div>
    <div>
        <span>Emails:</span>
        <ul class="emails"></ul>
    </div>
</div>

This is what you need to code (for example: user.js):

m2d2.ready($ => {
    const user = $("#user", user_data);
})

And that's it! ... But what if user_info doesn't match our HTML structure?

for example this one:

<div id="user">
    <div><span>Name:</span><span class="name"></span></div>
    <div><span>Email:</span><span class="email"></span></div>
</div>
m2d2.ready($ => {
    // Assuming we don't have empty fields (for simplicity)
    const user = $("#user", {
        dataset : { id : user_info.user_id }, // will create `data-id=` attribute in `#user`
        name  : user_info.first_name + " " + user_info.middle_name[0].toUpperCase() + ". " + user_info.last_name,
        email : user_info.emails[0]
    });
})

... and that's it! ... But what if you need to interact with it (using events) ?

m2d2.ready($ => {
    const user = $("#user", {
        /* ... */
        email : {
            text : user_info.emails[0],
            onclick : function(ev) {
                window.location.href = "mailto:" + this.text;
            }
        }
    });
})

... and that's it! ... But what if ... ?

Read the documentation, try the tutorial or the examples:

Quick Start:

5 minute reading

General Recommendations

Best practices when using M2D2

Tutorial:

Learn it now using jsfiddle

Live Demo:

Stand-alone html + js examples

Documentation:

M2D2 Reference

Install


You can use this library either with Web or NodeJS, Framework7, etc.

For the Web

Option 1 : Get M2D2 using npm / yarn

npm web page | yarn web page

npm i m2d2

or

yarn add m2d2

Then you will find the library files under node_modules/m2d2/dist/ (more about this below).

Option 2 : Direct download

Core Only (~19Kb): m2d2.min.js and set it in the HTML head.
With all extensions (~29Kb): m2d2.bundle.min.js and set it in the HTML head.

Option 3 : CDN

Core Only: m2d2.min.js
With all extensions: m2d2.bundle.min.js

To use it:

m2d2.ready($ => {
    // your code here
});

As Module

Using npm:

npm i m2d2

Then you will use it something like:

import m2d2 from 'm2d2';
const $ = m2d2.load();

You can use it together with JQuery, or with Framework7 or any other framework of your choice.

Extensions:

Alert


This extension makes it easy to display alerts, confirmation, input dialogs and more.

Example:

$.confirm("Are you sure?", "This is important", res => {
    if(res) {
        // Do something
    }
});

Try it (UTF8 Icons) Try it (FontAwesome) Try it (Google Material) or Learn about it

Storage


This extension provides an easy way to save and restore data into localStorage and sessionStorage.

Example:

// Store something in the localStorage:
$.local.set("key", { age: 20 });
console.log($.local.get("key"));

Try it or Learn about it

Lang


With this extension you can handle multiple languages easily.

Example:

$.lang('fr');
const _ = $.dict;
console.log(_("yes"));

Try it or Learn about it

XHR


This extension handles almost any kind of HTTP request to a server (e.g., GET, POST, PUT, DELETE, etc.)

Example:

$.put("/my/url", { name : "Tony" }, res => {
    // res = response from server
});

Try it or Learn about it

Upload


This extension makes it easy to upload files to a server via XHR (included in XHR bundle).

Example:

$("uploadFileButton", {
    onclick : function(event) {
        $.upload(event, {
            upload : "example.com/upload/",
            field  : "file",
            onDone : (response, allDone) => {
                console.log("Uploaded");
            }
        });
    }    
});

Learn about it

WS


This extension gives you an easy-to-use WebSocket client.

Example:

$.ws.connect({
    host    : "example.com",
    path    : "ws/",
    secure  : true, // for wss://
    request : {} // initial request
}, json => {
    // json is the data received from server
    if(json.user) { /* ... */ }
});
// Send a message to server:
$.ws.request({
    user : { id : 1000 }
});

Try it or Learn about it

Bundle Packs:


For your convenience, there are some minimized files included in each release (you can find them under dist/ directory if you install via npm or download them clicking on the file name):

Core Alert Storage Lang XHR WS Size
m2d2.min.js Yes No No No No No 19K
m2d2.bundle.xhr.min.js Yes Yes Yes Yes Yes No 28K
m2d2.bundle.ws.min.js Yes Yes Yes Yes No Yes 27K
m2d2.bundle.min.js Yes Yes Yes Yes Yes Yes 29K

Import:


You can import M2D2 in this way:

import m2d2 from 'm2d2'         // You get m2d2.bundle.min.js
import m2d2 from 'm2d2/core'    // You get m2d2.min.js
import m2d2 from 'm2d2/ws'      // You get m2d2.bundle.ws.min.js
import m2d2 from 'm2d2/xhr'     // You get m2d2.bundle.xhr.min.js

What's New in version 2.0:


This library was almost completely rewritten in v2.0. The main difference is that in 1.x, the M2D2 object was mainly a Proxy object which upon change, updated the DOM. However the main issue was that if you changed the DOM directly, there was no way to update the M2D2 object automatically, and thus could have side effects. In 2.x, the M2D2 object is a Node/HTMLElement wrapped around a Proxy and extended, which means that you can safely change the DOM directly without having side effects. Because now the M2D2 object is a DOM element, you have access to everything through vanilla javascript (like classList, appendChild, style, etc), which greatly simplified things.

Other big difference with v2.0 is that you can split your code across several small files in a very easy way (very useful if you use tools like 'gulp' to concatenate and minify your code).

Developing

To modify or contribute to this code, start by cloning this repository.

Then execute: npm install

To compile, execute: gulp

To run all tests, execute: npm test

Acknowledgments:


Developed with IntelliJ Ultimate Edition. I would like to thank JetBrains for their support.