UNPKG

devextreme

Version:

HTML5 JavaScript Component Suite for Responsive Web Development

569 lines (568 loc) • 24.2 kB
/** * DevExtreme (ui/pager.js) * Version: 18.1.3 * Build date: Tue May 15 2018 * * Copyright (c) 2012 - 2018 Developer Express Inc. ALL RIGHTS RESERVED * Read about DevExtreme licensing here: https://js.devexpress.com/Licensing/ */ "use strict"; var $ = require("../core/renderer"), eventsEngine = require("../events/core/events_engine"), Class = require("../core/class"), stringUtils = require("../core/utils/string"), registerComponent = require("../core/component_registrator"), commonUtils = require("../core/utils/common"), each = require("../core/utils/iterator").each, typeUtils = require("../core/utils/type"), extend = require("../core/utils/extend").extend, clickEvent = require("../events/click"), messageLocalization = require("../localization/message"), Widget = require("./widget/ui.widget"), SelectBox = require("./select_box"), NumberBox = require("./number_box"), eventUtils = require("../events/utils"); var PAGES_LIMITER = 4, PAGER_CLASS = "dx-pager", PAGER_PAGE_CLASS = "dx-page", PAGER_PAGES_CLASS = "dx-pages", LIGHT_MODE_CLASS = "dx-light-mode", LIGHT_PAGES_CLASS = "dx-light-pages", PAGER_PAGE_INDEX_CLASS = "dx-page-index", PAGER_PAGES_COUNT_CLASS = "dx-pages-count", PAGER_SELECTION_CLASS = "dx-selection", PAGER_PAGE_SEPARATOR_CLASS = "dx-separator", PAGER_PAGE_SIZES_CLASS = "dx-page-sizes", PAGER_PAGE_SIZE_CLASS = "dx-page-size", PAGER_NAVIGATE_BUTTON = "dx-navigate-button", PAGER_PREV_BUTTON_CLASS = "dx-prev-button", PAGER_NEXT_BUTTON_CLASS = "dx-next-button", PAGER_INFO_CLASS = "dx-info", PAGER_INFO_TEXT_CLASS = "dx-info-text", PAGER_BUTTON_DISABLE_CLASS = "dx-button-disable"; var Page = Class.inherit({ ctor: function(value, index) { var that = this; that.index = index; that._$page = $("<div>").text(value).addClass(PAGER_PAGE_CLASS) }, value: function(_value) { var that = this; if (typeUtils.isDefined(_value)) { that._$page.text(_value) } else { var text = that._$page.text(); if (typeUtils.isNumeric(text)) { return parseInt(text) } else { return text } } }, element: function() { return this._$page }, select: function(value) { this._$page.toggleClass(PAGER_SELECTION_CLASS, value) }, render: function(rootElement, rtlEnabled) { rtlEnabled ? this._$page.prependTo(rootElement) : this._$page.appendTo(rootElement) } }); var Pager = Widget.inherit({ _getDefaultOptions: function() { return extend(this.callBase(), { visible: true, pagesNavigatorVisible: "auto", pageIndex: 1, maxPagesCount: 10, pageCount: 10, totalCount: 0, pageSize: 5, showPageSizes: true, pageSizes: [5, 10], hasKnownLastPage: true, showNavigationButtons: false, showInfo: false, infoText: messageLocalization.getFormatter("dxPager-infoText"), pagesCountText: messageLocalization.getFormatter("dxPager-pagesCountText"), rtlEnabled: false, lightModeEnabled: false, pageIndexChanged: commonUtils.noop, pageSizeChanged: commonUtils.noop }) }, _toggleVisibility: function(value) { var $element = this.$element(); if ($element) { $element.css("display", value ? "" : "none") } }, _getPages: function(currentPage, count) { var firstValue, i, pages = [], showMoreButton = !this.option("hasKnownLastPage"); if (count > 0 || showMoreButton) { if (count <= this.option("maxPagesCount")) { for (i = 1; i <= count; i++) { pages.push(new Page(i, i - 1)) } if (showMoreButton) { pages.push(new Page(">", i - 1)) } } else { pages.push(new Page(1, 0)); firstValue = currentPage ? currentPage.value() - currentPage.index : 1; for (i = 1; i <= PAGES_LIMITER; i++) { pages.push(new Page(firstValue + i, i)) } pages.push(new Page(count, PAGES_LIMITER + 1)); if (showMoreButton) { pages.push(new Page(">", PAGES_LIMITER + 1)) } } } return pages }, _getPageByValue: function(value) { var page, i, that = this; for (i = 0; i < that._pages.length; i++) { page = that._pages[i]; if (page.value() === value) { return page } } }, _processSelectedPage: function(maxPagesCount, pageIndex, pageCount) { var selectedPageIndex, that = this, isPageIndexValid = false; if (that._pages) { each(that._pages, function(key, page) { if (pageIndex === page.value()) { isPageIndexValid = true } }); if (!isPageIndexValid) { that.selectedPage = null } } if (typeUtils.isDefined(that.selectedPage)) { if (pageIndex === pageCount && pageCount > maxPagesCount && that.selectedPage.index !== PAGES_LIMITER + 1) { that.selectedPage.index = PAGES_LIMITER + 1 } } else { if (pageIndex > PAGES_LIMITER && pageIndex < pageCount) { selectedPageIndex = pageCount - PAGES_LIMITER < pageIndex ? PAGES_LIMITER - (pageCount - pageIndex) + 1 : 2; that.selectedPage = new Page(pageIndex, selectedPageIndex) } } }, _selectPageByValue: function(value) { var i, prevPage, nextPage, morePage, that = this, page = that._getPageByValue(value), pages = that._pages, pagesLength = pages.length; if (!typeUtils.isDefined(page)) { return } prevPage = that._pages[page.index - 1]; nextPage = that._pages[page.index + 1]; if (nextPage && ">" === nextPage.value()) { morePage = nextPage; nextPage = void 0; pagesLength--; pages.pop() } if (that.selectedPage) { that.selectedPage.select(false) } page.select(true); that.selectedPage = page; if (nextPage && nextPage.value() - value > 1) { if (0 !== page.index) { prevPage.value(value + 1); that._pages.splice(page.index, 1); that._pages.splice(page.index - 1, 0, page); that._pages[page.index].index = page.index; page.index = page.index - 1; for (i = page.index - 1; i > 0; i--) { that._pages[i].value(that._pages[i + 1].value() - 1) } } else { for (i = 0; i < pagesLength - 1; i++) { that._pages[i].value(i + 1) } } } if (prevPage && value - prevPage.value() > 1) { if (page.index !== pagesLength - 1) { nextPage.value(value - 1); that._pages.splice(page.index, 1); that._pages.splice(page.index + 1, 0, page); that._pages[page.index].index = page.index; page.index = page.index + 1; for (i = page.index + 1; i < pagesLength - 1; i++) { that._pages[i].value(that._pages[i - 1].value() + 1) } } else { for (i = 1; i <= pagesLength - 2; i++) { that._pages[pagesLength - 1 - i].value(that._pages[pagesLength - 1].value() - i) } } } if (morePage) { pages.push(morePage) } }, _nextPage: function(direction) { var pageIndex = this.option("pageIndex"), pageCount = this.option("pageCount"); if (typeUtils.isDefined(pageIndex)) { pageIndex = "next" === direction ? ++pageIndex : --pageIndex; if (pageIndex > 0 && pageIndex <= pageCount) { this.option("pageIndex", pageIndex) } } }, _renderPages: function(pages) { var $separator, page, that = this, pagesLength = pages.length, clickPagesIndexAction = that._createAction(function(args) { var e = args.event, pageNumber = $(e.target).text(), pageIndex = ">" === pageNumber ? that.option("pageCount") + 1 : Number(pageNumber); that.option("pageIndex", pageIndex) }); if (pagesLength > 1) { that._pageClickHandler = function(e) { clickPagesIndexAction({ event: e }) }; eventsEngine.on(that._$pagesChooser, eventUtils.addNamespace(clickEvent.name, that.Name + "Pages"), "." + PAGER_PAGE_CLASS, that._pageClickHandler) } for (var i = 0; i < pagesLength; i++) { page = pages[i]; page.render(that._$pagesChooser, that.option("rtlEnabled")); that.setAria({ role: "button", label: "Page " + page.value() }, page.element()); if (pages[i + 1] && pages[i + 1].value() - page.value() > 1) { $separator = $("<div>").text(". . .").addClass(PAGER_PAGE_SEPARATOR_CLASS); that.option("rtlEnabled") ? $separator.prependTo(that._$pagesChooser) : $separator.appendTo(that._$pagesChooser) } } }, _calculateLightPagesWidth: function($pageIndex, pageCount) { return Number($pageIndex.css("minWidth").replace("px", "")) + 10 * pageCount.toString().length }, _renderLightPages: function() { var $pageCount, $pageIndex, that = this, pageCount = this.option("pageCount"), pageIndex = this.option("pageIndex"), clickAction = that._createAction(function() { that.option("pageIndex", pageCount) }), pagesCountText = this.option("pagesCountText"); var $container = $("<div>").addClass(LIGHT_PAGES_CLASS).appendTo(this._$pagesChooser); $pageIndex = $("<div>").addClass(PAGER_PAGE_INDEX_CLASS).appendTo($container); that._pageIndexEditor = that._createComponent($pageIndex, NumberBox, { value: pageIndex, min: 1, max: pageCount, width: that._calculateLightPagesWidth($pageIndex, pageCount), onValueChanged: function(e) { that.option("pageIndex", e.value) } }); $("<span>").text(pagesCountText).addClass(PAGER_INFO_TEXT_CLASS + " " + PAGER_INFO_CLASS).appendTo($container); $pageCount = $("<span>").addClass(PAGER_PAGES_COUNT_CLASS).text(pageCount); eventsEngine.on($pageCount, eventUtils.addNamespace(clickEvent.name, that.Name + "PagesCount"), function(e) { clickAction({ event: e }) }); $pageCount.appendTo($container); that.setAria({ role: "button", label: "Navigates to the last page" }, $pageCount) }, _renderPagesChooser: function() { var that = this, lightModeEnabled = that.option("lightModeEnabled"), pagesNavigatorVisible = that.option("pagesNavigatorVisible"), $element = that.$element(); that._$pagesChooser && that._$pagesChooser.remove(); if (!pagesNavigatorVisible) { return } if (that._pages && 0 === that._pages.length) { that.selectedPage = null; return } that._$pagesChooser = $("<div>").addClass(PAGER_PAGES_CLASS).appendTo($element); if ("auto" === pagesNavigatorVisible) { that._$pagesChooser.css("visibility", 1 === that.option("pageCount") ? "hidden" : "") } if (!lightModeEnabled) { that._renderInfo() } that._renderNavigateButton("prev"); if (lightModeEnabled) { that._renderLightPages() } else { that._renderPages(that._pages) } that._renderNavigateButton("next"); that._updatePagesChooserWidth() }, _renderPageSizes: function() { var i, pageSizeValue, $pageSize, that = this, pageSizes = that.option("pageSizes"), pagesSizesLength = pageSizes && pageSizes.length, currentPageSize = that.option("pageSize"), clickPagesSizeAction = that._createAction(function(args) { var e = args.event; pageSizeValue = parseInt($(e.target).text()); that.option("pageSize", pageSizeValue) }); eventsEngine.on(that._$pagesSizeChooser, eventUtils.addNamespace(clickEvent.name, that.Name + "PageSize"), "." + PAGER_PAGE_SIZE_CLASS, function(e) { clickPagesSizeAction({ event: e }) }); for (i = 0; i < pagesSizesLength; i++) { $pageSize = $("<div>").text(pageSizes[i]).addClass(PAGER_PAGE_SIZE_CLASS); that.setAria({ role: "button", label: "Display " + pageSizes[i] + " items on page" }, $pageSize); if (currentPageSize === pageSizes[i]) { $pageSize.addClass(PAGER_SELECTION_CLASS) } that._$pagesSizeChooser.append($pageSize) } }, _calculateLightPageSizesWidth: function(pageSizes) { return Number(this._$pagesSizeChooser.css("minWidth").replace("px", "")) + 10 * Math.max.apply(Math, pageSizes).toString().length }, _renderLightPageSizes: function() { var $editor, that = this, pageSizes = that.option("pageSizes"); $editor = $("<div>").appendTo(that._$pagesSizeChooser); that._pageSizeEditor = that._createComponent($editor, SelectBox, { dataSource: pageSizes, value: that.option("pageSize"), onSelectionChanged: function(e) { that.option("pageSize", e.selectedItem) }, width: that._calculateLightPageSizesWidth(pageSizes) }) }, _renderPagesSizeChooser: function() { var that = this, pageSizes = that.option("pageSizes"), showPageSizes = that.option("showPageSizes"), pagesSizesLength = pageSizes && pageSizes.length, $element = that.$element(); that._$pagesSizeChooser && that._$pagesSizeChooser.remove(); if (!showPageSizes || !pagesSizesLength) { return } that._$pagesSizeChooser = $("<div>").addClass(PAGER_PAGE_SIZES_CLASS).appendTo($element); if (that.option("lightModeEnabled")) { that._renderLightPageSizes() } else { that._renderPageSizes() } that._pagesSizeChooserWidth = that._$pagesSizeChooser.width() }, _renderInfo: function() { var infoText = this.option("infoText"); if (this.option("showInfo") && typeUtils.isDefined(infoText)) { this._$info = $("<div>").css("display", this._isInfoHide ? "none" : "").addClass(PAGER_INFO_CLASS).text(stringUtils.format(infoText, this.selectedPage && this.selectedPage.value(), this.option("pageCount"), this.option("totalCount"))).appendTo(this._$pagesChooser); if (!this._isInfoHide) { this._infoWidth = this._$info.outerWidth(true) } } }, _renderNavigateButton: function(direction) { var $button, that = this, clickAction = that._createAction(function() { that._nextPage(direction) }); if (that.option("showNavigationButtons") || that.option("lightModeEnabled")) { $button = $("<div>").addClass(PAGER_NAVIGATE_BUTTON); eventsEngine.on($button, eventUtils.addNamespace(clickEvent.name, that.Name + "Pages"), function(e) { clickAction({ event: e }) }); that.setAria({ role: "button", label: "prev" === direction ? "Previous page" : " Next page" }, $button); if (that.option("rtlEnabled")) { $button.addClass("prev" === direction ? PAGER_NEXT_BUTTON_CLASS : PAGER_PREV_BUTTON_CLASS); $button.prependTo(this._$pagesChooser) } else { $button.addClass("prev" === direction ? PAGER_PREV_BUTTON_CLASS : PAGER_NEXT_BUTTON_CLASS); $button.appendTo(this._$pagesChooser) } } }, _renderContentImpl: function() { this.$element().toggleClass(LIGHT_MODE_CLASS, this.option("lightModeEnabled")); this._toggleVisibility(this.option("visible")); this._updatePageSizes(true); this._updatePages(true) }, _initMarkup: function() { var $element = this.$element(); $element.addClass(PAGER_CLASS); var $pageSize = $("<div>").addClass(PAGER_PAGE_CLASS); this._$pagesChooser = $("<div>").addClass(PAGER_PAGES_CLASS).append($pageSize).appendTo($element) }, _render: function() { this.option().lightModeEnabled = false; this.callBase(); this._updateLightMode() }, _updatePageSizes: function(forceRender) { var lightModeEnabled = this.option("lightModeEnabled"), pageSize = this.option("pageSize"), pageSizes = this.option("pageSizes"); if (lightModeEnabled) { this._pageSizeEditor && this._pageSizeEditor.option({ value: pageSize, dataSource: pageSizes, width: this._calculateLightPageSizesWidth(pageSizes) }) } if (!lightModeEnabled || forceRender) { this._renderPagesSizeChooser() } }, _updatePages: function(forceRender) { var pageCount = this.option("pageCount"), pageIndex = this.option("pageIndex"), lightModeEnabled = this.option("lightModeEnabled"); if (!lightModeEnabled) { this._processSelectedPage(this.option("maxPagesCount"), pageIndex, pageCount); this._pages = this._getPages(this.selectedPage, pageCount); this._selectPageByValue(pageIndex) } else { this._pageIndexEditor && this._pageIndexEditor.option({ value: pageIndex, width: this._calculateLightPagesWidth(this._pageIndexEditor.$element(), pageCount) }) } if (!lightModeEnabled || forceRender) { this._renderPagesChooser() } this._updateButtonsState(pageIndex) }, _isPageIndexInvalid: function(direction, pageIndex) { var isNextDirection = "next" === direction, rtlEnabled = this.option("rtlEnabled"); if (rtlEnabled && isNextDirection || !rtlEnabled && !isNextDirection) { return pageIndex <= 1 } return pageIndex >= this.option("pageCount") }, _updateButtonsState: function(pageIndex) { var nextButton = this.$element().find("." + PAGER_NEXT_BUTTON_CLASS), prevButton = this.$element().find("." + PAGER_PREV_BUTTON_CLASS); nextButton.toggleClass(PAGER_BUTTON_DISABLE_CLASS, this._isPageIndexInvalid("next", pageIndex)); prevButton.toggleClass(PAGER_BUTTON_DISABLE_CLASS, this._isPageIndexInvalid("prev", pageIndex)) }, _optionChanged: function(args) { switch (args.name) { case "visible": this._toggleVisibility(args.value); break; case "pageIndex": var pageIndexChanged = this.option("pageIndexChanged"); if (pageIndexChanged) { pageIndexChanged(args.value) } this._updatePages(); break; case "maxPagesCount": case "pageCount": case "totalCount": case "hasKnownLastPage": case "pagesNavigatorVisible": case "showNavigationButtons": this._updatePages(); break; case "pageSize": var pageSizeChanged = this.option("pageSizeChanged"); if (pageSizeChanged) { pageSizeChanged(args.value) } this._updatePageSizes(); break; case "pageSizes": this._updatePageSizes(); break; case "lightModeEnabled": this._renderContentImpl(); !args.value && this._updateLightMode(); break; default: this._invalidate() } }, _clean: function() { this._$pagesChooser && eventsEngine.off(this._$pagesChooser, eventUtils.addNamespace(clickEvent.name, this.Name + "Pages"), "." + PAGER_PAGE_CLASS, this._pageClickHandler); this.callBase() }, _getMinPagerWidth: function() { var pagesChooserWidth = typeUtils.isDefined(this._pagesChooserWidth) ? this._pagesChooserWidth : 0, pagesSizeChooserWidth = typeUtils.isDefined(this._pagesSizeChooserWidth) ? this._pagesSizeChooserWidth : 0; return pagesChooserWidth + pagesSizeChooserWidth }, _updatePagesChooserWidth: commonUtils.deferUpdater(function() { var lastPageWidth = this._pages && this._pages.length > 0 ? this._pages[this._pages.length - 1]._$page.width() : 0; this._pagesChooserWidth = this._$pagesChooser.width() + lastPageWidth }), _updateLightMode: commonUtils.deferUpdater(function() { var that = this, width = this.$element().width(), infoWidth = typeUtils.isDefined(this._infoWidth) ? this._infoWidth : 0; commonUtils.deferRender(function() { if (that._isInfoHide && width > that._getMinPagerWidth() + infoWidth) { that._$info.show(); that._updatePagesChooserWidth(); that._isInfoHide = false } if (!that._isInfoHide && width > that._getMinPagerWidth() - infoWidth && width < that._getMinPagerWidth()) { that._$info.hide(); that._updatePagesChooserWidth(); that._isInfoHide = true } commonUtils.deferUpdate(function() { commonUtils.deferRender(function() { if (that.option("lightModeEnabled") && width > that._previousWidth) { that.option("lightModeEnabled", false) } else { if (width < that._getMinPagerWidth()) { that.option("lightModeEnabled", true) } } that._previousWidth = width }) }) }) }), _dimensionChanged: function() { this._updateLightMode() }, getHeight: function() { return this.option("visible") ? this.$element().outerHeight() : 0 } }); module.exports = Pager; registerComponent("dxPager", Pager);