// NPM imports import React, { Component, PropTypes } from "react"; import { Link } from "react-router"; import CSSModules from "react-css-modules"; import { defineMessages, injectIntl, intlShape, FormattedMessage, FormattedHTMLMessage } from "react-intl"; // Local imports import { computePaginationBounds, filterInt, messagesMap } from "../../utils"; // Translations import commonMessages from "../../locales/messagesDescriptors/common"; import messages from "../../locales/messagesDescriptors/elements/Pagination"; // Styles import css from "../../styles/elements/Pagination.scss"; // Define translations const paginationMessages = defineMessages(messagesMap(Array.concat([], commonMessages, messages))); /** * Pagination button bar */ class PaginationCSSIntl extends Component { constructor(props) { super (props); // Bind this this.goToPage = this.goToPage.bind(this); this.dotsOnClick = this.dotsOnClick.bind(this); this.dotsOnKeyDown = this.dotsOnKeyDown.bind(this); this.cancelModalBox = this.cancelModalBox.bind(this); } /** * Handle click on the "go to page" button in the modal. */ goToPage(e) { e.preventDefault(); // Parse and check page number const pageNumber = filterInt(this.refs.pageInput.value); if (pageNumber && !isNaN(pageNumber) && pageNumber > 0 && pageNumber <= this.props.nPages) { // Remove error class from input form this.refs.pageFormGroup.classList.remove("has-error"); this.refs.pageFormGroup.classList.add("has-success"); // Hide the modal and go to page $(this.refs.paginationModal).modal("hide"); this.props.goToPage(pageNumber); } else { // Set error class on input form this.refs.pageFormGroup.classList.add("has-error"); this.refs.pageFormGroup.classList.remove("has-success"); return; } } /** * Handle click on the ellipsis dots. */ dotsOnClick() { // Show modal $(this.refs.paginationModal).modal(); } /** * Bind key down events on ellipsis dots for a11y. */ dotsOnKeyDown(e) { e.preventDefault; const code = e.keyCode || e.which; if (code == 13 || code == 32) { // Enter or Space key this.dotsOnClick(); // Fire same event as onClick } } /** * Handle click on "cancel" in the modal box. */ cancelModalBox() { // Hide modal $(this.refs.paginationModal).modal("hide"); } render() { const { formatMessage } = this.props.intl; // Get bounds const { lowerLimit, upperLimit } = computePaginationBounds(this.props.currentPage, this.props.nPages); // Store buttons let pagesButton = []; let key = 0; // key increment to ensure correct ordering // If lower limit is above 1, push 1 and ellipsis if (lowerLimit > 1) { pagesButton.push(
  • ); key++; // Always increment key after a push if (lowerLimit > 2) { // Eventually push "…" pagesButton.push(
  • ); key++; } } // Main buttons, between lower and upper limits for (let i = lowerLimit; i < upperLimit; i++) { let classNames = ["page-item"]; let currentSpan = null; if (this.props.currentPage == i) { classNames.push("active"); currentSpan = (); } const title = formatMessage(paginationMessages["app.pagination.goToPageWithoutMarkup"], { pageNumber: i }); pagesButton.push(
  • {currentSpan}
  • ); key++; } // If upper limit is below the total number of page, show last page button if (upperLimit < this.props.nPages) { if (upperLimit < this.props.nPages - 1) { // Eventually push "…" pagesButton.push(
  • ); key++; } const title = formatMessage(paginationMessages["app.pagination.goToPageWithoutMarkup"], { pageNumber: this.props.nPages }); // Push last page pagesButton.push(
  • ); } // If there are actually some buttons, show them if (pagesButton.length > 1) { return (

    ); } return null; } } PaginationCSSIntl.propTypes = { currentPage: PropTypes.number.isRequired, goToPage: PropTypes.func.isRequired, buildLinkToPage: PropTypes.func.isRequired, nPages: PropTypes.number.isRequired, intl: intlShape.isRequired, }; export default injectIntl(CSSModules(PaginationCSSIntl, css));