PageSourceSearch

https://www.prpwine.com/wp-content/plugins/idstc-acuta/scripts/idstc/dirPagination.js?ver=3.1.20260923.1

js prpwine.com collected 2026-09-25 20:51:34 UTC 18,963 bytes, 396 lines download raw bytes

1/**
2 * dirPagination - AngularJS module for paginating (almost) anything.
3 *
4 *
5 * Credits
6 * =======
7 *
8 * Daniel Tabuenca: https://groups.google.com/d/msg/angular/an9QpzqIYiM/r8v-3W1X5vcJ
9 * for the idea on how to dynamically invoke the ng-repeat directive.
10 *
11 * I borrowed a couple of lines and a few attribute names from the AngularUI Bootstrap project:
12 * https://github.com/angular-ui/bootstrap/blob/master/src/pagination/pagination.js
13 *
14 * Copyright 2014 Michael Bromley <[email protected]>
15 * License: This code is made available under the MIT license, so feel free to use any of these is your projects. 
16 */
17
18(function () {
19
20    /**
21     * Config
22     */
23    var moduleName = 'angularUtils.directives.dirPagination';
24    var DEFAULT_ID = '__default';
25
26    /**
27     * Module
28     */
29    var module;
30    try {
31        module = angular.module(moduleName);
32    } catch (err) {
33        // named module does not exist, so create one
34        module = angular.module(moduleName, []);
35    }
36
37    module.directive('dirPaginate', ['$compile', '$parse', 'paginationService', function ($compile, $parse, paginationService) {
38
39        return {
40            terminal: true,
41            multiElement: true,
42            priority: 5000, // This setting is used in conjunction with the later call to $compile() to prevent infinite recursion of compilation
43            compile: function dirPaginationCompileFn(tElement, tAttrs
43) {
44
45                var expression = tAttrs.dirPaginate;
46                // regex taken directly from https://github.com/angular/angular.js/blob/master/src/ng/directive/ngRepeat.js#L211
47                var match = expression.match(/^\s*([\s\S]+?)\s+in\s+([\s\S]+?)(?:\s+track\s+by\s+([\s\S]+?))?\s*$/);
48
49                var filterPattern = /\|\s*itemsPerPage\s*:[^|]*/;
50                if (match[2].match(filterPattern) === null) {
51                    throw 'pagination directive: the \'itemsPerPage\' filter must be set.';
52                }
53                var itemsPerPageFilterRemoved = match[2].replace(filterPattern, '');
54                var collectionGetter = $parse(itemsPerPageFilterRemoved);
55
56                // If any value is specified for paginationId, we register the un-evaluated expression at this stage for the benefit of any
57                // dir-pagination-controls directives that may be looking for this ID.
58                var rawId = tAttrs.paginationId || DEFAULT_ID;
59                paginationService.registerInstance(rawId);
60
61                return function dirPaginationLinkFn(scope, element, attrs) {
62
63                    // Now that we have access to the `scope` we can interpolate any expression given in the paginationId attribute and
64                    // potentially register a new ID if it evaluates to a different value than the rawId.
65                    var paginationId = $parse(attrs.paginationId)(scope) || attrs.paginationId || DEFAULT_ID;
66                    paginationService.registerInstance(paginationId);
67
68                    var repeatExpression;
69                    var idDefinedInFilter = !!expression.match(/(\|\s*itemsPerPage\s*:[^|]*:[^|]*)/);
70                    if (paginationId !== DEFAULT_ID && !idDefinedInFilter) {
71                        repeatExpression = expression.replace(/(\|\s*itemsPerPage\s*:[^|]*)/, "$1 : '" + paginationId + "'");
72                    } else {
73                        repeatExpression = expression;
74                    }
75
76                    // Add ng-repeat to the dom element
77                    if (element[0].hasAttribute('dir-paginate-start') || element[0].hasAttribute('data-dir-paginate-start')) {
78                        // using multiElement mode (dir-paginate-start, dir-paginate-end)
79                        attrs.$set('ngRepeatStart', repeatExpression);
80                        element.eq(element.length - 1).attr('ng-repeat-end', true);
81                    } else {
82                        attrs.$set('ngRepeat', repeatExpression);
83                    }
84
85                    var compiled = $compile(element, false, 5000); // we manually compile the element again, as we have now added ng-repeat. Priority less than 5000 prevents infinite recursion of compiling dirPaginate
86
87                    var currentPageGetter;
88                    if (attrs.currentPage) {
89                        currentPageGetter = $parse(attrs.currentPage);
90                    } else {
91                        // if the current-page attribute was not set, we'll make our own
92                        var defaultCurrentPage = paginationId + '__currentPage';
93                        scope[defaultCurrentPage] = 1;
94                        currentPageGetter = $parse(defaultCurrentPage);
95                    }
96                    paginationService.setCurrentPageParser(paginationId, currentPageGetter, scope);
97
98                    if (typeof attrs.totalItems !== 'undefined') {
99                        paginationService.setAsyncModeTrue(paginationId);
100                        scope.$watch(function () {
101                            return $parse(attrs.totalItems)(scope);
102                        }, function (result) {
103                            if (0 <= result) {
104                                paginationService.setCollectionLength(paginationId, result);
105                            }
106                        });
107                    } else {
108                        scope.$watchCollection(function () {
109                            return collectionGetter(scope);
110                        }, function (collection) {
111                            if (collection) {
112                                paginationService.setCollectionLength(paginationId, collection.length);
113                            }
114                        });
115                    }
116
117                    // Delegate to the link function returned by the new compilation of the ng-repeat
118                    compiled(scope);
119                };
120            }
121        };
122    }]);
123
124    module.directive('dirPaginationControls', ['paginationService', '$location', '$rootScope', function (paginationService, $location, $rootScope) {
125
126        var numberRegex = /^\d+$/;
127
128        /**
129         * Generate an array of page numbers (or the '...' string) 
129which is used in an ng-repeat to generate the
130         * links used in pagination
131         *
132         * @param currentPage
133         * @param rowsPerPage
134         * @param paginationRange
135         * @param collectionLength
136         * @returns {Array}
137         */
138        function generatePagesArray(currentPage, collectionLength, rowsPerPage, paginationRange) {
139            var pages = [];
140            var totalPages = Math.ceil(collectionLength / rowsPerPage);
141            var halfWay = Math.ceil(paginationRange / 2);
142            var position;
143
144            if (currentPage <= halfWay) {
145                position = 'start';
146            } else if (totalPages - halfWay < currentPage) {
147                position = 'end';
148            } else {
149                position = 'middle';
150            }
151
152            var ellipsesNeeded = paginationRange < totalPages;
153            var i = 1;
154            while (i <= totalPages && i <= paginationRange) {
155                var pageNumber = calculatePageNumber(i, currentPage, paginationRange, totalPages);
156
157                var openingEllipsesNeeded = (i === 2 && (position === 'middle' || position === 'end'));
158                var closingEllipsesNeeded = (i === paginationRange - 1 && (position === 'middle' || position === 'start'));
159                if (ellipsesNeeded && (openingEllipsesNeeded || closingEllipsesNeeded)) {
160                    pages.push('...');
161                } else {
162                    pages.push(pageNumber);
163                }
164                i++;
165            }
166            return pages;
167        }
168
169        /**
170         * Given the position in the sequence of pagination links [i], figure out what page number corresponds to that position.
171         *
172         * @param i
173         * @param currentPage
174         * @param paginationRange
175         * @param totalPages
176         * @returns {*}
177         */
178        function calculatePageNumber(i, currentPage, paginationRange, totalPages) {
179            var halfWay = Math.ceil(paginationRange / 2);
180            if (i === paginationRange) {
181                return totalPages;
182            } else if (i === 1) {
183                return i;
184            } else if (paginationRange < totalPages) {
185                if (totalPages - halfWay < currentPage) {
186                    return totalPages - paginationRange + i;
187                } else if (halfWay < currentPage) {
188                    return currentPage - halfWay + i;
189                } else {
190                    return i;
191                }
192            } else {
193                return i;
194            }
195        }
196
197        return {
198            restrict: 'AE',
199            template: "\n<ul class=\"pagination\" >\n <li ng-if=\"boundaryLinks\" ng-class=\"{ disabled : pagination.current == 1 }\">\n        <a href=\"\" ng-click=\"setCurrent(1)\">&laquo;</a>\n    </li>\n    <li ng-if=\"directionLinks\" ng-class=\"{ disabled : pagination.current == 1 }\">\n        <a href=\"\" ng-click=\"setCurrent(pagination.current - 1)\">&lsaquo;</a>\n    </li>\n    <li ng-repeat=\"pageNumber in pages track by $index\" ng-class=\"{ active : pagination.current == pageNumber, disabled : pageNumber == '...' }\">\n        <a href=\"\" ng-click=\"setCurrent(pageNumber)\">{{ pageNumber }}</a>\n    </li>\n\n    <li ng-if=\"directionLinks\" ng-class=\"{ disabled : pagination.current == pagination.last }\">\n        <a href=\"\" ng-click=\"setCurrent(pagination.current + 1)\">&rsaquo;</a>\n    </li>\n    <li ng-if=\"boundaryLinks\" ng-class=\"{ disabled : pagination.current == pagination.last }\">\n        <a href=\"\" ng-click=\"setCurrent(pagination.last)\">&raquo;</a>\n    </li>\n</ul>\n",
200            scope: {
201                maxSize: '=?',
202                onPageChange: '&?',
203                paginationId: '=?'
204            },
205            link: function dirPaginationControlsLinkFn(scope, element, attrs) {
206
207                // rawId is the un-interpolated value of the pagination-id attribute. This is only important when the corresponding dir-paginate directive has
208                // not yet been linked (e.g. if it is inside an ng-if block), and in that case it prevents this controls directive from assuming that there is
209                // no corresponding dir-paginate directive and wrongly throwing an exception.
210                var rawId = attrs.paginationId || DEFAULT_ID;
211                var paginationId = scope.paginationId || attrs.paginationId || DEFAULT_ID;
212
213                if (!paginationService.isRegistered(paginationId) && !paginationService.isRegistered(rawId)) {
214                    var idMessage = (paginationId !== DEFAULT_ID) ? ' (id: ' + paginationId + ') ' : ' ';
215                    throw 'pagination directive: the pagination controls' + idMessage + 'cannot be used without the corresponding pagination directive.';
216                }
217
218                if (!scope.maxSize) { scope.maxSize = 9; }
219                scope.directionLinks = angular.isDefined(attrs.directionLinks) ? scope.$parent.$eval(attrs.directionLinks) : true;
220                scope.boundaryLinks = angular.isDefined(attrs.boundaryLinks) ? scope.$parent.$eval(attrs.boundaryLinks) : false;
221
222                var paginationRange = Math.max(scope.maxSize, 5);
223                scope.pages = [];
224                scope.pagination = {
225                    last: 1,
226                    current: 1
227                };
228                scope.range = {
229                    lower: 1,
230                    upper: 1,
231                    total: 1
232                };
233
234                scope.$watch(function () {
235                    return (paginationService.getCollectionLength(paginationId) + 1) * paginationService.getItemsPerPage(paginationId);
236                }, function (length) {
237                    if (0 < length) {
238                        generatePagination();
239                    }
240                });
241
242                scope.$watch(function () {
243                    return (paginationService.getItemsPerPage(paginationId));
244                }, function (current, previous) {
245                    if (current != previous) {
246                        goToPage(scope.pagination.current);
247                    }
248                });
249
250                scope.$watch(function () {
251                    return paginationService.getCurrentPage(paginationId);
252                }, function (currentPage, previousPage) {
253                    if (currentPage != previousPage) {
254                        goToPage(currentPage);
255                    }
256                });
257
258                scope.setCurrent = function (num) {
259                    if (isValidPageNumber(num)) {                        
260                        paginationService.setCurrentPage(paginationId, num);
261                    }
262                };
263
264                function goToPage(num) {
265                    if (isValidPageNumber(num)) {
266                        scope.pages = generatePagesArray(num, paginationService.getCollectionLength(paginationId), paginationService.getItemsPerPage(paginationId), paginationRange);
267                        scope.pagination.current = num;
268                        updateRangeValues();
269                                                
270                        // if a callback has been set, then call it with the page number as an argument
271                        if (scope.onPageChange) {
272                            scope.onPageChange({ newPageNumber: num });
273                        }
274                        $('html,body').scrollTop(0);
275                    }
276                }
277
278                function generatePagination() {
279                    var page = parseInt(paginationService.getCurrentPage(paginationId)) || 1;
280
281                    scope.pages = generatePagesArray(page, paginationService.getCollectionLength(paginationId), paginationService.getItemsPerPage(paginationId), paginationRange);
282                    scope.pagination.current = page;
283                    scope.pagination.last = scope.pages[scope.pages.length - 1];
284                    if (scope.pagination.last < scope.pagination.current) {
285                        scope.setCurrent(scope.pagination.last);
286                    } else {
287                        updateRangeValues();
288                    }
289                }
290
291                /**
292                 * This function updates the values (lower, upper, total) of the `scope.range` object, which can be used in the pagination
293                 * template to display the current page range, e.g. "showing 21 - 40 of 144 results";
294                 */
295                function updateRangeValues() {
296                    var currentPage = paginationService.getCurrentPage(paginationId),
297                        itemsPerPage = paginationService.getItemsPerPage(paginationId),
298                        totalItems = paginationService.getCollectionLength(paginationId);
299
300                    scope.range.lower = (currentPage - 1) * itemsPerPage + 1;
301                    scope.range.upper = Math.min(currentPage * itemsPerPage, totalItems);
302                    scope.range.total = totalItems;
303                }
304
305                function isValidPageNumber(num) {
306                    return (numberRegex.test(num) && (0 < num && num <= scope.pagination.last));
307                }
308            }
309        };
310    }]);
311
312    module.filter('itemsPerPage', ['paginationService', function (paginationService) {
313
314        return function (collection, itemsPerPage, paginationId) {
315            if (typeof (paginationId) === 'undefined') {
316                paginationId = DEFAULT_ID;
317            }
318            if (!paginationService.isRegistered(paginationId)) {
319                throw 'pagination directive: the itemsPerPage id argument (id: ' + paginationId + ') does not match a registered pagination-id.';
320            }
321            var end;
322            var start;
323            if (collection instanceof Array) {
324                itemsPerPage = parseInt(itemsPerPage) || 9999999999;
325                if (paginationService.isAsyncMode(paginationId)) {
326                    start = 0;
327                } else {
328                    start = (paginationService.getCurrentPage(paginationId) - 1) * itemsPerPage;
329                }
330                end = start + itemsPerPage;
331                paginationService.setItemsPerPage(paginationId, itemsPerPage);
332
333                return collection.slice(start, end);
334            } else {
335                return collection;
336            }
337        };
338    }]);
339
340    module.service('paginationService', function () {
341
342        var instances = {};
343        var lastRegisteredInstance;
344
345        this.registerInstance = function (instanceId) {
346            if (typeof instances[instanceId] === 'undefined') {
347                instances[instanceId] = {
348                    asyncMode: false
349                };
350                lastRegisteredInstance = instanceId;
351            }
352        };
353
354        this.isRegistered = function (instanceId) {
355            return (typeof instances[instanceId] !== 'undefined');
356        };
357
358        this.getLastInstanceId = function () {
359            return lastRegisteredInstance;
360        };
361
362        this.setCurrentPageParser = function (instanceId, val, scope) {
363            instances[instanceId].currentPageParser = val;
364            instances[instanceId].context = scope;
365        };
366        this.setCurrentPage = function (instanceId, val) {
367            instances[instanceId].currentPageParser.assign(instances[instanceId].context, val);
368        };
369        this.getCurrentPage = function (instanceId) {
370            var parser = instances[instanceId].currentPageParser;
371            return parser ? parser(instances[instanceId].context) : 1;
372        };
373
374        this.setItemsPerPage = function (instanceId, val) {
375            instances[instanceId].itemsPerPage = val;
376        };
377        this.getItemsPerPage = function (instanceId) {
378            return instances[instanceId].itemsPerPage;
379        };
380
381        this.setCollectionLength = function (instanceId, val) {
382            instances[instanceId].collectionLength = val;
383        };
384        this.getCollectionLength = function (instanceId) {
385            return instances[instanceId].collectionLength;
386        };
387
388        this.setAsyncModeTrue = function (instanceId) {
389            instances[instanceId].asyncMode = true;
390        };
391
392        this.isAsyncMode = function (instanceId) {
393            return instances[instanceId].asyncMode;
394        };
395    });        
396})();

Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.