// 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 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 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'); }); }); }); })();