mirror of
https://github.com/kiwix/kiwix-js-pwa.git
synced 2025-09-13 06:22:09 -04:00
Enabled scrolling to first full match
Former-commit-id: 27d217c412dbd3400674908a89213d6a68d5e500 [formerly 2c4f447f7f7d45bab10c2fac9476df798e615c9a] Former-commit-id: 1a0e4249cab5fda33c7e66d44366fe1a44293866
This commit is contained in:
parent
0564aad55c
commit
6343ba7d0e
@ -32,7 +32,7 @@
|
|||||||
<AppXManifest Include="C:\Users\geoff\Source\Repos\kiwix-js-windows\bin\Release\AppxManifest.xml">
|
<AppXManifest Include="C:\Users\geoff\Source\Repos\kiwix-js-windows\bin\Release\AppxManifest.xml">
|
||||||
<PackagePath>AppxManifest.xml</PackagePath>
|
<PackagePath>AppxManifest.xml</PackagePath>
|
||||||
<ReRegisterAppIfChanged>true</ReRegisterAppIfChanged>
|
<ReRegisterAppIfChanged>true</ReRegisterAppIfChanged>
|
||||||
<Modified>2017-08-19T13:17:37.811</Modified>
|
<Modified>2017-08-20T18:41:06.455</Modified>
|
||||||
</AppXManifest>
|
</AppXManifest>
|
||||||
</ItemGroup>
|
</ItemGroup>
|
||||||
<ItemGroup>
|
<ItemGroup>
|
||||||
@ -399,7 +399,7 @@
|
|||||||
</AppxPackagedFile>
|
</AppxPackagedFile>
|
||||||
<AppxPackagedFile Include="C:\Users\geoff\Source\Repos\kiwix-js-windows\www\css\app.css">
|
<AppxPackagedFile Include="C:\Users\geoff\Source\Repos\kiwix-js-windows\www\css\app.css">
|
||||||
<PackagePath>www\css\app.css</PackagePath>
|
<PackagePath>www\css\app.css</PackagePath>
|
||||||
<Modified>2017-08-17T13:55:29.992</Modified>
|
<Modified>2017-08-20T18:09:44.037</Modified>
|
||||||
</AppxPackagedFile>
|
</AppxPackagedFile>
|
||||||
<AppxPackagedFile Include="C:\Users\geoff\Source\Repos\kiwix-js-windows\www\css\bootstrap-theme.css">
|
<AppxPackagedFile Include="C:\Users\geoff\Source\Repos\kiwix-js-windows\www\css\bootstrap-theme.css">
|
||||||
<PackagePath>www\css\bootstrap-theme.css</PackagePath>
|
<PackagePath>www\css\bootstrap-theme.css</PackagePath>
|
||||||
@ -415,7 +415,7 @@
|
|||||||
</AppxPackagedFile>
|
</AppxPackagedFile>
|
||||||
<AppxPackagedFile Include="C:\Users\geoff\Source\Repos\kiwix-js-windows\www\index.html">
|
<AppxPackagedFile Include="C:\Users\geoff\Source\Repos\kiwix-js-windows\www\index.html">
|
||||||
<PackagePath>www\index.html</PackagePath>
|
<PackagePath>www\index.html</PackagePath>
|
||||||
<Modified>2017-08-19T13:17:20.030</Modified>
|
<Modified>2017-08-20T14:54:56.576</Modified>
|
||||||
</AppxPackagedFile>
|
</AppxPackagedFile>
|
||||||
<AppxPackagedFile Include="C:\Users\geoff\Source\Repos\kiwix-js-windows\www\favicon.ico">
|
<AppxPackagedFile Include="C:\Users\geoff\Source\Repos\kiwix-js-windows\www\favicon.ico">
|
||||||
<PackagePath>www\favicon.ico</PackagePath>
|
<PackagePath>www\favicon.ico</PackagePath>
|
||||||
@ -543,7 +543,7 @@
|
|||||||
</AppxPackagedFile>
|
</AppxPackagedFile>
|
||||||
<AppxPackagedFile Include="C:\Users\geoff\Source\Repos\kiwix-js-windows\www\js\app.js">
|
<AppxPackagedFile Include="C:\Users\geoff\Source\Repos\kiwix-js-windows\www\js\app.js">
|
||||||
<PackagePath>www\js\app.js</PackagePath>
|
<PackagePath>www\js\app.js</PackagePath>
|
||||||
<Modified>2017-08-19T13:17:32.154</Modified>
|
<Modified>2017-08-20T18:03:09.796</Modified>
|
||||||
</AppxPackagedFile>
|
</AppxPackagedFile>
|
||||||
<AppxPackagedFile Include="C:\Users\geoff\Source\Repos\kiwix-js-windows\www\js\init.js">
|
<AppxPackagedFile Include="C:\Users\geoff\Source\Repos\kiwix-js-windows\www\js\init.js">
|
||||||
<PackagePath>www\js\init.js</PackagePath>
|
<PackagePath>www\js\init.js</PackagePath>
|
||||||
@ -587,7 +587,7 @@
|
|||||||
</AppxPackagedFile>
|
</AppxPackagedFile>
|
||||||
<AppxPackagedFile Include="C:\Users\geoff\Source\Repos\kiwix-js-windows\www\js\lib\util.js">
|
<AppxPackagedFile Include="C:\Users\geoff\Source\Repos\kiwix-js-windows\www\js\lib\util.js">
|
||||||
<PackagePath>www\js\lib\util.js</PackagePath>
|
<PackagePath>www\js\lib\util.js</PackagePath>
|
||||||
<Modified>2017-08-19T13:11:37.419</Modified>
|
<Modified>2017-08-20T18:40:59.430</Modified>
|
||||||
</AppxPackagedFile>
|
</AppxPackagedFile>
|
||||||
<AppxPackagedFile Include="C:\Users\geoff\Source\Repos\kiwix-js-windows\www\js\lib\xzdec.js">
|
<AppxPackagedFile Include="C:\Users\geoff\Source\Repos\kiwix-js-windows\www\js\lib\xzdec.js">
|
||||||
<PackagePath>www\js\lib\xzdec.js</PackagePath>
|
<PackagePath>www\js\lib\xzdec.js</PackagePath>
|
||||||
|
@ -31,7 +31,7 @@
|
|||||||
|
|
||||||
[role=region] > header {
|
[role=region] > header {
|
||||||
/*margin: .5rem 0 1rem 0;*/
|
/*margin: .5rem 0 1rem 0;*/
|
||||||
margin: 0 0.75em 0 0;
|
margin: 0 0.75em 0 1px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,7 +116,7 @@
|
|||||||
background: inherit;
|
background: inherit;
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-sm {
|
.btn-sm, .btn-lg {
|
||||||
background: rgba(51,122,183,0.7) !important;
|
background: rgba(51,122,183,0.7) !important;
|
||||||
border: transparent !important;
|
border: transparent !important;
|
||||||
float: none !important;
|
float: none !important;
|
||||||
@ -160,30 +160,34 @@ footer .glyphicon {
|
|||||||
border-color: darkgray;
|
border-color: darkgray;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.dark a {
|
||||||
|
color: lightblue !important;
|
||||||
|
}
|
||||||
|
|
||||||
.darkfooter .dropdown-menu, .darkfooter .dropdown-menu a {
|
.darkfooter .dropdown-menu, .darkfooter .dropdown-menu a {
|
||||||
color: lightblue !important;
|
color: lightblue !important;
|
||||||
background-color: rgba(34,34,34,0.6) !important;
|
background-color: rgba(34,34,34,0.6) !important;
|
||||||
border-color: darkgray;
|
border-color: darkgray;
|
||||||
}
|
}
|
||||||
|
|
||||||
.darkfooter .dropdown-menu a:focus, .darkfooter .dropdown-menu a:hover {
|
.darkfooter .dropdown-menu a:focus, .darkfooter .dropdown-menu a:hover {
|
||||||
color: lightblue !important;
|
color: lightblue !important;
|
||||||
background: darkslategray !important;
|
background: darkslategray !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dark .list-group-item {
|
.dark .list-group-item {
|
||||||
color: lightblue !important;
|
color: lightblue !important;
|
||||||
background-color: #222 !important;
|
background-color: #222 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dark a.list-group-item:hover, .dark a.list-group-item:focus, .dark nav a:hover, .dark nav a:focus {
|
.dark a.list-group-item:hover, .dark a.list-group-item:focus, .dark nav a:hover, .dark nav a:focus, .dark nav .active {
|
||||||
color: lightblue !important;
|
color: lightblue !important;
|
||||||
background-color: darkslategray !important;
|
background-color: darkslategray !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dark .btn-default {
|
.dark .btn-default, .dark .input-group-addon {
|
||||||
background: #222 !important;
|
background: #222 !important;
|
||||||
color: dimgray !important;
|
color: lightgray !important;
|
||||||
text-shadow: none;
|
text-shadow: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,14 +98,13 @@
|
|||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="" id="row2" style="float:right; display:none;">
|
<div class="" id="row2" style="display:none;">
|
||||||
<span class="input-group">
|
<span class="input-group">
|
||||||
<input type="search" id="findInArticle" placeholder="Highlight in article..."
|
<input class="form-control" id="findInArticle" style="display:inline;" type="search" placeholder="Highlight in article...">
|
||||||
class="form-control" />
|
<span class="input-group-addon" id="matches">Full: 0</span>
|
||||||
Matches: 0
|
<span class="input-group-addon" id="partial">Partial: 0</span>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
@ -95,17 +95,24 @@ define(['jquery', 'zimArchiveLoader', 'util', 'uiUtil', 'cookies', 'abstractFile
|
|||||||
$('#findText').on('click', function (e) {
|
$('#findText').on('click', function (e) {
|
||||||
var innerDocument = window.frames[0].frameElement.contentDocument || window.frames[0].frameElement.contentWindow.document;
|
var innerDocument = window.frames[0].frameElement.contentDocument || window.frames[0].frameElement.contentWindow.document;
|
||||||
if (innerDocument.body.innerHTML.length < 10) return;
|
if (innerDocument.body.innerHTML.length < 10) return;
|
||||||
|
innerDocument = innerDocument.body;
|
||||||
|
if (!innerDocument) return;
|
||||||
var searchDiv = document.getElementById('row2');
|
var searchDiv = document.getElementById('row2');
|
||||||
var findInArticle = document.getElementById('findInArticle');
|
var findInArticle = document.getElementById('findInArticle');
|
||||||
if (searchDiv.style.display == 'none') {
|
if (searchDiv.style.display == 'none') {
|
||||||
searchDiv.style.display = "inline";
|
searchDiv.style.display = "inline";
|
||||||
|
document.getElementById('findText').classList.add("active");
|
||||||
findInArticle.focus();
|
findInArticle.focus();
|
||||||
} else {
|
} else {
|
||||||
|
findInArticle.value = "";
|
||||||
|
document.getElementById('matches').innerHTML = "Full: 0";
|
||||||
|
document.getElementById('partial').innerHTML = "Partial: 0";
|
||||||
searchDiv.style.display = "none";
|
searchDiv.style.display = "none";
|
||||||
|
document.getElementById('findText').classList.remove("active");
|
||||||
}
|
}
|
||||||
if (localSearch.remove) {
|
if (localSearch.remove) {
|
||||||
localSearch.remove();
|
localSearch.remove();
|
||||||
} else {
|
} else if (searchDiv.style.display == "inline") {
|
||||||
localSearch = new util.Hilitor(innerDocument);
|
localSearch = new util.Hilitor(innerDocument);
|
||||||
//TODO: Check right-to-left language support...
|
//TODO: Check right-to-left language support...
|
||||||
localSearch.setMatchType('left');
|
localSearch.setMatchType('left');
|
||||||
@ -113,14 +120,32 @@ define(['jquery', 'zimArchiveLoader', 'util', 'uiUtil', 'cookies', 'abstractFile
|
|||||||
findInArticle.addEventListener('keyup', function (e) {
|
findInArticle.addEventListener('keyup', function (e) {
|
||||||
//Ensure timeout doesn't occur if another key has been pressed within time window
|
//Ensure timeout doesn't occur if another key has been pressed within time window
|
||||||
clearTimeout(timer);
|
clearTimeout(timer);
|
||||||
|
//If user pressed Alt-F, exit
|
||||||
|
if (e.altKey && e.which == 70) return;
|
||||||
var val = this.value;
|
var val = this.value;
|
||||||
|
if (val && e.which == 13) {
|
||||||
|
localSearch.scrollToFullMatch(val);
|
||||||
|
return;
|
||||||
|
}
|
||||||
//Ensure nothing happens if only one value has been entered (not specific enough), but ensure timeout is set
|
//Ensure nothing happens if only one value has been entered (not specific enough), but ensure timeout is set
|
||||||
//if no value has been entered (clears highlighting if user deletes all values in search field)
|
//if no value has been entered (clears highlighting if user deletes all values in search field)
|
||||||
if (~(val.length - 2)) {
|
if (~(val.length - 2)) {
|
||||||
timer = setTimeout(function () {
|
timer = setTimeout(function () {
|
||||||
localSearch.apply(val);
|
localSearch.apply(val);
|
||||||
var x = localSearch.countMatches();
|
if (val.length) {
|
||||||
|
var fullTotal = localSearch.countFullMatches(val);
|
||||||
|
var partialTotal = localSearch.countPartialMatches();
|
||||||
|
fullTotal = fullTotal > partialTotal ? partialTotal : fullTotal;
|
||||||
|
document.getElementById('matches').innerHTML = '<a id="scrollLink" href="#">Full: ' + fullTotal + '</a>';
|
||||||
|
document.getElementById('partial').innerHTML = "Partial: " + partialTotal;
|
||||||
|
document.getElementById('scrollLink').addEventListener('click', function () {
|
||||||
|
localSearch.scrollToFullMatch(val);
|
||||||
|
});
|
||||||
|
//localSearch.scrollToFullMatch(val);
|
||||||
|
} else {
|
||||||
|
document.getElementById('matches').innerHTML = "Full: 0";
|
||||||
|
document.getElementById('partial').innerHTML = "Partial: 0";
|
||||||
|
}
|
||||||
}, 500);
|
}, 500);
|
||||||
}
|
}
|
||||||
}, false);
|
}, false);
|
||||||
|
@ -378,7 +378,6 @@ define(['q'], function(q) {
|
|||||||
// Please acknowledge use of this code by including this header.
|
// Please acknowledge use of this code by including this header.
|
||||||
// For documentation see: http://www.the-art-of-web.com/javascript/search-highlight/
|
// For documentation see: http://www.the-art-of-web.com/javascript/search-highlight/
|
||||||
function Hilitor(node, tag) {
|
function Hilitor(node, tag) {
|
||||||
|
|
||||||
var targetNode = node || document.body;
|
var targetNode = node || document.body;
|
||||||
var hiliteTag = tag || "EM";
|
var hiliteTag = tag || "EM";
|
||||||
var skipTags = new RegExp("^(?:" + hiliteTag + "|SCRIPT|FORM)$");
|
var skipTags = new RegExp("^(?:" + hiliteTag + "|SCRIPT|FORM)$");
|
||||||
@ -388,7 +387,7 @@ define(['q'], function(q) {
|
|||||||
var colorIdx = 0;
|
var colorIdx = 0;
|
||||||
var matchRegex = "";
|
var matchRegex = "";
|
||||||
//Add any symbols that may prefix a start string and don't match \b (word boundary)
|
//Add any symbols that may prefix a start string and don't match \b (word boundary)
|
||||||
var leadingSymbols = "’‘¿¡";
|
var leadingSymbols = "’‘¿¡-";
|
||||||
var openLeft = false;
|
var openLeft = false;
|
||||||
var openRight = false;
|
var openRight = false;
|
||||||
|
|
||||||
@ -417,11 +416,12 @@ define(['q'], function(q) {
|
|||||||
function addAccents(input) {
|
function addAccents(input) {
|
||||||
var retval = input;
|
var retval = input;
|
||||||
retval = retval.replace(/([ao])e/ig, "$1");
|
retval = retval.replace(/([ao])e/ig, "$1");
|
||||||
retval = retval.replace(/\\u00E[024]/ig, "a");
|
retval = retval.replace(/\\u00[CE][0124]/ig, "a");
|
||||||
retval = retval.replace(/\\u00E7/ig, "c");
|
retval = retval.replace(/\\u00E7/ig, "c");
|
||||||
retval = retval.replace(/\\u00E[89AB]|\\u00C[9A]/ig, "e");
|
retval = retval.replace(/\\u00E[89AB]|\\u00C[9A]/ig, "e");
|
||||||
retval = retval.replace(/\\u00E[DEF]/ig, "i");
|
retval = retval.replace(/\\u00[CE][DEF]/ig, "i");
|
||||||
retval = retval.replace(/\\u00F[46]/ig, "o");
|
retval = retval.replace(/\\u00[DF]1/ig, "n");
|
||||||
|
retval = retval.replace(/\\u00[FD][346]/ig, "o");
|
||||||
retval = retval.replace(/\\u00F[9BC]/ig, "u");
|
retval = retval.replace(/\\u00F[9BC]/ig, "u");
|
||||||
retval = retval.replace(/\\u00FF/ig, "y");
|
retval = retval.replace(/\\u00FF/ig, "y");
|
||||||
retval = retval.replace(/\\u00DF/ig, "s");
|
retval = retval.replace(/\\u00DF/ig, "s");
|
||||||
@ -459,10 +459,78 @@ define(['q'], function(q) {
|
|||||||
return retval;
|
return retval;
|
||||||
};
|
};
|
||||||
|
|
||||||
this.countMatches = function () {
|
this.countFullMatches = function (input) {
|
||||||
if (node === undefined || !node) return;
|
if (node === undefined || !node) return;
|
||||||
var matches = matchInner(node.body.innerHTML, '<' + hiliteTag + '\\b[^>]*class="hilitor"[^>]*>', '</' + hiliteTag + '>', 'gi');
|
var strippedText = node.innerHTML.replace(/<title[^>]*>[\s\S]*<\/title>/i, "");
|
||||||
return matches.length;
|
strippedText = node.innerHTML.replace(/<[^>]*>\s*/g, " ");
|
||||||
|
if (!strippedText) return 0;
|
||||||
|
strippedText = strippedText.replace(/(?: |\r?\n|[.,;:?!¿¡-])+/g, " ");
|
||||||
|
strippedText = strippedText.replace(/\s+/g, " ");
|
||||||
|
if (!strippedText.length) return 0;
|
||||||
|
input = input.replace(/[\s.,;:?!¿¡-]+/g, " ");
|
||||||
|
var inputMatcher = new RegExp(input, "ig");
|
||||||
|
var matches = strippedText.match(inputMatcher);
|
||||||
|
if (matches) return matches.length
|
||||||
|
else return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.countPartialMatches = function () {
|
||||||
|
if (node === undefined || !node) return;
|
||||||
|
var matches = matchInner(node.innerHTML, '<' + hiliteTag + '\\b[^>]*class="hilitor"[^>]*>', '</' + hiliteTag + '>', 'gi');
|
||||||
|
if (matches) return matches.length
|
||||||
|
else return 0;
|
||||||
|
//if (matches) {
|
||||||
|
// var input = document.getElementById('findInArticle').value.replace(/\s*/g, "").toLowerCase();
|
||||||
|
// var matchedWords = "";
|
||||||
|
// var buffer = "";
|
||||||
|
// var countFullMatches = 0;
|
||||||
|
// for (var i = 0; i < matches.length; i++ ) {
|
||||||
|
// var instance = matches[i].match(/<[^>]*>([^<]*)</i)[1].toLowerCase();
|
||||||
|
// buffer += instance;
|
||||||
|
// var inputMatcher = new RegExp('^' + buffer);
|
||||||
|
// if (input.match(inputMatcher)) {
|
||||||
|
// matchedWords += instance;
|
||||||
|
// } else {
|
||||||
|
// buffer = "";
|
||||||
|
// matchedWords = "";
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
// if (~matchedWords.indexOf(input)) {
|
||||||
|
// countFullMatches++;
|
||||||
|
// buffer = "";
|
||||||
|
// matchedWords = "";
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// return countFullMatches;
|
||||||
|
//} else return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.scrollToFullMatch = function (input) {
|
||||||
|
if (node === undefined || !node) return;
|
||||||
|
if (!input) return;
|
||||||
|
//Normalize spaces
|
||||||
|
input = input.replace(/\s+/g, " ");
|
||||||
|
var inputWords = input.split(" ");
|
||||||
|
var testInput = addAccents(input);
|
||||||
|
var testInput = new RegExp(testInput, "i");
|
||||||
|
var hilitedNodes = node.getElementsByClassName(className);
|
||||||
|
var subNodes = [];
|
||||||
|
var start;
|
||||||
|
var end = inputWords.length;
|
||||||
|
for (start = 0; start < hilitedNodes.length; start++) {
|
||||||
|
for (var f = start; f < end; f++) {
|
||||||
|
if (f > hilitedNodes.length - 1) break;
|
||||||
|
subNodes.push(hilitedNodes[f].innerHTML);
|
||||||
|
}
|
||||||
|
var nodeText = subNodes.join(" ");
|
||||||
|
if (testInput.test(nodeText)) {
|
||||||
|
//hilitedNodes[start].scrollIntoView(true);
|
||||||
|
$("#articleContent").contents().scrollTop($(hilitedNodes[start]).offset().top);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
subNodes = [];
|
||||||
|
end++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// recursively apply word highlighting
|
// recursively apply word highlighting
|
||||||
@ -484,7 +552,7 @@ define(['q'], function(q) {
|
|||||||
|
|
||||||
var match = document.createElement(hiliteTag);
|
var match = document.createElement(hiliteTag);
|
||||||
match.appendChild(document.createTextNode(regs[1]));
|
match.appendChild(document.createTextNode(regs[1]));
|
||||||
match.style.backgroundColor = wordColor[regs[1].toLowerCase()];
|
match.style.setProperty("background-color", wordColor[regs[1].toLowerCase()], "important");
|
||||||
match.style.fontStyle = "inherit";
|
match.style.fontStyle = "inherit";
|
||||||
match.style.color = "#000";
|
match.style.color = "#000";
|
||||||
match.className = className;
|
match.className = className;
|
||||||
|
@ -31,7 +31,7 @@
|
|||||||
|
|
||||||
[role=region] > header {
|
[role=region] > header {
|
||||||
/*margin: .5rem 0 1rem 0;*/
|
/*margin: .5rem 0 1rem 0;*/
|
||||||
margin: 0 0.75em 0 0;
|
margin: 0 0.75em 0 1px;
|
||||||
text-align: center;
|
text-align: center;
|
||||||
}
|
}
|
||||||
|
|
||||||
@ -116,7 +116,7 @@
|
|||||||
background: inherit;
|
background: inherit;
|
||||||
}
|
}
|
||||||
|
|
||||||
.btn-sm {
|
.btn-sm, .btn-lg {
|
||||||
background: rgba(51,122,183,0.7) !important;
|
background: rgba(51,122,183,0.7) !important;
|
||||||
border: transparent !important;
|
border: transparent !important;
|
||||||
float: none !important;
|
float: none !important;
|
||||||
@ -160,30 +160,34 @@ footer .glyphicon {
|
|||||||
border-color: darkgray;
|
border-color: darkgray;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
.dark a {
|
||||||
|
color: lightblue !important;
|
||||||
|
}
|
||||||
|
|
||||||
.darkfooter .dropdown-menu, .darkfooter .dropdown-menu a {
|
.darkfooter .dropdown-menu, .darkfooter .dropdown-menu a {
|
||||||
color: lightblue !important;
|
color: lightblue !important;
|
||||||
background-color: rgba(34,34,34,0.6) !important;
|
background-color: rgba(34,34,34,0.6) !important;
|
||||||
border-color: darkgray;
|
border-color: darkgray;
|
||||||
}
|
}
|
||||||
|
|
||||||
.darkfooter .dropdown-menu a:focus, .darkfooter .dropdown-menu a:hover {
|
.darkfooter .dropdown-menu a:focus, .darkfooter .dropdown-menu a:hover {
|
||||||
color: lightblue !important;
|
color: lightblue !important;
|
||||||
background: darkslategray !important;
|
background: darkslategray !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dark .list-group-item {
|
.dark .list-group-item {
|
||||||
color: lightblue !important;
|
color: lightblue !important;
|
||||||
background-color: #222 !important;
|
background-color: #222 !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dark a.list-group-item:hover, .dark a.list-group-item:focus, .dark nav a:hover, .dark nav a:focus {
|
.dark a.list-group-item:hover, .dark a.list-group-item:focus, .dark nav a:hover, .dark nav a:focus, .dark nav .active {
|
||||||
color: lightblue !important;
|
color: lightblue !important;
|
||||||
background-color: darkslategray !important;
|
background-color: darkslategray !important;
|
||||||
}
|
}
|
||||||
|
|
||||||
.dark .btn-default {
|
.dark .btn-default, .dark .input-group-addon {
|
||||||
background: #222 !important;
|
background: #222 !important;
|
||||||
color: dimgray !important;
|
color: lightgray !important;
|
||||||
text-shadow: none;
|
text-shadow: none;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,14 +98,13 @@
|
|||||||
</span>
|
</span>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
<div class="" id="row2" style="float:right; display:none;">
|
<div class="" id="row2" style="display:none;">
|
||||||
<span class="input-group">
|
<span class="input-group">
|
||||||
<input type="search" id="findInArticle" placeholder="Highlight in article..."
|
<input class="form-control" id="findInArticle" style="display:inline;" type="search" placeholder="Highlight in article...">
|
||||||
class="form-control" />
|
<span class="input-group-addon" id="matches">Full: 0</span>
|
||||||
Matches: 0
|
<span class="input-group-addon" id="partial">Partial: 0</span>
|
||||||
</span>
|
</span>
|
||||||
</div>
|
</div>
|
||||||
|
|
||||||
</form>
|
</form>
|
||||||
</div>
|
</div>
|
||||||
</nav>
|
</nav>
|
||||||
|
@ -95,17 +95,24 @@ define(['jquery', 'zimArchiveLoader', 'util', 'uiUtil', 'cookies', 'abstractFile
|
|||||||
$('#findText').on('click', function (e) {
|
$('#findText').on('click', function (e) {
|
||||||
var innerDocument = window.frames[0].frameElement.contentDocument || window.frames[0].frameElement.contentWindow.document;
|
var innerDocument = window.frames[0].frameElement.contentDocument || window.frames[0].frameElement.contentWindow.document;
|
||||||
if (innerDocument.body.innerHTML.length < 10) return;
|
if (innerDocument.body.innerHTML.length < 10) return;
|
||||||
|
innerDocument = innerDocument.body;
|
||||||
|
if (!innerDocument) return;
|
||||||
var searchDiv = document.getElementById('row2');
|
var searchDiv = document.getElementById('row2');
|
||||||
var findInArticle = document.getElementById('findInArticle');
|
var findInArticle = document.getElementById('findInArticle');
|
||||||
if (searchDiv.style.display == 'none') {
|
if (searchDiv.style.display == 'none') {
|
||||||
searchDiv.style.display = "inline";
|
searchDiv.style.display = "inline";
|
||||||
|
document.getElementById('findText').classList.add("active");
|
||||||
findInArticle.focus();
|
findInArticle.focus();
|
||||||
} else {
|
} else {
|
||||||
|
findInArticle.value = "";
|
||||||
|
document.getElementById('matches').innerHTML = "Full: 0";
|
||||||
|
document.getElementById('partial').innerHTML = "Partial: 0";
|
||||||
searchDiv.style.display = "none";
|
searchDiv.style.display = "none";
|
||||||
|
document.getElementById('findText').classList.remove("active");
|
||||||
}
|
}
|
||||||
if (localSearch.remove) {
|
if (localSearch.remove) {
|
||||||
localSearch.remove();
|
localSearch.remove();
|
||||||
} else {
|
} else if (searchDiv.style.display == "inline") {
|
||||||
localSearch = new util.Hilitor(innerDocument);
|
localSearch = new util.Hilitor(innerDocument);
|
||||||
//TODO: Check right-to-left language support...
|
//TODO: Check right-to-left language support...
|
||||||
localSearch.setMatchType('left');
|
localSearch.setMatchType('left');
|
||||||
@ -113,14 +120,32 @@ define(['jquery', 'zimArchiveLoader', 'util', 'uiUtil', 'cookies', 'abstractFile
|
|||||||
findInArticle.addEventListener('keyup', function (e) {
|
findInArticle.addEventListener('keyup', function (e) {
|
||||||
//Ensure timeout doesn't occur if another key has been pressed within time window
|
//Ensure timeout doesn't occur if another key has been pressed within time window
|
||||||
clearTimeout(timer);
|
clearTimeout(timer);
|
||||||
|
//If user pressed Alt-F, exit
|
||||||
|
if (e.altKey && e.which == 70) return;
|
||||||
var val = this.value;
|
var val = this.value;
|
||||||
|
if (val && e.which == 13) {
|
||||||
|
localSearch.scrollToFullMatch(val);
|
||||||
|
return;
|
||||||
|
}
|
||||||
//Ensure nothing happens if only one value has been entered (not specific enough), but ensure timeout is set
|
//Ensure nothing happens if only one value has been entered (not specific enough), but ensure timeout is set
|
||||||
//if no value has been entered (clears highlighting if user deletes all values in search field)
|
//if no value has been entered (clears highlighting if user deletes all values in search field)
|
||||||
if (~(val.length - 2)) {
|
if (~(val.length - 2)) {
|
||||||
timer = setTimeout(function () {
|
timer = setTimeout(function () {
|
||||||
localSearch.apply(val);
|
localSearch.apply(val);
|
||||||
var x = localSearch.countMatches();
|
if (val.length) {
|
||||||
|
var fullTotal = localSearch.countFullMatches(val);
|
||||||
|
var partialTotal = localSearch.countPartialMatches();
|
||||||
|
fullTotal = fullTotal > partialTotal ? partialTotal : fullTotal;
|
||||||
|
document.getElementById('matches').innerHTML = '<a id="scrollLink" href="#">Full: ' + fullTotal + '</a>';
|
||||||
|
document.getElementById('partial').innerHTML = "Partial: " + partialTotal;
|
||||||
|
document.getElementById('scrollLink').addEventListener('click', function () {
|
||||||
|
localSearch.scrollToFullMatch(val);
|
||||||
|
});
|
||||||
|
//localSearch.scrollToFullMatch(val);
|
||||||
|
} else {
|
||||||
|
document.getElementById('matches').innerHTML = "Full: 0";
|
||||||
|
document.getElementById('partial').innerHTML = "Partial: 0";
|
||||||
|
}
|
||||||
}, 500);
|
}, 500);
|
||||||
}
|
}
|
||||||
}, false);
|
}, false);
|
||||||
|
@ -378,7 +378,6 @@ define(['q'], function(q) {
|
|||||||
// Please acknowledge use of this code by including this header.
|
// Please acknowledge use of this code by including this header.
|
||||||
// For documentation see: http://www.the-art-of-web.com/javascript/search-highlight/
|
// For documentation see: http://www.the-art-of-web.com/javascript/search-highlight/
|
||||||
function Hilitor(node, tag) {
|
function Hilitor(node, tag) {
|
||||||
|
|
||||||
var targetNode = node || document.body;
|
var targetNode = node || document.body;
|
||||||
var hiliteTag = tag || "EM";
|
var hiliteTag = tag || "EM";
|
||||||
var skipTags = new RegExp("^(?:" + hiliteTag + "|SCRIPT|FORM)$");
|
var skipTags = new RegExp("^(?:" + hiliteTag + "|SCRIPT|FORM)$");
|
||||||
@ -388,7 +387,7 @@ define(['q'], function(q) {
|
|||||||
var colorIdx = 0;
|
var colorIdx = 0;
|
||||||
var matchRegex = "";
|
var matchRegex = "";
|
||||||
//Add any symbols that may prefix a start string and don't match \b (word boundary)
|
//Add any symbols that may prefix a start string and don't match \b (word boundary)
|
||||||
var leadingSymbols = "’‘¿¡";
|
var leadingSymbols = "’‘¿¡-";
|
||||||
var openLeft = false;
|
var openLeft = false;
|
||||||
var openRight = false;
|
var openRight = false;
|
||||||
|
|
||||||
@ -417,11 +416,12 @@ define(['q'], function(q) {
|
|||||||
function addAccents(input) {
|
function addAccents(input) {
|
||||||
var retval = input;
|
var retval = input;
|
||||||
retval = retval.replace(/([ao])e/ig, "$1");
|
retval = retval.replace(/([ao])e/ig, "$1");
|
||||||
retval = retval.replace(/\\u00E[024]/ig, "a");
|
retval = retval.replace(/\\u00[CE][0124]/ig, "a");
|
||||||
retval = retval.replace(/\\u00E7/ig, "c");
|
retval = retval.replace(/\\u00E7/ig, "c");
|
||||||
retval = retval.replace(/\\u00E[89AB]|\\u00C[9A]/ig, "e");
|
retval = retval.replace(/\\u00E[89AB]|\\u00C[9A]/ig, "e");
|
||||||
retval = retval.replace(/\\u00E[DEF]/ig, "i");
|
retval = retval.replace(/\\u00[CE][DEF]/ig, "i");
|
||||||
retval = retval.replace(/\\u00F[46]/ig, "o");
|
retval = retval.replace(/\\u00[DF]1/ig, "n");
|
||||||
|
retval = retval.replace(/\\u00[FD][346]/ig, "o");
|
||||||
retval = retval.replace(/\\u00F[9BC]/ig, "u");
|
retval = retval.replace(/\\u00F[9BC]/ig, "u");
|
||||||
retval = retval.replace(/\\u00FF/ig, "y");
|
retval = retval.replace(/\\u00FF/ig, "y");
|
||||||
retval = retval.replace(/\\u00DF/ig, "s");
|
retval = retval.replace(/\\u00DF/ig, "s");
|
||||||
@ -459,10 +459,78 @@ define(['q'], function(q) {
|
|||||||
return retval;
|
return retval;
|
||||||
};
|
};
|
||||||
|
|
||||||
this.countMatches = function () {
|
this.countFullMatches = function (input) {
|
||||||
if (node === undefined || !node) return;
|
if (node === undefined || !node) return;
|
||||||
var matches = matchInner(node.body.innerHTML, '<' + hiliteTag + '\\b[^>]*class="hilitor"[^>]*>', '</' + hiliteTag + '>', 'gi');
|
var strippedText = node.innerHTML.replace(/<title[^>]*>[\s\S]*<\/title>/i, "");
|
||||||
return matches.length;
|
strippedText = node.innerHTML.replace(/<[^>]*>\s*/g, " ");
|
||||||
|
if (!strippedText) return 0;
|
||||||
|
strippedText = strippedText.replace(/(?: |\r?\n|[.,;:?!¿¡-])+/g, " ");
|
||||||
|
strippedText = strippedText.replace(/\s+/g, " ");
|
||||||
|
if (!strippedText.length) return 0;
|
||||||
|
input = input.replace(/[\s.,;:?!¿¡-]+/g, " ");
|
||||||
|
var inputMatcher = new RegExp(input, "ig");
|
||||||
|
var matches = strippedText.match(inputMatcher);
|
||||||
|
if (matches) return matches.length
|
||||||
|
else return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.countPartialMatches = function () {
|
||||||
|
if (node === undefined || !node) return;
|
||||||
|
var matches = matchInner(node.innerHTML, '<' + hiliteTag + '\\b[^>]*class="hilitor"[^>]*>', '</' + hiliteTag + '>', 'gi');
|
||||||
|
if (matches) return matches.length
|
||||||
|
else return 0;
|
||||||
|
//if (matches) {
|
||||||
|
// var input = document.getElementById('findInArticle').value.replace(/\s*/g, "").toLowerCase();
|
||||||
|
// var matchedWords = "";
|
||||||
|
// var buffer = "";
|
||||||
|
// var countFullMatches = 0;
|
||||||
|
// for (var i = 0; i < matches.length; i++ ) {
|
||||||
|
// var instance = matches[i].match(/<[^>]*>([^<]*)</i)[1].toLowerCase();
|
||||||
|
// buffer += instance;
|
||||||
|
// var inputMatcher = new RegExp('^' + buffer);
|
||||||
|
// if (input.match(inputMatcher)) {
|
||||||
|
// matchedWords += instance;
|
||||||
|
// } else {
|
||||||
|
// buffer = "";
|
||||||
|
// matchedWords = "";
|
||||||
|
// continue;
|
||||||
|
// }
|
||||||
|
// if (~matchedWords.indexOf(input)) {
|
||||||
|
// countFullMatches++;
|
||||||
|
// buffer = "";
|
||||||
|
// matchedWords = "";
|
||||||
|
// }
|
||||||
|
// }
|
||||||
|
// return countFullMatches;
|
||||||
|
//} else return 0;
|
||||||
|
}
|
||||||
|
|
||||||
|
this.scrollToFullMatch = function (input) {
|
||||||
|
if (node === undefined || !node) return;
|
||||||
|
if (!input) return;
|
||||||
|
//Normalize spaces
|
||||||
|
input = input.replace(/\s+/g, " ");
|
||||||
|
var inputWords = input.split(" ");
|
||||||
|
var testInput = addAccents(input);
|
||||||
|
var testInput = new RegExp(testInput, "i");
|
||||||
|
var hilitedNodes = node.getElementsByClassName(className);
|
||||||
|
var subNodes = [];
|
||||||
|
var start;
|
||||||
|
var end = inputWords.length;
|
||||||
|
for (start = 0; start < hilitedNodes.length; start++) {
|
||||||
|
for (var f = start; f < end; f++) {
|
||||||
|
if (f > hilitedNodes.length - 1) break;
|
||||||
|
subNodes.push(hilitedNodes[f].innerHTML);
|
||||||
|
}
|
||||||
|
var nodeText = subNodes.join(" ");
|
||||||
|
if (testInput.test(nodeText)) {
|
||||||
|
//hilitedNodes[start].scrollIntoView(true);
|
||||||
|
$("#articleContent").contents().scrollTop($(hilitedNodes[start]).offset().top);
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
subNodes = [];
|
||||||
|
end++;
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// recursively apply word highlighting
|
// recursively apply word highlighting
|
||||||
@ -484,7 +552,7 @@ define(['q'], function(q) {
|
|||||||
|
|
||||||
var match = document.createElement(hiliteTag);
|
var match = document.createElement(hiliteTag);
|
||||||
match.appendChild(document.createTextNode(regs[1]));
|
match.appendChild(document.createTextNode(regs[1]));
|
||||||
match.style.backgroundColor = wordColor[regs[1].toLowerCase()];
|
match.style.setProperty("background-color", wordColor[regs[1].toLowerCase()], "important");
|
||||||
match.style.fontStyle = "inherit";
|
match.style.fontStyle = "inherit";
|
||||||
match.style.color = "#000";
|
match.style.color = "#000";
|
||||||
match.className = className;
|
match.className = className;
|
||||||
|
Loading…
x
Reference in New Issue
Block a user