查看源码第一行有空格

最后更新于:2022-04-01 23:43:51

如果你在编辑器内容之后,查看源码时候,发现源码的第一行有空格或者空行(如下图),如何处理呢? ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-05-04_572a07c1cb5cf.png) 修改方法比较简单,你需要将生成编辑器的`div`由下面这样 ```html

请输入内容...

``` 改成下面这样即可 ```html

请输入内容...

``` 修改之后,再查看源码,就是下图这样了: ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-05-04_572a07c1e1288.png)
';

关于mobile端编辑器

最后更新于:2022-04-01 23:43:49

wangEditor除了常用的PC端编辑器之外,还有一款mobile编辑器 http://wangeditor.github.io/m/ --- **不过在此做一个移动端编辑器的说明,请一定注意!** 第一,由于作者本人业余精力有限,mobile端编辑器好久没有维护了,有使用者反馈过很多问题,暂时也没有精力维护。 第二,mobild端编辑器在Android手机上使用有各种各样的兼容性问题,这也是目前还没有解决的问题。 第三,目前编辑器的使用者中,绝大部分用户都是需要PC端的,极少用户需要mobile端的。用户数量少,优先级就会降低。 第四,目前网络上没有任何一款易用性较好的、纯`javascript`开发的编辑器,作者也不清楚该如何做出一个好的设计。目前比较好的mobile端编辑器的设计(例如有道云笔记app、ios的备忘录)都是需要app程序来支持的,不是纯`javascript`写的。 因此,综合以上因此,作者短期之内不会花费很大精力去维护mobile端的编辑器。 --- **因此这里作者建议,如果你想用该mobile端编辑器做一个实验、demo之类的非正规运营产品,即可使用和交流。如果你想在正规产品中使用,那还得再等等,目前mobile端编辑器问题还比较多。**
';

如何插入视频链接

最后更新于:2022-04-01 23:43:47

您可以把优酷、爱奇艺、腾讯视频等网站的视频插入到wangEditor编辑器中,**支持手机观看**。您只需要从视频网站复制一段代码,粘贴到编辑器的输入框中即可。如下图: ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-02_56ffa8ec62ecb.png) 那么各个网站如何复制代码呢,请看下面: --- **优酷**的复制方法如下图: ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-02_56ffa8ec89c6c.png) --- **爱奇艺**的复制方法如下图: ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-02_56ffa8ecc600f.png) --- **腾讯视频**的复制方法如下图: ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-04-02_56ffa8ecf3532.png) --- **注意:如果您在以上三个网站中没有找到图示的代码,就说明您所观看的视频,还不支持移动端观看。此时您可以复制其中的`html代码`(即 ` ';

xss过滤

最后更新于:2022-04-01 23:43:44

富文本编辑器是黑客进行`xss`攻击的一个重要入口,因此不得不引起重视。本文就给出一个wangEditor编辑器在前端进行`xss`过滤的解决方案。 ---- 首先,编辑器本身将默认过滤在编辑源码模式下,用户输入的` ';

如何避免与项目中的css冲突

最后更新于:2022-04-01 23:43:42

有使用者在使用过程中反应编辑器的css和项目中的css会有冲突,导致编辑器的样式被覆盖而显示异常。这里说一个解决样式冲突的方法,不过需要使用者手动调整一下代码。 --- **需要下载`v2.0.18.1`或者以后的版本** 首先,你需要改动一下你的`html`文件,在编辑器的外面包一层有`id`的父容器,如下: ```html

请输入内容...

``` 然后,在下载的代码中找到`dist`目录的`wangEditor.less`文件,打开,在该文件的最上方和最下方加上如下代码: ```css /* 在 wangEditor.less 文件的最上方加上下一行代码 */ #editor-container { /* 此处是 wangEditor.less 原有的代码 */ .... /* 在 wangEditor.less 文件的最下方加上下一行代码 */ } ``` 保存,然后将这个`less`文件重新编译为`css`,然后引入到页面中就行了。 **PS:不了解如何将`less`编译为`css`的同学,其实方法很简单。百度搜索『less在线编译』就有会很多在线的工具可一键编译,使用很方便** ---- 最后,如果上一步操作还是不能解决冲突,那你就在编辑器`editor-container`便签外面再加一层带`id`的父容器,然后将该`id`再写入`less`文件中,用两个`id`做选择器。还不行,再加。 不过一般情况下,只加上述的第一个父容器就可解决问题。
';

集成到vue.js

最后更新于:2022-04-01 23:43:40

如果你想在`vue.js`的项目中使用`wangEditor`,以下有一个简单的demo,以及一个`vue`组件应用的demo。 ----- **第一,简单demo** 代码如下,也可参见 https://github.com/wangfupeng1988/wangEditor/blob/master/test/vue/test-vue.html 的代码。 ```html editor test

wangEditor width vuejs


以下是编辑器的内容:

{{ editorContent }}

``` --- **第二,vue组件demo** 具体请参见:https://github.com/jiangyoucai/vueComponents ,该demo由 [@jiangyoucai](https://github.com/jiangyoucai) 同学贡献,在此感谢!
';

集成到angular

最后更新于:2022-04-01 23:43:38

如果你想在`angular.js`的项目中使用`wangEditor`,以下是一个集成示例。也可参见 https://github.com/wangfupeng1988/wangEditor/blob/master/test/angular/test-angular.html 的代码。 ```html angular test

wangEditor 集成到 angular 的示例


以下是编辑器的内容:

```
';

集成到React

最后更新于:2022-04-01 23:43:35

目前`React`在前端开发中,正是如日中天的火。想要在`React`中使用wangEditor编辑器,下面给一个简单的demo供参考。具体在项目中如何使用,需要根据情况具体分析,有问题可以在QQ群交流或者提交issue到github。 注意:如果你此时使用了其他包管理工具,例如`seajs` `require.js`或者`webpack`,请参考:http://www.kancloud.cn/wangfupeng/wangeditor2/113994 demo代码如下: ```html test1
```
';

关于显示压缩图片

最后更新于:2022-04-01 23:43:33

**问题:** 手机端图片压缩问题 我有个问题, 我的网站文章里面有图片, 我的网站主要是在手机端访问, 我希望手机端看到的是一个压缩图片, 点击之后就出现一个原始图片, 用wangEditor怎么弄? ----- **回答:** 根据编辑器的文档的要求,上传图片,服务器端要返回得到的图片的url地址,例如:`http://www.abc.com/imgs/123.png` 如果你要实现像你说的,得到的是一个压缩图片,点击之后再显示正常图片,那好办!**(压缩图片的工作一定是在你的服务器端做的,否则下面的免谈)** 例如,你上传图片之后,得到的原始图片地址为 `http://www.abc.com/imgs/123.png`,得到的压缩图片地址为`http://www.abc.com/imgs/456.png`,那么这时你可以返回 `http://www.abc.com/imgs/456.png#http://www.abc.com/imgs/123.png`(中间的`#`一定要有) 你返回了这个,前端得到这个url,显示的图片肯定是`456.png`,即压缩图片。这样就实现了你的第一步了。 下一步需要你自己来写js程序实现。 点击这个压缩图片的时候,你可以得到图片的`src`,然后用`#`分割,你就可以得到原始图片的url,即`http://www.abc.com/imgs/123.png`,现在原始图片url都得到了,具体如何显示,不就简单了吗?
';

关于背景图片

最后更新于:2022-04-01 23:43:31

有几位使用者提到在编辑其中增加背景图片的功能,经过思考和参考其他成熟产品,觉得背景图片并不适合在编辑器中直接集成。 编辑器本身要保证编辑出来的内容的纯粹行,能在编辑器外面控制的东西,尽量在外面控制,例如上传附件(上面的章节提到过这个问题)。从设计原则和设计模式上,也提倡这种单一职责和开放封闭,这样才能保证系统的可扩展性。 ----- 实现背景图片,你完全可以参考QQ邮箱的『信纸』功能。如下图: ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-02-28_56d26e28e647e.png) 编辑器内容使用编辑器单独控制,而信纸在右侧单独控制。当保存内容时,富文本内容单独保存,信纸的图片地址也单独保存。显示内容时,用一个容器包含富文本,然后在容器上单独加上保存的信纸图片(作为背景图片)即可。 这是大体的过程。 ---- 还剩下一个问题,就是在编辑内容时,选择了信纸,如何立即让信纸作为背景图片成现在编辑区域?这个其实很简单: ```js // 选择了信纸之后,执行以下语句 editor.$txt.css('background-img', 'url(./bgimg/a.png)'); ``` 至于其他的`background`样式,自己在以上语句中自由控制即可。 但是注意:以上语句为`editor.$txt`设置了背景图片,是不会作为编辑器内容被获取的,信纸还得单独保存。
';

关于上传附件

最后更新于:2022-04-01 23:43:29

**有用户问到编辑器能否有上传附件的功能?我的建议是不要把附件做到内容中。** 原因很简单,如果将附件上传之后再插入到富文本内容中,其实就是一个链接的形式。如下图: ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-02-19_56c718ec6f9bf.png) 而用户在用编辑器编辑文本时,操作是非常随意多样的,他把这个链接删了,你服务器要想实时删除上传的附件文件,是难监控到的。 还有,用户如果要上传很多个附件,也是很难管理的,还是因为富文本的内容变化多样,用户可以随便在什么地方插入附件,而且形式和链接一样。 ------ 反过来,我们想一下平时用附件和编辑器最多的产品是什么——是邮箱。邮箱如何处理附件的,大家应该很清楚。它把文本内容和附件分开,这样附件就可以很轻松、明了的进行管理,绝对不会和编辑内容的链接产生混淆。 ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-02-19_56c718ec83f7e.png) 你能看到的所有的邮箱产品,几乎都是这样设计的。 ---- 因此,在你提问编辑器能否上传附件这个问题的时候,可以想一下能否参照邮箱的实现来设计?
';

关于markdown

最后更新于:2022-04-01 23:43:26

**好多使用者问到,wangEditor编辑器能否集成`markdown`?——答案是:富文本编辑器无法和`markdown`集成到一起。** ---- 先不说为什么,咱们先看看一个成熟产品中,对于富文本和`markdown`是如何处理的。 [简书](http://www.jianshu.com/) 是现在很火的一个博客网站,听人说它之所以快速的火起来,和支持`markdown`还有很大的关系。那么咱们看看这位靠着`markdown`火起来的网站,是不是真正的富文本和`markdown`集成起来了? 其实它的`markdown`编辑器和富文本编辑器完全是两个东西,根本没有在一个页面中集成起来。而切换富文本和`markdown`是在用户配置页来切换的。 默认进来是富文本编辑器,如下图: ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-02-19_56c70b5087195.png) 可以进入用户配置页面切换成`markdown`编辑器,如下图: ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-02-19_56c70b509b9a2.png) 再回头来新建一片文章,编辑器就切换到`markdown`了。 ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-02-19_56c70b50a924e.png) 看明白了吧? ---- 下面说说从技术角度为什么难以实现这两者的切换。 简单讲来,富文本和`markdown`对于文字的处理完全是两码事儿。例如,我们选择`abcd`进行加粗,富文本会生成`abcd`,而`markdown`会生成`**abcd**`。 如果想要两者自由切换,需要在切换时,随时切换两种规则,这就会带来很多问题。 第一,如果文字量大,要处理的信息多,单纯用js进行进算,性能是一个问题。 第二,`**abcd**`格式切换成`abcd`格式,有现成的js库可利用,但是`abcd`切换为`**abcd**`怎么办?`markdown`只能编辑常用格式的文字,没有`html`的样式那么强大。例如,``或`abc`切换成为`markdown`就无法实现。 **所以,目前还找不到一款编辑器能自由切换`markdown`和富文本。一个东西不存在,也是有不存在的道理的。** ---- 最后,请大家想明白,在你的产品中,到底是想要一个"理想主义"的自由切换,还是想要简书那样的两种形式。 想清楚。
';

常见问题

最后更新于:2022-04-01 23:43:24

';

开发一个插件

最后更新于:2022-04-01 23:43:22

####注意 **开发插件过程中,会用到编辑器提供的API,也需要了解编辑器的对象结构。这些请参见『插件开发 - 对象结构』、『插件开发 - 常用API - 全局API』、『插件开发 - 常用API - 对象API』** ------ ####如何引用到页面 将插件代码写到一个独立的js文件中,例如命名为`plugin.js`,编写完成后,要这样引用到页面中。 ```html

请输入内容...

``` ---- ####编写 `plugin.js` 做一个demo 在`plugin.js`中编写代码,做一个demo:点击编辑区域的图片时,弹出该图片的`url`。代码如下: ```js (function () { // 获取 wangEditor 构造函数和 jquery var E = window.wangEditor; var $ = window.jQuery; // 通过 E.plugin 注入插件代码 E.plugin(function () { // 此处的 this 指向 editor 对象本身 var editor = this; var $txt = editor.$txt; $txt.on('click', 'img', function (e) { var $img = $(e.currentTarget); alert($img.attr('src')); }); }); })(); ``` ----------- ####实际案例 wangEditor编辑器本身的许多功能都是使用插件机制开发的,例如图片、表格的toolbar ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-02-05_56b460d9da677.png) 这个插件的代码,可以在`wangEditor.js`中搜索 `// 编辑器区域 table toolbar` 来找到源码。 目前该插件的源码如下(**以搜索到的源码为准**) ```js // 编辑器区域 table toolbar (function () { // 获取 wangEditor 构造函数和 jquery var E = window.wangEditor; var $ = window.jQuery; E.plugin(function () { var editor = this; var txt = editor.txt; var $txt = txt.$txt; var $currentTable; // 用到的dom节点 var isRendered = false; var $toolbar = $('
'); var $triangle = $('
'); var $delete = $(''); var $zoomSmall = $(''); var $zoomBig = $(''); // 渲染到页面 function render() { if (isRendered) { return; } // 绑定事件 bindEvent(); // 拼接 渲染到页面上 $toolbar.append($triangle) .append($delete) .append($zoomSmall) .append($zoomBig); editor.$editorContainer.append($toolbar); isRendered = true; } // 绑定事件 function bindEvent() { // 统一执行命令的方法 var commandFn; function command(e, callback) { if (commandFn) { editor.customCommand(e, commandFn, callback); } } // 删除 $delete.click(function (e) { commandFn = function () { $currentTable.remove(); }; command(e, function () { setTimeout(hide, 100); }); }); // 放大 $zoomBig.click(function (e) { commandFn = function () { $currentTable.css({ width: '100%' }); }; command(e, function () { setTimeout(show); }); }); // 缩小 $zoomSmall.click(function (e) { commandFn = function () { $currentTable.css({ width: 'auto' }); }; command(e, function () { setTimeout(show); }); }); } // 显示 toolbar function show() { if ($currentTable == null) { return; } $currentTable.addClass('clicked'); var tablePosition = $currentTable.position(); var tableTop = tablePosition.top; var tableLeft = tablePosition.left; var tableHeight = $currentTable.outerHeight(); var tableWidth = $currentTable.outerWidth(); // --- 定位 toolbar --- // 计算初步结果 var top = tableTop + tableHeight; var left = tableLeft; var marginLeft = 0; var txtTop = $txt.position().top; var txtHeight = $txt.outerHeight(); if (top > (txtTop + txtHeight)) { // top 不得超出编辑范围 top = txtTop + txtHeight; } // 显示(方便计算 margin) $toolbar.show(); // 计算 margin var width = $toolbar.outerWidth(); marginLeft = tableWidth / 2 - width / 2; // 定位 $toolbar.css({ top: top + 5, left: left, 'margin-left': marginLeft }); } // 隐藏 toolbar function hide() { if ($currentTable == null) { return; } $currentTable.removeClass('clicked'); $currentTable = null; $toolbar.hide(); } // click table 事件 $txt.on('click', 'table', function (e) { var $table = $(e.currentTarget); // 渲染 render(); if ($currentTable && ($currentTable.get(0) === $table.get(0))) { setTimeout(hide, 100); return; } // 显示 toolbar $currentTable = $table; show(); // 阻止冒泡 e.preventDefault(); e.stopPropagation(); }).on('click keypress scroll', function (e) { setTimeout(hide, 100); }); E.$body.on('click keypress scroll', function (e) { setTimeout(hide, 100); }); }); })(); ```
';

『插入符号』菜单

最后更新于:2022-04-01 23:43:20

####前言 - 『插入符号』菜单是一个dropPanel类型的菜单,因为点击它要弹出一个面板Panel,然后再进行其他操作。 - 『插入符号』菜单的扩展过程和『缩进』菜单一样,除了`custom-menu.js`的内容不一样。**所以请先阅读上一节『缩进』菜单的创建过程。** - 因此,本节直接略过其他过程,直接分析`custom-menu.js`文件源码。 ----- ####编写 `custom-menu.js` 直接贴出`custom-menu.js`的源码,里面有非常详细的注释。 ```js (function () { // 获取 wangEditor 构造函数和 jquery var E = window.wangEditor; var $ = window.jQuery; // 用 createMenu 方法创建菜单 E.createMenu(function (check) { // 定义菜单id,不要和其他菜单id重复。编辑器自带的所有菜单id,可通过『参数配置-自定义菜单』一节查看 var menuId = 'symbol'; // check将检查菜单配置(『参数配置-自定义菜单』一节描述)中是否该菜单id,如果没有,则忽略下面的代码。 if (!check(menuId)) { return; } // this 指向 editor 对象自身 var editor = this; // 创建 menu 对象 var menu = new E.Menu({ editor: editor, // 编辑器对象 id: menuId, // 菜单id title: '符号', // 菜单标题 // 正常状态和选中装下的dom对象,样式需要自定义 $domNormal: $(''), $domSelected: $('') }); // 要插入的符号(可自行添加) var symbols = ['∑', '√', '∫', '∏', '≠', '♂', '♀'] // panel 内容 var $container = $('
'); $.each(symbols, function (k, value) { $container.append('' + value + ''); }); // 插入符号的事件 $container.on('click', 'a', function (e) { var $a = $(e.currentTarget); var s = $a.text(); // 执行插入的命令 editor.command(e, 'insertHtml', s); }); // 添加panel menu.dropPanel = new E.DropPanel(editor, menu, { $content: $container, width: 350 }); // 增加到editor对象中 editor.menus[menuId] = menu; }); })(); ``` ####效果 运行页面的效果如下 ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-02-05_56b460d9cc196.png)
';

『行高』菜单

最后更新于:2022-04-01 23:43:17

####前言 - 『行高』菜单是一个dropList类型的菜单,因为点击它要弹出一个下拉列表,然后再选择操作。 - 『行高』菜单的扩展过程和『缩进』菜单一样,除了`custom-menu.js`的内容不一样。**所以请先阅读上一节『缩进』菜单的创建过程。** - 因此,本节直接略过其他过程,直接分析`custom-menu.js`文件源码。 ----- ####编写 `custom-menu.js` 直接贴出`custom-menu.js`的源码,里面有非常详细的注释。 ```js (function () { // 获取 wangEditor 构造函数和 jquery var E = window.wangEditor; var $ = window.jQuery; // 用 createMenu 方法创建菜单 E.createMenu(function (check) { // 定义菜单id,不要和其他菜单id重复。编辑器自带的所有菜单id,可通过『参数配置-自定义菜单』一节查看 var menuId = 'lineheight'; // check将检查菜单配置(『参数配置-自定义菜单』一节描述)中是否该菜单id,如果没有,则忽略下面的代码。 if (!check(menuId)) { return; } // this 指向 editor 对象自身 var editor = this; // 由于浏览器自身不支持 lineHeight 命令,因此要做一个hook editor.commandHooks.lineHeight = function (value) { var rangeElem = editor.getRangeElem(); var targetElem = editor.getSelfOrParentByName(rangeElem, 'p,h1,h2,h3,h4,h5,pre'); if (!targetElem) { return; } $(targetElem).css('line-height', value + ''); }; // 创建 menu 对象 var menu = new E.Menu({ editor: editor, // 编辑器对象 id: menuId, // 菜单id title: '行高', // 菜单标题 commandName: 'lineHeight', // 命令名称 // 正常状态和选中装下的dom对象,样式需要自定义 $domNormal: $(''), $domSelected: $('') }); // 数据源 var data = { // 格式: 'value' : 'title' '1.0': '1.0倍', '1.5': '1.5倍', '1.8': '1.8倍', '2.0': '2.0倍', '2.5': '2.5倍', '3.0': '3.0倍' }; // 为menu创建droplist对象 var tpl = '{#title}'; menu.dropList = new E.DropList(editor, menu, { data: data, // 传入数据源 tpl: tpl // 传入模板 }); // 增加到editor对象中 editor.menus[menuId] = menu; }); })(); ``` ----- ####效果 运行页面的效果如下: ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-02-05_56b460d9ba82a.png)
';

『缩进』菜单

最后更新于:2022-04-01 23:43:15

####前言 - 把扩展菜单的`js`文件写在一个独立的文件中,命名为`custom-menu.js`,这个文件最终要引用到页面中。 - **将要扩展的『缩进』菜单的id命名为 `indent`** 。菜单id不能已有的菜单的id重复,现有菜单的id,可参见『参数配置 - 自定义菜单』 ------- ####页面 假设现在`custom-menu.js`已经编写完成(下文将描述该文件如何编写),要引用到页面中。而且页面中还有对`editor.config.menus`配置以显示刚刚扩展的菜单,详情可参见『参数配置 - 自定义菜单』。例如: ```html

请输入内容...

``` ---- ####编写 `custom-menu.js` 可直接查看源代码,里面有详细的注释描述 ```js (function () { // 获取 wangEditor 构造函数和 jquery var E = window.wangEditor; var $ = window.jQuery; // 用 createMenu 方法创建菜单 E.createMenu(function (check) { // 定义菜单id,不要和其他菜单id重复。编辑器自带的所有菜单id,可通过『参数配置-自定义菜单』一节查看 var menuId = 'indent'; // check将检查菜单配置(『参数配置-自定义菜单』一节描述)中是否该菜单id,如果没有,则忽略下面的代码。 if (!check(menuId)) { return; } // this 指向 editor 对象自身 var editor = this; // 创建 menu 对象 var menu = new E.Menu({ editor: editor, // 编辑器对象 id: menuId, // 菜单id title: '缩进', // 菜单标题 // 正常状态和选中状态下的dom对象,样式需要自定义 $domNormal: $(''), $domSelected: $('') }); // 菜单正常状态下,点击将触发该事件 menu.clickEvent = function (e) { // 找到当前选区所在的 p 元素 var elem = editor.getRangeElem(); var p = editor.getSelfOrParentByName(elem, 'p'); var $p; if (!p) { // 未找到 p 元素,则忽略 return e.preventDefault(); } $p = $(p); // 使用自定义命令 function commandFn() { $p.css('text-indent', '2em'); } editor.customCommand(e, commandFn); }; // 菜单选中状态下,点击将触发该事件 menu.clickEventSelected = function (e) { // 找到当前选区所在的 p 元素 var elem = editor.getRangeElem(); var p = editor.getSelfOrParentByName(elem, 'p'); var $p; if (!p) { // 未找到 p 元素,则忽略 return e.preventDefault(); } $p = $(p); // 使用自定义命令 function commandFn() { $p.css('text-indent', '0'); } editor.customCommand(e, commandFn); }; // 根据当前选区,自定义更新菜单的选中状态或者正常状态 menu.updateSelectedEvent = function () { // 获取当前选区所在的父元素 var elem = editor.getRangeElem(); var p = editor.getSelfOrParentByName(elem, 'p'); var $p; var indent; if (!p) { // 未找到 p 元素,则标记为未处于选中状态 return false; } $p = $(p); indent = $p.css('text-indent'); if (!indent || indent === '0px') { // 得到的p,text-indent 属性是 0,则标记为未处于选中状态 return false; } // 找到 p 元素,并且 text-indent 不是 0,则标记为选中状态 return true; }; // 增加到editor对象中 editor.menus[menuId] = menu; }); })(); ``` ---- #### 最终效果 最终运行页面的效果如下: ![](https://docs.gechiui.com/gc-content/uploads/sites/kancloud/2016-02-05_56b460d9ab2fc.png)
';

扩展一个菜单

最后更新于:2022-04-01 23:43:13

目前 wangEditor 编辑器的菜单有三种类型: - 基本命令类型,例如『粗体』、『斜体』、『引用』 - dropList 类型,例如『字体』、『标题』 - dropPanel 类型,例如『插入链接』、『插入图片』、『地图』等 下面通过扩展『缩进』、『行高』、『插入符号』三个示例来演示如果扩展不同类型的菜单。 ---- **扩展菜单过程中,会用到编辑器提供的API,也需要了解编辑器的对象结构。这些请参见『插件开发 - 对象结构』、『插件开发 - 常用API - 全局API』、『插件开发 - 常用API - 对象API』**
';

命令API

最后更新于:2022-04-01 23:43:11

####命令API 以下是编辑器命令操作相关的API,**使用以下API,最好先要了解浏览器的`document.execCommand`的相关知识** ----- - **`editor.command`** 对`document.execCommand`执行浏览器基础命令的封装。在二次开发中,如果遇到这种情况,尽量用分装好的`edtior.command`。例如: ```js $('#btn').click(function (e) { // 注意,下面的 e 参数尽量要传,否则可能导致其他问题 // 等同于 document.execCommand('bold') editor.command(e, 'bold'); // 等同于 document.exexCommand('BackColor', false, '#003399') editor.command(e, 'BackColor', '#003399'); }); ``` ----- - **`editor.commandForElem`** 针对当前选中的元素,向上查找,得到符合传入条件的父元素。然后把这个父元素当做选区,来执行命令。除了第一个参数之外,后面的参数和`editor.command`相同。例如: ```js $('#btn').click(function (e) { // 注意,下面的 e 参数尽量要传,否则可能导致其他问题 // 针对当前选区所处于的 b strong 元素,然后执行命令 editor.command('b,strong', e, 'bold'); // 为所处的整个 p 元素设置背景色 editor.command('p', e, 'BackColor', '#003399'); }); ``` ----- - **`editor.customCommand`** 用于自定义的命令操作,而非`document.execCommand`提供的基础命令。 **注意,建议你对编辑内容的所有修改,都使用命令的方式。如果基础命令满足不了要求,一定要使用这里的自定义命令。不要忽略命令,自己写代码来修改。那样会出现各种问题!!!**如果觉得好奇,可以搜索源码中的`E.fn.customCommand`来看看,自定义命令中那些复杂的操作过程。 程序举例: ```js $('#btn').click(function (e) { // 注意,下面的 e 参数尽量要传,否则可能导致其他问题 editor.command(e, function () { // 这里的 this 指向 editor 对象本身 var editor = this; editor.$txt.append('

自定义命令追加的内容

'); }); }); ``` ----- - **`editor.queryCommandValue`** 对`document.queryCommandValue`的封装,使用方法和`document.queryCommandValue`一样。分装中,规避了`IE8`异常错误。 ----- - **`editor.queryCommandState`** 对`document.queryCommandState`的封装,使用方法和`document.queryCommandState`一样。分装中,规避了`IE8`异常错误。 ----- - **`editor.queryCommandSupported`** 对`document.queryCommandSupported`的封装,使用方法和`document.queryCommandSupported`一样。分装中,规避了`IE8`异常错误。 ---- - **`editor.commandHooks`** 当遇到浏览器的`document.execCommand`不支持的命令时,就需要自定义一个命令,放在`editor.commandHooks`中。例如,IE浏览器的`document.execCommand`不支持`insertHtml`命令,为了保证IE浏览器的可用性,就需要增加这样的hook ```js editor.commandHooks.insertHtml = function (html) { var $elem = $(html); var rangeElem = editor.getRangeElem(); var targetElem; targetElem = editor.getLegalTags(rangeElem); if (!targetElem) { return; } $(targetElem).after($elem); }; ```
';

选区API

最后更新于:2022-04-01 23:43:08

###选区API 以下是与选择区域有关的API,**下面有些API在IE8、9可能无效,但是不会报错**。 *使用下面的API,最好要了解一下`javascript`的`range`和`selection`的基础知识。如果要兼容IE8、9,还有了解IE8、9特有的`selection`和 `textRange`的知识。* ----- - **`editor.currentRange`** 获取或者设置当前的选中区域,例如 ```js var range = editor.currentRange(); // 获取 editor.currentRange(range); // 设置 ``` ----- - **`editor.collapseRange`** 折叠传入的选区,或者当前选区。例如: ```js editor.collapseRange(); // 折叠当前选区,到结束位置 editor.collapseRange(range); // 折叠传入的选区,到结束位置 editor.collapseRange(null, 'start'); // 折叠当前选区,到开始位置 editor.collapseRange(range, 'start'); // 折叠传入的选区,到开始位置 ``` ----- - **`editor.getRangeText`** 获取当前选区的文字内容,例如 ```js var rangeText = editor.getRangeText(); ``` ----- - **`editor.getRangeElem`** 获取当前选区所在的容器元素,不会是`text node`,而是`elem node`。例如 ```js var elem = editor.getRangeElem(); ``` ----- - **`editor.isRangeEmpty`** 判断当前选区有没有选中文字内容。**说明:如果鼠标拖拽选择了若干个文字,那就是有选中内容;如果鼠标点击了某个地方,为选中文字,只有光标闪烁,那就是无选中内容** ```js if ( editor.isRangeEmpty() ) { console.log('当前选区无选中内容'); } ``` ----- - **`editor.saveSelection`** 将传入的选区对象或者从浏览器捕获的选区,保存为编辑器的当前选区。 ```js editor.saveSelection(); // 捕获浏览器的选区,保存 editor.saveSelection(range); //将传入的选区对象,保存为当前选区 ``` ----- - **`editor.restoreSelection`** 将编辑器的当前选区,或者传入的选区对象,恢复为浏览器能看得见的选择区域。 ```js editor.restoreSelection(); // 恢复当前选区为浏览器的选择区域 editor.restoreSelection(range); // 将传入的选区对象,恢复为浏览器的选择区域 ``` ----- - **`editor.restoreSelectionByElem`** 将传入的`elem`元素,作为选区,恢复为浏览器的选择区域。 ```js // 获取编辑器的最后一个 p 元素 var $p = editor.$txt.find('p').last(); var p = $p.get(0); if (!p) { return; } editor.restoreSelectionByElem(p); // 回复选区至最后一个 p,折叠到结束位置结束位置 editor.restoreSelectionByElem(p, 'start'); // 回复选区至最后一个 p,折叠到结束位置开始位置 ```
';