Skip to main content

Ralsina.Me — Roberto Alsina's website

New in Nikola v6 part II: We Love Javascript

I am plan­ning to do a ma­jor re­lease (ver­sion 6!) of Niko­la my stat­ic blog and site gen­er­a­tor the next week­end. It's a ma­jor ver­sion be­cause there has been a ton of fea­ture work done. So, I will do a quick se­ries high­light­ing some of those im­prove­ments this week.

Today's Topic: Javascript

So, Niko­la builds stat­ic pages. Like I of­ten say, that does­n't mean they have to be bor­ing. IN this re­lease, Niko­la's tem­plates are or­ga­nized in such a way that it's easy to cre­ate com­plex javascrip­t-based lay­out­s. Let's see an ex­am­ple.

Yes­ter­day I showed you a nice­ly type­set page con­tain­ing A Study in Scar­let. If you have not seen it yet, check it out, it has ty­po­graph­i­cal quotes and dash­es, jus­ti­fied text and hy­phen­ation.

In fac­t, if you re­size your win­dow to be "phone-­sized" it works quite com­fort­ably as a way to read. I would say the text lay­out is bet­ter than in the Kin­dle for An­droid ap­p, for in­stance.

So, what about go­ing fur­ther in that di­rec­tion? Why not make that spe­cif­ic web­page work more like an ebook read­er? In­deed let's do that!

First, we need to use a custom template for that specific page. That's easy using the template page metadata:

.. date: 2013/08/27 18:20:55
.. title: A STUDY IN SCARLET.
.. slug: a-study-in-scarlet
.. template: ebook.tmpl

===================
A STUDY IN SCARLET.
===================

By A. Conan Doyle [1]_
======================

And now, the fun part: let's do a very hackish JQuery script to make it look like an ebook reader! You have to put this code in templates/ebook.tmpl in your site. Code offered without comments mostly out of shame because I suck at JS:

## -*- coding: utf-8 -*-
<%inherit file="post.tmpl"/>
<%block name="extra_head">
</%block>
<%block name="content">
<div id="container" style="overflow:hidden; width: 100%;">
<div id="paginate">
%if title:
    <h1>${title}</h1>
%endif
    ${post.text()}
</div>
</div>
<div class="pagination" style="width:100%; text-align: center;">
    <a href="#" class="previous" data-action="previous">&lsaquo;</a>
    <input type="text" readonly="readonly" />
    <a href="#" class="next" data-action="next">&rsaquo;</a>
</div>
</%block>

<%block name="extra_js">
<script src="http://beneverard.github.io/jqPagination/js/jquery.jqpagination.js"></script>
<script>
var split_count=1;
var ready = false;
function current_page() {
// returns the current page, zero-based
    return Math.floor(($('#container').scrollLeft() +1) / $('#container').width())
}

$(document).ready(function(){
    $('#container').height($(window).height()-150-$('.pagination').height());
    split_count = Math.ceil($('#paginate').height() / ($('#container').height()))+2;
    $('#paginate').css('-webkit-column-count', ''+split_count);
    $('#paginate').width(split_count * $('#container').width());
    $('#paginate').height($('#container').height());
    $('.pagination').jqPagination({
        max_page: split_count,
        paged: function(page) {
            if (current_page() != page-1 && page >= 1)
            {
                $('#container').animate({scrollLeft: (page-1)*$('#container').width()}, 400);
                location.hash = 'page---'+page;
            }
        }});
    ready = true;
    hash_handler();
});

$('#container').scroll(function(){
    //$('.pagination').jqPagination('option', 'current_page', current_page()+1)
    });

function hash_handler() {
if (ready && location.hash) {
        if (location.hash.slice(0,8) == '#page---') {
            page = parseInt(location.hash.slice(8));
        }
        else {
            target = $(location.hash);
            w = $('#container').width();
            page = Math.ceil((target.position().left-target.height()+ $('#container').scrollLeft())/w);
        }
        if (page >= 1) {
            $('.pagination').jqPagination('option', 'current_page', page);
        }
    }
}
$(window).on('hashchange', hash_handler);
</script>
</%block>

Be­fore show­ing you the end re­sult, list of known bugs!

  • If you re­­size your win­­dow, the lay­out does­n't ad­just.

  • If you re­­size your win­­dow, the num­ber of pages changes.

  • Some chap­ter­s' links miss by a page in ei­ther di­rec­­tion.

  • No key­board short­­­cut­s.

  • It on­­ly sort-of-­­works in chrome and maybe oth­­er we­bkit-based browsers

And here is the end re­sult. En­joy!

Gustavo Bragança / 2013-08-29 03:03:

Nicely done! Maybe I could put my future thesis on this. How it would handle figures?

Roberto Alsina / 2013-08-29 10:28:

There is a figure directive (http://docutils.sourceforge... but it doesn't do things like figure indexes and cross referencing.

Gustavo Bragança / 2013-08-31 02:59:

Ah, it is on .rst. I saw this jQuery code and got lost. I am just starting a Nikola blog and I am still getting used to it.

Nice job, Roberto!