javascript - 为什么我的 iframe 的 contentEditable 会被重置?

标签 javascript html dom iframe contenteditable

我有一个网页,其中有一个空的 iframe,我想为其分配一个带有 javascript 的源并使其内容可编辑。 问题是 - 虽然我可以看到框架的内容在短时间内变得可编辑(浏览器开始在未通过拼写检查的单词下划线) - 某些东西重置了该状态,我留下了一个 iframe,它有正确的内容,但框架的 contentWindow.document.body.contentEditable 已重置为默认的“继承”。

在控制台中设置 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()”,并将其返回值分配给“onload”属性,这不是一个有效的函数。

如果你写它也不起作用

theFrame.onload = "setedit()";

可能是因为它尝试将文字字符串值分配给属性,这也不是有效的函数。

令人沮丧的事情以及我无法弄清楚如此日志的原因是,这两种方法都不会导致将错误记录到控制台,并且它们都与分配时分配 onload 处理程序的方式不一致它们在标签内,即

<iframe id="the_frame" onload=setedit()></iframe>
<iframe id="the_frame" onload="setedit()"></iframe>

两者都将“setedit()”函数指定为 onload 事件的处理程序,除非 - 当以这种方式定义时 - 它们最终会在父窗口 onload 之前和之后被调用,并且无法更改第二个窗口的 contentEditable 属性由于某种原因也有时间。 你必须在窗口的 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 事件触发。

https://jsfiddle.net/zwxrpdf8/1/

关于javascript - 为什么我的 iframe 的 contentEditable 会被重置?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/54287322/

相关文章:

javascript - 单行的 Angular6 多个 ngFor - 如何在一个 ngFor 中传递两个值

jquery - 如何使用 colorbox 显示 iframe

css - 相对和绝对定位混淆

javascript - 将 jQuery inputmask 附加到 DOM 元素

javascript - 如果输入了最低价格,如何使最高价格成为必需?

javascript - 类型错误 : Cannot set property 'xxx' of undefined

html - IE 中的 Flexbox 无法正确设置元素宽度

php - DOMDocument 删除脚本标签中的结束标签

javascript - Selenium 中的 XPath 是否针对 DOM 或 HTML 文件运行?

javascript - jQuery 切换不正确