contenteditable div 中的文件输入不适用于 FireFox

File input inside contenteditable div not working on FireFox

我有一个令人满意的 div。在这个div里面,有一个输入文件。但是,此输入文件无法浏览文件。当我从 div 中删除 contenteditable 的属性时,输入文件能够浏览文件。怎么了?

<div contenteditable="true">
    <input type="file"/>
</div>

versus

<div>
    <input type="file"/>
</div>

我可以确认 firefox 的这种行为(目前不在 know-issues over at CanIUse for contenteditable 上)。


contenteditable 上的 whatwg 规范指出:

The contenteditable content attribute is an enumerated attribute whose keywords are:
the empty string, true, and false.
The empty string and the true keyword map to the true state.
The false keyword maps to the false state.
In addition, there is a third state, the inherit state, which is the missing value default (and the invalid value default).

The true state indicates that the element is editable. The inherit state indicates that the element is editable if its parent is. The false state indicates that the element is not editable.


MDN entry on 'Content Editable' 状态:

In HTML5 any element can be editable.

但随后继续:

It can be used in almost all HTML elements.

但是,没有指定它可以(不能)用于哪些元素。


这些是我对 FireFox 的测试结果(注意这似乎不是最近的回归,FF12 的行为方式相同):

01 <input type="file" />                            WORKS              <br>
02 <input type="file" contenteditable="true" />     DOES NOT WORK      <br> 
03 <input type="file" contenteditable="" />         WORKS (wtf?)       <br>
04 <input type="file" contenteditable="false" />    WORKS              <br>
05 <input type="file" contenteditable="foobar" />   WORKS              <br>

<div>
  06 <input type="file" />                          WORKS
</div>

<div contenteditable="true">
  07 <input type="file" />                          DOES NOT WORK
</div>

<div contenteditable="true">
  <div contenteditable="false">
    08 <input type="file" />                        WORKS
  </div>
</div>

<div contenteditable="true">
  09 <input type="file" contenteditable="true" />   DOES NOT WORK
</div>

<div contenteditable="true">
  10 <input type="file" contenteditable="" />       DOES NOT WORK
</div>

<div contenteditable="true">
  11 <input type="file" contenteditable="false" />  DOES NOT WORK
</div>

<div contenteditable="true">
  12 <input type="file" contenteditable="foobar" /> DOES NOT WORK
</div>

<button onclick="
  document.getElementsByTagName('div')[1].setAttribute('contenteditable','false');
">set parent div for 07 to contenteditable="false" to make it WORK</button>

注意测试 3(矛盾)、8(虽然这可能不是您想要的......)和 11(这对我来说似乎是矛盾的)。

现在,我期待的事情正在发生
是 firefox 开发人员阅读 龙与地下城 Drag & Drop model 的安全部分 6.7.9:

Consider a hostile page providing some content and getting the user to select and drag and drop (or indeed, copy and paste) that content to a victim page's contenteditable region. If the browser does not ensure that only safe content is dragged, potentially unsafe content such as scripts and event handlers in the selection, once dropped (or pasted) into the victim site, get the privileges of the victim site. This would thus enable a cross-site scripting attack.

并更进一步(试图保护用户)。
你问 D&D 有什么关系?好吧.. select 01 [____][Browse] WORKS 来自 运行 测试片段并将其拖(放)到(^ 所在的位置):09 [____][Browse] DOES NO^T WORK... (并看到工作输入的副本也不起作用)。

但是,这并不能解释测试 3、8 或...(我猜至少测试 3 是一个错误),事实上...我仍然在这里摸不着头脑;我了解一些继承,但这看起来不一致。

我很想在这里看到某人 post 更好的答案(我 post 将此作为答案,因为它显然对评论,但也不认为这是一个确定的答案...)

编辑:
我在测试中添加了一个按钮,将测试 7 的父级 div 的 contenteditable 设置为 false。单击它可以使测试 7 工作。

实际上,这可能是一个解决方案(取决于您在做什么)。
看起来这种行为有点强制执行实时所见即所得的 'model'(可选地使用原始源 tab/area)和实际的实时渲染的东西('preview')。
就像邮件编辑器中的三个选项卡(例如):所见即所得、来源、预览...
这意味着你可以有一个 'dummy' 选项卡,当它被激活时,除了将 WYSIWYG 编辑器区域的 contenteditable 切换为 false。
如果需要(到目前为止我还没有测试),可以考虑将所见即所得区域的实时 innerHTML 复制到预览区域..
因此,看来解决方案是采用这种模式来支持firefox..