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 ?

Sᴀᴍ Onᴇᴌᴀ
29.5k16 gold badges45 silver badges201 bronze badges
asked Sep 25, 2017 at 14:27
\$\endgroup\$

1 Answer 1

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>

answered Nov 22, 2017 at 1:10
\$\endgroup\$

Your Answer

Draft saved
Draft discarded

Sign up or log in

Sign up using Google
Sign up using Email and Password

Post as a guest

Required, but never shown

Post as a guest

Required, but never shown

By clicking "Post Your Answer", you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.