Detecting if the file input dialog is open - javascript

How can I go about detecting if the file input dialog is currently open?
I'm trying to integrate some file upload functionality into a popup (bootstrap style) model on a web app I'm building. As part of the model's behaviour, if escape is pressed, the model is closed.
This is all good till I open a file input dialog from the open model, if I hit escape to close the input dialog, it'll also close the model.
A super simplified version of what I'm trying to achieve
http://jsfiddle.net/ckevy/1/

Try solving it like this:
When a user clicks on the file selection input, give it focus: $(el).focus().
Then, anytime a user hits ESC, look if the $(':focus') element is the file selection input. In that case, blur() that input and do not close the modal. Worst case – the user wants to close the modal, presses ESC and nothing happens [1]. Thinks "wtf", presses ESC again and modal closes as it should. Just make sure that the file selection input does get focus in all possible cases – tabbing through inputs, etc. If you use a third party uploader and what I've said doesn't work – look into how that uploader wraps the file selection in a custom link or button, and what actually receives the click event in different cases (e.g. when you tab, the input might receive the event, when you click, it could be the link). Overall, it's manageable to have this working with the caveat I've described.
This works with expanded -s too similarly (just check that a select is not focused when ESC is hit).
You won't be able to detect all the cases when you need to blur() the file selection input. It's not a cross-browser solution. Even FF needs adjustments to work. I've been testing on webkit with positive results, in other browsers it might not work.

In my case works this code on jQuery:
// esc must close popup
$("body").keyup(function(e) {
if (27 == e.keyCode) {
hidepopup();
}
});
// input in popup
var $file = $("input:file");
// keyup will be catched for input, not for body
$file.bind("click", function(e) {
$(this).focus();
});
// keyup catching will be changed back to body after selecting file
$file.bind("change", function(e) {
$(this).blur();
});
// we catched esc keyup, so change esc catching back to the body
$file.keyup(function(e) {
if (27 == e.keyCode) {
$(this).blur();
// i don't know, why it works with return false, because i am not js programmer ), but cancelBubble or e.preventDefault is not working
return false;
}
});

I do not believe you actually have direct control over the dialog itself. In some browsers such as FF people have been able to manipulate the dialog to an extent but this does not apply to all browsers and all browser versions.
The easiest way to do this is to disable the shortcut key on the model dialog before opening the file window.

Based on Nikita's answer. If you check for focus on the input field before firing your code it solves the issue:
$('input[type="file"]').on('keydown',function(e){
//Prevents code from firing if file browser is open
if($(this).is(':focus')){
//run code here that should only be applied when the dialog box is closed
}
});

Related

Triggering default behavior on enter key press simulation

So (just to start with "so") I want to create a greasemonkey script for a qwebirc platform. I need to send replies automatically based on some events that happen. For those who don't know, once logged in the qwebirc, there is an input text field at the bottom of the screen where you can write your reply and then, by pressing enter, the reply is sent to the server. The input field is contained in a form element, but the form has no submit button.
I can populate the input field (no problem) by writing to its "value" attribute, but I found no way to "submit" the reply to the server. I tried calling the .submit() method on the container form element, but that simply reloads the page (so it's sending to itself - and that makes sense, 'cause there's no "action" attribute on the form element). It seems to me that the only explanation is that once the enter key is pressed in the input field there's a method that's called somewhere on the qwebirc.js.
I can't find the code responsible for this action (though I worked that in Chrome, I set an Event Listener Breakpoint on the Keyboard - Input, and that stopped me when I pressed the enter key and pointed me to the beginning of some function) because the script is minified and there's no way for me to know what those "m", "n", "p", "t" etc mean. If I had the uncompressed version, I could scan it and, maybe, find it out. I also tried downloading the qwebirc project, but there are loads of files there - whereas on the server I'm trying to write the greasemonkey script there's a single script.
The main idea here is that I guess the enter key press simulation should trigger the sending function - wherever and whichever that may be.
In order to do this I found on stackoverflow some questions with the same subject - the simulation of enter key press. I tried that code:
function simulate() {
var evt = document.createEvent('KeyboardEvent'),
input = document.querySelector('.keyboard-input');
evt.initKeyboardEvent(
'keydown',
true,
true,
window,
false,
false,
false,
false,
13,
0
);
input.dispatchEvent(evt);
}
The event is created (I can see it in my DOM panel in FireBug), but no action whatsoever is taken. I mean why doesn't the .dispatchEvent() behave just like a real enter key press ?
Thanks in advance.
For the purposes of this answer, I'm going to assume that the message input pseudo-form is like others - i.e. the message can be sent by either pressing Enter or clicking a Send button.
You've tried the former; it didn't work. It's possible that the page is waiting for the Send button to be clicked (which may be triggered by an Enter keypress (though no, I don't know why your event isn't working - I'm unfamiliar with event intricacies)). Instead, then, try that.
Also, take note: IE uses fireEvent not dispatchEvent - so if you're in IE, this may be the problem.
To fire a click on the Send button:
var e = document.createEvent("MouseEvents");
e.initEvent("click", true, true);
e.target = "button#send";
if(document.fireEvent) {
document.fireEvent(e);
}
else {
document.dispatchEvent(e);
}
Change the string assigned to e.target to the CSS selector that uniquely identifies the Send button.

Can't click button when soft-keyboard is visible

When an text input element has focus (and the soft keyboard is visible), I can't click the submit button (which is clearly visible) directly. I have to first dismiss the keyboard (by clicking elsewhere or on "Done" on the keyboard), and then click the submit button.
This is confusing behaviour. I have considered removing the log-in button altogether when the keyboard is visible, but that would be too confusing (for users wouldn't know that they could click "Go", or will be annoyed that the login button keeps disappearing).
This only happens on iOS (not sure if its restricted to iOS 7, but suspect it might be), and I'm using Telirik AppBuilder for my app.
function isTextInput(node) {
return ['INPUT', 'TEXTAREA'].indexOf(node.nodeName) !== -1;
}
document.addEventListener('touchstart', function(e) {
if (!isTextInput(e.target) && isTextInput(document.activeElement)) {
document.activeElement.blur();
}
}, false);
Because I was using <button> tag the soft keyboard popped up when not required. I have now changed all for <table> (inside a <td> tag, but could be a <div> ) with an <img> tag inside for the icons. To make the table look more like a button there is a CSS class for colours/borders. A submit area is right at the top (too).
The page can be inspected at http://ask.stroudvoices.co.uk/
It would seem that Android (assume iPad etc also) treat buttons as another kind of <input>, whereas <table> is regarded as <body>.
Sometimes there is a simple answer, from old technology!
I meet a similar problem.What my need is when I tap the submit button and I want to keep the soft-keyboard visible.
Here is my solution.
submit.addEventListener('mousedown', function(e) {
e.preventDefault();
});
I give the submit button a mousedown event, and prevent the default event. it's work on most mobile phones.but in some system found ios 12.1.2 is not available.it's just like the question's owner says, i need to tap twice, one to hide the keyboard, second to reach the submit button.
This confused me and I can't solve it.

How can I prevent keypress events from interfering with the browser's input support?

I'm using Bootstrap's modal component to create an "Add User" dialog to my web app. To make it easy for users to work quickly I want to make the escape an enter keys close and submit the form as would be expected. After running into the usual troubles of divs not accepting input, and some elements under the modal getting focus I ended up just hooking a keypress event to 'document'. This actually works great with one exception.
When entering data into the form the browser will sometimes show a suggestion box:
Hitting escape to close the suggestion box, or enter to select an element from it will unfortunately trigger a keypress event which causes the form to be closed or submitted.
Is there a way I can ignore the keypresses in this situation? Do I need to be taking a completely different approach?
An alternative approach would be to add autocomplete="off" into the input tag.
Did you use $(document).keyUp() to bind your ESC and Enter key event. If so, you can try to add this code in that function to ignore keypress which pressed in a input tag:
$(document).keyup(function(e){
if(e.srcElement.tagName == 'INPUT'){
return;
}else{
// Your code to bind function to exit div or submit
}
});

toggle buttons using tab

It is simple. I have two buttons in a web page. They are sitting closely.
Currently I use mouse to click one of them then doing something.
Can we just use keyboard such as TAB?
Thanks.
Using tab to press buttons will completely break accessiblity on you websites and will effectively drive away any keyboard users from your website, it's an awful practice.
In any case, you might want to capture events for '*' using jquery:
$('*').keydown(function(event) {
if (event.keyCode == 9)
//stuff
})
Though I'd strongly recomend agaist doing this; never override what keys such as tab do, you'll create huge accessiblity issues.
[EDIT]:
Adding the event to document might be more efficient:
If key presses anywhere need to be caught (for example, to implement
global shortcut keys on a page), it is useful to attach this behavior
to the document object. Because of event bubbling, all key presses
will make their way up the DOM to the document object unless
explicitly stopped.
Source
jQuery would be perfect for this just bind the key to that button. something like this.
$('your selector here').keyup(function(e){
if(e.which == '9'){
//do your stuff here
}
});
I think 9 is the correct charcode for tab but you might need to check that. and make sure you do this inside of $(document).ready();
Yes, hit Tab until the button has a dotted border to indicate focus, then you can hit Enter or Space to click the button.
E.g. Button 2 has the focus here and pressing Space or Enter would "click" it:

Any alternative to jQuery change() to detect when user selects new file via dialog box in IE8?

I am unable to detect when input type="file" changes its value after user selects file and the dialog box closes.
$('.myInput').change(function(){
alert($(this).val());
})
Above jQuery code works perfectly in all browsers apart from IE. For some reason IE detects the change only after input field loses focus.
Is there a way to detect the change immediately after dialog box closes? Or maybe to force input field to lose focus after dialog box closes so IE can detect it?
I'm puzzled. Thanks for any help.
This was a known bug that was resolved as part of the jQuery 1.4.2 release, 1.4.2 got a major event model re-write and this was fixed as part of that, just upgrade to resolve the problem :)
Edit - Nick is right, it's fixed in 1.4.2. http://jsfiddle.net/7wR2L/
You can detect click and keep track of it's last value. Something like..
$('.myInput').click(function() {
var $file = $(this);
if( $file.val() != $file.data('lastVal') ) {
// different
}
$file.data('lastVal', $file.val() );
});
Dan Heberden's comment about updating to 1.4.2 works.
However if another element is used to trigger the file file selection, the file input element no longer registers a "change" event.
The new question I created for this has a fork your fiddle to illustrate this case. See jQuery: "change" event on file input element does not fire if the file selection is triggered by an element other than the file input for details.

Categories

Resources