Pagination.js 5.96 KB
define(function(require) {
    'use strict';
    var Backbone = require('backbone');
    var Util = require('./Util');

    var Pagination = Backbone.Model.extend({
        defaults: function defaults() {
            return {
                currentPage: 1,
                hasNext: false,
                hasNextJump: false,
                hasPrevious: false,
                hasPreviousJump: false,
                nextJumpPage: undefined,
                nextPage: undefined,
                pages: [],
                pageJump: 5,
                pageSize: 10,
                previousJumpPage: undefined,
                previousPage: undefined,
                totalCount: 0,
                totalPages: 0,
            };
        },
        initialize: function(data, options) {
            var buildPages = function buildPages() {
                var currentPage = parseInt(this.get('currentPage'));
                var pageSize = parseInt(this.get('pageSize'));
                var totalCount = parseInt(this.get('totalCount'));
                if (!totalCount) {
                    return;
                }
                var pages = [];
                var totalPages = Math.floor((totalCount + pageSize - 1) / pageSize);
                if (currentPage < 0) {
                    this.set('currentPage', 1);
                    return;
                } else if (currentPage > totalPages) {
                    this.set('currentPage', totalPages);
                    return;
                }
                function addPage(self, i) {
                    pages.push({
                        current: i === currentPage,
                        jump: function() {
                            self.set('currentPage', i);
                            return true;
                        },
                        number: i,
                    });
                }
                var startAt = currentPage - 4, endAt = currentPage + 5;
                if (startAt < 1) {
                    endAt += (1 - startAt);
                }
                if (endAt > totalPages) {
                    startAt -= endAt - totalPages - 1;
                    endAt = totalPages + 1;
                }
                if (startAt < 1) {
                    startAt = 1;
                }
                if (endAt - startAt < 9) {
                    ///* global console:false */
                    //console.log('foo');
                }

                for (var i = startAt; i < endAt; i++) {
                    addPage(this, i);
                }
                var hasPrevious = currentPage > 1;
                var hasNext = currentPage < totalPages;
                var pageJump = this.get('pageJump');
                var nextJumpPage, previousJumpPage, hasNextJump, hasPreviousJump;
                if (pageJump) {
                    nextJumpPage = currentPage + pageJump;
                    previousJumpPage = currentPage - pageJump;
                    hasNextJump = nextJumpPage < totalPages;
                    hasPreviousJump = previousJumpPage > 0;
                } else {
                    hasNextJump = false;
                    hasPreviousJump = false;
                }
                this.set({
                    hasNext: hasNext,
                    hasNextJump: hasNextJump,
                    hasPrevious: hasPrevious,
                    hasPreviousJump: hasPreviousJump,
                    nextJumpPage: hasNextJump ? nextJumpPage : undefined,
                    nextPage: hasNext ? currentPage + 1 : undefined,
                    pages: pages,
                    previousJumpPage: hasNextJump ? previousJumpPage : undefined,
                    previousPage: hasPrevious ? currentPage - 1 : undefined,
                    totalPages: totalPages,
                });
            };
            this.on('change:pageSize change:currentPage change:totalCount', buildPages, this);
            var installActions = _.bind(function installActions(eventName, nextName, hasNextName, previousName, hasPreviousName, pageCount) {
                this.on(eventName, function() {
                    var hasNext = this.get(hasNextName);
                    var hasPrevious = this.get(hasPreviousName);
                    var next, previous;
                    if (hasNext) {
                        next = _.bind(function(e) {
                            Util.preventDefault(e);
                            this.set('currentPage', this.get('currentPage') + pageCount);
                            return false;
                        }, this);
                    } else {
                        next = Util.stepFalse;
                    }
                    if (hasPrevious) {
                        previous = _.bind(function(e) {
                            Util.preventDefault(e);
                            this.set('currentPage', this.get('currentPage') - pageCount);
                            return false;
                        }, this);
                    } else {
                        previous = Util.stepFalse;
                    }
                    this.set(nextName, next);
                    this.set(previousName, previous);
                }, this);
                this[nextName] = _.bind(function() {
                    return this.get(nextName)();
                }, this);
                this[previousName] = _.bind(function() {
                    return this.get(previousName)();
                }, this);
            }, this);
            this.on('change:pageJump', function() {
                var pageJump = this.get('pageJump');
                installActions('change:hasNextJump change:hasPreviousJump', 'nextJump', 'hasNextJump', 'previousJump', 'hasPreviousJump', pageJump);
            }, this);
            installActions('change:hasNext change:hasPrevious', 'next', 'hasNext', 'previous', 'hasPrevious', 1);
            buildPages.apply(this);
            this.trigger('change:pageJump');
            return Pagination.__super__.initialize.apply(this, arguments);
        }
    });
    return Pagination;
});