Create a JS-based custom template from scratch

Blogger's templating language is a bit clunky, and as a result there are many template authors out there who are using JS-based solutions to develop custom templates.

But, even when you're inspired to do so, it's hard to know where to get started. This article covers creating a very basic custom template, with a few customizable skin settings, based on the Mustache JS templating language. To see the sad-looking output that this creates, you can view the demo.

An empty shell

First things first, we need to start from a template that is very, very empty, but passes the minimum validation requirements that Blogger has. The below snippet is an example of a very empty starting-point.

The main chunk of data that we need in order to produce the posts to be shown for any given view is all found in the Blog Posts gadget.

<?xml version="1.0" encoding="UTF-8" ?>
<!DOCTYPE html>
<html b:css='false'
      b:defaultwidgetversion='2'
      b:layoutsVersion='3'
      b:responsive='true'
      expr:dir='data:blog.languageDirection'
      xmlns='http://www.w3.org/1999/xhtml'
      xmlns:b='http://www.google.com/2005/gml/b'
      xmlns:data='http://www.google.com/2005/gml/data'
      xmlns:expr='http://www.google.com/2005/gml/expr'>
  <head>
    <meta content='width=device-width, initial-scale=1' name='viewport'/>
    <title><data:view.title.escaped/></title>
    
    <b:include data='blog' name='all-head-content' />
  </head>
  <body>
    <b:section id='widget-placeholders' preferred='yes'>
      <b:widget id='Blog1'
                locked='true'
                title='Blog Posts'
                type='Blog' />
    </b:section>
  </body>
</html>

Extracting the blog posts

The main task to get a JS-based template running is extracting the data we need from the Blog Posts gadget. Blogger's gadgets have their data scoped, not globally available, so to have the per-gadget data in the Blog post global, we'll need to put it in a global JS object.

To do this, we override the markup for the Blog to spit out the needed JS object, then call the normal markup. While the normal output isn't shown to the user, it ensures that a crawler with no JS won't see empty content (which would make our search engine rank suffer).

The following snippet extracts a few fields from the posts, building an array.

<b:widget id='Blog1' locked='true' title='Blog Posts' type='Blog' visible='true'>
  <b:includable id='main' var='this'>
    <b:comment>We override the main includable, to dump the data in the global JS dict</b:comment>
    <script>
      window.blogger.widgets.<data:widget.instanceId.jsEscaped /> = {
        sectionId: '<data:widget.sectionId.jsEscaped />',
        data: {
          title: '<data:this.title.jsEscaped />',
          description: '<data:this.description.jsEscaped />',
          posts: [<b:loop var='post' values='data:this.posts' index='i'>
            {
              title: '<data:post.title.jsEscaped />',
              body: '<data:post.body.jsEscaped />'
            }<b:if cond='data:i lt data:posts.size'>,</b:if>
          </b:loop>]
        }
      };
    </script>
    <b:include name='super.main' />
  </b:includable>
</b:widget>

Using the data in JS

This article covers Mustache JS in particular, but the code to consume the global dictionary could easily be ported to your favourite JS templating language (e.g. jsrender, PURE, or whatever you're into!).

We author up the template that the DOM will use, then we execute the template's render, and set the main div's content to be the result.

<script src='https://cdn.rawgit.com/janl/mustache.js/master/mustache.js' />
<script>
  window.blogger = {
    widgets: {}
  };
  document.addEventListener(
    'DOMContentLoaded',
    function () {
      var allData = _WidgetManager._GetAllData();
      window.blogger.blog = allData.blog;
      window.blogger.skin = allData.skin;
      window.blogger.template = allData.template;
      window.blogger.view = allData.view;
      var template = document.getElementById('template').innerHTML;
      document.getElementById('main').innerHTML =
        Mustache.to_html(template, window.blogger);
    });
</script>

The body template

<b:comment>This is the Mustache template for the whole page.</b:comment>
<script type='text/json' id='template'>
  <h1>
    <a href='{{blog.canonicalHomepageUrl}}'>
      {{blog.title}}
    </a>
  </h1>
  <p class='blog-description'>
    {{blog.description}}
  </p>

  {{#widgets.Blog1.data}}
  <div class='posts'>
    {{#posts}}
    <div class='post'>
      <h3 class='post-title'>{{title}}</h3>
      <div class='post-body'>
       {{body}}
      </div>
    </div>
    {{/posts}}
  </div>
  {{/widgets.Blog1.data}}
</script>

The final product

You can view (and take a copy if you want!) the full source of this very basic starting point, including a very simple custom skin with some basic variables, here, and you can view the (sad looking) running sample at https://js-template.blogspot.com.au/

Happy custom templating!

Comments

  1. Thanks for sharing this.

    While going through the code, I noticed b:css='false' attribute on the HTML tag. I am assumming this is for removing the default CSS that Blogger includes.

    My question is that, is there a similar attribute available for removing the default JavaScript included by Blogger (near the end of BODY tag)

    ReplyDelete
    Replies
    1. Prayag, thanks for the tip with the b:css, so useful!!! Thanks!

      Maybe they will implement our requests:
      https://productforums.google.com/forum/#!topic/blogger/9bSv26VRqMY (feedback related to JS)
      https://productforums.google.com/forum/#!topic/blogger/ogla7TG1Jw4 (feedback related to postMetadataJSON)
      https://productforums.google.com/forum/#!topic/blogger/o5ogDpFwFBk (feedback related to COOKIE NOTICE)
      https://productforums.google.com/forum/#!topic/blogger/dS1utcOZ1qI (feedback related to isMobileRequest)

      Delete
  2. This comment has been removed by the author.

    ReplyDelete

Post a Comment

Popular posts from this blog

Remove the header image for posts in Emporio

Rotate my Blogger images

Add snippets to the Emporio theme