在前文《状态驱动的编辑模型:SpreadJS 单元格类型的生命周期管理》中,解构了单元格静态显示和动态编辑的状态切换过程,自此了解了单元格编辑能力源于单元格类型的编辑器。作为前端页面上的编辑器,单元格类型的编辑器以可编辑DOM元素存在,便可通过为DOM元素设置style样式属性定义其显示效果。那么,在什么时候设置呢?
单元格生命周期有两个时期可以装饰编辑器,分别是创建编辑器元素和激活编辑器时。在createEditorElement方法中出厂即完成配置,这种一次性完成的方式相当于饿设置,一次设置永久生效。与之相比,生命周期蔓延至activateEditor时,可以获取的上下文信息包括编辑器上下文(editorContext)、单元格样式(cellStyle)、单元格位置(单元格在Canvas中的绘制位置,cellRect)和单元格上下文(context),延迟至激活编辑器时可以结合单元格上下文根据单元格坐标或者单元格数据设置编辑器样式,此为懒设置。比如,以Text单元格类型为例,如果当前单元格有数据,则显示背景色为黄色,否则背景色显示为浅绿色,如图1所示。
图1. 单元格编辑器背景色设置
参考如下代码:
- var oldActivateEditor = cellTypes.Text.prototype.activateEditor;
- cellTypes.Text.prototype.activateEditor = function(editorContext, cellStyle, cellRect, context) {
- console.log('activate editor, eidtorContext: ', editorContext, ', cellStyle: ', cellStyle, ', cellRect: ', cellRect, ', context: ', context);
- if (context.sheet.getValue(context.row, context.col)) {
- editorContext.style.backgroundColor = 'yellow';
- } else {
- editorContext.style.backgroundColor = 'lightgreen';
- }
- oldActivateEditor.apply(this, [editorContext, cellStyle, cellRect, context]);
- }
复制代码
虽然单元格样式支持了根据单元格状态显示不同样式效果,但该样式效果不受单元格数据或单元格坐标影响。单元格条件格式能够根据单元格数据显示不同样式效果,但此时单元格已处于静止显示状态,而非编辑状态。如果在开发场景中需要参考单元格中的既有数据或单元格坐标控制单元格编辑器的样式效果,首选从activateEditor方法介入定义控制逻辑,充分利用activateEditor方法能够获取的上下文信息。
Text单元格类型的编辑器仅一个DOM元素,而ComboBox单元格类型的编辑能力由编辑框(gcComboBoxEditor)、下拉按钮(gcDropDownButton)和下拉列表框(gcDropDownWindow)等多个元素共同提供,如图2所示。点击ComboBox单元格类型的下拉按钮令ComboBox进入输入态,编辑框被激活,具备了接收键盘输入的能力,同时弹出下拉列表框显示选项,供用户点击选项填入。那么如何控制上述三个组成DOM元素的显示样式呢?当然是依次对每个DOM元素设置样式属性。
图2. ComboBox单元格DOM元素
如图2所示,ComboBox中的DOM元素均有自定义属性gcuielement,由此纳入SpreadJS的管理范围。其中,ComboBox:activateEditor()方法接收到的编辑器上下文参数editorContxt对应为gcuielement属性值为gcComboBoxEditor的div元素。此外,下拉按钮对应的div元素的gcuielement属性值为gcDropDownButton,gcuielement属性值为gcDropDownWindow的div元素对应为下拉列表框。既然activateEditor方法接收了gcuielement属性值为gcComboBoxEditor的div元素,那么根据div元素之间的相邻关系,可以由其parentNode通过gcuielement属性值依次获得下拉按钮和下拉框对应的div元素,然后根据实际需要对各div元素设置style样式属性,参考如下代码:
- var oldComboBoxActivateEditor = GC.Spread.Sheets.CellTypes.ComboBox.prototype.activateEditor;
- GC.Spread.Sheets.CellTypes.ComboBox.prototype.activateEditor = function(editorContext, cellStyle, cellRect, context) {
- console.log('ComboBox activateEditor: ', editorContext, '\ncellStyle: ', cellStyle, '\ncellRect: ', cellRect, '\ncontext: ', context);
- editorContext.style.backgroundColor = 'red';
- var dropDownButton = editorContext.parentNode.querySelector('[gcuielement="gcDropDownButton"]');
- if (dropDownButton) {
- dropDownButton.style.backgroundColor = 'orange';
- }
- var dropDownWindow = editorContext.parentNode.querySelector('[gcuielement="gcDropDownWindow"]');
- if (dropDownWindow) {
- dropDownWindow.style.backgroundColor = 'green';
- }
- oldComboBoxActivateEditor.apply(this, [editorContext, cellStyle, cellRect, context]);
- }
复制代码
如图3所示,输入态的ComboBox的编辑框背景色呈红色,下拉按钮背景色显示为橘色,下拉列表框呈绿色背景色。
图3. ComboBox背景色
任何单元格类型的编辑器均为DOM元素,包括内置单元格类型和自定义单元格类型在内,而由于填报需要和显示效果的差异,单元格类型的编辑能力可能由单一DOM元素提供,也可以由多个DOM元素协同提供。如果需要自定义单元格编辑器的显示样式,可以在createEditorElement方法被执行时在初创编辑器时设置样式,一次设置,终生有效,此为饿设置;也可以在activateEditor方法中定义编辑器DOM元素样式设置,每次在使用DOM元素时充分结合当前单元格中的数据、坐标等信息控制样式效果。
|