A website for producing interactive charts without writing a single line of code. Built with Common Lisp and Python. https://charts.craigoates.net
You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
 
 
 
 

76 lines
2.7 KiB

(defpackage #:pagination
(:use #:cl)
(:export #:make-pagination))
(in-package #:pagination)
#| Found This Code on The Internet
================================================================================
Original Blog Post:
https://lisp-journey.gitlab.io/blog/lisp-for-the-web-pagination-and-cleaning-up-html/
Pagination Source Code:
https://gitlab.com/vindarel/abstock/-/blob/master/src/pagination.lisp
Djula HTML Template Code:
https://gitlab.com/vindarel/abstock/-/blob/master/src/templates/includes/pagination.html
I've modified the code a little bit to fit my needs but it's, for the most part,
as I found it (`BUTTON-RANGE' is the main thing I've added).
|#
(defun make-pagination (&key (page 1) (nb-elements 0) (page-size 200)
(max-nb-buttons 5))
"From a current page number, a total number of elements, a page size,
return a dict with all of that, and the total number of pages.
Example:
(get-pagination :nb-elements 1001)
;; =>
(dict
:PAGE 1
:NB-ELEMENTS 1001
:PAGE-SIZE 200
:NB-PAGES 6
:TEXT-LABEL \"Page 1 / 6\"
)
"
(let* ((nb-pages (get-nb-pages nb-elements page-size))
(max-nb-buttons (min nb-pages max-nb-buttons))
(button-list (build-pagination-list page max-nb-buttons)))
(serapeum:dict :page page
:nb-elements nb-elements
:page-size page-size
:nb-pages nb-pages
:button-range button-list
:max-nb-buttons max-nb-buttons
:text-label (format nil
"Page ~a / ~a" page nb-pages))))
(defun get-nb-pages (length page-size)
"Given a total number of elements and a page size, compute how many pages fit in there.
(if there's a remainder, add 1 page)"
(multiple-value-bind (nb-pages remainder)
(floor length page-size)
(if (plusp remainder)
(1+ nb-pages)
nb-pages)))
(defun build-pagination-list (current-page max-nb-buttons)
"Creates a list of numbers with values before and after `CURRENT-PAGE'.
This is a bit hacky because the list needs to have checks in the HTML
template (djula) to make sure it doesn't render negative numbers or
display page number beyond the maximun number of pages available,
`MAX-NB-BUTTONS'. With that said, it allows you to create a 'floating
list' of page numbers which updates itself based on what page the
viewer is on."
(let* ((start (- current-page max-nb-buttons))
(end (+ current-page max-nb-buttons)))
(range end :min start :step 1)))
(defun range (max &key (min 0) (step 1))
"Creates a list of number starting from `MIN' upto `MAX'.
Use `STEP' to specify the increment value for each entry. This is
basically the range function from Python."
(loop for n from min below max by step
collect n))