wahlhelfer/js/jquery.jqpagination.js
2014-05-15 18:49:45 +02:00

417 lines
11 KiB
JavaScript
Executable file

/*!
* jqPagination, a jQuery pagination plugin (obviously)
* Version: 1.3 (26th July 2013)
*
* Copyright (C) 2013 Ben Everard
*
* http://beneverard.github.com/jqPagination
*
* This program is free software: you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation, either version 3 of the License, or
* (at your option) any later version.
*
* This program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with this program. If not, see <http://www.gnu.org/licenses/>.
*
*/
(function ($) {
"use strict";
$.jqPagination = function (el, options) {
// To avoid scope issues, use 'base' instead of 'this'
// to reference this class from internal events and functions.
var base = this;
// Access to jQuery and DOM versions of element
base.$el = $(el);
base.el = el;
// get input jQuery object
base.$input = base.$el.find('input');
// Add a reverse reference to the DOM object
base.$el.data("jqPagination", base);
base.init = function () {
base.options = $.extend({}, $.jqPagination.defaultOptions, options);
// if the user hasn't provided a max page number in the options try and find
// the data attribute for it, if that cannot be found, use one as a max page number
if (base.options.max_page === null) {
if (base.$input.data('max-page') !== undefined) {
base.options.max_page = base.$input.data('max-page');
} else {
base.options.max_page = 1;
}
}
// if the current-page data attribute is specified this takes priority
// over the options passed in, so long as it's a number
if (base.$input.data('current-page') !== undefined && base.isNumber(base.$input.data('current-page'))) {
base.options.current_page = base.$input.data('current-page');
}
// remove the readonly attribute as JavaScript must be working by now ;-)
base.$input.removeAttr('readonly');
// set the initial input value
// pass true to prevent paged callback form being fired
base.updateInput(true);
//***************
// BIND EVENTS
base.$input.on('focus.jqPagination mouseup.jqPagination', function (event) {
// if event === focus, select all text...
if (event.type === 'focus') {
var current_page = parseInt(base.options.current_page, 10);
$(this).val(current_page).select();
}
// if event === mouse up, return false. Fixes Chrome bug
if (event.type === 'mouseup') {
return false;
}
});
base.$input.on('blur.jqPagination keydown.jqPagination', function (event) {
var $self = $(this),
current_page = parseInt(base.options.current_page, 10);
// if the user hits escape revert the input back to the original value
if (event.keyCode === 27) {
$self.val(current_page);
$self.blur();
}
// if the user hits enter, trigger blur event but DO NOT set the page value
if (event.keyCode === 13) {
$self.blur();
}
// only set the page is the event is focusout.. aka blur
if (event.type === 'blur') {
base.setPage($self.val());
}
});
base.$el.on('click.jqPagination', 'a', function (event) {
var $self = $(this);
// we don't want to do anything if we've clicked a disabled link
// return false so we stop normal link action btu also drop out of this event
if ($self.hasClass('disabled')) {
return false;
}
// for mac + windows (read: other), maintain the cmd + ctrl click for new tab
if (!event.metaKey && !event.ctrlKey) {
event.preventDefault();
base.setPage($self.data('action'));
}
});
};
base.setPage = function (page, prevent_paged) {
// return current_page value if getting instead of setting
if (page === undefined) {
return base.options.current_page;
}
var current_page = parseInt(base.options.current_page, 10),
max_page = parseInt(base.options.max_page, 10);
if (isNaN(parseInt(page, 10))) {
switch (page) {
/*
case 'first':
page = 1;
break;
case 'prev':
case 'previous':
page = current_page - 1;
break;
*/
case 'next':
page = current_page + 1;
break;
/*
case 'last':
page = max_page;
break;
*/
}
}
page = parseInt(page, 10);
// reject any invalid page requests
if (isNaN(page) || page < 1 || page > max_page) {
// update the input element
base.setInputValue(current_page);
return false;
}
// update current page options
base.options.current_page = page;
base.$input.data('current-page', page);
// update the input element
base.updateInput( prevent_paged );
};
base.setMaxPage = function (max_page, prevent_paged) {
// return the max_page value if getting instead of setting
if (max_page === undefined) {
return base.options.max_page;
}
// ignore if max_page is not a number
if (!base.isNumber(max_page)) {
console.error('jqPagination: max_page is not a number');
return false;
}
// ignore if max_page is less than the current_page
if (max_page < base.options.current_page) {
console.error('jqPagination: max_page lower than current_page');
return false;
}
// set max_page options
base.options.max_page = max_page;
base.$input.data('max-page', max_page);
// update the input element
base.updateInput( prevent_paged );
};
// ATTN this isn't really the correct name is it?
base.updateInput = function (prevent_paged) {
var current_page = parseInt(base.options.current_page, 10);
// set the input value
base.setInputValue(current_page);
// set the link href attributes
base.setLinks(current_page);
// we may want to prevent the paged callback from being fired
if (prevent_paged !== true) {
// fire the callback function with the current page
base.options.paged(current_page);
}
};
base.setInputValue = function (page) {
var page_string = base.options.page_string,
max_page = base.options.max_page;
// this looks horrible :-(
page_string = page_string
.replace("{current_page}", page)
.replace("{max_page}", max_page);
base.$input.val(page_string);
};
base.isNumber = function(n) {
return !isNaN(parseFloat(n)) && isFinite(n);
};
base.setLinks = function (page) {
var link_string = base.options.link_string,
current_page = parseInt(base.options.current_page, 10),
max_page = parseInt(base.options.max_page, 10);
if (link_string !== '') {
// set initial page numbers + make sure the page numbers aren't out of range
var previous = current_page - 1;
if (previous < 1) {
previous = 1;
}
var next = current_page + 1;
if (next > max_page) {
next = max_page;
}
// apply each page number to the link string, set it back to the element href attribute
base.$el.find('a.first').attr('href', link_string.replace('{page_number}', '1'));
base.$el.find('a.prev, a.previous').attr('href', link_string.replace('{page_number}', previous));
base.$el.find('a.next').attr('href', link_string.replace('{page_number}', next));
base.$el.find('a.last').attr('href', link_string.replace('{page_number}', max_page));
}
// set disable class on appropriate links
base.$el.find('a').removeClass('disabled');
if (current_page === max_page) {
base.$el.find('.next, .last').addClass('disabled');
}
if (current_page === 1) {
base.$el.find('.previous, .first').addClass('disabled');
}
};
base.callMethod = function (method, key, value) {
switch (method.toLowerCase()) {
case 'option':
// set default object to trigger the paged event (legacy opperation)
var options = {'trigger': true},
result = false;
// if the key passed in is an object
if($.isPlainObject(key) && !value){
$.extend(options, key)
}
else{ // make the key value pair part of the default object
options[key] = value;
}
var prevent_paged = (options.trigger === false);
// if max_page property is set call setMaxPage
if(options.max_page !== undefined){
result = base.setMaxPage(options.max_page, prevent_paged);
}
// if current_page property is set call setPage
if(options.current_page !== undefined){
result = base.setPage(options.current_page, prevent_paged);
}
// if we've not got a result fire an error and return false
if( result === false ) console.error('jqPagination: cannot get / set option ' + key);
return result;
break;
case 'destroy':
base.$el
.off('.jqPagination')
.find('*')
.off('.jqPagination');
break;
default:
// the function name must not exist
console.error('jqPagination: method "' + method + '" does not exist');
return false;
}
};
// Run initializer
base.init();
};
$.jqPagination.defaultOptions = {
current_page : 1,
link_string : '',
max_page : null,
page_string : 'Question {current_page} of {max_page}',
paged : function () {}
};
$.fn.jqPagination = function () {
// get any function parameters
var self = this,
args = Array.prototype.slice.call(arguments),
result = false;
// if the first argument is a string call the desired function
// note: we can only do this to a single element, and not a collection of elements
if (typeof args[0] === 'string') {
// if we're dealing with multiple elements, set for all
$.each(self, function(){
var $plugin = $(this).data('jqPagination');
result = $plugin.callMethod(args[0], args[1], args[2]);
});
return result;
}
// if we're not dealing with a method, initialise plugin
self.each(function () {
(new $.jqPagination(this, args[0]));
});
};
})(jQuery);
// polyfill, provide a fallback if the console doesn't exist
if (!console) {
var console = {},
func = function () { return false; };
console.log = func;
console.info = func;
console.warn = func;
console.error = func;
}