上周产品经理提出一个需求:javascript
在编辑框中,用户双击或直接选中左括号(右引号)或左引号(有引号),对其包含的全部字符(含括号或引号字符在内)进行高亮;前端
听到这个需求的时候,个人心理活动是这样的:“卧槽,这什么需求,历来没见过。前端作得了吗?”。 脸上笑嘻嘻,内心妈卖批,伪装淡定的对产品经理说,没那么快作,排到3月份的计划去吧~java
双手挠头,开始头脑风暴
首先想到的是,搜索时,在搜索结果中对关键词的进行高亮。这个思路很简单,就是在搜索结果的文本中匹配关键词,用个span标签包裹,并给span标签加个样式便可。这个,好像跟需求相去甚远啊!
百度了半天也没找到相关的案例,没事,咱们还有时间,能够本身来造个轮子。数组
正确思路:spa
target.value.substring(selectionStart, selectionEnd); // target是文本对象
复制代码
知道了怎么获取选中的文本和如何选中部分文本,接下来就是去实现了。设计
有了思路,实现就不难了,代码很简单,相信你们应该看一下就懂了,我就不在啰嗦了。
源码:code
/** * 选中括号、引号,对其包含的全部字符进行高亮显示 * @param target 目标对象 */
function keywordHighlight(target) {
var selectionStart = target.selectionStart, // 选中的文本的起始位置
selectionEnd = target.selectionEnd, // 选中的文本的结束位置
text = target.value, // 输入框中的文本内容
selectValue = target.value.substring(selectionStart, selectionEnd); // 选中的文本
var tmpValue, // 待匹配的文本
tmpArr = [], // 用于存放切割后的待匹配文本的数组
stack = [], // 栈
endIndex; // 结束位置在tmpArr中的下标
// selectValue === '(',从前向后匹配
if (selectValue === '(') {
tmpValue = text.slice(selectionStart);
tmpArr = tmpValue.split("");
for (var i = 0, len = tmpArr.length; i < len; i++) {
if (tmpArr[i] === '(') {
stack.push(tmpArr[i]);
} else if (tmpArr[i] === ')') {
stack.pop();
if (stack.length === 0) {
endIndex = i + 1;
break;
}
}
}
if (endIndex) {
target.setSelectionRange(selectionStart, selectionStart + endIndex);
}
}
// selectValue === ')',从后向前匹配
if (selectValue.trim() === ')') {
tmpValue = text.slice(0, selectionEnd);
tmpArr = tmpValue.split("");
for (var j = tmpArr.length - 1; j >= 0; j--) {
if (tmpArr[j] === ')') {
stack.push(tmpArr[j]);
} else if (tmpArr[j] === '(') {
stack.pop();
if (stack.length === 0) {
endIndex = j;
break;
}
}
}
if (endIndex || endIndex === 0) {
target.setSelectionRange(endIndex, selectionEnd);
}
}
if (selectValue.trim() === '"') {
// 获取引号出现次数
var count = (text.slice(0, selectionEnd).split('"')).length-1;
if (count % 2 !== 0) { // 引号出现次数为奇数,从前向后匹配
// slice获取匹配文本时length+1,获取匹配下标时length+1,故最后 +1+1
endIndex = text.slice(selectionStart + 1,text.length).indexOf('"') + 1 + 1;
if (endIndex) {
target.setSelectionRange(selectionStart, selectionStart + endIndex);
}
} else { // 引号出现次数为偶数,从后向前匹配
tmpValue = text.slice(0, selectionEnd).trim();
endIndex = tmpValue.slice(0,tmpValue.length-1).lastIndexOf('"');
if (endIndex || endIndex === 0) {
target.setSelectionRange(endIndex, selectionEnd);
}
}
}
};
复制代码
参考文献:《javascript高级程序设计》第三版对象