在 JavaScript 中,我可以以编程方式为文件输入元素触发“点击”事件吗?

Posted

技术标签:

【中文标题】在 JavaScript 中,我可以以编程方式为文件输入元素触发“点击”事件吗?【英文标题】:In JavaScript can I make a "click" event fire programmatically for a file input element? 【发布时间】:2010-09-17 15:51:27 【问题描述】:

我想以编程方式在 <input type="file"> 标记上触发点击事件。

只是调用 click() 似乎没有任何作用,或者至少它没有弹出文件选择对话框。

我一直在尝试使用侦听器捕获事件并重定向事件,但我无法让它像有人点击它那样实际执行事件。

【问题讨论】:

你触发的点击事件必须在用户发起的点击事件中调用,否则不起作用。 【参考方案1】:

我整天都在寻找解决方案。以下是我得出的结论:

    出于安全原因,Opera 和 Firefox 不允许触发文件输入。 唯一方便的替代方法是创建“隐藏”文件输入(使用不透明度,而不是“隐藏”或“显示:无”!),然后在“下方”创建按钮。通过这种方式,可以看到按钮,但在用户单击时,它实际上会激活文件输入。

希望这会有所帮助! :)

<div style="display: block; width: 100px; height: 20px; overflow: hidden;">
<button style="width: 110px; height: 30px; position: relative; top: -5px; left: -5px;"><a href="javascript: void(0)">Upload File</a></button>
<input type="file" id="upload_input" name="upload" style="font-size: 50px; width: 120px; opacity: 0; filter:alpha(opacity=0);  position: relative; top: -40px;; left: -20px" />
</div>

【讨论】:

这个解决方案效果很好。不知道为什么它被忽视和未升级。这不是*确切的问题要求,但它是一个很好的解决方法。您是否发现它与任何浏览器不兼容?我没有时间去测试所有 10 多种相关的风格。 谢谢你的回答,太棒了:D 不错的解决方案。也适用于安卓移动浏览器。 这不是真的,请参阅下面 Didier 的回复。编程点击必须来自用户操作上下文 - 就像在另一个按钮的点击处理程序中一样。然后它工作正常,不需要溢出元素。 唯一的问题是,如果你想改变悬停时的按钮样式,你不能。这意味着,如果您希望它看起来像您应用中的所有其他按钮,则不能。【参考方案2】:

你不能在所有浏览器中这样做,据说 IE允许,但 Mozilla 和 Opera 不允许。

当您在 GMail 中撰写邮件时,“附加文件”功能在 IE 和任何支持此功能的浏览器中以一种方式实现,然后在 Firefox 和不支持此功能的浏览器中实现另一种方式。

我不知道你为什么不能这样做,但是安全风险的一件事,你在任何浏览器中都不允许这样做,以编程方式设置文件名html 文件元素。

【讨论】:

德拉特。好吧,我当然明白它是可以利用的。这在任何地方都有记录吗?我猜它会被每个浏览器实现? 更新了我的答案,使其比以前的答案更正确 - 要点是相同的,但澄清应该会有所帮助。这家伙遇到了同样的问题:bytes.com/forum/thread542877.html 感谢上帝 FF5 允许此点击 澄清上述评论:Chrome 最近更改以检查文件 input 元素是否可见。如果可以看到元素,则触发 click 方法有效,包括在控制台中。 @Otvazhnii - 老兄,这个答案(你说的是错误的)已经 10 岁了 - 毫不奇怪,它不正确! (我不确定,我相信你的话)。 :P【参考方案3】:

您可以在任何浏览器上触发 click(),但某些浏览器需要元素可见且具有焦点。这是一个 jQuery 示例:

$('#input_element').show();
$('#input_element').focus();
$('#input_element').click();
$('#input_element').hide();

它适用于 click() 之前的 hide,但我不知道如果不调用 show 方法它是否有效。从来没有在 Opera 上试过这个,我在 IE/FF/Safari/Chrome 上测试过,它可以工作。我希望这会有所帮助。

【讨论】:

感谢分享。以防万一您不知道 - 您可以在 jQuery 中使用链接:$(...).show().focus().click().hide(); :) @pimvdb:据我测试,您的解决方案仅适用于 Chrome。 @Hoàng Long:您是指链式解决方案还是 Florin Mogos 的解决方案?我不相信链接会产生任何跨浏览器差异。 @HoàngLong 它适用于 IE 8 和 9、最新的 Chrome、Safari 和 Firefox。 奇怪。正如我测试的那样,它在 Ubuntu 的 Chrome 下不起作用。【参考方案4】:

这是可能的: 在 FF4+、Opera?、Chrome 下: 但是:

    inputElement.click() 应该从用户操作上下文中调用! (不是脚本执行上下文)

    &lt;input type="file" /&gt; 应该是可见的 (inputElement.style.display !== 'none')(你可以用可见性或其他方式隐藏它,但不能使用“显示”属性)

【讨论】:

这为我解决了。我必须将 javascript 添加到 onclick 属性而不是绑定到事件。 支持唯一合理的解决方案。溢出方法很丑。 哈!我知道它必须与上下文有关!我观察到从 keydown 事件(附加文件的快捷方式)中调用 inputElement.click() 有效,但在超时或 ajax 回调中调用它却没有。赞成。 顺便说一句,是否有人在“用户操作上下文”与“脚本执行上下文”上有任何进一步的资源?我在搜索时看到的一切都与执行上下文和this 有关。 :// @bretjonesdev 我认为这意味着它需要在用户启动的事件处理程序(如点击事件处理程序)内部执行,而不是承诺、超时或任何其他非用户启动的事件。跨度> 【参考方案5】:

只需使用标签标签,这样您就可以隐藏输入,并使其通过其相关标签工作 https://developer.mozilla.org/fr/docs/Web/HTML/Element/Label

【讨论】:

这是正确答案,应该推广。 这是正确的答案。所有其他都是漫长而痛苦的黑客攻击。【参考方案6】:

对于那些知道你必须在链接上覆盖一个不可见的表单但又懒得写的人,我为你写了它。好吧,对我来说,但不妨分享。欢迎评论。

HTML(某处):

<a id="fileLink" href="javascript:fileBrowse();" onmouseover="fileMove();">File Browse</a>

HTML(你不关心的地方):

<div id="uploadForm" style="filter:alpha(opacity=0); opacity: 0.0; width: 300px; cursor: pointer;">
    <form method="POST" enctype="multipart/form-data">
        <input type="file" name="file" />
    </form>
</div>

JavaScript:

function pageY(el) 
    var ot = 0;
    while (el && el.offsetParent != el) 
        ot += el.offsetTop ? el.offsetTop : 0;
        el = el.offsetParent;
    
    return ot;


function pageX(el) 
    var ol = 0;
    while (el && el.offsetParent != el) 
        ol += el.offsetLeft ? el.offsetLeft : 0;
        el = el.offsetParent;
    
    return ol;


function fileMove() 
    if (navigator.appName == "Microsoft Internet Explorer") 
        return; // Don't need to do this in IE. 
    
    var link = document.getElementById("fileLink");
    var form = document.getElementById("uploadForm");
    var x = pageX(link);
    var y = pageY(link);
    form.style.position = 'absolute';
    form.style.left = x + 'px';
    form.style.top = y + 'px';


function fileBrowse() 
    // This works in IE only. Doesn't do jack in FF. :( 
    var browseField = document.getElementById("uploadForm").file;
    browseField.click();

【讨论】:

【参考方案7】:

试试这个解决方案:http://code.google.com/p/upload-at-click/

【讨论】:

至少在 IE9 上看起来很丑。【参考方案8】:

如果您希望 click 方法在 Chrome、Firefox 等上工作,请将以下样式应用于您的输入文件。它将被完美隐藏,就像你在做一个display: none;

#fileInput 
    visibility: hidden;
    position: absolute;
    top: 0;
    left: -5000px;

就这么简单,我测试了它有效!

【讨论】:

我最喜欢这种方式,因为如果 inputElement.click() 被隐藏,一些较旧的浏览器不会对它执行任何操作。 为什么不直接将heightwidth 设置为0【参考方案9】:
$(document).one('mousemove', function()  $(element).trigger('click')  );

当我遇到类似问题时为我工作,这是一个普通的 eRube Goldberg。

【讨论】:

【参考方案10】:

工作解决方案

让我在这篇旧文章中补充一下,我曾经使用的一个可行的解决方案,可能适用于所有新旧浏览器的 80% 或更多。

解决方案既复杂又简单。第一步是使用 CSS 并使用“底层元素”来显示输入文件类型,因为它的不透明度为 0。下一步是使用 JavaScript 根据需要更新其标签。

HTML 如果您想快速访问特定元素,只需插入 ID,但是类是必须的,因为它们与设置此元素的 CSS 相关整个过程向上

<div class="file-input wrapper">
    <input id="inpFile0" type="file" class="file-input control" />
    <div class="file-input content">
        <label id="inpFileOutput0" for="inpFileButton" class="file-input output">Click Here</label>
        <input id="inpFileButton0" type="button" class="file-input button" value="Select File" />
    </div>
</div>

CSS 请记住,颜色和字体样式等完全是你的偏好,如果你使用这个基本的 CSS,你可以随时使用尾部标记来随意设置样式,这是显示在末尾列出的 jsFiddle 中。

.file-test-area 
    border: 1px solid;
    margin: .5em;
    padding: 1em;

.file-input 
    cursor: pointer !important;

.file-input * 
    cursor: pointer !important;
    display: inline-block;

.file-input.wrapper 
    display: inline-block;
    font-size: 14px;
    height: auto;
    overflow: hidden;
    position: relative;
    width: auto;

.file-input.control 
    -moz-opacity:0 ;
    filter:alpha(opacity: 0);
    opacity: 0;

    height: 100%;
    position: absolute;
    text-align: right;
    width: 100%;
    z-index: 2;

.file-input.content 
    position: relative;
    top: 0px;
    left: 0px;
    z-index: 1;

.file-input.output 
    background-color: #FFC;
    font-size: .8em;
    padding: .2em .2em .2em .4em;
    text-align: center;
    width: 10em;

.file-input.button 
    border: none;
    font-weight: bold;
    margin-left: .25em;
    padding: 0 .25em;

JavaScript 纯粹而真实,但是,一些较旧(已退役)的浏览器可能仍然存在问题(例如 Netscrape 2!)

var inp = document.getElementsByTagName('input');
for (var i=0;i<inp.length;i++) 
    if (inp[i].type != 'file') continue;
    inp[i].relatedElement = inp[i].parentNode.getElementsByTagName('label')[0];
    inp[i].onchange /*= inp[i].onmouseout*/ = function () 
        this.relatedElement.innerHTML = this.value;
    ;
;

Working jsFiddle Example

【讨论】:

【参考方案11】:

有效:

出于 Firefox 和 Opera 的安全原因,您不能触发文件输入点击,但您可以使用 MouseEvents 进行模拟:

<script>
click=function(element)
    if(element!=null)
        try element.click();
        catch(e) 
            var evt = document.createEvent("MouseEvents");
            evt.initMouseEvent("click",true,true,window,0,0,0,0,0,false,false,false,false,0,null);
            element.dispatchEvent(evt);
            
        
    ;
</script>

<input type="button" value="upload" onclick="click(document.getElementById('inputFile'));"><input type="file" id="inputFile" style="display:none">

【讨论】:

请注意,createEvent()initMouseEvent() 现在已弃用。【参考方案12】:

我知道这已经过时了,所有这些解决方案都是围绕浏览器安全预防措施的黑客攻击,具有真正的价值。

也就是说,截至今天,fileInput.click() 在当前的 Chrome (36.0.1985.125 m) 和当前的 Firefox ESR (24.7.0) 中有效,但在当前的 IE (11.0.9600.17207) 中无效。在按钮顶部覆盖不透明度为 0 的文件字段是可行的,但我想要一个链接元素作为可见触发器,并且悬停下划线在任何浏览器中都不起作用。它闪烁然后消失,可能是浏览器在考虑悬停样式是否真的适用。

但我确实找到了适用于所有这些浏览器的解决方案。我不会声称已经测试了每个浏览器的每个版本,或者我知道它会永远继续工作,但它现在似乎满足了我的需求。

很简单:将文件输入字段置于屏幕外(位置:绝对;顶部:-5000px),在其周围放置一个标签元素,然后触发对标签的点击,而不是文件字段本身。

请注意,链接确实需要编写脚本才能调用标签的 click 方法,它不会自动执行此操作,例如单击标签元素内的文本时。显然,链接元素捕获了点击,但它并没有到达标签。

另请注意,这不提供显示当前选定文件的方法,因为该字段不在屏幕上。我想在选择文件后立即提交,所以这对我来说不是问题,但如果您的情况不同,您将需要一种稍微不同的方法。

【讨论】:

好的,在按钮标签上,onclick="filetag.click()" 不适用于 IE 9 和 10(但适用于 IE 11、Firefox 4/10/26/27/28、Chrome /铬 31/32/33/36、Safari 7、Opera 23)。但是,如果您使用标签 for="id-of-file-input"(没有 onlick),它适用于 IE 9/10/11。【参考方案13】:

JS 小提琴:http://jsfiddle.net/eyedean/1bw357kw/

popFileSelector = function() 
    var el = document.getElementById("fileElem");
    if (el) 
        el.click();  
    
;

window.popRightAway = function() 
    document.getElementById('log').innerHTML += 'I am right away!<br />';
    popFileSelector();
;

window.popWithDelay = function() 
    document.getElementById('log').innerHTML += 'I am gonna delay!<br />';
    window.setTimeout(function() 
        document.getElementById('log').innerHTML += 'I was delayed!<br />';
        popFileSelector();
    , 1000);
;
<body>
  <form>
      <input type="file" id="fileElem" multiple accept="image/*" style="display:none" onchange="handleFiles(this.files)" />
  </form>
  <a onclick="popRightAway()" href="#">Pop Now</a>
    <br />
  <a onclick="popWithDelay()" href="#">Pop With 1 Second Delay</a>
    <div id="log">Log: <br /></div>
</body>

【讨论】:

延迟方法在 safari 中不起作用 另一个完整的例子codepen.io/damiencuvillier/pen/eYRQmjz【参考方案14】:

此代码对我有用。这是你想要做的吗?

<input type="file" style="position:absolute;left:-999px;" id="fileinput" />
<button  id="addfiles" >Add files</button>

<script language="javascript" type="text/javascript">
   $("#addfiles").click(function()
      $("#fileinput").click();
   );
</script>

【讨论】:

【参考方案15】:

我的 Safari 使用 jQuery 和 jQuery-ui 的解决方案:

$("<input type='file' class='ui-helper-hidden-accessible' />").appendTo("body").focus().trigger('click');

【讨论】:

注意:不适用于 firefox 33、chrome 38。 trigger('click') 只能在用户交互事件上下文 - 事件处理程序中工作。【参考方案16】:

这里是这个问题的纯 JavaScript 解决方案。适用于所有浏览器

<script>
    function upload_image_init()
        var elem = document.getElementById('file');
        if(elem && document.createEvent) 
           var evt = document.createEvent("MouseEvents");
           evt.initEvent("click", true, false);
           elem.dispatchEvent(evt);
        
    
</script>

【讨论】:

【参考方案17】:

有一些方法可以将事件重定向到控件,但不要期望自己能够轻松地将事件触发到火控,因为浏览器会出于(良好的)安全原因尝试阻止它。

如果您只需要在用户单击某些内容时显示文件对话框,假设因为您想要更好看的文件上传按钮,那么您可能需要查看what Shaun Inman came up with。

我已经能够通过在 keydown、keypress 和 keyup 事件之间创造性地将焦点移入和移出控制来实现键盘触发。 YMMV。

我真诚的建议是不要管它,因为这是一个浏览器不兼容的痛苦世界。较小的浏览器更新也可能会在没有警告的情况下阻止技巧,您可能必须不断重新发明黑客以使其正常工作。

【讨论】:

【参考方案18】:

我不久前正在研究这个问题,因为我想创建一个自定义按钮来打开文件对话框并立即开始上传。我刚刚注意到一些可能使这成为可能的东西 - 当您单击上传的任意位置时,firefox 似乎会打开对话框。所以以下可能会这样做:

    创建文件上传和包含要用作按钮的图像的单独元素 将它们重叠排列并使文件元素背景和边框透明,因此按钮是唯一可见的东西 添加 javascript 以使 IE 在单击按钮/文件输入时打开对话框 选择文件时使用 onchange 事件提交表单

这只是理论上的,因为我已经使用了另一种方法来解决问题,但它可能会起作用。

【讨论】:

【参考方案19】:

我有一个 &lt;input type="button"&gt; 隐藏在视图之外的标签。我所做的是将"onClick" 事件附加到任何类型的任何可见组件,例如标签。这是使用 Google Chrome 的开发者工具或 Mozilla Firefox 的 Firebug 使用右键单击“编辑 HTML”命令来完成的。在这种情况下,请指定以下脚本或类似内容:

如果你有 JQuery:

$('#id_of_component').click();

如果没有:

document.getElementById('id_of_component').click();

谢谢。

【讨论】:

【参考方案20】:

嘿,这个解决方案有效。 对于下载,我们应该使用 MSBLOB

$scope.getSingleInvoicePDF = function(invoiceNumberEntity) 
   var fileName = invoiceNumberEntity + ".pdf";
   var pdfDownload = document.createElement("a");
   document.body.appendChild(pdfDownload);

   AngularWebService.getFileWithSuffix("ezbillpdfget",invoiceNumberEntity,"pdf" ).then(function(returnedJSON) 
       var fileBlob = new Blob([returnedJSON.data], type: 'application/pdf');
       if (navigator.appVersion.toString().indexOf('.NET') > 0)  // for IE browser
           window.navigator.msSaveBlob(fileBlob, fileName);
        else  // for other browsers
           var fileURL = window.URL.createObjectURL(fileBlob);
           pdfDownload.href = fileURL;
           pdfDownload.download = fileName;
           pdfDownload.click();      
       
   );
;

对于 AngularJS 甚至对于普通的 javascript。

【讨论】:

【参考方案21】:

这在 Firefox 4 中现在是可能的,但需要注意的是它被视为一个弹出窗口,因此只要有弹出窗口就会被阻止。

【讨论】:

其实firefox4改善了很多文件上传的状态。我的麻烦是如何在 Google Chrome 浏览器中做同样的事情。【参考方案22】:

这是对我有用的解决方案: CSS:

#uploadtruefield 
    left: 225px;
    opacity: 0;
    position: absolute;
    right: 0;
    top: 266px;
    opacity:0;
    -moz-opacity:0;
    filter:alpha(opacity:0);
    width: 270px;
    z-index: 2;


.uploadmask 
    background:url(../img/browse.gif) no-repeat 100% 50%;

#uploadmaskfield
    width:132px;

带有“小”JQuery 帮助的 HTML:

<div class="uploadmask">
    <input id="uploadmaskfield" type="text" name="uploadmaskfield">
</div>
<input id="uploadtruefield"  type="file" onchange="$('#uploadmaskfield').val(this.value)" >

请确保真正的上传字段完全覆盖了 maskfied。

【讨论】:

【参考方案23】:

您可以按照Open File Dialog box on <a> tag 的回答执行此操作

<input type="file" id="upload" name="upload" style="visibility: hidden; width: 1px;     height: 1px" multiple />
<a href="" onclick="document.getElementById('upload').click(); return false">Upload</a>

【讨论】:

【参考方案24】:

我发现如果 input(file) 在表单之外,那么触发点击事件会调用文件对话框。

【讨论】:

【参考方案25】:

希望这对某人有所帮助 - 我花了 2 个小时来敲敲它:

在 IE8 或 IE9 中,如果您以任何方式触发使用 javascript 打开文件输入(相信我,我已经尝试过所有这些),它不会让您使用 javascript 提交表单,它只会默默地失败.

通过常规提交按钮提交表单可能有效,但调用 form.submit();会默默地失败。

我不得不求助于用透明的文件输入覆盖我的选择文件按钮。

【讨论】:

此外,您可以将文件输入包装在标签中,以便在 IE 中您可以获得标签的可点击区域以覆盖整个按钮区域,而仅使用文件输入标签,只有一半是可点击的在 IE 中。【参考方案26】:

这对我有用:

<script>
    function sel_file() 
        $("input[name=userfile]").trigger('click');
      
</script>

<input type="file" name="userfile" id="userfile" />

<a href="javascript:sel_file();">Click</a>

【讨论】:

【参考方案27】:

这并非不可能:

var evObj = document.createEvent('MouseEvents');
evObj.initMouseEvent('click', true, true, window);  
setTimeout(function() document.getElementById('input_field_id').dispatchEvent(evObj); ,100);

但不知何故,它只有在通过点击事件调用的函数中才有效。

所以你可能有以下设置:

html:

<div onclick="openFileChooser()" class="some_fancy_stuff">Click here to open image chooser</div>
<input type="file" id="input_img">

JavaScript:

    function openFileChooser() 
      var evObj = document.createEvent('MouseEvents');
      evObj.initMouseEvent('click', true, true, window);  
      setTimeout(function()
       
        document.getElementById('input_img').dispatchEvent(evObj);      
      ,100);      
    

【讨论】:

createEvent()initMouseEvent() 已弃用。你现在必须使用CustomEvent()...【参考方案28】:

你可以使用

<button id="file">select file</button>
<input type="file" name="file" id="file_input" style="display:none;">
<script>
$('#file').click(function() 
        $('#file_input').focus().trigger('click');
    );
</script>

【讨论】:

【参考方案29】:

为此,您可以单击文件输入上方的不可见的传递元素:

function simulateFileClick() 
  const div = document.createElement("div")
  div.style.visibility = "hidden"
  div.style.position = "absolute"
  div.style.width = "100%"
  div.style.height = "100%"
  div.style.pointerEvents = "none"
  const fileInput = document.getElementById("fileInput") // or whatever selector you like
  fileInput.style.position = "relative"
  fileInput.appendChild(div)
  const mouseEvent = new MouseEvent("click")
  div.dispatchEvent(mouseEvent)

【讨论】:

以上是关于在 JavaScript 中,我可以以编程方式为文件输入元素触发“点击”事件吗?的主要内容,如果未能解决你的问题,请参考以下文章

如何以编程方式监控 Web 浏览器中的 JavaScript 执行?

以编程方式控制 Javascript 中的断点?

如何以编程方式创建用户可以下载的 Javascript 客户端文件? [复制]

使用 Javascript 以编程方式取消标记 FB 照片

以编程方式刷新网页 - javascript [重复]

使用 JavaScript 以编程方式编写 html [关闭]