Merge branch 'javascript-resort' of https://github.com/Scarfmonster/yacy_search_server into jsResort

pull/127/merge
luccioman 7 years ago
commit e40a225bc1

@ -907,6 +907,11 @@ search.excludehosth=
# the cases of nocache, iffresh and ifexist causes an index deletion
search.verify.delete = true
# If enabled, the results are sorted in the browser using Javascript.
# This usually improves ranking accuracy, but doesn't work well for users
# who have Javascript disabled, are using screen readers, or are on slow computers.
search.jsresort = false
# remote search details
remotesearch.maxcount = 10
remotesearch.maxtime = 3000

@ -42,9 +42,12 @@ function fadeOutBar() {
}
/**
* @param offset item number to start with
* @param itemsperpage count of items requested per page
* @param totalcount count of items available from YaCy node for this query
* @returns pagination buttons
*/
function renderPaginationButtons(offset, itemsperpage, totalcount, navurlbase, localQuery) {
function renderPaginationButtons(offset, itemsperpage, totalcount, navurlbase, localQuery, jsResort) {
var resnav = "<ul class=\"pagination\">";
var thispage = Math.floor(offset / itemsperpage);
var firstPage = thispage - (thispage % 10);
@ -52,7 +55,11 @@ function renderPaginationButtons(offset, itemsperpage, totalcount, navurlbase, l
resnav += "<li class=\"disabled\"><a title=\"Previous page\" href=\"#\">&laquo;</a></li>";
} else {
resnav += "<li><a id=\"prevpage\" title=\"Previous page\" accesskey=\"p\" href=\"";
resnav += (navurlbase + "&amp;startRecord=" + ((thispage - 1) * itemsperpage));
if (jsResort) {
resnav += ("javascript:numberedPage(" + (thispage - 1) + ");");
} else {
resnav += (navurlbase + "&amp;startRecord=" + ((thispage - 1) * itemsperpage));
}
resnav += "\">&laquo;</a></li>";
}
@ -66,7 +73,11 @@ function renderPaginationButtons(offset, itemsperpage, totalcount, navurlbase, l
resnav += "</a></li>";
} else {
resnav += "<li><a href=\"";
resnav += (navurlbase + "&amp;startRecord=" + (i * itemsperpage));
if (jsResort) {
resnav += ("javascript:numberedPage(" + (i) + ");");
} else {
resnav += (navurlbase + "&amp;startRecord=" + (i * itemsperpage));
}
resnav += "\">" + (i + 1) + "</a></li>";
}
}
@ -74,7 +85,11 @@ function renderPaginationButtons(offset, itemsperpage, totalcount, navurlbase, l
resnav += "<li class=\"disabled\"><a href=\"#\" title=\"Next page\">&raquo;</a></li>";
} else {
resnav += "<li><a id=\"nextpage\" title=\"Next page\" accesskey=\"n\" href=\"";
resnav += (navurlbase + "&amp;startRecord=" + ((thispage + 1) * itemsperpage));
if (jsResort) {
resnav += ("javascript:numberedPage(" + (thispage + 1) + ");");
} else {
resnav += (navurlbase + "&amp;startRecord=" + ((thispage + 1) * itemsperpage));
}
resnav += "\">&raquo;</a>";
}
resnav += "</ul>";
@ -95,7 +110,7 @@ function parseFormattedInt(strIntValue) {
return intValue;
}
function statistics(offset, itemscount, itemsperpage, totalcount, localIndexCount, remoteIndexCount, remotePeerCount, navurlbase, localQuery, feedRunning) {
function statistics(offset, itemscount, itemsperpage, totalcount, localIndexCount, remoteIndexCount, remotePeerCount, navurlbase, localQuery, feedRunning, jsResort) {
var totalcountIntValue = parseFormattedInt(totalcount);
var offsetIntValue = parseFormattedInt(offset);
var itemscountIntValue = parseFormattedInt(itemscount);
@ -173,8 +188,8 @@ function statistics(offset, itemscount, itemsperpage, totalcount, localIndexCoun
progresseBarElement.setAttribute('style',"width:" + percent + "%");
}
var resnavElement = document.getElementById("resNav");
if (resnavElement != null) {
resnavElement.innerHTML = renderPaginationButtons(offsetIntValue, itemsperpageIntValue, totalcountIntValue, navurlbase, localQuery);
if (resnavElement != null && !jsResort) {
resnavElement.innerHTML = renderPaginationButtons(offsetIntValue, itemsperpageIntValue, totalcountIntValue, navurlbase, localQuery, jsResort);
}
}

@ -0,0 +1,342 @@
var itemCount = 0;
var highestRanking = Infinity;
var displayPage = function() {
// For every search item that has already been displayed...
$("#resultscontainer").find(".searchresults").each( function(i) {
// Apply the "earlierpage" class IFF the item is from an earlier page.
$(this).toggleClass("earlierpage", parseFloat($(this).data("ranking")) > highestRanking);
});
// For every search item from an earlier page...
$("#resultscontainer").find(".searchresults.earlierpage").each( function(i) {
// Hide the item
$(this).removeClass("currentpage");
$(this).css('animation', '1s 1 forwards hide');
});
// For every search item from a current or later page...
$("#resultscontainer").find(".searchresults:not(.earlierpage)").each( function(i) {
// If we now have too many results, hide the lowest-ranking ones.
if (i >= requestedResults) {
$(this).removeClass("currentpage");
$(this).css('animation', '1s 1 forwards hide');
}
else {
$(this).addClass("currentpage");
$(this).css('display', '');
$(this).css('animation', '1s 1 forwards show');
}
});
// TODO: The following statistical displays could maybe be moved to the latestinfo() call.
var offset = $("#resultscontainer").find(".searchresults.earlierpage").length + 1;
var itemscount = $("#resultscontainer").find(".searchresults.earlierpage").length + $("#resultscontainer").find(".searchresults.currentpage").length;
// TODO: This seems to often be smaller than the "totalcount" that statistics() ends up with. Why is that?
var totalcount = $("#resultscontainer").find(".searchresults").length;
$("#offset").html(offset);
$("#itemscount").html(itemscount);
$("#resNav").html(renderPaginationButtons(offset, requestedResults, totalcount, null, theLocalQuery, true));
//latestinfo();
console.log("Showing results " + ($("#resultscontainer").find(".searchresults.earlierpage").length + 1) + " - " + ($("#resultscontainer").find(".searchresults.earlierpage").length + requestedResults) + " out of " + $("#resultscontainer").find(".searchresults").length + "; notEarlierPage = " + $("#resultscontainer").find(".searchresults:not(.earlierpage)").length);
};
var earlierPage = function() {
// Find all items that are on an earlier page.
var allEarlierItems = $("#resultscontainer").find(".searchresults.earlierpage");
// If going back one page would put us at the beginning...
if (allEarlierItems.length <= requestedResults) {
highestRanking = Infinity;
}
// If going back one page would still be in the middle of the results...
else {
var earlierItem = allEarlierItems.get().reverse()[ requestedResults - 1 ];
highestRanking = parseFloat($(earlierItem).data("ranking"));
console.log("highestRanking is now " + highestRanking);
}
// Update the display to show the new page.
displayPage();
};
var laterPage = function() {
// Find all items that are on a later page.
var allCurrentAndLaterItems = $("#resultscontainer").find(".searchresults:not(.earlierpage)");
// If going forward one page would put us past the end...
if (allCurrentAndLaterItems.length <= requestedResults) {
return;
}
// If going forward one page would still be in the middle of the results...
else {
var laterItem = allCurrentAndLaterItems.get(requestedResults);
highestRanking = parseFloat($(laterItem).data("ranking"));
console.log("highestRanking is now " + highestRanking);
}
// Update the display to show the new page.
displayPage();
};
// pageNumber starts at 0.
var numberedPage = function(pageNumber) {
// Find all items.
var allItems = $("#resultscontainer").find(".searchresults");
var itemNumber = pageNumber * requestedResults;
// Check if the item number is too high.
while ( allItems.length - 1 < itemNumber) {
itemNumber = itemNumber - requestedResults;
}
// If the beginning of results is requested, set highestRanking to Infinity.
if ( itemNumber <= 0 ) {
highestRanking = Infinity;
}
else {
var item = allItems.get(itemNumber);
highestRanking = parseFloat($(item).data("ranking"));
}
console.log("highestRanking is now " + highestRanking);
// Update the display to show the new page.
displayPage();
};
var processSidebarNavProtocols = function(navProtocolsOld, navProtocolsNew) {
navProtocolsOld.find(".btn-group-xs").each( function(index, oldProtocol) {
var protocolId = $(oldProtocol).attr("id");
var newProtocol = navProtocolsNew.find("#" + protocolId);
// Check whether the protocol has been removed in the new sidebar.
if (newProtocol.length === 0) {
console.log("Deleting nav-protocol...");
$(oldProtocol).hide(1000);
}
} );
navProtocolsNew.find(".btn-group-xs").each( function(index, newProtocol) {
var protocolId = $(newProtocol).attr("id");
var oldProtocol = navProtocolsOld.find("#" + protocolId);
// Check whether the protocol exists in both the new and old sidebar
if (oldProtocol.length === 1) {
// Replace the HTML.
// TODO: Look into smoother animations.
$(oldProtocol).html($(newProtocol).html()).show(1000);
}
// Check whether the protocol has been added in the new sidebar.
if (oldProtocol.length === 0) {
// We need to insert the protocol in the right position.
// TODO: Insert in the correct position instead of the end.
$(newProtocol).hide();
$(navProtocolsOld).append($(newProtocol));
$(newProtocol).show(1000);
}
} );
};
// TODO: test this function
// This is for sidebar items that are <ul> elements with the "menugroup" class.
var processSidebarMenuGroup = function(listOld, listNew) {
if ( $(listNew).length === 1) {
if ( $(listOld).length < 1) {
console.warn("listOld doesn't exist, so can't replace it with listNew.");
return;
}
var childrenOld = $(listOld).children("li");
if ( childrenOld.length >= 2 ) {
// There are at least 2 <li> elements in the list.
// The first one is the heading, so skip that one.
var childToCheck = childrenOld[1];
if ( $(childToCheck).css("display") == "block" ) {
// The list has been expanded by the user already.
// That means we need to expand the new list to match.
// If we don't do this, the new list will be collapsed every time we update,
// which would annoy the user.
$(listNew).children("li").css("display", "block");
}
}
// TODO: animate
listOld.html(listNew.html());
}
};
var processSidebar = function(data) {
var oldSidebar = $("#sidebar");
var newSidebar = $('<div class="col-sm-4 col-md-3 sidebar" id="sidebar">\n\n' + data + '\n\n</div>');
/*
if( old_sidebar.html() == data ) {
console.log("Sidebar unchanged.");
return;
}
*/
/*
if( $.trim(old_sidebar.html()) == $.trim(data) ) {
console.log("Sidebar unchanged.");
return;
}
*/
//else if( $.trim(old_sidebar.html()) == $.trim("") ) {
if( oldSidebar.children().length === 0 ) {
console.log("Initializing sidebar...");
oldSidebar.html(newSidebar.html());
}
else {
console.log("Sidebar has changed, updating...");
var navProtocolsOld = $("#nav-protocols");
var navProtocolsNew = newSidebar.find("#nav-protocols");
if( navProtocolsNew.length === 1 ) {
processSidebarNavProtocols(navProtocolsOld, navProtocolsNew);
}
var tagCloudOld = $("#tagcloud");
var tagCloudNew = newSidebar.find("#tagcloud");
if ( tagCloudNew.length === 1 ) {
// TODO: animate
tagCloudOld.html(tagCloudNew.html());
}
var catLocationOld = $("#cat-location");
var catLocationNew = newSidebar.find("#cat-location");
if ( catLocationNew.length === 1 ) {
// TODO: animate
catLocationOld.html(catLocationNew.html());
}
// TODO: nav-dates
// domains (AKA providers)
// TODO: test domains
// TODO: we should assign an "id" attribute to the "domains" <ul>.
processSidebarMenuGroup($("#domains_0").parent(), newSidebar.find("#domains_0").parent());
// TODO: test languages
// TODO: we should assign an "id" attribute to the "languages" <ul>.
processSidebarMenuGroup($("#languages_0").parent(), newSidebar.find("#languages_0").parent());
// TODO: test authors
// TODO: we should assign an "id" attribute to the "authors" <ul>.
processSidebarMenuGroup($("#authors_0").parent(), newSidebar.find("#authors_0").parent());
// TODO: test Wiki Name Space
// TODO: we should assign an "id" attribute to the "namespace" <ul>.
processSidebarMenuGroup($("#namespace_0").parent(), newSidebar.find("#namespace_0").parent());
// TODO: test filetype
// TODO: we should assign an "id" attribute to the "filetype" <ul>.
processSidebarMenuGroup($("#filetype_0").parent(), newSidebar.find("#filetype_0").parent());
// TODO: navs
// TODO: nav-vocabulary
// TODO: nav-about
}
// TODO: figure out if a better timeout strategy is feasible
setTimeout(updateSidebar, 500);
};
var updateSidebar = function() {
$.get(
"yacysearchtrailer.html",
{
"eventID": theEventID,
},
processSidebar
);
//$("#sidebar").load("yacysearchtrailer.html", {"eventID": theEventID});
};
var processItem = function(data) {
var newItem = $(data).hide();
// If we didn't get a valid response from YaCy, wait 1 second and try again.
if( ! newItem.data("ranking") ) {
//console.log("Got undefined item, waiting 1 second...");
setTimeout(function() {
$.get(
"yacysearchitem.html",
{
eventID: theEventID,
item: itemCount
},
processItem
);
}, 1000);
return;
}
// For every search item that has already been displayed...
$("#resultscontainer").find(".searchresults").each( function(i) {
// If the existing search item is lower-ranked than the new item...
if (parseFloat($(this).data("ranking")) <= parseFloat(newItem.data("ranking")) ) {
// Insert new item before the existing item
newItem.insertBefore(this);
return false;
}
// If the new item is lower-ranked than all existing items...
else if (i == $("#resultscontainer").find(".searchresults").length - 1) {
// And if the new item (position i + 1) would be ranked 0 to requestedResults - 1...
if (i + 1 < requestedResults) {
// Insert new item at the end
newItem.appendTo("#resultscontainer");
return false;
}
// If the new item is too irrelevant to be displayed...
else {
// Insert new item at the end
newItem.appendTo("#resultscontainer");
console.log("Hiding search result because ranking " + newItem.data("ranking") + " too low.");
return false;
}
}
});
// Special case if this is the first search item...
if ($("#resultscontainer").find(".searchresults").length === 0) {
// Display the new item
newItem.appendTo("#resultscontainer");
}
displayPage();
if (itemCount === 0) {
updateSidebar();
}
// Increment itemCount and get another item.
itemCount++;
$.get(
"yacysearchitem.html",
{
eventID: theEventID,
item: itemCount
},
processItem
);
};

@ -12,6 +12,15 @@
<script type="text/javascript" src="js/highslide/highslide.js"></script>
<script type="text/javascript">hs.outlineType = 'rounded-white';</script>
<script type="text/javascript" src="env/bootstrap/js/typeahead.jquery.min.js"></script>
#(jsResort)#::
<script type="text/javascript">
var requestedResults = #[results]#;
var theEventID = "#[eventID]#";
var theLocalQuery = #[localQuery]#;
</script>
<script type="text/javascript" src="js/yacysort.js"></script>
<link rel="stylesheet" type="text/css" media="screen" href="yacysort.css" />
#(/jsResort)#
<script type="text/javascript">
var suggestMatcher = function() {
return function opensearch(q, cb) {
@ -31,7 +40,19 @@
});
};
};
$(document).ready(function() {
#(jsResort)#::
$.get(
"yacysearchitem.html",
{
eventID: theEventID,
item: itemCount
},
processItem
);
#(/jsResort)#
$('#search').typeahead({hint:false,highlight:true,minLength:1}, {
name: 'states',
displayKey: 'value',
@ -175,9 +196,14 @@ document.getElementById("Enter").innerHTML = "search again";
<!-- linklist begin -->
#(resultTable)#::<table width="100%"><tr class="TableHeader"><td width="30%">Media</td><td width="70%">URL</td></tr>#(/resultTable)#
#{results}#
<!--#include virtual="yacysearchitem.html?item=#[item]#&eventID=#[eventID]#" -->
#{/results}#
#(jsResort)#
#{results}#
<!--#include virtual="yacysearchitem.html?item=#[item]#&eventID=#[eventID]#" -->
#{/results}#
::
<div id="resultscontainer">
</div>
#(/jsResort)#
#(resultTable)#::</table>#(/resultTable)#
<!-- linklist end -->
@ -193,7 +219,10 @@ document.getElementById("Enter").innerHTML = "search again";
<div class="col-sm-4 col-md-3 sidebar" id="sidebar">
<!-- navigation begin -->
#(jsResort)#
<!--#include virtual="yacysearchtrailer.html?eventID=#[eventID]#" -->
::
#(/jsResort)#
<!-- navigation end -->
</div> <!-- close sidebar -->
@ -222,7 +251,11 @@ function latestinfo() {
}
if(rsp && rsp.offset != null) {
statistics(rsp.offset, rsp.itemscount, rsp.itemsperpage, rsp.totalcount, rsp.localIndexCount, rsp.remoteIndexCount, rsp.remotePeerCount, rsp.navurlBase, #[localQuery]#, rsp.feedRunning);
#(jsResort)#
statistics(rsp.offset, rsp.itemscount, rsp.itemsperpage, rsp.totalcount, rsp.localIndexCount, rsp.remoteIndexCount, rsp.remotePeerCount, rsp.navurlBase, #[localQuery]#, rsp.feedRunning, false);
::
statistics($("#resultscontainer .searchresults.earlierpage").length + 1, $("#resultscontainer .searchresults.earlierpage").length + $("#resultscontainer .searchresults.currentpage").length, rsp.itemsperpage, rsp.totalcount, rsp.localIndexCount, rsp.remoteIndexCount, rsp.remotePeerCount, rsp.navurlBase, #[localQuery]#, rsp.feedRunning, true);
#(/jsResort)#
if(rsp.feedRunning) {
/* Refresh statistics while server feeders are still running */
window.setTimeout(latestinfo, 1000);

@ -835,14 +835,22 @@ public class yacysearch {
QueryParams.navurlBase(RequestHeader.FileType.HTML, theQuery, null, true).append("&startRecord=")
.append(startRecord).append("&resortCachedResults=true").toString());
prop.put("jsResort", sb.getConfigBool("search.jsresort", false) );
prop.put("num-results_jsResort", sb.getConfigBool("search.jsresort", false) );
// generate the search result lines; the content will be produced by another servlet
for ( int i = 0; i < theQuery.itemsPerPage(); i++ ) {
prop.put("results_" + i + "_item", startRecord + i);
prop.put("results_" + i + "_eventID", theQuery.id(false));
prop.put("jsResort_results_" + i + "_item", startRecord + i);
prop.put("jsResort_results_" + i + "_eventID", theQuery.id(false));
}
prop.put("results", theQuery.itemsPerPage());
prop.put("jsResort_results", theQuery.itemsPerPage());
prop.put("resultTable", (contentdom == ContentDomain.APP || contentdom == ContentDomain.AUDIO || contentdom == ContentDomain.VIDEO) ? 1 : 0);
prop.put("eventID", theQuery.id(false)); // for bottomline
prop.put("jsResort_eventID", theQuery.id(false));
// process result of search
if ( !filtered.isEmpty() ) {
@ -864,6 +872,7 @@ public class yacysearch {
prop.put("depth", "0");
prop.put("localQuery", theSearch.query.isLocal() ? "1" : "0");
prop.put("jsResort_localQuery", theSearch.query.isLocal() ? "1" : "0");
}
prop.put("focus", focus ? 1 : 0); // focus search field

@ -1,5 +1,5 @@
#(content)#::
<div class="searchresults">
<div class="searchresults" data-ranking="#[ranking]#">
<h4 class="linktitle">
#(favicon)#::
<img width="16" height="16" src="#[faviconUrl]#" id="f#[urlhash]#" class="favicon" style="width:16px; height:16px;" alt="" />

@ -279,6 +279,7 @@ public class yacysearchitem {
prop.put("content_showSnapshots_link", snapshotPaths.iterator().next().getAbsolutePath());
}
prop.put("content_showRanking_ranking", Float.toString(result.score()));
prop.put("content_ranking", Float.toString(result.score()));
}
prop.put("content_urlhexhash", Seed.b64Hash2hexHash(urlhash));
prop.putHTML("content_urlname", nxTools.shortenURLString(result.urlname(), MAX_URL_LENGTH));

@ -69,9 +69,9 @@
#(nav-protocols)#::
<p class="navbutton"></p>
<div class="btn-group btn-group-justified">
<div id="nav-protocols" class="btn-group btn-group-justified">
#{element}#
<div class="btn-group btn-group-xs"><button type="button" class="btn btn-default#(on)#:: active#(/on)#"#(onclick)# onclick="window.location.href='#[url]#';"::#(/onclick)#>#[name]# (#[count]#)</button></div>
<div id="nav-protocols-#[name]#" class="btn-group btn-group-xs"><button type="button" class="btn btn-default#(on)#:: active#(/on)#"#(onclick)# onclick="window.location.href='#[url]#';"::#(/onclick)#>#[name]# (#[count]#)</button></div>
#{/element}#
</div>
#(/nav-protocols)#
@ -83,7 +83,7 @@
#(/nav-topics)#
#(cat-location)#::
<ul class="nav nav-sidebar menugroup">
<ul id="cat-location" class="nav nav-sidebar menugroup">
<li><h3>Location</h3></li>
<li>
<a href="yacysearch_location.html?query=#[queryenc]#" class="MenuItemLink">

@ -0,0 +1,41 @@
@keyframes show {
0% {
transform: scale(0);
max-height: 0;
opacity: 0;
padding-top: 0;
}
50% {
transform: scale(1);
opacity: 1;
}
99% {
max-height: 500px;
padding-top: 1em;
}
100% {
max-height: none;
}
}
@keyframes hide {
0% {
max-height: 500px;
padding-top: 1em;
}
50% {
transform: scale(1);
opacity: 1;
}
100% {
transform: scale(0);
max-height: 0;
opacity: 0;
padding-top: 0;
}
}
.searchresults {
overflow: hidden;
transform-origin: top left;
}
Loading…
Cancel
Save