JQuery分页插件Pagination扩展

    项目中用到了Pagination分页栏插件.很精简的一个插件,但是只提供分页栏显示的功能.

    如果使用ajax来翻页的话,用起来不太方便.所以打算自己扩展下,前台做的少,js不太好,欢迎大家指点 :-)

    例如: 如下使用

$("#pagination_div").pagination(totalSize, {callback:function(nextIndex){
    $.ajax({ type : "POST", url : "http://www.baidu.com", data : {page:(nextIndex+1), rows:"10"},
        success : function(html) {
            $("#page_table_tbody").html("").append(html);
        }
    });
}}

    这样每个用到分页的地方都需要写一次ajax请求,而且返回的html数据需要在后台处理好,如果是json数据的还需要自己去处理,挺麻烦的.

    而且现在经常会出现这种情况,后台的分页方法只有一个,返回json数据,然后需要用到的地方解析json,展示哪些属性由前端渲染界面的时候来决定. 所以为了少点重复劳动, 对它扩展了一下.

    原本是打算直接改Pagination源码的,但是感觉不太好,一个是怕改出问题,影响到原来已经使用了的地方,一个是升级啥的比较麻烦(虽然感觉这个插件应该不会升级了:-) ). 所以后面决定在另外的js文件中实现功能,然后通过callback将他们两者联系起来.

    先说说大概思路:

    1.解析json数据和dom的操作属于重复劳动,需要抽象出来.

    那么如何抽象出来呢? 列和后台对象的属性如何Mapping起来, 用过JQuery EasyUI的人都知道,它的表格初始化的时候都需要将列的显示名, 对应后台哪个属性(简单的说就是哪一列显示哪个属性)等等的配置在组件初始化的时候传入.

    这里我也是使用的这种方法.于是我们写table的时候需要加上一些配置信息,例如:

<table id="table_id">
    <thead head>
        <tr>
            <th name="id">主键</th>
            <th name="name">姓名</th>
            <th name="link">操作</th>
        </tr>
    </thead>
    <tbody data></tbody>
</table>

   这个时候,th的name属性值,就对应着后台对象的属性

    好了,现在映射对应起来,但是还有些问题, 很多情况下,表格中都包含一列,用来放按钮,链接等东西,而这些东西并不是后台的属性,而是通过后台属性动态生成的数据.  这个时候怎么办呢?  而且我们经常有的需求就是对日期,金钱等的格式化等等操作.

    很容易想到的就是在处理后台json数据的时候回调一下用户定义的函数.  那么有哪些地方需要回调呢?

    1.每一行(tr)生成后.        2.每一个单元格(td)完成后.       3.ajax网络错误处理回调.     4.全部处理完成回调    5.单击回调......      

    如果要做的很灵活的话,就要有很多回调的地方,但是现在项目需求并不是很复杂....提供1,2,3,4的功能就好...其他的有需求了再加,原理是一样的,就是在配置的时候提供回调函数,然后在对应的地方回调.

    回调的需要注意的是this对象的使用.如果碰到古怪的问题了,往这方面想象(-.-)

    好了,现在要将回调传给我们的组件,我们才能回调到~~!   其他的回调都好说,在初始化组件的时候传进去就好, 但是每一个单元格(td)的回调,就不太好传了..........后面想了个蛋疼的办法  如下面代码所示:

<th name="link" opts="{handler:function(index, data, td){
    var a = $('<a>查看</a>');
    a.attr('href',' + data.id);
    a.appendTo(td);
}}">操作</th>

    有点蛋疼,不过没办法...毕竟对于我现在的项目来说,这个情况少,哈哈哈哈哈哈哈,要不做成初始化的时候传也行.

    这里handler函数的 index表示当前是第几行, data是后台数据的json对象(某一行的), td是td标签对应的JQuery对象在最后我们会将td这个对象appendTo(tr).

    那么怎么将这些配置给初始化到我们的组件中呢? 我的做法:

$.PageProcesser = function(tableId, url, pageSize, opts){
	var that = this;
	this.tableId = tableId;//table的id,必须的
	this.url = url;        //ajax请求数据的url必须的             
	this.pageSize = pageSize ? pageSize : 10; //每页显示条数
	
	if(!tableId || !url){
	    throw "PageProcesser : the param tableId and url are required";
	}
	
	//初始化参数,rowHandler是每行处理完后的回调函数,参数和上面说的类似,提供一个默认配置
	//param参数是为了这种情况:ajax请求的时候有其他的请求参数.....
	this.opts = jQuery.extend({
            param:{},
            rowHandler:function(index, data, tr){return true;},},
            opts||{}
	);
	
	//这个是初始化每一类的配置,包括列对应的属性名,列的位置(1,2,3,4,5),列的处理回调函数
	//因为上面td的配置方式,所以这里用eval了,求勿喷 :-)
	this.tdOpts = [];
	$("#" + tableId + " th[name]").each(function(index, element){
            var fieldName = $(this).attr("name");
            var fieldOpts = $(this).attr("opts");
            fieldOpts = fieldOpts ? eval("fieldOpts = " + fieldOpts) : {};
            fieldOpts = jQuery.extend({handler:function(index, data, td){return true;}}, fieldOpts);
            that.tdOpts.push({name:fieldName, index:index, opts:fieldOpts});
	});
};

    好了,现在构造函数定义好了. 初始化类似于这样:

//第一个参数是table的id, 第二个:ajax请求路径, 
var pageHaper = new $.PageProcesser("table", "${path}/json", 100, {
    param:{type:"1"}, //ajax请求附带的参数
    rowHandler:function(index, data, tr){//行处理回调
        index % 2 == 0 ? tr.css("color", "red") : "";
    }
});

    好了,参数定义及初始化都好了,现在来定义方法. 如下代码:

$.extend($.PageProcesser.prototype, {

    callback:function(page_index, pagination){//代理pagination的回调函数
        this.requester(page_index); //ajax请求函数
        return false;
    },

    requester:function(page){//ajax请求数据
        var requestParam = jQuery.extend({page:(page+1), rows:this.pageSize}, this.opts.param);        //注意设置context:this 防止ajax回调函数中this调用不到handlerJson方法.
        $.ajax({ type : "POST", url : this.url, data : requestParam, context:this,
            success : function(json) {
                this.handlerJson(json);
            }
	});
    },
	
    handlerJson:function(json){//根据后台json和配置更新dom
        var datas = json ? (json.rows ? json.rows : []) : [] ;
        var tbody = $("#" + this.tableId + " tbody[data]");
        tbody.html("");//清空原来的数据
        
        for(var i=0 ; i<datas.length ; i++){//循环json中的数组,创建tr,td,并调用对应的回调
            var tr = $("<tr></tr>");
            for(var j=0 ; j<this.tdOpts.length ; j++){
                var val = datas[i][this.tdOpts[j].name];
                var td = $("<td></td>").text(val);
                this.tdOpts[j].opts.handler(i, datas[i], td);//回调列处理器
                td.appendTo(tr);//这里可以写成批量的方式来提高效率....
            }
            this.opts.rowHandler(i, datas[i], tr);//回调用户行处理器
            tr.appendTo(tbody);//这里也可以写成批量的方式来提高效率....
        }
		
    },
});

    好了,都搞完了,现在来用用看(还有些功能没有实现,比如ajax网络错误,应该有对应的处理,等等地方...我懒)

    现在看看完整的代码:

/**
 * jquery插件,用来扩展jquery分页插件,
 * 该插件做以下事情:
 * 1.$.ajax.post异步请求数据,数据格式{rows:[]};
 * 2.将获取到的数据根据配置生成tbody内容
 */
 (function($){
	 
	$.PageProcesser = function(tableId, url, pageSize, opts){
		var that = this;
		this.tableId = tableId;
		this.url = url;
		this.pageSize = pageSize ? pageSize : 10;
		
		if(!tableId || !url){
			throw "PageProcesser : the param tableId and url are required";
		}
		
		this.opts = jQuery.extend({
			param:{},
			rowHandler:function(index, data, tr){return true;},},
			opts||{}
		);
		
		this.tdOpts = [];
		$("#" + tableId + " th[name]").each(function(index, element){
			var fieldName = $(this).attr("name");
			var fieldOpts = $(this).attr("opts");
			fieldOpts = fieldOpts ? eval("fieldOpts = " + fieldOpts) : {};
			fieldOpts = jQuery.extend({handler:function(index, data, td){return true;}}, fieldOpts);
			that.tdOpts.push({name:fieldName, index:index, opts:fieldOpts});
		});
	};
	
	$.extend($.PageProcesser.prototype, {
		
		callback:function(page_index, pagination){//pagination的回调函数
			this.requester(page_index);
			return false;
		},
		
		requester:function(page){//ajax请求数据
			var requestParam = jQuery.extend({page:(page+1), rows:this.pageSize}, this.opts.param);
			$.ajax({ type : "POST", url : this.url, data : requestParam, context:this,
				success : function(json) {
					this.handlerJson(json);
				}
			});
		},
		
		handlerJson:function(json){
			var datas = json ? (json.rows ? json.rows : []) : [] ;
			var tbody = $("#" + this.tableId + " tbody[data]");
			tbody.html("");
			
			for(var i=0 ; i<datas.length ; i++){
				var tr = $("<tr></tr>");
				for(var j=0 ; j<this.tdOpts.length ; j++){
					var val = datas[i][this.tdOpts[j].name];
					var td = $("<td></td>").text(val);
					this.tdOpts[j].opts.handler(i, datas[i], td);
					td.appendTo(tr);
				}
				this.opts.rowHandler(i, datas[i], tr);
				tr.appendTo(tbody);
			}
			
		},
	});
	
})(jQuery);

   使用:

$(function() {
		var pageHaper = new $.PageProcesser("table", "${path}/json", 10, {
			param:{type:"1"}, 
			rowHandler:function(index, data, tr){//双行变红
				index % 2 == 0 ? tr.css("color", "red") : "";
			}
		});
		$("#page_bar").pagination(100,{callback:function(pageIndex, pagination){
				return pageHaper.callback(pageIndex, pagination);
			}
		});
	});

<table id="table" style="border: 1px; width: 50%; text-align: center;">
		<thead head>
			<tr>
				<th name="id">主键</th>
				<th name="name">姓名</th>
				<th name="link" opts="{handler:function(index, data, td){
					var a = $('<a>');
					a.attr('href','http://www.baidu.com/');
					a.text('删除:' + data.id);
					a.appendTo(td);
				}}">操作</th>
			</tr>
		</thead>
		<tbody data></tbody>
	</table>
	<div id="page_bar" style="margin-top: 50px;"></div>

    效果:

205625_wimd_181985.jpg

    后台代码(Spring mvc):

    @ResponseBody
    @RequestMapping(value = "/json")
    public Object testJson(Integer page, Integer rows){
        PageInfo<Map<String, String>> pageInfo = new PageInfo<Map<String,String>>(page, rows);
        pageInfo.setRows(getMapList(pageInfo));
        return pageInfo;
    }
    
    private List<Map<String, String>> getMapList(PageInfo<?> pageInfo){
        List<Map<String, String>> rows = new ArrayList<Map<String,String>>(); 
        for (int i = pageInfo.getBegin(); i < pageInfo.getEnd()*pageInfo.getPageNo(); i++) {
            HashMap<String, String> map = new HashMap<String, String>();
            map.put("id", "id" + i);
            map.put("name", "name" + i);
            rows.add(map);
        }
        return rows;
    }

    

PageInfo代码:

/**
 * 分页 实体类 (封装分页请求和结果数据)
 */
public class PageInfo<T> implements Serializable {

    private static final long serialVersionUID = 5367449251268716436L;
    public static final int DEFAULT_PAGE_SIZE = 10;

    /** 分页信息 */
    private int pageSize = DEFAULT_PAGE_SIZE; // 每页记录条数
    private int pageNo = 1; // 页码 从1开始

    /** 查询参数 **/
    private Map<String, Object> paramMap = new HashMap<String, Object>(); //查询条件
    private Object paramObj; //查询对象

    /** 结果数据 */
    private Integer total; // 总记录数
    private List<T> rows; // 当前页显示数据

    private boolean plugin = false; //是否走分页插件
    
    private String sqlId; //用于标识具体执行的分页标识
    
    public PageInfo() {
        super();
    }
    
    public PageInfo(Integer pageNo, Integer pageSize) {
        this.pageNo = pageNo != null ? pageNo : 1;
        this.pageSize = pageSize != null ? pageSize : PageInfo.DEFAULT_PAGE_SIZE;
    }
    
    public PageInfo(Integer pageNo, Integer pageSize, Object paramObj) {
        this.pageNo = pageNo != null ? pageNo : 1;
        this.pageSize = pageSize != null ? pageSize : PageInfo.DEFAULT_PAGE_SIZE;
        this.paramObj = paramObj;//防止sql配置文件中空判断时报空指针
    }
    /**
     * 获取分页begin参数 limit {begin}, {end}
     */
    @JsonIgnore
    public int getBegin() {
        Integer begin = (pageNo - 1) * pageSize;
        if (begin < 0) {
            begin = 0;
        }
        return begin;
    }

    /**
     * 获取分页end参数 limit {begin}, {end}
     */
    @JsonIgnore
    public int getEnd() {
        if (pageSize <= 0) {
            return DEFAULT_PAGE_SIZE;
        } else {
            return pageSize;
        }
    }

    //get set 方法略  改JsonIgnore的都忽略吧,

}

     

    需要注意的是:安全问题,后台数据显示到前台一定要过滤或者编码,否则容易有xss安全问题.


    以上皆为原创,转载请注明!

转载于:https://my.oschina.net/haogrgr/blog/221106

  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值