The ultimate layout engine for backend and frontend

I have created a lot of sites over the years and the single biggest problem I have, an always face is the layout engine. The layout engine is the way a view is mapped with data and outputted onto the page.

Backend libraries and frameworks have a tough choice of choosing between:
- fixed templates, predefined and hardcoded, less flexible
- loose templates, built using reusable blocks, look messy and unexpected results

Frameworks such as Drupal and Wordpress go for the flexible solution. However users end up overriding them using fixed templates because of the way they are structured. They also suffer from being far too complicated to edit and update and confusing users into putting the files in the wrong places.

So how can we solve this? We need a solution that sits firmly in the middle of fixed and flexible. The key is to determine which elements should be fixed and which should be flexible.

The solution is to have a flexible layout grid (rows and columns) with fixed module templates (item html). This works well because you retain control of both but in separate places. This is the basis behind the ultimate layout engine which I've developed.

backend code
- list of pages with urls (if the url is all then it will be shown on all pages)
- list of view templates that appear on each page
- each view specifies where it appears on the page using a row and col number
- each view also species which model (data) table and corresponding model (data) row should be mapped to it

The layout table

url view row col model modelrow
all Head 1
1
all Logo 1 1 1 0
all Contact 1 2 1 0
all Navigation 2 2 1

Banner 3 2 2 1

TextSmall 4 2 2 1

Highlights 4 2 1
events BannerText 3 1 3 0
events Highlights 3 2 1
all Foot 1
1

the logic of this table:
- loop through each item
- if item url equals the current page url, or the item url equals 'all' then render the view using the model table and model row
- then add each render view into an array of rows and cols for the page
- If no row or col values exists then don't put them inside a row and col, put them as their own item in the array.

Here is an example of the view rendered with model data, then put into an array in the correct order based upon it's row and col numbers:

The layout array

var data = [
    {
        'type': 'Head'
        'data': '<div class="head">head html</div>'
    },
    {
        'type': 'row'
        'data': [
            {
                'type': 'col',
                'data': '<div class="banner">banner 1 html</div>'
            }
        ]
    },
    {
        'type': 'row'
        'data': [
            {
                'type': 'col',
                'data': '<div class="text">text 1 html</div>'
            },
            {
                'type': 'col',
                'data': '<div class="text">text 2 html</div>'
            },
            {
                'type': 'col',
                'data': '<div class="text">text 3 html</div>'
            }
        ]
    }
]

the logic for this next step is to:
- loop through each item in the layout array
- if the type is not row or col then output the data html
- if the type is a row then create a row html
- if the type is a col then create col html
- add the inner html inside the col and output to the page

And this is how our html will look after all of this:

<div class="head">head html</div>
<div class="row">
    <div class="col">
        <div class="banner">banner 1 html</div>
    </div>
</div>
<div class="row">
    <div class="col">
        <div class="text">text 1 html</div>
    </div>
    <div class="col">
        <div class="text">text 2 html</div>
    </div>
    <div class="col">
        <div class="text">text 3 html</div>
    </div>
</div>

If you want more control over the layout then you can add some more columns to the layout table which contain classes for each row and col.

The layout table with row and col classes

url view row col model modelrow rowclasses colclasses
all Head 1
1
row980
all Logo 1 1 1 0 row980
all Contact 1 2 1 0 fill1of3
all Navigation 2 2 1
row980

Banner 3 2 2 1 row980

TextSmall 4 2 2 1 row980

Highlights 4 2 1
fill1of3
events BannerText 3 1 3 0 row980
events Highlights 3 2 1
all Foot 1
1
row980

Very simple logic, which makes your views much easier to maintain as they don't contain layout containers:

<div class="text">{{ item.name }}</div>

Hope that helps you!

Client-side compression techniques

There are lots of different ways to compress data, here are a few examples of common algorithms:

Index Compression
Values are saved in a flat store with an index number referencing each value. The more values that are the same the better results you will get with this.


Shared Dictionary Compression
Similar to index compression but the dictionary file of values is stored externally from the compressed string, which greatly reduces the size, but requires the dictionary file to be downloaded and stored for compression and decompression.


Huffman Compression
Loops through every single character value and creates a probability of how often it is used, then it creates a tree of values which can be navigated by switching left or right in the tree.



LZ Compression
Using the zip algorithm which matches repeating patterns in your binary data. This gives even better better results than index compression but require more cpu and time.

Each compression technique has different advantages and disadvantages depending on your data type and processing power available. However the options are reduced when you need to run these algorithms in the browser.


I've created my own version of Index compression which supports strings, arrays and json:
http://jsfiddle.net/kmturley/MCzN7/13/



JavaScript performance tests of different methods and libraries:
http://jsperf.com/json-compression/5

From my tests the JSONH library is not only the fastest library to pack and unpack, but it created a fairly small size string and the library is not very large. So I would choose this over any other method for compression client side.

Here's a real world example of compressing data using JSONH, then storing it in LocalStorage for retrieval later on:


function set(key, value) {
    var item = JSONH.pack(value);
    localStorage.setItem(key, JSON.stringify(item));
    return item;
}

function get(key, value) {
    var item = JSON.parse(localStorage.getItem(key));
    return JSONH.unpack(item);
}


var packed = set('people', data);
var unpacked = get('people', packed);

And a real-world example showing 58% of the size after compression which takes around 0.26 of second:
http://jsfiddle.net/kmturley/8cMY5/5/