天天看點

一個分頁插件的源碼分析



/**

 * this jquery plugin displays pagination links inside the selected elements.

 *

 * this plugin needs at least jquery 1.4.2

 * @author gabriel birke (birke *at* d-scribe *dot* de)

 * @version 2.2

 * @param {int}

 *            maxentries number of entries to paginate

 * @param {object}

 *            opts several options (see readme for documentation)

 * @return {object} jquery object

 */

(function($) {

   /**

    * @class class for calculating pagination values

     *

     * 下面的寫法我的了解是定義一個我任務的構造方法,或者方法,或者對象

     * $.paginationcalculator,這個$.paginationcalculator對象中有兩個參數

    */

   $.paginationcalculator = function(maxentries, opts) {

      this.maxentries = maxentries;

      this.opts = opts;

   }

 * 對這個對象進行擴充$.paginationcalculator,為它添加numpages方法,getinterval方法。

   $.extend($.paginationcalculator.prototype, {

      /**

       * calculate the maximum number of pages

       *

       * @method

       * @returns {number}

         * 編寫一個獲得頁碼的方法

         *

       */

      numpages : function() {

         return math.ceil(this.maxentries / this.opts.items_per_page);

      },

       * calculate start and end point of pagination links depending on

       * current_page and num_display_entries.

       * @returns {array}

      getinterval : function(current_page) {

         var ne_half = math.floor(this.opts.num_display_entries / 2);

         var np = this.numpages();

         var upper_limit = np - this.opts.num_display_entries;

         var start = current_page > ne_half ? math.max(math.min(current_page

                - ne_half, upper_limit), 0) : 0;

         var end = current_page > ne_half ? math.min(current_page + ne_half

                + (this.opts.num_display_entries % 2), np) : math.min(

                this.opts.num_display_entries, np);

         return {

            start : start,

            end : end

         };

      }

   });

   // initialize jquery object container for pagination renderers,下面的方式是定義一個對象

   $.paginationrenderers = {}

    * @class default renderer for rendering pagination links

     * 再次定義一個$.paginationrenderers.defaultrenderer對象

   $.paginationrenderers.defaultrenderer = function(maxentries, opts) {

      this.pc = new $.paginationcalculator(maxentries, opts);

   $.extend($.paginationrenderers.defaultrenderer.prototype,

                {

                   /**

                    * helper function for generating a single link (or a

                    * span tag if it's the current page)

                    *

                    * @param {number}

                    *            page_id the page id for the new item

                    *            current_page

                    * @param {object}

                    *            appendopts options for the new item: text

                    *            and classes

                    * @returns {jquery} jquery object containing the link

                    */

                   createlink : function(page_id, current_page, appendopts) {

                      var lnk, np = this.pc.numpages();

                      page_id = page_id < 0 ? 0 : (page_id < np ? page_id

                            : np - 1); // normalize page id to sane

                                     // value

                      appendopts = $.extend( {

                         text : page_id + 1,

                         classes : ""

                      }, appendopts || {});

                      if (page_id == current_page) {

                         lnk = $("<a class='current'>" + appendopts.text

                               + "</a>");

                      } else {

                         lnk = $("<a>" + appendopts.text + "</a>").attr(

                               'href',

                               this.opts.link_to.replace(/__id__/,

                                     page_id));

                      }

                      if (appendopts.classes) {

                         lnk.addclass(appendopts.classes);

                      lnk.data('page_id', page_id);

                      return lnk;

                   },

                   // generate a range of numeric links

                   appendrange : function(container, current_page, start,

                         end, opts) {

                      var i;

                      for (i = start; i < end; i++) {

                         this.createlink(i, current_page, opts)

                               .appendto(container);

                   getlinks : function(current_page, eventhandler) {

                      var begin, end, interval = this.pc

                            .getinterval(current_page), np = this.pc

                            .numpages(), fragment = $("<div class='pagination'></div>");

                      // generate "previous"-link

                      if (this.opts.prev_text

                            && (current_page > 0 || this.opts.prev_show_always)) {

                         fragment.append(this.createlink(

                               current_page - 1, current_page, {

                                  text : this.opts.prev_text,

                                  classes : "prev"

                               }));

                      // generate starting points

                      if (interval.start > 0

                            && this.opts.num_edge_entries > 0) {

                         end = math.min(this.opts.num_edge_entries,

                               interval.start);

                         this.appendrange(fragment, current_page, 0,

                               end, {

                                  classes : 'sp'

                               });

                         if (this.opts.num_edge_entries < interval.start

                               && this.opts.ellipse_text) {

                            $(

                                  "<span class='pagination-break'>"

                                        + this.opts.ellipse_text

                                        + "</span>").appendto(

                                  fragment);

                         }

                      // generate interval links

                      this.appendrange(fragment, current_page,

                            interval.start, interval.end);

                      // generate ending points

                      if (interval.end < np

                         if (np - this.opts.num_edge_entries > interval.end

                         begin = math.max(np

                               - this.opts.num_edge_entries,

                               interval.end);

                         this.appendrange(fragment, current_page, begin,

                               np, {

                                  classes : 'ep'

                      // generate "next"-link

                      if (this.opts.next_text

                            && (current_page < np - 1 || this.opts.next_show_always)) {

                               current_page + 1, current_page, {

                                  text : this.opts.next_text,

                                  classes : "next"

                     }

                      $('a', fragment).click(eventhandler);

                      return fragment;

                   }

                });

   // extend jquery,編寫一個插件

   $.fn.pagination = function(maxentries, opts) {

      // initialize options with default values

      opts = $.extend( {

         items_per_page : 1,

         num_display_entries : 4,

         current_page : 0,

         num_edge_entries : 1,

         link_to : "#",

         prev_text : "<i></i>上一頁",

         next_text : "下一頁 <i></i>",

         ellipse_text : "...",

         prev_show_always : true,

         next_show_always : true,

         renderer : "defaultrenderer",

         show_if_single_page : false,

         load_first_page : false,

         callback : function() {

            return false;

         }

      }, opts || {});

      var containers = this, renderer, links, current_page;

      // goto

      $(".page-btn").one("click", function() {

         var allpage = $(".allpage").text();

         // console.log(allpage);

            var gopage = $(".page-go input").val() - 1; // 跳轉頁數

            if (gopage > -1 && gopage < allpage) {

                opts.current_page = gopage;

                $("#pagination").pagination(allpage, opts);

            } else {

                $("#pagination").pagination(allpage);

            }

            // 清空使用者跳轉頁數

            $(".page-go input").val("");

         });

       * this is the event handling function for the pagination links.

       * @param {int}

       *            page_id the new page number

      function paginationclickhandler(evt) {

         var links, new_current_page = $(evt.target).data('page_id'), continuepropagation = selectpage(new_current_page);

         if (!continuepropagation) {

            evt.stoppropagation();

         return continuepropagation;

       * this is a utility function for the internal event handlers. it sets

       * the new current page on the pagination container objects, generates a

       * new html fragment for the pagination links and calls the callback

       * function.

      function selectpage(new_current_page) {

         // update the link display of a all containers

         containers.data('current_page', new_current_page);

         links = renderer.getlinks(new_current_page, paginationclickhandler);

         containers.empty();

         links.appendto(containers);

         // call the callback and propagate the event if it does not return

         // false

         var continuepropagation = opts.callback(new_current_page,

                containers);

      // -----------------------------------

      // initialize containers

      current_page = parseint(opts.current_page);

      containers.data('current_page', current_page);

      // create a sane value for maxentries and items_per_page

      maxentries = (!maxentries || maxentries < 0) ? 1 : maxentries;

      opts.items_per_page = (!opts.items_per_page || opts.items_per_page < 0) ? 1

            : opts.items_per_page;

      if (!$.paginationrenderers[opts.renderer]) {

         throw new referenceerror("pagination renderer '" + opts.renderer

                + "' was not found in jquery.paginationrenderers object.");

      renderer = new $.paginationrenderers[opts.renderer](maxentries, opts);

      // attach control events to the dom elements

      var pc = new $.paginationcalculator(maxentries, opts);

      var np = pc.numpages();

      containers.bind('setpage', {

         numpages : np

      }, function(evt, page_id) {

         if (page_id >= 0 && page_id < evt.data.numpages) {

            selectpage(page_id);

      });

      containers.bind('prevpage', function(evt) {

         var current_page = $(this).data('current_page');

         if (current_page > 0) {

            selectpage(current_page - 1);

         return false;

      containers.bind('nextpage', {

      }, function(evt) {

         if (current_page < evt.data.numpages - 1) {

            selectpage(current_page + 1);

      // when all initialisation is done, draw the links

      links = renderer.getlinks(current_page, paginationclickhandler);

      containers.empty();

      if (np > 1 || opts.show_if_single_page) {

      // call callback function

      if (opts.load_first_page) {

         opts.callback(current_page, containers);

   } // end of $.fn.pagination block

})(jquery);

繼續閱讀