/*
* Copyright (c) 2001-2014,FineReport Inc, All Rights Reserved.
*/
;
(function ($) {
/**
* 表格控件
*
* @example
* var grid = new FR.QuickGrid({
* renderEl : $('body'),
* baseCls: 'fr-grid',
* marginLeft : 20,
* marginRight :0,
* items : [],
* columnsConfig:[],
* page : true,
* pageCount: 15,
* isFootShow :true,
* isHeadShow :true,
* multiSelect : false,
* intervalColor : false,
* isInitWithData : true,
* async: false,
* onBeforeRowCreate: null,
* onAfterRowCreate: null,
* onBeforeHeadCreate: null,
* onAfterHeadCreate: null,
* onRowClick: null,
* items: [
* {
* name: 'Task1',
* sender: 'peter',
* deadline: '2014-09-10',
* status: '0',
* operation: '1'
* },
* {
* name: 'Task2',
* sender: 'alex',
* deadline: '2005-12-10',
* status: '1',
* operation: '2'
* }
* ],
* columnsConfig: [
* {
* key: 'name',
* value: '任务名称',
* width: 200
* },
* {
* key: 'sender',
* value: '发送人',
* width: 85,
* },
* {
* key: 'sendtime',
* value: '发送时间',
* width: 120
* },
* {
* key: 'status',
* value: '任务状态',
* width: 120
* },
* {
* key: 'operation',
* value: '任务操作',
* width: 120
* },
* {
* onCellCreate: function(rowIdx, colIdx, item, colCfg){
* if(item.operation == '1'){
* return $('<div/>').html('right');
* }else{
* return $('<div/>').html('wrong');
* }
* },
* width: 90
* },
* {
* onCellCreate: function(rowIdx, colIdx, item, colCfg){
* if(item.status == '1'){
* return $('<div/>').html('‹');
* }else{
* return $('<div/>').html('›');
* }
* },
* width: 90
* }
* ]
* });
* @class FR.QuickGrid
* @extends FR.Widget
* @since 7.0.6
*
* @cfg {JSON} options 配置属性
* @cfg {String} options.baseCls 控件基础类
* @cfg {String} options.baseId 控件唯一ID
* @cfg {Number} options.marginLeft 左间距
* @cfg {Number} options.marginRight 右间距
* @cfg {Array} options.items 数据
* @cfg {Array} options.columnsConfig 列属性配置
* @cfg {Array} options.localeArray 需要做国际化转换的列名数组
* @cfg {Function} options.columnsConfig[columnIndex].onCellCreate 单元格生成事件
* @cfg {Function} options.columnsConfig[columnIndex].onCellClick 单元格点击事件
* @cfg {Function} options.columnsConfig[columnIndex].onHeadCellCreate 表头单元格生成事件
* @cfg {Object} options.columnsConfig[columnIndex].css 单元格自定义样式
* @cfg {Boolean} [options.page=false] 是否分页
* @cfg {Boolean} [options.autoPage=true] 是否自动计算分页
* @cfg {Number} [options.pageCount=15] 分页后每页显示的数据数,page属性为true时生效
* @cfg {String} [options.footAlign='bottom'] 翻页按钮的位置,'bottom'|'top'
* @cfg {Boolean} [options.isFootShow=true] 是否显示表尾控制按钮,page属性为true时生效
* @cfg {Boolean} [options.isHeadShow=true] 是否显示表头
* @cfg {Boolean} [options.intervalColor=false] 是否颜色相间
* @cfg {Boolean} [options.multiSelect=false] 是否多选
* @cfg {Boolean} [options.isInitWithData=true] 控件生成时是否初始化数据
* @cfg {Boolean} [options.hasHoverCls=true] 是否有悬浮样式
* @cfg {Object} options.async 异步属性配置
* @cfg {String} options.async.url 异步请求地址
* @cfg {String} options.async.type 异步请求方式
* @cfg {Object} options.async.data 异步请求参数
* @cfg {Function} options.onPageTurn 翻页事件
* @cfg {Function} options.onBeforeRowCreate 行生成前事件
* @cfg {Function} options.onAfterRowCreate 行生成后事件
* @cfg {Function} options.onBeforeHeadCreate 表头行生成前事件
* @cfg {Function} options.onAfterHeadCreate 表头行生成后事件
* @cfg {Function} options.onRowClick 行点击事件
* @cfg {Function} options.onRowMouseDown 行鼠标下按事件
* @cfg {Function} options.onRowMouseOver 行鼠标悬浮事件
* @cfg {Function} options.onRowMouseOut 行鼠标移出事件
* @cfg {Function} options.onAsyncSuccess 异步请求成功事件,async属性配置后生效
* @cfg {Function} options.onAsyncError 异步请求错误事件,async属性配置后生效
*/
FR.QuickGrid = FR.extend(FR.Widget, /**@class FR.QuickGrid*/{
NAV: {
FIRSTPAGE: 'first', //第一页
PREVPAGE: 'prev', //上一页
NEXTPAGE: 'next', //下一页
LASTPAGE: 'last', //最后一页
JUMPPAGE: 'jump' //跳转至某页
},
_defaultConfig: function () {
return $.extend(FR.QuickGrid.superclass._defaultConfig.call(), {
baseCls: 'fr-grid',
baseId: null,
marginLeft: 10,
marginRight: 10,
items: [],
columnsConfig: [],
page: false,
autoPage: true,
pageCount: 15,
footAlign: 'bottom',
isFootShow: true,
isHeadShow: true,
multiSelect: false,
intervalColor: false,
isInitWithData: true,
async: null,
hasHoverCls: true,
onPageTurn: null,
onAsyncSuccess: null,
onAsyncError: null,
onBeforeRowCreate: null,
onAfterRowCreate: null,
onBeforeHeadCreate: null,
onAfterHeadCreate: null,
localeArray: []
});
},
_init: function () {
FR.QuickGrid.superclass._init.apply(this, arguments);
this.$container = $('<div class="fr-grid-table"/>');
this.element.append(this.$container);
this.activedPage = 1;
var o = this.options;
if(o.baseId){
this.element.attr('id', o.baseId);
}
if (o.isInitWithData) {
this.refresh();
} else {
this._initWidth();
this.$table = $('<table cellPadding="0" cellSpacing="0"/>');
this._onCreateHead();
this._onCreateFoot();
this.$table.appendTo(this.$container);
}
},
/**
* 刷新数据并重建数据表格
* @param {Array} items 需要刷新的静态数据或是异步取数时的其他需要传递的信息
*/
refresh: function (items) {
var self = this, o = this.options;
if ($.isArray(items)) {
this.options.items = items;
this.reBuild();
} else if (o.async) {
FR.ajax({
url: o.async.url,
type: o.async.type ? o.async.type : 'POST',
data: o.async.data,
success: function (res, status) {
FR.applyFunc(self, o.onAsyncSuccess, [res, status, items]);
self.reBuild();
},
error: function (res, status) {
FR.applyFunc(self, o.onAsyncError, [res, status, items])
}
});
} else {
this.reBuild();
}
},
/**
* 重新构建数据表格,但不刷新原有数据
*/
reBuild: function () {
if(this.options.multiSelect){
this.allBoxes = [];
}
if (this.$table) {
this.$table.remove();
this.$table = null;
}
this._initWidth();
this.$table = $('<table cellPadding="0" cellSpacing="0"/>');
this._onCreateHead();
this._onCreateTable();
this._onCreateFoot();
this._bindEvts();
this.$container.append(this.$table);
},
/**
* 控件总宽度计算
*/
_initWidth: function () {
var width = 0, opts = this.options;
for (var i = 0, len = opts.columnsConfig.length; i < len; i++) {
width += opts.columnsConfig[i].width;
}
if(opts.multiSelect){
width +=25;
}
width += opts.marginLeft;
width += opts.marginRight;
opts.width = width;
this.element.width(width);
},
/**
* 生成表头
* @private
*/
_onCreateHead: function () {
var opts = this.options, self = this;
var needHead = opts.isHeadShow;
this.$head = $('<thead/>');
var $tr = $('<tr/>').appendTo(this.$head);
FR.applyFunc(this, opts.onBeforeHeadCreate, [$tr], false);
$('<td/>').append($('<div/>').width(opts.marginLeft)).appendTo($tr);
if (opts.multiSelect) {
this.$AllCheck = new FR.CheckBox({
width: 25,
listeners: [
{
eventName: FR.Events.STATECHANGE,
action: function(){
if(!self.allBoxes){
return;
}
var isSel = this.isSelected();
for(var i= 0,len=self.allBoxes.length;i<len;i++){
var box = self.allBoxes[i];
box.setValue(isSel);
}
}
}
]
});
$('<td/>').append(this.$AllCheck.element).appendTo($tr);
}
for (var colIdx = 0, len = opts.columnsConfig.length; colIdx < len; colIdx++) {
var itemcfg = opts.columnsConfig[colIdx];
var $cell = $('<td/>').width(this._calculateWidth(itemcfg));
var $el = FR.applyFunc(this, itemcfg.onHeadCellCreate, [colIdx, itemcfg], false);
if ($el === false) {
$cell.css('text-align', itemcfg.textAlign ? itemcfg.textAlign : 'left')
.text(itemcfg.value ? itemcfg.value : itemcfg.key);
} else {
$cell.append($el);
}
$cell.appendTo($tr);
}
$('<td/>').append($('<div/>').width(opts.marginRight)).appendTo($tr);
FR.applyFunc(this, opts.onAfterHeadCreate, [$tr], false);
if (needHead) {
this.$table.append(this.$head);
}
},
_calculateWidth: function (itemcfg) {
if (itemcfg) {
if (itemcfg.width > 0 && itemcfg.width < 1) {
return itemcfg.width * this.element.width();
} else {
return itemcfg.width
}
}
return 0;
},
/**
* 生成表体
* @private
*/
_onCreateTable: function () {
this.$tbody = $('<tbody/>');
var o = this.options;
var items = o.items;
if(o.page && o.autoPage){
this.totalpages = Math.ceil(o.items.length/o.pageCount);
items = o.items.slice(o.pageCount * (this.activedPage - 1), o.pageCount * this.activedPage);
}
for (var i = 0, len = items.length; i < len; i++) {
var $row = this.onCreateRow(i, items[i]);
this.$tbody.append($row);
}
this.$table.append(this.$tbody);
},
* 生成表尾的翻页按钮
* @private
*/
_onCreateFoot: function(){
var self = this, o = this.options, nav = this.NAV;
if(!o.page){
return;
}
if(this.$foot){
this.$foot.remove();
this.$foot = null;
}
this.$foot = $('<div class="fr-grid-foot"/>').css({'margin-left': o.width - 240 - o.marginRight});
//到第一页
var mf = new FR.IconButton({
imgsrc : 'fr-grid-foot-first',
width: 24,
height: 24,
handler : function() {
self.activedPage = 1;
if(!FR.applyFunc(self, o.onPageTurn, [self.activedPage, o.pageCount, nav['FIRSTPAGE']], false)){
self.reBuild();
}
}
});
//到前一页
var mp = new FR.IconButton({
imgsrc : 'fr-grid-foot-prev',
width: 24,
height: 24,
handler : function() {
self.activedPage --;
if(!FR.applyFunc(self, o.onPageTurn, [self.activedPage, o.pageCount, nav['PREVPAGE']], false)){
self.reBuild();
}
}
});
//到下一页
var mn = new FR.IconButton({
imgsrc : 'fr-grid-foot-next',
width: 24,
height: 24,
handler : function() {
self.activedPage ++;
if(!FR.applyFunc(self, o.onPageTurn, [self.activedPage, o.pageCount, nav['NEXTPAGE']], false)){
self.reBuild();
}
}
});
//到最后一页
var ml = new FR.IconButton({
imgsrc : 'fr-grid-foot-last',
width: 24,
height: 24,
handler : function() {
self.activedPage = self.totalpages;
if(!FR.applyFunc(self, o.onPageTurn, [self.activedPage, o.pageCount, nav['LASTPAGE']], false)){
self.reBuild();
}
}
});
var pageLoader = $('<input class="fr-grid-foot-loader" type="text"/>')
.val(this.activedPage).keydown(function(e) {
if (e.keyCode === 13) {
self.activedPage = $(this).val();
if(!FR.applyFunc(self, o.onPageTurn, [self.activedPage, o.pageCount, nav['JUMPPAGE']], false)){
self.reBuild();
}
e.stopEvent();
}
});
var showPage = this.totalpages?this.totalpages: 1;
if(this.activedPage >= showPage){
ml.setEnable(false);
mn.setEnable(false);
}
if(this.activedPage <= 1){
mp.setEnable(false);
mf.setEnable(false);
}
var totalPane = $('<div class="fr-grid-foot-page"/>').text(" /"+showPage +" "+ FR.i18nText("FR-Basic_Page_Number"));
var table = $('<table/>').attr({id : 'fr-grid-foot-table', cellPadding : 0, cellSpacing : 0});
$('<tr/>').append($('<td/>').append(mf.element)).append($('<td>').append(mp.element))
.append($('<td/>').addClass('fr-grid-foot-pageshow').append(pageLoader).append(totalPane))
.append($('<td/>').append(mn.element)).append($('<td/>').append(ml.element)).appendTo(table);
this.$foot.append(table);
if(o.footAlign == 'top'){
this.$foot.prependTo(this.element);
}else{
this.$foot.appendTo(this.element);
}
},
/**
* 绑定事件
* @private
*/
_bindEvts: function () {
var self = this, o = this.options;
var proxy = function (event) {
var target = event.target;
var type = event.type;
var $row = self._getTargetDom(target, 'TR');
if (!$row) {
return;
}
if (type === 'mousedown') {
FR.applyFunc(self, o.onRowMouseDown, [$row], false);
} else if (type === 'mouseover') {
o.hasHoverCls && $row.addClass('hover');
FR.applyFunc(self, o.onRowMouseOver, [$row], false);
} else if (type === "mouseout") {
$row.removeClass('hover');
FR.applyFunc(self, o.onRowMouseOut, [$row], false);
} else if (type === "mouseup") {
FR.applyFunc(self, o.onRowClick, [$row], false);
}
};
this.element.bind("mousedown", proxy)
.bind("mouseover", proxy)
.bind("mouseup", proxy)
.bind("mouseout", proxy);
},
/**
* 回溯获取指定DOM层对象
* @param {Object} curDom 当前DOM
* @param {String} targetTag DOM节点的标签
* @returns {*} 返回获取的DOM对象
* @private
*/
_getTargetDom: function (curDom, targetTag) {
while (curDom && curDom.tagName) {
if (curDom.tagName.toUpperCase() !== targetTag.toUpperCase()) {
curDom = curDom.parentNode;
} else {
return $(curDom);
}
}
return null;
},
/**
* 生成行数据
* @param rowIdx 行索引
* @param item 数据项
* @returns {*|jQuery|HTMLElement}
*/
onCreateRow: function (rowIdx, item) {
var o = this.options ,self = this;
var $row = $('<tr/>');
FR.applyFunc(this, o.onBeforeRowCreate, [$row, rowIdx, item], false);
$('<td/>').width(o.marginLeft).appendTo($row);
if (o.multiSelect) {
var $check = new FR.CheckBox({
width: 25,
gridRowData: item,
listeners: [{
eventName: FR.Events.STATECHANGE,
action: function(){
if(!self.$AllCheck){
return;
}
if(this.isSelected()){
var isAllsel = true;
for(var i= 0,len= self.allBoxes.length;i<len;i++){
var box = self.allBoxes[i];
if(!box.isSelected()){
isAllsel = false;
break;
}
}
self.$AllCheck.setValue(isAllsel);
}else{
self.$AllCheck.setValue(false);
}
}
}]
});
this.allBoxes.push($check);
$('<td/>').append($check.element).appendTo($row);
}
for (var colIdx = 0, len = o.columnsConfig.length; colIdx < len; colIdx++) {
var colCfg = o.columnsConfig[colIdx];
var $cell = this.onCellCreate(rowIdx, colIdx, item, colCfg);
$cell.appendTo($row);
}
if (o.intervalColor && rowIdx % 2 === 0) {
$row.addClass('even');
}
$('<td/>').width(o.marginRight).appendTo($row);
FR.applyFunc(this, o.onAfterRowCreate, [$row, rowIdx, item], false);
return $row;
},
/**
* 生成单元格事件
* @param rowIdx 行索引
* @param colIdx 列索引
* @param item 数据项
* @param colCfg 列属性配置
* @returns {*|jQuery|HTMLElement}
*/
onCellCreate: function (rowIdx, colIdx, item, colCfg) {
var $td = $('<td/>'), self = this;
var $cell = FR.applyFunc(this, colCfg.onCellCreate, [rowIdx, colIdx, item, colCfg], false);
if ($cell === false) {
if (!FR.isEmpty(colCfg.value)) {
var val = $.inArray(colCfg.key, self.options.localeArray) == -1 ? item[colCfg.key] : FR.i18nText(item[colCfg.key]);
$cell = $('<div class="cell"/>').width(self._calculateWidth(colCfg))
.text(val).attr('title', val)
.appendTo($td);
}
} else {
$td.append($cell);
}
$td.click(function(){
FR.applyFunc(self, colCfg.onCellClick, [rowIdx, colIdx, item, colCfg, $cell], false);
});
FR.applyStyles($cell, colCfg.css);
return $td;
},
getValue: function () {
return this.options.items;
},
/*API for QuickGrid*/
addRowData: function (item) {
var self = this, o = this.options;
if (o.async) {
} else {
var $row = this.onCreateRow(this.options.items.length, item);
this.options.items.push(item);
$row.appendTo(this.$tbody);
}
},
/**
* multiSelet为true时,可获取选中行的数据
* @returns {Array} 返回所有选中的数据
*/
getSelectedData: function(){
var datas = [];
if(this.allBoxes){
for(var i= 0,len=this.allBoxes.length;i<len;i++){
var box = this.allBoxes[i];
if(box.isSelected()){
datas.push(box.options.gridRowData);
}
}
}
return datas;
}
});
$.shortcut("quickgrid", FR.QuickGrid);
}(jQuery));