189 changes: 104 additions & 85 deletions js/jquery.twbsPagination.js
@@ -1,12 +1,11 @@
/*!
* jQuery pagination plugin v1.2.6
* jQuery pagination plugin v1.4
* http://esimakin.github.io/twbs-pagination/
*
* Copyright 2014, Eugene Simakin
* Copyright 2014-2016, Eugene Simakin
* Released under Apache 2.0 license
* http://apache.org/licenses/LICENSE-2.0.html
*/
;
(function ($, window, document, undefined) {

'use strict';
Expand All @@ -33,19 +32,23 @@
throw new Error('Visible pages option is not correct!');
}

// hide if only one page exists
if (this.options.totalPages == 1) {
return this;
}

if (this.options.totalPages < this.options.visiblePages) {
this.options.visiblePages = this.options.totalPages;
}

if (this.options.onPageClick instanceof Function) {
this.$element.first().bind('page', this.options.onPageClick);
this.$element.first().on('page', this.options.onPageClick);
}

if (this.options.href) {
var m, regexp = this.options.href.replace(/[-\/\\^$*+?.|[\]]/g, '\\$&');
regexp = regexp.replace(this.options.hrefVariable, '(\\d+)');
if ((m = new RegExp(regexp, 'i').exec(window.location.href)) != null) {
this.options.startPage = parseInt(m[1], 10);
this.options.startPage = this.getPageFromQueryString();
if (!this.options.startPage) {
this.options.startPage = 1;
}
}

Expand All @@ -64,11 +67,11 @@
this.$element.append(this.$listContainer);
}

this.render(this.getPages(this.options.startPage));
this.setupEvents();

if (this.options.initiateStartPageClick) {
this.$element.trigger('page', this.options.startPage);
this.show(this.options.startPage);
} else {
this.render(this.getPages(this.options.startPage));
this.setupEvents();
}

return this;
Expand All @@ -81,84 +84,64 @@
destroy: function () {
this.$element.empty();
this.$element.removeData('twbs-pagination');
this.$element.unbind('page');
this.$element.off('page');

return this;
},

show: function (page) {
if (page < 1 || page > this.options.totalPages) {
throw new Error('Page is incorrect.');
}
this.currentPage = page;

this.render(this.getPages(page));
this.setupEvents();

this.$element.trigger('page', page);

return this;
},

buildListItems: function (pages) {
var $listItems = $();
var listItems = [];

if (this.options.first) {
$listItems = $listItems.add(this.buildItem('first', 1));
listItems.push(this.buildItem('first', 1));
}

if (this.options.prev) {
var prev = pages.currentPage > 1 ? pages.currentPage - 1 : this.options.loop ? this.options.totalPages : 1;
$listItems = $listItems.add(this.buildItem('prev', prev));
listItems.push(this.buildItem('prev', prev));
}

for (var i = 0; i < pages.numeric.length; i++) {
$listItems = $listItems.add(this.buildItem('page', pages.numeric[i]));
listItems.push(this.buildItem('page', pages.numeric[i]));
}

if (this.options.next) {
var next = pages.currentPage < this.options.totalPages ? pages.currentPage + 1 : this.options.loop ? 1 : this.options.totalPages;
$listItems = $listItems.add(this.buildItem('next', next));
listItems.push(this.buildItem('next', next));
}

if (this.options.last) {
$listItems = $listItems.add(this.buildItem('last', this.options.totalPages));
listItems.push(this.buildItem('last', this.options.totalPages));
}

return $listItems;
return listItems;
},

buildItem: function (type, page) {
var itemContainer = $('<li></li>'),
itemContent = $('<a></a>'),
itemText = null;

switch (type) {
case 'page':
itemText = page;
itemContainer.addClass(this.options.pageClass);
break;
case 'first':
itemText = this.options.first;
itemContainer.addClass(this.options.firstClass);
break;
case 'prev':
itemText = this.options.prev;
itemContainer.addClass(this.options.prevClass);
break;
case 'next':
itemText = this.options.next;
itemContainer.addClass(this.options.nextClass);
break;
case 'last':
itemText = this.options.last;
itemContainer.addClass(this.options.lastClass);
break;
default:
break;
}
var $itemContainer = $('<li></li>'),
$itemContent = $('<a></a>'),
itemText = this.options[type] ? this.makeText(this.options[type], page) : page;

itemContainer.data('page', page);
itemContainer.data('page-type', type);
itemContainer.append(itemContent.attr('href', this.makeHref(page)).html(itemText));
return itemContainer;
$itemContainer.addClass(this.options[type + 'Class']);
$itemContainer.data('page', page);
$itemContainer.data('page-type', type);
$itemContainer.append($itemContent.attr('href', this.makeHref(page)).addClass(this.options.anchorClass).html(itemText));

return $itemContainer;
},

getPages: function (currentPage) {
Expand Down Expand Up @@ -188,9 +171,12 @@
},

render: function (pages) {
var that = this;
var _this = this;
this.$listContainer.children().remove();
this.$listContainer.append(this.buildListItems(pages));
var items = this.buildListItems(pages);
jQuery.each(items, function(key, item){
_this.$listContainer.append(item);
});

this.$listContainer.children().each(function () {
var $this = $(this),
Expand All @@ -199,21 +185,21 @@
switch (pageType) {
case 'page':
if ($this.data('page') === pages.currentPage) {
$this.addClass(that.options.activeClass);
$this.addClass(_this.options.activeClass);
}
break;
case 'first':
$this.toggleClass(that.options.disabledClass, pages.currentPage === 1);
$this.toggleClass(_this.options.disabledClass, pages.currentPage === 1);
break;
case 'last':
$this.toggleClass(that.options.disabledClass, pages.currentPage === that.options.totalPages);
$this.toggleClass(_this.options.disabledClass, pages.currentPage === _this.options.totalPages);
break;
case 'prev':
$this.toggleClass(that.options.disabledClass, !that.options.loop && pages.currentPage === 1);
$this.toggleClass(_this.options.disabledClass, !_this.options.loop && pages.currentPage === 1);
break;
case 'next':
$this.toggleClass(that.options.disabledClass,
!that.options.loop && pages.currentPage === that.options.totalPages);
$this.toggleClass(_this.options.disabledClass,
!_this.options.loop && pages.currentPage === _this.options.totalPages);
break;
default:
break;
Expand All @@ -223,26 +209,54 @@
},

setupEvents: function () {
var base = this;
this.$listContainer.find('li').each(function () {
var _this = this;
this.$listContainer.off('click').on('click', 'li', function (evt) {
var $this = $(this);
$this.off();
if ($this.hasClass(base.options.disabledClass) || $this.hasClass(base.options.activeClass)) {
$this.click(function (evt) {
evt.preventDefault();
});
return;
if ($this.hasClass(_this.options.disabledClass) || $this.hasClass(_this.options.activeClass)) {
return false;
}
$this.click(function (evt) {
// Prevent click event if href is not set.
!base.options.href && evt.preventDefault();
base.show(parseInt($this.data('page'), 10));
});
// Prevent click event if href is not set.
!_this.options.href && evt.preventDefault();
_this.show(parseInt($this.data('page')));
});
},

makeHref: function (c) {
return this.options.href ? this.options.href.replace(this.options.hrefVariable, c) : "#";
makeHref: function (page) {
return this.options.href ? this.generateQueryString(page) : "#";
},

makeText: function (text, page) {
return text.replace(this.options.pageVariable, page)
.replace(this.options.totalPagesVariable, this.options.totalPages)
},
getPageFromQueryString: function (searchStr) {
var search = this.getSearchString(searchStr),
regex = new RegExp(this.options.pageVariable + '(=([^&#]*)|&|#|$)'),
page = regex.exec(search);
if (!page || !page[2]) {
return null;
}
page = decodeURIComponent(page[2]);
page = parseInt(page);
if (isNaN(page)) {
return null;
}
return page;
},
generateQueryString: function (pageNumber, searchStr) {
var search = this.getSearchString(searchStr),
regex = new RegExp(this.options.pageVariable + '=*[^&#]*');
if (!search) return '';
return '?' + search.replace(regex, this.options.pageVariable + '=' + pageNumber);

},
getSearchString: function (searchStr) {
var search = searchStr || window.location.search;
if (search === '') {
return null;
}
if (search.indexOf('?') === 0) search = search.substr(1);
return search;
}

};
Expand All @@ -255,7 +269,7 @@

var $this = $(this);
var data = $this.data('twbs-pagination');
var options = typeof option === 'object' && option;
var options = typeof option === 'object' ? option : {};

if (!data) $this.data('twbs-pagination', (data = new TwbsPagination(this, options) ));
if (typeof option === 'string') methodReturn = data[ option ].apply(data, args);
Expand All @@ -264,26 +278,29 @@
};

$.fn.twbsPagination.defaults = {
totalPages: 0,
totalPages: 1,
startPage: 1,
visiblePages: 5,
initiateStartPageClick: true,
href: false,
hrefVariable: '{{number}}',
pageVariable: '{{page}}',
totalPagesVariable: '{{total_pages}}',
page: null,
first: 'First',
prev: 'Previous',
next: 'Next',
last: 'Last',
loop: false,
onPageClick: null,
paginationClass: 'pagination',
nextClass: 'next',
prevClass: 'prev',
lastClass: 'last',
firstClass: 'first',
pageClass: 'page',
nextClass: 'page-item next',
prevClass: 'page-item prev',
lastClass: 'page-item last',
firstClass: 'page-item first',
pageClass: 'page-item',
activeClass: 'active',
disabledClass: 'disabled'
disabledClass: 'disabled',
anchorClass: 'page-link'
};

$.fn.twbsPagination.Constructor = TwbsPagination;
Expand All @@ -293,4 +310,6 @@
return this;
};

})(jQuery, window, document);
$.fn.twbsPagination.version = "1.4";

})(window.jQuery, window, document);