如何做一个高级的文本编辑器 textarea,拥有快捷键操作

最近想做一个高级点的 textarea ,支持 JetBrains 系列软件的快捷键,比如:

  • CTRL+ D 复制当前行。
  • Tab 在前面插入 4 个空格。
  • Shift + Tab 删除行前的空格,多于4个,一次性删除4个,小于四个,清除前面的空格。
  • CTRL+ ← 移动到行最左端
  • CTRL+ → 移动到行最右端

一步一步来,你需要知道一些关于 input textarea 的基础知识

一、重点: input textarea 基础知识

要想做好一个文本编辑器,就需要知道输入元素 input textarea 的基础知识,不是一般人都知道的知识。

  1. 获取 textarea 中光标的位置:textarea.selectionStartevent.target.selectionStart
  2. 设置 textarea 中的光标位置:textarea.setSelectionRange()

本文中的通用方法:

/*** 去除前面的空格* @param initSpaceCount 初始空格数* @param lineContent 行的内容* @returns {*}*/
removeSpaceBeforeLine(initSpaceCount, lineContent){  // 去除字符行中前面的空格let countSpace = initSpaceCountif (lineContent.substring(0,1) === ' '){countSpace  = countSpace + 1lineContent = lineContent.substring(1)return this.removeSpaceBeforeLine(countSpace, lineContent)} else {return {countSpace, lineContent}}
},getTextareaInfo(textarea, textContent){let cursorPosition = textarea.selectionStart // cursorPoslet cursorLineIndex = textContent.substring(0, cursorPosition).split('\n').length - 1 // 光标所在行let textLineArray = textContent.split('\n') // 原始文字 行数组let cursorLineContent = textLineArray[cursorLineIndex] // 光标所在行的内容return {cursorPosition,cursorLineIndex,textLineArray,cursorLineContent}
},

二、CTRL + D 复制当前行

如何实现

  1. 确定光标位置
  2. 获取光标所在行的内容
    1. 截取 0-光标位置 的字符串,substring
    2. substring.split('\n')
    3. 得到光标在第 n 行
    4. 切割整个文本,split('\n'),获得 splitLineArray
    5. 在获得的字符串数组中取到上面第 n 行的内容, newLineContent = splitLineArray[n]
  3. 在取得的内容行数组中,插入刚才那行的内容 splitLineArray.splice(n, 1, newLineContent )
  4. 生成最终字符串 splitLineArray.join('\n')
  5. 定位光标到原来的光标位置


代码

  // CTRL + D 复选行
if ((event.ctrlKey || event.metaKey) && event.key === 'd') {event.preventDefault()let textarea = this.$refs.textarea // domlet textAreaInfo = this.getTextareaInfo(textarea, this.diary.content)textAreaInfo.textLineArray.splice(textAreaInfo.cursorLineIndex, 0, textAreaInfo.cursorLineContent)this.diary.content = textAreaInfo.textLineArray.join('\n')this.$nextTick(_=>{textarea.setSelectionRange(textAreaInfo.cursorPosition, textAreaInfo.cursorPosition) // 定位光标})
}

三、tab 在光标后面插入 4 个空格

如何实现

  1. 得到 textarea 中光标的位置 index
  2. 字符串根据 index 位置切割成前后两块。
  3. 最终结果:前半部分 + 4个空格 + 后半部分
  4. 把光标移动到 index + 4 的位置

四、shift + tab 删除行内前面的空格

如何实现

  1. 获取光标位置 index
  2. 获取光标所在行的内容
  3. 判断行内容前面的空格,如果前四个字符 === 4个空格,就 substring(4)
  4. 如果不是,就判断第一个字符是否为空格
    1. 如果是 就 substring(1),去除第一个空格,记录已去除的空格数量,+1 ,接着执行 第4步,此处为递归。
    2. 如果不是说明已经没有空格可删了,就返回最终结果。
  5. 移动光标到 -4-spaceCount 的位置


代码

 // shift + tab
if (event.shiftKey && event.key === 'Tab'){event.preventDefault()let textarea = this.$refs.textarea // domlet textAreaInfo = this.getTextareaInfo(textarea, this.diary.content)let tempLine = textAreaInfo.cursorLineContentlet deleteSpaceCount = 0if (tempLine.substring(0,4) === '    '){tempLine = tempLine.substring(4)deleteSpaceCount = 4} else {let trimSpaceResult = this.removeSpaceBeforeLine(0, tempLine)tempLine = trimSpaceResult.lineContentdeleteSpaceCount = trimSpaceResult.countSpace}textAreaInfo.textLineArray.splice(textAreaInfo.cursorLineIndex,1, tempLine)this.diary.content = textAreaInfo.textLineArray.join('\n')this.$nextTick(_=>{textarea.setSelectionRange(textAreaInfo.cursorPosition - deleteSpaceCount, textAreaInfo.cursorPosition - deleteSpaceCount)})} else if (event.key === 'Tab'){// tabevent.preventDefault()let textarea = this.$refs.textarea // domlet textAreaInfo = this.getTextareaInfo(textarea, this.diary.content)let contentBeforeCursor = this.diary.content.substring(0,textAreaInfo.cursorPosition)let contentAfterCursor = this.diary.content.substring(textAreaInfo.cursorPosition)this.diary.content = contentBeforeCursor + '    ' + contentAfterCursorthis.$nextTick(_=>{textarea.setSelectionRange(textAreaInfo.cursorPosition + 4, textAreaInfo.cursorPosition + 4)})}

五、CTRL+ ← 移动到行最左端,CTRL+ → 移动到行最右端

1. CTRL+ ← 移动到行最左端 如何实现

  1. 获取光标位置
  2. 获取光标位置行的行号 lineIndex
  3. 截取 lineIndex 之前的行数组
  4. join('\n') 前面的数组,取到前面内容的 index + 1
  5. 就是 ctrl + ← 的位置,设置光标到这个位置即可

2. CTRL+ → 移动到行最右端 如何实现

  1. 获取光标位置
  2. 获取光标位置行的行号 lineIndex
  3. 截取 lineIndex + 1 之前的行数组
  4. join('\n') 前面的数组,取到前面内容的 index
  5. 就是 ctrl + → 的位置,设置光标到这个位置即可


代码:

 // CTRL + ArrowLeft 移到最左端
if ((event.ctrlKey || event.metaKey) && event.key === 'ArrowLeft') {event.preventDefault()let textarea = this.$refs.textarea // domlet textAreaInfo = this.getTextareaInfo(textarea, this.diary.content)let linesBefore = textAreaInfo.textLineArray.slice(0, textAreaInfo.cursorLineIndex)let textBefore = linesBefore.join('\n')let newCursorLocation = textBefore.length + 1  // -1行末尾 + 1this.$nextTick(_=>{textarea.setSelectionRange(newCursorLocation, newCursorLocation)})
}// CTRL + ArrowRight 移到最右端
if ((event.ctrlKey || event.metaKey) && event.key === 'ArrowRight') {event.preventDefault()let textarea = this.$refs.textarea // domlet textAreaInfo = this.getTextareaInfo(textarea, this.diary.content)let linesBefore = textAreaInfo.textLineArray.slice(0, textAreaInfo.cursorLineIndex + 1)let textBefore = linesBefore.join('\n')let newCursorLocation = textBefore.lengththis.$nextTick(_=>{textarea.setSelectionRange(newCursorLocation, newCursorLocation) // 定位光标})
}

如何做一个高级的文本编辑器 textarea,拥有快捷键操作相关推荐

  1. 用Python做一个简陋的文本编辑器

    Hello,大家好,我是Gary! 想必大家都用过Windows系统自带的"记事本"应用吧?它是一个编辑txt文件的应用. 当然,咱们可不能只局限于记事本,咱们也可以自己做一个! ...

  2. C++程序设计:原理与实践(进阶篇)15.6 实例:一个简单的文本编辑器

    15.6 实例:一个简单的文本编辑器 列表最重要的性质就是可以在不移动元素的情况下对其进行插入或删除操作.下面我们通过一个例子来说明这一点.考虑应该如何在文本编辑器中表示一个文本文件中的字符.所选用的 ...

  3. Java实现一个简单的文本编辑器(简易版)

    (用Java做了一个简单的文本编辑器,其中看了很多博主的教学和代码,在这里感谢:@Mark7758.@Kingsly_Liang.@佐敦不下雨.再次感谢!) 1.功能说明: 文件菜单:打开.保存.新建 ...

  4. python源码编译 带tkinter_python通过Tkinter库实现的一个简单的文本编辑器源码

    下边资料是关于python通过Tkinter库实现的一个简单的文本编辑器的内容. from tkSimpleDialog import askstring from tkFileDialog impo ...

  5. python通过Tkinter库实现的一个简单的文本编辑器源码

    下边资料是关于python通过Tkinter库实现的一个简单的文本编辑器的内容. from tkSimpleDialog import askstring from tkFileDialog impo ...

  6. 【Qt5开发及实例】16、实现一个简单的文本编辑器(over)

    实现一个简单的文本编辑器 其他具体的代码基础看前面:http://blog.csdn.net/cutter_point/article/details/42839071 1.功能 这个程序又添加了文本 ...

  7. 微信小程序之使用Vant Weapp做一个弹窗填写文本

    在小程序中,我们经常使用到输入文本框这个组件.比如要填写个人信息,填信息就要去跳转到一个填信息的页面,这样操作起来会有点浪费空间和时间.比如我只需要改一个自己的名字或者一点别的信息就要跳转到另外一个页 ...

  8. Visual Studio 文本编辑器水平滚动条快捷键

    Visual Studio 文本编辑器水平滚动条快捷键 一时上头,观摩前辈代码时老是要手动拖动水平滚动条.百度半天,自己瞎折腾,想设置快捷键里设置个跟WPS类似的水平滚动条拖动的快捷键(WPS里Alt ...

  9. Win7下安装一个装逼文本编辑器Atom + activate-power-mode插件

    Atom是Github推出的一个文本编辑器,搜索一下大概是给Web前端用的,最近比较火的是他的一个插件activate-power-mode,可以实现打字屏振效果. 用来装装逼还是挺适合的,本来想试试 ...

最新文章

  1. 【南科大发言】人类赋予人工智能伦理,生物进化方向的突破是关键
  2. android开发超级群(500人)
  3. [导入]Vista的屏幕截图小工具:Snipping Tool
  4. Eclipse/MyEclipse安装FindBugs
  5. MySQL数据库中如何使用rand随机查询记录
  6. DAOSquare将于今晚9点-12点进行两轮ITO
  7. java中web错误返回码,Java-Web3j Transfer.sendFunds()返回错误“天然气...
  8. linux定时任务Crond之服务器同步时间05
  9. HTML资源嗅探,scrapy-2 嗅探网站,解析HTML
  10. 局域网 访问计算机 软件,局域网共享软件
  11. 简单C语言小程序:求根公式求一元二次方程式的根!
  12. Redis学习(三) - Redis客户端对比及配置(SpringBoot)
  13. PS 常用的形状工具
  14. 76----平面二次曲线的分类: 消去二次交叉项
  15. AirTest Poco定位 和启动方式
  16. VS2015 + QT 编译出现public: virtual struct QMetaObject const * __thiscall 错误
  17. 51单片机 | 并行I/O口扩展实例(74LS244/74LS373/4071)
  18. 计算机视觉——DoG和LoG算子
  19. Matlab求解阶跃响应性能指标 (上升时间、调整时间、峰值时间、超调量)
  20. 从单机架构------》到现在复杂的微服务,分布式,集群,云平台途中是遇到了什么问题,又如何解决的?

热门文章

  1. 使用Kali上的Metasploit获取ssh登录到靶机权限
  2. 无为才能够无不为-曾仕强
  3. 如何批量输出条形码图片
  4. jQuery实现五星好评
  5. 一套打通 Github 搜索语法
  6. 易语言教程数据库替换
  7. 【重磅推荐】基于truffle-contract库实现的以太坊solidity合约调用案例(注:web3.js切勿和truffle-contract库同时使用,否则报错,无法修复!)
  8. LED 控制技术将日间行车灯的优势发挥到极致
  9. IE8和IE7下js的兼容性问题
  10. 【Sublime Text 3】Sublime Text 3 - cracked 3086