为什么我的 iframe 的 contentEditable 会被重置?
Why does my iframe's contentEditable get reset?
我有一个网页,里面有一个空的 iframe,我想用 javascript 为它分配一个源,并使其内容可编辑。
问题是 - 虽然我可以看到框架的内容在短时间内变得可编辑(浏览器开始在未通过拼写检查的单词下划线) - 某些东西会重置该状态,我只剩下一个 iframe,它有正确的内容,但框架的 contentWindow.document.body.contentEditable 已重置为默认值 'inherit'。
在控制台中设置 contentEditable 属性 有效。创建一个在 1000 毫秒后更改 contentEditable 属性 的等待函数也是如此。我确定的解决方案是为我希望 iframe 包含的 URL 创建 XMLHttpRequest,将响应分配给中间 html 元素,更改该元素正文的 contentEditable 属性,然后将其 InnerHTML 分配给 iframe 的 srcdoc。
所以,我有变通办法,但我想了解是什么阻碍了我最初的、更简单的方法。
完成html:
<!DOCTYPE html>
<html>
<head>
<script>
function setedit(){
var editableFrame = document.getElementById("editableFrame");
editableFrame.src = '/b.html'
editableFrame.contentWindow.document.body.contentEditable = true;
}
</script>
</head>
<body onload="setedit()">
<iframe id="editableFrame"></iframe>
</body>
</html>
b.html:
<!DOCTYPE html>
<html>
<body>
<p>Lorem ipsum yadda yadda</p>
</body>
</html>
编辑: 虽然公认的带箭头函数的解决方案有效,但现在我不明白为什么我写的时候没有
function setsrc(){
var theFrame = document.getElementById('the_frame');
theFrame.src = '/b.html';
theFrame.onload = setedit();
}
function setedit(){
var theFrame = document.getElementById('the_frame');
theFrame.contentWindow.document.body.contentEditable='true';
}
编辑 2:
好的,我明白了。
theFrame.onload = setedit();
在加载 iframe 之前立即计算 'setedit()' 并将其 return 值分配给 'onload' 属性,这不是一个有效的函数。
这样写也是不行的
theFrame.onload = "setedit()";
大概是因为它试图将文字字符串值分配给 属性,这也不是一个有效的函数。
令人沮丧的是,我无法弄清楚 so log 的原因是,这些方法都不会导致将错误记录到控制台,并且它们都与分配 onload 处理程序的方式不一致你在标签内分配它们,即
<iframe id="the_frame" onload=setedit()></iframe>
<iframe id="the_frame" onload="setedit()"></iframe>
两者都将 'setedit()' 函数指定为 onload 事件的处理程序,除了 - 当以这种方式定义时 - 它们最终在父 window onload 之前和之后被调用并且无法更改contentEditable 属性 也出于某种原因第二次出现。
你必须在 window 的 onload 中构建函数,就像 Kaiido 对箭头函数所做的那样,或者在 ES5 中像这样:
onload = function(){
var myFrame = document.getElementById('the_frame');
myFrame.srcdoc = "<html><body><p>This should be editable</p></body></html>";
myFrame.onload = function(){
myFrame.contentDocument.body.contentEditable=true;
};
}
这是因为加载 iframe(顺便说一句,就像任何资源一样)是一项异步任务。
因此,您访问的 editableFrame.contentWindow
(及其 document.body
)与文档加载后的内容不同。
你调用的时候是一个空文档;例如,可以通过记录本文档的 textContent
来检查。
我必须外包 live example to jsfiddle 因为 null 来源的 StackSnippets 框架不允许访问内部框架内容。
window.onload = e => {
the_frame.src = URL.createObjectURL(
new Blob([`<html><body>An other doc</body></html>`])
);
console.log(
the_frame.contentWindow.document.documentElement.textContent
); // ""
// while in the iframe's onload event
the_frame.onload = e =>
console.log(
the_frame.contentWindow.document.documentElement.textContent
); // "An other doc"
};
<iframe id="the_frame"></iframe>
正如您可能已经理解的那样,解决方案是在您更改其 src
.
后等待 iframe 的 onload 事件触发
我有一个网页,里面有一个空的 iframe,我想用 javascript 为它分配一个源,并使其内容可编辑。 问题是 - 虽然我可以看到框架的内容在短时间内变得可编辑(浏览器开始在未通过拼写检查的单词下划线) - 某些东西会重置该状态,我只剩下一个 iframe,它有正确的内容,但框架的 contentWindow.document.body.contentEditable 已重置为默认值 'inherit'。
在控制台中设置 contentEditable 属性 有效。创建一个在 1000 毫秒后更改 contentEditable 属性 的等待函数也是如此。我确定的解决方案是为我希望 iframe 包含的 URL 创建 XMLHttpRequest,将响应分配给中间 html 元素,更改该元素正文的 contentEditable 属性,然后将其 InnerHTML 分配给 iframe 的 srcdoc。
所以,我有变通办法,但我想了解是什么阻碍了我最初的、更简单的方法。
完成html:
<!DOCTYPE html>
<html>
<head>
<script>
function setedit(){
var editableFrame = document.getElementById("editableFrame");
editableFrame.src = '/b.html'
editableFrame.contentWindow.document.body.contentEditable = true;
}
</script>
</head>
<body onload="setedit()">
<iframe id="editableFrame"></iframe>
</body>
</html>
b.html:
<!DOCTYPE html>
<html>
<body>
<p>Lorem ipsum yadda yadda</p>
</body>
</html>
编辑: 虽然公认的带箭头函数的解决方案有效,但现在我不明白为什么我写的时候没有
function setsrc(){
var theFrame = document.getElementById('the_frame');
theFrame.src = '/b.html';
theFrame.onload = setedit();
}
function setedit(){
var theFrame = document.getElementById('the_frame');
theFrame.contentWindow.document.body.contentEditable='true';
}
编辑 2: 好的,我明白了。
theFrame.onload = setedit();
在加载 iframe 之前立即计算 'setedit()' 并将其 return 值分配给 'onload' 属性,这不是一个有效的函数。
这样写也是不行的
theFrame.onload = "setedit()";
大概是因为它试图将文字字符串值分配给 属性,这也不是一个有效的函数。
令人沮丧的是,我无法弄清楚 so log 的原因是,这些方法都不会导致将错误记录到控制台,并且它们都与分配 onload 处理程序的方式不一致你在标签内分配它们,即
<iframe id="the_frame" onload=setedit()></iframe>
<iframe id="the_frame" onload="setedit()"></iframe>
两者都将 'setedit()' 函数指定为 onload 事件的处理程序,除了 - 当以这种方式定义时 - 它们最终在父 window onload 之前和之后被调用并且无法更改contentEditable 属性 也出于某种原因第二次出现。 你必须在 window 的 onload 中构建函数,就像 Kaiido 对箭头函数所做的那样,或者在 ES5 中像这样:
onload = function(){
var myFrame = document.getElementById('the_frame');
myFrame.srcdoc = "<html><body><p>This should be editable</p></body></html>";
myFrame.onload = function(){
myFrame.contentDocument.body.contentEditable=true;
};
}
这是因为加载 iframe(顺便说一句,就像任何资源一样)是一项异步任务。
因此,您访问的 editableFrame.contentWindow
(及其 document.body
)与文档加载后的内容不同。
你调用的时候是一个空文档;例如,可以通过记录本文档的 textContent
来检查。
我必须外包 live example to jsfiddle 因为 null 来源的 StackSnippets 框架不允许访问内部框架内容。
window.onload = e => {
the_frame.src = URL.createObjectURL(
new Blob([`<html><body>An other doc</body></html>`])
);
console.log(
the_frame.contentWindow.document.documentElement.textContent
); // ""
// while in the iframe's onload event
the_frame.onload = e =>
console.log(
the_frame.contentWindow.document.documentElement.textContent
); // "An other doc"
};
<iframe id="the_frame"></iframe>
正如您可能已经理解的那样,解决方案是在您更改其 src
.