Skip to content

Commit

Permalink
Select SearchLocator in WebView
Browse files Browse the repository at this point in the history
  • Loading branch information
hrishikesh-kadam committed Nov 2, 2018
1 parent 078ab70 commit 975fe40
Show file tree
Hide file tree
Showing 14 changed files with 165 additions and 386 deletions.
7 changes: 2 additions & 5 deletions folioreader/res/values/strings.xml
Expand Up @@ -84,10 +84,6 @@
<string name="please_enter_note">please enter a note</string>
<string name="contents">Contents</string>

<string name="highlight_search_result" translatable="false">javascript:highlightSearchResult(\"%s\", %d)</string>
<string name="make_search_results_invisible" translatable="false">javascript:makeSearchResultsInvisible()</string>
<string name="reset_search_results" translatable="false">javascript:resetSearchResults()</string>

<!-- TODO: Remove or change this placeholder text -->
<string name="hello_blank_fragment">Hello blank fragment</string>
<string name="debug_start_drag">Starting drag!</string>
Expand All @@ -100,7 +96,6 @@

<string name="xhtml_mime_type" translatable="false">application/xhtml+xml</string>
<string name="html_mime_type" translatable="false">text/html</string>
<string name="back_compat" translatable="false">BackCompat</string>

<string name="menu_item_search">Search</string>
<string name="menu_item_config">Configuration</string>
Expand All @@ -118,5 +113,7 @@
<!-- JS Calls -->
<string name="callComputeLastReadCfi" translatable="false">javascript:computeLastReadCfi()</string>
<string name="callScrollToCfi" translatable="false">javascript:scrollToCfi(\"%s\")</string>
<string name="callHighlightSearchLocator" translatable="false">javascript:highlightSearchLocator(\"%s\")</string>
<string name="callClearSelection" translatable="false">javascript:clearSelection()</string>

</resources>
267 changes: 46 additions & 221 deletions folioreader/src/main/assets/js/Bridge.js
Expand Up @@ -27,11 +27,6 @@ var horizontalIntervalPeriod = 1000;
var horizontalIntervalCounter = 0;
var horizontalIntervalLimit = 3000;

var searchResults = [];
var lastSearchQuery = null;
var testCounter = 0;
var searchResultsInvisible = true;

var viewportRect;

// Class manipulation
Expand Down Expand Up @@ -118,7 +113,7 @@ function audioMarkID(className, id) {
audioMarkClass = className
var el = document.getElementById(id);

scrollToNode(el);
scrollToNodeOrRange(el);
el.classList.add(className)
}

Expand Down Expand Up @@ -210,7 +205,7 @@ function getSentenceWithIndex(className) {

var text = sentence.innerText || sentence.textContent;

scrollToNode(sentence);
scrollToNodeOrRange(sentence);

if (audioMarkClass) {
removeAllClasses(audioMarkClass);
Expand Down Expand Up @@ -497,15 +492,15 @@ var LoadingView = {
function goToHighlight(highlightId) {
var element = document.getElementById(highlightId.toString());
if (element)
scrollToNode(element);
scrollToNodeOrRange(element);

LoadingView.hide();
}

function goToAnchor(anchorId) {
var element = document.getElementById(anchorId);
if (element)
scrollToNode(element);
scrollToNodeOrRange(element);

LoadingView.hide();
}
Expand Down Expand Up @@ -550,8 +545,12 @@ function scrollToFirst() {
LoadingView.hide();
}

function getCompatMode() {
FolioWebView.setCompatMode(document.compatMode);
function checkCompatMode() {
if (document.compatMode === "BackCompat") {
console.error("-> Web page loaded in Quirks mode. Please report to developer " +
"for debugging with current EPUB file, as many features might stop working " +
"(ex. Horizontal scroll feature).")
}
}

function horizontalRecheck() {
Expand Down Expand Up @@ -674,10 +673,10 @@ function bodyOrHtml() {
}

/**
* @param {(Element|Text)} node
* @returns {(Element|Text)} node
* @param {(Element|Text|Range)} nodeOrRange
* @returns {(Element|Text|Range)} nodeOrRange
*/
function scrollToNode(node) {
function scrollToNodeOrRange(nodeOrRange) {

var scrollingElement = bodyOrHtml();
var direction = FolioWebView.getDirection();
Expand All @@ -688,26 +687,28 @@ function scrollToNode(node) {
// For Direction.HORIZONTAL
var nodeOffsetLeft;

switch (node.nodeType) {
if (nodeOrRange instanceof Range || nodeOrRange.nodeType === Node.TEXT_NODE) {

case Node.TEXT_NODE:
var rect;
if (nodeOrRange.nodeType && nodeOrRange.nodeType === Node.TEXT_NODE) {
var range = document.createRange();
range.selectNode(node);
var rect = RangeFix.getBoundingClientRect(range);
nodeOffsetTop = scrollingElement.scrollTop + rect.top;
nodeOffsetHeight = rect.height;
nodeOffsetLeft = scrollingElement.scrollLeft + rect.left;
break;
range.selectNode(nodeOrRange);
rect = RangeFix.getBoundingClientRect(range);
} else {
rect = RangeFix.getBoundingClientRect(nodeOrRange);
}
nodeOffsetTop = scrollingElement.scrollTop + rect.top;
nodeOffsetHeight = rect.height;
nodeOffsetLeft = scrollingElement.scrollLeft + rect.left;

case Node.ELEMENT_NODE:
nodeOffsetTop = node.offsetTop;
nodeOffsetHeight = node.offsetHeight;
nodeOffsetLeft = node.offsetLeft;
break;
} else if (nodeOrRange.nodeType === Node.ELEMENT_NODE) {

default:
console.error("-> Illegal Argument Exception, node.nodeType found " + node.nodeType);
return null;
nodeOffsetTop = nodeOrRange.offsetTop;
nodeOffsetHeight = nodeOrRange.offsetHeight;
nodeOffsetLeft = nodeOrRange.offsetLeft;

} else {
throw("-> Illegal Argument Exception, nodeOrRange -> " + nodeOrRange);
}

switch (direction) {
Expand Down Expand Up @@ -747,204 +748,28 @@ function scrollToNode(node) {
break;
}

return node;
return nodeOrRange;
}

// Testing purpose calls
function test() {

++testCounter;
console.log("-> testCounter = " + testCounter);

var searchQuery = "look";

if (testCounter == 1) {

getCompatMode();
function highlightSearchLocator(rangeCfi) {

if (FolioWebView.getDirection() == Direction.HORIZONTAL)
initHorizontalDirection();

highlightSearchResult(searchQuery, 1);

} else if (testCounter == 2) {

makeSearchResultsInvisible();

} else if (testCounter == 3) {

highlightSearchResult(searchQuery, 2);

} else if (testCounter == 4) {

}
}
try {
var $obj = EPUBcfi.Interpreter.getRangeTargetElements(rangeCfi, document);

function highlightSearchResult(searchQuery, occurrenceInChapter) {
var range = document.createRange();
range.setStart($obj.startElement, $obj.startOffset);
range.setEnd($obj.endElement, $obj.endOffset);

if (searchQuery == lastSearchQuery) {
makeSearchResultsInvisible();
} else {
resetSearchResults();
searchResults = applySearchResultClass(searchQuery);
console.debug("-> Search Query Found = " + searchResults.length);
window.getSelection().removeAllRanges();
window.getSelection().addRange(range);
scrollToNodeOrRange(range);
} catch (e) {
console.error("-> " + e);
}

applySearchResultVisibleClass(occurrenceInChapter);
LoadingView.hide();
}

function applySearchResultClass(searchQuery) {

var searchQueryRegExp = new RegExp(escapeRegExp(searchQuery), "i");

var searchResults = [];
var searchChildNodesArray = [];
var elementArray = [];
var textNodeArray = [];

var bodyElement = document.getElementsByTagName('body')[0];
var elementsInBody = bodyElement.getElementsByTagName('*');

for (var i = 0; i < elementsInBody.length; i++) {

var childNodes = elementsInBody[i].childNodes;

for (var j = 0; j < childNodes.length; j++) {

if (childNodes[j].nodeType == Node.TEXT_NODE &&
childNodes[j].nodeValue.trim().length) {
//console.log("-> " + childNodes[j].nodeValue);

if (childNodes[j].nodeValue.match(searchQueryRegExp)) {
//console.log("-> Found -> " + childNodes[j].nodeValue);

searchChildNodesArray.push(
getSearchChildNodes(childNodes[j].nodeValue, searchQuery));

elementArray.push(elementsInBody[i]);
textNodeArray.push(childNodes[j]);
}
}
}
}

for (var i = 0; i < searchChildNodesArray.length; i++) {

var searchChildNodes = searchChildNodesArray[i];

for (var j = 0; j < searchChildNodes.length; j++) {

if (searchChildNodes[j].className == "search-result")
searchResults.push(searchChildNodes[j]);
elementArray[i].insertBefore(searchChildNodes[j], textNodeArray[i]);
}

elementArray[i].removeChild(textNodeArray[i]);
}

lastSearchQuery = searchQuery;
return searchResults;
}

function getSearchChildNodes(text, searchQuery) {

var arrayIndex = [];
var matchIndexStart = -1;
var textChunk = "";
var searchChildNodes = [];

for (var i = 0, j = 0; i < text.length; i++) {

textChunk += text[i];

if (text[i].match(new RegExp(escapeRegExp(searchQuery[j]), "i"))) {

if (matchIndexStart == -1)
matchIndexStart = i;

if (searchQuery.length == j + 1) {

var textNode = document.createTextNode(
textChunk.substring(0, textChunk.length - searchQuery.length));

var searchNode = document.createElement("span");
searchNode.className = "search-result";
var queryTextNode = document.createTextNode(
text.substring(matchIndexStart, matchIndexStart + searchQuery.length));
searchNode.appendChild(queryTextNode);

searchChildNodes.push(textNode);
searchChildNodes.push(searchNode);

arrayIndex.push(matchIndexStart);
matchIndexStart = -1;
j = 0;
textChunk = "";

} else {
j++;
}

} else {
matchIndexStart = -1;
j = 0;
}
}

if (textChunk !== "") {
var textNode = document.createTextNode(textChunk);
searchChildNodes.push(textNode);
}

return searchChildNodes;
}

function makeSearchResultsVisible() {

for (var i = 0; i < searchResults.length; i++) {
searchResults[i].className = "search-result-visible";
}
searchResultsInvisible = false;
}

function makeSearchResultsInvisible() {

if (searchResultsInvisible)
return;
for (var i = 0; i < searchResults.length; i++) {
if (searchResults[i].className == "search-result-visible")
searchResults[i].className = "search-result-invisible";
}
searchResultsInvisible = true;
}

function applySearchResultVisibleClass(occurrenceInChapter) {

var searchResult = searchResults[occurrenceInChapter - 1];
if (searchResult === undefined)
return;
searchResult.className = "search-result-visible";
searchResultsInvisible = false;

scrollToNode(searchResult);
}

function resetSearchResults() {

for (var i = 0; i < searchResults.length; i++) {
searchResults[i].outerHTML = searchResults[i].innerHTML;
}

searchResults = [];
lastSearchQuery = null;
searchResultsInvisible = true;
}

function escapeRegExp(str) {
return str.replace(/([.*+?^=!:${}()|\[\]\/\\])/g, "\\$1");
}

/**
* Returns JSON of selection rect
* @param {Element} [element]
Expand Down Expand Up @@ -1022,7 +847,7 @@ function computeLastReadCfi() {
cfi = EPUBcfi.Generator.generateElementCFIComponent(node);
}

cfi = EPUBcfi.Generator.generateCompleteCFI("", cfi);
cfi = EPUBcfi.Generator.generateCompleteCFI("/0!", cfi);
viewportRect = null;
FolioPageFragment.storeLastReadCfi(cfi);
}
Expand Down Expand Up @@ -1078,8 +903,8 @@ function getFirstVisibleNode(node) {
function scrollToCfi(cfi) {

try {
var $node = EPUBcfi.Interpreter.getTargetElementWithPartialCFI(cfi, document);
scrollToNode($node[0]);
var $node = EPUBcfi.Interpreter.getTargetElement(cfi, document);
scrollToNodeOrRange($node[0]);
} catch (e) {
console.error("-> " + e);
}
Expand Down

0 comments on commit 975fe40

Please sign in to comment.