mirror of
				https://github.com/gyurix1968/guacamole-client.git
				synced 2025-10-31 00:53:21 +00:00 
			
		
		
		
	GUAC-1138: Generalize "pager" module into "list" module.
This commit is contained in:
		
							
								
								
									
										303
									
								
								guacamole/src/main/webapp/app/list/directives/guacPager.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										303
									
								
								guacamole/src/main/webapp/app/list/directives/guacPager.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,303 @@ | ||||
| /* | ||||
|  * Copyright (C) 2015 Glyptodon LLC | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|  * of this software and associated documentation files (the "Software"), to deal | ||||
|  * in the Software without restriction, including without limitation the rights | ||||
|  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
|  * copies of the Software, and to permit persons to whom the Software is | ||||
|  * furnished to do so, subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice and this permission notice shall be included in | ||||
|  * all copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
|  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
|  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
|  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
|  * THE SOFTWARE. | ||||
|  */ | ||||
|  | ||||
| /** | ||||
|  * A directive which provides pagination controls, along with a paginated | ||||
|  * subset of the elements of some given array. | ||||
|  */ | ||||
| angular.module('list').directive('guacPager', [function guacPager() { | ||||
|  | ||||
|     return { | ||||
|         restrict: 'E', | ||||
|         replace: true, | ||||
|         scope: { | ||||
|  | ||||
|             /** | ||||
|              * The property to which a subset of the provided array will be | ||||
|              * assigned. | ||||
|              * | ||||
|              * @type Array | ||||
|              */ | ||||
|             page : '=', | ||||
|  | ||||
|             /** | ||||
|              * The maximum number of items per page. | ||||
|              * | ||||
|              * @type Number | ||||
|              */ | ||||
|             pageSize : '&', | ||||
|  | ||||
|             /** | ||||
|              * The maximum number of page choices to provide, regardless of the | ||||
|              * total number of pages. | ||||
|              * | ||||
|              * @type Number | ||||
|              */ | ||||
|             pageCount : '&', | ||||
|  | ||||
|             /** | ||||
|              * An array objects to paginate. Subsets of this array will be | ||||
|              * exposed as pages. | ||||
|              * | ||||
|              * @type Array | ||||
|              */ | ||||
|             items : '&' | ||||
|  | ||||
|         }, | ||||
|  | ||||
|         templateUrl: 'app/pager/templates/guacPager.html', | ||||
|         controller: ['$scope', function guacPagerController($scope) { | ||||
|  | ||||
|             /** | ||||
|              * The default size of a page, if not provided via the pageSize | ||||
|              * attribute. | ||||
|              * | ||||
|              * @type Number | ||||
|              */ | ||||
|             var DEFAULT_PAGE_SIZE = 10; | ||||
|  | ||||
|             /** | ||||
|              * The default maximum number of page choices to provide, if a | ||||
|              * value is not providede via the pageCount attribute. | ||||
|              * | ||||
|              * @type Number | ||||
|              */ | ||||
|             var DEFAULT_PAGE_COUNT = 11; | ||||
|  | ||||
|             /** | ||||
|              * An array of arrays, where the Nth array contains the contents of | ||||
|              * the Nth page. | ||||
|              * | ||||
|              * @type Array[] | ||||
|              */ | ||||
|             var pages = []; | ||||
|  | ||||
|             /** | ||||
|              * The number of the first selectable page. | ||||
|              * | ||||
|              * @type Number; | ||||
|              */ | ||||
|             $scope.firstPage = 1; | ||||
|  | ||||
|             /** | ||||
|              * The number of the page immediately before the currently-selected | ||||
|              * page. | ||||
|              * | ||||
|              * @type Number; | ||||
|              */ | ||||
|             $scope.previousPage = 1; | ||||
|  | ||||
|             /** | ||||
|              * The number of the currently-selected page. | ||||
|              * | ||||
|              * @type Number; | ||||
|              */ | ||||
|             $scope.currentPage = 1; | ||||
|  | ||||
|             /** | ||||
|              * The number of the page immediately after the currently-selected | ||||
|              * page. | ||||
|              * | ||||
|              * @type Number; | ||||
|              */ | ||||
|             $scope.nextPage = 1; | ||||
|  | ||||
|             /** | ||||
|              * The number of the last selectable page. | ||||
|              * | ||||
|              * @type Number; | ||||
|              */ | ||||
|             $scope.lastPage = 1; | ||||
|  | ||||
|             /** | ||||
|              * An array of relevant page numbers that the user may want to jump | ||||
|              * to directly. | ||||
|              * | ||||
|              * @type Number[] | ||||
|              */ | ||||
|             $scope.pageNumbers = []; | ||||
|  | ||||
|             /** | ||||
|              * Updates the displayed page number choices. | ||||
|              */ | ||||
|             var updatePageNumbers = function updatePageNumbers() { | ||||
|  | ||||
|                 // Get page count | ||||
|                 var pageCount = $scope.pageCount() || DEFAULT_PAGE_COUNT; | ||||
|  | ||||
|                 // Determine start/end of page window | ||||
|                 var windowStart = $scope.currentPage - (pageCount - 1) / 2; | ||||
|                 var windowEnd   = windowStart + pageCount - 1; | ||||
|  | ||||
|                 // Shift window as necessary if it extends beyond the first page | ||||
|                 if (windowStart < $scope.firstPage) { | ||||
|                     windowEnd = Math.min($scope.lastPage, windowEnd - windowStart + $scope.firstPage); | ||||
|                     windowStart = $scope.firstPage; | ||||
|                 } | ||||
|  | ||||
|                 // Shift window as necessary if it extends beyond the last page | ||||
|                 else if (windowEnd > $scope.lastPage) { | ||||
|                     windowStart = Math.max(1, windowStart - windowEnd + $scope.lastPage); | ||||
|                     windowEnd = $scope.lastPage; | ||||
|                 } | ||||
|  | ||||
|                 // Generate list of relevant page numbers | ||||
|                 $scope.pageNumbers = []; | ||||
|                 for (var pageNumber = windowStart; pageNumber <= windowEnd; pageNumber++) | ||||
|                     $scope.pageNumbers.push(pageNumber); | ||||
|  | ||||
|             }; | ||||
|  | ||||
|             /** | ||||
|              * Iterates through the bound items array, splitting it into pages | ||||
|              * based on the current page size. | ||||
|              */ | ||||
|             var updatePages = function updatePages() { | ||||
|  | ||||
|                 // Get current items and page size | ||||
|                 var items = $scope.items(); | ||||
|                 var pageSize = $scope.pageSize() || DEFAULT_PAGE_SIZE; | ||||
|  | ||||
|                 // Clear current pages | ||||
|                 pages = []; | ||||
|  | ||||
|                 // Only split into pages if items actually exist | ||||
|                 if (items) { | ||||
|  | ||||
|                     // Split into pages of pageSize items each | ||||
|                     for (var i = 0; i < items.length; i += pageSize) | ||||
|                         pages.push(items.slice(i, i + pageSize)); | ||||
|  | ||||
|                 } | ||||
|  | ||||
|                 // Update minimum and maximum values | ||||
|                 $scope.firstPage = 1; | ||||
|                 $scope.lastPage  = pages.length; | ||||
|  | ||||
|                 // Select an appropriate page | ||||
|                 var adjustedCurrentPage = Math.min($scope.lastPage, Math.max($scope.firstPage, $scope.currentPage)); | ||||
|                 $scope.selectPage(adjustedCurrentPage); | ||||
|  | ||||
|             }; | ||||
|  | ||||
|             /** | ||||
|              * Selects the page having the given number, assigning that page to | ||||
|              * the property bound to the page attribute. If no such page | ||||
|              * exists, the property will be set to undefined instead. Valid | ||||
|              * page numbers begin at 1. | ||||
|              * | ||||
|              * @param {Number} page | ||||
|              *     The number of the page to select. Valid page numbers begin | ||||
|              *     at 1. | ||||
|              */ | ||||
|             $scope.selectPage = function selectPage(page) { | ||||
|  | ||||
|                 // Select the chosen page | ||||
|                 $scope.currentPage = page; | ||||
|                 $scope.page = pages[page-1]; | ||||
|  | ||||
|                 // Update next/previous page numbers | ||||
|                 $scope.nextPage     = Math.min($scope.lastPage,  $scope.currentPage + 1); | ||||
|                 $scope.previousPage = Math.max($scope.firstPage, $scope.currentPage - 1); | ||||
|  | ||||
|                 // Update which page numbers are shown | ||||
|                 updatePageNumbers(); | ||||
|  | ||||
|             }; | ||||
|  | ||||
|             /** | ||||
|              * Returns whether the given page number can be legally selected | ||||
|              * via selectPage(), resulting in a different page being shown. | ||||
|              * | ||||
|              * @param {Number} page | ||||
|              *     The page number to check. | ||||
|              * | ||||
|              * @returns {Boolean} | ||||
|              *     true if the page having the given number can be selected, | ||||
|              *     false otherwise. | ||||
|              */ | ||||
|             $scope.canSelectPage = function canSelectPage(page) { | ||||
|                 return page !== $scope.currentPage | ||||
|                     && page >=  $scope.firstPage | ||||
|                     && page <=  $scope.lastPage; | ||||
|             }; | ||||
|  | ||||
|             /** | ||||
|              * Returns whether the page having the given number is currently | ||||
|              * selected. | ||||
|              * | ||||
|              * @param {Number} page | ||||
|              *     The page number to check. | ||||
|              * | ||||
|              * @returns {Boolean} | ||||
|              *     true if the page having the given number is currently | ||||
|              *     selected, false otherwise. | ||||
|              */ | ||||
|             $scope.isSelected = function isSelected(page) { | ||||
|                 return page === $scope.currentPage; | ||||
|             }; | ||||
|  | ||||
|             /** | ||||
|              * Returns whether pages exist before the first page listed in the | ||||
|              * pageNumbers array. | ||||
|              * | ||||
|              * @returns {Boolean} | ||||
|              *     true if pages exist before the first page listed in the | ||||
|              *     pageNumbers array, false otherwise. | ||||
|              */ | ||||
|             $scope.hasMorePagesBefore = function hasMorePagesBefore() { | ||||
|                 var firstPageNumber = $scope.pageNumbers[0] | ||||
|                 return firstPageNumber !== $scope.firstPage; | ||||
|             }; | ||||
|  | ||||
|             /** | ||||
|              * Returns whether pages exist after the last page listed in the | ||||
|              * pageNumbers array. | ||||
|              * | ||||
|              * @returns {Boolean} | ||||
|              *     true if pages exist after the last page listed in the | ||||
|              *     pageNumbers array, false otherwise. | ||||
|              */ | ||||
|             $scope.hasMorePagesAfter = function hasMorePagesAfter() { | ||||
|                 var lastPageNumber = $scope.pageNumbers[$scope.pageNumbers.length - 1]; | ||||
|                 return lastPageNumber !== $scope.lastPage; | ||||
|             }; | ||||
|  | ||||
|             // Update available pages when available items are changed | ||||
|             $scope.$watchCollection($scope.items, function itemsChanged() { | ||||
|                 updatePages(); | ||||
|             }); | ||||
|  | ||||
|             // Update available pages when page size is changed | ||||
|             $scope.$watch($scope.pageSize, function pageSizeChanged() { | ||||
|                 updatePages(); | ||||
|             }); | ||||
|  | ||||
|             // Update available page numbers when page count is changed | ||||
|             $scope.$watch($scope.pageCount, function pageCountChanged() { | ||||
|                 updatePageNumbers(); | ||||
|             }); | ||||
|  | ||||
|         }] | ||||
|  | ||||
|     }; | ||||
| }]); | ||||
							
								
								
									
										26
									
								
								guacamole/src/main/webapp/app/list/listModule.js
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										26
									
								
								guacamole/src/main/webapp/app/list/listModule.js
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,26 @@ | ||||
| /* | ||||
|  * Copyright (C) 2015 Glyptodon LLC | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|  * of this software and associated documentation files (the "Software"), to deal | ||||
|  * in the Software without restriction, including without limitation the rights | ||||
|  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
|  * copies of the Software, and to permit persons to whom the Software is | ||||
|  * furnished to do so, subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice and this permission notice shall be included in | ||||
|  * all copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
|  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
|  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
|  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
|  * THE SOFTWARE. | ||||
|  */ | ||||
|  | ||||
| /** | ||||
|  * Module for displaying the contents of a list, split into multiple pages. | ||||
|  */ | ||||
| angular.module('list', []); | ||||
							
								
								
									
										90
									
								
								guacamole/src/main/webapp/app/list/styles/pager.css
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										90
									
								
								guacamole/src/main/webapp/app/list/styles/pager.css
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,90 @@ | ||||
| /* | ||||
|  * Copyright (C) 2015 Glyptodon LLC | ||||
|  * | ||||
|  * Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|  * of this software and associated documentation files (the "Software"), to deal | ||||
|  * in the Software without restriction, including without limitation the rights | ||||
|  * to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
|  * copies of the Software, and to permit persons to whom the Software is | ||||
|  * furnished to do so, subject to the following conditions: | ||||
|  * | ||||
|  * The above copyright notice and this permission notice shall be included in | ||||
|  * all copies or substantial portions of the Software. | ||||
|  * | ||||
|  * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|  * IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|  * FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
|  * AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
|  * LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
|  * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
|  * THE SOFTWARE. | ||||
|  */ | ||||
|  | ||||
| .pager { | ||||
|     text-align: center; | ||||
|     margin: 1em; | ||||
| } | ||||
|  | ||||
| .pager .page-numbers { | ||||
|     display: inline-block; | ||||
|     margin: 0; | ||||
|     padding: 0; | ||||
| } | ||||
|  | ||||
| .pager .first-page, | ||||
| .pager .prev-page, | ||||
| .pager .set-page, | ||||
| .pager .next-page, | ||||
| .pager .last-page { | ||||
|     cursor: pointer; | ||||
|     vertical-align: middle; | ||||
| } | ||||
|  | ||||
| .pager .first-page.disabled, | ||||
| .pager .prev-page.disabled, | ||||
| .pager .set-page.disabled, | ||||
| .pager .next-page.disabled, | ||||
| .pager .last-page.disabled { | ||||
|     cursor: auto; | ||||
|     opacity: 0.25; | ||||
| } | ||||
|  | ||||
| .pager .set-page, | ||||
| .pager .more-pages { | ||||
|     display: inline-block; | ||||
|     padding: 0.25em; | ||||
|     text-align: center; | ||||
|     min-width: 1.25em; | ||||
| } | ||||
|  | ||||
| .pager .set-page { | ||||
|     text-decoration: underline; | ||||
| } | ||||
|  | ||||
| .pager .set-page.current { | ||||
|     cursor: auto; | ||||
|     text-decoration: none; | ||||
|     font-weight: bold; | ||||
|     background: rgba(0, 0, 0, 0.1); | ||||
|     border: 1px solid rgba(0, 0, 0, 0.1); | ||||
|     -moz-border-radius: 0.2em; | ||||
|     -webkit-border-radius: 0.2em; | ||||
|     -khtml-border-radius: 0.2em; | ||||
|     border-radius: 0.2em; | ||||
| } | ||||
|  | ||||
| .pager .icon.first-page { | ||||
|     background-image: url('images/action-icons/guac-first-page.png'); | ||||
| } | ||||
|  | ||||
| .pager .icon.prev-page { | ||||
|     background-image: url('images/action-icons/guac-prev-page.png'); | ||||
| } | ||||
|  | ||||
| .pager .icon.next-page { | ||||
|     background-image: url('images/action-icons/guac-next-page.png'); | ||||
| } | ||||
|  | ||||
| .pager .icon.last-page { | ||||
|     background-image: url('images/action-icons/guac-last-page.png'); | ||||
| } | ||||
							
								
								
									
										46
									
								
								guacamole/src/main/webapp/app/list/templates/guacPager.html
									
									
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								guacamole/src/main/webapp/app/list/templates/guacPager.html
									
									
									
									
									
										Normal file
									
								
							| @@ -0,0 +1,46 @@ | ||||
| <div class="pager" ng-show="pageNumbers.length > 1"> | ||||
|     <!-- | ||||
|        Copyright (C) 2015 Glyptodon LLC | ||||
|  | ||||
|        Permission is hereby granted, free of charge, to any person obtaining a copy | ||||
|        of this software and associated documentation files (the "Software"), to deal | ||||
|        in the Software without restriction, including without limitation the rights | ||||
|        to use, copy, modify, merge, publish, distribute, sublicense, and/or sell | ||||
|        copies of the Software, and to permit persons to whom the Software is | ||||
|        furnished to do so, subject to the following conditions: | ||||
|  | ||||
|        The above copyright notice and this permission notice shall be included in | ||||
|        all copies or substantial portions of the Software. | ||||
|  | ||||
|        THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR | ||||
|        IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, | ||||
|        FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE | ||||
|        AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER | ||||
|        LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, | ||||
|        OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN | ||||
|        THE SOFTWARE. | ||||
|     --> | ||||
|  | ||||
|     <!-- First / Previous --> | ||||
|     <div class="first-page icon" ng-class="{disabled: !canSelectPage(firstPage)}"    ng-click="selectPage(firstPage)"/> | ||||
|     <div class="prev-page icon"  ng-class="{disabled: !canSelectPage(previousPage)}" ng-click="selectPage(previousPage)"/> | ||||
|  | ||||
|     <!-- Indicator of the existence of pages before the first page number shown --> | ||||
|     <div class="more-pages" ng-show="hasMorePagesBefore()">...</div> | ||||
|      | ||||
|     <!-- Page numbers --> | ||||
|     <ul class="page-numbers"> | ||||
|         <li class="set-page" | ||||
|             ng-class="{current: isSelected(pageNumber)}" | ||||
|             ng-repeat="pageNumber in pageNumbers" | ||||
|             ng-click="selectPage(pageNumber)">{{pageNumber}}</li> | ||||
|     </ul> | ||||
|  | ||||
|     <!-- Indicator of the existence of pages beyond the last page number shown --> | ||||
|     <div class="more-pages" ng-show="hasMorePagesAfter()">...</div> | ||||
|  | ||||
|     <!-- Next / Last --> | ||||
|     <div class="next-page icon" ng-class="{disabled: !canSelectPage(nextPage)}" ng-click="selectPage(nextPage)"/> | ||||
|     <div class="last-page icon" ng-class="{disabled: !canSelectPage(lastPage)}" ng-click="selectPage(lastPage)"/> | ||||
|  | ||||
| </div> | ||||
		Reference in New Issue
	
	Block a user