diff options
| -rw-r--r-- | defaults/yacy.init | 5 | ||||
| -rw-r--r-- | htroot/js/yacysort.js | 139 | ||||
| -rw-r--r-- | htroot/yacysearch.html | 42 | ||||
| -rw-r--r-- | htroot/yacysearch.java | 9 |
4 files changed, 190 insertions, 5 deletions
diff --git a/defaults/yacy.init b/defaults/yacy.init index a9dc0abfc..a6365f18f 100644 --- a/defaults/yacy.init +++ b/defaults/yacy.init @@ -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
diff --git a/htroot/js/yacysort.js b/htroot/js/yacysort.js new file mode 100644 index 000000000..4ed983506 --- /dev/null +++ b/htroot/js/yacysort.js @@ -0,0 +1,139 @@ +var itemCount = 0; +var highestRanking = Infinity; + +var displayPage = function() { + // For every search item that has already been displayed... + $("#resultscontainer .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 .searchresults.earlierpage").each( function(i) { + // Hide the item + $(this).removeClass("currentpage"); + $(this).hide(1000); + }); + + // For every search item from a current or later page... + $("#resultscontainer .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).hide(1000); + } + else { + $(this).addClass("currentpage"); + $(this).show(1000); + } + }); + + $("#offset").html($("#resultscontainer .searchresults.earlierpage").length + 1); + $("#itemscount").html($("#resultscontainer .searchresults.earlierpage").length + $("#resultscontainer .searchresults.currentpage").length); + + console.log("Showing results " + ($("#resultscontainer .searchresults.earlierpage").length + 1) + " - " + ($("#resultscontainer .searchresults.earlierpage").length + requestedResults) + " out of " + $("#resultscontainer .searchresults").length + "; notEarlierPage = " + $("#resultscontainer .searchresults:not(.earlierpage)").length); +}; + +var earlierPage = function() { + // Find all items that are on an earlier page. + var allEarlierItems = $("#resultscontainer .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 .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(); +}; + +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 .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 .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 .searchresults").length === 0) { + // Display the new item + newItem.appendTo("#resultscontainer"); + } + + displayPage(); + + // Increment itemCount and get another item. + itemCount++; + $.get( + "yacysearchitem.html", + { + eventID: theEventID, + item: itemCount + }, + processItem + ); +}; diff --git a/htroot/yacysearch.html b/htroot/yacysearch.html index 8a46a2041..437bfccb5 100644 --- a/htroot/yacysearch.html +++ b/htroot/yacysearch.html @@ -12,6 +12,13 @@ <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]#"; + </script> + <script type="text/javascript" src="js/yacysort.js"></script> + #(/jsResort)# <script type="text/javascript"> var suggestMatcher = function() { return function opensearch(q, cb) { @@ -31,7 +38,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 +194,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 --> @@ -185,7 +209,11 @@ document.getElementById("Enter").innerHTML = "search again"; :: :: :: - <span id="resNav" class="col-sm-12 col-md-12" style="display: inline;"></span> + #(jsResort)# + <span id="resNav" class="col-sm-12 col-md-12" style="display: inline;"></span> + :: + <p><br><br><a href="javascript:earlierPage();">Prev Page</a> <a href="javascript:laterPage();">Next Page</a></p> + #(/jsResort)# :: #(/num-results)# @@ -222,7 +250,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); + :: + 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); + #(/jsResort)# if(rsp.feedRunning) { /* Refresh statistics while server feeders are still running */ window.setTimeout(latestinfo, 1000); diff --git a/htroot/yacysearch.java b/htroot/yacysearch.java index 79bed9769..4c2de7d7a 100644 --- a/htroot/yacysearch.java +++ b/htroot/yacysearch.java @@ -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 |
