ui-grid.pagination.js 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498
  1. /*!
  2. * ui-grid - v4.4.6 - 2018-04-06
  3. * Copyright (c) 2018 ; License: MIT
  4. */
  5. (function() {
  6. 'use strict';
  7. /**
  8. * @ngdoc overview
  9. * @name ui.grid.pagination
  10. *
  11. * @description
  12. *
  13. * # ui.grid.pagination
  14. *
  15. * <div class="alert alert-warning" role="alert"><strong>Alpha</strong> This feature is in development. There will almost certainly be breaking api changes, or there are major outstanding bugs.</div>
  16. *
  17. * This module provides pagination support to ui-grid
  18. */
  19. var module = angular.module('ui.grid.pagination', ['ng', 'ui.grid']);
  20. /**
  21. * @ngdoc service
  22. * @name ui.grid.pagination.service:uiGridPaginationService
  23. *
  24. * @description Service for the pagination feature
  25. */
  26. module.service('uiGridPaginationService', ['gridUtil',
  27. function (gridUtil) {
  28. var service = {
  29. /**
  30. * @ngdoc method
  31. * @name initializeGrid
  32. * @methodOf ui.grid.pagination.service:uiGridPaginationService
  33. * @description Attaches the service to a certain grid
  34. * @param {Grid} grid The grid we want to work with
  35. */
  36. initializeGrid: function (grid) {
  37. service.defaultGridOptions(grid.options);
  38. /**
  39. * @ngdoc object
  40. * @name ui.grid.pagination.api:PublicAPI
  41. *
  42. * @description Public API for the pagination feature
  43. */
  44. var publicApi = {
  45. events: {
  46. pagination: {
  47. /**
  48. * @ngdoc event
  49. * @name paginationChanged
  50. * @eventOf ui.grid.pagination.api:PublicAPI
  51. * @description This event fires when the pageSize or currentPage changes
  52. * @param {int} currentPage requested page number
  53. * @param {int} pageSize requested page size
  54. */
  55. paginationChanged: function (currentPage, pageSize) { }
  56. }
  57. },
  58. methods: {
  59. pagination: {
  60. /**
  61. * @ngdoc method
  62. * @name getPage
  63. * @methodOf ui.grid.pagination.api:PublicAPI
  64. * @description Returns the number of the current page
  65. */
  66. getPage: function () {
  67. return grid.options.enablePagination ? grid.options.paginationCurrentPage : null;
  68. },
  69. /**
  70. * @ngdoc method
  71. * @name getFirstRowIndex
  72. * @methodOf ui.grid.pagination.api:PublicAPI
  73. * @description Returns the index of the first row of the current page.
  74. */
  75. getFirstRowIndex: function () {
  76. if (grid.options.useCustomPagination) {
  77. return grid.options.paginationPageSizes.reduce(function(result, size, index) {
  78. return index < grid.options.paginationCurrentPage - 1 ? result + size : result;
  79. }, 0);
  80. }
  81. return ((grid.options.paginationCurrentPage - 1) * grid.options.paginationPageSize);
  82. },
  83. /**
  84. * @ngdoc method
  85. * @name getLastRowIndex
  86. * @methodOf ui.grid.pagination.api:PublicAPI
  87. * @description Returns the index of the last row of the current page.
  88. */
  89. getLastRowIndex: function () {
  90. if (grid.options.useCustomPagination) {
  91. return publicApi.methods.pagination.getFirstRowIndex() + grid.options.paginationPageSizes[grid.options.paginationCurrentPage - 1] - 1;
  92. }
  93. return Math.min(grid.options.paginationCurrentPage * grid.options.paginationPageSize, grid.options.totalItems) - 1;
  94. },
  95. /**
  96. * @ngdoc method
  97. * @name getTotalPages
  98. * @methodOf ui.grid.pagination.api:PublicAPI
  99. * @description Returns the total number of pages
  100. */
  101. getTotalPages: function () {
  102. if (!grid.options.enablePagination) {
  103. return null;
  104. }
  105. if (grid.options.useCustomPagination) {
  106. return grid.options.paginationPageSizes.length;
  107. }
  108. return (grid.options.totalItems === 0) ? 1 : Math.ceil(grid.options.totalItems / grid.options.paginationPageSize);
  109. },
  110. /**
  111. * @ngdoc method
  112. * @name nextPage
  113. * @methodOf ui.grid.pagination.api:PublicAPI
  114. * @description Moves to the next page, if possible
  115. */
  116. nextPage: function () {
  117. if (!grid.options.enablePagination) {
  118. return;
  119. }
  120. if (grid.options.totalItems > 0) {
  121. grid.options.paginationCurrentPage = Math.min(
  122. grid.options.paginationCurrentPage + 1,
  123. publicApi.methods.pagination.getTotalPages()
  124. );
  125. } else {
  126. grid.options.paginationCurrentPage++;
  127. }
  128. },
  129. /**
  130. * @ngdoc method
  131. * @name previousPage
  132. * @methodOf ui.grid.pagination.api:PublicAPI
  133. * @description Moves to the previous page, if we're not on the first page
  134. */
  135. previousPage: function () {
  136. if (!grid.options.enablePagination) {
  137. return;
  138. }
  139. grid.options.paginationCurrentPage = Math.max(grid.options.paginationCurrentPage - 1, 1);
  140. },
  141. /**
  142. * @ngdoc method
  143. * @name seek
  144. * @methodOf ui.grid.pagination.api:PublicAPI
  145. * @description Moves to the requested page
  146. * @param {int} page The number of the page that should be displayed
  147. */
  148. seek: function (page) {
  149. if (!grid.options.enablePagination) {
  150. return;
  151. }
  152. if (!angular.isNumber(page) || page < 1) {
  153. throw 'Invalid page number: ' + page;
  154. }
  155. grid.options.paginationCurrentPage = Math.min(page, publicApi.methods.pagination.getTotalPages());
  156. }
  157. }
  158. }
  159. };
  160. grid.api.registerEventsFromObject(publicApi.events);
  161. grid.api.registerMethodsFromObject(publicApi.methods);
  162. var processPagination = function( renderableRows ){
  163. if (grid.options.useExternalPagination || !grid.options.enablePagination) {
  164. return renderableRows;
  165. }
  166. //client side pagination
  167. var pageSize = parseInt(grid.options.paginationPageSize, 10);
  168. var currentPage = parseInt(grid.options.paginationCurrentPage, 10);
  169. var visibleRows = renderableRows.filter(function (row) { return row.visible; });
  170. grid.options.totalItems = visibleRows.length;
  171. var firstRow = publicApi.methods.pagination.getFirstRowIndex();
  172. var lastRow = publicApi.methods.pagination.getLastRowIndex();
  173. if (firstRow > visibleRows.length) {
  174. currentPage = grid.options.paginationCurrentPage = 1;
  175. firstRow = (currentPage - 1) * pageSize;
  176. }
  177. return visibleRows.slice(firstRow, lastRow + 1);
  178. };
  179. grid.registerRowsProcessor(processPagination, 900 );
  180. },
  181. defaultGridOptions: function (gridOptions) {
  182. /**
  183. * @ngdoc object
  184. * @name ui.grid.pagination.api:GridOptions
  185. *
  186. * @description GridOptions for the pagination feature, these are available to be
  187. * set using the ui-grid {@link ui.grid.class:GridOptions gridOptions}
  188. */
  189. /**
  190. * @ngdoc property
  191. * @name enablePagination
  192. * @propertyOf ui.grid.pagination.api:GridOptions
  193. * @description Enables pagination. Defaults to true.
  194. */
  195. gridOptions.enablePagination = gridOptions.enablePagination !== false;
  196. /**
  197. * @ngdoc property
  198. * @name enablePaginationControls
  199. * @propertyOf ui.grid.pagination.api:GridOptions
  200. * @description Enables the paginator at the bottom of the grid. Turn this off if you want to implement your
  201. * own controls outside the grid.
  202. */
  203. gridOptions.enablePaginationControls = gridOptions.enablePaginationControls !== false;
  204. /**
  205. * @ngdoc property
  206. * @name useExternalPagination
  207. * @propertyOf ui.grid.pagination.api:GridOptions
  208. * @description Disables client side pagination. When true, handle the paginationChanged event and set data
  209. * and totalItems. Defaults to `false`
  210. */
  211. gridOptions.useExternalPagination = gridOptions.useExternalPagination === true;
  212. /**
  213. * @ngdoc property
  214. * @name useCustomPagination
  215. * @propertyOf ui.grid.pagination.api:GridOptions
  216. * @description Disables client-side pagination. When true, handle the `paginationChanged` event and set `data`,
  217. * `firstRowIndex`, `lastRowIndex`, and `totalItems`. Defaults to `false`.
  218. */
  219. gridOptions.useCustomPagination = gridOptions.useCustomPagination === true;
  220. /**
  221. * @ngdoc property
  222. * @name totalItems
  223. * @propertyOf ui.grid.pagination.api:GridOptions
  224. * @description Total number of items, set automatically when using client side pagination, but needs set by user
  225. * for server side pagination
  226. */
  227. if (gridUtil.isNullOrUndefined(gridOptions.totalItems)) {
  228. gridOptions.totalItems = 0;
  229. }
  230. /**
  231. * @ngdoc property
  232. * @name paginationPageSizes
  233. * @propertyOf ui.grid.pagination.api:GridOptions
  234. * @description Array of page sizes, defaults to `[250, 500, 1000]`
  235. */
  236. if (gridUtil.isNullOrUndefined(gridOptions.paginationPageSizes)) {
  237. gridOptions.paginationPageSizes = [250, 500, 1000];
  238. }
  239. /**
  240. * @ngdoc property
  241. * @name paginationPageSize
  242. * @propertyOf ui.grid.pagination.api:GridOptions
  243. * @description Page size, defaults to the first item in paginationPageSizes, or 0 if paginationPageSizes is empty
  244. */
  245. if (gridUtil.isNullOrUndefined(gridOptions.paginationPageSize)) {
  246. if (gridOptions.paginationPageSizes.length > 0) {
  247. gridOptions.paginationPageSize = gridOptions.paginationPageSizes[0];
  248. } else {
  249. gridOptions.paginationPageSize = 0;
  250. }
  251. }
  252. /**
  253. * @ngdoc property
  254. * @name paginationCurrentPage
  255. * @propertyOf ui.grid.pagination.api:GridOptions
  256. * @description Current page number, defaults to 1
  257. */
  258. if (gridUtil.isNullOrUndefined(gridOptions.paginationCurrentPage)) {
  259. gridOptions.paginationCurrentPage = 1;
  260. }
  261. /**
  262. * @ngdoc property
  263. * @name paginationTemplate
  264. * @propertyOf ui.grid.pagination.api:GridOptions
  265. * @description A custom template for the pager, defaults to `ui-grid/pagination`
  266. */
  267. if (gridUtil.isNullOrUndefined(gridOptions.paginationTemplate)) {
  268. gridOptions.paginationTemplate = 'ui-grid/pagination';
  269. }
  270. },
  271. /**
  272. * @ngdoc method
  273. * @methodOf ui.grid.pagination.service:uiGridPaginationService
  274. * @name uiGridPaginationService
  275. * @description Raises paginationChanged and calls refresh for client side pagination
  276. * @param {Grid} grid the grid for which the pagination changed
  277. * @param {int} currentPage requested page number
  278. * @param {int} pageSize requested page size
  279. */
  280. onPaginationChanged: function (grid, currentPage, pageSize) {
  281. grid.api.pagination.raise.paginationChanged(currentPage, pageSize);
  282. if (!grid.options.useExternalPagination) {
  283. grid.queueGridRefresh(); //client side pagination
  284. }
  285. }
  286. };
  287. return service;
  288. }
  289. ]);
  290. /**
  291. * @ngdoc directive
  292. * @name ui.grid.pagination.directive:uiGridPagination
  293. * @element div
  294. * @restrict A
  295. *
  296. * @description Adds pagination features to grid
  297. * @example
  298. <example module="app">
  299. <file name="app.js">
  300. var app = angular.module('app', ['ui.grid', 'ui.grid.pagination']);
  301. app.controller('MainCtrl', ['$scope', function ($scope) {
  302. $scope.data = [
  303. { name: 'Alex', car: 'Toyota' },
  304. { name: 'Sam', car: 'Lexus' },
  305. { name: 'Joe', car: 'Dodge' },
  306. { name: 'Bob', car: 'Buick' },
  307. { name: 'Cindy', car: 'Ford' },
  308. { name: 'Brian', car: 'Audi' },
  309. { name: 'Malcom', car: 'Mercedes Benz' },
  310. { name: 'Dave', car: 'Ford' },
  311. { name: 'Stacey', car: 'Audi' },
  312. { name: 'Amy', car: 'Acura' },
  313. { name: 'Scott', car: 'Toyota' },
  314. { name: 'Ryan', car: 'BMW' },
  315. ];
  316. $scope.gridOptions = {
  317. data: 'data',
  318. paginationPageSizes: [5, 10, 25],
  319. paginationPageSize: 5,
  320. columnDefs: [
  321. {name: 'name'},
  322. {name: 'car'}
  323. ]
  324. }
  325. }]);
  326. </file>
  327. <file name="index.html">
  328. <div ng-controller="MainCtrl">
  329. <div ui-grid="gridOptions" ui-grid-pagination></div>
  330. </div>
  331. </file>
  332. </example>
  333. */
  334. module.directive('uiGridPagination', ['gridUtil', 'uiGridPaginationService',
  335. function (gridUtil, uiGridPaginationService) {
  336. return {
  337. priority: -200,
  338. scope: false,
  339. require: 'uiGrid',
  340. link: {
  341. pre: function ($scope, $elm, $attr, uiGridCtrl) {
  342. uiGridPaginationService.initializeGrid(uiGridCtrl.grid);
  343. gridUtil.getTemplate(uiGridCtrl.grid.options.paginationTemplate)
  344. .then(function (contents) {
  345. var template = angular.element(contents);
  346. $elm.append(template);
  347. uiGridCtrl.innerCompile(template);
  348. });
  349. }
  350. }
  351. };
  352. }
  353. ]);
  354. /**
  355. * @ngdoc directive
  356. * @name ui.grid.pagination.directive:uiGridPager
  357. * @element div
  358. *
  359. * @description Panel for handling pagination
  360. */
  361. module.directive('uiGridPager', ['uiGridPaginationService', 'uiGridConstants', 'gridUtil', 'i18nService', 'i18nConstants',
  362. function (uiGridPaginationService, uiGridConstants, gridUtil, i18nService, i18nConstants) {
  363. return {
  364. priority: -200,
  365. scope: true,
  366. require: '^uiGrid',
  367. link: function ($scope, $elm, $attr, uiGridCtrl) {
  368. var defaultFocusElementSelector = '.ui-grid-pager-control-input';
  369. $scope.aria = i18nService.getSafeText('pagination.aria'); //Returns an object with all of the aria labels
  370. var updateLabels = function(){
  371. $scope.paginationApi = uiGridCtrl.grid.api.pagination;
  372. $scope.sizesLabel = i18nService.getSafeText('pagination.sizes');
  373. $scope.totalItemsLabel = i18nService.getSafeText('pagination.totalItems');
  374. $scope.paginationOf = i18nService.getSafeText('pagination.of');
  375. $scope.paginationThrough = i18nService.getSafeText('pagination.through');
  376. };
  377. updateLabels();
  378. $scope.$on(i18nConstants.UPDATE_EVENT, updateLabels);
  379. var options = uiGridCtrl.grid.options;
  380. uiGridCtrl.grid.renderContainers.body.registerViewportAdjuster(function (adjustment) {
  381. if (options.enablePaginationControls) {
  382. adjustment.height = adjustment.height - gridUtil.elementHeight($elm, "padding");
  383. }
  384. return adjustment;
  385. });
  386. var dataChangeDereg = uiGridCtrl.grid.registerDataChangeCallback(function (grid) {
  387. if (!grid.options.useExternalPagination) {
  388. grid.options.totalItems = grid.rows.length;
  389. }
  390. }, [uiGridConstants.dataChange.ROW]);
  391. $scope.$on('$destroy', dataChangeDereg);
  392. var deregP = $scope.$watch('grid.options.paginationCurrentPage + grid.options.paginationPageSize', function (newValues, oldValues) {
  393. if (newValues === oldValues || oldValues === undefined) {
  394. return;
  395. }
  396. if (!angular.isNumber(options.paginationCurrentPage) || options.paginationCurrentPage < 1) {
  397. options.paginationCurrentPage = 1;
  398. return;
  399. }
  400. if (options.totalItems > 0 && options.paginationCurrentPage > $scope.paginationApi.getTotalPages()) {
  401. options.paginationCurrentPage = $scope.paginationApi.getTotalPages();
  402. return;
  403. }
  404. uiGridPaginationService.onPaginationChanged($scope.grid, options.paginationCurrentPage, options.paginationPageSize);
  405. }
  406. );
  407. $scope.$on('$destroy', function() {
  408. deregP();
  409. });
  410. $scope.cantPageForward = function () {
  411. if ($scope.paginationApi.getTotalPages()) {
  412. return $scope.cantPageToLast();
  413. } else {
  414. return options.data.length < 1;
  415. }
  416. };
  417. $scope.cantPageToLast = function () {
  418. var totalPages = $scope.paginationApi.getTotalPages();
  419. return !totalPages || options.paginationCurrentPage >= totalPages;
  420. };
  421. $scope.cantPageBackward = function () {
  422. return options.paginationCurrentPage <= 1;
  423. };
  424. var focusToInputIf = function(condition){
  425. if (condition){
  426. gridUtil.focus.bySelector($elm, defaultFocusElementSelector);
  427. }
  428. };
  429. //Takes care of setting focus to the middle element when focus is lost
  430. $scope.pageFirstPageClick = function () {
  431. $scope.paginationApi.seek(1);
  432. focusToInputIf($scope.cantPageBackward());
  433. };
  434. $scope.pagePreviousPageClick = function () {
  435. $scope.paginationApi.previousPage();
  436. focusToInputIf($scope.cantPageBackward());
  437. };
  438. $scope.pageNextPageClick = function () {
  439. $scope.paginationApi.nextPage();
  440. focusToInputIf($scope.cantPageForward());
  441. };
  442. $scope.pageLastPageClick = function () {
  443. $scope.paginationApi.seek($scope.paginationApi.getTotalPages());
  444. focusToInputIf($scope.cantPageToLast());
  445. };
  446. }
  447. };
  448. }
  449. ]);
  450. })();