JSFiddle - React, Tailwind, and code Playground

by shtrih

HTML

<div id="book">
    <div class="content"></div>
    
    <div id="spine-back-top"></div>
    <div id="spine-back-bottom"></div>
    <div class="page" id="page1"></div>       
    <div class="page" id="page2"></div>
    <div class="page" id="page3"></div>
    <div class="page" id="page4"></div>
    <div id="spine"></div>
    <div class="page" id="page5"></div>       
    <div class="page" id="page6"></div>
    <div class="page" id="page7"></div>
    <div class="page" id="page8"></div>
</div>

<div class="ruler"></div>
<div class="base">
    <h2>16 Месяц Урожая (День 1)</h2>
    <p>
    Мне <span class="link">приказано</span> отправляться в город <span class="link">Балмору</span> в <span class="link">Районе Вварденфелл</span> и явиться к человеку по имени <span class="link">Кай Косадес</span>. Узнать, где он живет я могу в трактире <span class="link">Южная Стена</span>. Когда я найду <span class="link">Кая Косадеса</span>, мне надо отдать ему пакет с документами и ждать дальнейших <span class="link">приказаний</span>.
    </p>
    <h2>16 Месяц Урожая (День 1)</h2>
    <p>
    На дороге к северо-западу от <span class="link">Пелагиада</span>, мне повстречалось красивая молодая <span class="link">бретонка</span>, <span class="link">Морри Ормин</span>, которая была в смятении из-за нападения бандита.
    </p>
    <h2>17 Месяц Урожая (День 2)</h2>
    <p>
    Завсегдатай Трактира <span class="link">Южной Стены</span> назвал <span class="link">Кая Косадеса</span> 'старым пройдохой', и посоветовал спросить о нем у <span class="link">содержателя</span> трактира, <span class="link">Баколы Клосиуса</span>.
    </p>
    <h2>17 Месяц Урожая (День 2)</h2>
    <p>
    <span class="link">Бакола Клосиус</span> сказал, что <span class="link">Кай Косадес</span> снимает небольшую лачужку на холме неподалеку от <span class="link">Южной Стены</span>. Надо подняться по лестнице у входной двери, потом налево на верху лестницы, и вниз к концу улицы.
    </p>
    <h2>17 Месяц Урожая (День...

CSS

/*@font-face {
	font-family: Goudyold;
	src:  local('Goudyold'), url('http://dl.dropbox.com/u/23033545/Archives/goudyold.ttf');
}
@import url(http://fonts.googleapis.com/css?family=Underdog&subset=latin,cyrillic);*/
.base {
    display: none;
}
p, h2 {
	font-family: 'Goudyold', 'Underdog', cursive, sans-serif;
	font-size: 1.2em;
}
h2 {
    color: rgb(82, 12, 10);
}
#book {
    position: relative;
    width: 940px;
    height: 580px;
    background-color: rgb(164, 69, 66);
    padding: 10px;   
    border-radius: 3px;
    box-shadow: inset 0 0 10px rgb(82, 12, 10);
    margin: 10px auto;
}
.content {
    background: #f5dca6 url('https://dl.dropbox.com/u/23033545/Archives/bg.png');
    width: 900px;
    height: 560px;
    padding: 10px 20px;
    float: left;
    box-shadow: inset 0px 0px 40px 3px rgba(109, 96, 36,0.8);
    -moz-column-count: 2;
    -webkit-column-count: 2;
    column-count: 2;
    -moz-column-gap:40px;
    -webkit-column-gap:40px;
    column-gap:40px;
}
.ruler {
    position: absolute;
    top: 0;
    visibility: hidden;
    width: 900px;
    padding: 10px 20px;
    -moz-column-count: 2;
    -webkit-column-count: 2;
    column-count: 2;
    -moz-column-gap:40px;
    -webkit-column-gap:40px;
    column-gap:40px;
}
#book .page {
    position: absolute;
    top: 10px; 
    height: 580px;
}
#page1 {
    left: 12px;
    width: 1px;
    border-left: 1px solid rgb(177, 158, 77);
    border-right: 1px solid rgb(162, 152, 110);
    background-color: rgb(82, 60, 18);
    box-shadow: 0px 0px 2px rgb(82, 60, 18);
    transform: rotate(2deg);
    -webkit-transform: rotate(1deg);
}
#page3 {
    left: 12px;
    width: 1px;
    border-left: 1px solid rgb(177, 158, 77);
    border-right: 1px solid rgb(162, 152, 110);
    background-color: rgb(198, 187, 138);
    transform: rotate(-1deg);
    -webkit-transform: rotate(-1deg);
}
#page4 {
    left: 12px;
    width: 1px;
    border-left: 1px solid rgba(165, 142, 46, 0.89);
    border-right: 1px solid rgb(162, 152,...

JavaScript

var content       = $('.content'),
    ruler         = $('.ruler'),
    elements      = $('.base').children(),
    current_page  = 1,
    pages         = [];

pages = getPages(content, ruler, elements);
showContent(elements, pages, current_page);

for (var i = pages.length - 1; i > 0; i--) {
    $('#book').after(
        $('<a/>', {
            href: '#'+i, 
            text: i
        }).on('click', function () {
            current_page = Number($(this).text());
            showContent(elements, pages, current_page);
            return false;            
        })
    );
}
     
/**
* @param parentEl  JQuery-элемент, под который нужно размечать страницы (с фикс. размерами)
* @param rulerEl   JQuery-элемент, который используется в качестве «линейки». Должен иметь те же параметры, что и parentEl, но без фиксированной высоты.
* @param elements  Массив JQuery-элементов, которые должны располагаться постранично.
*
* @return [[a, b], ...], где a – номер последнего элемента, отображенного на данной странице, b – количество элементов на данной странице.
*/
function getPages(parentEl, rulerEl, elements) {
    var position = 0,
        elonpage = 0,
        contentheight = parentEl.height(),
        elcount = elements.length,
        result = [];
    
    while(position <= elcount) {
        while(contentheight >= rulerEl.height()) {
            rulerEl.append( elements.eq(position) );
            
            if (position <= elcount)
                position++;
            else
                break;
        } 
        // если высота получилась более, чем нужно, то если число элементов нечетное, то убираем 1 элемент, иначе убираем два элемента
        while (contentheight < rulerEl.height()) {
            if (position % 2) {
                rulerEl.children().eq(-1).remove();
                position--;
            }
            else {
                rulerEl.children().eq(-1).remove();
                rulerEl.children().eq(-1).remove();
                position -= 2;
...