索引
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)
设置该列是否可编辑,默认为false
isBatchEditable()
和setBatchEditable(true/false)
设置该列是否允许多选时批量编辑,默认为true
getAccessType()
和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')
决定以文本方式进行渲染时的水平对齐方式,默认为left
isNullable()
和setNullable(true/false)
决定属性是否可为空,默认为true
,设置为false
可避免输入null
或undefined
isEmptiable()
和setEmptiable(true/false)
决定属性是否可为空字符串,默认为false
,可避免输入空字符串,空字符串转换成undefined
getSortOrder()
和setSortOrder('desc'/'asc')
存取列升降序状态,点击表头排序时会自动改变其值isSortable()
和setSortable(true/false)
存取列是否可排序标志,默认为true
getSortFunc()
和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
:枚举下拉编辑器是否允许可输入,默认为false
enumStrict
:值匹配时是否采用严格的===
进行比较,默认为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)
获取和设置列线是否可见,默认为true
isColumnLineColor()
和setColumnLineColor(color)
获取和设置列线颜色isResizable()
和setResizable(true/false)
获取和设置列宽是否允许改变,默认为true
isMovable()
和setMovable(true/false)
获取和设置列顺序是否允许移动改变,默认为true
getTableView()
获取表头绑定的表格组件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)
获取和设置行线是否可见,默认为true
getRowLineColor()
和setRowLineColor(color)
获取和设置行线颜色isColumnLineVisible()
和setColumnLineVisible()
获取和设置列线是否可见,默认为true
getColumnLineColor()
和setColumnLineColor(color)
获取和设置列线颜色getSortColumn()
和setSortColumn(column)
获取和设置当前排序列getSortFunc()
和setSortFunc(sortFunc)
获取和设置排序函数,默认值为空不排序,其值在没有sortColumn
情况下起作用getVisibleFunc()
和setVisibleFunc()
获取和设置可见过滤器,其可过滤DataModel
中的Data
数据对象getScrollBarColor()
和setScrollBarColor(color)
获取和设置滚动条颜色getScrollBarSize()
和setScrollBarSize(6)
获取和设置滚动条宽度isAutoHideScrollBar()
和setAutoHideScrollBar(true/false)
获取和设置是否自动隐藏滚动条,默认为true
isCheckMode()
和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);
}
}
]);