从父表单中分离输入

disassociate input from parent form

本文关键字:分离 输入 表单      更新时间:2023-09-26

是否有可能将<input>元素与其父元素完全分离?我有一个情况,我必须使用一个<input>元素的文本输入,但我不希望它是表单的一部分。我知道留下name属性空白有效地隐藏了大多数时间的字段,但是,例如,我在form.elements集合上编写了循环代码,其中包含未命名的字段。我不想过滤elements列表。

我尝试在可编辑的div中模拟<input>行为,但实现变得相当复杂(处理复制/粘贴,格式化,换行)。它看起来像form属性可能有帮助,但我想支持IE10+。

我想要的<input>行为不包括它的任何父的表单提交或表单元素查询方法。

编辑:澄清一下,我最关心的是从form.elements集合中删除<input>。即使元素没有命名,它仍然会出现在列表中。 编辑2:我不能简单地将元素移动到另一个div,因为它们实际出现在表单中,并与其他内容一起流动。

表单提交事件处理程序没有帮助,因为它们不适用于form.elements集合。

遍历表单并找到所有输入。克隆每个输入并将其附加到某个地方,例如<div>(如果您仍然想保留输入),然后使用.remove()方法删除输入。

$('form :input').each(function(){
  $input=$(this).clone(true);
  $('#container').append($input).append('<br>');
  $(this).remove();
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<form>
  Inside Form
  <input type="text" id="txt1" name="txt1" value="txt1"><br>
  <input type="text" id="txt2" name="txt2" value="txt2">
</form>
<br>
<br>
<div id="container">
  Inside Div <br>
</div>

您可以将"容器"元素(如div)放在您希望输入出现的地方(在form中),但将实际的input元素放在表单之外,因此它不是DOM树中它的后代。

然后在页面加载时,以及每次调整窗口大小时,将input(具有absolute位置样式)移动到容器顶部,而不改变其在DOM树中的位置:

function positionInput() {
    var myinput = document.querySelector('#myinput');
    // give input same size as container element
    var container = document.querySelector('#container');
    myinput.style.height = container.offsetHeight + 'px'; 
    myinput.style.width = container.offsetWidth + 'px';
    // move input element to the container location
    myinput.style.top = container.offsetTop + 'px';
    myinput.style.left = container.offsetLeft + 'px';
}
document.addEventListener('DOMContentLoaded', positionInput);
window.addEventListener('resize', positionInput);
<input id="myinput" style="position:absolute" value="hello">
<h1>Title of form</h1>
<form style="margin: 10px">
    <div id="container" style="background: yellow">&nbsp;</div>
</form>

请注意,我给容器一个黄色的背景,只是为了证明它完全被移动的input元素覆盖。

在上面的代码中,捕获resize事件以根据容器的新位置和大小重新对齐input。您可以扩展这一点,以便在发生其他事件时,甚至在设置的间隔(使用setInterval)执行此重新排列。

我想我想到了一个合适的解决方案。它感觉有点俗气(读作:真的俗气),但完成了我需要它做的事情。如果谁有更好的主意,请告诉我。

如果我将输入包装在iframe中,它将有效地隐藏在表单中。不幸的是,我认为我不能直接将输入附加到子文档,因此需要手工克隆它。下面是我的概念验证代码:

<style>
    iframe {
        border: 0;
        width: 100%;
    }
</style>
<form id="myForm">
    <input style="width: 100%"/>
</form>
<script>
    (function() {
        var myForm = document.getElementById("myForm");
        console.log(myForm.elements.length);
        var input = myForm.querySelector("input");
        input.parentElement.removeChild(input)
        var frame = myForm.appendChild(document.createElement("iframe"));
        var frameInput = frame.contentDocument.querySelector("body").appendChild(frame.contentDocument.createElement("input"));
        frameInput.setAttribute("style", input.getAttribute("style"));
        console.log(myForm.elements.length);
        frameInput.addEventListener("click", externalListener);
    })();
    function externalListener() {
        alert();
    }
</script>

这表明父表单不再看到输入,并且父文档仍然可以侦听从iframe内触发的事件。