hytzgroup / blog

write & read & though
0 stars 0 forks source link

pagination原理 #8

Open hytzgroup opened 4 years ago

hytzgroup commented 4 years ago

pagination原理

(function(){
    // list pageSize [10,20,30,50]
    // sep |分隔符号
    // first 跳转到第一页
    // prev 跳转到前一页
    // manual 输入框
    // next 跳转到下一页
    // last 跳转到最后一页
    // refresh 刷新按钮
    // links 数字列表
    function buildToolbar(target){
        // 
        var state = $.data(target, 'pagination'); 
        var opts = state.options;
        var bb = state.bb = {};
        var pager = $(target).addClass("pagination").html("<table cellspacing=\"0\" cellpadding=\"0\" border=\"0\"><tr></tr></table>");
        var tr = _b0.find("tr");
        var layout = $.extend([], opts.layout);

        // 每页显示的总数
        if(!opts.showPageList){
            isInArray(layout,'list');
        }

        // 显示page信息
        if(!opts.showPageInfo){
            isInArray(layout, 'info');
        }

        // 刷新按钮
        if(!opts.showRefresh){
            isInArray(layout, 'refresh');
        }
        if(layout[0] == 'sep'){
            layout.shift();
        }
        if(layout[layout.length -1] == 'sep'){
            layout.pop();
        }
        for(var i = 0; i < layout.length; i++){
            var item = layout[i];
            switch(item){
                case 'list':
                    var $select = $('<select class=\"pagination-page-list\"></select>');
                    $select.unbind('change', function(){
                        opts.pageSize = parseInt($(this).val());
                        opts.onChangePageSize.call(target, opts.pageSize);
                        selectPage(target, opts.pageNumber);
                    })
                    for(var i = 0; i < opts.pageList.length; i++){
                        $('<option></option>').text(opts.pageList[i]).appendTo($select);
                    }
                    $('<td></td>').append($select).appendTo(tr);
                    break;
                case 'sep':
                    $('<td><div class=\"pagination-btn-separator\"></div><td>').appendTo(tr);
                    break;
                case 'first':
                    bb.first = addEvent('first');
                    break;
                case 'prev':
                    bb.prev = addEvent('prev');
                    break;
                case 'last':
                    bb.last = addEvent('last');
                    break;
                case 'manual':
                    $('<span style=\"padding-left:6px;\"></span>')
                        .html(opts.beforePageText)
                        .appendTo(tr)
                        .wrap('<td></td>');
                    bb.num = $('<input class=\"pagination-num\" type=\"text\" value=\"1\" size=\"2\" />').appendTo(tr).wrap('<td></td>');
                    bb.num.unbind('.pagination')
                          .bind('keydown.pagination', function(e){
                                if(e.keyCode == 13){
                                    var pageNumber = parseInt($(this).val()) || 1;
                                    selectPage(target, pageNumber);
                                    return false;
                                }
                          })
                    bb.after = $('<span style=\"padding-right:6px;\"></span>').appendTo(tr).wrap('<td></td>');
                    break;
                case 'refresh':
                    bb.refresh = addEvent('refresh');
                    break;
                case 'links':
                    $('<td class=\"pagination-links\"></td>').appendTo(tr);
                    break;
                case 'info':
                    if(index == layout.length -1){
                        $('<div class=\"pagination-info\"></div>').appendTo(pager);
                    }else{
                        $('<td><div class=\"pagination-info\"></div></td>').appendTo(tr);
                    }
                    break;
                default:
                    console.log('can not find name '+ name + 'in layout')
                    break;
            }
        }

        // 用户自定义按钮
        if(opts.buttons){

        }
        $("<div style=\"clear:both;\"></div>").appendTo(_b0);

        function addEvent(key){
            var btn = opts.nav[key];
            var $a = $('<a href=\"javascript:;\"></a>').appendTo(tr);
            $a.wrap('<td></td>');
            $.linkbutton({
                iconCls:btn.iconCls,
                plain: true
            })
            .unbind('.pagination')
            .bind('click.pagination',function(){
                btn.handler.call(target)
            })
            return $a;
        }

        function isInArray(arr, item){
            var index = $.isInArray(item, arr);
            if(index >= 0){
                arr.splice(index, 1);
            }
            return arr;
        }
    }

    function showInfo(target){

    }

    function selectPage(target, page){
        var opts = $.data(target, 'pagination').options;
        calcPage(target, {pageNumber: page});
        opts.onSelectPage.call(target, opts.pageNumber, opts.pageSize);
    }

    function calcPage(target, options){
        var state = $.data(target, 'pagination');
        var opts = state.options;
        var bb = state.bb;
        $.extend(opts, options || {});
        var $pageList = $(target).find('select.pagination-page-list');
        if($pageList.length){
            $pageList.val(opts.pageSize + '');
            opts.pageSize = parseInt($pageList.val());
        }
        var totalSize = Math.ceil(opts.total / opts.pageSize) || 1;
        if(opts.pageNumber < 1){
            opts.pageNumber = 1;
        }
        if(opts.pageNumber > totalSize){
            opts.pageNumber = totalSize;
        }
        if(opts.total == 0){
            opts.pageNumber = 0;
            totalSize = 0;
        }
        if(bb.num){
            bb.num.value(opts.pageNumber);
        }
        if(bb.after){
            bb.after.html(opts.afterPageText.replace(/{pages}/, totalSize));
        }
        var td = $(target).find('td.pagination-links');
        if(td.length){
            td.empty();
            // 计算中间值,尝试向前5个值作为起点
            var startNum = opts.pageNumber - Math.floor(opts.links / 2);
            if(startNum < 1){
                startNum = 1;
            }
            // 从起点计算9个点作为终点
            var endNum = startNum + opts.links -1;
            if(endNum > totalSize){
                endNum = totalSize;
            }
            // 重新计算起点,防止出现负值
            startNum = endNum - opts.links + 1;
            if(startNum < 1){
                startNum = 1;
            }
            for(var i = startNum; i < endNum; i++){
                var $a = $('<a class=\"pagination-link\" href=\"javascript:;\"></a>');
                $a.linkbutton({
                    plain: true,
                    text: i
                });
                if(i == opts.pageNumber){
                    $a.linkbutton('select');
                }else{
                    $a.unbind('.pagination')
                      .bind('click.pagination', {pageNumber: i}, function(e){
                            selectPage(target, e.data.pageNumber);
                      });
                }
            }
        }
        var displayMsg = opts.displayMsg;
        displayMsg = displayMsg.replace(/{from}/, opts.total == 0 ? 0 : opts.pageSize*(opts.pageNumber -1)+1)
        displayMsg = displayMsg.replace(/{to}/,Math.min(opts.pageSize*opts.pageNumber,opts.total));
        displayMsg = displayMsg.replace(/{total}/, opts.total);
        $(target).find('div.pagination-info').html(displayMsg);
        if(bb.first){
            bb.first.linkbutton({disabled: (!opts.total || opts.pageNumber == 1)});
        }
        if(bb.prev){
            bb.prev.linkbutton({disabled: (!opts.total || opts.pageNumber == 1)});
        }

        if(bb.next){
            bb.next.linkbutton({disabled: (opts.pageNumber == totalSize)});
        }
        if(bb.last){
            bb.last.linkbutton({disabled: (opts.pageNumber == totalSize)});
        }
        setLoadStatus(target,opts.loading);
    }

    function setLoadStatus(target, loading){
        var state = $.data(target, 'pagination');
        var opts = state.options;
        opts.loading = loading;
        if(opts.showRefresh && state.bb.refresh){
            state.bb.refresh.linkbutton({
                iconCls:(opts.loading ? 'pagination-loading':'pagination-load')
            });
        }
    }

    $.fn.pagination = function(options, params){
        if(typeof options == 'string'){
            return $.fn.pagination.methods[options](this, params);
        }
        var options = options || {};
        return this.each(function(){
            var opts;
            var state = $.data(this, 'pagination');
            if(state){
                opts = $.extend(state.options, options);
            }else{
                opts = $.extend({}, $.fn.pagination.defaults);
                $.data(this, 'pagination', {options: opts})
            }
            buildToolbar(this);
            showInfo(this)
        })
    };
    $.fn.pagination.methods = {
        options: function(jq){
            return $.data(jq[0],'pagination').options;
        },
        loading: function(){},
        loaded: function(){},
        refresh: function(){},
        select: function(){}
    };
    $.fn.pagination.defaults = {
        total: 1,
        pageSize: 10,
        pageNumber: 1,
        pageList: [10, 20, 30, 50],
        loading: false,
        buttons: null,
        showPageList: true,
        showPageInfo: true,
        showRefresh: true,
        links: 10,
        layout: ['list', 'sep', 'first', 'prev', 'sep','manual','sep', 'next', 'last', 'sep', 'refresh', 'info'],
        onSelectPage: function(pageNumber, pageSize){},
        onBeforeRefresh: function(pageNumber, pageSize){},
        onRefresh: function(pageNumber, pageSize){},
        onChangePageSize: function(pageSize){},
        beforePageText: 'page',
        afterPageText: 'of {pages}',
        displayMsg: 'Displaying {from} to {to} of {total} items',
        nav: {
            first: {
                iconCls: 'pagination-first',
                handler: function(){
                    var opts = $(this).pagination('options');
                    if(opts.pageNumber > 1){
                        $(this).pagination('select','1')
                    }
                }
            },
            prev: {
                iconCls: 'pagination-prev',
                handler: function(){
                    var opts = $(this).pagination('options');
                    if(opts.pageNumber > 1){
                        $(this).pagination('select',opts.pageNumber -1);
                    }
                }
            },
            next: {
                iconCls: 'pagination-next',
                handler: function(){
                    var opts = $(this).pagination('options');
                    var total = Math.ceil(opts.total / opts.pageSize);
                    if(opts.pageNumber < total){
                        $(this).pagination('select', opts.pageNumber + 1);
                    }
                }
            },
            last: {
                iconCls: 'pagination-last',
                handler: function(){
                    var opts = $(this).pagination('options');
                    var total = Math.ceil(opts.total / opts.pageSize);
                    if(opts.pageNumber < total){
                        $(this).pagination('select', total);
                    }
                }
            },
            refresh: {
                iconCls: 'pagination-refresh',
                handler: function(){
                    var opts = $(this).pagination('options');
                    if(opts.onBeforeRefresh.call(this, opts.pageNumber) != false){
                        $(this).pagination('select', opts.pageNumber);
                        opts.onRefresh.call(this, opts.pageNumber, opts.pageSize);
                    }
                }
            }
        }
    };    
})(jQuery);