文件输入标签点击的解决方法(Firefox)

时间:2011-10-12 15:11:22

标签: html firefox file-upload label

<label for="input">Label</label><input type="file" id="input"/>

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

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

有什么想法吗?

10 个答案:

答案 0 :(得分:22)

谢谢你这个q&amp; a ...帮帮我。

@ 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,允许初次点击<em>

    <label for="field">click <em>here</em></label>
    
  • 使用label元素的control属性来实现更清晰,更简单的基于规范的表单字段关联。

答案 1 :(得分: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>

答案 2 :(得分:1)

使用jQuery浏览器检测时出现了一些问题,最明显的是使用浏览器检测而非功能检测的反模式,以及1.9+不提供该功能的事实。

那么,或许,我得到的解决方案有点虚伪,但它运作良好,似乎坚持今天最好的做法。

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

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

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

答案 3 :(得分:1)

click() event可以在所有浏览器中触发文件选择对话框。这个问题的一个不引人注目的解决方案可能是这样的:

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

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

我在Chrome 25,Firefox 19和IE 9中进行过测试,效果很好。

答案 4 :(得分:1)

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

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

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

这很难看,但是一旦FF版本消失,这个修复程序就会被删除。

答案 5 :(得分:0)

如果需要,您可以将事件从任何事件调度到type = file输入 输入display:none和visibility:hidden,然后从中调度事件, 比如,点击图像......

<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>

答案 6 :(得分:0)

当您不需要/想要输入框(如图片上传)时,要在元素中使用opacity: 0并在标签中使用pointer-events: none;。 该解决方案实际上是针对特定设计的,但也许应该适合那些参与其中的人。 (直到现在这个bug还没有修复)

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

答案 7 :(得分:0)

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>
        </>
    );
};

答案 8 :(得分:-1)

反转标签和输入元素的顺序。嘿,把标签元素放在输入元素之后。

答案 9 :(得分:-1)

试试此代码

<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>