:- module(html_paginator, [ html_paginator//3 ]). :- use_module(library(http/http_wrapper)). :- use_module(library(http/http_host)). :- use_module(library(http/html_write)). % html_paginator(+NumberOfResults, +Offset, +Limit) % % Emit HTML paginator. html_paginator(Total, _Offset, Limit) --> { Total < Limit }, !. html_paginator(Total, Offset, Limit) --> { http_current_request(Request), request_url_components(Request, URLComponents), Pages is ceiling(Total/Limit), ActivePage is floor(Offset/Limit), ( ActivePage < 9 -> EndPage is min(10, Pages) ; EndPage is min(10+ActivePage, Pages) ), StartPage is max(0, EndPage-20), ( select(search(Search0), URLComponents, Cs) -> delete(Search0, offset=_, Search) ; Search = Search0 ), parse_url(URL, [search(Search)|Cs]), ( Search = [] -> Delim = '?' ; Delim = '&' ) }, prev_page(ActivePage, Limit, URL, Delim), html_pages(StartPage, EndPage, Limit, URL, Delim, ActivePage), next_page(ActivePage, Pages, Limit, URL, Delim). prev_page(0, _, _, _) --> !. prev_page(Active, Limit, URL, Delim) --> { Offset is (Active-1)*Limit, First = 0 }, html([span(class(first), a(href(URL+Delim+'offset='+First), '<<')), span(class(prev), a(href(URL+Delim+'offset='+Offset), '<'))]). next_page(_, 0, _, _, _) --> !. next_page(Active, Last, _, _, _) --> { Active is Last-1 }, !. next_page(Active, Last, Limit, URL, Delim) --> { Offset is (Active+1)*Limit, LastOffset is (Last-1)*Limit }, html([span(class(next), a(href(URL+Delim+'offset='+Offset), '>')), span(class(last), a(href(URL+Delim+'offset='+LastOffset), '>>'))]). html_pages(N, N, _, _, _, _) --> !. html_pages(N, Pages, Limit, URL, Delim, ActivePage) --> { N1 is N+1, Offset is N*Limit, ( N = ActivePage -> Class = active ; Class = '' ) }, html(span(class(Class), a(href(URL+Delim+'offset='+Offset), N1))), html_pages(N1, Pages, Limit, URL, Delim, ActivePage). %% request_url_components(+Request, -URLComponents) % % URLComponents contains all element in Request that together % create the request URL. request_url_components(Request, [ protocol(http), host(Host), port(Port), path(Path), search(Search) ]) :- http_current_host(Request, Host, Port, [ global(false) ]), ( option(x_redirected_path(Path), Request) -> true ; option(path(Path), Request, /) ), option(search(Search), Request, []).