UNPKG

epubjs

Version:
508 lines (437 loc) 12.4 kB
"use strict"; Object.defineProperty(exports, "__esModule", { value: true }); exports.isElement = isElement; exports.uuid = uuid; exports.documentHeight = documentHeight; exports.isNumber = isNumber; exports.isFloat = isFloat; exports.prefixed = prefixed; exports.defaults = defaults; exports.extend = extend; exports.insert = insert; exports.locationOf = locationOf; exports.indexOfSorted = indexOfSorted; exports.bounds = bounds; exports.borders = borders; exports.windowBounds = windowBounds; exports.cleanStringForXpath = cleanStringForXpath; exports.indexOfTextNode = indexOfTextNode; exports.isXml = isXml; exports.createBlob = createBlob; exports.createBlobUrl = createBlobUrl; exports.createBase64Url = createBase64Url; exports.type = type; exports.parse = parse; exports.qs = qs; exports.qsa = qsa; exports.qsp = qsp; exports.sprint = sprint; exports.treeWalker = treeWalker; exports.walk = walk; exports.blob2base64 = blob2base64; exports.defer = defer; exports.querySelectorByType = querySelectorByType; exports.findChildren = findChildren; var requestAnimationFrame = exports.requestAnimationFrame = typeof window != "undefined" ? window.requestAnimationFrame || window.mozRequestAnimationFrame || window.webkitRequestAnimationFrame || window.msRequestAnimationFrame : false; function isElement(obj) { return !!(obj && obj.nodeType == 1); } // http://stackoverflow.com/questions/105034/how-to-create-a-guid-uuid-in-javascript function uuid() { var d = new Date().getTime(); var uuid = "xxxxxxxx-xxxx-4xxx-yxxx-xxxxxxxxxxxx".replace(/[xy]/g, function (c) { var r = (d + Math.random() * 16) % 16 | 0; d = Math.floor(d / 16); return (c == "x" ? r : r & 0x7 | 0x8).toString(16); }); return uuid; } function documentHeight() { return Math.max(document.documentElement.clientHeight, document.body.scrollHeight, document.documentElement.scrollHeight, document.body.offsetHeight, document.documentElement.offsetHeight); } function isNumber(n) { return !isNaN(parseFloat(n)) && isFinite(n); } function isFloat(n) { return isNumber(n) && Math.floor(n) !== n; } function prefixed(unprefixed) { var vendors = ["Webkit", "Moz", "O", "ms"]; // var prefixes = ["-Webkit-", "-moz-", "-o-", "-ms-"]; var upper = unprefixed[0].toUpperCase() + unprefixed.slice(1); var length = vendors.length; if (typeof document === "undefined" || typeof document.body.style[unprefixed] != "undefined") { return unprefixed; } for (var i = 0; i < length; i++) { if (typeof document.body.style[vendors[i] + upper] != "undefined") { return vendors[i] + upper; } } return unprefixed; } function defaults(obj) { for (var i = 1, length = arguments.length; i < length; i++) { var source = arguments[i]; for (var prop in source) { if (obj[prop] === void 0) obj[prop] = source[prop]; } } return obj; } function extend(target) { var sources = [].slice.call(arguments, 1); sources.forEach(function (source) { if (!source) return; Object.getOwnPropertyNames(source).forEach(function (propName) { Object.defineProperty(target, propName, Object.getOwnPropertyDescriptor(source, propName)); }); }); return target; } // Fast quicksort insert for sorted array -- based on: // http://stackoverflow.com/questions/1344500/efficient-way-to-insert-a-number-into-a-sorted-array-of-numbers function insert(item, array, compareFunction) { var location = locationOf(item, array, compareFunction); array.splice(location, 0, item); return location; } // Returns where something would fit in function locationOf(item, array, compareFunction, _start, _end) { var start = _start || 0; var end = _end || array.length; var pivot = parseInt(start + (end - start) / 2); var compared; if (!compareFunction) { compareFunction = function compareFunction(a, b) { if (a > b) return 1; if (a < b) return -1; if (a == b) return 0; }; } if (end - start <= 0) { return pivot; } compared = compareFunction(array[pivot], item); if (end - start === 1) { return compared > 0 ? pivot : pivot + 1; } if (compared === 0) { return pivot; } if (compared === -1) { return locationOf(item, array, compareFunction, pivot, end); } else { return locationOf(item, array, compareFunction, start, pivot); } } // Returns -1 of mpt found function indexOfSorted(item, array, compareFunction, _start, _end) { var start = _start || 0; var end = _end || array.length; var pivot = parseInt(start + (end - start) / 2); var compared; if (!compareFunction) { compareFunction = function compareFunction(a, b) { if (a > b) return 1; if (a < b) return -1; if (a == b) return 0; }; } if (end - start <= 0) { return -1; // Not found } compared = compareFunction(array[pivot], item); if (end - start === 1) { return compared === 0 ? pivot : -1; } if (compared === 0) { return pivot; // Found } if (compared === -1) { return indexOfSorted(item, array, compareFunction, pivot, end); } else { return indexOfSorted(item, array, compareFunction, start, pivot); } } function bounds(el) { var style = window.getComputedStyle(el); var widthProps = ["width", "paddingRight", "paddingLeft", "marginRight", "marginLeft", "borderRightWidth", "borderLeftWidth"]; var heightProps = ["height", "paddingTop", "paddingBottom", "marginTop", "marginBottom", "borderTopWidth", "borderBottomWidth"]; var width = 0; var height = 0; widthProps.forEach(function (prop) { width += parseFloat(style[prop]) || 0; }); heightProps.forEach(function (prop) { height += parseFloat(style[prop]) || 0; }); return { height: height, width: width }; } function borders(el) { var style = window.getComputedStyle(el); var widthProps = ["paddingRight", "paddingLeft", "marginRight", "marginLeft", "borderRightWidth", "borderLeftWidth"]; var heightProps = ["paddingTop", "paddingBottom", "marginTop", "marginBottom", "borderTopWidth", "borderBottomWidth"]; var width = 0; var height = 0; widthProps.forEach(function (prop) { width += parseFloat(style[prop]) || 0; }); heightProps.forEach(function (prop) { height += parseFloat(style[prop]) || 0; }); return { height: height, width: width }; } function windowBounds() { var width = window.innerWidth; var height = window.innerHeight; return { top: 0, left: 0, right: width, bottom: height, width: width, height: height }; } //-- https://stackoverflow.com/questions/13482352/xquery-looking-for-text-with-single-quote/13483496#13483496 function cleanStringForXpath(str) { var parts = str.match(/[^'"]+|['"]/g); parts = parts.map(function (part) { if (part === "'") { return "\"\'\""; // output "'" } if (part === "\"") { return "\'\"\'"; // output '"' } return "'" + part + "'"; }); return "concat(''," + parts.join(",") + ")"; } function indexOfTextNode(textNode) { var parent = textNode.parentNode; var children = parent.childNodes; var sib; var index = -1; for (var i = 0; i < children.length; i++) { sib = children[i]; if (sib.nodeType === Node.TEXT_NODE) { index++; } if (sib == textNode) break; } return index; } function isXml(ext) { return ["xml", "opf", "ncx"].indexOf(ext) > -1; } function createBlob(content, mime) { return new Blob([content], { type: mime }); } function createBlobUrl(content, mime) { var _URL = window.URL || window.webkitURL || window.mozURL; var tempUrl; var blob = this.createBlob(content, mime); tempUrl = _URL.createObjectURL(blob); return tempUrl; } function createBase64Url(content, mime) { var data; var datauri; if (typeof content !== "string") { // Only handles strings return; } data = btoa(content); datauri = "data:" + mime + ";base64," + data; return datauri; } function type(obj) { return Object.prototype.toString.call(obj).slice(8, -1); } function parse(markup, mime, forceXMLDom) { var doc; var Parser; if (typeof DOMParser === "undefined" || forceXMLDom) { Parser = require("xmldom").DOMParser; } else { Parser = DOMParser; } doc = new Parser().parseFromString(markup, mime); return doc; } function qs(el, sel) { var elements; if (!el) { throw new Error("No Element Provided"); } if (typeof el.querySelector != "undefined") { return el.querySelector(sel); } else { elements = el.getElementsByTagName(sel); if (elements.length) { return elements[0]; } } } function qsa(el, sel) { if (typeof el.querySelector != "undefined") { return el.querySelectorAll(sel); } else { return el.getElementsByTagName(sel); } } function qsp(el, sel, props) { var q, filtered; if (typeof el.querySelector != "undefined") { sel += "["; for (var prop in props) { sel += prop + "='" + props[prop] + "'"; } sel += "]"; return el.querySelector(sel); } else { q = el.getElementsByTagName(sel); filtered = Array.prototype.slice.call(q, 0).filter(function (el) { for (var prop in props) { if (el.getAttribute(prop) === props[prop]) { return true; } } return false; }); if (filtered) { return filtered[0]; } } } /** * Sprint through all text nodes in a document * @param {element} root element to start with * @param {function} func function to run on each element */ function sprint(root, func) { var doc = root.ownerDocument || root; if (typeof doc.createTreeWalker !== "undefined") { treeWalker(root, func, NodeFilter.SHOW_TEXT); } else { walk(root, function (node) { if (node && node.nodeType === 3) { // Node.TEXT_NODE func(node); } }, true); } } function treeWalker(root, func, filter) { var treeWalker = document.createTreeWalker(root, filter, null, false); var node = void 0; while (node = treeWalker.nextNode()) { func(node); } } // export function walk(root, func, onlyText) { // var node = root; // // if (node && !onlyText || node.nodeType === 3) { // Node.TEXT_NODE // func(node); // } // console.log(root); // // node = node.firstChild; // while(node) { // walk(node, func, onlyText); // node = node.nextSibling; // } // } /** * @param callback return false for continue,true for break * @return boolean true: break visit; */ function walk(node, callback) { if (callback(node)) { return true; } node = node.firstChild; if (node) { do { var walked = walk(node, callback); if (walked) { return true; } node = node.nextSibling; } while (node); } } function blob2base64(blob, cb) { var reader = new FileReader(); reader.readAsDataURL(blob); reader.onloadend = function () { cb(reader.result); }; } // From: https://developer.mozilla.org/en-US/docs/Mozilla/JavaScript_code_modules/Promise.jsm/Deferred#backwards_forwards_compatible function defer() { var _this = this; /* A method to resolve the associated Promise with the value passed. * If the promise is already settled it does nothing. * * @param {anything} value : This value is used to resolve the promise * If the value is a Promise then the associated promise assumes the state * of Promise passed as value. */ this.resolve = null; /* A method to reject the assocaited Promise with the value passed. * If the promise is already settled it does nothing. * * @param {anything} reason: The reason for the rejection of the Promise. * Generally its an Error object. If however a Promise is passed, then the Promise * itself will be the reason for rejection no matter the state of the Promise. */ this.reject = null; this.id = uuid(); /* A newly created Pomise object. * Initially in pending state. */ this.promise = new Promise(function (resolve, reject) { _this.resolve = resolve; _this.reject = reject; }); Object.freeze(this); } function querySelectorByType(html, element, type) { var query; if (typeof html.querySelector != "undefined") { query = html.querySelector(element + "[*|type=\"" + type + "\"]"); } // Handle IE not supporting namespaced epub:type in querySelector if (!query || query.length === 0) { query = qsa(html, element); for (var i = 0; i < query.length; i++) { if (query[i].getAttributeNS("http://www.idpf.org/2007/ops", "type") === type) { return query[i]; } } } else { return query; } } function findChildren(el) { var result = []; var childNodes = el.parentNode.childNodes; for (var i = 0; i < childNodes.length; i++) { var node = childNodes[i]; if (node.nodeType === 1) { result.push(node); } } return result; }