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
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))
|
|
|