不到200行 JavaScript 代码实现富文本编辑器的方法

前段时间在寻找一些关于富文本编辑器的资料,然后发现了这个名为 Pell 的项目,它是一个所见即所得(WYSIWYG)的文本编辑器,虽然它的功能很简单,但是令人吃惊的是它只有 1kb 大小。而项目最核心的文件 pell.js 只有130行,即使加上其它部分,总的 js 数量也不到200行。这引起了我的兴趣,决定看看它的源码是如何做到这一点的。

项目的主要代码在 pell.js文件中,其结构很简单,主要功能的实现依赖于以下的几个部分

  • actions 对象
  • exec() 函数
  • init() 函数

Document.execCommand()

先从最简单的部分看起, exec() 函数只有下面三行:

export const exec = (command, value =null) => {
  document.execCommand(command, false, value);
};

它将 document.execCommand() 进行了一个简单的包装, Document.execCommand() 就是这个编辑器的核心,其语法如下

bool = document.execCommand(aCommandName, aShowDefaultUI, aValueArgument)
  • aCommandName 是表示想执行的命令的字符串,比如:加粗 ‘bold',创建链接 ‘createLink',改变字体大小 ‘fontSize' 等等
  • aShowDefaultUI 是否显示默认的用户界面
  • aValueArgument 有些命令需要额外的输入,如插入图片、链接时需要给出地址

注:经过我的试验,在 Chrome 下改变 aShowDefaultUI 的值并未发现影响, 这个stackoverflow 的问题 中提到这是一个来自于旧版 IE 的参数,所以这里设置为默认的 false 即可。

actions 对象

文件中定义了一个名为 actions 的对象,对应的是下图工具栏上的这一行按钮, actions 中的每个子对象都保存了一个按钮的属性。

部分代码:

const actions = {
  bold: {
    icon: '<b>B</b>',
    title: 'Bold',
    result: ()=> exec('bold')
  },
  italic: {
    icon: '<i>I</i>',
    title: 'Italic',
    result: ()=> exec('italic')
  },
  underline: {
    icon: '<u>U</u>',
    title: 'Underline',
    result: ()=> exec('underline')
  },
  // …
}

这段代码中显示了名为 bold , italic , underline 的三个对象属性,对应于工具栏中前方的 加粗 、 斜体 、下划线按钮,可以看出它们的结构是相同的,都有下列三个属性:

  • icon : 如何在工具栏中显示
  • title : 就是 title 啦
  • result : 一个函数,会赋给按钮作为点击事件,调用之前所提到的 exec() 函数来对文本进行操作

现在已有了 actions 对象,那么如何使用它呢?这就要看看 init() 函数了,它会根据一定的规则从 actions 对象中选出元素组成一个数组,数组的每一项都会生成一个按钮。下面代码中的 settings.actions 即为此数组,其中的每个元素都对应一个显示在工具栏上的按钮。 settings.actions 的生成规则会在后面进行解释。

// pell.js 中的 init() 函数
settings.actions.forEach(action=> {
  // 新建一个按钮元素
  const button = document.createElement('button')
  // 给按钮加上 css 样式
  button.className = settings.classes.button
  // 把 icon 属性作为内容显示出来
  button.innerHTML = action.icon
  button.title = action.title
  // 把 result 属性赋给按钮作为点击事件
  button.onclick = action.result
  // 将创建的按钮添加到工具栏上
  actionbar.appendChild(button)
})

这样数组中的每个元素就都生成了一个工具栏上的按钮了。

init() 初始化函数

想使用 pell 编辑器时,只要调用 init() 函数来初始化一个编辑器即可。它接收一个 setting 对象作为参数,其中包含这样的一些属性:

  • element : 编辑器的 DOM 元素
  • styleWithCSS : 设置为 true 时,将会用 <span style="font-weight: bold;"></span> 代替 <b></b>
  • actions
  • onChange

其中最重要的是 actions ,它是一个数组,包含了你想在工具栏显示的按钮列表。

actions 数组中可以有这几种元素:

  • 一个字符串
  • 一个有 name 属性的对象
  • 一个对象,没有 name 属性,但有生成一个按钮的必需属性 icon , result 等
actions: [
 'bold',
 'underline',
 'italic',
 {
  name: 'image',
  result: ()=> {
   const url = window.prompt('Enter the image URL')
   if (url) window.pell.exec('insertImage', ensureHTTP(url))
  }
 },
 // ...
]

在 init() 函数中会把这个 actions 参数 和 pell.js 中定义的 actions 对象组合起来,可以将 actions 对象当作一个默认设置,看以下代码:

// pell.js 中的 init() 函数
settings.actions = settings.actions
  ? settings.actions.map(action=> {
    if (typeof action === 'string') return actions[action]
    // 如果参数中传入的 action 已经在默认设置中存在,用传入的参数覆盖默认设置
    else if (actions[action.name]) {
      return { ...actions[action.name], ...action }
    }
    return action
  })
  : Object.keys(actions).map(action=> actions[action])

如果参数对象 setting 中不包含 actions 数组, 则会默认使用之前定义的 actions 对象来初始化。

init() 函数里还有一个重要的部分,就是创建一个可编辑区域,这里创建了一个 div 元素,将其 contentEditable 属性设为 true ,从而可以在这里使用之前提到的 document.execCommand() 命令了。

// 创建编辑区域的元素
settings.element.content = document.createElement('div')
// 让 div 成为可编辑状态
settings.element.content.contentEditable = true
settings.element.content.className = settings.classes.content
// 当用户输入时,更新页面的相应部分
settings.element.content.oninput = event=>
  settings.onChange(event.target.innerHTML)
settings.element.content.onkeydown = preventTab
settings.element.appendChild(settings.element.content)

流程整理

最后以“插入链接”为例来梳理下整个编辑器的流程:

一、在调用 init() 函数时,在参数对象的 action 数组中加入以下一项

{
  name: 'link',
  result: ()=> {
    const url = window.prompt('Enter the link URL')
    if (url) window.pell.exec('createLink', ensureHTTP(url))
  }
}

二、在 init() 的运行过程中,会检查已定义的 actions 对象中是否有 link 这个属性。经检查属性确实存在

link: {
  icon: '',
  title: 'Link',
  result: ()=> {
    const url = window.prompt('Enter the link URL')
    if (url) exec('createLink', url)
  }
}

因为传入的参数中有 result 这一项,所以用传入的 result 来代替 link 对象中的默认值,然后将修改过的 link 对象放入 settings.actions 数组中。

三、对 settings.actions 数组进行一次迭代来生成工具栏, link 对象作为其中的一项生成了一个“插入链接”的按钮。 result 属性成为其点击事件。

四、点击“插入链接”的按钮后,会让你输入一个 url,然后调用 exec('createLink', url) 在编辑区域插入该链接。

编辑器其它按钮的功能流程也类似。

这样 Pell 编辑器的大部分内容就讲解完毕了,剩余部分还需要自己去看源码。毕竟项目的代码不长,以此作为文本编辑器的入门倒不错。

总结

以上所述是小编给大家介绍的不到200行 JavaScript 代码实现富文本编辑器的方法,希望对大家有所帮助,如果大家有任何疑问请给我留言,小编会及时回复大家的。在此也非常感谢大家对我们网站的支持!

(0)

相关推荐

  • 学习js在线html(富文本,所见即所得)编辑器

    你要的是所见即所得HTML编辑器,简单来说需要几个基本步骤: 1,需要一个可以编辑同时又可显效果的编辑框.textarea不行,它只能用来输入纯文本,不能显示颜色.斜体之类的文字样式,就像记事本.你可以使用iframe来实现,修改iframe的designMode属性使其可以被编辑. 复制代码 代码如下: <iframe id="myEditer" width="100%" height="150px"></iframe>

  • Javascript实现简单的富文本编辑器附演示

    复制代码 代码如下: <span style="font-size:14px;"><!DOCTYPE html PUBLIC "-//W3C//DTD XHTML 1.0 Transitional//EN" "http://www.w3.org/TR/xhtml1/DTD/xhtml1-transitional.dtd"> <html xmlns="http://www.w3.org/1999/xhtml&

  • 19款Javascript富文本网页编辑器

    1. AIE (演示地址) AIE是一个开源的ajax图片编辑器,基于ExtJS与PHP ImageMagick开发,易于与博客/相册等其它应用相集成.提供调整图片大小,裁剪图片,旋转/翻转图片,应用滤镜,添加文本,添加水印等功能. 2. MarkitUp (演示地址) MarkitUp是一个轻量级,可定制,灵活的WYSIWYG Editor. 3. SmartMarkUP SmartMarkUP是一个轻量级,强大的JavaScript library,它能够将Textarea控件转换成富文本编

  • javascript开发随笔3 开发iframe富文本编辑器的一点体会

    就把遇到的问题记录一下.写这篇文章时用的TinyMCE编辑器就很强大,但毕竟是第三方的,项目也考虑了这些,如果做些自定义的东西不太方便. 1. 判断光标位置的元素(或者选中的部分)的样式.光标位置改变的时候更新工具栏对应按钮的样式.什么情况下光标的位置会改变呢?是键盘方向键和鼠标点击,于是就判断键盘事件和鼠标事件来执行光标移动的处理. a. 获得光标位置或选中元素:首先getSelection,创建range.然后获得元素,获取到元素之后就可以或得样式.tagName等等,做更多的操作,运行代码

  • nodejs后台集成ueditor富文本编辑器的实例

    UEditor是由百度web前端研发部开发所见即所得富文本web编辑器,具有轻量,可定制,注重用户体验等特点,开源基于MIT协议,允许自由使用和修改代码.. 1 下载ueditor nodejs版本 2 复制public目录下面的文件 到项目静态资源public文件夹下 3 在项目根目录创建ueditor文件夹 要复制进来的内容为 4 在根目录的 ueditor文件夹下执行 npm install 安装此目录下面package.json依赖的模块 5 项目根目录下创建 ue.js 代码部分来自于

  • Vue.js结合Ueditor富文本编辑器的实例代码

    在前端开发的项目中.难免会遇到需要在页面上集成一个富文本编辑器. 前一段时间公司Vue.js项目需要使用UEditor富文本编辑器,在百度上搜索一圈没有发现详细的说明,决定自己尝试,忙活了一天终于搞定了. 1. 总体思路 1.1 模块化 vue的很大的一个优势在于模块化,我们可以通过模块化实现页面和逻辑的复用.所以可以把Ueditor重新封装成一个.vue的模板文件.其他组件通过引入这个模板实现代码复用. 1.2 数据传输 首先父组件需要设置编辑器的长度.宽度.初始文本,这些数据可以通过prop

  • 不到200行 JavaScript 代码实现富文本编辑器的方法

    前段时间在寻找一些关于富文本编辑器的资料,然后发现了这个名为 Pell 的项目,它是一个所见即所得(WYSIWYG)的文本编辑器,虽然它的功能很简单,但是令人吃惊的是它只有 1kb 大小.而项目最核心的文件 pell.js 只有130行,即使加上其它部分,总的 js 数量也不到200行.这引起了我的兴趣,决定看看它的源码是如何做到这一点的. 项目的主要代码在 pell.js文件中,其结构很简单,主要功能的实现依赖于以下的几个部分 actions 对象 exec() 函数 init() 函数 Do

  • iOS实现富文本编辑器的方法详解

    前言 富文本编辑器不同于文本编辑器,国内做的比较好的比如有百度的UEditor和kindEditor.但是这两个也有它的缺点:界面过于复杂.不够简洁.UI设计也比较落后.不够轻量化,这篇文章我们将给大家介绍利用iOS如何实现富文本编辑器. 实现的效果 解决思路 采用webview加载一个本地html文件,该html内部编写好js方法用于与oc相互调用 最终输出该富文本字符串传输给服务器 为什么选择这样的方式 服务端要求我最终返回的数据格式为: { @"Id":"当时新建模板这

  • Vue2.0中集成UEditor富文本编辑器的方法

    在vue的'项目中遇到了需要使用富文本编辑器的需求,在github上看了很多vue封装的editor插件,很多对图片上传和视频上传的支持并不是很好,最终还是决定使用UEditor. 这类的文章网上有很多,我进行了摸索.手写代码.汇总.排版,形成了这篇文章. 下载对应的UEditor源码 首先,去官网上下载UEditor的源码,根据你后台语言的不同下载对应的版本(PHP.Asp..Net.Jsp). http://ueditor.baidu.com/website/download.html 下载

  • vue2.x集成百度UEditor富文本编辑器的方法

    最近开发vue项目过程中,由于产品需要在项目中添加富文本编辑器,也在npm上找了几个基于vue开发的富文本编辑器,但是对兼容性比较高,不能兼容到IE9,10.所以最后决定使用百度UEditor.然后又是各种找如何集成到vue中.好记性不如烂笔头,记录下来以便以后需要的时候可以直接用. 1.首先下载UEditor源码,将整个文件放到static文件夹中 2.然后将UEditor集成到项目中去. 找到src/main.js,在main.js中 import '../static/ueditor/ue

  • node使用UEditor富文本编辑器的方法实例

    大部分编辑器的后台是基于java.php.asp等,很少有基于node.js的.今天就做一个基于node的 最近在做一个微信素材编辑器的小项目,使用到了UEditor编辑器,使用中出现了许多问题. 1.介绍 UEditor是由百度web前端研发部开发所见即所得富文本web编辑器,具有轻量,可定制,注重用户体验等特点,开源基于MIT协议,允许自由使用和修改代码... 2.下载 下载地址 :http://www.jb51.net/codes/45434.html 选择开发版 ,因为我们使用node

  • PHP如何搭建百度Ueditor富文本编辑器

    本文为大家分享了PHP搭建百度Ueditor富文本编辑器的方法,供大家参考,具体内容如下 下载UEditor 官网:下载地址 将下载好的文件解压到thinkphp项目中,本文是解压到PUBLIC目录下并改文件夹名称为ueditor 第一步 引入javascript 在html中如入下面的js语句引入相关文件 <script type="text/javascript" charset="utf-8" src="__PUBLIC__/ueditor/u

  • ASP.NET网站使用Kindeditor富文本编辑器配置步骤

    1. 下载编辑器 下载 KindEditor 最新版本,下载页面: http://www.kindsoft.net/down.php 2. 部署编辑器 解压 kindeditor-x.x.x.zip 文件,将editor文件夹复制到web目录下  3.在网页中加入(ValidateRequest="false") 复制代码 代码如下: <%@ Page Language="C#" AutoEventWireup="true" Validat

  • 9行javascript代码获取QQ群成员具体实现

    昨天看到一条微博:「22 行 JavaScript 代码实现 QQ 群成员提取器」. 本着好奇心点击进去,发现没有达到效果,一是 QQ 版本升级了,二是博客里面的代码也有些繁琐. 于是自己试着写了一个,算上空行才 9 行,麻雀虽小,五脏俱全. 复制代码 代码如下: var ids = document.querySelectorAll(".member_id"); var names = document.querySelectorAll(".member_name"

  • 200行Java代码编写一个计算器程序

    发现了大学时候写的计算器小程序,还有个图形界面,能够图形化展示表达式语法树,哈哈;) 只有200行Java代码,不但能够计算加减乘除,还能够匹配小括号~ 代码点评: 从朴素的界面配色到简单易懂错误提示,无不体现了"用户体验"至上的设计理念:代码异常处理全面合理.滴水不漏,代码缩进优雅大方,变量命名直观易懂:再结合长度适中简单明了的注释,程序整体给人一种清新脱俗之感.背后不难看出作者对学习的热爱以及对设计的苛求,工匠精神可见一斑,真可谓是大学数据结构学以致用的典范! 实现代码如下所示:

  • 200行python代码实现2048游戏

    Python实战系列用于记录实战项目中的思路,代码实现,出现的问题与解决方案以及可行的改进方向 本文为第2篇–200行Python代码实现2048 一.分析与函数设计 1.1 游戏玩法 2048这款游戏的玩法很简单,每次可以选择上下左右滑动,每滑动一次,所有的数字方块都会往滑动的方向靠拢,系统也会在空白的地方乱数出现一个数字方块,相同数字的方块在靠拢.相撞时会相加.(介绍来自百度百科) 1.2 函数设计 _init _() 初始化4*4游戏地图,分数等游戏基本数据 is_gameover() 判

随机推荐