HandsonTable封装构思
来源:互联网 发布:大数据工程师 年龄要求 编辑:程序博客网 时间:2024/06/07 14:11
HandsonTable是一个很牛逼的仿Excel的jQuery表格插件。
在做现在这个项目的时候,用原生的HandsonTable可以实现80%左右的需求。然而,第三方的插件毕竟不是为自己的项目定制的,所以在实现某些功能或者效果的时候,感觉比较费劲;而插件所提供的一系列强大的功能又没有派上用场。
当下的考虑是抽空把HandsonTable梳理一下,然后包装一层给我们的项目使用。这样一方面可以踩在巨人的肩膀上,起点较高地往上爬;另一方面,又能因地制宜地把重心集中于我们自己的业务需求上。
当前项目主要业务需求的分析:
1.层级结构展示,以及展开折叠;
2.Dropdown形式的下拉选择编辑;
2.联动编辑(包括纵向联动,横向联动);
3.“展开到”功能实现;
4.在存在折叠的情况下的联动编辑;
5.去除为展现而增加的html元素后向服务器做请求;
6.拖选控制(精准到列,以及跳过有关联控制的行);
层级结构展示,展开折叠:
现有实现:
- 在向HandsonTable添加数据的时候,直接将html元素内嵌到表格值中去;
- 向嵌入的html元素添加level之类的class属性(level,level1,level2……,lastLevel等),通过css进行样式控制(主要是margin属性的左边距);
- 为附加的html元素添加事件,用来做展开折叠;
- 在折叠的时候是通过将折叠数据临时存放到一个以rowNo做索引的二位数组中来实现的,这样可以保证在HandsonTable做滚动加载的时候不会出现留白的现象;
var sectionLevel = 'level' + section.level; if ((section.sectionNo == undefined) || (section.sectionNo == '')) { sectionObj.code = '<a class="level ' + sectionLevel + '">' + '<i class="iconfont icon-reduce"></i></a>' + section.sequenceNo; } else { sectionObj.code = '<a class="level ' + sectionLevel + '">' + '<i class="iconfont icon-reduce"></i></a>' + section.sectionNo; }
考虑封装:
- 将用来做展开折叠的列封装起来,不在每个包含HandsonTable的页面写这些嵌入html元素的代码,而是由封装的Table控件统一处理;
- 在进行编辑时,移除html元素的处理封装到组件中,并考虑是否能够在显示的时候不闪现html代码;
- 展开折叠使用的hideData全局变量考虑重构,现有实现对于同一页面包含多个Table的情况下有问题;
- 将展开折叠的实现封装到Table控件中,hideData作为Table属性存在;
Dropdown形式的下拉选择编辑:
现有实现:
- 使用HandsonTable的钩子回调事件afterBeginEditing,也就是在一个表格进入编辑状态的时候,在HandsonTable的InputHolder中嵌入一个下拉列表html串,然后将其呈现出来;
- html串自行组装,因此可以按照自己的业务要求来做控制;
- 在下拉列表点击完成之后,将InputHolder自带的Editor销毁,然后移除下拉列表内容;
relationTable.addHook('afterBeginEditing', function (row, col) { var colProp = this.colToProp(col); var cellVal = this.getDataAtCell(row, col); var colIndex = indexCols.indexOf(colProp); if ((colProp == 'tradeType') || (colIndex >= 0)) { if (cellVal) { var iconIndex = cellVal.indexOf(getRelationTableSelectIconContent()); var realVal = cellVal.substring(0, iconIndex); this.setDataAtCell(row, col, realVal); } if (colProp == 'tradeType') { showFloatingList(buildTradeTypeListHtml()); } else { var currTradeTypeId = relationTable.getSourceDataAtRow(row).tradeTypeId; showFloatingList(buildRelationIndexListHtml(currTradeTypeId, getIndexInfosByColProp(colProp))); } } });
var $selectModal = $(".handsontableInputHolder .selectModal"); if ($selectModal) { $(".handsontableInputHolder .selectModal").remove(); } var $holder = $('.handsontableInputHolder'); $holder.append(listHtml); $('.handsontableInputHolder .selectModal').show();
$("body").on("click", ".handsontableInputHolder .selectModal li", function() { var selectedVal = $(this).html(); var selectedKey = $(this).attr('accesskey'); var highlight = relationTable.getSelectedRange().highlight; var col = highlight.col; var prop = relationTable.colToProp(col); if (prop == 'tradeType') { tradeTypeCallback(selectedVal, selectedKey); } else { indexCallback(prop, selectedVal, selectedKey); } relationTable.destroyEditor(true); $(".handsontableInputHolder .selectModal").remove(); return false; });
考虑封装:
- 首先,针对column的编辑方式type为dropdown的列,将html元素(下拉箭头div)嵌入的逻辑放到封装的Table组件中;
- 将afterBeginEditing事件的去除html元素的处理封装到组件中;
- 将呈现下拉列表的处理提供回调事件列表进行处理,业务逻辑中仅仅提供下拉列表纯数据,html组装由组件完成;
- 点击响应事件提供回调进行处理,此处需要与联动编辑共同考虑;可能要用到HandsonTable的beforeChange钩子回调事件;
联动编辑:
现有实现:
- 在HandsonTable的afterChange或者beforeChange或者下拉列表框的click事件中进行业务逻辑处理;
- 业务逻辑代码中查找需要联动的子记录,并判断是否符合业务逻辑(可否联动),然后进行服务器的请求,请求成功后进行表格填充;
$("body").on("click", ".handsontableInputHolder .selectModal li", function() { var selectedVal = $(this).html(); var selectedKey = $(this).attr('accesskey'); var highlight = relationTable.getSelectedRange().highlight; var col = highlight.col; var prop = relationTable.colToProp(col); if (prop == 'tradeType') { tradeTypeCallback(selectedVal, selectedKey); } else { indexCallback(prop, selectedVal, selectedKey); } relationTable.destroyEditor(true); $(".handsontableInputHolder .selectModal").remove(); return false; });
layer.load(1, {shade : [0.3, '#ccc']}); do { if (relationData.type == 'section') { currTypeIds.push(relationData.id); } else if (relationData.type == 'normitem') { childTypeIds.push(relationData.id); } validRows.push(row); relationData = normInfoTable.getSourceDataAtRow(++row); } while ((relationData != undefined) && (relationData.level > currLevel)); collectRelationInfoIdsFromHideData(currRow, row, 'section', 'normitem', currTypeIds, childTypeIds); updateSectionTradeType(currTypeIds, childTypeIds, selectedKey, function () { $.each(validRows, function (rowIndex, rowValue) { validCells.push([rowValue, currCol, cellVal]); normInfoTable.setDataAtRowProp(rowValue, 'tradeTypeId', selectedKey); resetDisplayNormInfoIndex(rowValue); }); setHideNormInfoTradeType(currRow, row, cellVal, selectedKey); normInfoTable.setDataAtCell(validCells); layer.closeAll(); }, function () { normInfoTable.setDataAtCell([ [currRow, currCol, getCellValueWithSelectIcon(normInfoTable.getDataAtCell(currRow, currCol))] ]); layer.closeAll(); });
封装考虑:
- 根据层级关系,提供默认联动机制;
- 联动机制中提供allow回调机制,由业务层提供回调判断逻辑;
- allow回调机制是一个Hash,键为列的prop属性,值为回调方法;
展开到:
现有实现:
无
封装考虑:
- 使用封装到组件中的hideData属性来实现(展开折叠中曾用到);
- 不影响原有的展开折叠,原先展开的仍然展开,原先折叠的仍然折叠;
- 根据行元素的level属性来做折叠的功能实现;
- 将实现封装到组件内部,外部直接调用expand或者collapse,并传入一个level参数即可;
在存在折叠的情况下的联动编辑:
现有实现:
- 业务层自行实现,在处理了目前呈现的记录之后,再行考虑折叠隐藏的记录(即hideData中的记录);
$.each(hideData, function (index, data) { if ((parseInt(index) >= minRow) && (parseInt(index) < maxRow)) { $.each(data, function (arrayIndex, arrayData) { if (arrayData.type == currType) { if (currTradeTypeId == undefined) { currTypeIds.push(arrayData.id); } else if (arrayData.tradeTypeId == currTradeTypeId) { currTypeIds.push(arrayData.id); } } else if (arrayData.type == childType) { if (currTradeTypeId == undefined) { childTypeIds.push(arrayData.id); } else if (arrayData.tradeTypeId == currTradeTypeId) { childTypeIds.push(arrayData.id); } } }); } });
updateSectionTradeType(currTypeIds, childTypeIds, selectedKey, function () { $.each(validRows, function (rowIndex, rowValue) { validCells.push([rowValue, currCol, cellVal]); normInfoTable.setDataAtRowProp(rowValue, 'tradeTypeId', selectedKey); resetDisplayNormInfoIndex(rowValue); }); **setHideNormInfoTradeType(currRow, row, cellVal, selectedKey);** normInfoTable.setDataAtCell(validCells); layer.closeAll(); }, function () { normInfoTable.setDataAtCell([ [currRow, currCol, getCellValueWithSelectIcon(normInfoTable.getDataAtCell(currRow, currCol))] ]); layer.closeAll(); });
$.each(hideData, function (index, data) { if ((parseInt(index) >= minRow) && (parseInt(index) < maxRow)) { $.each(data, function (arrayIndex, arrayData) { arrayData.tradeType = cellValue; arrayData.tradeTypeId = selectedKey; arrayData.normEconomicIndex = getRelationTableSelectIconContent(); arrayData.normEconomicIndexId = undefined; arrayData.normQuantityIndex = getRelationTableSelectIconContent(); arrayData.normQuantityIndexId = undefined; arrayData.quantityIndexUnit = undefined; arrayData.quantityIndexFactor = undefined; }); } });
封装考虑:
- 将针对hideData的处理封装到组件层,而不是业务层;
- 业务层仅提供相关回调判断,是否需要联动编辑等;
去除为展现而增加的html元素后向服务器做请求
现有实现
- 业务层在做上传请求之前,对获得的数据进行组装和拆除,同时将为呈现嵌入的html元素移除掉;
if (oldVal != newVal) { var indexData = indexTable.getSourceDataAtRow(row); var formatIndex = formatIndexJson(indexData); updateCallback(formatIndex); }
function formatIndexJson(indexJson) { var formatIndex = {}; formatIndex['tradeType\.id'] = tradeId; $.each(indexJson, function (key, val) { if (key == 'sequenceNo') { return true; } else if (key == 'description') { formatIndex.description = getIndexRealDescription(indexJson.description); return true; } else if (key == 'parentIndex\.id') { if (val != undefined) { formatIndex['parentIndex\.id'] = indexJson['parentIndex\.id']; } return true; } formatIndex[key] = val; }); return formatIndex;}
封装考虑
- 考虑两种情况,单值请求与单记录请求;
- 如果在某一列prop上面挂接了单值请求的回调,则不会重复调用单记录请求;否则整行记录进行请求;
- 考虑上下级联动的情况下进行多记录请求(同样分值级别与记录级别);
- 在请求时,组件自动进行拆装箱(对每一条记录的每个属性,分为两种情况,请求带有的,呈现附加的),将为呈现附加的prop去掉,将嵌入了html元素的prop的值进行重组;然后再做上传请求处理;
拖选控制(精准到列,以及跳过有关联控制的行)
现有实现
无
封装考虑
待定,需要看一下HandsonTable的实现再做定夺!
阅读全文
0 0
- HandsonTable封装构思
- Handsontable
- Handsontable
- c++ 不破坏类封装的回调函数构思
- handsontable测试
- handsontable 的使用方法
- handsontable的核心方法
- handsontable插件事件
- Handsontable通用方法
- handsontable自定义渲染
- handsontable创建测试数据
- handsontable日期控件汉化
- 动画构思
- 开发构思
- 项目构思
- Handsontable对单元格的操作
- Html下显示表格插件-handsontable
- handsontable常规配置的中文API
- ascii unicode utf8到底是啥
- 【翻译】--docker是什么
- java使用Socket连接指定主机
- Python格式化字符串
- SHELL脚本并发问题一则记录
- HandsonTable封装构思
- C Primer Plus学习笔记----第二章C语言概述
- 当我参加培训的时候,我在学什么?
- javaweb简单的登录注册功能实现
- Java学习路线图
- 日语语法整理一
- 编程常用技巧(为了不要反复出现同样的错误)
- 20170619
- FAFU OJ 纳尼~没人中奖?