使用 jQuery 清除 <input type='file' />

IT技术 javascript jquery html file-io forms
2021-01-16 07:25:17

是否可以<input type='file' />使用 jQuery清除控件值?我尝试了以下方法:

$('#control').attr({ value: '' }); 

但它不起作用。

6个回答

简单:将 a 包裹<form>在元素周围,在表单上调用 reset,然后使用.unwrap(). .clone()此线程中的其他解决方案不同,您最终会得到相同的元素(包括在其上设置的自定义属性)。

在 Opera、Firefox、Safari、Chrome 和 IE6+ 中测试和工作。也适用于其他类型的表单元素,除了type="hidden".

window.reset = function(e) {
  e.wrap('<form>').closest('form').get(0).reset();
  e.unwrap();
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>

<form>
  <input id="file" type="file">
  <br>
  <input id="text" type="text" value="Original">
</form>

<button onclick="reset($('#file'))">Reset file</button>
<button onclick="reset($('#text'))">Reset text</button>

JSFiddle

正如下面 Timo 所指出的,如果您有触发 内部字段重置的按钮,则<form>必须调用.preventDefault()该事件以防止<button>触发提交。


编辑

由于未修复的错误,在 IE 11 中不起作用。输入中的文本(文件名)被清除,但其File列表仍然填充。

@cHao,当然,这仅在输入元素实际上是一种形式时才成立,而不必如此。
2021-03-12 07:25:17
问题是,这至少会暂时使文档无效。(表单不能包含其他表单。)无论当前是否有效,它都可以随时打破。
2021-03-18 07:25:17
优胜者!适用于所有浏览器并避免克隆输入字段。但如果清除按钮在表单内,请重命名reset()为例如。reset2(),因为至少在 Chrome 中,如果是 ,则所有字段都会被清除reset()并在清除调用后添加 event.preventDefault() 以防止提交。这样:<button onclick="reset2($('#file'));event.preventDefault()">Reset file</button>工作示例:jsfiddle.net/rPaZQ/23
2021-03-21 07:25:17
@Timo,我已将该函数重命名为resetFormElement并添加了一条注释,指出您应该在 button 上 preventDefault() onclick
2021-03-28 07:25:17
最新的 Chrome 不喜欢它(get(0)未定义),我不得不.wrap('<form></form>')按照 jQuery 文档中的建议去做
2021-03-30 07:25:17

快速回答:更换它。

在下面的代码中,我使用replaceWithjQuery 方法将控件替换为自身的克隆。如果您有任何绑定到此控件上的事件的处理程序,我们也希望保留这些处理程序。为此,我们将其true作为方法的第一个参数传入clone

<input type="file" id="control"/>
<button id="clear">Clear</button>
var control = $("#control");

$("#clear").on("click", function () {
    control.replaceWith( control = control.clone( true ) );
});

小提琴:http : //jsfiddle.net/jonathansampson/dAQVM/

如果在保留事件处理程序的同时克隆出现任何问题,您可以考虑使用事件委托来处理来自父元素的此控件的点击:

$("form").on("focus", "#control", doStuff);

这可以防止在刷新控件时将任何处理程序与元素一起克隆。

这个解决方案的烦人之处在于你的代码中必须有两次元素,所以如果有人改变了,例如名称,你必须改变你的代码两次(这很容易忘记)
2021-03-11 07:25:17
它仍然不起作用。需要在更换前清除。所以你需要 .val() 在 .replaceWith() 之前。所以它会是 control.val('').replaceWith(...);
2021-03-17 07:25:17
您还可以在 $('#clone').replaceWith($(this).clone()); 字段上使用 .clone() 方法。
2021-04-02 07:25:17

Jquery 应该为您处理跨浏览器/旧浏览器问题。

这适用于我测试过的现代浏览器:Chromium v​​25、Firefox v20、Opera v12.14

使用 jquery 1.9.1

HTML

<input id="fileopen" type="file" value="" />
<button id="clear">Clear</button>

查询

$("#clear").click(function () {
    $("#fileopen").val("");
});

jsfiddle 上

以下 javascript 解决方案也适用于上述浏览器。

document.getElementById("clear").addEventListener("click", function () {
    document.getElementById("fileopen").value = "";
}, false);

jsfiddle 上

我无法用 IE 进行测试,但理论上这应该可行。如果 IE 足够不同以至于 Javascript 版本不起作用,因为 MS 以不同的方式完成了它,我认为 jquery 方法应该为您处理它,否则值得将它与 jquery 团队一起指出IE 需要的方法。(我看到人们说“这在 IE 上不起作用”,但没有香草 javascript 来显示它如何在 IE 上工作(据说是“安全功能”?),也许也将其作为错误报告给 MS(如果他们愿意的话)算它),以便它在任何更新的版本中得到修复)

就像在另一个答案中提到的,jquery 论坛上的帖子

 if ($.browser.msie) {
      $('#file').replaceWith($('#file').clone());
 } else {
      $('#file').val('');
 }

但是 jquery 现在已经取消了对浏览器测试的支持,jquery.browser。

这个 javascript 解决方案也对我有用,它是jquery.replaceWith方法的香草等价物

document.getElementById("clear").addEventListener("click", function () {
    var fileopen = document.getElementById("fileopen"),
        clone = fileopen.cloneNode(true);

    fileopen.parentNode.replaceChild(clone, fileopen);
}, false);

jsfiddle 上

需要注意的重要一点是cloneNode方法不保留关联的事件处理程序。

请参阅此示例。

document.getElementById("fileopen").addEventListener("change", function () {
    alert("change");
}, false);

document.getElementById("clear").addEventListener("click", function () {
    var fileopen = document.getElementById("fileopen"),
        clone = fileopen.cloneNode(true);

    fileopen.parentNode.replaceChild(clone, fileopen);
}, false);

jsfiddle 上

但是jquery.clone提供了这个[*1]

$("#fileopen").change(function () {
    alert("change");
});

$("#clear").click(function () {
    var fileopen = $("#fileopen"),
        clone = fileopen.clone(true);

    fileopen.replaceWith(clone);
});

jsfiddle 上

[*1]如果事件是由 jquery 的方法添加的,则 jquery 能够做到这一点,因为它在jquery.data 中保留了一个副本,否则它不起作用,所以它有点作弊/变通,意味着事情不是在不同的方法或库之间兼容。

document.getElementById("fileopen").addEventListener("change", function () {
    alert("change");
}, false);

$("#clear").click(function () {
    var fileopen = $("#fileopen"),
        clone = fileopen.clone(true);

    fileopen.replaceWith(clone);
});

jsfiddle 上

您无法直接从元素本身获取附加的事件处理程序。

这是 vanilla javascript 中的一般原则,这就是 jquery 和所有其他库的做法(大致)。

(function () {
    var listeners = [];

    function getListeners(node) {
        var length = listeners.length,
            i = 0,
            result = [],
            listener;

        while (i < length) {
            listener = listeners[i];
            if (listener.node === node) {
                result.push(listener);
            }

            i += 1;
        }

        return result;
    }

    function addEventListener(node, type, handler) {
        listeners.push({
            "node": node,
                "type": type,
                "handler": handler
        });

        node.addEventListener(type, handler, false);
    }

    function cloneNode(node, deep, withEvents) {
        var clone = node.cloneNode(deep),
            attached,
            length,
            evt,
            i = 0;

        if (withEvents) {
            attached = getListeners(node);
            if (attached) {
                length = attached.length;
                while (i < length) {
                    evt = attached[i];
                    addEventListener(clone, evt.type, evt.handler);

                    i += 1;
                }
            }
        }

        return clone;
    }

    addEventListener(document.getElementById("fileopen"), "change", function () {
        alert("change");
    });

    addEventListener(document.getElementById("clear"), "click", function () {
        var fileopen = document.getElementById("fileopen"),
            clone = cloneNode(fileopen, true, true);

        fileopen.parentNode.replaceChild(clone, fileopen);
    });
}());

jsfiddle 上

当然jquery和其他库都有维护这样一个列表所需的所有其他支持方法,这只是一个演示。

出于明显的安全原因,您无法设置文件输入的值,即使设置为空字符串。

您所要做的就是重置该字段所在的表单,或者如果您只想重置包含其他字段的表单的文件输入,请使用以下命令:

function reset_field (e) {
    e.wrap('<form>').parent('form').trigger('reset');
    e.unwrap();
}​

这是一个例子:http : //jsfiddle.net/v2SZJ/1/

这对我有用。

$("#file").replaceWith($("#file").clone());

http://forum.jquery.com/topic/how-to-clear-a-file-input-in-ie

希望能帮助到你。

对我有用!值得注意的是,如果您有任何由文件输入更改触发的事件侦听器,那么您需要在替换输入后重新分配它们。
2021-03-15 07:25:17