【问题标题】:Workaround for file input label click (Firefox)文件输入标签单击的解决方法 (Firefox)
【发布时间】:2011-12-06 05:40:26
【问题描述】:
<label for="input">Label</label><input type="file" id="input"/>

在 Firefox 7 中,无法通过单击标签来触发打开文件对话框。

This SO question 非常相似,但是用绿色检查 这是 FF 中的错误。我正在寻找解决方法。

有什么想法吗?

【问题讨论】:

  • 在 FF.4 på Ubuntu-maskin 下的 Kan jutillägga att det inte fungerar ... 可以补充一点,它甚至在 Ubuntu 下的 FF.4 中也不起作用。
  • @maxxie 你能试试我在你的机器上发布的解决方法吗?
  • 注意:这个错误的修复似乎即将发布bugzilla.mozilla.org/show_bug.cgi?id=701353
  • 好消息,这已在 Firefox 23 中得到修复(我已通过最新的开发版本确认),预计将于 2013 年 8 月发布。在此之前,如果您想使用没有迁移插件的最新 jQuery ,你可以使用这个垫片:greatwebguy.com/jquery-2/browser-detection-shim-for-jquery-1-9

标签: html firefox file-upload label


【解决方案1】:

感谢您的问答...帮助了我。

我对@marten-wikstrom 解决方案的变体:

if($.browser.mozilla) {
  $(document).on('click', 'label', function(e) {
    if(e.currentTarget === this && e.target.nodeName !== 'INPUT') {
      $(this.control).click();
    }
  });
}

注释

  • 在任一解决方案中都不需要使用 document.ready ($(function() {...});)。 jQuery.fn.live 在 @marten-wikstrom 的情况下负责处理;在我的示例中显式绑定到 document
  • 使用jQuery.fn.on...当前推荐的绑定技术。
  • 在此处添加了!== 'INPUT' 检查以确保执行不会陷入循环:

    <label>
      <input type="file">
    </label>
    

    (因为文件字段点击会冒泡回到标签)

  • event.target检查更改为event.currentTarget,允许初始点击&lt;em&gt;

    <label for="field">click <em>here</em></label>
    
  • 使用标签元素的control 属性实现更简洁、规范的表单字段关联。

【讨论】:

  • 只是想提供一个更新和我的想法,而不是要成为先生。 knowitall ;) $.browser 自 jquery 1.9 以来已过时。文件上的jquery.on() 有点粗鲁。尝试缩小范围,更接近元素(性能)。或者为什么仍然使用 deligate 变体..? $("label[name=input]").on("click",function() {...}); 也应该能做到这一点..
  • 只是附注:在 jQuery 1.9+ 发布后,如果您包含 jquery.migrate 插件,您只能使用 $.browser.VENDOR。或者使用诸如modernizr之类的东西进行浏览器检测。
  • 请注意,该问题已在 FF 22 中修复,因此脚本会双倍打开文件对话框。我建议了以下脚本更新,但奇怪的是它被审阅者拒绝了,但建议的脚本仍然可以正常工作。 stackoverflow.com/review/suggested-edits/2481980
【解决方案2】:

我想出了一个可行的解决方法:

<script type="text/javascript" src="http://ajax.googleapis.com/ajax/libs/jquery/1.6.4/jquery.min.js"></script>
<script type="text/javascript">
    $(function () {
        $("label").click(function () {
            $("#input").click();
        });
    });
</script>
<label for="input">Label</label><input type="file" id="input"/>

很奇怪,FF 允许您模拟对文件输入的点击。我认为这被认为是一种安全风险......

更新:这是一个通用的解决方法:

<script type="text/javascript">
    $(function () {
        if ($.browser.mozilla) {
            $("label").live("click", function (event) {
                if (event.target == this) {
                    $("#" + $(this).attr("for")).extend($("input", this)).first().click();
                }
            });
        }
    });
</script>

【讨论】:

  • 但我仍然认为它不适用于普通的&lt;label for="input"&gt;........
【解决方案3】:

使用 jQuery 浏览器检测时会出现一些问题,最明显的是使用浏览器检测而不是功能检测的反模式,此外 1.9+ 不提供该功能。

那么,也许我得出的解决方案有点虚伪,但效果很好,并且似乎符合当今大多数最佳实践。

首先,确保您使用的是Paul Irish's conditional classes。然后,使用类似的东西:

  if($("html").hasClass("ie")) {
    $("label").click();
  } else {
    $("input").click();
  }

否则,我发现该事件会在 Chrome 等浏览器中双重触发。这个解决方案看起来很优雅。

【讨论】:

    【解决方案4】:

    click() event 可以在所有浏览器中触发文件选择对话框。这个问题的一个不显眼的解决方案可能如下所示:

    $('label')
        .attr('for', null)
        .click(function() {
            $('#input').click();
        });
    

    删除 for 属性很重要,因为其他浏览器(例如 Chrome、IE)仍会批准它并显示两次对话框。

    我在 Chrome 25、Firefox 19 和 IE 9 中对其进行了测试,效果非常好。

    【讨论】:

      【解决方案5】:

      似乎在 FF 23 中已修复,因此浏览器检测变得危险并导致双系统对话框;(

      您可以添加另一个测试以将修复限制为版本 23 之前的 FF 版本:

      if(parseInt(navigator.buildID,10) < 20130714000000){
        //DO THE FIX
      }
      

      这很丑陋,但是一旦旧版本的 FF 消失,此修复程序就会被删除。

      【讨论】:

        【解决方案6】:

        当您不需要/想要输入框(如图片上传)时,一种解决方法是在元素中使用 opacity: 0 并在标签中使用 pointer-events: none;。 该解决方案确实是特定于设计的,但也许应该适用于遇到此问题的人。 (到现在这个bug还没修复)

        http://codepen.io/octavioamu/pen/ByOQBE

        【讨论】:

          【解决方案7】:

          如果需要,您可以将任何事件中的事件分派到 type=file 输入 使输入显示:无和可见性:隐藏,然后调度事件, 比如说,点击|触摸图像...

          <img id="customImg" src="file.ext"/>
          <input id="fileLoader" type="file" style="display:none;visibility:hidden"/>
          
          <script>
              customImg.addEventListener(customImg.ontouchstart?'touchstart':'click', function(e){
                  var evt = document.createEvent('HTMLEvents');
                  evt.initEvent('click',false,true);
                  fileLoader.dispatchEvent(evt);
              },false);
          </script>
          

          【讨论】:

            【解决方案8】:

            React 环境中使用上面Corey 的答案,我必须执行以下操作:

            (Firefox 检查基于:How to detect Safari, Chrome, IE, Firefox and Opera browser?

            
            const ReactFileInputButton = ({ onClick }) => {
            
                const isFirefox = typeof InstallTrigger !== 'undefined';
            
                const handleClick = isFirefox ? (e) => {
                    e.currentTarget.control.click();
                } : undefined;
            
                const handleFileSelect = (e) => {
                    if (e.target.files && e.target.files[0]) {
                        onClick({ file: e.target.files[0] });
                    }
                }
            
                return (
                    <>
                        <input type="file" id="file" onChange={handleFileSelect} />
                        <label htmlFor="file" onClick={handleClick}>
                            Select file
                        </label>
                    </>
                );
            };
            

            【讨论】:

              【解决方案9】:

              颠倒标签和输入元素的顺序。 iow,把标签元素放在输入元素之后。

              【讨论】:

              • 当我在 Firefox 中单击标签时没有任何反应。即使我将标签元素放在输入元素之后。我错过了什么吗?
              【解决方案10】:

              试试这个代码

              <img id="uploadPreview" style="width: 100px; height: 100px;" 
              onclick="document.getElementById('uploadImage').click(event);" />
              <input id="uploadImage" type="file" name="myPhoto" onchange="PreviewImage();" />
              <script type="text/javascript">
                  function PreviewImage() {
                      var oFReader = new FileReader();
                      oFReader.readAsDataURL(document.getElementById("uploadImage").files[0]);
                      oFReader.onload = function (oFREvent) {
                          document.getElementById("uploadPreview").src = oFREvent.target.result;
                      };
                  };
              </script>
              

              【讨论】:

                猜你喜欢
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 2015-03-13
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                • 1970-01-01
                相关资源
                最近更新 更多