/**
* JavScript分页控件
*
* @param config 配置参数
* prefix:控件名称的前缀,用以区分页面上有多个需要分页的table的情况.例如:上一页链接id为,previousLinkId,则在配置了prefix参数是其id应为prefix_previousLinkId.
* toFirstLinkId:转到第一页的链接id
* previousLinkId:转到上一页的链接id
* toNextLinkId:转到下一页的链接id
* toLastLinkId:转到最后一页的链接id
* rowCountSpanId:显示总行数的span的id
* pageIndexSpanId:显示当前页的span的id
* pageCountSpanId:显示总页数的span的id
* dataTableId:table的id
* columnCount:表格的列数,用以在没有数据时显示提示时使用.没有传入时会自动计算列数.如果表头比较复杂例如存在多行表头的情况下建议手动设置列数
* sortCfg:排序配置,接受的是一个对象,类似于下面的结构.columnNames表示个列的列名,不需要排序的列则传入null,数组长度必须与columnCount保持一致.
* defaultColumn表示默认使用哪一列排序,allowNotSort表示是否允许任何列都不进行排序的状态.
* sortShitSequence表示当allowNotSort为true时点击表头时排序方式的变换序列,长度为3.
* defaultDirection表示默认的排序是升序还是降序其中notsort表示未排序的状态,只有allowNotSort为true是才生效.
* {
* columnNames : ["aa", null, "bb"],
* defaultColumn : "aa",
* allowNotSort : false,
* sortShitSequence : ["desc", "asc", "notsort"],
* defaultDirection : "asc" ("desc", "notsort")
* }
* 如果存在sortCfg时dataFetcher必须结构5个参数function(pageSize, pageIndex, sortColumn, sortDirection, fnCallBack),sortColumn表示当前排序的列名,
* sortDirection表示排序是升序还是降序.
* nullPrompt:没有数据时的提示信息
* dataFetcher:查询数据时调用的回调函数,该函数签名为function(pageSize, pageIndex, fnCallBack).其中pageSize为每页行数,pageIndex为查询的页索引以0为起始值,
* fnCallBack为查询后填充数据时调用的函数在dataFetcher获取到数据时必须回调该函数.fnCallBack接受一个参数,参数结构符合以下结构
* {
* pageIndex: Number当前页索引,以0为起始值
* rowCount: 数据的总行数
* pageSize: 每页行数(可选)
* data: 查询数据,没有数据可传入undefined,null或者长度为0的数组
* }
* rowInterpreter:解析每一行时调用的回调函数.该函数应接受一个参数,该参数为从服务端返回的数据中的一行记录.该函数调用后返回一行(包括tr)的HTML代码或者JQuery对象或者DOM对象.
* pageSize:每一页的行数,不传时默认值为10
* pageSizeSelectorId:选择页尺寸大小的控件的id
* queryOnInit:初始化时立刻进行一次查询,默认为true
* tableRendered:查询成功后调用的回调函数,该函数的this指针为Paginator,接受一个参数为从dataFetcher中返回的对象.
*
* 以上参数中只有dataFetcher和rowInterpreter为必传参数,其他为可选参数
*/
var Paginator = function(config)
{
this.dataFetcher = config.dataFetcher;
this.rowInterpreter = config.rowInterpreter;
this._checkConfig(config, "prefix");
this._checkConfig(config, "toFirstLinkId");
this._checkConfig(config, "previousLinkId");
this._checkConfig(config, "toNextLinkId");
this._checkConfig(config, "toLastLinkId");
this._checkConfig(config, "rowCountSpanId");
this._checkConfig(config, "pageIndexSpanId");
this._checkConfig(config, "pageCountSpanId");
this._checkConfig(config, "dataTableId");
this._checkConfig(config, "columnCount");
this._checkConfig(config, "sortCfg");
this._checkConfig(config, "nullPrompt");
this._checkConfig(config, "pageSize");
this._checkConfig(config, "pageSizeSelectorId");
this._checkConfig(config, "queryOnInit");
this._checkConfig(config, "tableRendered");
this.init();
};
/**
* 升序排列的名称
*/
Paginator.prototype.SORT_ASC = "asc";
/**
* 降序排列的名称
*/
Paginator.prototype.SORT_DESC = "desc";
/**
* 不进行排序排列的名称
*/
Paginator.prototype.NOT_SORT = "notsort";
/**
* 表头元素用来保存列名得属性名称
*/
Paginator.prototype.SORT_COLUMN_ATTR_NAME = "sortColumnName";
/**
* 分页控件的id前缀
*/
Paginator.prototype.prefix = undefined;
/**
* 每页行数
*/
Paginator.prototype.pageSize = 10;
/**
* 当前页索引,0为起始值
*/
Paginator.prototype.pageIndex = 0;
/**
* 总行数
*/
Paginator.prototype.rowCount = -1;
/**
* 总页数
*/
Paginator.prototype.pageCount = -1;
/**
* 初始化时是否进行一次查询
*/
Paginator.prototype.queryOnInit = true;
/**
* 转向第一页的链接id
*/
Paginator.prototype.toFirstLinkId = "toFirstPage";
/**
* 转向上一页的链接id
*/
Paginator.prototype.previousLinkId = "toPreviousPage";
/**
* 转向下一页的链接id
*/
Paginator.prototype.toNextLinkId = "toNextPage";
/**
* 转向最后一页的链接id
*/
Paginator.prototype.toLastLinkId = "toLastPage";
/**
* 显示总行数的span id
*/
Paginator.prototype.rowCountSpanId = "rowCountSpan";
/**
* 页数的选择控件
*/
Paginator.prototype.pageSizeSelectorId = "pageSizeSelector";
/**
* 显示页索引的span id,显示时页索引以1为起始值
*/
Paginator.prototype.pageIndexSpanId = "pageIndexSpan";
/**
* 显示总页数的span id
*/
Paginator.prototype.pageCountSpanId = "pageCountSpan";
/**
* table的id
*/
Paginator.prototype.dataTableId = "dataTable";
/**
* 表格列数
*/
Paginator.prototype.columnCount = -1;
/**
* 列排序配置
*/
Paginator.prototype.sortCfg = null;
/**
* 当前排序的列名
*/
Paginator.prototype._sortColumnName = "";
/**
* 当前排序的方向
*/
Paginator.prototype._sortDirection = "";
/**
* 没有数据时的提示信息
*/
Paginator.prototype.nullPrompt = "";
/**
* 查询数据时调用的回调函数
*/
Paginator.prototype.dataFetcher = null;
/**
* 解析每一行时调用的回调函数
*/
Paginator.prototype.rowInterpreter = null;
/**
* dataFetcher调用填充函数时传入的参数
*/
Paginator.prototype.data = null;
/**
* 查询成功后调用的回调函数
*/
Paginator.prototype.tableRendered = null;
/**
* 私有函数,如果配置参数的属性存在则配置属性
*
* @param {Object} config 配置参数
* @param {String} attrName 属性名称
*/
Paginator.prototype._checkConfig = function(config, attrName)
{
if (config[attrName] != undefined && config[attrName] != null)
{
this[attrName] = config[attrName];
}
};
/**
* 私有属性,转向第一页的链接对象
*/
Paginator.prototype._toFistLink = null;
/**
* 私有属性,转向上一页的链接对象
*/
Paginator.prototype._toPreviousLink = null;
/**
* 私有属性,转向下一页的链接对象
*/
Paginator.prototype._toNextLink = null;
/**
* 私有属性,转向最后一页的链接对象
*/
Paginator.prototype._toLastLink = null;
/**
* 私有属性,显示总行数的span对象
*/
Paginator.prototype._rowCountSpan = null;
/**
* 私有属性,显示当前页索引的span对象
*/
Paginator.prototype._pageIndexSpan = null;
/**
* 私有属性,显示总页数的span对象
*/
Paginator.prototype._pageCountSpan = null;
/**
* 私有属性,datable对象
*/
Paginator.prototype._dataTable = null;
/**
* 当前是否正在刷新中
*/
Paginator.prototype.refreshing = false;
/**
* DataFetcher调用后的回调函数
* @param {Object} data 返回的数据.符合以下结构
* {
* pageIndex: Number当前页索引,以0为起始值
* rowCount: 数据的总行数
* pageSize: 每页行数(可选)
* data: 查询数据,没有数据可传入undefined,null或者长度为0的数组
* }
*/
Paginator.prototype._dataFetcherCallback = function(data)
{
arguments.callee.paginator.refreshing = false;
arguments.callee.paginator.fillData(data);
};
/**
* 调用DataFetcher
* @param {Number} pageSize 页行数
* @param {Number} pageIndex 页索引
*/
Paginator.prototype._callDataFetcher = function(pageSize, pageIndex)
{
if (this.refreshing)
{
return;
}
this.refreshing = true;
var len = this._dataTable.find("tbody").length;
if(len >0 ){
this._dataTable.find("tbody").empty();
}
else{
this._dataTable.find("ul").empty();
}
this._rowCountSpan.text(0);
this._pageIndexSpan.text(0);
this._pageCountSpan.text(0);
this._dataFetcherCallback.paginator = this;
if (!this._sortColumnName || !this._sortDirection)
{
this.dataFetcher(pageSize, pageIndex, this._dataFetcherCallback);
}
else
{
if (this._sortColumnName == Paginator.prototype.NOT_SORT)
{
this.dataFetcher(pageSize, pageIndex, null, null, this._dataFetcherCallback);
}
else
{
this.dataFetcher(pageSize, pageIndex, this._sortColumnName, this._sortDirection, this._dataFetcherCallback);
}
}
};
/**
* 换页链接的事件函数
* @param {Object} e jQuery事件对象
*/
Paginator.prototype._linkClickEventFunc = function(e)
{
var $link = $(this), paginator = e.data;
e.preventDefault();
e.stopPropagation();
if (!$link.hasClass("disable"))
{
if (this == paginator._toFistLink.get(0))
{
paginator._callDataFetcher(paginator.pageSize, 0);
}
else if (this == paginator._toPreviousLink.get(0))
{
paginator._callDataFetcher(paginator.pageSize, paginator.pageIndex - 1);
}
else if (this == paginator._toNextLink.get(0))
{
paginator._callDataFetcher(paginator.pageSize, paginator.pageIndex + 1);
}
else if (this == paginator._toLastLink.get(0))
{
paginator._callDataFetcher(paginator.pageSize, (paginator.pageCount > 0) ? (paginator.pageCount - 1) : 2147483647);
}
}
};
/**
* 私有函数,初始化换页链接
*
* @param {Object} $link 链接的jQuery对象
*/
Paginator.prototype._initLinkClickEvent = function($link)
{
$link.bind("click", this, this._linkClickEventFunc);
};
/**
* 私有函数,初始化页行数控制控件
*
* @param {Object} $ctrl 控件的jQuery对象
*/
Paginator.prototype._initLinkChangeEvent = function($ctrl)
{
var $this = this;
$ctrl.change(function(e)
{
e.preventDefault();
e.stopPropagation();
if ($ctrl == $this._pageSizeSelector)
{
$this.pageSize = parseInt($ctrl.val(), 10);
$this._callDataFetcher($this.pageSize, $this.pageIndex);
}
});
};
/**
* 点击排序表头的事件
* @param {Object} e 事件对象
*/
Paginator.prototype._clickSortColumnHeader = function(e)
{
var paginator = e.data.paginator, clickColumn = $(this),
clickOld = clickColumn.attr(Paginator.prototype.SORT_COLUMN_ATTR_NAME) == paginator._sortColumnName;
paginator._sortColumnName = clickOld ? paginator._sortColumnName : clickColumn.attr(Paginator.prototype.SORT_COLUMN_ATTR_NAME);
paginator._dataTable.find("thead tr th[" + Paginator.prototype.SORT_COLUMN_ATTR_NAME + "] span.order").hide();
var newAnchor = clickColumn.children("span.order");
newAnchor.removeClass(Paginator.prototype.SORT_ASC).removeClass(Paginator.prototype.SORT_DESC);
if (clickOld)
{
if (paginator.sortCfg.allowNotSort)
{
var index = 0, sortShitSequence = paginator.sortCfg.sortShitSequence;
for (var i = 0; i < sortShitSequence.length; ++i)
{
if (sortShitSequence[i] == paginator._sortDirection)
{
index = i;
break;
}
}
paginator._sortDirection = sortShitSequence[(index == sortShitSequence.length - 1) ? 0 : ++index];
}
else
{
paginator._sortDirection = (paginator._sortDirection == Paginator.prototype.SORT_ASC ? Paginator.prototype.SORT_DESC : Paginator.prototype.SORT_ASC);
}
}
else
{
paginator._sortDirection = Paginator.prototype.SORT_ASC;
}
if (paginator._sortDirection != Paginator.prototype.NOT_SORT)
{
newAnchor.addClass(paginator._sortDirection).css("display", "");
}
paginator.refreshCurrent();
};
/**
* 初始化函数,通常不需要手动调用
*/
Paginator.prototype.init = function()
{
if (this.prefix)
{
this._toFistLink = $("#" + this.prefix + "_" + this.toFirstLinkId);
this._toPreviousLink = $("#" + this.prefix + "_" + this.previousLinkId);
this._toNextLink = $("#" + this.prefix + "_" + this.toNextLinkId);
this._toLastLink = $("#" + this.prefix + "_" + this.toLastLinkId);
this._rowCountSpan = $("#" + this.prefix + "_" + this.rowCountSpanId);
this._pageIndexSpan = $("#" + this.prefix + "_" + this.pageIndexSpanId);
this._pageCountSpan = $("#" + this.prefix + "_" + this.pageCountSpanId);
this._dataTable = $("#" + this.prefix + "_" + this.dataTableId);
this._pageSizeSelector = $("#" + this.prefix + "_" + this.pageSizeSelectorId);
}
else
{
this._toFistLink = $("#" + this.toFirstLinkId);
this._toPreviousLink = $("#" + this.previousLinkId);
this._toNextLink = $("#" + this.toNextLinkId);
this._toLastLink = $("#" + this.toLastLinkId);
this._rowCountSpan = $("#" + this.rowCountSpanId);
this._pageIndexSpan = $("#" + this.pageIndexSpanId);
this._pageCountSpan = $("#" + this.pageCountSpanId);
this._dataTable = $("#" + this.dataTableId);
this._pageSizeSelector = $("#" + this.pageSizeSelectorId);
}
var headThs = this._dataTable.find("thead tr th");
if (this.columnCount <= 0)
{
this.columnCount = headThs.size();
}
if (this.sortCfg && this.sortCfg.columnNames && this.sortCfg.columnNames.length == this.columnCount)
{
var $this = this;
headThs.each(function(index, domEle)
{
if ($this.sortCfg.columnNames[index] && $this.sortCfg.columnNames[index] != "")
{
$(domEle).attr($this.SORT_COLUMN_ATTR_NAME, $this.sortCfg.columnNames[index]).append($("<span class='order'></span>").hide())
.css("cursor", "pointer").bind("click",{paginator: $this}, $this._clickSortColumnHeader);
if (!$this._sortColumnName)
{
$this._sortColumnName = $this.sortCfg.columnNames[index];
}
}
});
if (headThs.filter("[" + this.SORT_COLUMN_ATTR_NAME + "]").size() > 0)
{
if (this.sortCfg.defaultColumn && this.sortCfg.defaultColumn != "")
{
this._sortColumnName = this.sortCfg.defaultColumn;
}
if (this.sortCfg.defaultDirection && this.sortCfg.defaultDirection != "")
{
this._sortDirection = this.sortCfg.defaultDirection;
}
else
{
this._sortDirection = this.SORT_ASC;
}
if (this._sortDirection != Paginator.prototype.NOT_SORT)
{
headThs.filter("[" + this.SORT_COLUMN_ATTR_NAME + "='" + this._sortColumnName + "']").children("span.order").addClass(this._sortDirection).css("display", "");
}
}
}
this._initLinkClickEvent(this._toFistLink);
this._initLinkClickEvent(this._toPreviousLink);
this._initLinkClickEvent(this._toNextLink);
this._initLinkClickEvent(this._toLastLink);
this._initLinkChangeEvent(this._pageSizeSelector);
if (this.queryOnInit)
{
this._callDataFetcher(this.pageSize, 0);
}
};
/**
* 在dataFetcher中调用的填充数据函数
* @param {Object} data 数据对象
*/
Paginator.prototype.fillData = function(data)
{
this.data = data;
this.pageIndex = data.pageIndex;
this.rowCount = data.rowCount > 0 ? data.rowCount : 0;
if (data.pageSize && data.pageSize > 0)
{
this.pageSize = data.pageSize;
this._pageSizeSelector.val(data.pageSize);
}
this.pageCount = parseInt(this.rowCount / this.pageSize) + ((this.rowCount % this.pageSize > 0) ? 1 : 0);
if (this.pageIndex <= 0)
{
this._toFistLink.addClass("disable");
this._toPreviousLink.addClass("disable");
}
else
{
this._toFistLink.removeClass("disable");
this._toPreviousLink.removeClass("disable");
}
if (this.pageIndex >= (this.pageCount - 1))
{
this._toNextLink.addClass("disable");
this._toLastLink.addClass("disable");
}
else
{
this._toNextLink.removeClass("disable");
this._toLastLink.removeClass("disable");
}
this._rowCountSpan.text(this.rowCount);
if (this.pageCount > 0)
{
this._pageIndexSpan.text(this.pageIndex + 1);
}
else
{
this._pageIndexSpan.text(0);
}
this._pageCountSpan.text(this.pageCount);
var len = this._dataTable.find("tbody").length;
if(len > 0){
$tbody = this._dataTable.find("tbody");
}
else{
$tbody = this._dataTable.find("ul");
}
if (data.data && data.data.length > 0)
{
for (var i = 0; i < data.data.length; ++i)
{
$tbody.append(this.rowInterpreter(data.data[i]));
}
}
else if (this.nullPrompt && this.nullPrompt.length > 0)
{
$tbody.append("<tr><td style=\"text-align: center;\" colspan=\"" + this.columnCount + "\">" + this.nullPrompt + "</td></tr>");
}
initDataGrid(this._dataTable.attr("id"));
if (this.tableRendered)
{
this.tableRendered(data);
}
};
/**
* 刷新列表
*/
Paginator.prototype.refresh = function()
{
this._callDataFetcher(this.pageSize, 0);
};
/**
* 重新查询当前页
*/
Paginator.prototype.refreshCurrent = function()
{
this._callDataFetcher(this.pageSize, this.pageIndex);
};