diff --git a/htroot/js/yacysearch.js b/htroot/js/yacysearch.js
index 09305031d..dc9a19868 100644
--- a/htroot/js/yacysearch.js
+++ b/htroot/js/yacysearch.js
@@ -62,7 +62,8 @@ function renderPaginationButtons(buttonsList, offset, itemsperpage, totalcount,
var firstPage = thispage - (thispage % 10);
var prevPageElement = buttons[0];
- var prevPageLink = prevPageElement.firstChild;
+ var links = prevPageElement.getElementsByTagName("a");
+ var prevPageLink = links.length == 1 ? links[0] : null;
if (thispage == 0) {
/* First page : the prev page button is disabled */
prevPageElement.className = "disabled";
@@ -83,14 +84,12 @@ function renderPaginationButtons(buttonsList, offset, itemsperpage, totalcount,
}
}
- var nextPageElement = buttons[buttons.length - 1];
-
var totalPagesNb = Math.floor(1 + ((totalcount - 1) / itemsperpage));
var numberofpages = Math.min(10, totalPagesNb - firstPage);
if (!numberofpages) {
numberofpages = 10;
}
- if(numberofpages > 1) {
+ if(totalPagesNb > 1 && numberofpages >= 1) {
buttonsList.className = "pagination";
} else {
/* Hide the pagination buttons when there is less than one page of results */
@@ -140,7 +139,9 @@ function renderPaginationButtons(buttonsList, offset, itemsperpage, totalcount,
buttonsList.removeChild(buttons[buttons.length - 2]);
}
- var nextPageLink = nextPageElement.firstChild;
+ var nextPageElement = buttons[buttons.length - 1];
+ links = nextPageElement.getElementsByTagName("a");
+ var nextPageLink = links.length == 1 ? links[0] : null;
if ((localQuery && thispage >= (totalPagesNb - 1))
|| (!localQuery && thispage >= (numberofpages - 1))) {
/* Last page on a local query, or last fetchable page in p2p mode : the next page button is disabled */
@@ -181,7 +182,7 @@ function parseFormattedInt(strIntValue) {
return intValue;
}
-function statistics(offset, itemscount, itemsperpage, totalcount, localIndexCount, remoteIndexCount, remotePeerCount, navurlbase, localQuery, feedRunning, jsResort) {
+function statistics(offset, itemscount, itemsperpage, totalcount, localIndexCount, remoteIndexCount, remotePeerCount, navurlbase, localQuery, feedRunning, jsResort, updatePagination) {
var totalcountIntValue = parseFormattedInt(totalcount);
var offsetIntValue = parseFormattedInt(offset);
var itemscountIntValue = parseFormattedInt(itemscount);
@@ -259,7 +260,7 @@ function statistics(offset, itemscount, itemsperpage, totalcount, localIndexCoun
progresseBarElement.setAttribute('style',"width:" + percent + "%");
}
var buttonsList = document.getElementById("paginationButtons");
- if (buttonsList != null && !jsResort) {
+ if (buttonsList != null && !jsResort && updatePagination) {
renderPaginationButtons(buttonsList, offsetIntValue, itemsperpageIntValue, totalcountIntValue, navurlbase, localQuery, jsResort);
}
}
diff --git a/htroot/yacysearch.html b/htroot/yacysearch.html
index 824d4d23d..4d8cb281c 100644
--- a/htroot/yacysearch.html
+++ b/htroot/yacysearch.html
@@ -255,19 +255,7 @@ document.getElementById("Enter").innerHTML = "search again";
#(resultTable)#::::#(/resultTable)#
-#(num-results)#
- ::
- ::
- ::
-
-
-
- ::
-#(/num-results)#
+
@@ -306,9 +294,9 @@ function latestinfo() {
if(rsp && rsp.offset != null) {
#(jsResort)#
- statistics(rsp.offset, rsp.itemscount, rsp.itemsperpage, rsp.totalcount, rsp.localIndexCount, rsp.remoteIndexCount, rsp.remotePeerCount, rsp.navurlBase, #[localQuery]#, rsp.feedRunning, false);
+ statistics(rsp.offset, rsp.itemscount, rsp.itemsperpage, rsp.totalcount, rsp.localIndexCount, rsp.remoteIndexCount, rsp.remotePeerCount, rsp.navurlBase, #[localQuery]#, rsp.feedRunning, false, true);
::
- 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);
+ 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, false);
#(/jsResort)#
if(rsp.feedRunning) {
/* Refresh statistics while server feeders are still running */
diff --git a/htroot/yacysearchpagination.html b/htroot/yacysearchpagination.html
new file mode 100644
index 000000000..00b550f3d
--- /dev/null
+++ b/htroot/yacysearchpagination.html
@@ -0,0 +1,22 @@
+#(pagination)#
+ ::
+
+
+
+#(/pagination)#
\ No newline at end of file
diff --git a/htroot/yacysearchpagination.java b/htroot/yacysearchpagination.java
new file mode 100644
index 000000000..52ba39c26
--- /dev/null
+++ b/htroot/yacysearchpagination.java
@@ -0,0 +1,135 @@
+
+// yacysearchpagination.java
+// ---------------------------
+// Copyright 2019 by luccioman; https://github.com/luccioman
+//
+// This is a part of YaCy, a peer-to-peer based web search engine
+//
+// LICENSE
+//
+// This program is free software; you can redistribute it and/or modify
+// it under the terms of the GNU General Public License as published by
+// the Free Software Foundation; either version 2 of the License, or
+// (at your option) any later version.
+//
+// This program is distributed in the hope that it will be useful,
+// but WITHOUT ANY WARRANTY; without even the implied warranty of
+// MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+// GNU General Public License for more details.
+//
+// You should have received a copy of the GNU General Public License
+// along with this program; if not, write to the Free Software
+// Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA
+
+import net.yacy.cora.protocol.RequestHeader;
+import net.yacy.http.servlets.TemplateMissingParameterException;
+import net.yacy.search.Switchboard;
+import net.yacy.search.SwitchboardConstants;
+import net.yacy.search.query.QueryParams;
+import net.yacy.search.query.SearchEvent;
+import net.yacy.search.query.SearchEventCache;
+import net.yacy.server.serverObjects;
+import net.yacy.server.serverSwitch;
+
+/**
+ * Render yacysearch results page fragment containing pagination links.
+ */
+public class yacysearchpagination {
+
+ /** The maximum number of pagination links to render */
+ private static final int MAX_PAGINATION_LINKS = 10;
+
+ /**
+ * @param header servlet request headers
+ * @param post request parameters
+ * @param env server environment
+ * @return the servlet answer object
+ */
+ public static serverObjects respond(final RequestHeader header, final serverObjects post, final serverSwitch env) {
+ if (post == null) {
+ throw new TemplateMissingParameterException("The eventID parameter is required");
+ }
+
+ final serverObjects prop = new serverObjects();
+ final Switchboard sb = (Switchboard) env;
+ final String eventID = post.get("eventID");
+ if (eventID == null) {
+ throw new TemplateMissingParameterException("The eventID parameter is required");
+ }
+ final boolean jsResort = post.getBoolean("jsResort");
+ final boolean authFeatures = post.containsKey("auth");
+ final int defaultItemsPerPage = sb.getConfigInt(SwitchboardConstants.SEARCH_ITEMS, 10);
+
+ /* Detailed rules on items per page limits are handle in yacysearch.html */
+ int itemsPerPage = Math.max(1, post.getInt("maximumRecords", defaultItemsPerPage));
+
+ final SearchEvent theSearch = SearchEventCache.getEvent(eventID);
+ if (theSearch == null) {
+ /*
+ * the event does not exist in cache
+ */
+ prop.put("pagination", false);
+ } else {
+ prop.put("pagination", true);
+
+ final RequestHeader.FileType fileType = header.fileType();
+
+ if(jsResort) {
+ /* Pagination links are processed on browser side : just prepare prev and next buttons */
+ prop.put("pagination_hidePagination", true);
+ prop.put("pagination_prevDisabled", true);
+ prop.put("pagination_pages", 0);
+ prop.put("pagination_nextDisabled", true);
+ } else {
+ final int startRecord = post.getInt("startRecord", post.getInt("offset", post.getInt("start", 0)));
+ final int totalCount = theSearch.getResultCount();
+
+ final int activePage = (int) Math.floor(startRecord / (double) itemsPerPage);
+ final int firstLinkedPage = activePage - (activePage % MAX_PAGINATION_LINKS);
+ final int totalPagesNb = (int) Math.floor(1 + ((totalCount - 1) / (double) itemsPerPage));
+ final int displayedPagesNb = Math.min(MAX_PAGINATION_LINKS, totalPagesNb - firstLinkedPage);
+
+
+ prop.put("pagination_prevDisabled", activePage == 0);
+ prop.putUrlEncoded(fileType, "pagination_prevDisabled_prevHref", QueryParams
+ .navurl(fileType, Math.max(activePage - 1, 0), theSearch.query, null, false, authFeatures).toString());
+
+ prop.put("pagination_hidePagination", totalPagesNb <= 1 || displayedPagesNb < 1);
+
+ for (int i = 0; i < displayedPagesNb; i++) {
+ if (activePage == (firstLinkedPage + i)) {
+ prop.put("pagination_pages_" + i + "_active", true);
+ } else {
+ prop.put("pagination_pages_" + i + "_active", false);
+ prop.put("pagination_pages_" + i + "_active_pageIndex", (firstLinkedPage + i));
+ prop.putUrlEncoded(fileType, "pagination_pages_" + i + "_active_href",
+ QueryParams
+ .navurl(fileType, firstLinkedPage + i, theSearch.query, null, false, authFeatures)
+ .toString());
+ }
+ prop.put("pagination_pages_" + i + "_pageNum", firstLinkedPage + i + 1L);
+ }
+ prop.put("pagination_pages", displayedPagesNb);
+
+ final boolean localQuery = theSearch.query.isLocal();
+ if ((localQuery && activePage >= (totalPagesNb - 1))
+ || (!localQuery && activePage >= (displayedPagesNb - 1))) {
+ /*
+ * Last page on a local query, or last fetchable page in p2p mode : the next
+ * page button is disabled
+ */
+ prop.put("pagination_nextDisabled", true);
+ } else {
+ prop.put("pagination_nextDisabled", false);
+ prop.putUrlEncoded(fileType, "pagination_nextDisabled_nextHref", QueryParams
+ .navurl(fileType, activePage + 1, theSearch.query, null, false, authFeatures).toString());
+ }
+ }
+
+
+ }
+
+ return prop;
+ }
+
+}
\ No newline at end of file