2

I have code that let my users open the File Browser of the client's browser so they can select a file.

That works fine when the user clicks a button with the mouse, but somehow it completely fails with the keyboard.

So I setup the button as follow:

var that = this,
    upload_button = jQuery(".upload-button");

upload_button.click(function(e)
    {
        e.preventDefault();
        e.stopPropagation();

        // simulate a click on the hidden file-input button
        that.upload(editor_widget);
    });

I setup the keyboard as follow (the upload_button will get focus first, obviously):

upload_button.keypress(function(e)
    {
        if(!e.shiftKey && !e.ctrlKey && !e.altKey && !e.metaKey)
        {
            switch(e.which)
            {
            case 85:   // [U]pload
            case 13:   // Enter
                e.preventDefault();
                e.stopPropagation();

                // simulate a click on the hidden file-input Browse button
                that.upload(editor_widget);
                break;

            }
        }
    });

Then the upload function looks like this:

....prototype.upload = function(editor_widget)
{
    var upload_button = jQuery(".upload-button"),
        upload_input_file = w.find(".file-input input");

    // ignore clicks if the button does not exist
    if(!upload_button.exists())
    {
        return;
    }

    // simulate a click on the file "Browse" button
    //
    upload_input_file.focus();
    upload_input_file.click();
    c.focus();
};

So, somehow the upload_input_file.click(); works fine when I click the button. It completely fails when I press U or <enter>...

I'm primarily testing in Firefox at the moment.

Alexis Wilke
  • 19,179
  • 10
  • 84
  • 156
  • for security reasons, you usually need a click event in the stack for the dialog to show. – dandavis Mar 18 '16 at 02:41
  • See http://stackoverflow.com/questions/29728705/trigger-click-on-input-file-on-asynchronous-ajax-done – guest271314 Mar 18 '16 at 03:23
  • @guest271314, only I do not call the `click()` in an asynchronous function, but on a keyboard trigger, opposed to a mouse click. – Alexis Wilke Mar 18 '16 at 03:25
  • Is `.click()` jQuery `.click()` or DOM `.click()` – guest271314 Mar 18 '16 at 03:26
  • I use the jQuery interface, but tried `upload_input_file.get(0).click()` and got the same result: nothing. I also tried with and without the `focus()` call. The input is hidden, but not with `display:none` (it has opacity of 0). – Alexis Wilke Mar 18 '16 at 03:34
  • @AlexisWilke The opacity of the element should not matter; see stacksnippets at post both `Enter` and `U` should trigger "Open File" dialog – guest271314 Mar 18 '16 at 03:35
  • @dandavis, I personally fail to see why it would be a security problem to offer the functionality on a keyboard event too. I can understand if it were to just happen (i.e. in an asynchronous code snippet like a timer, some callback triggered by an AJAX event, etc.) Is there a page that would explain why a trigger from the keyboard would be viewed as a security issue? I think that's a shame because it will prevent blinds from using that functionality (although I allow drag and drop too, but a file manager can be a lot easier for blind people.) – Alexis Wilke Mar 18 '16 at 03:44
  • @AlexisWilke: it's not that a trigger from a kb is an issue, it's simply that they check for a click(). note that [return] usually fires a `click()` event, so it might pass the screen, but i don't think i would count on it. – dandavis Mar 18 '16 at 04:22
  • @dandavis, guest271314 actually gave a link to the list of W3C trusted events. Strange that the keyboard events are not included... http://stackoverflow.com/questions/29728705/trigger-click-on-input-file-on-asynchronous-ajax-done – Alexis Wilke Mar 18 '16 at 22:23

3 Answers3

2

You can totally do this. Register keyup event for document then trigger click to file browser button.

$(document).keyup(function (e) {
  if (e.keyCode === 85) {
     $(".upload-button").click(); 
  }
});  
Kaitou Kid
  • 51
  • 4
  • I tried with `keydown()`, `keypress()`, and `keyup()`, but it looks like dandavis is correct... Firefox must be testing something that does not feel *compliant* and prevent the file manager from opening. Did you try in IE or some other browser? – Alexis Wilke Mar 18 '16 at 03:20
  • @Alexis Wilke: I'm so sorry. When using $(".upload-button").click(); without registering keyup event, it worked fine. But with this, nothing happened. – Kaitou Kid Mar 18 '16 at 08:06
1

Try substituting using .click() on DOM element for jQuery .click() on jQuery object

$(window).on("keydown", function(event) {      
  if (event.which === 13 || event.which === 85) {
    event.preventDefault();
    event.stopImmediatePropagation();
    $("input")[0].click()
  }
})
<script src="https://ajax.googleapis.com/ajax/libs/jquery/1.11.1/jquery.min.js">
</script>
<input type="file" />
guest271314
  • 1
  • 15
  • 104
  • 177
  • Note that I am under Ubuntu, testing with Firefox and it just does not trigger for me... with either key (unless I give the Input button focus then Enter works, obviously.) – Alexis Wilke Mar 18 '16 at 03:41
  • @AlexisWilke _"unless I give the Input button focus then Enter works, obviously.) "_ Adding `.focus()` returns expected results ? Will try at nightly . – guest271314 Mar 18 '16 at 03:43
  • I have that in my code now and it *works*, but only with enter if I use `keydown()` because then the `keyup()` happens on the file input widget. So I can trick it in that way. That requires the removal of the `preventDefault()` and `StopImmediatePropagation()` calls too. (since if you stop the propagation of keydown, you never get the keyup event.) However, the `U` still fails. – Alexis Wilke Mar 18 '16 at 03:48
  • _"I have that in my code now and it works"_ Can you create a stacksnippets or plnkr http://plnkr.co to demonstrate ? You are correct, tried at nightly where expected results were not returned. Returns expected results at chromium – guest271314 Mar 18 '16 at 03:55
  • 1
    I have a sample based on your code here: http://alexis.m2osw.com/input-file-keyboard.html – Alexis Wilke Mar 18 '16 at 04:20
0

As mentioned in the comments of the other two answers, I found something that will make the Enter (and eventually spacebar) work in Firefox, but not the U key.

The idea is to change the focus to the input of type file in keydown and thus let the normal Enter or Space keyup event do what it normally does.

upload_button.keydown(function(e)
{
    if(!e.shiftKey && !e.ctrlKey && !e.altKey && !e.metaKey)
    {
        switch(e.which)
        {
        case 85:   // [U]pload -- does not work in Firefox
        case 13:   // Enter
        case 32:   // Space
            // we cannot simulate a click in this case, but we can
            // change the focus and let the system manage the keyup
            // event as normal... be sure to let the normal propagation
            // of the event happen since that's where things
            // actually happens. So all we do is:
            upload_input_file.focus();
            break;

        }
    }
});

I have not tested yet, I may have to manage the U key with the click() so it works as expected in other browsers.


Okay, I now also tested with IE and it works with the U key with the original code. The Space and Enter keys do not both work in IE so if you want to support both, that will require a test to know whether to handle those keys as in IE or as in Firefox...

Alexis Wilke
  • 19,179
  • 10
  • 84
  • 156
  • Interestingly space key triggers "File Upload" at nightly at http://alexis.m2osw.com/input-file-keyboard.html – guest271314 Mar 18 '16 at 04:32
  • It could be that your browser sets the focus on the input file by default... You could try again by first clicking somewhere in the page before using the spacebar key. – Alexis Wilke Mar 18 '16 at 04:56
  • 1
    Yes, only occurs when `input` has focus . Space character `which` is not at `if` condition – guest271314 Mar 18 '16 at 04:59
  • See linked page http://stackoverflow.com/questions/29728705/trigger-click-on-input-file-on-asynchronous-ajax-done description of trusted events. Try substituting `mouseup` for `keyup` ; though this still does not address firefox appearing to require focus – guest271314 Mar 18 '16 at 15:03