Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Workaround for file input label click (Firefox)

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

In Firefox 7 it is not possible to trigger 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?

like image 582
Mårten Wikström Avatar asked Oct 12 '11 15:10

Mårten Wikström


6 Answers

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

like image 64
Octavioamu Avatar answered Oct 05 '22 10:10

Octavioamu


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.
like image 38
Corey Innis Avatar answered Oct 05 '22 10:10

Corey Innis


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>
like image 39
Mårten Wikström Avatar answered Oct 05 '22 11:10

Mårten Wikström


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.

like image 23
James Lai Avatar answered Oct 05 '22 10:10

James Lai


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.

like image 28
Michal Chruszcz Avatar answered Oct 05 '22 12:10

Michal Chruszcz


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.

like image 32
tete_d_acier Avatar answered Oct 05 '22 10:10

tete_d_acier