Download raw (14.3 KB)
// Wrap image s // Make page 1 cover // Add pages untill all flows fit // Go page by page through them // If image compare page nums, if placed before text, insert break // requestAnimationFrame // Get classes on page elements // If class in list to take, add class to page // If image region empty reveal secondary text frame increase pagenumber ;(function () { 'use strict'; if ((!document.getNamedFlows) && document.webkitGetNamedFlows) { document.getNamedFlows = document.webkitGetNamedFlows; } if (!document.getNamedFlow) { document.getNamedFlow = function (name) { return document.getNamedFlows(name).namedItem(name); } } var master, container, textFlow = document.getNamedFlow('main'), imageFlow = document.getNamedFlow('images'), captionFlow = document.getNamedFlow('figcaptions'); function getStartPage () { var selector = "body#" + document.body.id + " #pages", stylesheets = document.styleSheets; for (var s=0; s < stylesheets.length; s++) { var rules = stylesheets[s].cssRules; for (var r=0; r < rules.length;r++) { if (rules[r].selectorText == selector) { return parseInt(/\d+/.exec(rules[r].style.counterReset)[0]); } } } } function insertBreakBefore (refNode, className) { var brkNode = document.createElement('div'); brkNode.classList.add('break-after'); brkNode.classList.add(className); refNode.parentElement.insertBefore(brkNode, refNode); } /** * Returns first region the given node is shown within * * workaround for getRegionsForContent() as that function only seems to work * on block-elements */ function getRegionByNode(flow, node) { var ranges, regions = flow.getRegionsByContent(node); if (regions.length > 0) { return regions[0]; } else { regions = flow.getRegions(); for (var i=0; i < regions.length; i++) { ranges = regions[i].webkitGetRegionFlowRanges(); for (var r=0; r < ranges.length; r++) { if (ranges[r].isPointInRange(node, 0)) { return regions[i]; } } } console.log('Could not find region for node', node); } } /** * Returns nodes within given region */ function regionContent (flow, region) { var ranges = region.webkitGetRegionFlowRanges(), flowContent = flow.getContent(), regionContent = []; for (var r=0; r < ranges.length; r++) { for (var i=0; i < flowContent.length; i++) { if (ranges[r].isPointInRange(flowContent[i])) { regionContent.push(flowContent[i]); } } } return regionContent; } /** * Return page number for given page */ function getPageNum (page) { return parseInt(page.id.replace(/\D/g, '')); } /** * Retreive page by number */ function getPageByNum (num) { return document.querySelector('#page-' + num); } /** * Find page for given node, travels up the DOM tree to find * first wrapping paper element. Does not work for Nodes in a flow. */ function getPageByNode (node) { if (node) { if (node.classList.contains('paper')) { return node; } else { if (node.parentElement) { return getPageByNode(node.parentElement); } else { return false; } } return false; } } /** * Get page by node in region */ function getPageByRegionNode (flow, node) { return getPageByNode(getRegionByNode(flow, node)); } /** * Return the region on the page with given number */ function getRegionByPageNum (flow, num) { var regionPageNum, regions = flow.getRegions(); for (var i = 0; i < regions.length; i++) { regionPageNum = getPageNum(getPageByNode(regions[i])); if (regionPageNum == num) { return regions[i]; } else if (regionPageNum > num) { return null; } } } function getNodeIndex(nodes, refnode) { for (var i=0; i < nodes.length; i++) { if (nodes[i] == refnode) { return i; } } } function wrapImages () { var im, wrapper, clsName, imgs = document.querySelectorAll("#main img"); for (var i=0;i<imgs.length;i++) { im = imgs[i]; wrapper = document.createElement("div"); wrapper.classList.add("img"); while (im.classList.length > 0) { clsName = im.classList[0]; if (clsName != 'None') { wrapper.classList.add(clsName); im.classList.remove(clsName); } } wrapper.appendChild(im.cloneNode()); im.parentNode.replaceChild(wrapper, im); if (wrapper.classList.contains('insert-break-before')) { wrapper.classList.remove('insert-break-before'); var breakDiv = document.createElement("div"); breakDiv.classList.add('break-before'); breakDiv.classList.add('img_break'); wrapper.parentElement.insertBefore(breakDiv, wrapper); } } var imgs = document.querySelectorAll("#main div.img"); for (var i=0; i<imgs.length; i++) { if (imgs[i].classList.contains('wrap-next')) { var wrapper = document.createElement('div'); wrapper.classList.add('wrapped_images'); for (var c=0; c<imgs[i].classList.length; c++) { wrapper.classList.add(imgs[i].classList[c]); } imgs[i].parentNode.insertBefore(wrapper, imgs[i]); var caption = imgs[i].nextElementSibling; wrapper.appendChild(imgs[i]); wrapper.appendChild(caption); imgs[i].classList.remove('img'); do { i++; var caption = imgs[i].nextElementSibling; imgs[i].classList.remove('img'); wrapper.appendChild(imgs[i]); wrapper.appendChild(caption); } while (i < imgs.length && imgs[i].classList.contains('wrap-next')); } } } function addPages(amount) { var page, pagenum, offset = getStartPage(); for (var i=0;i<amount;i++) { page = master.cloneNode(true); container.appendChild(page); pagenum = offset + document.querySelectorAll('.paper').length; page.setAttribute('id', 'page-'+pagenum); if (pagenum == 1) { page.classList.add('cover'); } } } function fitContent (callback) { if (textFlow.overset || imageFlow.overset || captionFlow.overset) { addPages(25); window.requestAnimationFrame(function () { fitContent(callback) }); } else { callback(); } } /** * Return content in flow on given page */ function getPageFlowContent (num, flow) { var region = getRegionByPageNum(flow, num); if (region) { return regionContent(flow, region); } else { return []; } } function getNextNodeInFlow (flow, refnode) { var flowContent = flow.getContent(), refIndex = getNodeIndex(flowContent, refnode); if (refIndex + 1 < flowContent.length) { return flowContent[refIndex + 1]; } else { return null; } } function findFirstEmptyPage (flow) { var regions = flow.getRegions(); for (var i=0; i<regions.length;i++) { if (regions[i].webkitRegionOverset == 'empty' && !regions[i].classList.contains('secondary')) { return getPageNum(getPageByNode(regions[i])); } } } function getImageRef (image) { while(!image.classList.contains('img')) { image = image.parentNode; } var ref = image.previousElementSibling; while(!(ref.classList.contains('img_ref'))) { ref = ref.previousElementSibling; } return ref; } var pageNum; document.addEventListener("storiesloaded", function () { container = document.querySelector('#pages'); master = document.querySelector('#master-page'); master.removeAttribute('id'); master.remove(); wrapImages(); fitContent (function() { function alignCaptions (callback) { var i = 0, captions = captionFlow.getContent(); function validRegion(captionRegion, imageRegion) { var imgPage = getPageNum(getPageByNode(imageRegion)), captionPage = getPageNum(getPageByNode(captionRegion)); if (captionPage < imgPage) { return false; } else if (imageRegion.classList.contains('secondary') && getPageByNode(imageRegion).classList.contains('no-reveal')) { if (captionPage > imgPage) { return true; } else { return captionRegion.classList.contains('secondary'); } } else { return true; } } function exec () { if (i < captions.length) { var caption, captionPage, captionIndex, captionRegion, imageRegion, img, imgPage; caption = captions[i], captionRegion = getRegionByNode(captionFlow, caption) img = caption.previousElementSibling; while (!img.classList.contains('img')) { img = img.parentElement; } imageRegion = getRegionByNode(imageFlow, img); while (!validRegion(captionRegion, imageRegion)) { insertBreakBefore(caption.parentElement, 'figcaption_break'); captionRegion = getRegionByNode(captionFlow, caption); } i++; window.requestAnimationFrame(exec); } else { callback(); } } exec(); } function allowedAsMainImage(image, pageNum) { var buffer = 0, imageRef = getImageRef(image), imageRefPageNum = getPageNum(getPageByRegionNode(textFlow, imageRef)); if (image.classList.contains('push-more')) { buffer = -3; } else if (image.classList.contains('push')) { buffer = -2; } else if (image.classList.contains('cheat')) { buffer = 1; } else if (image.classList.contains('cheat-a-lot')) { buffer = 2; } if (pageNum+buffer >= imageRefPageNum) { return true; } else { return false; } } function allowedAsNextImage (image, pageNum) { if (image.classList.contains('full') || image.classList.contains('not-secondary')) { return false; } else { var imageRef = getImageRef(image), imageRefPageNum = getPageNum(getPageByRegionNode(textFlow, imageRef)), buffer = (image.classList.contains('cheat')) ? 1 : 0; buffer = (image.classList.contains('cheat-a-lot')) ? 2 : buffer; if (pageNum+buffer >= imageRefPageNum) { return true; } return false } } function layoutPage () { if (pageNum < parseInt(/\d+/.exec(document.querySelector('.paper:last-of-type').id)[0])) { var page, image, imagesOnPage = getPageFlowContent(pageNum, imageFlow); page = getPageByNum(pageNum); if (imagesOnPage.length > 0) { for (var i = 0; i < imagesOnPage.length; i++) { image = imagesOnPage[i]; if (i == 0) { if (! allowedAsMainImage(image, pageNum)) { page.classList.add('reveal_secondary_main'); pageNum++; return layoutPage(); } if (image.classList.contains('half')) { page.classList.add('half'); if (image.classList.contains('no-reveal')) { page.classList.add('no-reveal'); } var nextImage = getNextNodeInFlow(imageFlow, image); if (nextImage) { while (!nextImage.classList.contains('img')) { nextImage = getNextNodeInFlow(imageFlow, nextImage); } while(getPageNum(getPageByRegionNode(imageFlow, nextImage)) == pageNum) { nextImage = getNextNodeInFlow(imageFlow, nextImage); } if (allowedAsNextImage(nextImage, pageNum)) { if (nextImage.classList.contains('half')) { page.classList.add('reveal_secondary_images_half'); } else { page.classList.add('reveal_secondary_images'); } } else { page.classList.add('reveal_secondary_main'); pageNum++; return layoutPage(); } } else { page.classList.add('reveal_secondary_main'); pageNum++; return layoutPage(); } } } else { if (! allowedAsNextImage(image, pageNum)) { insertBreakBefore(image.parentNode, 'img_break'); pageNum++; return layoutPage(); } } if (image.classList.contains('full')) { page.classList.add('full'); pageNum++; return layoutPage(); } } } else { page.classList.add('reveal_secondary_main'); } pageNum++; return layoutPage(); } } var firstPage = document.querySelector('.paper:first-of-type'); firstPage.classList.add('cover'); pageNum = parseInt(/\d+/.exec(firstPage.id)[0]) + 1; console.log('Layouting pages'); layoutPage(); console.log('Positioning captions'); alignCaptions(function () { console.log('Fixing typography'); window.typographicFixes(); var firstEmptyPage = Math.max.apply(Math, [ findFirstEmptyPage(textFlow), findFirstEmptyPage(captionFlow)]), lastPageWithContent = document.querySelector('#page-' + (firstEmptyPage - 1)); console.log(lastPageWithContent); while (lastPageWithContent.nextSibling) { lastPageWithContent.parentNode.removeChild(lastPageWithContent.nextSibling); } //indexKeywords(); indexNames(); window.setTimeout(function () { document.layoutcomplete = true; }, 1000); console.log('layout done'); }); }); }); })();