Vue
by Dominic Myers
HTML
<script src="https://cdnjs.cloudflare.com/ajax/libs/vue/2.7.14/vue.min.js"></script>
<div id="app">
<ol v-if="totalPages > 0"
aria-label="Pagination navigation">
<li v-on:click="paginationOptions.page = 1"
aria-label="Go to the first page"
title="Go to the first page"
v-bind:class="{
'disabled': paginationOptions.page === 1
}">
<div class="content">←</div>
</li>
<li v-if="totalPages > 3 && paginationOptions.page - 2 >= 1"
v-on:click="paginationOptions.page = (paginationOptions.page - 3 < 1) ? 1 : paginationOptions.page - 3"
aria-label="Jump three pages backward"
title="Jump three pages backward"><div class="content">…</div></li>
<li v-for="page in pages"
v-bind:key="page"
v-on:click="paginationOptions.page = page"
v-bind:aria-label="(page === paginationOptions.page) ? 'Current page, page ' + page : 'Go to page ' + page"
v-bind:aria-current="page === paginationOptions.page"
v-bind:title="(page === paginationOptions.page) ? 'Current page, page ' + page : 'Go to page ' + page"
v-bind:class="{
'active': page === paginationOptions.page
}">
<div class="content">{{page}}</div>
<span v-if="page === paginationOptions.page"
style="display: none">(current)</span>
</li>
<li v-if="totalPages > 3 && paginationOptions.page + 2 <= totalPages"
v-on:click="paginationOptions.page = (paginationOptions.page + 3 <= totalPages) ? paginationOptions.page + 3 : totalPages"
aria-label="Jump three pages forward"
title="Jump three pages forward"><div class="content">…</div></li>
<li v-on:click="paginationOptions.page = totalPages"
aria-label="Go to the last page"
title="Go to the last page"
...
SCSS
#app{
margin: 1em;
}
ol {
display: flex;
align-items: center;
justify-content: flex-end;
margin: 0;
padding: 0;
list-style-type: none;
width: 100%;
text-align: right;
li{
display: inline-block;
&.disabled {
cursor: not-allowed;
}
.content {
text-decoration: none;
font-weight: bold;
background-color: #fff;
color: #7f8c8d;
display: flex;
align-items: center;
justify-content: center;
width: 40px;
height: 40px;
margin: 0 3px;
border: 1px solid #e5e5e5;
}
&.active {
.content {
border-color: #2c3e50;
background-color: #2c3e50;
color: #fff;
text-decoration: none;
}
}
}
}
JavaScript
new Vue({
el: "#app",
data: {
paginationOptions: {
page: 2,
total: 45,
pageSize: 10
}
},
computed: {
totalPages() {
return Math.ceil(this.paginationOptions.total / this.paginationOptions.pageSize);
},
pages: () => {
const returnArray = [];
if(this.paginationOptions.page === 1){
for(i = 1, count = 0; i <= this.totalPages && count < 3; i++, count++){
returnArray.push(i)
}
} else {
if(this.paginationOptions.page === this.totalPages){
for(let i = this.totalPages, count = 0; i >= 1 && count < 3; i--, count++){
returnArray.push(i)
}
returnArray.reverse();
} else {
returnArray.push(this.paginationOptions.page);
if(this.paginationOptions.page < this.totalPages){
returnArray.push(this.paginationOptions.page + 1)
}
if(this.paginationOptions.page >= 1){
returnArray.unshift(this.paginationOptions.page - 1)
}
}
}
return returnArray;
},
}
});