Firefox上的JavaScript TinyMCE / jQuery竞争条件

我有一个网站,其表格使用TinyMCE; 独立地,我使用jQuery。 当我从Firefox 3(MacOS X,Linux)上的登台服务器加载表单时,TinyMCE无法完成加载。 Firefox控制台中有一个错误,说t.getBody()返回nullt.getBody() ,据我所知,从TinyMCE docs,是一个函数,返回文档的body元素,以检查某些function。 使用Safari时不会出现问题,也不会在使用从localhost运行的同一站点的Firefox时出现问题。

原始的,失败的JavaScript相关代码如下所示:

      tinyMCE.init({ mode:"specific_textareas", editor_selector:"mce", theme:"simple", language:"pl" });      $(document).ready(function(){ /* jQuery initialization */ });  

我尝试更改脚本加载顺序,将tinyMCE.init() call to the tag containing $(document).ready() call—before, after, and inside this call. No result. When tinyMCE.init() was called from within $(document).ready() handler, the browser did hang on request—looks like it was too late to call the init function.移动tinyMCE.init() call to the tag containing $(document).ready() call—before, after, and inside this call. No result. When tinyMCE.init() was called from within $(document).ready() handler, the browser did hang on request—looks like it was too late to call the init function. tinyMCE.init() call to the tag containing $(document).ready() call—before, after, and inside this call. No result. When tinyMCE.init() was called from within $(document).ready() handler, the browser did hang on request—looks like it was too late to call the init function.

然后,在谷歌搜索与jQuery一起使用TinyMCE之后,我将tinyMCE.init()调用改为:

 tinyMCE.init({ mode:"none", theme:"simple", language:"pl" }); 

并添加了以下jQuery调用$(document).ready()处理程序:

 $(".mce").each( function(i) { tinyMCE.execCommand("mceAddControl",true,this.id); }); 

还是一样的错误。 但是,当我添加警报(i)时,这里的东西开始看起来像真正的伏都教; 在tinyMCE.execCommand()调用之前,给出了警报,并正确初始化了TinyMCE textareas。 我认为这可能是等待用户解除警报引起的延迟问题,所以我通过更改仍在$(document).ready()处理程序内的调用来引入第二个延迟:

  setTimeout('$(“。mce”)。each(function(i){tinyMCE.execCommand(“mceAddControl”,true,this.id);});',1000);

随着超时,TinyMCE textareas正确初始化,但它正在绕过真正的问题。 问题看起来像一个明显的竞争条件(特别是当我考虑在同一个浏览器上,但当服务器在localhost上时,问题不会发生)。 但是JavaScript执行是不是单线程? 有人可以告诉我这里发生了什么,实际问题在哪里,我能做些什么来实际修复它?

浏览器按照加载的顺序执行脚本,而不是写入。 你的直接脚本 – tinyMCE.init(...)$(document.ready(...)); – 可以在文件完成加载之前执行。

因此,问题可能是网络延迟 – 尤其是6个独立的脚本(每个脚本需要在浏览器和服务器之间进行不同的HTTP对话)。 因此,浏览器可能在tiny_mce.js完成解析并且tinyMCE完全定义之前尝试执行tinyMCE.init()

如果没有Firebug, 那就去吧。 ;)
它有一个Net选项卡,可以显示加载所有脚本需要多长时间。


虽然您可能会认为setTimeout是风管编带,但它实际上是一个不错的解决方案。 我看到的唯一问题是它假设1秒将永远修复。 快速连接,他们可以看到暂停。 连接速度慢而且等待时间不够长 – 您仍然会收到错误。

或者,您可以使用window.onload – 假设jQuery尚未使用它。 (其他人可以validation吗?)

 window.onload = function () { tinyMCE.init(...); $(document).ready(...); }; 

还有,那是直接复制吗?

  

它错过了结束ready

  

缺少标点符号会造成大量伤害。 解析器只是在它找到它之前继续阅读 – 弄乱它们之间的任何东西。

因为当我问自己同样的问题时,这是谷歌的第一页,这就是我发现的这个问题。

资源

tinyMCE中有一个回调函数,当组件加载并准备就绪时会触发该函数。 你可以像这样使用它:

 tinyMCE.init({ ... setup : function(ed) { ed.onInit.add(function(ed) { console.log('Editor is loaded: ' + ed.id); }); } }); 

如果您使用的是jquery.tinymce.js那么您不需要tiny_mce.js因为TinyMCE会尝试使用ajax请求加载它。 如果你发现window.tinymce (或简称tinymce )是undefined那么这意味着ajax尚未完成(这可能解释了为什么使用setTimeout为你工作)。 这是典型的事件顺序:

  1. 使用脚本标记(或谷歌加载)加载jquery.js
  2. 使用脚本标记加载TinyMCE的jQuery插件jquery.tinymce.js
  3. 记录准备好的事件火灾; 这是你在textarea上调用.tinymce(settings)的地方。 例如$('textarea').tinymce({ script_url: '/tiny_mce/tiny_mce.js' })

  4. 加载tiny_mce.js这一步是由TinyMCE的jQuery插件为你完成的,但它可能在文件就绪事件触发后发生。

有时您可能真的需要访问window.tinymce ,这是最安全的方法:

$(document).tinymce({‘script_url’:’/ tiny_mce / tiny_mce.js”setup’:function(){alert(tinymce);}});

TinyMCE甚至可以创建一个tinymce.Editor对象并执行设置回调。 没有触发编辑器的事件,并且没有将为文档创建的编辑器对象添加到tinymce.editors

我还发现TinyMCE的ajax调用干扰了我的.ajaxStop函数,所以我也使用了setTimeout

$(document).tinymce({‘script_url’:’/ tiny_mce / tiny_mce.js”setup’:function(){setTimeout(function(){$(document).ajaxStart(function(e){/ * stuff / } ;; $(document).ajaxStop(function(e){/ stuff * /});},0);}});