博客
关于我
强烈建议你试试无所不能的chatGPT,快点击我
分享一个冷门知识——文本框的选择文本在业务中的应用
阅读量:7297 次
发布时间:2019-06-30

本文共 3131 字,大约阅读时间需要 10 分钟。

上周产品经理提出一个需求:

在编辑框中,用户双击或直接选中左括号(右引号)或左引号(有引号),对其包含的所有字符(含括号或引号字符在内)进行高亮;

听到这个需求的时候,我的心理活动是这样的:“卧槽,这什么需求,从来没见过。前端做得了吗?”。 脸上笑嘻嘻,心里妈卖批,假装淡定的对产品经理说,没那么快做,排到3月份的计划去吧~

双手挠头,开始头脑风暴

首先想到的是,搜索时,在搜索结果中对关键词的进行高亮。这个思路很简单,就是在搜索结果的文本中匹配关键词,用个span标签包裹,并给span标签加个样式即可。这个,好像跟需求相去甚远啊!
百度了半天也没找到相关的案例,没事,我们还有时间,可以自己来造个轮子。

正确思路:

选择(select)事件

  • 从事件入手。高亮是文本被选中时触发,文本框有个DOM事件——select,表示文本框文本被选中时触发的事件。

如果取得选中的文本:

  • 两个属性:selectionStart、selectionEnd。 这两个属性中保存的是基于 0 的数值,表示所选择 文本的范围(即文本选区开头和结尾的偏移量)。
  • 要获得选中的文本,可以使用如下代码:
target.value.substring(selectionStart, selectionEnd);  // target是文本对象复制代码
  • IE9+、Firefox、Safari、Chrome 和 Opera 都支持这两个属性。IE8 及之前版本不支持这两个属性, 而是提供了另一种方案,这里不做介绍

如何选择部分文本

  • 所有文本框都有一个 setSelectionRange()方法。这个方法接收两个参数:要选择的第一个字符的索引和要选择的最后一个字符之后的字符的索引。

实现

知道了怎么获取选中的文本和如何选中部分文本,接下来就是去实现了。

  • 括号跟引号的匹配逻辑是不同的,括号要考虑嵌套问题,而引号不用,因为引号的嵌套没有语义。
  • 左括号跟右括号的匹配逻辑也是不同的,如果用户选中的是左括号,则要从前向后匹配。如果是右括号,则要从后往前匹配。
  • 引号类似,只是不需要考虑嵌套关系

有了思路,实现就不难了,代码很简单,相信大家应该看一下就懂了,我就不在啰嗦了。

源码:

/** * 选中括号、引号,对其包含的所有字符进行高亮显示 * @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高级程序设计》第三版

转载于:https://juejin.im/post/5c81d105e51d453c8f485f9e

你可能感兴趣的文章
[Tool]靜態程式碼分析-FxCop
查看>>
URAL 1055 Combinations
查看>>
小白学数据分析----->聚类分析理论之K-means理论篇
查看>>
Spark SQL Catalyst源代码分析之TreeNode Library
查看>>
怎样学好C语言,一个成功人士的心得!
查看>>
linux 内核经典面试题
查看>>
ThinkPhp学习13
查看>>
小白学数据分析----->Excel制作INFOGRAPHIC
查看>>
Silverlight Telerik RadGridView动态增删行及行列操作(转载)
查看>>
Html.DropDownListFor练习(2)
查看>>
C++ Primer 学习笔记_75_模板与泛型编程 --模板定义
查看>>
SQL Server里Grouping Sets的威力
查看>>
Spring利用JDBCTemplate实现批量插入和返回id
查看>>
C# asp.net mvc 配置多个route 参数
查看>>
订单数字提醒的实现
查看>>
导出excel——入门
查看>>
设计模式(十)享元模式Flyweight(结构型)
查看>>
有图有真相!同是滑屏,荣耀Magic2不只比小米MIX3缝隙小,还更稳定
查看>>
AI+云 华为开启智能时代新纪元
查看>>
就是好骑!骑ofo小黄蜂和舒畅早晨say hi,跟闹心堵车say bye
查看>>