前言:
由于项目需要,采用UEditor在线编辑器(百度编辑器 http://ueditor.baidu.com/website/onlinedemo.html)来对文稿进行编排,其中对字数统计有一个需求是,当在ueditor编辑器中敲空格不算字数。
在ueditor.config.js中查找了一翻并没有字数统计时不算空格的配置项,后来在ueditor.all.js中找到了修改处,原来的字数统计是不算制表位\t、回车\r、换行\n的,现在只需把空格\s也加上就好了。
实现:
在ueditor.all.js中搜索 getContentLength 方法名,找到如下代码:
getContentLength: function (ingoneHtml, tagNames) {
var count = this.getContent(false,false,true).length;
if (ingoneHtml) {
tagNames = (tagNames || []).concat([ 'hr', 'img', 'iframe']);
count = this.getContentTxt().replace(/[\t\r\n]+/g, '').length;
for (var i = 0, ci; ci = tagNames[i++];) {
count += this.document.getElementsByTagName(ci).length;
}
}
return count;
},
字数统计不算空格功能实现,将上面的代码修改如下:
getContentLength: function (ingoneHtml, tagNames) {
var count = this.getContent(false,false,true).length;
if (ingoneHtml) {
tagNames = (tagNames || []).concat([ 'hr', 'img', 'iframe']);
count = this.getContentTxt().replace(/[\t\r\n\s]+/g, '').length; // 加了\s
for (var i = 0, ci; ci = tagNames[i++];) {
count += this.document.getElementsByTagName(ci).length;
}
}
return count;
},
其他问题:
问题1:UEditor编辑器在初始化完成时,或者,在往编辑器中粘贴内容时,会新增另起一行,自动跟随内容的 <p><br /></p>
原因:由于默认编辑器是不能为空内容的,所以加了 me.body.innerHTML = '<p>' + (browser.ie ? '' : '<br/>') + '</p>';
解决办法:在ueditor.all.js中搜索:domUtils.isEmptyNode(me.body),然后将 me.body.innerHTML = ' '; 设为空就OK了
// 编辑器不能为空内容
if (domUtils.isEmptyNode(me.body)) {
// me.body.innerHTML = '<p>' + (browser.ie ? '' : '<br/>') + '</p>';
me.body.innerHTML = '';
}
问题2:在往编辑器中输入空格时,空格间隔大小长度不一,有的是英文状态下的空格,有的是中文状态下的空格,有的是半角空格,有的是全角空格 【输入法全半角状态切换(同时按下Shift键+Space空格键)】,导致在编辑器输入空格的效果和打印的效果长短不一。
原因:有的用户不知道当前输入法的空格是全角还是半角(在ueditor编辑器中测试,2个全角空格 = 7个半角空格)
解决办法:监听空格键,当按下空格时统一输入全角或半角空格,在 ueditor.all.js文件中添加如下代码:
/**
* 对编辑器设置keydown事件监听,绑定快捷键和命令,当快捷键组合触发成功,会响应对应的命令
* @method _bindshortcutKeys
* @private
*/
_bindshortcutKeys: function () {
var me = this, shortcutkeys = this.shortcutkeys;
me.addListener('keydown', function (type, e) {
var keyCode = e.keyCode || e.which;
for (var i in shortcutkeys) {
var tmp = shortcutkeys[i].split(',');
for (var t = 0, ti; ti = tmp[t++];) {
ti = ti.split(':');
var key = ti[0], param = ti[1];
if (/^(ctrl)(\+shift)?\+(\d+)$/.test(key.toLowerCase()) || /^(\d+)$/.test(key)) {
if (( (RegExp.$1 == 'ctrl' ? (e.ctrlKey || e.metaKey) : 0)
&& (RegExp.$2 != "" ? e[RegExp.$2.slice(1) + "Key"] : 1)
&& keyCode == RegExp.$3
) ||
keyCode == RegExp.$1
) {
if (me.queryCommandState(i,param) != -1)
me.execCommand(i, param);
domUtils.preventDefault(e);
}
}
}
}
});
// 添加下面这段代码
me.body.addEventListener('keydown', function (e) {
var ev = e || window.event;
if(32 == ev.keyCode) {
ev.preventDefault();
ev.stopPropagation();
me.execCommand('insertHtml', ' ');
return false;
}
});
},
在一般情况下,在html文件中不管输入多少空格,在浏览器中都会自动截去1个以外的其他空格,因为多余的空格外都被当做一个空格。比如你在两个字之间加了10个空格,html会截去9个空格,只保留一个。为了在网页中增加空格,你可以使用 表示空格。
HTML空格字符:
说明 | 实体名称(html) | 实体编号(js) |
---|---|---|
半角空格 |   |   |
半角空格 |   |   |
全角空格 |   |   |
正常空格 | |   |
JavaScript转义符:
转义序列 | 字符 |
---|---|
\b | 退格 |
\f | 走纸换页 |
\n | 换行 |
\r | 回车 |
\t | 横向跳格 (Ctrl-I) |
\' | 单引号 |
\" | 双引号 |
\\ | 反斜杠 |
注:在js中某些地方由于反斜杠本身用作转义符,因此不能直接在脚本中键入一个反斜杠。如在正则中要产生一个反斜杠,须输入两个反斜杠 \\。
问题3:在往编辑器中粘贴内容时,想过滤(修改、删除)掉某些格式,如:标签、样式、属性等
原因:当在外部某个网站上复制一篇文章进来时,想要过滤掉一些格式 如:标签,样式,属性
解决办法:在 ueditor.config.js文件中有相应的配置选项:
UEditor前端配置项说明:http://fex.baidu.com/ueditor/#start-config
- retainOnlyLabelPasted: false //是否在粘贴时只保留标签,去除标签所有属性 。
- pasteplain: true //是否默认为纯文本粘贴。false为不使用纯文本粘贴,true为使用纯文本粘贴。
- filterTxtRules: function(){} // 纯文本粘贴模式下的过滤规则,可以自定义粘贴板中内容。
filterTxtRules返回的是一个函数(注要:pasteplain: true 才生效哦),函数的return{ }中就是你想要过滤的标签,由于在过滤规则中不能对粘贴进来的dom元素直接操作(因为这些dom元素还没有被渲染到编辑器中,此时它还是一些字符串,但是编辑器模拟了这些节点),所以要想操作dom元素,可以通过编辑器提供的uNode类、Api接口,就能完成过滤标签,样式,属性等操作啦!
实例代码:
//粘贴只保留标签,去除标签所有属性
, retainOnlyLabelPasted: false
, pasteplain: true //是否默认为纯文本粘贴。false为不使用纯文本粘贴,true为使用纯文本粘贴
//纯文本粘贴模式下的过滤规则
'filterTxtRules': function () {
// 过滤caption,th,tr,h1-h6标签 替换为 p标签
function transP(node) {
node.tagName = 'p';
node.attrs.style = ''; //去除该节点的style样式
// node.setStyle();
}
// 过滤a,i标签(直接删除a和i标签,只保留里面的文子内容)
function removeDom(node) {
node.parentNode.removeChild(node, node.innerText())
}
// 以下return中的标签及其子节点都会被过滤掉
return {
//直接删除及其字节点内容
'-': 'script style object iframe embed input select',
'p': { $: {} },
'a': removeDom,
'i': removeDom,
'br': { $: {} },
'div': { '$': {} },
'li': { '$': {} },
'caption': transP,
'th': transP,
'tr': transP,
'h1': transP, 'h2': transP, 'h3': transP, 'h4': transP, 'h5': transP, 'h6': transP,
'td': function (node) {
//没有内容的td直接删掉
var txt = !!node.innerText();
if (txt) {
node.parentNode.insertAfter(UE.uNode.createText(' '), node);
}
node.parentNode.removeChild(node, node.innerText())
}
}
}()
UEditor编辑器的UE.uNode类提供了以下成员方法(这里只例举了部份常用的)
方法 | 描述 |
---|---|
node | 是函数中的参数,就是被过滤的那个节点(标签) |
toHtml() | 当前节点对象,转换成html文本 |
getData() | 获取当前对象的data属性 |
getIndex() | 获取当前节点在父节点下的位置索引 |
getNodeById(String id) | 在当前节点下,根据id查找节点 |
innerText() | 获取节点的纯文本内容 |
innerText(String textStr) | 设置节点的纯文本内容 |
innerHTML() | 获取节点的html内容 |
innerHTML(String htmlstr) | 设置节点的html内容 |
removeChild(UE.uNode node, Boolean keepChildren) | 从当前节点的子节点列表中,移除节点 |
appendChild(UE.uNode node) | 在节点的子节点列表最后位置插入一个节点 |
getAttr(String attrName) | 获取当前节点所代表的元素属性,即获取attrs对象下的属性值 |
setAttr(String attrName, * attrVal) | 设置当前节点所代表的元素属性,即设置attrs对象下的属性值 |
getStyle(String name) | 根据样式名称,获取节点的样式值 |
setStyle(String name, String val) | 给节点设置样式 |
扩展:
我对原UEditor(百度编辑器,PHP1.4.3版)进行了二次开发,新增了一功实用功能 和 修改部分UI界面, 类似 (微信编辑器,微信公众号,图文发布在线编辑器) ,有需要的小伙伴可以参考一下:
代码地址:https://github.com/MuGuiLin/wxEditor