:- 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, []).