jQuery分页插件jqPagination 可自定义输入页码

本文作者html5tricks,转载请注明出处

jqPagination是一款基于jQuery的分页插件,这款jQuery分页插件非常实用,不仅可以上下翻页,而且也支持第一页和最后一页的翻页。另外,jqPagination还支持自定义输入页码来跳转到任意页。jqPagination分页插件的UI外观也比较漂亮,分页按钮不仅大气,而且还有渐变的颜色,看起来很简单,你可以将jqPagination应用在自己的个人博客上。

jquery-jqpagination

下面我们来简单介绍一下jqPagination分页插件实现的代码,主要由HTML代码、CSS代码以及jQuery代码组成,实现也比较简单。

HTML代码:

<div>
		<a href="#" data-action="first">&laquo;</a>
		<a href="#" data-action="previous">&lsaquo;</a>
		<input type="text" readonly="readonly" />
		<a href="#" data-action="next">&rsaquo;</a>
		<a href="#" data-action="last">&raquo;</a>
</div>

很简单,在页面上陈列了4个翻页按钮和一个页码输入框。

CSS代码:

.pagination {
  display: inline-block;
  border: 1px solid #CDCDCD;
  border-radius: 3px; }

.pagination a {
  display: block;
  float: left;
  width: 20px;
  height: 20px;
  outline: none;
  border-right: 1px solid #CDCDCD;
  border-left: 1px solid #CDCDCD;
  color: #555555;
  vertical-align: middle;
  text-align: center;
  text-decoration: none;
  font-weight: bold;
  font-size: 16px;
  font-family: Times, 'Times New Roman', Georgia, Palatino;
  /* ATTN: need a better font stack */
  background-color: #f3f3f3;
  background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #f3f3f3), color-stop(100%, lightgrey));
  background-image: -webkit-linear-gradient(#f3f3f3, lightgrey);
  background-image: linear-gradient(#f3f3f3, lightgrey); }
  .pagination a:hover, .pagination a:focus, .pagination a:active {
    background-color: #cecece;
    background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #e4e4e4), color-stop(100%, #cecece));
    background-image: -webkit-linear-gradient(#e4e4e4, #cecece);
    background-image: linear-gradient(#e4e4e4, #cecece); }
  .pagination a.disabled, .pagination a.disabled:hover, .pagination a.disabled:focus, .pagination a.disabled:active {
    background-color: #f3f3f3;
    background-image: -webkit-gradient(linear, left top, left bottom, color-stop(0%, #f3f3f3), color-stop(100%, lightgrey));
    background-image: -webkit-linear-gradient(#f3f3f3, lightgrey);
    background-image: linear-gradient(#f3f3f3, lightgrey);
    color: #A8A8A8;
    cursor: default; }

.pagination a:first-child {
  border: none;
  border-radius: 2px 0 0 2px; }

.pagination a:last-child {
  border: none;
  border-radius: 0 2px 2px 0; }

.pagination input {
  float: left;
  margin: 0;
  padding: 0;
  width: 120px;
  height: 20px;
  outline: none;
  border: none;
  vertical-align: middle;
  text-align: center; }

/* gigantic class for demo purposes */
.gigantic.pagination {
  margin: 30px 0; }

.gigantic.pagination a {
  height: 60px;
  width: 60px;
  font-size: 50px;
  line-height: 50px; }

.gigantic.pagination input {
  width: 300px;
  height: 60px;
  font-size: 30px; }

jQuery代码:

(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':

					// if we're getting, immediately return the value
					if ( value === undefined && typeof key !== "object" ) {
						return base.options[key];
					}

					// 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 current_page property is set call setPage
					if(options.current_page !== undefined){
						result = base.setPage(options.current_page, prevent_paged);
					}

					// if max_page property is set call setMaxPage
					if(options.max_page !== undefined){
						result = base.setMaxPage(options.max_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		: 'Page {current_page} of {max_page}',
		paged			: function () {}
	};

	$.fn.jqPagination = function () {

		// get any function parameters
		var self = this,
			$self = $(self),
			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 getting, we can only get value for the first pagination element
			if (args[2] === undefined) {

				result = $self.first().data('jqPagination').callMethod(args[0], args[1]);

			} else {

				// if we're setting, set values for all pagination elements
				$self.each(function(){
					result = $(this).data('jqPagination').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);

以上就是jqPagination分页插件的实现过程,应该还算简单,大家可以下载源代码研究。

在线演示源码下载

热门推荐

jQuery分页插件jqPagination 可自定义输入页码》上有3条评论

发表评论

电子邮件地址不会被公开。 必填项已用*标注

您可以使用这些HTML标签和属性: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>