blob: 3539e67a872852e87590d55d41086fc94577f718 [file] [log] [blame]
/**
* @module module/pagination-sk
* @description <h2><code>pagination-sk</code></h2>
*
* Widget to let user page forward and backward. Page buttons will be
* disabled/enabled depending on the offset/total/page_size values.
*
* Compatible with the server code httputils.PaginationParams.
*
* @attr offset {int} indicates the offset into the list of the items we are paged to.
*
* @attr page_size {int} the number of items we go forward/backward on a single page.
*
* @attr total {int} the total number of items that can be paged through or MANY if the
* server doesn't know.
*
* @evt page-changed - Sent when user pages forward or backward. Check
* e.detail.delta for how many pages changed and which direction.
*/
import { html } from 'lit-html'
import { define } from 'elements-sk/define'
import { ElementSk } from '../../../infra-sk/modules/ElementSk'
import 'elements-sk/styles/buttons'
const template = (ele) => html`
<button ?disabled=${ele._currPage() <= 1}
title="Go to previous page of results."
@click=${() => ele._page(-1)}
class="prev">
Prev
</button>
<div class=counter>
page ${ele._currPage()}
</div>
<button ?disabled=${!canGoNext(ele.total, ele.offset + ele.page_size)}
title="Go to next page of results."
@click=${() => ele._page(1)}
class="next">
Next
</button>
<button ?disabled=${!canGoNext(ele.total, ele.offset + 5 * ele.page_size)}
title="Skip forward 5 pages of results."
@click=${() => ele._page(5)}
class="skip">
+5
</button>
`;
// MANY (2^31-1, aka math.MaxInt32) is a special value meaning the
// server doesn't know how many items there are, only that it's more
// than are currently being displayed.
const MANY = 2147483647
function canGoNext(total, next) {
if (total === MANY) {
return true;
}
return next <= total;
}
define('pagination-sk', class extends ElementSk {
constructor() {
super(template);
}
connectedCallback() {
super.connectedCallback();
this._upgradeProperty('offset');
this._upgradeProperty('page_size');
this._upgradeProperty('total');
this._render();
}
static get observedAttributes() {
return ['offset', 'page_size', 'total'];
}
/** @prop offset {int} Reflects offset attribute for convenience. */
get offset() { return +this.getAttribute('offset'); }
set offset(val) { this.setAttribute('offset', +val); }
/** @prop page_size {int} Reflects page_size attribute for convenience. */
get page_size() { return +this.getAttribute('page_size'); }
set page_size(val) { this.setAttribute('page_size', +val); }
/** @prop total {int} Reflects total attribute for convenience. */
get total() { return +this.getAttribute('total'); }
set total(val) { this.setAttribute('total', +val); }
attributeChangedCallback() {
this._render();
}
_currPage() {
return Math.round(this.offset/this.page_size) + 1;
}
_page(n) {
this.dispatchEvent(new CustomEvent('page-changed', { detail: {
delta: n,
}, bubbles: true}));
}
});