JSFiddle - React, Tailwind, and code Playground

by djibouti33

HTML

<form id="uploader-form" action="http://hotblocks.nl/_http_server.php">
    <label for="fileinput" id="link" class="trigger-file-input">Link Label</label>
    <br />
    <label for="fileinput" id="button" class="trigger-file-input">Button Label</label>
    <input type="file" id="fileinput" />
</form>

CSS

body { font-family: Helvetica; }

/* hide the file input. important to position it offscreen as opposed display:none. some browsers don't like that */
#fileinput { position: absolute; left: -9999em; }

/* an example of styling your label to look/behave like a link */
#link { color: #2a9dcf; font-size: 16px; }
#link:hover { text-decoration: underline; cursor: pointer; }

/* an example of styling your label to look like a button */
#button {
    display: block;
    width: 31px;
    height: 27px;
    text-indent: -9999em;
    background: transparent url(http://www.afar.com/assets/profile_sprite.png) 0 0 no-repeat;
}

#button:hover {
    cursor: pointer;
}

JavaScript

/* 

The Goals:
 1) allow user to upload a file by using standard html file input control
 2) hide standard html file input control and apply own styling
 3) after user selects file to upload, automatically submit the form

The Browsers:
 - Firefox, Chrome, IE8/9, Safari
 - IE7 didn't work, but it might if you add that browser to the workaround detailed at the bottom

The Initial Solution
 1) Hide the file input by positioning it offscreen. Important not to display:none as some browsers won't like this.
 2) Add another styled element to the page (link, button). 
 3) Listen for a click on that element, then programmatically send a click to the file input to trigger the native 'file explorer'
 4) Listen for the file input's onchange event (occurs after a user chooses their file) 
 5) Submit the form

The Problem:
 1) IE: if you programmatically send a click to a file input in order to activate it (2), programmatically submitting the form (5) will throw a security error

The Workaround Solution
 1) Same as above
 2) Take advantage of the accessibility features built in to the <label> tag (clicking on a label will activate it's associated control) by styling 
    a <label> tag instead of a link/button
 3) Listen for the file input's onchange event
 4) Submit the form
 5) For some reason Mozilla browsers won't activate a file input by clicking on it's <label>. For Mozilla, listen for the click on the label and send a click
    event to the file input to activate it.

*/

// after the user selects the file they want to upload, submit the form
$('#fileinput').on("change", function() {
    $('#uploader-form').submit();
});


// mozilla won't focus a file input with the click of a corresponding
// label, but all other browsers do. if we detect mozilla, listen for
// the label click and send a click to the file input programmatically
if($.browser.mozilla) {
    $('.trigger-file-input').click(function() {
      $('#fileinput').click();                             
    });
}