开发者

Workaround for file input label click (Firefox)

开发者 https://www.devze.com 2023-04-12 07:41 出处:网络
<label for=\"input\">Label</label><input type=\"file\" id=\"input\"/> In Firefox 7 it is not possible to trig开发者_Python百科ger the open file dialog by clicking on the label.
<label for="input">Label</label><input type="file" id="input"/>

In Firefox 7 it is not possible to trig开发者_Python百科ger the open file dialog by clicking on the label.

This SO question is very similar but that's green checked with it's a bug in FF. I'm looking for a workaround.

Any ideas?


thank you for this q&a... helped me out.

my variation of @marten-wikstrom's solution:

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

notes

  • using document.ready ($(function() {...});) is unnecessary, in either solution. jQuery.fn.live takes care of that in @marten-wikstrom's case; explicitly binding to document does in my example.
  • using jQuery.fn.on... current recommended binding technique.
  • added the !== 'INPUT' check to ensure execution does not get caught in a loop here:

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

    (since the file field click will bubble back up to the label)

  • change event.target check to event.currentTarget, allowing for initial click on the <em> in:

    <label for="field">click <em>here</em></label>
    
  • using the label element's control attribute for cleaner, simpler, spec-base form field association.


I came up with a feasible workaround:

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

Quite strange that FF allows you to simulate a click on a file input. I thought that was considered a security risk...

UPDATE: This is a generic workaround:

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


A couple problems arise when using the jQuery browser detection, most notably the anti-pattern of using browser detection rather than feature detection, in addition to the fact that 1.9+ doesn't provide that functionality.

Perhaps, then, the solution I arrived at is a bit hypocritical, but it worked well and seems to adhere to most best practices today.

First, ensure you're using Paul Irish's conditional classes. Then, use something like:

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

Otherwise, I found the event would be double-fired in browsers such as Chrome. This solution seemed elegant enough.


The file-selection dialog can be triggered in all browsers by the click() event. An unobtrusive solution to this problem could look like that:

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

Removing the for attribute is important since other browsers (e.g. Chrome, IE) will still ratify it and show the dialog twice.

I tested it in Chrome 25, Firefox 19 and IE 9 and works like a charm.


It seems to be fixed in FF 23, so browser detection becomes hazardous and leads to double system dialogs ;(

You can add another test to restrict the fix to FF version prior to version 23:

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

It's quite ugly, but this fix will be removed as soon as old the version of FF will have disappeared.


A work around when you don't need/want to have the input box (like image upload) is to use opacity: 0 in the element and use pointer-events: none; in the label. The solution is really design specific but maybe should work for someone who comes to this. (until now the bug doesn't been fixed)

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


you can dispatch the event from any event to the type=file input if you want make the input display:none and visibility:hidden, and then dispatch the event from, say, the click|touch of an image ...

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


Using the answer of Corey above in a React environment I had to do the following:

(Firefox check is based on: 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>
        </>
    );
};


Reverse the order of the label and input elements. iow, put the label element after the input element.


Try this code

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

精彩评论

暂无评论...
验证码 换一张
取 消

关注公众号