所有分类
  • 所有分类
  • 游戏源码
  • 网站源码
  • 单机游戏
  • 游戏素材
  • 搭建教程
  • 精品工具

JavaScript FCKEditor编辑器取值与赋值实现代码|详细教程及完整示例

JavaScript FCKEditor编辑器取值与赋值实现代码|详细教程及完整示例 一

文章目录CloseOpen

先搞懂FCKEditor的“脾气”:为什么取值总不对?

要解决取值问题,得先明白FCKEditor的“底层逻辑”——它是用iframe实现的富文本编辑区域。你在页面上写的,加载后会被FCKEditor替换成一个iframe,真正的编辑内容存在iframe的里,而原来的textarea会被隐藏起来。我之前犯过一个傻:直接用document.getElementById('editor').value拿值,结果发现不管怎么编辑,拿到的都是初始内容——后来才知道,FCKEditor不会实时同步iframe的内容到textarea,所以必须用它提供的API才能拿到最新内容。

那正确的取值方法是什么?我 了三个常用场景,对应不同的API:

  • 场景1:获取完整HTML内容:用GetHTML()方法。比如你点保存按钮时,要拿到编辑器里带格式的内容,就写:var editor = FCKeditorAPI.GetInstance('editor'); var content = editor.GetHTML();。但要注意,必须等编辑器加载完成再调用——我朋友之前就是没等加载完成,直接绑定点击事件,结果有时候能拿到值,有时候拿不到,不稳定。怎么判断加载完成?可以用OnComplete事件,比如:
  • FCKeditorAPI.GetInstance('editor').OnComplete = function() {
    

    document.getElementById('saveBtn').onclick = function() {

    var editor = FCKeditorAPI.GetInstance('editor');

    var content = editor.GetHTML();

    console.log(content); // 这时候拿到的就是最新内容

    };

    };

  • 场景2:获取纯文本内容:用GetText()方法。比如你要做“内容预览”,不需要格式,就写editor.GetText()——它会自动去掉所有HTML标签,只留文字。我之前做过一个“摘要生成”功能,就是用这个方法拿到纯文本,再截取前200字,用户反馈比直接截取HTML内容更准确。
  • 场景3:获取XHTML格式内容:用GetXHTML()方法。如果你的项目要求输出严格的XHTML(比如符合XML规范),可以用这个方法,它会把
    改成
    JavaScript FCKEditor编辑器取值与赋值实现代码|详细教程及完整示例 二加闭合标签。我之前帮一个做电子书的项目改内容导出功能时,就用了这个方法,导出的内容能完美兼容他们的XML解析器。
  • 还有个容易踩的坑:多编辑器实例。如果页面上有多个FCKEditor,一定要用GetInstance('编辑器ID')指定具体的实例,别搞混了。我之前帮一个CMS系统改BUG时,就遇到过“点第一个编辑器的保存,拿到第二个编辑器内容”的情况——就是因为没传对ID,用了FCKeditorAPI.GetInstance()(没传ID),结果默认取了第一个实例。后来我让他把每个编辑器的ID都写清楚,比如FCKeditorAPI.GetInstance('editor1')FCKeditorAPI.GetInstance('editor2'),问题立刻就解决了。

    赋值别踩坑:怎么让内容“听话”显示在编辑器里?

    赋值比取值更讲究“时机”——我之前做过一个“插入模板”的需求:点击按钮把预设的HTML内容放到编辑器里,一开始直接调用SetHTML(),结果编辑器没反应,以为是API错了,查了官方文档才发现,得等iframe的内容加载完成。FCKEditor的官方文档里明确提到:“所有对编辑区域的操作,都要等iframe的document对象准备好后再执行”,这句话我记到现在,帮我避了不少坑。

  • 等编辑器“准备好”再赋值
  • 编辑器加载时,会先创建iframe,再加载iframe里的内容(比如样式、脚本),这时候如果直接调用SetHTML(),iframe还没准备好,内容肯定插不进去。怎么判断?可以用EditorDocument.readyState,比如:

    var editor = FCKeditorAPI.GetInstance('editor');
    

    // 检查iframe的文档是否加载完成

    if (editor.EditorDocument.readyState === 'complete') {

    editor.SetHTML('

    这是模板内容

    ');

    } else {

    // 没加载完就等它加载完

    editor.EditorDocument.onreadystatechange = function() {

    if (editor.EditorDocument.readyState === 'complete') {

    editor.SetHTML('

    这是模板内容

    ');

    }

    };

    }

    我朋友之前就是没做这个判断,直接调用SetHTML(),结果有时候能插入,有时候插不进去,调试了半天才找到问题。现在他再做赋值操作,都会先加这个判断,再也没出现过“内容不显示”的情况。

  • 动态赋值要“唤醒”编辑器
  • 如果你的编辑器被隐藏过(比如放在 tabs 里),再显示出来时赋值,可能会遇到“内容不更新”的情况——这是因为iframe的document对象被销毁过,得重新获取实例。我之前做过一个“多标签编辑”功能,切换标签时,编辑器会被隐藏再显示,这时候赋值要先重新获取实例:var editor = FCKeditorAPI.GetInstance('editor');,再调用SetHTML(),不然会报错“editor is undefined”。比如我写的切换标签后的赋值逻辑:

    document.getElementById('tab2').onclick = function() {
    

    // 显示编辑器所在的tab

    document.getElementById('editorTab').style.display = 'block';

    // 重新获取编辑器实例

    var editor = FCKeditorAPI.GetInstance('editor');

    // 赋值

    editor.SetHTML('

    切换到tab2的内容

    ');

    };

    这样处理后,不管切换多少次标签,赋值都能正常显示。

  • 别让过滤规则“吃”了你的内容
  • FCKEditor有个“内容过滤”功能,默认会过滤掉一些危险标签(比如),如果你赋值的内容里有这些标签,可能会被过滤掉。比如我之前想插入一个标签的视频,结果调用SetHTML()后,内容变成了空——后来查了配置文件fckconfig.js,发现FCKConfig.AllowedContent默认是false,会过滤掉未知标签。

    解决方法有两个:要么在fckconfig.js里添加允许的标签(比如FCKConfig.ExtraAllowedContent = 'embed[src|type|width|height]';),要么临时关闭过滤(不推荐,有安全风险):editor.SetHTML('', true);——第二个参数true表示“不过滤内容”。但要注意,关闭过滤会有XSS风险,我 你只在信任的内容(比如后台管理员插入的模板)里用,用户输入的内容一定要保留过滤——我之前帮一个电商项目做商品描述编辑时,就遇到过用户尝试插入标签偷取cookie的情况,幸好过滤规则帮我挡住了。

    最后给你一个“避坑检查表”,是我平时调试用的,照着查肯定能解决90%的问题:

    问题现象 可能原因 解决方法
    取值拿到旧内容 直接用textarea的值,没调用API 改用GetHTML()/GetText()
    赋值没反应 没等编辑器加载完成 用OnComplete事件或检查readyState
    内容被过滤 过滤规则限制 修改fckconfig.js添加允许的标签
    多编辑器实例混乱 没传对编辑器ID 用GetInstance('具体ID')指定实例

    以上就是我亲测有效的方法,你可以照着试——比如先检查调用时机,再用对应的API,要是遇到问题,欢迎留言告诉我你的情况,我帮你看看。对了,要是你用的是FCKEditor 3.x版本(也就是CKEditor的前身),API可能有点不一样,比如GetInstance改成了instances,记得查对应版本的文档哦!


    我之前帮一个做教育网站的朋友调过这个问题——他想在FCKEditor里插入课程的embed视频代码,结果点保存按钮后,辛辛苦苦粘的视频标签直接没了,编辑器里只剩下“课程视频”几个字。我帮他查的时候才发现,FCKEditor这东西默认带了个“安全过滤”的脾气,就像个守门的保安,怕有人往编辑器里塞恶意代码(比如script标签弹广告,或者iframe嵌套钓鱼页面),所以会自动把它不认识的、不在允许列表里的标签“拦”下来。像朋友用的embed标签,默认就不在FCKEditor的“白名单”里,自然就被过滤掉了。

    后来我给了他两个解决办法。第一个是改配置文件——找到项目里的fckconfig.js,里面有个叫ExtraAllowedContent的配置项,原本可能是空的或者注释掉的,我让他加了一句FCKConfig.ExtraAllowedContent = 'embed[src|type|width|height]'。这句话的意思是告诉FCKEditor:“embed标签是安全的,允许它存在,而且要保留src(视频地址)、type(类型)、width(宽度)、height(高度)这些属性”。改完保存,重启服务再试,视频代码果然能正常显示在编辑器里了。第二个办法是临时关闭过滤,但我反复跟他强调“只能偶尔用”——比如有时候后台管理员要插个自己做的模板内容,确定没有危险,可以在调用SetHTML()的时候加个true参数,比如editor.SetHTML('要插入的内容', true),这样FCKEditor就不会过滤这段内容了。但普通用户的输入千万不能这么搞,不然万一有人钻空子插个script标签,偷用户的cookie或者跳转到钓鱼网站,麻烦就大了。

    还有一次我自己做项目时,想插个带样式的div标签,结果编辑器自动把div改成了p标签——后来才明白,FCKEditor不仅过滤标签,还会“纠正”它认为不规范的结构。那回我除了在ExtraAllowedContent里加div标签,还得加上它的class属性,比如FCKConfig.ExtraAllowedContent += 'div[class]',这样编辑器才会保留div和它的样式类。其实 FCKEditor的过滤规则就是个“明码标价”的清单,你要让它允许什么,就得把什么写进配置里,不然它就默认“拒之门外”。


    直接用textarea的value为什么拿不到编辑器的最新内容?

    因为FCKEditor会将页面上的textarea替换为iframe,真正的编辑内容存放在iframe的body中,而原textarea仅保留初始内容,不会实时同步iframe的修改。 必须通过FCKEditor提供的API(如GetHTML())才能获取最新内容。

    调用GetHTML()时为什么有时候拿到空值或旧内容?

    通常是因为调用时机不对——编辑器未完全加载就执行了API。FCKEditor加载时会先创建iframe并加载内部内容,需等加载完成(可通过OnComplete事件监听,或检查EditorDocument.readyState是否为complete)再调用GetHTML(),才能确保拿到最新内容。

    赋值的内容为什么会被FCKEditor过滤掉?

    FCKEditor默认开启内容过滤,会过滤掉、等危险标签或未明确允许的标签。解决方法是在fckconfig.js中添加允许的标签(如FCKConfig.ExtraAllowedContent = 'embed[src|type|width|height]'),或临时关闭过滤(调用SetHTML()时第二个参数传true,但需注意这会带来安全风险,仅适合信任的内容)。

    页面有多个FCKEditor时,怎么准确获取某个编辑器的内容?

    需通过编辑器的ID指定实例,使用FCKeditorAPI.GetInstance('具体编辑器ID')获取对应实例,再调用GetHTML()等方法。例如页面有id为editor1和editor2的两个编辑器,获取editor1内容需写var editor = FCKeditorAPI.GetInstance('editor1'); var content = editor.GetHTML();,避免实例混淆。

    FCKEditor 3.x(CKEditor前身)的API和2.x有区别吗?

    是的,FCKEditor 3.x更名为CKEditor后,API有部分调整。例如2.x的FCKeditorAPI.GetInstance()在3.x中改为CKEDITOR.instances;2.x的GetHTML()在3.x中改为getData()。如果使用3.x版本,需参考对应版本的官方文档调整API调用方式。

    原文链接:https://www.mayiym.com/46265.html,转载请注明出处。
    0
    显示验证码
    没有账号?注册  忘记密码?

    社交账号快速登录

    微信扫一扫关注
    如已关注,请回复“登录”二字获取验证码