--- /dev/null
+//\r
+// Bridge.js\r
+// FolioReaderKit\r
+//\r
+// Created by Heberti Almeida on 06/05/15.\r
+// Copyright (c) 2015 Folio Reader. All rights reserved.\r
+//\r
+\r
+var thisHighlight;\r
+var audioMarkClass;\r
+var wordsPerMinute = 180;\r
+\r
+document.addEventListener("DOMContentLoaded", function(event) {\r
+// var lnk = document.getElementsByClassName("lnk");\r
+// for (var i=0; i<lnk.length; i++) {\r
+// lnk[i].setAttribute("onclick","return callVerseURL(this);");\r
+// }\r
+});\r
+\r
+// Generate a GUID\r
+function guid() {\r
+ function s4() {\r
+ return Math.floor((1 + Math.random()) * 0x10000).toString(16).substring(1);\r
+ }\r
+ var guid = s4() + s4() + '-' + s4() + '-' + s4() + '-' + s4() + '-' + s4() + s4() + s4();\r
+ return guid.toUpperCase();\r
+}\r
+\r
+// Get All HTML\r
+function getHTML() {\r
+ Highlight.getHtmlAndSaveHighlight(document.documentElement.outerHTML);\r
+ //return document.documentElement.outerHTML;\r
+}\r
+\r
+// Class manipulation\r
+function hasClass(ele,cls) {\r
+ return !!ele.className.match(new RegExp('(\\s|^)'+cls+'(\\s|$)'));\r
+}\r
+\r
+function addClass(ele,cls) {\r
+ if (!hasClass(ele,cls)) ele.className += " "+cls;\r
+}\r
+\r
+function removeClass(ele,cls) {\r
+ if (hasClass(ele,cls)) {\r
+ var reg = new RegExp('(\\s|^)'+cls+'(\\s|$)');\r
+ ele.className=ele.className.replace(reg,' ');\r
+ }\r
+}\r
+\r
+// Font name class\r
+function setFontName(cls) {\r
+ var elm = document.documentElement;\r
+ removeClass(elm, "andada");\r
+ removeClass(elm, "lato");\r
+ removeClass(elm, "lora");\r
+ removeClass(elm, "raleway");\r
+ addClass(elm, cls);\r
+}\r
+\r
+// Toggle night mode\r
+function nightMode(enable) {\r
+ var elm = document.documentElement;\r
+ if(enable) {\r
+ addClass(elm, "nightMode");\r
+ } else {\r
+ removeClass(elm, "nightMode");\r
+ }\r
+}\r
+\r
+// Set font size\r
+function setFontSize(cls) {\r
+ var elm = document.documentElement;\r
+ removeClass(elm, "textSizeOne");\r
+ removeClass(elm, "textSizeTwo");\r
+ removeClass(elm, "textSizeThree");\r
+ removeClass(elm, "textSizeFour");\r
+ removeClass(elm, "textSizeFive");\r
+ addClass(elm, cls);\r
+}\r
+\r
+\r
+// Menu colors\r
+function setHighlightStyle(style) {\r
+ Highlight.getUpdatedHighlightId(thisHighlight.id, style);\r
+}\r
+\r
+function removeThisHighlight() {\r
+ return thisHighlight.id;\r
+}\r
+\r
+function removeHighlightById(elmId) {\r
+ var elm = document.getElementById(elmId);\r
+ elm.outerHTML = elm.innerHTML;\r
+ return elm.id;\r
+}\r
+\r
+function getHighlightContent() {\r
+ return thisHighlight.textContent\r
+}\r
+\r
+function getBodyText() {\r
+ return document.body.innerText;\r
+}\r
+\r
+// Method that returns only selected text plain\r
+var getSelectedText = function() {\r
+ return window.getSelection().toString();\r
+}\r
+\r
+// Method that gets the Rect of current selected text\r
+// and returns in a JSON format\r
+var getRectForSelectedText = function(elm) {\r
+ if (typeof elm === "undefined") elm = window.getSelection().getRangeAt(0);\r
+\r
+ var rect = elm.getBoundingClientRect();\r
+ return "{{" + rect.left + "," + rect.top + "}, {" + rect.width + "," + rect.height + "}}";\r
+}\r
+\r
+// Method that call that a hightlight was clicked\r
+// with URL scheme and rect informations\r
+var callHighlightURL = function(elm) {\r
+ event.stopPropagation();\r
+ var URLBase = "highlight://";\r
+ var currentHighlightRect = getRectForSelectedText(elm);\r
+ thisHighlight = elm;\r
+\r
+ window.location = URLBase + encodeURIComponent(currentHighlightRect);\r
+}\r
+\r
+// Reading time\r
+function getReadingTime() {\r
+ var text = document.body.innerText;\r
+ var totalWords = text.trim().split(/\s+/g).length;\r
+ var wordsPerSecond = wordsPerMinute / 60; //define words per second based on words per minute\r
+ var totalReadingTimeSeconds = totalWords / wordsPerSecond; //define total reading time in seconds\r
+ var readingTimeMinutes = Math.round(totalReadingTimeSeconds / 60);\r
+\r
+ return readingTimeMinutes;\r
+}\r
+\r
+/**\r
+ Get Vertical or Horizontal paged #anchor offset\r
+ */\r
+var getAnchorOffset = function(target, horizontal) {\r
+ var elem = document.getElementById(target);\r
+\r
+ if (!elem) {\r
+ elem = document.getElementsByName(target)[0];\r
+ }\r
+\r
+ if (horizontal) {\r
+ return document.body.clientWidth * Math.floor(elem.offsetTop / window.innerHeight);\r
+ }\r
+\r
+ return elem.offsetTop;\r
+}\r
+\r
+function scrollAnchor(id) {\r
+ window.location.hash = id;\r
+}\r
+\r
+function findElementWithID(node) {\r
+ if( !node || node.tagName == "BODY")\r
+ return null\r
+ else if( node.id )\r
+ return node\r
+ else\r
+ return findElementWithID(node)\r
+}\r
+\r
+function findElementWithIDInView() {\r
+\r
+ if(audioMarkClass) {\r
+ // attempt to find an existing "audio mark"\r
+ var el = document.querySelector("."+audioMarkClass)\r
+\r
+ // if that existing audio mark exists and is in view, use it\r
+ if( el && el.offsetTop > document.body.scrollTop && el.offsetTop < (window.innerHeight + document.body.scrollTop))\r
+ return el\r
+ }\r
+\r
+ // @NOTE: is `span` too limiting?\r
+ var els = document.querySelectorAll("span[id]")\r
+\r
+ for(indx in els) {\r
+ var element = els[indx];\r
+\r
+ // Horizontal scroll\r
+ if (document.body.scrollTop == 0) {\r
+ var elLeft = document.body.clientWidth * Math.floor(element.offsetTop / window.innerHeight);\r
+ // document.body.scrollLeft = elLeft;\r
+\r
+ if (elLeft == document.body.scrollLeft) {\r
+ return element;\r
+ }\r
+\r
+ // Vertical\r
+ } else if(element.offsetTop > document.body.scrollTop) {\r
+ return element;\r
+ }\r
+ }\r
+\r
+ return null\r
+}\r
+\r
+\r
+/**\r
+ Play Audio - called by native UIMenuController when a user selects a bit of text and presses "play"\r
+ */\r
+function playAudio() {\r
+ var sel = getSelection();\r
+ var node = null;\r
+\r
+ // user selected text? start playing from the selected node\r
+ if (sel.toString() != "") {\r
+ node = sel.anchorNode ? findElementWithID(sel.anchorNode.parentNode) : null;\r
+\r
+ // find the first ID'd element that is within view (it will\r
+ } else {\r
+ node = findElementWithIDInView()\r
+ }\r
+\r
+ playAudioFragmentID(node ? node.id : null)\r
+}\r
+\r
+\r
+/**\r
+ Play Audio Fragment ID - tells page controller to begin playing audio from the following ID\r
+ */\r
+function playAudioFragmentID(fragmentID) {\r
+ var URLBase = "play-audio://";\r
+ window.location = URLBase + (fragmentID?encodeURIComponent(fragmentID):"")\r
+}\r
+\r
+/**\r
+ Go To Element - scrolls the webview to the requested element\r
+ */\r
+function goToEl(el) {\r
+ var top = document.body.scrollTop;\r
+ var elTop = el.offsetTop - 20;\r
+ var bottom = window.innerHeight + document.body.scrollTop;\r
+ var elBottom = el.offsetHeight + el.offsetTop + 60\r
+\r
+ if(elBottom > bottom || elTop < top) {\r
+ document.body.scrollTop = el.offsetTop - 20\r
+ }\r
+\r
+ /* Set scroll left in case horz scroll is activated.\r
+\r
+ The following works because el.offsetTop accounts for each page turned\r
+ as if the document was scrolling vertical. We then divide by the window\r
+ height to figure out what page the element should appear on and set scroll left\r
+ to scroll to that page.\r
+ */\r
+ if( document.body.scrollTop == 0 ){\r
+ var elLeft = document.body.clientWidth * Math.floor(el.offsetTop / window.innerHeight);\r
+ document.body.scrollLeft = elLeft;\r
+ }\r
+\r
+ return el;\r
+}\r
+\r
+/**\r
+ Remove All Classes - removes the given class from all elements in the DOM\r
+ */\r
+function removeAllClasses(className) {\r
+ var els = document.body.getElementsByClassName(className)\r
+ if( els.length > 0 )\r
+ for( i = 0; i <= els.length; i++) {\r
+ els[i].classList.remove(className);\r
+ }\r
+}\r
+\r
+/**\r
+ Audio Mark ID - marks an element with an ID with the given class and scrolls to it\r
+ */\r
+function audioMarkID(className, id) {\r
+ if (audioMarkClass)\r
+ removeAllClasses(audioMarkClass);\r
+\r
+ audioMarkClass = className\r
+ var el = document.getElementById(id);\r
+\r
+ goToEl(el);\r
+ el.classList.add(className)\r
+}\r
+\r
+function setMediaOverlayStyle(style){\r
+ document.documentElement.classList.remove("mediaOverlayStyle0", "mediaOverlayStyle1", "mediaOverlayStyle2")\r
+ document.documentElement.classList.add(style)\r
+}\r
+\r
+function setMediaOverlayStyleColors(color, colorHighlight) {\r
+ var stylesheet = document.styleSheets[document.styleSheets.length-1];\r
+ stylesheet.insertRule(".mediaOverlayStyle0 span.epub-media-overlay-playing { background: "+colorHighlight+" !important }")\r
+ stylesheet.insertRule(".mediaOverlayStyle1 span.epub-media-overlay-playing { border-color: "+color+" !important }")\r
+ stylesheet.insertRule(".mediaOverlayStyle2 span.epub-media-overlay-playing { color: "+color+" !important }")\r
+}\r
+\r
+var currentIndex = -1;\r
+\r
+\r
+function findSentenceWithIDInView(els) {\r
+ // @NOTE: is `span` too limiting?\r
+ for(indx in els) {\r
+ var element = els[indx];\r
+\r
+ // Horizontal scroll\r
+ if (document.body.scrollTop == 0) {\r
+ var elLeft = document.body.clientWidth * Math.floor(element.offsetTop / window.innerHeight);\r
+ // document.body.scrollLeft = elLeft;\r
+\r
+ if (elLeft == document.body.scrollLeft) {\r
+ currentIndex = indx;\r
+ return element;\r
+ }\r
+\r
+ // Vertical\r
+ } else if(element.offsetTop > document.body.scrollTop) {\r
+ currentIndex = indx;\r
+ return element;\r
+ }\r
+ }\r
+\r
+ return null\r
+}\r
+\r
+function findNextSentenceInArray(els) {\r
+ if(currentIndex >= 0) {\r
+ currentIndex ++;\r
+ return els[currentIndex];\r
+ }\r
+\r
+ return null\r
+}\r
+\r
+function resetCurrentSentenceIndex() {\r
+ currentIndex = -1;\r
+}\r
+\r
+function rewindCurrentIndex() {\r
+ currentIndex = currentIndex-1;\r
+}\r
+\r
+function getSentenceWithIndex(className) {\r
+ var sentence;\r
+ var sel = getSelection();\r
+ var node = null;\r
+ var elements = document.querySelectorAll("span.sentence");\r
+\r
+ // Check for a selected text, if found start reading from it\r
+ if (sel.toString() != "") {\r
+ console.log(sel.anchorNode.parentNode);\r
+ node = sel.anchorNode.parentNode;\r
+\r
+ if (node.className == "sentence") {\r
+ sentence = node\r
+\r
+ for(var i = 0, len = elements.length; i < len; i++) {\r
+ if (elements[i] === sentence) {\r
+ currentIndex = i;\r
+ break;\r
+ }\r
+ }\r
+ } else {\r
+ sentence = findSentenceWithIDInView(elements);\r
+ }\r
+ } else if (currentIndex < 0) {\r
+ sentence = findSentenceWithIDInView(elements);\r
+ } else {\r
+ sentence = findNextSentenceInArray(elements);\r
+ }\r
+\r
+ var text = sentence.innerText || sentence.textContent;\r
+\r
+ goToEl(sentence);\r
+\r
+ if (audioMarkClass){\r
+ removeAllClasses(audioMarkClass);\r
+ }\r
+\r
+ audioMarkClass = className;\r
+ sentence.classList.add(className)\r
+ return text;\r
+}\r
+\r
+function wrappingSentencesWithinPTags(){\r
+ currentIndex = -1;\r
+ "use strict";\r
+\r
+ var rxOpen = new RegExp("<[^\\/].+?>"),\r
+ rxClose = new RegExp("<\\/.+?>"),\r
+ rxSupStart = new RegExp("^<sup\\b[^>]*>"),\r
+ rxSupEnd = new RegExp("<\/sup>"),\r
+ sentenceEnd = [],\r
+ rxIndex;\r
+\r
+ sentenceEnd.push(new RegExp("[^\\d][\\.!\\?]+"));\r
+ sentenceEnd.push(new RegExp("(?=([^\\\"]*\\\"[^\\\"]*\\\")*[^\\\"]*?$)"));\r
+ sentenceEnd.push(new RegExp("(?![^\\(]*?\\))"));\r
+ sentenceEnd.push(new RegExp("(?![^\\[]*?\\])"));\r
+ sentenceEnd.push(new RegExp("(?![^\\{]*?\\})"));\r
+ sentenceEnd.push(new RegExp("(?![^\\|]*?\\|)"));\r
+ sentenceEnd.push(new RegExp("(?![^\\\\]*?\\\\)"));\r
+ //sentenceEnd.push(new RegExp("(?![^\\/.]*\\/)")); // all could be a problem, but this one is problematic\r
+\r
+ rxIndex = new RegExp(sentenceEnd.reduce(function (previousValue, currentValue) {\r
+ return previousValue + currentValue.source;\r
+ }, ""));\r
+\r
+ function indexSentenceEnd(html) {\r
+ var index = html.search(rxIndex);\r
+\r
+ if (index !== -1) {\r
+ index += html.match(rxIndex)[0].length - 1;\r
+ }\r
+\r
+ return index;\r
+ }\r
+\r
+ function pushSpan(array, className, string, classNameOpt) {\r
+ if (!string.match('[a-zA-Z0-9]+')) {\r
+ array.push(string);\r
+ } else {\r
+ array.push('<span class="' + className + '">' + string + '</span>');\r
+ }\r
+ }\r
+\r
+ function addSupToPrevious(html, array) {\r
+ var sup = html.search(rxSupStart),\r
+ end = 0,\r
+ last;\r
+\r
+ if (sup !== -1) {\r
+ end = html.search(rxSupEnd);\r
+ if (end !== -1) {\r
+ last = array.pop();\r
+ end = end + 6;\r
+ array.push(last.slice(0, -7) + html.slice(0, end) + last.slice(-7));\r
+ }\r
+ }\r
+\r
+ return html.slice(end);\r
+ }\r
+\r
+ function paragraphIsSentence(html, array) {\r
+ var index = indexSentenceEnd(html);\r
+\r
+ if (index === -1 || index === html.length) {\r
+ pushSpan(array, "sentence", html, "paragraphIsSentence");\r
+ html = "";\r
+ }\r
+\r
+ return html;\r
+ }\r
+\r
+ function paragraphNoMarkup(html, array) {\r
+ var open = html.search(rxOpen),\r
+ index = 0;\r
+\r
+ if (open === -1) {\r
+ index = indexSentenceEnd(html);\r
+ if (index === -1) {\r
+ index = html.length;\r
+ }\r
+\r
+ pushSpan(array, "sentence", html.slice(0, index += 1), "paragraphNoMarkup");\r
+ }\r
+\r
+ return html.slice(index);\r
+ }\r
+\r
+ function sentenceUncontained(html, array) {\r
+ var open = html.search(rxOpen),\r
+ index = 0,\r
+ close;\r
+\r
+ if (open !== -1) {\r
+ index = indexSentenceEnd(html);\r
+ if (index === -1) {\r
+ index = html.length;\r
+ }\r
+\r
+ close = html.search(rxClose);\r
+ if (index < open || index > close) {\r
+ pushSpan(array, "sentence", html.slice(0, index += 1), "sentenceUncontained");\r
+ } else {\r
+ index = 0;\r
+ }\r
+ }\r
+\r
+ return html.slice(index);\r
+ }\r
+\r
+ function sentenceContained(html, array) {\r
+ var open = html.search(rxOpen),\r
+ index = 0,\r
+ close,\r
+ count;\r
+\r
+ if (open !== -1) {\r
+ index = indexSentenceEnd(html);\r
+ if (index === -1) {\r
+ index = html.length;\r
+ }\r
+\r
+ close = html.search(rxClose);\r
+ if (index > open && index < close) {\r
+ count = html.match(rxClose)[0].length;\r
+ pushSpan(array, "sentence", html.slice(0, close + count), "sentenceContained");\r
+ index = close + count;\r
+ } else {\r
+ index = 0;\r
+ }\r
+ }\r
+\r
+ return html.slice(index);\r
+ }\r
+\r
+ function anythingElse(html, array) {\r
+ pushSpan(array, "sentence", html, "anythingElse");\r
+\r
+ return "";\r
+ }\r
+\r
+ function guessSenetences() {\r
+ var paragraphs = document.getElementsByTagName("p");\r
+\r
+ Array.prototype.forEach.call(paragraphs, function (paragraph) {\r
+ var html = paragraph.innerHTML,\r
+ length = html.length,\r
+ array = [],\r
+ safety = 100;\r
+\r
+ while (length && safety) {\r
+ html = addSupToPrevious(html, array);\r
+ if (html.length === length) {\r
+ if (html.length === length) {\r
+ html = paragraphIsSentence(html, array);\r
+ if (html.length === length) {\r
+ html = paragraphNoMarkup(html, array);\r
+ if (html.length === length) {\r
+ html = sentenceUncontained(html, array);\r
+ if (html.length === length) {\r
+ html = sentenceContained(html, array);\r
+ if (html.length === length) {\r
+ html = anythingElse(html, array);\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+ }\r
+\r
+ length = html.length;\r
+ safety -= 1;\r
+ }\r
+\r
+ paragraph.innerHTML = array.join("");\r
+ });\r
+ }\r
+\r
+ guessSenetences();\r
+}\r
+\r
+// Class based onClick listener\r
+\r
+function addClassBasedOnClickListener(schemeName, querySelector, attributeName, selectAll) {\r
+ if (selectAll) {\r
+ // Get all elements with the given query selector\r
+ var elements = document.querySelectorAll(querySelector);\r
+ for (elementIndex = 0; elementIndex < elements.length; elementIndex++) {\r
+ var element = elements[elementIndex];\r
+ addClassBasedOnClickListenerToElement(element, schemeName, attributeName);\r
+ }\r
+ } else {\r
+ // Get the first element with the given query selector\r
+ var element = document.querySelector(querySelector);\r
+ addClassBasedOnClickListenerToElement(element, schemeName, attributeName);\r
+ }\r
+}\r
+\r
+function addClassBasedOnClickListenerToElement(element, schemeName, attributeName) {\r
+ // Get the content from the given attribute name\r
+ var attributeContent = element.getAttribute(attributeName);\r
+ // Add the on click logic\r
+ element.setAttribute("onclick", "onClassBasedListenerClick(\"" + schemeName + "\", \"" + encodeURIComponent(attributeContent) + "\");");\r
+}\r
+\r
+var onClassBasedListenerClick = function(schemeName, attributeContent) {\r
+ // Prevent the browser from performing the default on click behavior\r
+ event.preventDefault();\r
+ // Don't pass the click event to other elemtents\r
+ event.stopPropagation();\r
+ // Create parameters containing the click position inside the web view.\r
+ var positionParameterString = "/clientX=" + event.clientX + "&clientY=" + event.clientY;\r
+ // Set the custom link URL to the event\r
+ window.location = schemeName + "://" + attributeContent + positionParameterString;\r
+}\r
+\r
+function getHighlightString(style) {\r
+ var range = window.getSelection().getRangeAt(0);\r
+ var selectionContents = range.extractContents();\r
+ var elm = document.createElement("highlight");\r
+ var id = guid();\r
+\r
+ elm.appendChild(selectionContents);\r
+ elm.setAttribute("id", id);\r
+ elm.setAttribute("onclick","callHighlightURL(this);");\r
+ elm.setAttribute("class", style);\r
+\r
+ range.insertNode(elm);\r
+ thisHighlight = elm;\r
+\r
+ var params = [];\r
+ params.push({id: id, rect: getRectForSelectedText(elm)});\r
+ Highlight.getHighlightJson(JSON.stringify(params));\r
+}\r
+\r
+function gotoHighlight(highlightId){\r
+ var element = document.getElementById(highlightId.toString());\r
+ if(element != null) {\r
+ goToEl(element);\r
+ }\r
+}\r
+\r
+$(function(){\r
+ window.ssReader = Class({\r
+ $singleton: true,\r
+\r
+ init: function() {\r
+ rangy.init();\r
+\r
+ this.highlighter = rangy.createHighlighter();\r
+\r
+ this.highlighter.addClassApplier(rangy.createClassApplier("highlight_yellow", {\r
+ ignoreWhiteSpace: true,\r
+ tagNames: ["span", "a"]\r
+ }));\r
+\r
+ this.highlighter.addClassApplier(rangy.createClassApplier("highlight_green", {\r
+ ignoreWhiteSpace: true,\r
+ tagNames: ["span", "a"]\r
+ }));\r
+\r
+ this.highlighter.addClassApplier(rangy.createClassApplier("highlight_blue", {\r
+ ignoreWhiteSpace: true,\r
+ tagNames: ["span", "a"]\r
+ }));\r
+\r
+ this.highlighter.addClassApplier(rangy.createClassApplier("highlight_pink", {\r
+ ignoreWhiteSpace: true,\r
+ tagNames: ["span", "a"]\r
+ }));\r
+\r
+ this.highlighter.addClassApplier(rangy.createClassApplier("highlight_underline", {\r
+ ignoreWhiteSpace: true,\r
+ tagNames: ["span", "a"]\r
+ }));\r
+\r
+ },\r
+\r
+ setFontAndada: function(){\r
+ this.setFont("andada");\r
+ },\r
+\r
+ setFontLato: function(){\r
+ this.setFont("lato");\r
+ },\r
+\r
+ setFontPtSerif: function(){\r
+ this.setFont("pt-serif");\r
+ },\r
+\r
+ setFontPtSans: function(){\r
+ this.setFont("pt-sans");\r
+ },\r
+\r
+ base64encode: function(str){\r
+ return btoa(unescape(encodeURIComponent(str)));\r
+ },\r
+\r
+ base64decode: function(str){\r
+ return decodeURIComponent(escape(atob(str)));\r
+ },\r
+\r
+ clearSelection: function(){\r
+ if (window.getSelection) {\r
+ if (window.getSelection().empty) { // Chrome\r
+ window.getSelection().empty();\r
+ } else if (window.getSelection().removeAllRanges) { // Firefox\r
+ window.getSelection().removeAllRanges();\r
+ }\r
+ } else if (document.selection) { // IE?\r
+ document.selection.empty();\r
+ }\r
+ },\r
+\r
+ // Public methods\r
+\r
+ setFont: function(fontName){\r
+ $("#ss-wrapper-font").removeClass().addClass("ss-wrapper-"+fontName);\r
+ },\r
+\r
+ setSize: function(size){\r
+ $("#ss-wrapper-size").removeClass().addClass("ss-wrapper-"+size);\r
+ },\r
+\r
+ setTheme: function(theme){\r
+ $("body, #ss-wrapper-theme").removeClass().addClass("ss-wrapper-"+theme);\r
+ },\r
+\r
+ setComment: function(comment, inputId){\r
+ $("#"+inputId).val(ssReader.base64decode(comment));\r
+ $("#"+inputId).trigger("input", ["true"]);\r
+ },\r
+\r
+ highlightSelection: function(color){\r
+ try {\r
+\r
+ this.highlighter.highlightSelection("highlight_" + color, null);\r
+ var range = window.getSelection().toString();\r
+ var params = {content: range,rangy: this.getHighlights(),color: color};\r
+ this.clearSelection();\r
+ Highlight.onReceiveHighlights(JSON.stringify(params));\r
+ } catch(err){\r
+ console.log("highlightSelection : " + err);\r
+ }\r
+ },\r
+\r
+ unHighlightSelection: function(){\r
+ try {\r
+ this.highlighter.unhighlightSelection();\r
+ Highlight.onReceiveHighlights(this.getHighlights());\r
+ } catch(err){}\r
+ },\r
+\r
+ getHighlights: function(){\r
+ try {\r
+ return this.highlighter.serialize();\r
+ } catch(err){}\r
+ },\r
+\r
+ setHighlights: function(serializedHighlight){\r
+ try {\r
+ this.highlighter.removeAllHighlights();\r
+ this.highlighter.deserialize(serializedHighlight);\r
+ } catch(err){}\r
+ },\r
+\r
+ removeAll: function(){\r
+ try {\r
+ this.highlighter.removeAllHighlights();\r
+ } catch(err){}\r
+ },\r
+\r
+ copy: function(){\r
+ SSBridge.onCopy(window.getSelection().toString());\r
+ this.clearSelection();\r
+ },\r
+\r
+ share: function(){\r
+ SSBridge.onShare(window.getSelection().toString());\r
+ this.clearSelection();\r
+ },\r
+\r
+ search: function(){\r
+ SSBridge.onSearch(window.getSelection().toString());\r
+ this.clearSelection();\r
+ }\r
+ });\r
+\r
+ if(typeof ssReader !== "undefined"){\r
+ ssReader.init();\r
+ }\r
+\r
+ $(".verse").click(function(){\r
+ SSBridge.onVerseClick(ssReader.base64encode($(this).attr("verse")));\r
+ });\r
+\r
+ $("code").each(function(i){\r
+ var textarea = $("<textarea class='textarea'/>").attr("id", "input-"+i).on("input propertychange", function(event, isInit) {\r
+ $(this).css({'height': 'auto', 'overflow-y': 'hidden'}).height(this.scrollHeight);\r
+ $(this).next().css({'height': 'auto', 'overflow-y': 'hidden'}).height(this.scrollHeight);\r
+\r
+ if (!isInit) {\r
+ var that = this;\r
+ if (timeout !== null) {\r
+ clearTimeout(timeout);\r
+ }\r
+ timeout = setTimeout(function () {\r
+ SSBridge.onCommentsClick(\r
+ ssReader.base64encode($(that).val()),\r
+ $(that).attr("id")\r
+ );\r
+ }, 1000);\r
+ }\r
+ });\r
+ var border = $("<div class='textarea-border' />");\r
+ var container = $("<div class='textarea-container' />");\r
+\r
+ $(textarea).appendTo(container);\r
+ $(border).appendTo(container);\r
+\r
+ $(this).after(container);\r
+ });\r
+ });\r
+\r
+function array_diff(array1, array2){\r
+ var difference = $.grep(array1, function(el) { return $.inArray(el,array2) < 0});\r
+ return difference.concat($.grep(array2, function(el) { return $.inArray(el,array1) < 0}));;\r
+}\r