How to prevent focus change on long press in Chrome on Android? - javascript

I want focus to stay on the currently focused DOM element. I am using the usual way to prevent focus change on click on another element:
button.addEventListener("mousedown", (evt)=>{evt.preventDefault();});
This works on normal clicks, but not on long press.
I expected it to work on long press too. Anyone knows if the behavior is a bug?
Is there any way to prevent focus change on long press?

Listen to the touchstart event:
element.addEventListener("touchstart", (evt)=>{evt.preventDefault();});
Note that you will still need the mousedown event listener for non-touch devices.

Related

How to ignore all keyboard events on Chrome for Android?

It's easy on any desktop browser. I just listen for keydown of document or window, and call preventDefault, as with the answers here and here.
I usually use something like this, so it's like ignoring all keyboard inputs:
window.addEventListener('keydown', function(e){
e.preventDefault();
e.stopPropagation();
e.stopImmediatePropagation();
}, true);
But they don't work on my Android tablet. (Tested on Chrome 63.0.3239.83 and Firefox 57.0.1 for Android)
Here is the typical scenario: I have an <input> focused as the current active element, and then I need some JavaScript to execute to freeze the user interface so all user inputs are ignored.
I wasted a lot of time on this issue and still cannot find a workaround for my Android tablet.
I considered some other ways, like changing focus to another element, or setting readOnly of the element to true. But there are caveats. Calling focus() triggers the onblur of the previously focused element. Setting readOnly does not prevent the event listeners of the focused element from firing (e.g. any keydown or keyup handlers for that <input>), and sometimes the enter key becomes a key that allows user to jump to the next input field on the page.
Is there a way to ignore all keyboard inputs on Chrome for Android without undesirable side effects?
At last I called window.addEventListener to attach the same handler (the function used in the question) for not only keydown, but also blur and focus, and then called document.documentElement.focus(). (Need to add tabindex="0" to <html>)
This avoids the problem of triggering onblur of the previously focused element, which is mentioned in the question.
(Note that blur and focus are not cancelable events, so handlers are only for stopping propagation here.)

Prevent blur event on keyboard close

This is for mobile web apps, not native.
I have an autocomplete drop-down that closes on the blur event. But I want to prevent this from happening when the user closes the keyboard on mobile (ie the autocomplete dropdown should stay visible). Is there a way to distinguish a blur event caused by the keyboard closing, and other kinds of blur events? Can I prevent a blur event specifically caused by closing the keyboard in mobile?
Ok, first I would recommend checking your libraries' documentation because they might provide something in their API, although there's nothing I'm aware of. That's the disadvantage of Web Apps: you can't access native functionality.
If you still really want to do it, here's a possible solution. It's ugly, but it might work.
Container on tap function (event)
If !autocomplete return // if you cant see the popup do nothing and blur normally
If (event.target != inputID) AND (event.target != autocID)
CloseAutocomplete()`
Essentially, instead of closing the autocomplete on blur, close it whenever the user taps on your parent container, but not on the input itself or the autocomplete. Depending on how it works, you could extend it to check any tap on screen.
I see you tagged iOS... you can observe keyboard events with UIKeyboardWillHideNotification. [https://developer.apple.com/library/ios/documentation/UIKit/Reference/UIWindow_Class/index.html#//apple_ref/c/data/UIKeyboardWillHideNotification] You may have to do and asynchronous delay to catch that event on with onblur, though.
If you really want to prevent all "other kinds of blur events" you could make your drop-down close on specific events (instead of on blur). For example: when a another field is clicked, navigation, and/or add an 'x' close button next to that drop-down control.
In the blur event listener, test for event.relatedTarget === null. If focus has moved to a different element, event.relatedTarget will refer to that element, but if there is no focus (as is the case when the cause of the blur is keyboard close), event.relatedTarget will be null.

How to handle differences in iOS and Android Keyboard

For HTML/JS in mobile browsers, I'm having an issue where blur events trigger differently in iOS and Android. In iOS, a user can click on "Done" on the native keyboard, which hides the keyboard and causes the focused element to blur.
The same, however, does not happen when a user clicks the back icon in Android to hide the native keyboard; The elements that were previously focused keep their focus.
Is there a way to listen for the keyboard hiding and trigger a blur on the focused element? Or is there a way to force the Android keyboard to display a "done" button? Or is there a generally better solution?
Maybe a solution would be to listen to the keydown event on the input, and check if the keypress is "Enter".
To do that, please refer to this :
Enter key press event in JavaScript

Emulating "input clear" icon in iOS-targeted web app

Native iOS apps contain "clear buttons" in input fields. They clear the text while maintaining field focus.
I am developing a web app targeted specifically at iOS devices, and not having any luck emulating the behavior. If I overlay another element with a click event to clear & refocus the input, the iPad ignores the call to focus because it begins hiding the keyboard the instant the blur event fires on the input (before the click event). Therefore the user must manually re-focus the field after clicking the clear icon to get back the keyboard.
Is there any way to grab a touch event on the overlay image/icon without the soft keyboard deciding to vanish, or a better way to do this?
daxelrod's 2nd comment above led me to the solution: Trap the mousedown event on the clear icon, stop it, and clear the input. Thereby a "click" never occurs, and the input does not lose focus.
I thought that blur() fired at the browser level before any of the mouse events (down, up, click) did, so I didn't think to try it. Glad to see I was wrong!
In Mootools flavored JS:
document.id('inputClearImage').addEvent('mousedown', function (e) {
e.stop();
document.id('input').set('value', '');
});

Determine what triggered focus event?

I need to determine what caused a focus event.
Ideally, I want to differentiate between a click, a tab/keyboard input, and a manual (via code) trigger.
How can I do this?
I'm looking at the event object, but I'm not seeing anything too useful.
If the focus comes from a $x.focus() call, then the event won't have an originalEvent property because there was no event from the browser so:
if(ev.hasOwnProperty('originalEvent')) {
// Focus event was manually triggered.
}
To differentiate between keyboard and mouse based focus events, you could try binding a keydown handler to everything else to detect a Tab or Shift-Tab but that would be a gross hack and probably not reliable; for example, on an iPad, you don't hit Tab to move to the next field, you hit Next or Previous in the popup keyboard to move around and those may not register as key presses at all.
There's a similar question about click events that might be of interest as well:
In jQuery, how can I tell between a programmatic and user click?
As you note in the comments, you could trap click events to detect a mouse-based focus change and set a flag somewhere to remember it. Then you'd have this:
If there is no originalEvent in the jQuery event then the focus change was triggered manually (i.e. $x.focus() or similar).
If the click handler flag is set then the focus change came from a mouse action.
Otherwise the focus change came from a keyboard event.
You'd have to be careful that your click and focus events came in the right order and you'd need to make sure the flag was cleared when you're done with it. This might not be bullet proof but maybe it doesn't need to be.

Categories