Better MV-ish Framework

From simple user interfaces to complex single-page applications using faster, server-side rendered and easy to learn framework

Learn more Download
level up your html

Level UP your HTML

Write code queries in your HTML. No need to learn a new syntax

<input data-query="val(newTodo)">
two-way data binding

Two-way data binding

Keep your model and view always in sync by using observables

this.newTodo = blocks.observable();
data manipulation

Work with data

Use built-in utility library for advanced & faster data manipulations

blocks([1, 2, 3]).map(/* code */) .filter(/* code */).each()(/* code */);

Performance

jsblocks is fast but we will not stop here. We have ideas how to make it even faster.
Download all performance test cases from here.

Rendering

rendering 1500 rows and 12 columns

jsblocks

Fastest
or 700ms

React

35% slower
or 950ms

Angular

310% slower
or 2200ms

Syncing Changes

repopulating table with different data 10 times

jsblocks

Fastest
or 1900ms

React

25% slower
or 2400ms

Angular

360% slower
or 6800ms

Working with data

executing map().filter().reduce()

jsblocks

Fastest
or 190k ops/sec

underscore

6x slower
or 32k ops/sec

lodash

9x slower
or 20k ops/sec

Hello World

<!DOCTYPE html>
<html>
  <head>
    <script src="http://jsblocks.com/jsblocks/blocks.js"></script>
    <script>
      blocks.query({
        firstName: blocks.observable('John'),
        lastName: blocks.observable('Doe')
      });
    </script>
  </head>
  <body>
    First Name: <input data-query="val(firstName)">
    Last Name: <input data-query="val(lastName)">
    <h2>Hello {{firstName}} {{lastName}}!</h2>
  </body>
</html>

Hello John Doe!

Animations

This example shows how easy it is to implement CSS3 Transitions.

<!DOCTYPE html>
<html>
<head>
    <link rel="stylesheet" href="style.css">
    <link rel="stylesheet" href="//maxcdn.bootstrapcdn.com/font-awesome/4.3.0/css/font-awesome.min.css">
    <script src="http://jsblocks.com/jsblocks/blocks.js"></script>
    <script src="script.js"></script>
</head>
<body>
    <input data-query="val(filterVal)" placeholder="Search for a block name">

    <div class="result-box" data-query="each(items.view)">
        <div class="tile" data-query="css('top', Math.floor($index() / 4) * 91).css('left', ($index() % 4) * 91)">
            <span class="fa fa-{{icon}}"></span>
            <h4>{{title}}</h4>
        </div>
    </div>
</body>
</html>
var items = [
  { icon: 'cubes', title: 'blocks' },
  { icon: 'exchange', title: 'bindings' },
  { icon: 'line-chart', title: 'speed' },
  { icon: 'database', title: 'data' },
  { icon: 'wrench', title: 'debugging' },
  { icon: 'server', title: 'architecture' },
  { icon: 'cube', title: 'modular'},
  { icon: 'cogs', title: 'extensible' },
  { icon: 'crosshairs', title: 'consistent' },
  { icon: 'lightbulb-o', title: 'innovative' },
  { icon: 'terminal', title: 'clean' },
  { icon: 'plug', title: 'feature rich' }
];
var filterVal = blocks.observable();
blocks.query({
  filter: filterVal,
  items: blocks.observable(items).extend('filter', function (value) {
    return !filterVal() || value.title.indexOf(filterVal().toLowerCase()) != -1;
  })
});
/* CSS Transitions */
/* The built-in classes shown below allow for easy CSS transitions */
.tile.b-hide-end {
    opacity: 0;
}
.tile.b-show {
    opacity: 0;
}
.tile.b-show-end {
    opacity: 1;
}


/* Other styles */
input { font-size: 16px;  padding: 12px 16px; margin-bottom: 40px;
    width: 326px;  background: #ddf4e8;  border: 1px solid #54b07e;}
.result-box {  position: relative;  text-align: center;  }
.tile {  position: absolute;  width: 86px; background-color: #3ebee3;
    height: 86px; color: #fff;  transition: 1s linear all;  }
.tile .fa {  margin-top: 20px;  font-size: 24px;  }
.tile h4 {  font-size: 14px;  margin: 15px 0;  }

blocks

bindings

speed

data

debugging

architecture

modular

extensible

consistent

innovative

clean

feature rich

Simple Application

This example is built using the MVC architecture that jsblocks offers. This powerful module lets you build complex applications. However, if you don't need this functionality you could always remove it to reduce file size.

<!DOCTYPE html>
<html>
<head>
  <link rel="stylesheet" href="style.css">
  <script src="http://jsblocks.com/jsblocks/blocks.js"></script>
  <script src="script.js"></script>
</head>
<body>
  <div id="products" data-query="view(Products)">
    <input data-query="val(newProduct.name).keydown(keydown)" placeholder="Add new value and press enter">
    <div data-query="each(products)">
      <div class="result-wrap">
        <span data-query="visible(!editing())" class="value-holder">
          {{name}}
        </span>
        <span data-query="visible(editing)" class="value-holder">
          <input data-query="val(name)">
        </span>
        <span class="buttons-holder">
            <span data-query="click(toggleEdit)">
              {{editing() ? 'Update' : 'Edit'}}
            </span>
            <span data-query="click(remove)" class="btn-delete">Delete</span>
        </span>
      </div>
    </div>
  </div>
</body>
</html>
var App = blocks.Application();

var Product = App.Model({
  name: App.Property(),

  editing: blocks.observable(false),

  toggleEdit: function () {
    this.editing(!this.editing());
  },

  remove: function () {
    this.destroy(true);
  }
});

var Products = App.Collection(Product);

App.View('Products', {
  newProduct: Product(),

  products: Products([{ name: 'HTML' }, { name: 'CSS' }, { name: 'JavaScript' }]),

  keydown: function (e) {
    if (e.which == 13) {
      this.products.add(this.newProduct);
      this.newProduct.reset();
    }
  }
});
#products > input {
    font-size: 16px;
    padding: 12px 16px;
    width: 326px;
    background: #ddf4e8;
    border: 1px solid #54b07e;
}
.result-wrap {
    margin-top: 10px;
    border: 1px solid #dcdcdc;
    background: #fbfbfb;
    width: 360px;
}
.result-wrap .buttons-holder {
    display: table-cell;
}
.buttons-holder > span {
    cursor: pointer;
    margin-left: 10px;
    color: #2d8dc4;
}
.buttons-holder .btn-delete {
    color: #e65f5f;
}
.result-wrap .value-holder {
    display: table-cell;
    border-right: 1px solid  #dcdcdc;
    width: 220px;
    padding: 10px;
}
HTML
CSS
JavaScript
The Web