代码改变世界

Jquery分页组件

2013-08-28 10:54 龙恩0707 阅读(...) 评论(...) 编辑 收藏

   最近工作不是很忙,所以就看看淘宝kissy分页组件源码,感觉代码也不怎么难 容易理解,所以就按照他们的思路自己重新理一遍,来加深自己对他们的理解,同时对他们的分页组件进行一些重构(因为他们分页是做好了,但是不能直接拿来用,所以就封装了下),所以就用jquery封装了一个。

     配置参数如下:

       影响分页组件信息展现的因素如下图所示:

                            

     组件提供以下配置参数: totalPage总页数,默认值为1currentPage初始选中的页码,默认值为1 firstPagesCount最前面的展现页数,默认值为2, preposePagesCount当前页的紧邻前置页数,默认值为2 postposePagesCount当前页的紧邻后置页数,默认值为1, lastPagesCount最后面的展现页数,默认值为0 render是否自动渲染组件,默认值为true。

   对外公开的方法:

    render():  渲染组件

    show():    显示组件

    hide():     隐藏组件

    destory():  销毁组件

   页码显示及对应的HTML结构渲染问题:

    一: 当前“选中的页”前面HTML结构渲染的方式如下:

          判断当前选中的页码 如果小于或者等于 (最前面的展示页数 + 当前页的紧邻前置页数 +1)的话

            if (currentPage <= firstPagesCount + preposePagesCount + 1) {
              
                for(var i=1; i<currentPage; i++) {
                    pageHTML += self._renderActivePage(i);
                }
            }

         这种情况下:对应的描述图如下:

          

   对应的HTML结构代码如:  

       那么否则的话         // 对应图3

  else {
                for(var i=1; i<= firstPagesCount; i++) {
                    pageHTML += self._renderActivePage(i);
                }
                pageHTML += '<span class="pagination-break">...</span>';
                for(var i = currentPage-preposePagesCount; i <= currentPage-1; i++) {
                    pageHTML += self._renderActivePage(i);
                }
            }  

           那么对应的描述图如这样的:

              图3:

      

         渲染HTML结构:

        

        接着 就是当前选中的页 html结构

  // 当前页的页码 html显示
        pageHTML += '<span class="pagination-curr">' + currentPage + '</span>';

   

 二: 当前页页码后面的html展示 

  如果当前页 大于或者等于 (总页数 - 最后面的展现页数 - 当前页的紧邻后置页数)的话 代码如下:

         if (currentPage >= totalPage - lastPagesCount - postposePagesCount) {
                offset = currentPage + 1;
                for(var i=currentPage+1; i<=totalPage; i++) {
                    pageHTML += self._renderActivePage(i);
                }
            }

      对应的图如下:

    

     对应的HTML结构渲染如下:

    

     否则的话:代码如下

   else {
                for(var i=currentPage+1; i<= currentPage+postposePagesCount; i++) {
                    pageHTML += self._renderActivePage(i);
                }
                pageHTML += '<span class="pagination-break">...</span>';
                for(var i=totalPage-lastPagesCount+1; i<=totalPage; i++) {
                    pageHTML += self._renderActivePage(i);
                }
            }

   对应图如下:

     

  对应的HTML结构渲染如下:

    

 最后判断下一页的显示方式   代码如下:

   pageHTML += currentPage === totalPage ? '<span class="pagination-end"><span>下一页</span></span>' : '<a class="pagination-next"><span>下一页<span></a>';

 

Jquery所有的JS代码如下:

      
/**
 * fileoverview Jquery分页组件
 * @param {selector} 分页容器
 * @param {cfg} object 默认配置
 */

 var Pagination = (function(){

    function Pagination(selector,cfg){
        if(this instanceof Pagination) {

            // 匹配传参数clickElem
            if($.isPlainObject(selector)){
                this.selector = selector;
            }else if(/^\./.test(selector)){
                this.selector = $(selector);
            }else if(/^#/.test(selector)){
                this.selector = $(selector);
            }else if($('.'+selector)){
                this.selector = $('.'+selector);
            }else {
                throw new Error('传递参数不符合!');
            }
        }else {
            new Pagination(selector,cfg);
        }
        
        cfg = $.extend(Pagination.config,cfg || {});
        this.config = cfg || {};
        
        // 初始化时候 默认选中的页数
        $.isFunction(this.config.callback) && this.config.callback(this.config.currentPage);

        this._init();
        
    }

    Pagination.config = {
        
        // 总页数
        totalPage:1,
        
        // 默认选中的页数
        currentPage: 1,

        //当前页最大紧邻前置页数(不包括最前面显示页数)
        preposePagesCount: 2,

        //当前页的最大紧邻后置页数
        postposePagesCount: 1,

        // 第一个"..."前显示的页数
        firstPagesCount: 2,

        // 第二个"..."后显示的页数
        lastPagesCount: 0,
        
        render: true,

        callback: function(idx){}
    };
    Pagination.prototype = {
        
        _init: function(){
            
            var self = this;
            
            if(self.config.render === true){
                
                self.render();
            }
            
        },

        /* 渲染 */
        render: function(){
            
            var self = this;
            self._renderUI();
            
            self._bindUI();
        },
        _renderUI: function(){
            var self = this;
            self._resetPagination();
        },

        // 处理点击元素
        _bindUI: function(){
            
            var self = this;
            
            /*
             * 注意jquery1.9 没有live这个方法 所以在jquery1.9 API上会报错 jquery1.9以上考虑用其他的绑定事件方法
             */
            $('.pagination-spec').live('click',function(e){
                var target = e.target,
                    toPage = $(target).attr('data-page') * 1;
                self._switchToPage(toPage);
            });
            $('.pagination-prev').live('click',function(e){
                var toPage = self.config.currentPage - 1;
                self._switchToPage(toPage);
            });
            $('.pagination-next').live('click',function(e){
                var toPage = self.config.currentPage + 1;
                self._switchToPage(toPage);
            });
        },
        _switchToPage: function(page){
            var self = this;
            self.config.currentPage = page;
            self._resetPagination();
            
            // 页面显示成功后 回调
            $.isFunction(self.config.callback) && self.config.callback(self.config.currentPage);
        },
        /*
         * 刷新分页
         */
        _resetPagination: function(){
            
            var self = this,
                pageHTML = '',
                totalPage = self.config.totalPage > 0 ? self.config.totalPage : 1,
                currentPage = (self.config.currentPage <= totalPage) && (self.config.currentPage > 0) ? self.config.currentPage : 1,
                preposePagesCount = self.config.preposePagesCount >=0 ? self.config.preposePagesCount : 2,
                postposePagesCount = self.config.postposePagesCount >=0 ? self.config.postposePagesCount : 1,
                firstPagesCount = self.config.firstPagesCount >=0 ? self.config.firstPagesCount : 2,
                lastPagesCount = self.config.lastPagesCount >=0 ? self.config.lastPagesCount : 0,
                offset;
            // 当前页码显示
            pageHTML += currentPage === 1 ? '<span class="pagination-start"><span>上一页</span></span>' :
            '<a class="pagination-prev"><span>上一页</span></a>';
            
            //当前页的 前面html结构显示问题
            if (currentPage <= firstPagesCount + preposePagesCount + 1) {
                
                for(var i=1; i<currentPage; i++) {
                    pageHTML += self._renderActivePage(i);
                }

            }else {
                for(var i=1; i<= firstPagesCount; i++) {
                    pageHTML += self._renderActivePage(i);
                }
                pageHTML += '<span class="pagination-break">...</span>';
                for(var i=currentPage-preposePagesCount; i<=currentPage-1; i++) {
                    pageHTML += self._renderActivePage(i);
                }
            }
            // 当前页的页码 html显示
            pageHTML += '<span class="pagination-curr">' + currentPage + '</span>';

            // 当前页页码后面的html展示
            if (currentPage >= totalPage - lastPagesCount - postposePagesCount) {
                offset = currentPage + 1;
                for(var i=currentPage+1; i<=totalPage; i++) {
                    pageHTML += self._renderActivePage(i);
                }

            } else {
                for(var i=currentPage+1; i<= currentPage+postposePagesCount; i++) {
                    pageHTML += self._renderActivePage(i);
                }
                pageHTML += '<span class="pagination-break">...</span>';
                for(var i=totalPage-lastPagesCount+1; i<=totalPage; i++) {
                    pageHTML += self._renderActivePage(i);
                }
            }
            pageHTML += currentPage === totalPage ? '<span class="pagination-end"><span>下一页</span></span>' :
                '<a class="pagination-next"><span>下一页<span></a>';
            
            $(self.selector).html(pageHTML);
        },

        /**
            * @ 渲染可点击的页码
         * @param index {Number} 页码索引
         *
         */
        _renderActivePage: function(index) {
            return '<a class="pagination-spec" data-page="' + index + '">' + index + '</a>';
        },
        show: function(){
            var self = this;
            $(self.selector).show();
        },
        hide: function(){
            var self = this;
            $(self.selector).hide();
        },
        
        // 销毁
        destory: function(){
            var self = this;
            $(self.selector) = null;

            // 销毁用live绑定的事情
            $('.pagination-spec').die('click');
            $('.pagination-prev').die('click');
            $('.pagination-next').die('click');
        }
    };
    return Pagination;
 })();

     HTML调用方式如下:
     <div id = "Pagination"></div>
     <div id="content"></div>
     <script type="text/javascript">
         var intPageSize = 8, //一页定义8条数据
             intRowCount = 100; //记录总数
             intPageCount = Math.ceil(intRowCount/intPageSize);
         new Pagination('#Pagination',{
             totalPage: intPageCount,
             callback: function(idx){
                 console.log(idx);
             }
         });
     </script>
 
    其中一页显示多少条intPageSize 是用户自定义的,
    记录总数intRowCount  是后台开发人员给的,
    总共多少页 intPageCount  是我们要计算的。
    初始化方式如上 通过实例化。
    然后callback回调函数 把相对应的 每页显示多少条intPageSize  
    和  相对应的页码 idx ajax方式传参提交给开发人员  
    返回相应的信息 我们渲染出来 就ok!

    css也放上来吧!如下

       <style>
        body {
            font: 12px/1.5 tahoma,arial,宋体b8b\4f53;
        }
        
        .pagination-start,
        .pagination-prev,
        .pagination-next,
        .pagination-end
        {
            width: 36px;
            background: url(http://img04.taobaocdn.com/tps/i4/T1cP85XihuXXXXXXXX-13-101.png) no-repeat;
        }
        .pagination-start,
        .pagination-prev,
        .pagination-next,
        .pagination-end,
        .pagination-spec,
        .pagination-curr,
        .pagination-break
        {
            min-width: 16px;
            _width: 16px;
            border: 1px solid #ccc;
            display: inline;
            float: left;
            height: 24px;
            margin-right: 3px;
            padding: 0 5px;
            line-height: 24px;
            text-align: center;
            font-family: Tahoma,SimSun,Arial;
            vertical-align: top;
            white-space: nowrap;
            overflow: hidden;
        }
        .pagination-start {
            padding-left: 16px;
            background-position: 5px 8px;
        }
         .pagination-prev {
            padding-left: 16px;
            background-position: 0 -12px;
        }
        .pagination-curr {
            font-weight: 700;
            color: #fd6d01;
            background-color: #ffede1;
            border: 1px solid #fd6d01;
        }
         .pagination-break {
            color: #c0c0c0;
            border: 0;
        }
         .pagination-next {
            padding-right: 16px;
            background-position: 42px -50px;
        }
        .pagination-end {
            padding-right: 16px;
            background-position: 47px -31px;
        }
        a {
            color: #36c;
            cursor: pointer;
        }
         a:hover {
            border: 1px solid #fd6d01;
        }
        
    </style>