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!

No comments:

Post a Comment