Pull to refresh

Онлайн-книга своими руками на JavaScript

Reading time 3 min
Views 18K
image

Итак, требовалось: опубликовать книгу с иллюстрациями онлайн так, чтобы ее можно было дописывать и переписывать, и извещать об этом читателей. Быстрое и изящное решение под катом.

Изначально планировалось написать полноценную админку с WYSIWYG-редактором, у которого обязательно должна быть хорошая проверка орфографии, удобный интерфейс и возможность прицепить к записи анимацию. В планах было анимировать рисование карандашных набросков на полях. Забегая чуть вперед, скажу, что делали саму отрисовку с помощью vivus.

В общем, купили домен, но разработка серверной части никак не шла: получались какие-то громоздкие уродцы, у которых лишнего было больше, чем полезного. Может так бы все и осталось, если бы мне на глаза не попалось описание одного продукта (jekyll), где в преимуществах при прочих было отмечено отсутствие базы данных. Тут-то меня и осенило, что книге база данных как корове седло не нужна.

И завертелось: решено было хостить книгу на github, а страницы размечать markdown, благо для любимого автором word’а быстро нашелся плагин для сохранения в этом формате (Writage). Ну а для преобразования его в html подвернулась библиотека ShowDown

Достаточно быстро задуманное было реализовано. Книга состоит из файлов-страничек в формате .md и файла .json, в котором перечислено что за чем идет, какую анимацию грузить и надо ли вообще.

Вот так выглядит конфигурационный файл:

[{
    "file": "имяфайла.md",
    "hash": "хештег",
    "animation": {
        "svg": "анимация.svg",
        "duration": 2000,//Продолжительность анимации в милисекундах
        "style": "width:400px;height:300px;opacity:0.5;float:right;margin-right:20px;"//Стиль для блока анимации, чтобы было понятно где его размещать
    },
{
    "file": "имяфайла2.md",
    "hash": "хештег2"
}]

Собственно, сами страницы загружаются асинхронно при прокрутке и по хештегу, чтобы пользователь мог продолжить читать с того же месте, где остановился. При загрузке страницы по хештегу подгружается еще и предыдущая запись, если она есть, чтобы не казалось, что это начало книги.

Синхронный Ajax браузер мне использовать не дал, но может оно и к лучшему. Делала так: сначала создаются блоки с id=хештег, потом отправляются запросы к непосредственным страницам. Таким образом, все запрошенные страницы встают на свое место, независимо от того, какой из запросов быстрее выполнится.

Вот функция загрузки страницы, которая принимает объект страницы из конфигурационного файла и опционально параметры: нужно ли изменять хеш страницы, добавить ли эту страницу после текущей или перед и нужно ли скроллить к новой странице после загрузки. Параметры дают возможность фоновой загрузки страниц.

function loadPage(page, options = {}) {

    if (options.changeHash === undefined) {
        options.changeHash = true;
    }
    if (options.next === undefined) {
        options.next = true;
    }
    if (options.scroll === undefined) {
        options.scroll = true;
    }
    if (options.changeHash) {
        document.location.hash = "#" + page.hash;
    }
    if ($("#" + page.hash).size() == 0) {
        if (options.next) {
            $("#content").append('<div id="' + page.hash + '"></div>');
        } else {
            $("#content").prepend('<div id="' + page.hash + '"></div>');
        }
        $("#loader").show();
        jQuery.ajax({
            url: "/book/" + page.file,
            success: function(result) {
                //Преобразуем markdown в html
                var converter = new showdown.Converter();
                var html = converter.makeHtml(result);
                $("#" + page.hash).html(html);
                if(page.animation!==undefined){
                //Рисуем иллюстрацию, если она есть
                  $("#" + page.hash).prepend('<div id="animation-'+page.hash+'" style="'+page.animation.style+'"></div>');
                  var vivus=new Vivus('animation-'+page.hash, {duration: page.animation.duration, file: '/svg/'+page.animation.svg, type:'oneByOne'}, finishedDrawing);
                }
                $("#loader").fadeOut();
                if (options.scroll) {
                //Ползем к загруженной странице, если нужно
                    $('html,body').animate({
                        scrollTop: $("#" + page.hash).offset().top
                    }, 300, 'swing');
                }
            }
        });
    }
}

Собственно, вот и вся магия. Автор спокойно пишет себе книгу и в пару кликов публикует (с редактурой json файла он тоже справился сам).

Готовую книгу (она на английском) можно почитать тут, а рассмотреть внутренности подробнее в коде на github.

Спасибо за уделенное время, надеюсь, что вы не сочли его потраченным впустую!
Tags:
Hubs:
+11
Comments 33
Comments Comments 33

Articles