解决innerHTML包含的js代码不能被执行的问题
今天我写了个js弹出模态对话框,这个模态对话框能直接显示一个html或者是url的文本内容,因为加入我需要在对话框里面显示比较复杂的布局的话直接用字符串来做是很麻烦且很难修改的。各方面都比较完善了,但是今天,在我想用这个对话框加载一个页面的时候发现了新问题。
在我的要加载的页面里面有和用户的交互过程,这是用js实现的,我把这个页面加载到我的模态对话框里面,页面显示完全正确,可是在测试交互功能的时候发现js没有响应。我用firebug插件查看,发现里面是有这段js代码的,但怎么执行不了呢。
于是我将这段js代码写在了调用模态对话框的页面,这样交互功能恢复正常了。原来使用innerHTML获得的js代码是不能被执行的,js只有在页面初次加载的时候才有效。
网上有很多种解决的方法,有用iframe实现的,有通过浏览器的特性实现的,但这些都通通不是我喜爱的方法,要我使用iframe,那还不如我把这个问题放着,每次都把被加载页面的js拷贝到调用页面算了。
不过还是找到了一个比较完美的方法,这个方法不仅没有使用限制,而且还是跨浏览器的。我需要的就是这样的代码。有时候发现要在网上找到好的代码简直比登天还难,因为大部分都是copy的,你可以看到一篇不知所云的垃圾文章被copy了好多份。同样你也可以看到好多精品文章被copy了好多份而找不到出处。不过话说回来,自己写文章确实需要很大的耐心,要写一篇别人都能看懂的文章起码需要40分钟,不然你就是在制造垃圾。所以看到好的文章注明出处是一种美德。这篇文章的出处是 http://jcodecraeer.com/a/jquery_js_ajaxjishu/2012/0625/278.html 谢谢转载,可以不带链接但别破坏了我的代码格式,不然别人没法看啊。
说正题。这个方法只需调用一个函数set_innerHTML(obj_id, html, time);
set_innerHTML('要插入innerhtml的ID名称', '要插入的代码');time参数可以忽略,我急于实现功能就没去看实现的细节了。
以下是代码:
/* innerhtml.js
* Version: 1.9
* LastModified: 2006-06-04
* This library is free. You can redistribute it and/or modify it.
*
*/
var global_html_pool = \[\];
var global_script_pool = \[\];
var global_script_src_pool = \[\];
var global_lock_pool = \[\];
var innerhtml_lock = null;
var document_buffer = "";
function set_innerHTML(obj_id, html, time) {
if (innerhtml_lock == null) {
innerhtml_lock = obj_id;
}
else if (typeof(time) == "undefined") {
global_lock_pool\[obj_id + "_html"\] = html;
window.setTimeout("set_innerHTML('" + obj_id + "', global_lock_pool\['" + obj_id + "_html'\]);", 10);
return;
}
else if (innerhtml_lock != obj_id) {
global_lock_pool\[obj_id + "_html"\] = html;
window.setTimeout("set_innerHTML('" + obj_id + "', global_lock_pool\['" + obj_id + "_html'\], " + time + ");", 10);
return;
}
function get_script_id() {
return "script_" + (new Date()).getTime().toString(36)
+ Math.floor(Math.random() * 100000000).toString(36);
}
document_buffer = "";
document.write = function (str) {
document_buffer += str;
}
document.writeln = function (str) {
document_buffer += str + "\\n";
}
global_html_pool = \[\];
var scripts = \[\];
html = html.split(/<\\/script>/i);
for (var i = 0; i < html.length; i++) {
global_html_pool\[i\] = html\[i\].replace(/<script\[\\s\\S\]*$/ig, "");
scripts\[i\] = {text: '', src: '' };
scripts\[i\].text = html\[i\].substr(global_html_pool\[i\].length);
scripts\[i\].src = scripts\[i\].text.substr(0, scripts\[i\].text.indexOf('>') + 1);
scripts\[i\].src = scripts\[i\].src.match(/src\\s*=\\s*(\\"(\[^\\"\]*)\\"|\\'(\[^\\'\]*)\\'|(\[^\\s\]*)\[\\s>\])/i);
if (scripts\[i\].src) {
if (scripts\[i\].src\[2\]) {
scripts\[i\].src = scripts\[i\].src\[2\];
}
else if (scripts\[i\].src\[3\]) {
scripts\[i\].src = scripts\[i\].src\[3\];
}
else if (scripts\[i\].src\[4\]) {
scripts\[i\].src = scripts\[i\].src\[4\];
}
else {
scripts\[i\].src = "";
}
scripts\[i\].text = "";
}
else {
scripts\[i\].src = "";
scripts\[i\].text = scripts\[i\].text.substr(scripts\[i\].text.indexOf('>') + 1);
scripts\[i\].text = scripts\[i\].text.replace(/^\\s*<\\!--\\s*/g, "");
}
}
var s;
if (typeof(time) == "undefined") {
s = 0;
}
else {
s = time;
}
var script, add_script, remove_script;
for (var i = 0; i < scripts.length; i++) {
var add_html = "document_buffer += global_html_pool\[" + i + "\];\\n";
add_html += "document.getElementById('" + obj_id + "').innerHTML = document_buffer;\\n";
script = document.createElement("script");
if (scripts\[i\].src) {
script.src = scripts\[i\].src;
if (typeof(global_script_src_pool\[script.src\]) == "undefined") {
global_script_src_pool\[script.src\] = true;
s += 2000;
}
else {
s += 10;
}
}
else {
script.text = scripts\[i\].text;
s += 10;
}
script.defer = true;
script.type = "text/javascript";
script.id = get_script_id();
global_script_pool\[script.id\] = script;
add_script = add_html;
add_script += "document.getElementsByTagName('head').item(0)";
add_script += ".appendChild(global_script_pool\['" + script.id + "'\]);\\n";
window.setTimeout(add_script, s);
remove_script = "document.getElementsByTagName('head').item(0)";
remove_script += ".removeChild(document.getElementById('" + script.id + "'));\\n";
remove_script += "delete global_script_pool\['" + script.id + "'\];\\n";
window.setTimeout(remove_script, s + 10000);
}
var end_script = "if (document_buffer.match(/<\\\\/script>/i)) {\\n";
end_script += "set_innerHTML('" + obj_id + "', document_buffer, " + s + ");\\n";
end_script += "}\\n";
end_script += "else {\\n";
end_script += "document.getElementById('" + obj_id + "').innerHTML = document_buffer;\\n";
end_script += "innerhtml_lock = null;\\n";
end_script += "}";
window.setTimeout(end_script, s);
}
有了这个方法,原来这样写
document.getElementById("sch_nameArea").innerHTML= text;
的地方就可以写成这样
set_innerHTML('sch_nameArea',text);
值得注意的是,这个代码用到了一些全局变量,
var global_html_pool = \[\];
var global_script_pool = \[\];
var global_script_src_pool = \[\];
var global_lock_pool = \[\];
var innerhtml_lock = null;
var document_buffer = "";
至少你应该尽可能的避免和这些全局变量冲突。决绝全局变量冲突的良策貌似是使用闭包,最近正在学习这些概念,如果你是一个严谨的人,我觉得有必要重写这段代码,让它更灵活和稳定。
最后向写这段代码的济南大学马秉尧老师致敬!