Skip to content
Snippets Groups Projects
Pagination.vue 3.29 KiB
Newer Older
Florent Lavelle's avatar
dev
Florent Lavelle committed
<template>
  <div style="display: flex;">
    <nav style="margin: 0 auto;">
      <ul class="pagination">
        <li
          class="page-item"
          :class="{ disabled: page === 1 }"
        >
          <a
            class="page-link"
            href="#"
            @click="page -= 1"
          >
            <b-icon icon="chevron-left" scale="1.5"></b-icon>
          </a>
        </li>
        <div v-if="nbPages > 5" style="display: contents;">
          <li
            v-for="index in pagination(page, nbPages)"
            :key="index"
            class="page-item"
            :class="{ active: page === index }"
          >
            <a
              class="page-link"
              href="#"
              @click="changePage(index)"
            >
              {{ index }}
            </a>
          </li>
        </div>
        <div v-else style="display: contents;">
          <li
            v-for="index in nbPages"
            :key="index"
            class="page-item"
            :class="{ active: page === index }"
          >
            <a
              class="page-link"
              href="#"
              @click="page = index"
            >
              {{ index }}
            </a>
          </li>
        </div>
        <li
          class="page-item"
          :class="{ disabled: page === nbPages }"
        >
          <a
            class="page-link"
            href="#"
            @click="page += 1"
          >
            <b-icon icon="chevron-right" scale="1.5"></b-icon>
          </a>
        </li>
      </ul>
    </nav>
  </div>
</template>

<script>
export default {
  name: 'Pagination',

  props: {
    nbPages: {
      type: Number,
      default: 1
    },

    onPageChange: {
      type: Function,
      default: () => {
        return () => 1;
      }
    }
  },

  data() {
    return {
      page: 1
    }
  },

  watch: {
    page: function(newValue, oldValue) {
      if (newValue !== oldValue) {
        this.onPageChange(newValue);
        this.$emit('change-page', newValue);
      }
    }
  },

  methods: {
    pagination(c, m) {
      const current = c,
            last = m,
            delta = 2,
            left = current - delta,
            right = current + delta + 1,
            range = [],
            rangeWithDots = [];
      let   l;

      for (let i = 1; i <= last; i++) {
        if (i === 1 || i === last || i >= left && i < right) {
            range.push(i);
        }
      }
      for (const i of range) {
        if (l) {
          if (i - l === 2) {
              rangeWithDots.push(l + 1);
          } else if (i - l !== 1) {
              rangeWithDots.push('...');
          }
        }
        rangeWithDots.push(i);
        l = i;
      }

      return rangeWithDots;
    },

    changePage(num) {
      if (typeof num === 'number') {
        this.page = num;
      }
    }
  }
}
</script>

<style lang="less" scoped>
.pagination {
  .page-item {
    .page-link {
      border: none;
      font-weight: 400;
      color: #000000;
    }
  }
  .page-item.active {
    .page-link {
      color: #000000;
      background-color: transparent;
      font-weight: bolder;
      font-size: 1.2em;
      text-shadow: 0 0 2px #000000;
      padding: 0.325em 0.75em;
      pointer-events: none;
    }
  }
  .page-item.disabled {
    .page-link {
      opacity: 0.5;
    }
  }
}
</style>