diff --git a/epubjs/hooks/embedh.js b/epubjs/hooks/embedh.js new file mode 100644 index 0000000..144639b --- /dev/null +++ b/epubjs/hooks/embedh.js @@ -0,0 +1,11 @@ +EPUBJS.Hooks.register("beforeChapterDisplay").example = function(callback, chapter){ + + + var s = document.createElement("script"); + s.type = 'text/javascript'; + s.src ="https://test.hypothes.is/app/embed.js" + + chapter.doc.body.appendChild(s); + + //-- Continue to other hooks + if(callback) callback();} \ No newline at end of file diff --git a/epubjs/hooks/endnotes.js b/epubjs/hooks/endnotes.js new file mode 100644 index 0000000..d853bbf --- /dev/null +++ b/epubjs/hooks/endnotes.js @@ -0,0 +1,154 @@ +EPUBJS.Hooks.register("beforeChapterDisplay").endnotes = function(callback, chapter){ + + var notes = chapter.doc.querySelectorAll('a[href]'), + items = Array.prototype.slice.call(notes), //[].slice.call() + attr = "epub:type", + type = "noteref", + popups = {}; + + + EPUBJS.core.addCss("css/popup.css", false, chapter.doc.head); + + //console.log("notes", items) + items.forEach(function(item){ + var epubType = item.getAttribute(attr), + href, + id, + el, + pop, + pos, + left, + top, + txt; + + if(epubType != type) return; + + href = item.getAttribute("href"); + id = href.replace("#", ''); + el = chapter.doc.getElementById(id); + + + item.addEventListener("mouseover", showPop, false); + item.addEventListener("mouseout", hidePop, false); + + function showPop(){ + var poppos, + iheight = chapter.iframe.height, + iwidth = chapter.iframe.width, + tip, + pop, + maxHeight = 225; + + if(!txt) { + pop = el.cloneNode(true); + txt = pop.querySelector("p"); + } + + //-- create a popup with endnote inside of it + if(!popups[id]) { + popups[id] = document.createElement("div"); + popups[id].setAttribute("class", "popup"); + + pop_content = document.createElement("div"); + + popups[id].appendChild(pop_content); + + pop_content.appendChild(txt); + pop_content.setAttribute("class", "pop_content"); + + chapter.bodyEl.appendChild(popups[id]); + + //-- TODO: will these leak memory? - Fred + popups[id].addEventListener("mouseover", onPop, false); + popups[id].addEventListener("mouseout", offPop, false); + + //-- Add hide on page change + chapter.book.listenUntil("book:pageChanged", "book:chapterDestroy", hidePop); + chapter.book.listenUntil("book:pageChanged", "book:chapterDestroy", offPop); + + } + + pop = popups[id]; + + + //-- get location of item + itemRect = item.getBoundingClientRect(); + left = itemRect.left; + top = itemRect.top; + + //-- show the popup + pop.classList.add("show"); + + //-- locations of popup + popRect = pop.getBoundingClientRect(); + + //-- position the popup + pop.style.left = left - popRect.width / 2 + "px"; + pop.style.top = top + "px"; + + + //-- Adjust max height + if(maxHeight > iheight / 2.5) { + maxHeight = iheight / 2.5; + pop_content.style.maxHeight = maxHeight + "px"; + } + + //-- switch above / below + if(popRect.height + top >= iheight - 25) { + pop.style.top = top - popRect.height + "px"; + pop.classList.add("above"); + }else{ + pop.classList.remove("above"); + } + + //-- switch left + if(left - popRect.width <= 0) { + pop.style.left = left + "px"; + pop.classList.add("left"); + }else{ + pop.classList.remove("left"); + } + + //-- switch right + if(left + popRect.width / 2 >= iwidth) { + //-- TEMP MOVE: 300 + pop.style.left = left - 300 + "px"; + + popRect = pop.getBoundingClientRect(); + pop.style.left = left - popRect.width + "px"; + //-- switch above / below again + if(popRect.height + top >= iheight - 25) { + pop.style.top = top - popRect.height + "px"; + pop.classList.add("above"); + }else{ + pop.classList.remove("above"); + } + + pop.classList.add("right"); + }else{ + pop.classList.remove("right"); + } + + + } + + function onPop(){ + popups[id].classList.add("on"); + } + + function offPop(){ + popups[id].classList.remove("on"); + } + + function hidePop(){ + setTimeout(function(){ + popups[id].classList.remove("show"); + }, 100); + } + + }); + + + if(callback) callback(); + +} diff --git a/epubjs/hooks/extras/annotate.js b/epubjs/hooks/extras/annotate.js new file mode 100644 index 0000000..fc82d02 --- /dev/null +++ b/epubjs/hooks/extras/annotate.js @@ -0,0 +1,78 @@ +EPUBJS.Hooks.register("beforeChapterDisplay").annotate = function(callback, chapter){ + + + var chap = chapter.bodyEl, + server = 'http://127.0.0.1:5000/'; + files = [ + EPUBJS.filePath + "libs/jquery-1.9.0.js", + EPUBJS.filePath + "libs/jquery-migrate-1.1.1.js", + EPUBJS.filePath + "libs/annotator-full.js" + ]; + + + //EPUBJS.core.loadScripts(files, annotate, chapter.doc.head); + $(chapter.doc.body).annotator().annotator('setupPlugins', {}, { + + Filter:false, + Store: { + annotationData: { + 'uri': chapter.path + }, + loadFromSearch: { + 'limit': 100, + 'uri': chapter.path + } + } + + }); + EPUBJS.core.addCss("css/annotator.css", false, chapter.doc.head); + if(callback) callback(); + + function annotate(){ + EPUBJS.core.addCss("css/annotator.css", false, chapter.doc.head); + + var s = document.createElement("script"); + s.type = 'text/javascript'; + + var a = "jQuery.migrateTrace = false;"; + //a += "console.log(document.getElementById('c001p0002').getBoundingClientRect());"; + + a += "var content = $('body').annotator().annotator('setupPlugins', {}, {Filter:false});"; + + //-- Use Local Server: + + // a += "var content = $('body').annotator(),"; + // a += " server = '" + server + "';"; + // a += " path = '" + chapter.path + "';"; + // + // a += " content.annotator('addPlugin', 'Store', {"; + // // The endpoint of the store on your server. + // a += " prefix: server,"; + // + // // Attach the uri of the current page to all annotations to allow search. + // a += " annotationData: {"; + // a += " 'uri': path"; + // a += " }"; + + // This will perform a search action rather than read when the plugin + // loads. Will request the last 20 annotations for the current url. + // eg. /store/endpoint/search?limit=20&uri=http://this/document/only + // a += "," + // a += " loadFromSearch: {"; + // a += " 'limit': 20,"; + // a += " 'uri': path"; + // a += " }"; + //a += "});"; + + s.innerHTML = a; + + chapter.doc.body.appendChild(s); + + if(callback) callback(); + } + + + +} + + diff --git a/epubjs/hooks/extras/example.js b/epubjs/hooks/extras/example.js new file mode 100644 index 0000000..8bbcdf3 --- /dev/null +++ b/epubjs/hooks/extras/example.js @@ -0,0 +1,43 @@ +EPUBJS.Hooks.register("beforeChapterDisplay").example = function(callback, chapter){ + + EPUBJS.core.addCss("css/annotator.css", false, chapter.doc.head); + + EPUBJS.core.addScript(EPUBJS.filePath + "libs/annotator-full.js", function() { + + //-- Config script + var s = document.createElement("script"); + s.type = 'text/javascript'; + + a = '/* -*- js -*- */ +/*{literal} chapter.colWidth){ + // ratio = chapter.colWidth / width; + // + // width = chapter.colWidth; + // height = height * ratio; + // } + // + // iframe.width = width; + // iframe.height = height; + } + + function shouldPlay(e) { + page = 1; + if(e) page = e.msg; + + if(page != onSpread) return; + + if(playing) playing.pause(); + + item.play(); + + playing = item; + + console.log("start", item.src) + + } + + + + + //-- resize event + + + chapter.book.listenUntil("book:resized", "book:chapterDestroy", getPage); + + chapter.book.listenUntil("book:pageChanged", "book:chapterDestroy", shouldPlay); + + item.removeAttribute("controls"); + + getPage(); + shouldPlay(); + + }); + + + + + if(callback) callback(); + + +} diff --git a/epubjs/hooks/smartimages.js b/epubjs/hooks/smartimages.js new file mode 100644 index 0000000..ff24a2b --- /dev/null +++ b/epubjs/hooks/smartimages.js @@ -0,0 +1,45 @@ +EPUBJS.Hooks.register("beforeChapterDisplay").smartimages = function(callback, chapter){ + + var image = chapter.doc.querySelectorAll('img'), + items = Array.prototype.slice.call(image), + iheight = chapter.iframe.height, + oheight; + + items.forEach(function(item){ + + function size() { + var itemRect = item.getBoundingClientRect(), + height = itemRect.height, + top = itemRect.top; + + iheight = chapter.iframe.height; + + + if(height + top >= iheight) { + + if(top < iheight/2) { + item.style.maxHeight = iheight - top + "px"; + item.style.width= "auto"; + }else{ + + item.style.maxHeight = (height < iheight ? height : iheight) + "px"; + item.style.marginTop = iheight - top + "px"; + item.style.width= "auto"; + } + + }else{ + item.style.removeProperty('max-height'); + item.style.removeProperty('margin-top'); + } + } + + + chapter.book.listenUntil("book:resized", "book:chapterDestroy", size); + + size(); + + }); + + if(callback) callback(); + +} diff --git a/epubjs/hooks/transculsions.js b/epubjs/hooks/transculsions.js new file mode 100644 index 0000000..7a5bac9 --- /dev/null +++ b/epubjs/hooks/transculsions.js @@ -0,0 +1,59 @@ +EPUBJS.Hooks.register("beforeChapterDisplay").transculsions = function(callback, chapter){ + /* + + */ + + var trans = chapter.doc.querySelectorAll('[transclusion]'), + items = Array.prototype.slice.call(trans); + + items.forEach(function(item){ + var src = item.getAttribute("ref"), + iframe = document.createElement('iframe'), + orginal_width = item.getAttribute("width"), + orginal_height = item.getAttribute("height"), + parent = item.parentNode, + width = orginal_width, + height = orginal_height, + ratio; + + + function size() { + width = orginal_width; + height = orginal_height; + + if(width > chapter.colWidth){ + ratio = chapter.colWidth / width; + + width = chapter.colWidth; + height = height * ratio; + } + + iframe.width = width; + iframe.height = height; + } + + + size(); + + //-- resize event + + + chapter.book.listenUntil("book:resized", "book:chapterDestroy", size); + + iframe.src = src; + + // + parent.replaceChild(iframe, item); + + + }); + + + + + if(callback) callback(); + + +} diff --git a/epubjs/libs/annotator-full-o.js b/epubjs/libs/annotator-full-o.js new file mode 100644 index 0000000..046cec6 --- /dev/null +++ b/epubjs/libs/annotator-full-o.js @@ -0,0 +1,2759 @@ +/* +** Annotator 1.2.6-dev-f4e0b5d +** https://github.com/okfn/annotator/ +** +** Copyright 2012 Aron Carroll, Rufus Pollock, and Nick Stenning. +** Dual licensed under the MIT and GPLv3 licenses. +** https://github.com/okfn/annotator/blob/master/LICENSE +** +** Built at: 2013-03-04 19:18:55Z +*/ + +(function() { + var $, Annotator, Delegator, LinkParser, Range, base64Decode, base64UrlDecode, createDateFromISO8601, fn, functions, g, gettext, parseToken, util, _Annotator, _gettext, _i, _j, _len, _len2, _ref, _ref2, _t, + __slice = Array.prototype.slice, + __hasProp = Object.prototype.hasOwnProperty, + __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor; child.__super__ = parent.prototype; return child; }, + __bind = function(fn, me){ return function(){ return fn.apply(me, arguments); }; }, + __indexOf = Array.prototype.indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; }; + + gettext = null; + + if (typeof Gettext !== "undefined" && Gettext !== null) { + _gettext = new Gettext({ + domain: "annotator" + }); + gettext = function(msgid) { + return _gettext.gettext(msgid); + }; + } else { + gettext = function(msgid) { + return msgid; + }; + } + + _t = function(msgid) { + return gettext(msgid); + }; + + if (!(typeof jQuery !== "undefined" && jQuery !== null ? (_ref = jQuery.fn) != null ? _ref.jquery : void 0 : void 0)) { + console.error(_t("Annotator requires jQuery: have you included lib/vendor/jquery.js?")); + } + + if (!(JSON && JSON.parse && JSON.stringify)) { + console.error(_t("Annotator requires a JSON implementation: have you included lib/vendor/json2.js?")); + } + + $ = jQuery.sub(); + + $.flatten = function(array) { + var flatten; + flatten = function(ary) { + var el, flat, _i, _len; + flat = []; + for (_i = 0, _len = ary.length; _i < _len; _i++) { + el = ary[_i]; + flat = flat.concat(el && $.isArray(el) ? flatten(el) : el); + } + return flat; + }; + return flatten(array); + }; + + $.plugin = function(name, object) { + return jQuery.fn[name] = function(options) { + var args; + args = Array.prototype.slice.call(arguments, 1); + return this.each(function() { + var instance; + instance = $.data(this, name); + if (instance) { + return options && instance[options].apply(instance, args); + } else { + instance = new object(this, options); + return $.data(this, name, instance); + } + }); + }; + }; + + $.fn.textNodes = function() { + var getTextNodes; + getTextNodes = function(node) { + var nodes; + if (node && node.nodeType !== 3) { + nodes = []; + if (node.nodeType !== 8) { + node = node.lastChild; + while (node) { + nodes.push(getTextNodes(node)); + node = node.previousSibling; + } + } + return nodes.reverse(); + } else { + return node; + } + }; + return this.map(function() { + return $.flatten(getTextNodes(this)); + }); + }; + + $.fn.xpath = function(relativeRoot) { + var jq; + jq = this.map(function() { + var elem, idx, path; + path = ''; + elem = this; + while (elem && elem.nodeType === 1 && elem !== relativeRoot) { + idx = $(elem.parentNode).children(elem.tagName).index(elem) + 1; + idx = "[" + idx + "]"; + path = "/" + elem.tagName.toLowerCase() + idx + path; + elem = elem.parentNode; + } + return path; + }); + return jq.get(); + }; + + $.escape = function(html) { + return html.replace(/&(?!\w+;)/g, '&').replace(//g, '>').replace(/"/g, '"'); + }; + + $.fn.escape = function(html) { + if (arguments.length) return this.html($.escape(html)); + return this.html(); + }; + + $.fn.reverse = []._reverse || [].reverse; + + functions = ["log", "debug", "info", "warn", "exception", "assert", "dir", "dirxml", "trace", "group", "groupEnd", "groupCollapsed", "time", "timeEnd", "profile", "profileEnd", "count", "clear", "table", "error", "notifyFirebug", "firebug", "userObjects"]; + + if (typeof console !== "undefined" && console !== null) { + if (!(console.group != null)) { + console.group = function(name) { + return console.log("GROUP: ", name); + }; + } + if (!(console.groupCollapsed != null)) console.groupCollapsed = console.group; + for (_i = 0, _len = functions.length; _i < _len; _i++) { + fn = functions[_i]; + if (!(console[fn] != null)) { + console[fn] = function() { + return console.log(_t("Not implemented:") + (" console." + name)); + }; + } + } + } else { + this.console = {}; + for (_j = 0, _len2 = functions.length; _j < _len2; _j++) { + fn = functions[_j]; + this.console[fn] = function() {}; + } + this.console['error'] = function() { + var args; + args = 1 <= arguments.length ? __slice.call(arguments, 0) : []; + return alert("ERROR: " + (args.join(', '))); + }; + this.console['warn'] = function() { + var args; + args = 1 <= arguments.length ? __slice.call(arguments, 0) : []; + return alert("WARNING: " + (args.join(', '))); + }; + } + + Delegator = (function() { + + Delegator.prototype.events = {}; + + Delegator.prototype.options = {}; + + Delegator.prototype.element = null; + + function Delegator(element, options) { + this.options = $.extend(true, {}, this.options, options); + this.element = $(element); + this.on = this.subscribe; + this.addEvents(); + } + + Delegator.prototype.addEvents = function() { + var event, functionName, sel, selector, _k, _ref2, _ref3, _results; + _ref2 = this.events; + _results = []; + for (sel in _ref2) { + functionName = _ref2[sel]; + _ref3 = sel.split(' '), selector = 2 <= _ref3.length ? __slice.call(_ref3, 0, _k = _ref3.length - 1) : (_k = 0, []), event = _ref3[_k++]; + _results.push(this.addEvent(selector.join(' '), event, functionName)); + } + return _results; + }; + + Delegator.prototype.addEvent = function(bindTo, event, functionName) { + var closure, isBlankSelector, + _this = this; + closure = function() { + return _this[functionName].apply(_this, arguments); + }; + isBlankSelector = typeof bindTo === 'string' && bindTo.replace(/\s+/g, '') === ''; + if (isBlankSelector) bindTo = this.element; + if (typeof bindTo === 'string') { + this.element.delegate(bindTo, event, closure); + } else { + if (this.isCustomEvent(event)) { + this.subscribe(event, closure); + } else { + $(bindTo).bind(event, closure); + } + } + return this; + }; + + Delegator.prototype.isCustomEvent = function(event) { + event = event.split('.')[0]; + return $.inArray(event, Delegator.natives) === -1; + }; + + Delegator.prototype.publish = function() { + this.element.triggerHandler.apply(this.element, arguments); + return this; + }; + + Delegator.prototype.subscribe = function(event, callback) { + var closure; + closure = function() { + return callback.apply(this, [].slice.call(arguments, 1)); + }; + closure.guid = callback.guid = ($.guid += 1); + this.element.bind(event, closure); + return this; + }; + + Delegator.prototype.unsubscribe = function() { + this.element.unbind.apply(this.element, arguments); + return this; + }; + + return Delegator; + + })(); + + Delegator.natives = (function() { + var key, specials, val; + specials = (function() { + var _ref2, _results; + _ref2 = jQuery.event.special; + _results = []; + for (key in _ref2) { + if (!__hasProp.call(_ref2, key)) continue; + val = _ref2[key]; + _results.push(key); + } + return _results; + })(); + return "blur focus focusin focusout load resize scroll unload click dblclick\nmousedown mouseup mousemove mouseover mouseout mouseenter mouseleave\nchange select submit keydown keypress keyup error".split(/[^a-z]+/).concat(specials); + })(); + + Range = {}; + + Range.sniff = function(r) { + if (r.commonAncestorContainer != null) { + return new Range.BrowserRange(r); + } else if (typeof r.start === "string") { + return new Range.SerializedRange(r); + } else if (r.start && typeof r.start === "object") { + return new Range.NormalizedRange(r); + } else { + console.error(_t("Could not sniff range type")); + return false; + } + }; + + Range.nodeFromXPath = function(xpath, root) { + var customResolver, evaluateXPath, namespace, node, segment; + if (root == null) root = document; + evaluateXPath = function(xp, nsResolver) { + if (nsResolver == null) nsResolver = null; + return document.evaluate('.' + xp, root, nsResolver, XPathResult.FIRST_ORDERED_NODE_TYPE, null).singleNodeValue; + }; + if (!$.isXMLDoc(document.documentElement)) { + return evaluateXPath(xpath); + } else { + customResolver = document.createNSResolver(document.ownerDocument === null ? document.documentElement : document.ownerDocument.documentElement); + node = evaluateXPath(xpath, customResolver); + if (!node) { + xpath = ((function() { + var _k, _len3, _ref2, _results; + _ref2 = xpath.split('/'); + _results = []; + for (_k = 0, _len3 = _ref2.length; _k < _len3; _k++) { + segment = _ref2[_k]; + if (segment && segment.indexOf(':') === -1) { + _results.push(segment.replace(/^([a-z]+)/, 'xhtml:$1')); + } else { + _results.push(segment); + } + } + return _results; + })()).join('/'); + namespace = document.lookupNamespaceURI(null); + customResolver = function(ns) { + if (ns === 'xhtml') { + return namespace; + } else { + return document.documentElement.getAttribute('xmlns:' + ns); + } + }; + node = evaluateXPath(xpath, customResolver); + } + return node; + } + }; + + Range.RangeError = (function(_super) { + + __extends(RangeError, _super); + + function RangeError(type, message, parent) { + this.type = type; + this.message = message; + this.parent = parent != null ? parent : null; + RangeError.__super__.constructor.call(this, this.message); + } + + return RangeError; + + })(Error); + + Range.BrowserRange = (function() { + + function BrowserRange(obj) { + this.commonAncestorContainer = obj.commonAncestorContainer; + this.startContainer = obj.startContainer; + this.startOffset = obj.startOffset; + this.endContainer = obj.endContainer; + this.endOffset = obj.endOffset; + } + + BrowserRange.prototype.normalize = function(root) { + var it, node, nr, offset, p, r, _k, _len3, _ref2; + if (this.tainted) { + console.error(_t("You may only call normalize() once on a BrowserRange!")); + return false; + } else { + this.tainted = true; + } + r = {}; + nr = {}; + _ref2 = ['start', 'end']; + for (_k = 0, _len3 = _ref2.length; _k < _len3; _k++) { + p = _ref2[_k]; + node = this[p + 'Container']; + offset = this[p + 'Offset']; + if (node.nodeType === 1) { + it = node.childNodes[offset]; + node = it || node.childNodes[offset - 1]; + if (node.nodeType === 1 && !node.firstChild) { + it = null; + node = node.previousSibling; + } + while (node.nodeType !== 3) { + node = node.firstChild; + } + offset = it ? 0 : node.nodeValue.length; + } + r[p] = node; + r[p + 'Offset'] = offset; + } + nr.start = r.startOffset > 0 ? r.start.splitText(r.startOffset) : r.start; + if (r.start === r.end) { + if ((r.endOffset - r.startOffset) < nr.start.nodeValue.length) { + nr.start.splitText(r.endOffset - r.startOffset); + } + nr.end = nr.start; + } else { + if (r.endOffset < r.end.nodeValue.length) r.end.splitText(r.endOffset); + nr.end = r.end; + } + nr.commonAncestor = this.commonAncestorContainer; + while (nr.commonAncestor.nodeType !== 1) { + nr.commonAncestor = nr.commonAncestor.parentNode; + } + return new Range.NormalizedRange(nr); + }; + + BrowserRange.prototype.serialize = function(root, ignoreSelector) { + return this.normalize(root).serialize(root, ignoreSelector); + }; + + return BrowserRange; + + })(); + + Range.NormalizedRange = (function() { + + function NormalizedRange(obj) { + this.commonAncestor = obj.commonAncestor; + this.start = obj.start; + this.end = obj.end; + } + + NormalizedRange.prototype.normalize = function(root) { + return this; + }; + + NormalizedRange.prototype.limit = function(bounds) { + var nodes, parent, startParents, _k, _len3, _ref2; + nodes = $.grep(this.textNodes(), function(node) { + return node.parentNode === bounds || $.contains(bounds, node.parentNode); + }); + if (!nodes.length) return null; + this.start = nodes[0]; + this.end = nodes[nodes.length - 1]; + startParents = $(this.start).parents(); + _ref2 = $(this.end).parents(); + for (_k = 0, _len3 = _ref2.length; _k < _len3; _k++) { + parent = _ref2[_k]; + if (startParents.index(parent) !== -1) { + this.commonAncestor = parent; + break; + } + } + return this; + }; + + NormalizedRange.prototype.serialize = function(root, ignoreSelector) { + var end, serialization, start; + serialization = function(node, isEnd) { + var n, nodes, offset, origParent, textNodes, xpath, _k, _len3; + if (ignoreSelector) { + origParent = $(node).parents(":not(" + ignoreSelector + ")").eq(0); + } else { + origParent = $(node).parent(); + } + xpath = origParent.xpath(root)[0]; + textNodes = origParent.textNodes(); + nodes = textNodes.slice(0, textNodes.index(node)); + offset = 0; + for (_k = 0, _len3 = nodes.length; _k < _len3; _k++) { + n = nodes[_k]; + offset += n.nodeValue.length; + } + if (isEnd) { + return [xpath, offset + node.nodeValue.length]; + } else { + return [xpath, offset]; + } + }; + start = serialization(this.start); + end = serialization(this.end, true); + return new Range.SerializedRange({ + start: start[0], + end: end[0], + startOffset: start[1], + endOffset: end[1] + }); + }; + + NormalizedRange.prototype.text = function() { + var node; + return ((function() { + var _k, _len3, _ref2, _results; + _ref2 = this.textNodes(); + _results = []; + for (_k = 0, _len3 = _ref2.length; _k < _len3; _k++) { + node = _ref2[_k]; + _results.push(node.nodeValue); + } + return _results; + }).call(this)).join(''); + }; + + NormalizedRange.prototype.textNodes = function() { + var end, start, textNodes, _ref2; + textNodes = $(this.commonAncestor).textNodes(); + _ref2 = [textNodes.index(this.start), textNodes.index(this.end)], start = _ref2[0], end = _ref2[1]; + return $.makeArray(textNodes.slice(start, end + 1 || 9e9)); + }; + + NormalizedRange.prototype.toRange = function() { + var range; + range = document.createRange(); + range.setStartBefore(this.start); + range.setEndAfter(this.end); + return range; + }; + + return NormalizedRange; + + })(); + + Range.SerializedRange = (function() { + + function SerializedRange(obj) { + this.start = obj.start; + this.startOffset = obj.startOffset; + this.end = obj.end; + this.endOffset = obj.endOffset; + } + + SerializedRange.prototype.normalize = function(root) { + var contains, length, node, p, range, tn, _k, _l, _len3, _len4, _ref2, _ref3; + range = {}; + _ref2 = ['start', 'end']; + for (_k = 0, _len3 = _ref2.length; _k < _len3; _k++) { + p = _ref2[_k]; + try { + node = Range.nodeFromXPath(this[p], root); + } catch (e) { + throw new Range.RangeError(p, ("Error while finding " + p + " node: " + this[p] + ": ") + e, e); + } + if (!node) { + throw new Range.RangeError(p, "Couldn't find " + p + " node: " + this[p]); + } + length = 0; + _ref3 = $(node).textNodes(); + for (_l = 0, _len4 = _ref3.length; _l < _len4; _l++) { + tn = _ref3[_l]; + if (length + tn.nodeValue.length >= this[p + 'Offset']) { + range[p + 'Container'] = tn; + range[p + 'Offset'] = this[p + 'Offset'] - length; + break; + } else { + length += tn.nodeValue.length; + } + } + if (!(range[p + 'Offset'] != null)) { + throw new Range.RangeError("" + p + "offset", "Couldn't find offset " + this[p + 'Offset'] + " in element " + this[p]); + } + } + contains = !(document.compareDocumentPosition != null) ? function(a, b) { + return a.contains(b); + } : function(a, b) { + return a.compareDocumentPosition(b) & 16; + }; + $(range.startContainer).parents().each(function() { + if (contains(this, range.endContainer)) { + range.commonAncestorContainer = this; + return false; + } + }); + return new Range.BrowserRange(range).normalize(root); + }; + + SerializedRange.prototype.serialize = function(root, ignoreSelector) { + return this.normalize(root).serialize(root, ignoreSelector); + }; + + SerializedRange.prototype.toObject = function() { + return { + start: this.start, + startOffset: this.startOffset, + end: this.end, + endOffset: this.endOffset + }; + }; + + return SerializedRange; + + })(); + + util = { + uuid: (function() { + var counter; + counter = 0; + return function() { + return counter++; + }; + })(), + getGlobal: function() { + return (function() { + return this; + })(); + }, + maxZIndex: function($elements) { + var all, el; + all = (function() { + var _k, _len3, _results; + _results = []; + for (_k = 0, _len3 = $elements.length; _k < _len3; _k++) { + el = $elements[_k]; + if ($(el).css('position') === 'static') { + _results.push(-1); + } else { + _results.push(parseInt($(el).css('z-index'), 10) || -1); + } + } + return _results; + })(); + return Math.max.apply(Math, all); + }, + mousePosition: function(e, offsetEl) { + var offset; + offset = $(offsetEl).offset(); + return { + top: e.pageY, + left: e.pageX + }; + }, + preventEventDefault: function(event) { + return event != null ? typeof event.preventDefault === "function" ? event.preventDefault() : void 0 : void 0; + } + }; + + _Annotator = this.Annotator; + + Annotator = (function(_super) { + + __extends(Annotator, _super); + + Annotator.prototype.events = { + ".annotator-adder button click": "onAdderClick", + ".annotator-adder button mousedown": "onAdderMousedown", + ".annotator-hl mouseover": "onHighlightMouseover", + ".annotator-hl mouseout": "startViewerHideTimer" + }; + + Annotator.prototype.html = { + adder: '
', + wrapper: '' + }; + + Annotator.prototype.options = { + readOnly: false + }; + + Annotator.prototype.plugins = {}; + + Annotator.prototype.editor = null; + + Annotator.prototype.viewer = null; + + Annotator.prototype.selectedRanges = null; + + Annotator.prototype.mouseIsDown = false; + + Annotator.prototype.ignoreMouseup = false; + + Annotator.prototype.viewerHideTimer = null; + + function Annotator(element, options) { + this.onDeleteAnnotation = __bind(this.onDeleteAnnotation, this); + this.onEditAnnotation = __bind(this.onEditAnnotation, this); + this.onAdderClick = __bind(this.onAdderClick, this); + this.onAdderMousedown = __bind(this.onAdderMousedown, this); + this.onHighlightMouseover = __bind(this.onHighlightMouseover, this); + this.checkForEndSelection = __bind(this.checkForEndSelection, this); + this.checkForStartSelection = __bind(this.checkForStartSelection, this); + this.clearViewerHideTimer = __bind(this.clearViewerHideTimer, this); + this.startViewerHideTimer = __bind(this.startViewerHideTimer, this); + this.showViewer = __bind(this.showViewer, this); + this.onEditorSubmit = __bind(this.onEditorSubmit, this); + this.onEditorHide = __bind(this.onEditorHide, this); + this.showEditor = __bind(this.showEditor, this); Annotator.__super__.constructor.apply(this, arguments); + this.plugins = {}; + if (!Annotator.supported()) return this; + if (!this.options.readOnly) this._setupDocumentEvents(); + this._setupWrapper()._setupViewer()._setupEditor(); + this._setupDynamicStyle(); + this.adder = $(this.html.adder).appendTo(this.wrapper).hide(); + } + + Annotator.prototype._setupWrapper = function() { + this.wrapper = $(this.html.wrapper); + this.element.find('script').remove(); + this.element.wrapInner(this.wrapper); + this.wrapper = this.element.find('.annotator-wrapper'); + return this; + }; + + Annotator.prototype._setupViewer = function() { + var _this = this; + this.viewer = new Annotator.Viewer({ + readOnly: this.options.readOnly + }); + this.viewer.hide().on("edit", this.onEditAnnotation).on("delete", this.onDeleteAnnotation).addField({ + load: function(field, annotation) { + if (annotation.text) { + $(field).escape(annotation.text); + } else { + $(field).html("" + (_t('No Comment')) + ""); + } + return _this.publish('annotationViewerTextField', [field, annotation]); + } + }).element.appendTo(this.wrapper).bind({ + "mouseover": this.clearViewerHideTimer, + "mouseout": this.startViewerHideTimer + }); + return this; + }; + + Annotator.prototype._setupEditor = function() { + this.editor = new Annotator.Editor(); + this.editor.hide().on('hide', this.onEditorHide).on('save', this.onEditorSubmit).addField({ + type: 'textarea', + label: _t('Comments') + '\u2026', + load: function(field, annotation) { + return $(field).find('textarea').val(annotation.text || ''); + }, + submit: function(field, annotation) { + return annotation.text = $(field).find('textarea').val(); + } + }); + this.editor.element.appendTo(this.wrapper); + return this; + }; + + Annotator.prototype._setupDocumentEvents = function() { + $(document).bind({ + "mouseup": this.checkForEndSelection, + "mousedown": this.checkForStartSelection + }); + return this; + }; + + Annotator.prototype._setupDynamicStyle = function() { + var max, sel, style, x; + style = $('#annotator-dynamic-style'); + if (!style.length) { + style = $('').appendTo(document.head); + } + sel = '*' + ((function() { + var _k, _len3, _ref2, _results; + _ref2 = ['adder', 'outer', 'notice', 'filter']; + _results = []; + for (_k = 0, _len3 = _ref2.length; _k < _len3; _k++) { + x = _ref2[_k]; + _results.push(":not(.annotator-" + x + ")"); + } + return _results; + })()).join(''); + max = util.maxZIndex($(document.body).find(sel)); + max = Math.max(max, 1000); + style.text([".annotator-adder, .annotator-outer, .annotator-notice {", " z-index: " + (max + 20) + ";", "}", ".annotator-filter {", " z-index: " + (max + 10) + ";", "}"].join("\n")); + return this; + }; + + Annotator.prototype.getSelectedRanges = function() { + var browserRange, i, normedRange, r, ranges, rangesToIgnore, selection, _k, _len3; + selection = util.getGlobal().getSelection(); + ranges = []; + rangesToIgnore = []; + if (!selection.isCollapsed) { + ranges = (function() { + var _ref2, _results; + _results = []; + for (i = 0, _ref2 = selection.rangeCount; 0 <= _ref2 ? i < _ref2 : i > _ref2; 0 <= _ref2 ? i++ : i--) { + r = selection.getRangeAt(i); + browserRange = new Range.BrowserRange(r); + normedRange = browserRange.normalize().limit(this.wrapper[0]); + if (normedRange === null) rangesToIgnore.push(r); + _results.push(normedRange); + } + return _results; + }).call(this); + selection.removeAllRanges(); + } + for (_k = 0, _len3 = rangesToIgnore.length; _k < _len3; _k++) { + r = rangesToIgnore[_k]; + selection.addRange(r); + } + return $.grep(ranges, function(range) { + if (range) selection.addRange(range.toRange()); + return range; + }); + }; + + Annotator.prototype.createAnnotation = function() { + var annotation; + annotation = {}; + this.publish('beforeAnnotationCreated', [annotation]); + return annotation; + }; + + Annotator.prototype.setupAnnotation = function(annotation) { + var normed, normedRanges, r, root, _k, _l, _len3, _len4, _ref2; + root = this.wrapper[0]; + annotation.ranges || (annotation.ranges = this.selectedRanges); + normedRanges = []; + _ref2 = annotation.ranges; + for (_k = 0, _len3 = _ref2.length; _k < _len3; _k++) { + r = _ref2[_k]; + try { + normedRanges.push(Range.sniff(r).normalize(root)); + } catch (e) { + if (e instanceof Range.RangeError) { + this.publish('rangeNormalizeFail', [annotation, r, e]); + } else { + throw e; + } + } + } + annotation.quote = []; + annotation.ranges = []; + annotation.highlights = []; + for (_l = 0, _len4 = normedRanges.length; _l < _len4; _l++) { + normed = normedRanges[_l]; + annotation.quote.push($.trim(normed.text())); + annotation.ranges.push(normed.serialize(this.wrapper[0], '.annotator-hl')); + $.merge(annotation.highlights, this.highlightRange(normed)); + } + annotation.quote = annotation.quote.join(' / '); + $(annotation.highlights).data('annotation', annotation); + return annotation; + }; + + Annotator.prototype.updateAnnotation = function(annotation) { + this.publish('beforeAnnotationUpdated', [annotation]); + this.publish('annotationUpdated', [annotation]); + return annotation; + }; + + Annotator.prototype.deleteAnnotation = function(annotation) { + var h, _k, _len3, _ref2; + _ref2 = annotation.highlights; + for (_k = 0, _len3 = _ref2.length; _k < _len3; _k++) { + h = _ref2[_k]; + $(h).replaceWith(h.childNodes); + } + this.publish('annotationDeleted', [annotation]); + return annotation; + }; + + Annotator.prototype.loadAnnotations = function(annotations) { + var clone, loader, + _this = this; + if (annotations == null) annotations = []; + loader = function(annList) { + var n, now, _k, _len3; + if (annList == null) annList = []; + now = annList.splice(0, 10); + for (_k = 0, _len3 = now.length; _k < _len3; _k++) { + n = now[_k]; + _this.setupAnnotation(n); + } + if (annList.length > 0) { + return setTimeout((function() { + return loader(annList); + }), 10); + } else { + return _this.publish('annotationsLoaded', [clone]); + } + }; + clone = annotations.slice(); + if (annotations.length) loader(annotations); + return this; + }; + + Annotator.prototype.dumpAnnotations = function() { + if (this.plugins['Store']) { + return this.plugins['Store'].dumpAnnotations(); + } else { + return console.warn(_t("Can't dump annotations without Store plugin.")); + } + }; + + Annotator.prototype.highlightRange = function(normedRange, cssClass) { + var hl, node, white, _k, _len3, _ref2, _results; + if (cssClass == null) cssClass = 'annotator-hl'; + white = /^\s*$/; + hl = $(""); + _ref2 = normedRange.textNodes(); + _results = []; + for (_k = 0, _len3 = _ref2.length; _k < _len3; _k++) { + node = _ref2[_k]; + if (!white.test(node.nodeValue)) { + _results.push($(node).wrapAll(hl).parent().show()[0]); + } + } + return _results; + }; + + Annotator.prototype.highlightRanges = function(normedRanges, cssClass) { + var highlights, r, _k, _len3; + if (cssClass == null) cssClass = 'annotator-hl'; + highlights = []; + for (_k = 0, _len3 = normedRanges.length; _k < _len3; _k++) { + r = normedRanges[_k]; + $.merge(highlights, this.highlightRange(r, cssClass)); + } + return highlights; + }; + + Annotator.prototype.addPlugin = function(name, options) { + var klass, _base; + if (this.plugins[name]) { + console.error(_t("You cannot have more than one instance of any plugin.")); + } else { + klass = Annotator.Plugin[name]; + if (typeof klass === 'function') { + this.plugins[name] = new klass(this.element[0], options); + this.plugins[name].annotator = this; + if (typeof (_base = this.plugins[name]).pluginInit === "function") { + _base.pluginInit(); + } + } else { + console.error(_t("Could not load ") + name + _t(" plugin. Have you included the appropriate