0

I need your help.

I would like to design a javascript function, such that when I call it, it will open up a dialog box asking me to navigate to the selected file, once I click on the "open" button, it will then save the file's path into a var.

How do you do this? I would NOT like to the input type="file" method, as I dont require that particular input to be on my page.

ie:

function getlocation() {
var x = popup the open file dialog box and let the user select a file
}
John Smith
  • 1,639
  • 11
  • 36
  • 51
  • 1
    You can't do what you want. Without using a ``, there is no way to open a file selection dialog. Even if you do use that, you can only get the file name, you cannot get its full path (that's a huge security hazard). If you don't want the input to be shown, you can hide it, and trigger it using JavaScript. – gen_Eric Apr 12 '13 at 16:31
  • 1
    @RocketHazmat Actually, I don't think you can trigger it using Javascript. Everything else you said sounds good :) But I think (maybe in just IE) some browsers don't allow you to open it programmatically. You have to hide it and trick the user into clicking on an opaque, stacked file input...at least to be cross-browser compatible. – Ian Apr 12 '13 at 16:33
  • 2
    @Ian: I made a quick demo of a `display: none` input, and triggering its `click` method seems to work; at least in Chrome, Firefox, and IE 9. http://jsfiddle.net/rJA7n/ Anyway, the other method works too. I know the AJAX uploader I use on my website does that. – gen_Eric Apr 12 '13 at 16:34
  • 1
    @RocketHazmat Good example. I guess that I've read in the past, it isn't fully compatible with all browsers. Some combination of reading http://stackoverflow.com/questions/1829774/jquery-simulating-a-click-on-a-input-type-file-doesnt-work-in-firefox (and its possible duplicate) is just an idea for how inconsistent it is. Of course, I'm guessing the inconsistency mainly lies with old IE and Opera (and older versions of FF/Chrome even). Of course, we shouldn't always code for the past, but I wanted to point it out. Specifically that the opaque/stacked trick should be fully consistent – Ian Apr 12 '13 at 16:44
  • 1
    @Ian: My example doesn't seem to work in the latest Opera, and it may not work in IE < 9. For a good example of the opaque trick, look at this uploader: http://fineuploader.com – gen_Eric Apr 12 '13 at 16:47
  • @RocketHazmat Yeah, that's all I wanted to point out :) And that looks like a cool uploader. I know in the past, because we wanted the styling of an `input[file]` element to be consistent with the rest of our page, I had to create a pseudo `input[file]` and figure out the styling to use the opaque trick. We weren't targeting an immediate upload, so the whole ajax/auto upload and progress bar stuff weren't a part of it, but it was interesting to iron out and learn. – Ian Apr 12 '13 at 16:54
  • @Ian: I do like how they trick you into actually clicking on an file upload element! Anyway, after some testing it seems my example does work in IE 8! It's just Opera that doesn't like triggering `.click` on a file upload element. http://jsbin.com/esahij/5/edit (jsbin because jsFiddle doesn't work in IE 8) So, for a more cross-browser method, use the opaque/stacked trick :) – gen_Eric Apr 12 '13 at 17:01
  • 1
    @JohnSmith: What do you want to do with the string you get? Like I said, all you can get is the file's name, you can't get its full path. Some browsers will even give the path as `C:\fakepath\file.name`, and others will just return `file.name`. Remember, file pickers are asynchronous! You need to use the `onchange` event handler to get the chosen file. – gen_Eric Apr 12 '13 at 17:04
  • 1
    @RocketHazmat Yeah, sneaky sneaky. I never would've thought of it unless I read how to do it =/. But that's weird it works in IE8, it seemed to be on the list that doesn't work. Are you testing on a native IE8 or on IE9 with IE8 emulated? Just wondering. And yeah, Opera stinks it up when it comes to this, I guess. Also, I realized with fiddles - you could develop it on a different browser, then open this version of the fiddle: http://jsfiddle.com/whatever/show/ in IE. Of course, it doesn't allow for Live editing of the fiddle, but allows you to "keep using" jsFiddle – Ian Apr 12 '13 at 17:04
  • @Ian: I was testing on a native IE 8 (using a virtual machine of Windows XP). – gen_Eric Apr 12 '13 at 17:04
  • @RocketHazmat Very cool. I guess it may not work in **older** IE :) – Ian Apr 12 '13 at 17:08
  • @Ian: I hope to G-d that no one is using a version of IE older than 8! :O – gen_Eric Apr 12 '13 at 17:13
  • @RocketHazmat I wish. Unfortunately, that's currently what I'm targeting with our current project - IE 7/8, and kinda 9. I know people still have to target IE 6. I'm pretty sure 6 & 7 are really only used by companies with locked down networks, especially medical companies. IT just doesn't like to upgrade from a "stable" environment, and sometimes they're just lazy. But it's a big step when there's hundreds of computers that need updated. Their motto's something like "If it ain't broke, don't fix it" - their current setup works well enough, but they don't realize how it affects other people... – Ian Apr 12 '13 at 17:17
  • @RocketHazmat By the way, I think you should just post an answer (if you want) explaining the options for the OP. Their intent is unclear, but the two options we've discussed should be enough to answer their question. A hidden `input[file]` that is programmatically triggered to open a dialog, or is opaque/stacked to trick the user into physically clicking it, when appearing to click something else (a button, pseudo button, etc.) – Ian Apr 12 '13 at 17:20
  • 1
    @Ian: Yeah, might as well put this as an answer. As it stands, regardless of what the OP wants, this is the only solution. – gen_Eric Apr 12 '13 at 17:21

1 Answers1

2

The only way to allow the user to select a file is to use an <input type="file" />1. You don't have to have this element visible, just on the page.

When a user selects a file, all you can get from it is its name. You cannot get its path. Also, note that file upload elements are asynchronous. You need to use the onchange event (callback) to get the name.

You can hide the upload element using display: none, and then just have another JavaScript function programmatically trigger it. (NOTE: This method doesn't work in Opera, and possibly other browsers. It was tested in Chrome, Firefox, and IE 8/9)

<style>
    #getFile{
        display: none;
    }
</style>

<input type="file" id="getFile" />
<button id="openFile" type="button">Click Me</button>

<script>
    var uploadElement = document.getElementById('getFile'),
        uploadTrigger = document.getElementById('openFile'),
        openFileUpload = function(){
            uploadElement.click();
        },
        alertValue = function () {
            alert(uploadElement.value);
        };

    if (window.addEventListener) {
        uploadTrigger.addEventListener('click', openFileUpload);
        uploadElement.addEventListener('change', alertValue);
    } else {
        uploadTrigger.attachEvent('onclick', openFileUpload);
        uploadElement.attachEvent('onchange', alertValue);
    }
</script>

DEMO: http://jsfiddle.net/rJA7n/3/show (Edit it at: http://jsfiddle.net/rJA7n/3/)

Another method that should work in most browsers (including Opera) is to make the file upload element "invisible" and put an element on top of it. So, when you click on what you think is a button, you're really clicking on the upload element. AJAX uploaders (like http://fineuploader.com/) use this method to allow you to "style" upload buttons.

<style>
    #getFile{
        width: 100px;
        opacity: 0;
        filter: alpha(opacity = 0);
    }

    #openFile{
        display: inline;
        margin-left: -100px;
        background-color: red;
        height: 30px;
        width: 100px;
        padding: 10px;
        color: white;
        text-align: center;
    }
</style>

<input type="file" id="getFile" />
<div id="openFile">Click Me</div>

<script>
    var uploadElement = document.getElementById('getFile'),
        alertValue = function(){
            alert(uploadElement.value);
        };

    if(window.addEventListener){
        uploadElement.addEventListener('change', alertValue);
    }
    else{
        uploadElement.attachEvent('onchange', alertValue);
    }
</script>

DEMO: http://jsfiddle.net/cKGft/4/show/ (Edit it at: http://jsfiddle.net/cKGft/4/)

1 Well, you can use drag and drop if you want to be really fancy. I made a quick demo of that here: http://jsfiddle.net/S6BY8/2/show (edit it at: http://jsfiddle.net/S6BY8/2/)

gen_Eric
  • 223,194
  • 41
  • 299
  • 337