contenteditable 的 html 数据列表(非输入标签)

vsy*_*ync 7 html javascript html-input contenteditable html-datalist

我想知道是否有任何非法侵入的方式可能有人知道这将允许HTML数据列表元件的作用,与contenteditable元素,不会与<input>元素

示例代码:

<label>Choose a browser from this list:
  <span contenteditable list="browsers" name="myBrowser">choose</span> 
</label>
<datalist id="browsers">
  <option value="Chrome">
  <option value="Firefox">
  <option value="Internet Explorer">
  <option value="Opera">
  <option value="Safari">
  <option value="Microsoft Edge">
</datalist>
Run Code Online (Sandbox Code Playgroud)

小提琴演示

似乎它只能与<input>元素绑定。在我的情况下,我有一个 javascript 插件,它隐藏了一个输入字段并将其替换为span,对于一些只能使用常规 DOM 元素完成的“特殊”事情,例如span. 这个跨度是contenteditable和行为是它替换的输入的模拟,而输入是隐藏的。

Kyl*_*Mit 1

据我所知,没有标准将 a 应用于<datalist>具有该[contenteditable]属性的随机元素,或者除了具有该属性的输入之外的任何元素[list]。充其量,您只能关注各个浏览器如何选择实现该规范。

显然,最好的药物是转换为语义正确的 html,但如果可能的话,只需添加注释以供将来的访问者执行,因为这不是您的用例。

input一种可能的解决方法是在事件期间旋转元素focusin,匹配周围范围的样式,允许本机浏览器事件触发,并在输入失去焦点时应用更新的值。

在 JavaScript 中是这样的:

document.addEventListener('focusin', function (event) {
    if (event.target.matches('[contenteditable]')) {
        var editable = event.target

        // get text
        var text = editable.innerText

        // create input
        var input = document.createElement("input");
        input.type = "text";
        input.className = "editable-mirror";
        input.setAttribute("list", "browsers");
        input.value = text;

        editable.appendChild(input);

        input.focus()
    }
});
document.addEventListener('focusout', function (event) {
    if (event.target.matches('.editable-mirror')) {
        var input = event.target
        var editable = input.closest("[contenteditable]")

        // get text
        var text = input.value;

        // destroy input
        input.parentNode.removeChild(input);

        // apply value
        editable.innerText = text;
    }
});
Run Code Online (Sandbox Code Playgroud)

以及一些入门款式(尽管您的里程可能会有所不同)

[contenteditable] {
  position: relative;
  border: 1px solid silver;
  padding: 2px 5px;
  display: inline-block;
}

.editable-mirror {
    position: absolute;
    left: -1px;
    top: -1px;
    height: calc(100% + 2px);
    width: calc(100% + 7px);
    padding: 2px 5px;
    margin: 0;
    border: 0;
}
Run Code Online (Sandbox Code Playgroud)

这是 Stack Snippets 和JSFiddle中的工作演示

document.addEventListener('focusin', function (event) {
	if (event.target.matches('[contenteditable]')) {
        console.log('focused')

        var editable = event.target

        // enter edit mode
        editable.classList.add("editing")
        
        // get text
        var text = editable.innerText

        // create input
        var input = document.createElement("input");
        input.type = "text";
        input.className = "editable-mirror";
        input.setAttribute("list", "browsers");
        input.value = text;

        editable.appendChild(input);

        input.focus()
        
	}
}, false);
document.addEventListener('focusout', function (event) {
    if (event.target.matches('.editable-mirror')) {
        console.log('blur')
        
        var input = event.target
        var editable = input.closest("[contenteditable]")

        // leave edit mode
        editable.classList.remove("editing")

        // get text
        var text = input.value;

        // destroy input
        input.parentNode.removeChild(input);

        // apply value
        editable.innerText = text;
    }
}, false);
Run Code Online (Sandbox Code Playgroud)
[contenteditable] {
  position: relative;
  border: 1px solid silver;
  padding: 2px 5px;
}

.editable-mirror {
    position: absolute;
    left: -1px;
    top: -1px;
    height: calc(100% + 2px);
    width: calc(100% + 12px);
    padding: 2px 5px;
    margin: 0;
    border: 0;
    font: inherit;
}
Run Code Online (Sandbox Code Playgroud)
<h2>Regular - Input + Datalist</h2>
<label>Choose a browser from this list:
<input type="text" list="browsers" placeholder="Edit Me" id="regular" /></label>

<datalist id="browsers">
  <option value="Chrome"/>
  <option value="Firefox"/>
  <option value="Internet Explorer"/>
  <option value="Opera"/>
  <option value="Safari"/>
  <option value="Microsoft Edge"/>
</datalist>

<h2>Workaround - ContentEditable + Datalist</h2>

<label>Choose a browser from this list:
<span contenteditable list="browsers" name="myBrowser">edit me</span></label>
Run Code Online (Sandbox Code Playgroud)