/*! * 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 . * */ (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; }