【发布时间】:2010-11-05 20:23:09
【问题描述】:
是否可以使用 jQuery 清除 <input type='file' /> 控件值?我尝试了以下方法:
$('#control').attr({ value: '' });
但它不起作用。
【问题讨论】:
标签: javascript jquery html file-io forms
是否可以使用 jQuery 清除 <input type='file' /> 控件值?我尝试了以下方法:
$('#control').attr({ value: '' });
但它不起作用。
【问题讨论】:
标签: javascript jquery html file-io forms
快速回答:替换它。
在下面的代码中,我使用replaceWith jQuery 方法将控件替换为自身的克隆。如果您有任何处理程序绑定到此控件上的事件,我们也希望保留这些处理程序。为此,我们传入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);
这样可以避免在刷新控件时将任何处理程序与元素一起克隆。
【讨论】:
文件输入的值是只读的(出于安全原因)。您不能以编程方式将其置空(除了调用表单的 reset() 方法,它的范围比该字段更广泛)。
【讨论】:
在 IE8 中,为了安全起见,他们将文件上传字段设为只读。见IE team blog post:
从历史上看,HTML 文件上传控件 () 一直是大量信息泄露漏洞的来源。为了解决这些问题,对控件的行为进行了两项更改。
为了阻止依靠“窃取”击键来暗中诱骗用户在控件中键入本地文件路径的攻击,文件路径编辑框现在是只读的。用户必须使用“文件浏览”对话框明确选择要上传的文件。
此外,“上传文件时包括本地目录路径”URLAction 已针对 Internet 区域设置为“禁用”。此更改可防止潜在敏感的本地文件系统信息泄露到 Internet。例如,Internet Explorer 8 现在将仅提交文件名 image.png,而不是提交完整路径 C:\users\ericlaw\documents\secret\image.png。
【讨论】:
什么? 在您的验证功能中,只需输入
document.onlyform.upload.value="";
假设上传的是名字:
<input type="file" name="upload" id="csv_doc"/>
我正在使用 JSP,不确定这是否会有所不同...
对我有用,而且我认为它更容易。
【讨论】:
$("input[type=file]").wrap("<div id='fileWrapper'/>");
$("#fileWrapper").append("<div id='duplicateFile' style='display:none'>"+$("#fileWrapper").html()+"</div>");
$("#fileWrapper").html($("#duplicateFile").html());
【讨论】:
这适用于 Chrome、FF 和 Safari
$("#control").val("")
可能不适用于 IE 或 Opera
【讨论】:
很容易哈哈(适用于所有浏览器[除了歌剧]):
$('input[type=file]').each(function(){
$(this).after($(this).clone(true)).remove();
});
JS 小提琴:http://jsfiddle.net/cw84x/1/
【讨论】:
我最终得到了这个:
if($.browser.msie || $.browser.webkit){
// doesn't work with opera and FF
$(this).after($(this).clone(true)).remove();
}else{
this.setAttribute('type', 'text');
this.setAttribute('type', 'file');
}
可能不是最优雅的解决方案,但据我所知,它确实有效。
【讨论】:
.clone() 的东西在 Opera(可能还有其他)中不工作。它保留内容。
对我来说最接近的方法是 Jonathan 的早期方法,但在我的情况下,确保字段保留其名称、类等会导致代码混乱。
这样的事情可能会很好用(也感谢 Quentin):
function clearInput($source) {
var $form = $('<form>')
var $targ = $source.clone().appendTo($form)
$form[0].reset()
$source.replaceWith($targ)
}
【讨论】:
简单:您将<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>
正如 Timo 在下面指出的,如果您有用于触发 <form> 内的字段重置的按钮,则必须在事件上调用 .preventDefault() 以防止 <button> 触发提交。
由于未修复的错误,无法在 IE 11 中运行。输入中的文本(文件名)被清除,但其File 列表仍然填充。
【讨论】:
reset() 重命名为例如。 reset2(),因为至少在 Chrome 中,如果是 reset(),所有字段都会被清除。并在清除调用后添加 event.preventDefault() 以防止提交。这样:<button onclick="reset2($('#file'));event.preventDefault()">Reset file</button>。工作示例:jsfiddle.net/rPaZQ/23.
resetFormElement 并添加了一条注释,说明您应该在按钮 onclick 上防止Default()。
get(0) 未定义),我不得不做.wrap('<form></form>'),无论如何都按照 jQuery 文档的建议。
我使用过https://github.com/malsup/form/blob/master/jquery.form.js,它有一个名为clearInputs() 的函数,它是跨浏览器,经过良好测试,易于使用,还可以处理IE 问题和需要时清除隐藏字段。可能只清除文件输入的解决方案有点长,但是如果您正在处理跨浏览器文件上传,那么建议使用此解决方案。
使用简单:
// 清除所有文件字段: $("输入:文件").clearInputs(); // 清除隐藏字段: $("输入:文件").clearInputs(true); // 清除特定字段: $("#myfilefield1,#myfilefield2").clearInputs(); /** * 清除选中的表单元素。 */ $.fn.clearFields = $.fn.clearInputs = function(includeHidden) { var re = /^(?:color|date|datetime|email|month|number|password|range|search|tel|text|time|url|week)$/i; // 'hidden' 不在此列表中 返回 this.each(function() { var t = this.type, tag = this.tagName.toLowerCase(); if (re.test(t) || tag == 'textarea') { this.value = ''; } else if (t == 'checkbox' || t == 'radio') { this.checked = false; } 否则 if (tag == 'select') { this.selectedIndex = -1; } 否则如果(t ==“文件”){ if (/MSIE/.test(navigator.userAgent)) { $(this).replaceWith($(this).clone(true)); } 别的 { $(this).val(''); } } 否则如果(包括隐藏){ // includeHidden 可以是真值,也可以是选择器字符串 // 表示特殊测试;例如: // $('#myForm').clearForm('.special:hidden') // 以上将清除具有“特殊”类的隐藏输入 if ( (includeHidden === true && /hidden/.test(t)) || (typeof includeHidden == 'string' && $(this).is(includeHidden)) ) this.value = ''; } }); };【讨论】:
使其异步,并在完成按钮所需的操作后将其重置。
<!-- Html Markup --->
<input id="btn" type="file" value="Button" onchange="function()" />
<script>
//Function
function function(e) {
//input your coding here
//Reset
var controlInput = $("#btn");
controlInput.replaceWith(controlInput = controlInput.val('').clone(true));
}
</script>
【讨论】:
这对我有用。
$("#file").replaceWith($("#file").clone());
http://forum.jquery.com/topic/how-to-clear-a-file-input-in-ie
希望对你有帮助。
【讨论】:
Jquery 应该为您处理跨浏览器/旧浏览器的问题。
这适用于我测试过的现代浏览器:Chromium v25、Firefox v20、Opera v12.14
使用 jquery 1.9.1
HTML
<input id="fileopen" type="file" value="" />
<button id="clear">Clear</button>
jQuery
$("#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 forum 上的帖子
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
您不能直接从元素本身获取附加的事件处理程序。
这是原版 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/
【讨论】:
我尝试了用户提到的大多数技术,但它们都不能在所有浏览器中使用。即:clone() 在 FF 中不适用于文件输入。 我最终手动复制了文件输入,然后用复制的文件替换了原始文件。它适用于所有浏览器。
<input type="file" id="fileID" class="aClass" name="aName"/>
var $fileInput=$("#fileID");
var $fileCopy=$("<input type='file' class='"+$fileInput.attr("class")+" id='fileID' name='"+$fileInput.attr("name")+"'/>");
$fileInput.replaceWith($fileCopy);
【讨论】:
我被这里的所有选项卡住了。这是我制作的一个 hack:
<form>
<input type="file">
<button type="reset" id="file_reset" style="display:none">
</form>
您可以使用 jQuery 触发重置,代码类似于:
$('#file_reset').trigger('click');
(jsfiddle:http://jsfiddle.net/eCbd6/)
【讨论】:
我能够让我使用以下代码:
var input = $("#control");
input.replaceWith(input.val('').clone(true));
【讨论】:
我已经设法使用以下方法使其工作......
function resetFileElement(ele)
{
ele.val('');
ele.wrap('<form>').parent('form').trigger('reset');
ele.unwrap();
ele.prop('files')[0] = null;
ele.replaceWith(ele.clone());
}
已在 IE10、FF、Chrome 和 Opera 中测试。
有两个注意事项...
在 FF 中仍然无法正常工作,如果刷新页面,文件元素会重新填充所选文件。从哪里获取这些信息超出了我的范围。我还可以尝试清除与文件输入元素相关的哪些内容?
请记住对附加到文件输入元素的任何事件使用委托,以便在进行克隆时它们仍然有效。
我不明白,到底谁认为不允许您从无效的不可接受的文件选择中清除输入字段是个好主意?
好的,不要让我用值动态设置它,这样我就不能从用户的操作系统中提取文件,但是让我在不重置整个表单的情况下清除无效的选择。
无论如何,“接受”除了过滤器之外什么都不做,而且在 IE10 中,它甚至不理解 MS Word 的 mime 类型,这是个笑话!
【讨论】:
.pop(),而不是将其设置为 null。这似乎可以正确清除文件。
在我的 Firefox 40.0.3 上只能使用这个
$('input[type=file]').val('');
$('input[type=file]').replaceWith($('input[type=file]').clone(true));
【讨论】:
$("#control").val('') 就是你所需要的!使用 JQuery 1.11 在 Chrome 上测试
其他用户也在 Firefox 中进行了测试。
【讨论】:
它适用于所有浏览器。
var input = $(this);
var next = this.nextSibling;
var parent = input.parent();
var form = $("<form></form>");
form.append(input);
form[0].reset();
if (next) {
$(next).before(input);
} else {
parent.append(input);
}
【讨论】:
我一直在寻找简单而干净的方法来清除 HTML 文件输入,上面的答案很棒,但没有一个能真正回答我正在寻找的东西,直到我在网上遇到了一种简单而优雅的方法去做吧:
var $input = $("#control");
$input.replaceWith($input.val('').clone(true));
所有功劳归Chris Coyier。
// Referneces
var control = $("#control"),
clearBn = $("#clear");
// Setup the clear functionality
clearBn.on("click", function(){
control.replaceWith( control.val('').clone( true ) );
});
// Some bound handlers to preserve when cloning
control.on({
change: function(){ console.log( "Changed" ) },
focus: function(){ console.log( "Focus" ) }
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<input type="file" id="control">
<br><br>
<a href="#" id="clear">Clear</a>
【讨论】:
你可以像这样用它的克隆替换它
var clone = $('#control').clone();
$('#control').replacewith(clone);
但是这个克隆也有它的价值,所以你最好这样
var emtyValue = $('#control').val('');
var clone = emptyValue.clone();
$('#control').replacewith(clone);
【讨论】:
function clear() {
var input = document.createElement("input");
input.setAttribute('type', 'file');
input.setAttribute('value', '');
input.setAttribute('id', 'email_attach');
$('#email_attach').replaceWith( input.cloneNode() );
}
【讨论】:
它对我不起作用:
$('#Attachment').replaceWith($(this).clone());
or
$('#Attachment').replaceWith($('#Attachment').clone());
所以在 asp mvc 中我使用 razor 特性来替换文件输入。 首先为具有 Id 和 Name 的输入字符串创建一个变量,然后将其用于在页面中显示并在重置按钮单击时替换:
@{
var attachmentInput = Html.TextBoxFor(c => c.Attachment, new { type = "file" });
}
@attachmentInput
<button type="button" onclick="$('#@(Html.IdFor(p => p.Attachment))').replaceWith('@(attachmentInput)');">--</button>
【讨论】:
一种简单的方法是更改输入类型并再次更改。
类似这样的:
var input = $('#attachments');
input.prop('type', 'text');
input.prop('type', 'file')
【讨论】: