1
\$\begingroup\$

I've been working on a solution to replace the HTML input file element with a custom styled button.

jsFiddle: https://jsfiddle.net/Lau1989/4jLz04pc/5/

  1. First route the click event to the actual file input

    //route click event on styled button to the actual file input
    button.addEventListener('click', function() {
        input.click();
    }, false);
    
  2. Then replace the full/fake path of the file to display only the file name and its extension

    //display the name of the selected file
    input.addEventListener('change', function() {
        console.log('val', input.value);
        //Remove the full/fake path to display only the file name
        var file_name = input.value.replace(/[A-Za-z]:\\fakepath\\/i, '');
        output.innerText = file_name;
    }, false);
    

Although this code works so far on all tested browsers, I have no idea if it really should be used in production in terms of security or cross-browser compatibility.

Is there any downside to this approach I don't see yet ? If so, what would be a better approach to do this ?

\$\endgroup\$
1
\$\begingroup\$

Your question

Is there any downside to this approach I don't see yet ? If so, what would be a better approach to do this ?

I don't really think there is a downside to this approach. Below I outline an alternative approach to updating the text - it may not necessarily be better but possibly more robust.

Feedback

This looks like a good approach - who needs the fakepath anyway??

I tested this code in Windows 10 Chrome, Firefox and Opera; Safari on Mac OS X, as well as FIrefox on Linux Mint. It appears to work in all except in Firefox on Linux Mint, where the output <span> tag text was not updated correctly. I was able to update the code to use Element.innerHTML for setting the HTML correctly.

Alternative approach

An alternate approach is to use String.split() on the file input value, splitting on \, then use Array.pop() to get the last item in the array. Expand the snippet below to see it in action.

In theory, this alternate approach should be quicker because it just uses string splitting and array access instead of a regular expression replacement... Here is a jsPerf test - so far it seems it is quicker to use the split() technique in FF and Edge on Windows but not Chrome...

var input = document.getElementById('input'),
  button = document.getElementById('button'),
  output = document.getElementById('output');

//route click event on styled button to the actual file input
button.addEventListener('click', function() {
  input.click();
}, false);

//display the name of the selected file
input.addEventListener('change', function() {
  console.log('val', input.value);
  var parts = input.value.split('\\');
  output.innerHTML = parts.pop();
}, false);
input[type="file"] {
  width: 1px;
  height: 1px;
  position: absolute;
  top: -10px;
  left: -10px;
}

button {
  width: 200px;
  height: 40px;
  cursor: pointer;
}

button,
#output {
  display: inline-block;
  vertical-align: middle;
}
<input type="file" id="input"> <br>
<button id="button">Upload image</button>
<span id="output"></span>

\$\endgroup\$

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.