(function() { if (window.RDReaderBridge) { return; } window.addEventListener('error', function(event) { try { var message = event && (event.message || (event.error && event.error.message)) || 'Unknown JavaScript error'; window.webkit.messageHandlers.{{JAVASCRIPT_ERROR_MESSAGE}}.postMessage(message); } catch (error) { } }); function nodePath(node) { var path = []; var current = node; while (current && current !== document) { var parent = current.parentNode; if (!parent) { break; } var index = Array.prototype.indexOf.call(parent.childNodes, current); path.unshift(index); current = parent; } return path; } function nodeFromPath(path) { var current = document; for (var i = 0; i < path.length; i += 1) { if (!current || !current.childNodes || current.childNodes.length <= path[i]) { return null; } current = current.childNodes[path[i]]; } return current; } function serializeRange(range) { return JSON.stringify({ kind: 'dom-range', startPath: nodePath(range.startContainer), startOffset: range.startOffset, endPath: nodePath(range.endContainer), endOffset: range.endOffset }); } function rangeFromInfo(rangeInfo) { try { var payload = typeof rangeInfo === 'string' ? JSON.parse(rangeInfo) : rangeInfo; var startNode = nodeFromPath(payload.startPath || []); var endNode = nodeFromPath(payload.endPath || []); if (!startNode || !endNode) { return null; } var range = document.createRange(); range.setStart(startNode, payload.startOffset || 0); range.setEnd(endNode, payload.endOffset || 0); return range; } catch (error) { return null; } } var visiblePageIndex = 0; var configuredPageCount = 1; var configuredPageStride = 1; var relayoutTimer = null; var fixedLayoutDocument = false; function isFixedLayoutDocument() { if (fixedLayoutDocument) { return true; } fixedLayoutDocument = !!document.getElementById('ss-fixed-root') || !!document.querySelector('.ss-fixed-page'); return fixedLayoutDocument; } function ensurePaginationStructure() { if (isFixedLayoutDocument()) { return null; } var viewport = document.getElementById('ss-reader-viewport'); var content = document.getElementById('ss-reader-content'); if (viewport && content) { return content; } viewport = document.createElement('div'); viewport.id = 'ss-reader-viewport'; content = document.createElement('div'); content.id = 'ss-reader-content'; while (document.body.firstChild) { content.appendChild(document.body.firstChild); } viewport.appendChild(content); document.body.appendChild(viewport); return content; } function paginationContent() { if (isFixedLayoutDocument()) { return null; } return ensurePaginationStructure(); } function effectivePageStride() { return Math.max(1, configuredPageStride || 1); } function measuredPageCount() { if (isFixedLayoutDocument()) { return 1; } var content = paginationContent(); var scrollingElement = document.scrollingElement || document.documentElement || document.body; var scrollWidth = Math.max( content ? content.scrollWidth : 0, content ? content.offsetWidth : 0, scrollingElement ? scrollingElement.scrollWidth : 0, document.documentElement ? document.documentElement.scrollWidth : 0, document.body ? document.body.scrollWidth : 0, effectivePageStride() ); return Math.max(1, Math.ceil(scrollWidth / effectivePageStride())); } function totalPageCount() { return Math.max(configuredPageCount, measuredPageCount()); } function currentPageOffset() { return Math.round(visiblePageIndex * effectivePageStride()); } function reportProgression(fragment) { var pageCount = totalPageCount(); var progression = pageCount <= 1 ? 0 : visiblePageIndex / Math.max(pageCount - 1, 1); var lastProgression = progression; window.webkit.messageHandlers.{{PROGRESSION_CHANGED_MESSAGE}}.postMessage({ progression: progression, lastProgression: lastProgression, fragment: fragment || null }); } function setVisiblePageIndex(pageIndex) { if (isFixedLayoutDocument()) { visiblePageIndex = 0; return; } var pageCount = totalPageCount(); var maxPageIndex = Math.max(0, pageCount - 1); var safePageIndex = Math.max(0, Math.min(maxPageIndex, Math.round(pageIndex || 0))); visiblePageIndex = safePageIndex; var content = paginationContent(); if (content) { content.style.transform = 'translate3d(' + (-currentPageOffset()) + 'px, 0, 0)'; } } function scheduleRelayout() { if (isFixedLayoutDocument()) { return; } clearTimeout(relayoutTimer); relayoutTimer = setTimeout(function() { setVisiblePageIndex(visiblePageIndex); reportProgression(null); }, 60); } function pageIndexForElement(target) { if (isFixedLayoutDocument()) { return 0; } if (!target) { return 0; } var rect = target.getBoundingClientRect(); var absoluteLeft = Math.max(0, rect.left + currentPageOffset()); return Math.max(0, Math.floor(absoluteLeft / effectivePageStride())); } function unwrapHighlights() { document.querySelectorAll('mark.ss-reader-highlight').forEach(function(mark) { var parent = mark.parentNode; if (!parent) { return; } while (mark.firstChild) { parent.insertBefore(mark.firstChild, mark); } parent.removeChild(mark); }); } function setHighlights(items) { unwrapHighlights(); if (!Array.isArray(items)) { return; } items.forEach(function(item) { if (!item || !item.rangeInfo) { return; } var range = rangeFromInfo(item.rangeInfo); if (!range || range.collapsed) { return; } try { var mark = document.createElement('mark'); var style = item.style || 'highlight'; mark.className = 'ss-reader-highlight ss-reader-highlight-' + style; mark.style.color = 'inherit'; if (style === 'underline') { mark.style.background = 'transparent'; mark.style.textDecorationColor = item.color || '#F8E16C'; } else { mark.style.background = item.color || '#F8E16C'; } mark.dataset.highlightId = item.id || ''; range.surroundContents(mark); } catch (error) { } }); } function selectionPayload() { var selection = window.getSelection(); if (!selection || selection.rangeCount === 0 || selection.isCollapsed) { return null; } var range = selection.getRangeAt(0); var text = selection.toString(); if (!text || !text.trim()) { return null; } var pageCount = totalPageCount(); var progression = pageCount <= 1 ? 0 : visiblePageIndex / Math.max(pageCount - 1, 1); var lastProgression = progression; return { text: text, rangeInfo: serializeRange(range), progression: progression, lastProgression: lastProgression }; } var selectionTimer = null; document.addEventListener('selectionchange', function() { clearTimeout(selectionTimer); selectionTimer = setTimeout(function() { var payload = selectionPayload(); window.webkit.messageHandlers.{{SELECTION_CHANGED_MESSAGE}}.postMessage(payload); }, 120); }); window.addEventListener('resize', function() { if (isFixedLayoutDocument()) { return; } setVisiblePageIndex(visiblePageIndex); reportProgression(null); }, { passive: true }); window.addEventListener('load', scheduleRelayout, { passive: true }); if (!isFixedLayoutDocument() && document.fonts && document.fonts.ready) { document.fonts.ready.then(scheduleRelayout).catch(function() {}); } if (!isFixedLayoutDocument()) { Array.prototype.forEach.call(document.querySelectorAll('img, iframe, video'), function(node) { node.addEventListener('load', scheduleRelayout, { passive: true }); node.addEventListener('error', scheduleRelayout, { passive: true }); }); } document.addEventListener('click', function(event) { var anchor = event.target.closest ? event.target.closest('a[href]') : null; if (!anchor) { return; } var href = anchor.getAttribute('href'); if (!href) { return; } if (/^(https?:|mailto:|tel:)/i.test(href)) { event.preventDefault(); window.webkit.messageHandlers.{{EXTERNAL_LINK_MESSAGE}}.postMessage({ url: href }); return; } event.preventDefault(); window.webkit.messageHandlers.{{INTERNAL_LINK_MESSAGE}}.postMessage({ href: href }); }, true); window.RDReaderBridge = { applyPagination: function(styleText) { if (isFixedLayoutDocument()) { return; } var style = document.getElementById('ss-reader-pagination'); if (!style) { style = document.createElement('style'); style.id = 'ss-reader-pagination'; document.head.appendChild(style); } style.textContent = styleText; ensurePaginationStructure(); }, setPageMetrics: function(pageCount, pageStride) { if (isFixedLayoutDocument()) { return; } configuredPageCount = Math.max(1, Math.round(pageCount || 1)); configuredPageStride = Math.max(1, Number(pageStride) || configuredPageStride || 1); setVisiblePageIndex(visiblePageIndex); scheduleRelayout(); }, scrollToPage: function(pageIndex) { if (isFixedLayoutDocument()) { return; } setVisiblePageIndex(pageIndex); reportProgression(null); }, scrollToLocation: function(location, fallbackPageIndex) { if (location && location.fragment) { var target = document.getElementById(location.fragment) || document.querySelector('[name="' + location.fragment.replace(/"/g, '\\"') + '"]'); if (target) { setVisiblePageIndex(pageIndexForElement(target)); reportProgression(location.fragment); return; } } var pageCount = totalPageCount(); var progression = location && typeof location.progression === 'number' ? location.progression : 0; var derivedPageIndex = progression > 0 && pageCount > 1 ? Math.round(progression * Math.max(pageCount - 1, 0)) : (fallbackPageIndex || 0); this.scrollToPage(derivedPageIndex); }, setHighlights: setHighlights, clearHighlights: unwrapHighlights, reportProgression: reportProgression, selectionPayload: selectionPayload }; })();