UNPKG

r2-navigator-js

Version:

Readium 2 'navigator' for NodeJS (TypeScript)

1,149 lines (1,148 loc) 137 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.computeCFI = exports.computeProgressionData = void 0; var tslib_1 = require("tslib"); var debounce_1 = require("debounce"); var debug_ = require("debug"); var electron_1 = require("electron"); var tabbable_1 = require("tabbable"); var UrlUtils_1 = require("r2-utils-js/dist/es5/src/_utils/http/UrlUtils"); var sessions_1 = require("../../common/sessions"); var events_1 = require("../../common/events"); var readium_css_inject_1 = require("../../common/readium-css-inject"); var selection_1 = require("../../common/selection"); var styles_1 = require("../../common/styles"); var animateProperty_1 = require("../common/animateProperty"); var cssselector2_3_1 = require("../common/cssselector2-3"); var dom_text_utils_1 = require("../common/dom-text-utils"); var easings_1 = require("../common/easings"); var popup_dialog_1 = require("../common/popup-dialog"); var querystring_1 = require("../common/querystring"); var rect_utils_1 = require("../common/rect-utils"); var url_params_1 = require("../common/url-params"); var audiobook_1 = require("./audiobook"); var epubReadingSystem_1 = require("./epubReadingSystem"); var highlight_1 = require("./highlight"); var popoutImages_1 = require("./popoutImages"); var popupFootNotes_1 = require("./popupFootNotes"); var readaloud_1 = require("./readaloud"); var readium_css_1 = require("./readium-css"); var selection_2 = require("./selection"); var IS_DEV = (process.env.NODE_ENV === "development" || process.env.NODE_ENV === "dev"); if (IS_DEV) { var cr = require("../common/console-redirect"); cr.consoleRedirect("r2:navigator#electron/renderer/webview/preload", process.stdout, process.stderr, true); } var debug = debug_("r2:navigator#electron/renderer/webview/preload"); var INJECTED_LINK_TXT = "__"; var win = global.window; win.READIUM2 = { DEBUG_VISUALS: false, fxlViewportHeight: 0, fxlViewportScale: 1, fxlViewportWidth: 0, fxlZoomPercent: 0, hashElement: null, isAudio: false, ignorekeyDownUpEvents: false, isClipboardIntercept: false, isFixedLayout: false, locationHashOverride: undefined, locationHashOverrideInfo: { audioPlaybackInfo: undefined, docInfo: undefined, epubPage: undefined, epubPageID: undefined, headings: undefined, href: "", locations: { cfi: undefined, cssSelector: undefined, position: undefined, progression: undefined, }, paginationInfo: undefined, secondWebViewHref: undefined, selectionInfo: undefined, selectionIsNew: undefined, title: undefined, userInteract: false, }, ttsClickEnabled: false, ttsOverlayEnabled: false, ttsPlaybackRate: 1, ttsSkippabilityEnabled: false, ttsSentenceDetectionEnabled: true, ttsVoice: null, urlQueryParams: win.location.search ? (0, querystring_1.getURLQueryParams)(win.location.search) : undefined, webViewSlot: styles_1.WebViewSlotEnum.center, }; win.alert = function () { var args = []; for (var _i = 0; _i < arguments.length; _i++) { args[_i] = arguments[_i]; } console.log.apply(win, args); }; win.confirm = function () { var args = []; for (var _i = 0; _i < arguments.length; _i++) { args[_i] = arguments[_i]; } console.log.apply(win, args); return false; }; win.prompt = function () { var args = []; for (var _i = 0; _i < arguments.length; _i++) { args[_i] = arguments[_i]; } console.log.apply(win, args); return ""; }; var CSS_PIXEL_TOLERANCE = 5; var TOUCH_SWIPE_DELTA_MIN = 80; var TOUCH_SWIPE_LONG_PRESS_MAX_TIME = 500; var TOUCH_SWIPE_MAX_TIME = 500; var touchstartEvent; var touchEventEnd; win.document.addEventListener("touchstart", function (event) { if ((0, popup_dialog_1.isPopupDialogOpen)(win.document)) { touchstartEvent = undefined; touchEventEnd = undefined; return; } if (event.changedTouches.length !== 1) { return; } touchstartEvent = event; }, true); win.document.addEventListener("touchend", function (event) { if ((0, popup_dialog_1.isPopupDialogOpen)(win.document)) { touchstartEvent = undefined; touchEventEnd = undefined; return; } if (event.changedTouches.length !== 1) { return; } if (!touchstartEvent) { return; } var startTouch = touchstartEvent.changedTouches[0]; var endTouch = event.changedTouches[0]; if (!startTouch || !endTouch) { return; } var deltaX = (startTouch.clientX - endTouch.clientX) / win.devicePixelRatio; var deltaY = (startTouch.clientY - endTouch.clientY) / win.devicePixelRatio; if (Math.abs(deltaX) < TOUCH_SWIPE_DELTA_MIN && Math.abs(deltaY) < TOUCH_SWIPE_DELTA_MIN) { if (touchEventEnd) { touchstartEvent = undefined; touchEventEnd = undefined; return; } if (event.timeStamp - touchstartEvent.timeStamp > TOUCH_SWIPE_LONG_PRESS_MAX_TIME) { touchstartEvent = undefined; touchEventEnd = undefined; return; } touchstartEvent = undefined; touchEventEnd = event; return; } touchEventEnd = undefined; if (event.timeStamp - touchstartEvent.timeStamp > TOUCH_SWIPE_MAX_TIME) { touchstartEvent = undefined; return; } var slope = (startTouch.clientY - endTouch.clientY) / (startTouch.clientX - endTouch.clientX); if (Math.abs(slope) > 0.5) { touchstartEvent = undefined; return; } if (deltaX < 0) { var payload = { direction: "LTR", go: "NEXT", nav: true, }; electron_1.ipcRenderer.sendToHost(events_1.R2_EVENT_PAGE_TURN_RES, payload); } else { var payload = { direction: "LTR", go: "PREVIOUS", nav: true, }; electron_1.ipcRenderer.sendToHost(events_1.R2_EVENT_PAGE_TURN_RES, payload); } touchstartEvent = undefined; }, true); function keyDownUpEventHandler(ev, keyDown) { if (win.READIUM2.ignorekeyDownUpEvents) { return; } var elementName = (ev.target && ev.target.nodeName) ? ev.target.nodeName : ""; var elementAttributes = {}; if (ev.target && ev.target.attributes) { for (var i = 0; i < ev.target.attributes.length; i++) { var attr = ev.target.attributes[i]; elementAttributes[attr.name] = attr.value; } } var payload = { altKey: ev.altKey, code: ev.code, ctrlKey: ev.ctrlKey, elementAttributes: elementAttributes, elementName: elementName, key: ev.key, metaKey: ev.metaKey, shiftKey: ev.shiftKey, }; electron_1.ipcRenderer.sendToHost(keyDown ? events_1.R2_EVENT_WEBVIEW_KEYDOWN : events_1.R2_EVENT_WEBVIEW_KEYUP, payload); } win.document.addEventListener("keydown", function (ev) { keyDownUpEventHandler(ev, true); }, { capture: true, once: false, passive: false, }); win.document.addEventListener("keyup", function (ev) { keyDownUpEventHandler(ev, false); }, { capture: true, once: false, passive: false, }); win.READIUM2.isAudio = win.location.protocol === "data:"; if (win.READIUM2.urlQueryParams) { var readiumEpubReadingSystemJson = void 0; var base64EpubReadingSystem = win.READIUM2.urlQueryParams[url_params_1.URL_PARAM_EPUBREADINGSYSTEM]; if (base64EpubReadingSystem) { try { var str = Buffer.from(base64EpubReadingSystem, "base64").toString("utf8"); readiumEpubReadingSystemJson = JSON.parse(str); } catch (err) { debug(err); } } if (readiumEpubReadingSystemJson) { (0, epubReadingSystem_1.setWindowNavigatorEpubReadingSystem)(win, readiumEpubReadingSystemJson); } win.READIUM2.DEBUG_VISUALS = win.READIUM2.urlQueryParams[url_params_1.URL_PARAM_DEBUG_VISUALS] === "true"; win.READIUM2.isClipboardIntercept = win.READIUM2.urlQueryParams[url_params_1.URL_PARAM_CLIPBOARD_INTERCEPT] === "true"; win.READIUM2.webViewSlot = win.READIUM2.urlQueryParams[url_params_1.URL_PARAM_WEBVIEW_SLOT] === "left" ? styles_1.WebViewSlotEnum.left : (win.READIUM2.urlQueryParams[url_params_1.URL_PARAM_WEBVIEW_SLOT] === "right" ? styles_1.WebViewSlotEnum.right : styles_1.WebViewSlotEnum.center); } if (IS_DEV) { electron_1.ipcRenderer.on(events_1.R2_EVENT_DEBUG_VISUALS, function (_event, payload) { win.READIUM2.DEBUG_VISUALS = payload.debugVisuals; if (!payload.debugVisuals) { var existings = win.document.querySelectorAll("*[".concat(styles_1.readPosCssStylesAttr1, "], *[").concat(styles_1.readPosCssStylesAttr2, "], *[").concat(styles_1.readPosCssStylesAttr3, "], *[").concat(styles_1.readPosCssStylesAttr4, "]")); existings.forEach(function (existing) { existing.removeAttribute("".concat(styles_1.readPosCssStylesAttr1)); existing.removeAttribute("".concat(styles_1.readPosCssStylesAttr2)); existing.removeAttribute("".concat(styles_1.readPosCssStylesAttr3)); existing.removeAttribute("".concat(styles_1.readPosCssStylesAttr4)); }); } if (payload.cssClass) { if (_blacklistIdClassForCssSelectors.indexOf(payload.cssClass) < 0) { _blacklistIdClassForCssSelectors.push(payload.cssClass.toLowerCase()); } if (payload.debugVisuals && payload.cssStyles && payload.cssStyles.length) { var idSuffix = "debug_for_class_".concat(payload.cssClass); (0, readium_css_inject_1.appendCSSInline)(win.document, idSuffix, payload.cssStyles); if (payload.cssSelector) { var toHighlights = win.document.querySelectorAll(payload.cssSelector); toHighlights.forEach(function (toHighlight) { var clazz = "".concat(payload.cssClass); if (!toHighlight.classList.contains(clazz)) { toHighlight.classList.add(clazz); } }); } } else { var existings = win.document.querySelectorAll(".".concat(payload.cssClass)); existings.forEach(function (existing) { existing.classList.remove("".concat(payload.cssClass)); }); } } }); } function computeVisibility_(element, domRect) { if (win.READIUM2.isFixedLayout) { return true; } else if (!win.document || !win.document.documentElement || !win.document.body) { return false; } if (element === win.document.body || element === win.document.documentElement) { return true; } var blacklisted = checkBlacklisted(element); if (blacklisted) { return false; } var elStyle = win.getComputedStyle(element); if (elStyle) { var display = elStyle.getPropertyValue("display"); if (display === "none") { if (IS_DEV) { debug("element DISPLAY NONE"); } return false; } var opacity = elStyle.getPropertyValue("opacity"); if (opacity === "0") { if (IS_DEV) { debug("element OPACITY ZERO"); } return false; } } var scrollElement = (0, readium_css_1.getScrollingElement)(win.document); if (!(0, readium_css_inject_1.isPaginated)(win.document)) { var rect = domRect || element.getBoundingClientRect(); if (rect.top >= 0 && rect.top <= win.document.documentElement.clientHeight) { return true; } return false; } if ((0, readium_css_1.isVerticalWritingMode)()) { return false; } var scrollLeftPotentiallyExcessive = getScrollOffsetIntoView(element, domRect); var extraShift = scrollElement.scrollLeftExtra; var currentOffset = scrollElement.scrollLeft; if (extraShift) { currentOffset += (((currentOffset < 0) ? -1 : 1) * extraShift); } if (scrollLeftPotentiallyExcessive >= (currentOffset - 10) && scrollLeftPotentiallyExcessive <= (currentOffset + 10)) { return true; } return false; } function computeVisibility(location) { var visible = false; if (win.READIUM2.isAudio) { visible = true; } else if (win.READIUM2.isFixedLayout) { visible = true; } else if (!win.document || !win.document.documentElement || !win.document.body) { visible = false; } else if (!location || !location.cssSelector) { visible = false; } else { var selected = null; try { selected = win.document.querySelector(location.cssSelector); } catch (err) { debug(err); } if (selected) { visible = computeVisibility_(selected, undefined); } } return visible; } electron_1.ipcRenderer.on(events_1.R2_EVENT_LOCATOR_VISIBLE, function (_event, payload) { payload.visible = computeVisibility(payload.location); electron_1.ipcRenderer.sendToHost(events_1.R2_EVENT_LOCATOR_VISIBLE, payload); }); electron_1.ipcRenderer.on(events_1.R2_EVENT_SCROLLTO, function (_event, payload) { if (win.READIUM2.isAudio) { return; } showHideContentMask(false, win.READIUM2.isFixedLayout); (0, selection_2.clearCurrentSelection)(win); (0, popup_dialog_1.closePopupDialogs)(win.document); if (!win.READIUM2.urlQueryParams) { win.READIUM2.urlQueryParams = {}; } if (payload.isSecondWebView) { win.READIUM2.urlQueryParams[url_params_1.URL_PARAM_SECOND_WEBVIEW] = "1"; } else { win.READIUM2.urlQueryParams[url_params_1.URL_PARAM_SECOND_WEBVIEW] = "0"; } if (payload.previous) { win.READIUM2.urlQueryParams[url_params_1.URL_PARAM_PREVIOUS] = "true"; } else { if (typeof win.READIUM2.urlQueryParams[url_params_1.URL_PARAM_PREVIOUS] !== "undefined") { delete win.READIUM2.urlQueryParams[url_params_1.URL_PARAM_PREVIOUS]; } } if (payload.goto) { win.READIUM2.urlQueryParams[url_params_1.URL_PARAM_GOTO] = payload.goto; } else { if (typeof win.READIUM2.urlQueryParams[url_params_1.URL_PARAM_GOTO] !== "undefined") { delete win.READIUM2.urlQueryParams[url_params_1.URL_PARAM_GOTO]; } } if (payload.gotoDomRange) { win.READIUM2.urlQueryParams[url_params_1.URL_PARAM_GOTO_DOM_RANGE] = payload.gotoDomRange; } else { if (typeof win.READIUM2.urlQueryParams[url_params_1.URL_PARAM_GOTO_DOM_RANGE] !== "undefined") { delete win.READIUM2.urlQueryParams[url_params_1.URL_PARAM_GOTO_DOM_RANGE]; } } if (win.READIUM2.isFixedLayout) { win.READIUM2.locationHashOverride = win.document.body; resetLocationHashOverrideInfo(); debug("processXYRaw BODY"); processXYRaw(0, 0, false); notifyReadingLocationDebounced(); return; } var delayScrollIntoView = false; if (payload.hash) { debug(".hashElement = 1"); win.READIUM2.hashElement = win.document.getElementById(payload.hash); if (win.READIUM2.DEBUG_VISUALS) { if (win.READIUM2.hashElement) { win.READIUM2.hashElement.setAttribute(styles_1.readPosCssStylesAttr1, "R2_EVENT_SCROLLTO hashElement"); } } win.location.href = "#" + payload.hash; delayScrollIntoView = true; } else { win.location.href = "#"; win.READIUM2.hashElement = null; } win.READIUM2.locationHashOverride = undefined; resetLocationHashOverrideInfo(); if (delayScrollIntoView) { setTimeout(function () { debug("++++ scrollToHashRaw FROM DELAYED SCROLL_TO"); scrollToHashRaw(false); }, 100); } else { debug("++++ scrollToHashRaw FROM SCROLL_TO"); scrollToHashRaw(false); } }); function resetLocationHashOverrideInfo() { win.READIUM2.locationHashOverrideInfo = { audioPlaybackInfo: undefined, docInfo: undefined, epubPage: undefined, epubPageID: undefined, headings: undefined, href: "", locations: { cfi: undefined, cssSelector: undefined, position: undefined, progression: undefined, }, paginationInfo: undefined, secondWebViewHref: undefined, selectionInfo: undefined, selectionIsNew: undefined, title: undefined, userInteract: false, }; } var _lastAnimState; function elementCapturesKeyboardArrowKeys(target) { var curElement = target; while (curElement && curElement.nodeType === Node.ELEMENT_NODE) { var editable = curElement.getAttribute("contenteditable"); if (editable) { return true; } var arrayOfKeyboardCaptureElements = ["input", "textarea", "video", "audio", "select"]; if (arrayOfKeyboardCaptureElements.indexOf(curElement.tagName.toLowerCase()) >= 0) { return true; } curElement = curElement.parentNode; } return false; } function ensureTwoPageSpreadWithOddColumnsIsOffsetTempDisable() { var scrollElement = (0, readium_css_1.getScrollingElement)(win.document); var val = scrollElement.scrollLeftExtra; if (val === 0) { return 0; } scrollElement.scrollLeftExtra = 0; electron_1.ipcRenderer.sendToHost(events_1.R2_EVENT_SHIFT_VIEW_X, { offset: 0, backgroundColor: undefined }); return val; } function ensureTwoPageSpreadWithOddColumnsIsOffsetReEnable(scrollLeftExtra) { var scrollElement = (0, readium_css_1.getScrollingElement)(win.document); scrollElement.scrollLeftExtra = scrollLeftExtra; var scrollLeftExtraBackgroundColor = scrollElement.scrollLeftExtraBackgroundColor; electron_1.ipcRenderer.sendToHost(events_1.R2_EVENT_SHIFT_VIEW_X, { backgroundColor: scrollLeftExtraBackgroundColor ? scrollLeftExtraBackgroundColor : undefined, offset: ((0, readium_css_1.isRTL)() ? 1 : -1) * scrollLeftExtra, }); } function ensureTwoPageSpreadWithOddColumnsIsOffset(scrollOffset, maxScrollShift) { if (!win || !win.document || !win.document.body || !win.document.documentElement) { return; } var scrollElement = (0, readium_css_1.getScrollingElement)(win.document); var dialogPopup = (0, popup_dialog_1.isPopupDialogOpen)(win.document); if (dialogPopup) { var diagEl = win.document.getElementById(styles_1.POPUP_DIALOG_CLASS); if (diagEl) { var isCollapsed = diagEl.classList.contains(styles_1.POPUP_DIALOG_CLASS_COLLAPSE); if (isCollapsed) { dialogPopup = false; } } } var noChange = dialogPopup || !(0, readium_css_inject_1.isPaginated)(win.document) || !(0, readium_css_1.isTwoPageSpread)() || (0, readium_css_1.isVerticalWritingMode)() || maxScrollShift <= 0 || Math.abs(scrollOffset) <= maxScrollShift; if (noChange) { scrollElement.scrollLeftExtra = 0; electron_1.ipcRenderer.sendToHost(events_1.R2_EVENT_SHIFT_VIEW_X, { offset: 0, backgroundColor: undefined }); return; } var extraOffset = Math.abs(scrollOffset) - maxScrollShift; var backgroundColor; var docStyle = win.getComputedStyle(win.document.documentElement); if (docStyle) { backgroundColor = docStyle.getPropertyValue("background-color"); } if (!backgroundColor || backgroundColor === "transparent") { var bodyStyle = win.getComputedStyle(win.document.body); backgroundColor = bodyStyle.getPropertyValue("background-color"); if (backgroundColor === "transparent") { backgroundColor = undefined; } } scrollElement.scrollLeftExtra = extraOffset; scrollElement.scrollLeftExtraBackgroundColor = backgroundColor; electron_1.ipcRenderer.sendToHost(events_1.R2_EVENT_SHIFT_VIEW_X, { backgroundColor: backgroundColor ? backgroundColor : undefined, offset: ((0, readium_css_1.isRTL)() ? 1 : -1) * extraOffset, }); } function onEventPageTurn(payload) { var leftRightKeyWasUsedInsideKeyboardCapture = false; if (win.document.activeElement && elementCapturesKeyboardArrowKeys(win.document.activeElement)) { if (win.document.hasFocus()) { leftRightKeyWasUsedInsideKeyboardCapture = true; } else { var oldDate = win.document.activeElement.r2_leftrightKeyboardTimeStamp; if (oldDate) { var newDate = new Date(); var msDiff = newDate.getTime() - oldDate.getTime(); if (msDiff <= 300) { leftRightKeyWasUsedInsideKeyboardCapture = true; } } } } if (leftRightKeyWasUsedInsideKeyboardCapture) { return; } (0, selection_2.clearCurrentSelection)(win); (0, popup_dialog_1.closePopupDialogs)(win.document); if (win.READIUM2.isAudio || win.READIUM2.isFixedLayout || !win.document.body) { electron_1.ipcRenderer.sendToHost(events_1.R2_EVENT_PAGE_TURN_RES, payload); return; } if (!win.document || !win.document.documentElement) { return; } var scrollElement = (0, readium_css_1.getScrollingElement)(win.document); var reduceMotion = win.document.documentElement.classList.contains(styles_1.ROOT_CLASS_REDUCE_MOTION); var isPaged = (0, readium_css_inject_1.isPaginated)(win.document); var goPREVIOUS = payload.go === "PREVIOUS"; var animationTime = 300; if (_lastAnimState && _lastAnimState.animating) { win.cancelAnimationFrame(_lastAnimState.id); _lastAnimState.object[_lastAnimState.property] = _lastAnimState.destVal; } if (!goPREVIOUS) { var maxScrollShift = (0, readium_css_1.calculateMaxScrollShift)().maxScrollShift; var maxScrollShiftTolerated = maxScrollShift - CSS_PIXEL_TOLERANCE; if (isPaged) { var unit = (0, readium_css_1.isVerticalWritingMode)() ? win.document.documentElement.offsetHeight : win.document.documentElement.offsetWidth; var scrollElementOffset = Math.round((0, readium_css_1.isVerticalWritingMode)() ? scrollElement.scrollTop : scrollElement.scrollLeft); var isNegative = scrollElementOffset < 0; var scrollElementOffsetAbs = Math.abs(scrollElementOffset); var fractional = scrollElementOffsetAbs / unit; var integral = Math.floor(fractional); var decimal = fractional - integral; var partial = decimal * unit; if (partial <= CSS_PIXEL_TOLERANCE) { scrollElementOffset = (isNegative ? -1 : 1) * integral * unit; } else if (partial >= (unit - CSS_PIXEL_TOLERANCE)) { scrollElementOffset = (isNegative ? -1 : 1) * (integral + 1) * unit; } if ((0, readium_css_1.isVerticalWritingMode)() && (scrollElementOffsetAbs < maxScrollShiftTolerated) || !(0, readium_css_1.isVerticalWritingMode)() && (scrollElementOffsetAbs < maxScrollShiftTolerated)) { var scrollOffsetPotentiallyExcessive_ = (0, readium_css_1.isVerticalWritingMode)() ? (scrollElementOffset + unit) : (scrollElementOffset + ((0, readium_css_1.isRTL)() ? -1 : 1) * unit); var nWholes = Math.floor(scrollOffsetPotentiallyExcessive_ / unit); var scrollOffsetPotentiallyExcessive = nWholes * unit; ensureTwoPageSpreadWithOddColumnsIsOffset(scrollOffsetPotentiallyExcessive, maxScrollShift); var scrollOffset = (scrollOffsetPotentiallyExcessive < 0 ? -1 : 1) * Math.min(Math.abs(scrollOffsetPotentiallyExcessive), maxScrollShift); var targetObj = scrollElement; var targetProp = (0, readium_css_1.isVerticalWritingMode)() ? "scrollTop" : "scrollLeft"; if (reduceMotion) { _lastAnimState = undefined; targetObj[targetProp] = scrollOffset; } else { _ignoreScrollEvent = true; _lastAnimState = (0, animateProperty_1.animateProperty)(win.cancelAnimationFrame, function (_cancelled) { _ignoreScrollEvent = false; onScrollDebounced(); }, targetProp, animationTime, targetObj, scrollOffset, win.requestAnimationFrame, easings_1.easings.easeInOutQuad); } payload.go = ""; payload.direction = ""; electron_1.ipcRenderer.sendToHost(events_1.R2_EVENT_PAGE_TURN_RES, payload); return; } } else { if ((0, readium_css_1.isVerticalWritingMode)() && (Math.abs(scrollElement.scrollLeft) < maxScrollShiftTolerated) || !(0, readium_css_1.isVerticalWritingMode)() && (Math.abs(scrollElement.scrollTop) < maxScrollShiftTolerated)) { var newVal = (0, readium_css_1.isVerticalWritingMode)() ? (scrollElement.scrollLeft + ((0, readium_css_1.isRTL)() ? -1 : 1) * win.document.documentElement.clientWidth) : (scrollElement.scrollTop + win.document.documentElement.clientHeight); var targetObj = scrollElement; var targetProp = (0, readium_css_1.isVerticalWritingMode)() ? "scrollLeft" : "scrollTop"; if (reduceMotion) { _lastAnimState = undefined; targetObj[targetProp] = newVal; } else { _ignoreScrollEvent = true; _lastAnimState = (0, animateProperty_1.animateProperty)(win.cancelAnimationFrame, function (_cancelled) { _ignoreScrollEvent = false; onScrollDebounced(); }, targetProp, animationTime, targetObj, newVal, win.requestAnimationFrame, easings_1.easings.easeInOutQuad); } payload.go = ""; payload.direction = ""; electron_1.ipcRenderer.sendToHost(events_1.R2_EVENT_PAGE_TURN_RES, payload); return; } } } else if (goPREVIOUS) { if (isPaged) { var unit = (0, readium_css_1.isVerticalWritingMode)() ? win.document.documentElement.offsetHeight : win.document.documentElement.offsetWidth; var scrollElementOffset = Math.round((0, readium_css_1.isVerticalWritingMode)() ? scrollElement.scrollTop : scrollElement.scrollLeft); var isNegative = scrollElementOffset < 0; var scrollElementOffsetAbs = Math.abs(scrollElementOffset); var fractional = scrollElementOffsetAbs / unit; var integral = Math.floor(fractional); var decimal = fractional - integral; var partial = decimal * unit; if (partial <= CSS_PIXEL_TOLERANCE) { scrollElementOffset = (isNegative ? -1 : 1) * integral * unit; } else if (partial >= (unit - CSS_PIXEL_TOLERANCE)) { scrollElementOffset = (isNegative ? -1 : 1) * (integral + 1) * unit; } if ((0, readium_css_1.isVerticalWritingMode)() && (scrollElementOffsetAbs > 0) || !(0, readium_css_1.isVerticalWritingMode)() && (scrollElementOffsetAbs > 0)) { var scrollOffset_ = (0, readium_css_1.isVerticalWritingMode)() ? (scrollElementOffset - unit) : (scrollElementOffset - ((0, readium_css_1.isRTL)() ? -1 : 1) * unit); var nWholes = (0, readium_css_1.isRTL)() ? Math.floor(scrollOffset_ / unit) : Math.ceil(scrollOffset_ / unit); var scrollOffset = nWholes * unit; ensureTwoPageSpreadWithOddColumnsIsOffset(scrollOffset, 0); var targetObj = scrollElement; var targetProp = (0, readium_css_1.isVerticalWritingMode)() ? "scrollTop" : "scrollLeft"; if (reduceMotion) { _lastAnimState = undefined; targetObj[targetProp] = scrollOffset; } else { _ignoreScrollEvent = true; _lastAnimState = (0, animateProperty_1.animateProperty)(win.cancelAnimationFrame, function (_cancelled) { _ignoreScrollEvent = false; onScrollDebounced(); }, targetProp, animationTime, targetObj, scrollOffset, win.requestAnimationFrame, easings_1.easings.easeInOutQuad); } payload.go = ""; payload.direction = ""; electron_1.ipcRenderer.sendToHost(events_1.R2_EVENT_PAGE_TURN_RES, payload); return; } } else { if ((0, readium_css_1.isVerticalWritingMode)() && (Math.abs(scrollElement.scrollLeft) > 0) || !(0, readium_css_1.isVerticalWritingMode)() && (Math.abs(scrollElement.scrollTop) > 0)) { var newVal = (0, readium_css_1.isVerticalWritingMode)() ? (scrollElement.scrollLeft - ((0, readium_css_1.isRTL)() ? -1 : 1) * win.document.documentElement.clientWidth) : (scrollElement.scrollTop - win.document.documentElement.clientHeight); var targetObj = scrollElement; var targetProp = (0, readium_css_1.isVerticalWritingMode)() ? "scrollLeft" : "scrollTop"; if (reduceMotion) { _lastAnimState = undefined; targetObj[targetProp] = newVal; } else { _ignoreScrollEvent = true; _lastAnimState = (0, animateProperty_1.animateProperty)(win.cancelAnimationFrame, function (_cancelled) { _ignoreScrollEvent = false; onScrollDebounced(); }, targetProp, animationTime, targetObj, newVal, win.requestAnimationFrame, easings_1.easings.easeInOutQuad); } payload.go = ""; payload.direction = ""; electron_1.ipcRenderer.sendToHost(events_1.R2_EVENT_PAGE_TURN_RES, payload); return; } } } electron_1.ipcRenderer.sendToHost(events_1.R2_EVENT_PAGE_TURN_RES, payload); } electron_1.ipcRenderer.on(events_1.R2_EVENT_PAGE_TURN, function (_event, payload) { setTimeout(function () { onEventPageTurn(payload); }, 100); }); function focusElement(element) { if (element === win.document.body) { var attr = element.getAttribute("tabindex"); if (!attr) { element.setAttribute("tabindex", "-1"); element.classList.add(styles_1.CSS_CLASS_NO_FOCUS_OUTLINE); if (IS_DEV) { debug("tabindex -1 set BODY (focusable):"); debug(getCssSelector(element)); } } element.focus({ preventScroll: true }); } else { element.focus(); } electron_1.ipcRenderer.sendToHost(events_1.R2_EVENT_KEYBOARD_FOCUS_REQUEST, null); if (IS_DEV) { debug("KEYBOARD FOCUS REQUEST (1) ", getCssSelector(element)); } } var _lastAnimState2; var animationTime2 = 400; function scrollElementIntoView(element, doFocus, animate, domRect) { if (win.READIUM2.DEBUG_VISUALS) { var existings = win.document.querySelectorAll("*[".concat(styles_1.readPosCssStylesAttr3, "]")); existings.forEach(function (existing) { existing.removeAttribute("".concat(styles_1.readPosCssStylesAttr3)); }); element.setAttribute(styles_1.readPosCssStylesAttr3, "scrollElementIntoView"); } if (win.READIUM2.isFixedLayout) { debug("scrollElementIntoView_ SKIP FXL"); return; } if (doFocus) { if (!domRect && !(0, tabbable_1.isFocusable)(element)) { var attr = element.getAttribute("tabindex"); if (!attr) { element.setAttribute("tabindex", "-1"); element.classList.add(styles_1.CSS_CLASS_NO_FOCUS_OUTLINE); if (IS_DEV) { debug("tabindex -1 set (focusable):"); debug(getCssSelector(element)); } } } var targets = win.document.querySelectorAll(".".concat(styles_1.LINK_TARGET_CLASS)); targets.forEach(function (t) { t.classList.remove(styles_1.LINK_TARGET_CLASS); }); element.style.animation = "none"; void element.offsetWidth; element.style.animation = ""; element.classList.add(styles_1.LINK_TARGET_CLASS); if (element._timeoutTargetClass) { clearTimeout(element._timeoutTargetClass); element._timeoutTargetClass = undefined; } element._timeoutTargetClass = setTimeout(function () { debug("ANIMATION TIMEOUT REMOVE"); element.classList.remove(styles_1.LINK_TARGET_CLASS); }, 2000); if (!domRect) { focusElement(element); } } setTimeout(function () { var isPaged = (0, readium_css_inject_1.isPaginated)(win.document); if (isPaged) { scrollIntoView(element, domRect); } else { var scrollElement = (0, readium_css_1.getScrollingElement)(win.document); var rect = domRect || element.getBoundingClientRect(); var scrollTopMax = scrollElement.scrollHeight - win.document.documentElement.clientHeight; var offset = scrollElement.scrollTop + (rect.top - (win.document.documentElement.clientHeight / 2)); if (offset > scrollTopMax) { offset = scrollTopMax; } else if (offset < 0) { offset = 0; } var diff = Math.abs(scrollElement.scrollTop - offset); if (diff < 10) { return; } if (animate) { var reduceMotion = win.document.documentElement.classList.contains(styles_1.ROOT_CLASS_REDUCE_MOTION); if (_lastAnimState2 && _lastAnimState2.animating) { win.cancelAnimationFrame(_lastAnimState2.id); _lastAnimState2.object[_lastAnimState2.property] = _lastAnimState2.destVal; } var targetObj = scrollElement; var targetProp = "scrollTop"; if (reduceMotion) { _lastAnimState2 = undefined; targetObj[targetProp] = offset; } else { _ignoreScrollEvent = true; _lastAnimState2 = (0, animateProperty_1.animateProperty)(win.cancelAnimationFrame, function (_cancelled) { _ignoreScrollEvent = false; onScrollDebounced(); }, targetProp, animationTime2, targetObj, offset, win.requestAnimationFrame, easings_1.easings.easeInOutQuad); } } else { scrollElement.scrollTop = offset; } } }, doFocus ? 100 : 0); } function getScrollOffsetIntoView(element, domRect) { if (!win.document || !win.document.documentElement || !win.document.body || !(0, readium_css_inject_1.isPaginated)(win.document) || (0, readium_css_1.isVerticalWritingMode)()) { return 0; } var scrollElement = (0, readium_css_1.getScrollingElement)(win.document); var rect = domRect || element.getBoundingClientRect(); var columnDimension = (0, readium_css_1.calculateColumnDimension)(); var isTwoPage = (0, readium_css_1.isTwoPageSpread)(); var fullOffset = ((0, readium_css_1.isRTL)() ? ((columnDimension * (isTwoPage ? 2 : 1)) - (rect.left + rect.width)) : rect.left) + (((0, readium_css_1.isRTL)() ? -1 : 1) * scrollElement.scrollLeft); var columnIndex = Math.floor(fullOffset / columnDimension); var spreadIndex = isTwoPage ? Math.floor(columnIndex / 2) : columnIndex; return ((0, readium_css_1.isRTL)() ? -1 : 1) * (spreadIndex * (columnDimension * (isTwoPage ? 2 : 1))); } function scrollIntoView(element, domRect) { if (!win.document || !win.document.documentElement || !win.document.body || !(0, readium_css_inject_1.isPaginated)(win.document)) { return; } var maxScrollShift = (0, readium_css_1.calculateMaxScrollShift)().maxScrollShift; var scrollLeftPotentiallyExcessive = getScrollOffsetIntoView(element, domRect); ensureTwoPageSpreadWithOddColumnsIsOffset(scrollLeftPotentiallyExcessive, maxScrollShift); var scrollElement = (0, readium_css_1.getScrollingElement)(win.document); var scrollOffset = (scrollLeftPotentiallyExcessive < 0 ? -1 : 1) * Math.min(Math.abs(scrollLeftPotentiallyExcessive), maxScrollShift); scrollElement.scrollLeft = scrollOffset; } var scrollToHashRaw = function (animate) { if (!win.document || !win.document.body || !win.document.documentElement) { return; } (0, highlight_1.recreateAllHighlights)(win); debug("++++ scrollToHashRaw"); var isPaged = (0, readium_css_inject_1.isPaginated)(win.document); if (win.READIUM2.locationHashOverride) { scrollElementIntoView(win.READIUM2.locationHashOverride, true, animate, undefined); notifyReadingLocationDebounced(); return; } else if (win.READIUM2.hashElement) { win.READIUM2.locationHashOverride = win.READIUM2.hashElement; scrollElementIntoView(win.READIUM2.hashElement, true, animate, undefined); notifyReadingLocationDebounced(); return; } else { var scrollElement = (0, readium_css_1.getScrollingElement)(win.document); if (win.READIUM2.urlQueryParams) { var previous = win.READIUM2.urlQueryParams[url_params_1.URL_PARAM_PREVIOUS]; var isPreviousNavDirection = previous === "true"; if (isPreviousNavDirection) { var _a = (0, readium_css_1.calculateMaxScrollShift)(), maxScrollShift = _a.maxScrollShift, maxScrollShiftAdjusted = _a.maxScrollShiftAdjusted; _ignoreScrollEvent = true; if (isPaged) { if ((0, readium_css_1.isVerticalWritingMode)()) { scrollElement.scrollLeft = 0; scrollElement.scrollTop = maxScrollShift; } else { var scrollLeftPotentiallyExcessive = ((0, readium_css_1.isRTL)() ? -1 : 1) * maxScrollShiftAdjusted; ensureTwoPageSpreadWithOddColumnsIsOffset(scrollLeftPotentiallyExcessive, maxScrollShift); var scrollLeft = ((0, readium_css_1.isRTL)() ? -1 : 1) * maxScrollShift; scrollElement.scrollLeft = scrollLeft; scrollElement.scrollTop = 0; } } else { if ((0, readium_css_1.isVerticalWritingMode)()) { scrollElement.scrollLeft = ((0, readium_css_1.isRTL)() ? -1 : 1) * maxScrollShift; scrollElement.scrollTop = 0; } else { scrollElement.scrollLeft = 0; scrollElement.scrollTop = maxScrollShift; } } win.READIUM2.locationHashOverride = undefined; resetLocationHashOverrideInfo(); setTimeout(function () { processXYRaw(0, 0, false); showHideContentMask(false, win.READIUM2.isFixedLayout); if (!win.READIUM2.locationHashOverride) { notifyReadingLocationDebounced(); } setTimeout(function () { _ignoreScrollEvent = false; }, 10); }, 60); return; } var gto = win.READIUM2.urlQueryParams[url_params_1.URL_PARAM_GOTO]; var gotoCssSelector = void 0; var gotoProgression = void 0; if (gto) { var locStr = Buffer.from(gto, "base64").toString("utf8"); var locObj = JSON.parse(locStr); gotoCssSelector = locObj.cssSelector; gotoProgression = locObj.progression; } if (gotoCssSelector) { gotoCssSelector = gotoCssSelector.replace(/\+/g, " "); var selected = null; try { selected = win.document.querySelector(gotoCssSelector); } catch (err) { debug(err); } if (selected) { win.READIUM2.locationHashOverride = selected; debug(".hashElement = 2"); win.READIUM2.hashElement = selected; resetLocationHashOverrideInfo(); if (win.READIUM2.locationHashOverrideInfo) { win.READIUM2.locationHashOverrideInfo.locations.cssSelector = gotoCssSelector; } var domRect = void 0; var gtoDomRange = win.READIUM2.urlQueryParams[url_params_1.URL_PARAM_GOTO_DOM_RANGE]; if (gtoDomRange) { try { var rangeInfoStr = Buffer.from(gtoDomRange, "base64").toString("utf8"); var rangeInfo = JSON.parse(rangeInfoStr); debug("rangeInfo", rangeInfo); var domRange = (0, selection_2.convertRangeInfo)(win.document, rangeInfo); if (domRange) { domRect = domRange.getBoundingClientRect(); } } catch (err) { debug("gtoDomRange", err); } } scrollElementIntoView(selected, true, animate, domRect); notifyReadingLocationDebounced(); return; } } else if (gotoProgression) { var maxScrollShift = (0, readium_css_1.calculateMaxScrollShift)().maxScrollShift; if (isPaged) { var isTwoPage = (0, readium_css_1.isTwoPageSpread)(); var nColumns = (0, readium_css_1.calculateTotalColumns)(); var nUnits = isTwoPage ? Math.ceil(nColumns / 2) : nColumns; var unitIndex = Math.floor(gotoProgression * nUnits); var unit = (0, readium_css_1.isVerticalWritingMode)() ? win.document.documentElement.offsetHeight : win.document.documentElement.offsetWidth; var scrollOffsetPotentiallyExcessive = (0, readium_css_1.isVerticalWritingMode)() ? (unitIndex * unit) : (((0, readium_css_1.isRTL)() ? -1 : 1) * unitIndex * unit); ensureTwoPageSpreadWithOddColumnsIsOffset(scrollOffsetPotentiallyExcessive, maxScrollShift); var scrollOffsetPaged = (scrollOffsetPotentiallyExcessive < 0 ? -1 : 1) * Math.min(Math.abs(scrollOffsetPotentiallyExcessive), maxScrollShift); _ignoreScrollEvent = true; if ((0, readium_css_1.isVerticalWritingMode)()) { scrollElement.scrollTop = scrollOffsetPaged; } else { scrollElement.scrollLeft = scrollOffsetPaged; } setTimeout(function () { _ignoreScrollEvent = false; }, 10); win.READIUM2.locationHashOverride = win.document.body; resetLocationHashOverrideInfo(); focusElement(win.READIUM2.locationHashOverride); processXYRaw(0, 0, false); if (!win.READIUM2.locationHashOverride) { notifyReadingLocationDebounced(); } return; } var scrollOffset = gotoProgression * maxScrollShift; _ignoreScrollEvent = true; if ((0, readium_css_1.isVerticalWritingMode)()) { scrollElement.scrollLeft = scrollOffset; } else { scrollElement.scrollTop = scrollOffset; } setTimeout(function () { _ignoreScrollEvent = false; }, 10); win.READIUM2.locationHashOverride = win.document.body; resetLocationHashOverrideInfo(); focusElement(win.READIUM2.locationHashOverride); processXYRaw(0, 0, false); if (!win.READIUM2.locationHashOverride) { notifyReadingLocationDebounced(); } return; } } _ignoreScrollEvent = true; scrollElement.scrollLeft = 0; scrollElement.scrollTop = 0; setTimeout(function () { _ignoreScrollEvent = false; }, 10); win.READIUM2.locationHashOverride = win.document.body; resetLocationHashOverrideInfo(); focusElement(win.READIUM2.locationHashOverride); debug("processXYRaw BODY"); processXYRaw(0, 0, false); } notifyReadingLocationDebounced(); }; var scrollToHashDebounced = (0, debounce_1.debounce)(function (animate) { debug("++++ scrollToHashRaw FROM DEBOUNCED"); scrollToHashRaw(animate); }, 100); var _ignoreScrollEvent = false; function showHideContentMask(doHide, isFixedLayout) { if (doHide) { win.document.documentElement.classList.add(styles_1.ROOT_CLASS_INVISIBLE_MASK); win.document.documentElement.classList.remove(styles_1.ROOT_CLASS_INVISIBLE_MASK_REMOVED); } else { electron_1.ipcRenderer.sendToHost(events_1.R2_EVENT_SHOW, null); if (isFixedLayout) { win.document.documentElement.classList.add(styles_1.ROOT_CLASS_INVISIBLE_MASK_REMOVED); } win.document.documentElement.classList.remove(styles_1.ROOT_CLASS_INVISIBLE_MASK); } } function focusScrollRaw(el, doFocus, animate, domRect) { scrollElementIntoView(el, doFocus, animate, domRect); if (win.READIUM2.locationHashOverride === el) { return; } var blacklisted = checkBlacklisted(el); if (blacklisted) { return; } debug(".hashElement = 3"); win.READIUM2.hashElement = doFocus ? el : win.READIUM2.hashElement; win.READIUM2.locationHashOverride = el; notifyReadingLocationDebounced(); } var focusScrollDebounced = (0, debounce_1.debounce)(function (el, doFocus, animate, domRect) { focusScrollRaw(el, doFocus, animate, domRect); }, 100); var handleFocusInDebounced = (0, debounce_1.debounce)(function (target, tabKeyDownEvent) { handleFocusInRaw(target, tabKeyDownEvent); }, 100); function handleFocusInRaw(target, _tabKeyDownEvent) { if (!target || !win.document.body) { return; } focusScrollRaw(target, false, false, undefined); } electron_1.ipcRenderer.on(events_1.R2_EVENT_READIUMCSS, function (_event, payload) { showHideContentMask(true, payload.isFixedLayout || win.READIUM2.isFixedLayout); (0, readium_css_1.readiumCSS)(win.document, payload); (0, highlight_1.recreateAllHighlights)(win); showHideContentMask(false, payload.isFixedLayout || win.READIUM2.isFixedLayout); }); var _docTitle; win.addEventListener("DOMContentLoaded", function () { debug("############# DOMContentLoaded"); var titleElement = win.document.documentElement.querySelector("head > title"); if (titleElement && titleElement.textContent) { _docTitle = titleElement.textContent; } if (!win.READIUM2.isAudio && win.location.hash && win.location.hash.length > 1) { debug(".hashElement = 4"); win.READIUM2.hashElement = win.document.getElementById(win.location.hash.substr(1)); if (win.READIUM2.DEBUG_VISUALS) { if (win.READIUM2.hashElement) { win.READIUM2.hashElement.setAttribute(styles_1.readPosCssStylesAttr1, "DOMContentLoaded hashElement"); } } } win.READIUM2.locationHashOverride = undefined; win.READIUM2.ttsClickEnabled = false; win.READIUM2.ttsSkippabilityEnabled = false; win.READIUM2.ttsSentenceDetectionEnabled = true; win.READIUM2.ttsOverlayEnabled = false; var readiumcssJson; if (win.READIUM2.urlQueryParams) { var base64ReadiumCSS = win.READIUM2.urlQueryParams[url_params_1.URL_PARAM_CSS]; if (base64ReadiumCSS) { var str = void 0;