├── README.md ├── demo ├── index.html ├── vue-pagination.js └── vue-table.js ├── dist ├── vue-pagination.js └── vue-pagination.vue └── templates ├── bootstrap-table.tpl.html ├── bootstrap.tpl.html └── semantic.tpl.html /README.md: -------------------------------------------------------------------------------- 1 | # vue-pagination 2 | pagination for vue.js 3 | -------------------------------------------------------------------------------- /demo/index.html: -------------------------------------------------------------------------------- 1 |  2 | 3 | 4 | Vue Pagination Demo 5 | 6 | 7 | 8 | 9 |
10 |
11 |
12 |
13 | 14 |
15 |
16 |
17 |
18 | 19 | 20 | 21 | 22 | 23 | 24 | 64 | 65 | 88 | 89 | -------------------------------------------------------------------------------- /demo/vue-pagination.js: -------------------------------------------------------------------------------- 1 | (function (Vue) { 2 | 3 | Vue.component('pagination', { 4 | props: { 5 | pageNo: { 6 | twoWay: true, 7 | type: Number, 8 | validator: function (value) { 9 | return value > 0 10 | }, 11 | default: 1 12 | }, 13 | pageSize: { 14 | twoWay: true, 15 | type: Number, 16 | validator: function (value) { 17 | return value > 0 18 | }, 19 | default: 10 20 | }, 21 | totalResult: { 22 | type: Number, 23 | default: 0 24 | }, 25 | displayNum: { 26 | type: Number, 27 | default: 6 28 | }, 29 | edgeNum: { 30 | type: Number, 31 | default: 2 32 | }, 33 | }, 34 | template: "", 35 | replace: true, 36 | inherit: false, 37 | computed: { 38 | noPrevious: function () { 39 | return this.pageNo === 1; 40 | }, 41 | noNext: function () { 42 | return this.pageNo === this.totalPages; 43 | }, 44 | pages: function () { 45 | return getPages(this.pageNo, this.totalPages, this.edgeNum, this.displayNum); 46 | }, 47 | totalPages: function () { 48 | return getTotalPages(this.pageSize, this.totalResult); 49 | }, 50 | }, 51 | methods: { 52 | selectPage: function (num) { 53 | if (this.pageNo != num && num > 0 && num <= this.totalPages) { 54 | this.pageNo = num; 55 | this.$emit('page-change'); 56 | } 57 | }, 58 | selectSize: function (size) { 59 | if (this.pageSize != size && size > 0) { 60 | this.pageSize = size; 61 | if (this.pageNo > this.totalPages) { 62 | this.selectPage(this.totalPages); 63 | } 64 | else { 65 | this.$emit('page-change'); 66 | } 67 | } 68 | }, 69 | }, 70 | }); 71 | 72 | function getTotalPages(pageSize, totalResult) { 73 | var totalPages = pageSize < 1 ? 1 : Math.ceil(totalResult / pageSize); 74 | return Math.max(totalPages || 0, 1); 75 | } 76 | 77 | // Create page object used in template 78 | function makePage(number, text, isActive) { 79 | return { 80 | number: number, 81 | text: text, 82 | disabled: number === -1, 83 | }; 84 | } 85 | 86 | /** 87 | * Calculate start and end point of pagination links depending on 88 | * currentPage and num_display_entries. 89 | * @return {Array} 90 | */ 91 | function getInterval(currentPage, pageCount, num_display_entries) { 92 | //var num_display_entries = 6; 93 | var ne_half = Math.ceil(num_display_entries / 2); 94 | var np = pageCount; 95 | var upper_limit = np - num_display_entries; 96 | var start = currentPage > ne_half ? Math.max(Math.min(currentPage - ne_half, upper_limit), 0) : 0; 97 | var end = currentPage > ne_half ? Math.min(currentPage + ne_half, np) : Math.min(num_display_entries, np); 98 | return [start, end]; 99 | } 100 | 101 | function getPages(currentPage, totalPages, num_edge_entries, num_display_entries) { 102 | var ret = []; 103 | //var num_edge_entries = 2; 104 | var skip_text = '...'; 105 | var np = totalPages; 106 | var interval = getInterval(currentPage - 1, totalPages, num_display_entries); 107 | 108 | // Generate starting points 109 | if (interval[0] > 0 && num_edge_entries > 0) { 110 | var end = Math.min(num_edge_entries, interval[0]); 111 | for (var i = 0; i < end; i++) { 112 | var page = makePage(i + 1, i + 1); 113 | ret.push(page); 114 | } 115 | if (num_edge_entries < interval[0]) { 116 | var page = makePage(-1, skip_text); 117 | ret.push(page); 118 | } 119 | } 120 | // Generate interval links 121 | for (var i = interval[0]; i < interval[1]; i++) { 122 | var page = makePage(i + 1, i + 1); 123 | ret.push(page); 124 | } 125 | // Generate ending points 126 | if (interval[1] < np && num_edge_entries > 0) { 127 | if (np - num_edge_entries > interval[1]) { 128 | var page = makePage(-1, skip_text); 129 | ret.push(page); 130 | } 131 | var begin = Math.max(np - num_edge_entries, interval[1]); 132 | for (var i = begin; i < np; i++) { 133 | var page = makePage(i + 1, i + 1); 134 | ret.push(page); 135 | } 136 | } 137 | 138 | return ret; 139 | } 140 | 141 | })(Vue) -------------------------------------------------------------------------------- /demo/vue-table.js: -------------------------------------------------------------------------------- 1 | (function (Vue) { 2 | 3 | Vue.directive('selectAll', { 4 | params: ['array'], 5 | twoWay: true, 6 | deep: true, 7 | bind: function () { 8 | var self = this; 9 | this.handler = function () { 10 | var arr = self.vm.$get(self.expression); 11 | arr.forEach(function (t) { 12 | t.$checked = self.el.checked; 13 | }); 14 | }.bind(this) 15 | this.el.addEventListener('click', this.handler) 16 | }, 17 | update: function (newVal) { 18 | var count = 0; 19 | newVal.forEach(function (t) { 20 | if (t.$checked) count++; 21 | }) 22 | var checked = newVal.length === count; 23 | this.el.checked = checked; 24 | //this.el.indeterminate = !checked && newVal.length > 0; 25 | }, 26 | unbind: function () { 27 | this.el.removeEventListener('click', this.handler) 28 | } 29 | }) 30 | 31 | Vue.component('vTable', { 32 | props: ['filters', 'url', 'tpl'], 33 | created: function () { 34 | this.$options.template = this.tpl || '#table-tpl'; 35 | this.queryChange(); 36 | }, 37 | data: function () { 38 | return { 39 | checklist: [], 40 | items: [], 41 | pageNo: 1, 42 | pageSize: 10, 43 | totalResult: 0, 44 | orderBy: null, 45 | isDesc: false, 46 | loading: false, 47 | }; 48 | }, 49 | template: '#table-tpl', 50 | replace: true, 51 | inherit: false, 52 | computed: { 53 | 54 | }, 55 | methods: { 56 | queryChange: function () { 57 | this.pageChange(1); 58 | }, 59 | pageChange: function () { 60 | if (this.loading) return; 61 | this.loading = true; 62 | this.$http.get(this.url, { 63 | limit: this.pageSize, 64 | offset: (this.pageNo - 1) * this.pageSize, 65 | }).then(function (response) { 66 | response.data.objects.forEach(function (t) { 67 | t.$checked = false; 68 | }) 69 | this.items = response.data.objects; 70 | this.totalResult = response.data.meta.total_count; 71 | this.loading = false; 72 | }); 73 | }, 74 | orderChange: function (colName) { 75 | if (this.orderBy == colName) { 76 | this.isDesc = !this.isDesc; 77 | } 78 | else { 79 | this.orderBy = colName; 80 | this.isDesc = false; 81 | } 82 | this.queryChange(); 83 | }, 84 | } 85 | }); 86 | 87 | })(Vue) -------------------------------------------------------------------------------- /dist/vue-pagination.js: -------------------------------------------------------------------------------- 1 | (function (Vue) { 2 | 3 | Vue.component('pagination', { 4 | props: { 5 | pageNo: { 6 | twoWay: true, 7 | type: Number, 8 | validator: function (value) { 9 | return value > 0 10 | }, 11 | default: 1 12 | }, 13 | pageSize: { 14 | twoWay: true, 15 | type: Number, 16 | validator: function (value) { 17 | return value > 0 18 | }, 19 | default: 10 20 | }, 21 | totalResult: { 22 | type: Number, 23 | default: 0 24 | }, 25 | displayNum: { 26 | type: Number, 27 | default: 6 28 | }, 29 | edgeNum: { 30 | type: Number, 31 | default: 2 32 | }, 33 | }, 34 | template: "", 35 | replace: true, 36 | inherit: false, 37 | computed: { 38 | noPrevious: function () { 39 | return this.pageNo === 1; 40 | }, 41 | noNext: function () { 42 | return this.pageNo === this.totalPages; 43 | }, 44 | pages: function () { 45 | return getPages(this.pageNo, this.totalPages, this.edgeNum, this.displayNum); 46 | }, 47 | totalPages: function () { 48 | return getTotalPages(this.pageSize, this.totalResult); 49 | }, 50 | startIndex: function () { 51 | return Math.min(this.totalResult, (this.pageNo - 1) * this.pageSize + 1); 52 | }, 53 | endIndex: function () { 54 | return Math.min(this.totalResult, this.pageNo * this.pageSize); 55 | } 56 | }, 57 | methods: { 58 | selectPage: function (num) { 59 | if (this.pageNo != num && num > 0 && num <= this.totalPages) { 60 | this.pageNo = num; 61 | this.$dispatch('page-change'); 62 | } 63 | }, 64 | selectSize: function (size) { 65 | if (this.pageSize != size && size > 0) { 66 | this.pageSize = size; 67 | if (this.pageNo > this.totalPages) { 68 | this.selectPage(this.totalPages); 69 | } 70 | else { 71 | this.$dispatch('page-change'); 72 | } 73 | } 74 | }, 75 | }, 76 | }); 77 | 78 | function getTotalPages(pageSize, totalResult) { 79 | var totalPages = pageSize < 1 ? 1 : Math.ceil(totalResult / pageSize); 80 | return Math.max(totalPages || 0, 1); 81 | } 82 | 83 | // Create page object used in template 84 | function makePage(number, text, isActive) { 85 | return { 86 | number: number, 87 | text: text, 88 | disabled: number === -1, 89 | }; 90 | } 91 | 92 | /** 93 | * Calculate start and end point of pagination links depending on 94 | * currentPage and num_display_entries. 95 | * @return {Array} 96 | */ 97 | function getInterval(currentPage, pageCount, num_display_entries) { 98 | //var num_display_entries = 6; 99 | var ne_half = Math.ceil(num_display_entries / 2); 100 | var np = pageCount; 101 | var upper_limit = np - num_display_entries; 102 | var start = currentPage > ne_half ? Math.max(Math.min(currentPage - ne_half, upper_limit), 0) : 0; 103 | var end = currentPage > ne_half ? Math.min(currentPage + ne_half, np) : Math.min(num_display_entries, np); 104 | return [start, end]; 105 | } 106 | 107 | function getPages(currentPage, totalPages, num_edge_entries, num_display_entries) { 108 | var ret = []; 109 | //var num_edge_entries = 2; 110 | var skip_text = '...'; 111 | var np = totalPages; 112 | var interval = getInterval(currentPage - 1, totalPages, num_display_entries); 113 | 114 | // Generate starting points 115 | if (interval[0] > 0 && num_edge_entries > 0) { 116 | var end = Math.min(num_edge_entries, interval[0]); 117 | for (var i = 0; i < end; i++) { 118 | var page = makePage(i + 1, i + 1); 119 | ret.push(page); 120 | } 121 | if (num_edge_entries < interval[0]) { 122 | var page = makePage(-1, skip_text); 123 | ret.push(page); 124 | } 125 | } 126 | // Generate interval links 127 | for (var i = interval[0]; i < interval[1]; i++) { 128 | var page = makePage(i + 1, i + 1); 129 | ret.push(page); 130 | } 131 | // Generate ending points 132 | if (interval[1] < np && num_edge_entries > 0) { 133 | if (np - num_edge_entries > interval[1]) { 134 | var page = makePage(-1, skip_text); 135 | ret.push(page); 136 | } 137 | var begin = Math.max(np - num_edge_entries, interval[1]); 138 | for (var i = begin; i < np; i++) { 139 | var page = makePage(i + 1, i + 1); 140 | ret.push(page); 141 | } 142 | } 143 | 144 | return ret; 145 | } 146 | 147 | })(Vue) -------------------------------------------------------------------------------- /dist/vue-pagination.vue: -------------------------------------------------------------------------------- 1 |  20 | 21 | 167 | -------------------------------------------------------------------------------- /templates/bootstrap-table.tpl.html: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /templates/bootstrap.tpl.html: -------------------------------------------------------------------------------- 1 |  -------------------------------------------------------------------------------- /templates/semantic.tpl.html: -------------------------------------------------------------------------------- 1 |  --------------------------------------------------------------------------------