索引
HT for Web提供了表格组件类ht.widget.TableView,用于显示DataModel数据容器中Data类型对象的属性信息,支持排序和过滤等功能。
通过tableView = new ht.widget.TableView(dataModel);初始化构建一个表格组件对象,dataModel参数为表格组件绑定的数据模型,
该模型为空时表格组件构造函数内部将创建一个新的数据模型进行绑定。
表格组件的getColumnModel()函数返回列模型对象,其本质也是个DataModel类型对象,只不过该对象是仅用于添加ht.Column类型对象,
ht.Column类型的父类为ht.Data,增加了和属性定义相关的函数接口。
因此用户所需要做的工作是,根据要显示的属性信息构建出ht.Column对象,然后添加到tableView.getColumnModel()函数返回的列模型,
这样tableView.getDataModel()的数据模型中的Data的相关属性信息,就会根据tableView.getColumnModel()上存储的
ht.Column对象的配置进行显示。
ht.Column列类继承于ht.Data,不可设置父子关系,具备以下属性函数:
getName()和setName(name)用于存取name属性,该属性结合accessType属性最终实现对Data属性的存取getDisplayName()和setDisplayName(displayName)用于存取表头的列名内容,若为空则显示name值getIcon()和setIcon('icon')存取表头的列名左侧显示的图标getWidth()和setWidth(80)存取列宽度,默认setWidth函数允许的最小宽度为16,避免列过窄isVisible()和setVisible(true/false)存取列是否可见getColor()和setColor(color)存取表头的列名的文本颜色isEditable()和setEditable(true/false)设置该列是否可编辑,默认为falseisBatchEditable()和setBatchEditable(true/false)设置该列是否允许多选时批量编辑,默认为truegetAccessType()和setAccessType(type)操作存取列的属性类型:null: 默认类型,如name为age,采用getAge()和setAge(98)的get/set或is/set方式存取style:如name为age,采用getStyle('age')和setStyle('age', 98)的方式存取field:如name为age,采用data.age和data.age = 98的方式存取attr:如name为age,采用getAttr('age')和setAttr('age', 98)的方式存取valueType值类型用于提示组件提供合适的renderer渲染,合适的编辑控件,及改变值时必要的类型转换:null:默认类型,显示为文本方式string:字符串类型,显示为文本方式boolean:布尔类型,显示为勾选框color:颜色类型,以填充背景色的方式显示int:整型类型,文本编辑器改变值时自动通过parseInt进行转换number:浮点数类型,文本编辑器改变值时自动通过parseFloat转换getAlign()和setAlign('left'/'center'/'right')决定以文本方式进行渲染时的水平对齐方式,默认为leftisNullable()和setNullable(true/false)决定属性是否可为空,默认为true,设置为false可避免输入null或undefinedisEmptiable()和setEmptiable(true/false)决定属性是否可为空字符串,默认为false,可避免输入空字符串,空字符串转换成undefinedgetSortOrder()和setSortOrder('desc'/'asc')存取列升降序状态,点击表头排序时会自动改变其值isSortable()和setSortable(true/false)存取列是否可排序标志,默认为truegetSortFunc()和setSortFunc(function(v1, v2, d1, d2){return 1/-1/0})存取列排序函数,用于自定义排序逻辑column.getValue = function(data, column, view){return value}自定义获取值方式column.setValue = function(data, column, value, view){}自定义设置值方式column.drawCell = function (g, data, selected, column, x, y, w, h, view){}自定义单元格渲染方式column.formatValue = function(value)一般用于将数字转换更易读的文本格式,可重载自定义column.getToolTip = function(data, tableView)自定义文字提示内容`枚举是较为常见的属性编辑选择应用,在编辑时候呈现下拉列表,因此ht对枚举类型属性考虑了很多应用场景,setEnum(params)函数即可设置单个的json参数,
也可以设置逐个的参数信息setEnum(enumValues, enumLabels, enumIcons, enumEditable, enumStrict),
以下为常见的案例:
setEnum(['C','C++','JS']),传递数值数组setEnum([1,2,3], ['C','C++','JS']),传递数值和文字数组setEnum([1,2,3], ['C','C++','JS'], ['c_icon', 'c++_icon', 'js_icon']),传递数值、文字和图标数组setEnum({values:[1,2,3]}),传递数值数组setEnum({values:[1,2,3], labels:['C','C++','JS']}),传递数值和文字数组setEnum({values:[1,2,3], labels:['C','C++','JS'], icons:['c_icon', 'c++_icon', 'js_icon']}),传递数值、文字和图标数组
ht内部会自动检测用户是否引入了表单插件,若引入了表单插件的ht.widget.ComboBox组件则采用之作为编辑器, 否则采用原生html的select组件,由于原生html的select下拉组件只文本显示,因此上面的很多参数仅对ht.widget.ComboBox组件起作用。
enumValues:枚举值数组enumLabels:枚举文本数组enumIcons:枚举图标数组enumEditable:枚举下拉编辑器是否允许可输入,默认为falseenumStrict:值匹配时是否采用严格的===进行比较,默认为true,若为false则采用==进行比较表单插件中的滑动条ht.widget.Slider也是较为常见和易用的编辑组件,
为此ht也增加了该类型相应列属性的设置,通过getSlider()和setSlider(parmas)可指定该列在编辑状态呈现的滑动条信息。
上列中告警级别信息存于Data对象的attr类型的属性alarmSeverity中,第一列设置了setSortFunc的排序函数,
实现Cleared告警级别置顶,其他告警级值越高排在越上层的效果,同时调用了tableView.setSortColumn(column)指定了当前排序列。
var column = new ht.Column();
column.setName("alarmSeverity");
column.setAccessType('attr');
column.setSortFunc(function(v1, v2, d1, d2){
if(v1 === v2){
return 0;
}
// keep 'Cleared' on top
if(v1 === 0){
return -1;
}
if(v2 === 0){
return 1;
}
// compare value
if(v1 > v2){
return -1;
}else{
return 1;
}
});
columnModel.add(column);
tableView.setSortColumn(column);
第二列重载了column.getValue自定义了获取值的方式,根据attr类型的属性alarmSeverity值,通过map对象的
配置找到对应的告警级别颜色。通过设置valueType为color类型后,ht自动会用填充满单元格背景色的方式渲染该属性。
column = new ht.Column();
column.setValueType('color');
column.getValue = function(data){
var alarmSeverity = data.getAttr('alarmSeverity'),
color = map[alarmSeverity].color;
return tableView.isSelected(data) ? ht.Default.darker(color) : color;
};
columnModel.add(column);
第三列重载了column.drawCell自定义单元格渲染效果,通过tableView.getRowIndex(data)返回data对象所在行索引,
将索引信息通过ht.Default.drawText绘制在单元格中间,同时根据索引的奇偶绘制不同的行背景色。
column = new ht.Column();
column.drawCell = function (g, data, selected, column, x, y, w, h, tableView) {
var index = tableView.getRowIndex(data);
// draw background
var color = index % 2 === 0 ? '#ECF0F1' : '#3498DB';
g.fillStyle = selected ? ht.Default.darker(color) : color;
g.beginPath();
g.rect(x, y, w, h);
g.fill();
// draw label
color = selected ? 'white' : 'black';
ht.Default.drawText(g, 'row ' + index, null, color, x, y, w, h, 'center');
};
columnModel.add(column);
第四列重载了column.drawCell自定义单元格渲染效果,根据attr类型的属性alarmSeverity值,
通过map对象的配置找到对应的告警级别名字和颜色信息进行渲染绘制。
column = new ht.Column();
column.setWidth(200);
column.drawCell = function (g, data, selected, column, x, y, w, h, tableView) {
var alarmSeverity = data.getAttr('alarmSeverity'),
info = map[alarmSeverity],
color = info.color;
// draw background
g.fillStyle = selected ? ht.Default.darker(color) : color;
g.beginPath();
g.rect(x, y, w, h);
g.fill();
// draw label
color = selected ? 'white' : 'black';
ht.Default.drawText(g, info.name, null, color, x, y, w, h, 'center');
};
columnModel.add(column);
ht.widget.TableHeader表头组件常与TableView和TreeTableView结合呈现Column信息,
并提供Column的正反排序切换、列宽大小拉伸,以及列顺序位置变化等交互操作功能。
通过tableHeader = new ht.widget.TableHeader(tableView/treeTableView);初始化构建一个表头组件对象,
可传入tableView或treeTableView的表格组件对象进行绑定,tableHeader将自动监听tableView.getColumnModel()的列模型,
当用户点击排序、列宽变化以及列顺序变化等操作,都将相应的修改到列模型的Column属性上,用户直接通过API修改Column属性时表头组件也会自动刷新。
getSortDescIcon()和setSortDescIcon(icon)获取和设置表头列降序图标getSortAscIcon()和setSortAscIcon(icon)获取和设置表头列升序图标getMoveBackground()和setMoveBackground(color)获取和设置移动列时的列头背景色getInsertColor()和setInsertColor(color)获取和设置移动列时可插入位置的提示颜色isColumnLineVisible()和setColumnLineVisible(true/false)获取和设置列线是否可见,默认为trueisColumnLineColor()和setColumnLineColor(color)获取和设置列线颜色isResizable()和setResizable(true/false)获取和设置列宽是否允许改变,默认为trueisMovable()和setMovable(true/false)获取和设置列顺序是否允许移动改变,默认为truegetTableView()获取表头绑定的表格组件getLabel(column)获取列头文字信息,默认返回column.toLabel(),可重载自定义getLabelFont(column)获取列头文字字体,可重载自定义getLabelColor(column)获取列头文字颜色,默认会考虑column.getColor()值,可重载自定义getLabelAlign(column)获取列头文字水平对齐方式,默认会考虑column.getAlign()值,可重载自定义drawColumn(g, column, x, y, width, height)绘制列头,可重载自定义以上例子构建了两个ht.widget.TableHeader表头组件,他们绑定同一个tableView对象,因此两个表头可实现交互同步的效果。
tableHeader1 = new ht.widget.TableHeader(tableView);
tableHeader2 = new ht.widget.TableHeader(tableView);
borderPane = new ht.widget.BorderPane();
borderPane.setTopView(tableHeader1);
borderPane.setCenterView(tableView);
borderPane.setBottomView(tableHeader2);
TableView提供了addColumns和setColumns的函数,可通过json格式较容易的批量添加Column列,上例采用了如下的代码方式:
tableView.addColumns([
{
displayName: 'Severity',
name: 'alarmSeverity',
accessType: 'attr',
sortOrder: 'desc',
tag: 'sortableColumn',
sortFunc: function(v1, v2, d1, d2){
if(v1 === v2){
return 0;
}
// keep 'Cleared' on top
if(v1 === 0){
return -1;
}
if(v2 === 0){
return 1;
}
// compare value
if(v1 > v2){
return -1;
}else{
return 1;
}
}
},
// ...
]);
例子中只有第一列允许排序,其他列的sortable属性都设置成了false,为了初始化显示就对该列进行排序,代码中特意为第一列设置了tag标识,
通过tableView.getColumnModel().getDataByTag('sortableColumn')查找到该列对象。
tableView.setSortColumn(tableView.getColumnModel().getDataByTag('sortableColumn'));
注意
tableView.getColumnModel()也就是DataModel,Column也是继承于Data类型,因此具备tag等数据容器的相关操作。
上节例子通过BorderPane容器组合了TableView和TableHeader对象,大部分情况这两个对象是需要一体化使用,
为此HT提供了ht.widget.TablePane和ht.widget.TreeTablePane,这两个组件分别内置构建了TableView和TreeTableView对象,
同时也都内置构建了一个TableHeader对象,界面上TableHeader组件呈现于上方,TableView和TreeTableView组件呈现于下方。
ht.widget.TablePane和ht.widget.TreeTablePane构造函数可分别传入TableView和TreeTableView对象,
若未传入则内部自动生成一个TableView和TreeTableView对象,其他常用函数如下:
getTableView()获取表格组件getTableHeader()获取表头组件getDataModel()获取表格组件绑定的数据模型getColumnModel()获取表格组件绑定的列模型addColumns(array)用json的数组参数方式批量添加列信息setColumns(array)用json的数组参数方式批量添加列信息,参数为空时代表清空目前所有列以上例子中继承于ht.Column扩展了com.hightopo.LanguageColumn和com.hightopo.LanguageColumn这两个列类型,
主要目的是在构造函数中初始化必要的参数配置信息,这样可以避免在项目比较大,同类型列需要多处定义时重复配置信息过多,
并有利于参数信息的统一修改。
com = {};
com.hightopo = {};
var LanguageColumn = com.hightopo.LanguageColumn = function(){
LanguageColumn.superClass.constructor.call(this);
this.setName('Language');
this.setAccessType('attr');
this.setEnum({values: [1, 2, 3, 4, 5, 6], labels: ['C', 'C++', 'Java', 'JS', 'AS', 'C#']});
this.setEditable(true);
this.setSortFunc(function(v1, v2, d1, d2){
if(v1 === v2){
return 0;
}
if(v1 === 2){
return 1;
}
if(v2 === 2){
return -1;
}
if(v1 === 5){
return -1;
}
if(v2 === 5){
return 1;
}
return v1 - v2;
});
};
ht.Default.def('com.hightopo.LanguageColumn', ht.Column, {
});
var SexColumn = com.hightopo.SexColumn = function(){
SexColumn.superClass.constructor.call(this);
this.setName('Sex');
this.setAccessType('attr');
this.setEnum(['Male', 'Female']);
this.setEditable(true);
};
ht.Default.def('com.hightopo.SexColumn', ht.Column, {
});
通过以上的类封装,配置列属性时就减少了很多参数,以下代码需注意className的关键字,
ht会根据这个className特殊关键字信息来替换默认的ht.Column类型,
同理属性组件也会通过className特殊关键字信息来替换默认的ht.Property类型。
tablePane.addColumns([
{
name: 'id',
width: 60,
tag: 'id'
},
{
className: 'com.hightopo.LanguageColumn',
width: 100,
tag: 'language'
},
{
className: 'com.hightopo.SexColumn',
width: 100,
tag: 'sex'
}
]);
propertyView.addProperties([
{
name: 'id'
},
{
className: 'com.hightopo.LanguageProperty',
editable: true
},
{
className: 'com.hightopo.SexProperty',
editable: true
}
]);
通过tablePane.getTableHeader().setResizable(false)将表头被设置成不可改变列宽度:
tablePane.getTableHeader().setResizable(false);
通过tablePane.addViewListener监听tablePane的组件事件,当监听到beginValidate事件触发时,
根据当前组件宽度,对每个列宽进行分配,在定义column时设置了tag参数,
因此通过columnModel.getDataByTag('language')可找到对应的列:
tablePane.addViewListener(function(e){
if(e.kind === 'beginValidate'){
var columnModel = tablePane.getColumnModel(),
width = tablePane.getWidth();
columnModel.getDataByTag('id').setWidth(width * 0.2);
columnModel.getDataByTag('language').setWidth(width * 0.4);
columnModel.getDataByTag('sex').setWidth(width * 0.4);
}
});
表格组件类ht.widget.TableView主要可配置属性和函数如下:
enableToolTip()和disableToolTip()开启和关闭文字提示isDisabled()和setDisabled(true/false, iconURL)可获取和设置整个组件处于不可用状态addTopPainter(func)和removeTopPainter(func)增加和删除顶层绘制器function(g){...}addBottomPainter(func)和removeBottomPainter(func)增加和删除底层绘制器function(g){...}isEditable()和setEditable(true/false)控制可否编辑的总开关,默认为false,每个Column列对象可再控制isBatchEditable()和setBatchEditable(true/false)控制可否多选时批量编辑总开关,默认为true,每个Column列对象可再控制getRowHeight()和setRowHeight(20)获取和设置行高isRowLineVisible()和setRowLineVisible(true/false)获取和设置行线是否可见,默认为truegetRowLineColor()和setRowLineColor(color)获取和设置行线颜色isColumnLineVisible()和setColumnLineVisible()获取和设置列线是否可见,默认为truegetColumnLineColor()和setColumnLineColor(color)获取和设置列线颜色getSortColumn()和setSortColumn(column)获取和设置当前排序列getSortFunc()和setSortFunc(sortFunc)获取和设置排序函数,默认值为空不排序,其值在没有sortColumn情况下起作用getVisibleFunc()和setVisibleFunc()获取和设置可见过滤器,其可过滤DataModel中的Data数据对象getScrollBarColor()和setScrollBarColor(color)获取和设置滚动条颜色getScrollBarSize()和setScrollBarSize(6)获取和设置滚动条宽度isAutoHideScrollBar()和setAutoHideScrollBar(true/false)获取和设置是否自动隐藏滚动条,默认为trueisCheckMode()和setCheckMode(true/false)获取和设置是否为check模式,默认为false,为true时自动插入checkColumn列getColumnModel(): 表格组件内置一个DataModel类型的列模型,用于存储Column列对象信息onColumnClicked(column)列头被点击时调用,可重载做后续处理,如远程排序功能getCheckIcon(data)返回data对象对应的check图标,可重载自定义check图标,该函数在checkMode模式下有效getFocusData()、setFocusData(data)和setFocusDataById(id)在checkMode模式下图元除了被选中有check状态外,还可以有被点击行的focus状态getDataAt(pointOrEvent)传入逻辑坐标点或交互事件event参数,返回对应的data对象或空onDataDoubleClicked(data)当data所在行被双击时回调,可重载对双击事件做响应onDataClicked(data)当data所在行被单击时回调,可重载对单击事件做响应getLabelFont(data, column, value)返回对应的单元格文本字体,可重载自定义getLabelColor(data, column, value)返回对应的单元格文本颜色,可重载自定义getSelectBackground(data)和setSelectBackground(color)获取和设置行选中背景颜色getStartRowIndex()返回当前可见区域的起始行索引getEndRowIndex()返回当前可见区域的结束行索引getRowDatas()返回当前显示的Data对象数组,该数组已被排序和过滤getRowIndex(data)返回data对象所在的行索引getRowSize()返回当前可见行总行数isVisible(data)判断data对象是否可见,可重载自定义getDataModel()获取绑定的DatModel数据模型setDataModel(dataModel)绑定新的DatModel数据模型makeVisible(data)该函数触发组件滚动到确保data对象出现在可见区域。invalidateModel()该函数触发组件重新排序过滤加载数据,一般组件会自动调用,除非数据变化但未派发事件时才需强制调用redraw()重绘刷新,注意该函数不会触发数据模型的重新加载invalidateData(data)调用该函数会重绘data对象所在行drawRowBackground(g, data, selected, x, y, width, height)绘制行背景色,默认仅在选中该行时填充选中背景色,可重载自定义drawCell(g, data, selected, column, x, y, width, height)绘制单元格,可重载自定义单元格渲染drawCheckColumnCell(g, data, selected, column, x, y, width, height, view)绘制check列单元格,可重载自定义isCellEditable(data, column)判断单元格是否可编辑,可重载自定义getCurrentSortFunc()该函数默认返回sortFunc函数,当sortColumn不为空时将返回其对应的排序函数handleDragAndDrop(event, state)该函数默认为空,若该函数被重载,则pan平移组件功能将被关闭event鼠标或Touch交互事件state当前状态,先后会有prepare-begin-between-end四种过程以下为getCurrentSortFunc函数默认实现,TableView的sortFunc回调时的两个参数分别是d1和d2即两个不同的Data对象,
Column的sortFunc回调时传入的是v1,v2,d1,d2四个参数,也就是头两个参数分别为Data对象对应列的值。
getCurrentSortFunc: function () {
var column = this._sortColumn;
if (column && column.isSortable()) {
var func = column.getSortFunc(),
tableView = this,
order = 'asc' === column.getSortOrder() ? 1 : -1;
if (!func) {
func = ht.Default.sortFunc;
}
return function (d1, d2) {
var v1 = tableView.getValue(d1, column),
v2 = tableView.getValue(d2, column);
return func.call(tableView, v1, v2, d1, d2) * order;
};
}
return this._sortFunc;
}
以下代码通过tableHeader.getView().style获取表头的底层div组件,采用css的设置以repeat-x方式平铺了渐进色的背景。
tableHeader = tablePane.getTableHeader();
tableHeader.getView().style.background = 'url(images/header.png) repeat-x';
以下代码重载了drawRowBackground函数,绘制了表格行交替斑马线的效果。
tableView.drawRowBackground = function(g, data, selected, x, y, width, height){
if(tableView.isSelected(data)){
g.fillStyle = '#87A6CB';
}
else if(tableView.getRowIndex(data) % 2 === 0){
g.fillStyle = '#F1F4F7';
}
else{
g.fillStyle = '#FAFAFA';
}
g.beginPath();
g.rect(x, y, width, height);
g.fill();
};
以下代码设置了可见过滤器,过滤器根据toolbar工具条的元素选中状态决定Data对象是否可见,由于过滤器只设置一次,
过滤规则随着工具条状态的变化而变化,但工具条元素的状态变化并未派发任何任何事件,因此工具条按钮的action都显示
调用了tableView.invalidateModel();通知表格进行数据重新加载更新。
tableView.setVisibleFunc(function(data){
var nation = data.a('nation'),
sex = data.a('sex');
// filter nation
if(!toolbar.getItemById('nation-all').selected){
if(toolbar.getItemById('uk').selected && nation !== 0){
return false;
}
if(toolbar.getItemById('usa').selected && nation !== 1){
return false;
}
if(toolbar.getItemById('mexico').selected && nation !== 2){
return false;
}
}
// filter sex
if(!toolbar.getItemById('sex-all').selected){
if(toolbar.getItemById('man').selected && sex !== 0){
return false;
}
if(toolbar.getItemById('woman').selected && sex !== 1){
return false;
}
}
return true;
});
以下代码在添加的列中重载了drawCell函数,通过ht.Default.drawStretchImage函数在单元格中心位置绘制了对应的图标,
drawStretchImage函数的第三个参数可传入fill、uniform或centerUniform的类型。
tablePane.addColumns([
{
name: 'index',
displayName: 'Index',
accessType: 'attr',
align: 'center'
},
{
name: 'nation',
displayName: 'Nation',
accessType: 'attr',
align: 'center',
drawCell: function (g, data, selected, column, x, y, w, h, view) {
var image = ht.Default.getImage('images/' + nations[data.a('nation')] + '.png');
ht.Default.drawStretchImage(g, image, 'centerUniform', x, y, w, h);
}
},
{
name: 'sex',
displayName: 'Sex',
accessType: 'attr',
align: 'center',
drawCell: function (g, data, selected, column, x, y, w, h, view) {
var image = ht.Default.getImage('images/' + sexs[data.a('sex')] + '.png');
ht.Default.drawStretchImage(g, image, 'centerUniform', x, y, w, h);
}
}
]);