浮动到表格中某一行,根据改行信息高亮某区域文字,并设置对应滚动高度,使高亮文字出现在当前视野
第一版:事先说明,此代码结合应用项目场景,故这里的代码很难理解,纯本人笔记
highlightOpinion: function (opinion) { $scope.mark.highlightContent = $scope.mark.highlightContentStore;//highlightContentStore是后台接受不带高亮效果的文字 var reg = new RegExp(); var replaceStr = ''; for (var k in opinion) { if (k == '评论关键字') { if (opinion[k] !== ' ' && opinion[k] !== '/') { reg = new RegExp(opinion[k], 'ig'); replaceStr = `<span class="color-bg-green">${opinion[k]}</span>`; $scope.mark.highlightContent = $scope.mark.highlightContent.replace(reg, replaceStr); } } else if (k == '评论小类') { if (opinion[k] !== ' ' && opinion[k] !== '/') { reg = new RegExp(opinion[k], 'ig'); replaceStr = `<span class="color-bg-blue">${opinion[k]}</span>`; $scope.mark.highlightContent = $scope.mark.highlightContent.replace(reg, replaceStr); } } } //滚动条移动到该词语 var ele = document.getElementById('textarea2'); var scrollHeight = ele.scrollHeight, totalStrLength = ele.value.length, currentStr = ele.value.toLowerCase().indexOf(opinion['评论关键字'].toLowerCase()) == -1 ? ele.value.toLowerCase().indexOf(opinion['评论小类'].toLowerCase()) : ele.value.toLowerCase().indexOf(opinion['评论关键字'].toLowerCase()); $timeout(function () { if (currentStr == -1) return; //说明原文中不包含评论关键字和评论小类 var eleCopy = document.getElementById('textarea2-copy'); eleCopy.scrollTop = (scrollHeight * currentStr / totalStrLength - 20 > 0) ? (scrollHeight * currentStr / totalStrLength - 20) : (currentStr / totalStrLength); }, 0); $scope.mark.showHighlight = true; },
效果:
附加浮动到某列。并且定位当前列和高亮当前列的方法
//item为该行的数据,tdIndex为列的位置,程序中的answerColumnName代表所有列名,answerColumnName【tdIndex】则对应该列的列名,也是该列字段的key
highlightOpinion: function (item, tdIndex) { $scope.mark.highlightContent = $scope.mark.highlightContentStore;//highlightContentStore是后台接收的不带高亮效果的文字 var reg = new RegExp(); var replaceStr = ''; var ele = document.getElementById('textarea2'); var scrollHeight = ele.scrollHeight, totalStrLength = ele.value.length, currentStr = -1; if (tdIndex >= 0) { if (item[$scope.mark.answerColumnName[tdIndex]] !== ' ' && item[$scope.mark.answerColumnName[tdIndex]] !== '/') { currentStr = ele.value.toLowerCase().indexOf(item[$scope.mark.answerColumnName[tdIndex]].toLowerCase()); } } if (tdIndex >= 0 && currentStr != -1) { //浮动到具体某列,并且该列在原文中出现,那么先高亮当前列,再高亮所有列(此时currentStr!=-1代表已定位到当前列) reg = new RegExp(item[$scope.mark.answerColumnName[tdIndex]], 'ig'); replaceStr = `<span class="answer-column-color-bg-${tdIndex + 1}">${item[$scope.mark.answerColumnName[tdIndex]]}</span>`; $scope.mark.highlightContent = $scope.mark.highlightContent.replace(reg, replaceStr); for (var i = 0; i < $scope.mark.answerColumnName.length; i++) { var keyName = $scope.mark.answerColumnName[i]; if (item[keyName] !== ' ' && item[keyName] !== '/') { reg = new RegExp(item[keyName], 'ig'); replaceStr = `<span class="answer-column-color-bg-${i + 1}">${item[keyName]}</span>`; $scope.mark.highlightContent = $scope.mark.highlightContent.replace(reg, replaceStr); } } } else { //没浮动到具体某列,那么高亮所有列,定位到在原文中出现的第一列 for (var i = 0; i < $scope.mark.answerColumnName.length; i++) { var keyName = $scope.mark.answerColumnName[i]; if (item[keyName] !== ' ' && item[keyName] !== '/') { reg = new RegExp(item[keyName], 'ig'); replaceStr = `<span class="answer-column-color-bg-${i + 1}">${item[keyName]}</span>`; $scope.mark.highlightContent = $scope.mark.highlightContent.replace(reg, replaceStr); } } for (var i = 0; i < $scope.mark.answerColumnName.length; i++) { var keyName = $scope.mark.answerColumnName[i]; if (item[keyName] !== ' ' && item[keyName] !== '/') { currentStr = ele.value.toLowerCase().indexOf(item[keyName].toLowerCase()); if (currentStr !== -1) break; } } } $timeout(function () { if (currentStr == -1) return; //说明原文中不包含老答案字段 var eleCopy = document.getElementById('textarea2-copy'); eleCopy.scrollTop = (scrollHeight * currentStr / totalStrLength - 50 > 0) ? (scrollHeight * currentStr / totalStrLength - 50) : (scrollHeight * currentStr / totalStrLength - 20 > 0) ? (scrollHeight * currentStr / totalStrLength - 20) : (currentStr / totalStrLength); }, 0); $scope.mark.showHighlight = true; },
第二版: 列浮动的升级:
升级的意义:因为列中可能包含*?+等正则表达式的敏感字段,所以需要先将这些字段进行处理,才能正确的生成正则表达式
//处理字符串中可能对正则有影响的字符串 escapeString(value) { let str = value.replace(new RegExp('\\\\', 'g'), '\\\\'); let characterss = ['(', ')', '[', ']', '{', '}', '^', '$', '|', '?', '*', '+', '.']; characterss.forEach((characters) => { var r = new RegExp('\\' + characters, 'g') str = str.replace(r, '\\' + characters) }) return str; },
//浮动高亮 highlightOpinion: function (item, tdIndex) { $scope.mark.highlightContent = $scope.mark.highlightContentStore;//highlightContentStore是后台接收的不带高亮效果的文字 var reg = new RegExp(); var replaceStr = ''; var ele = document.getElementById('textarea2'); var scrollHeight = ele.scrollHeight, totalStrLength = ele.value.length, currentStr = -1; if (tdIndex >= 0) { if (item[$scope.mark.answerColumnName[tdIndex]] !== ' ' && item[$scope.mark.answerColumnName[tdIndex]] !== '/') { currentStr = ele.value.toLowerCase().indexOf(item[$scope.mark.answerColumnName[tdIndex]].toLowerCase()); } } if (tdIndex >= 0 && currentStr != -1) { //浮动到具体某列,并且该列在原文中出现,那么先高亮当前列,再高亮所有列(此时currentStr!=-1代表已定位到当前列) var resStr = $scope.mark.escapeString(item[$scope.mark.answerColumnName[tdIndex]]) reg = new RegExp(resStr, 'ig'); replaceStr = `<span class="answer-column-color-bg-${tdIndex + 1}">${item[$scope.mark.answerColumnName[tdIndex]]}</span>`; $scope.mark.highlightContent = $scope.mark.highlightContent.replace(reg, replaceStr); for (var i = 0; i < $scope.mark.answerColumnName.length; i++) { var keyName = $scope.mark.answerColumnName[i]; if (item[keyName] !== ' ' && item[keyName] !== '/') { var resStr = $scope.mark.escapeString(item[keyName]) reg = new RegExp(resStr, 'ig'); replaceStr = `<span class="answer-column-color-bg-${i + 1}">${item[keyName]}</span>`; $scope.mark.highlightContent = $scope.mark.highlightContent.replace(reg, replaceStr); } } } else { //没浮动到具体某列,那么高亮所有列,定位到在原文中出现的第一列 for (var i = 0; i < $scope.mark.answerColumnName.length; i++) { var keyName = $scope.mark.answerColumnName[i]; if (item[keyName] !== ' ' && item[keyName] !== '/') { var resStr = $scope.mark.escapeString(item[keyName]) reg = new RegExp(resStr, 'ig'); replaceStr = `<span class="answer-column-color-bg-${i + 1}">${item[keyName]}</span>`; $scope.mark.highlightContent = $scope.mark.highlightContent.replace(reg, replaceStr); } } for (var i = 0; i < $scope.mark.answerColumnName.length; i++) { var keyName = $scope.mark.answerColumnName[i]; if (item[keyName] !== ' ' && item[keyName] !== '/') { currentStr = ele.value.toLowerCase().indexOf(item[keyName].toLowerCase()); if (currentStr !== -1) break; } } } $timeout(function () { if (currentStr == -1) return; //说明原文中不包含老答案字段 var eleCopy = document.getElementById('textarea2-copy'); eleCopy.scrollTop = (scrollHeight * currentStr / totalStrLength - 40 > 0) ? (scrollHeight * currentStr / totalStrLength - 40) : (scrollHeight * currentStr / totalStrLength - 20 > 0) ? (scrollHeight * currentStr / totalStrLength - 20) : (currentStr / totalStrLength); }, 0); $scope.mark.showHighlight = true; }, //取消浮动高亮 deleteHighlightOpinion: function () { $scope.mark.showHighlight = false; },
第三版:点击行高亮方法封装
/** * 浮动高亮 * @param rowObj:选中的行内容对象 * @param columnsTitle: 列名,注意列名都是行对象的key值 * @param mainContent:要高亮的文字 * @returns arr:arr[0]:高亮后的文字,arr[1]:第一个高亮词的位置 */ highlightOpinion: function (rowObj, columnsTitle, mainContent) { var highlightContent = mainContent; //高亮文字 var currentStr = -1; //第一个高亮词的位置 var reg = new RegExp(); var replaceStr = ''; //高亮 for (var i = 0; i < columnsTitle.length; i++) { var keyName = columnsTitle[i]; if (rowObj[keyName] != '' && rowObj[keyName] != null && rowObj[keyName] != ' ' && rowObj[keyName] !== '/') { var resStr = $scope.mark.escapeString(rowObj[keyName]) reg = new RegExp(resStr, 'ig'); replaceStr = `<span class="answer-column-color-bg-${i + 1}">${rowObj[keyName]}</span>`; highlightContent = highlightContent.replace(reg, replaceStr); var highlightIndex = mainContent.toLowerCase().indexOf(rowObj[keyName].toLowerCase()); if (highlightIndex != -1 && currentStr == -1) { currentStr = highlightIndex; //只取第一个高亮位置 } } } var arr = []; arr.push(highlightContent); arr.push(currentStr); return arr; }, highlightMarkedArea(rowObj, columnsTitle, initContent) { var arr = $scope.mark.highlightOpinion(rowObj, columnsTitle, initContent); $scope.mark.markContent = arr[0]; if (arr[1] != -1) { //有高亮的位置,gundong滚动到第一个高亮位置 var currentStr = arr[1]; var eleCopy = document.getElementById('marked-area'); var scrollHeight = eleCopy.scrollHeight; var totalStrLength = $scope.mark.markContentStore.length; eleCopy.scrollTop = (scrollHeight * currentStr / totalStrLength - 90 > 0) ? (scrollHeight * currentStr / totalStrLength - 90) : (scrollHeight * currentStr / totalStrLength - 40 > 0) ? (scrollHeight * currentStr / totalStrLength - 40) : (currentStr / totalStrLength); } },
用:
//选中、取消选中操作 clickHighlightOpinion: function (answer, index) { /* 点击时其他行取消选中,本行取反 */ $scope.mark.opinionCheckList = $scope.mark.opinionCheckList.map(function (item, index2) { if (index2 === index) { item.checked = !item.checked; } else { item.checked = false; } return item; }); /* 如果选中就高亮,不选择则显示原内容 */ if (answer.checked) { var arr = $scope.mark.highlightOpinion2(answer, $scope.mark.answerColumnName, $scope.mark.highlightContentStore); $scope.mark.mainContent = arr[0]; if (arr[1] != -1) { //有高亮的位置,gundong滚动到第一个高亮位置 var currentStr = arr[1]; var eleCopy = document.getElementById('main-content'); var scrollHeight = eleCopy.scrollHeight; var totalStrLength = $scope.mark.highlightContentStore.length; $timeout(function () { eleCopy.scrollTop = (scrollHeight * currentStr / totalStrLength - 90 > 0) ? (scrollHeight * currentStr / totalStrLength - 90) : (scrollHeight * currentStr / totalStrLength - 40 > 0) ? (scrollHeight * currentStr / totalStrLength - 40) : (currentStr / totalStrLength); }, 0); } } else { $scope.mark.mainContent = $scope.mark.highlightContentStore; } }