Enable/Disable Android virtual keyboard with dummy textarea - javascript

I want to have virtual keyboard for jquery terminal, here is my test code: http://terminal.jcubic.pl/android.html
the plugin code is here: http://terminal.jcubic.pl/js/jquery.terminal-src.js (uncommitted)
For a moment it was working but it stopped, even then I run focus and blur on textarea the keyboard don't show up. The cursor is not in textarea. The focus/blur work when I run the page on desktop Chromium.
Anybody know why textarea don't have focus?
Sometimes the cursor is inside but the keyboard don't show up and there is no that green outline. Sometime it get focus but then blur. Virtual keyboard show up only when I click inside textarea. I can't find any code that may cause this and why it was working for a moment (but not exactly I wanted).
I've try:
$('textarea').blur(function() { return false; });
or call preventDefault when I click the terminal. (the textarea is my clipboard but I want to reuse it). I keep trying different things with no success.

I've solve the issue, two things about andorid I've found. You can't delay action that trigger focus on textarea/input it need to be direct call (stack of focus call need point to html/browser native action), and it's seems that you can focus (trigger virtual keyboard) only on native events, (for instance you can't focus on load).

Related

.focus() doesn't work on chrome mobile when not activated with click. Workaround?

I've come across some strange functionality on chrome, mobile.
When I try to focus on an element on chrome, it doesn't work when you try to just load the input, getItById and do .focus(). However, if you wrap it in an event listener attached to a button, and click the button with your mouse, it works fine.
So, I tried to trick it by seeing if you could call btn.click(), but that doesn't activate the .focus()
Have a go below: On mobile, chrome (at least for iOS), load the page. You should get an alert 'Clicked', but it won't focus on the input. Then, try clicking on the button. You will get both the alert AND the focus works.
I found this interesting and wanted to see if people knew of a workaround.
Link here - jsfiddle
const btn = document.getElementById('button')
btn.addEventListener('click', () => {
alert('clicked')
const input = document.getElementById('input')
input.focus()
})
btn.click()
<input id="input" type="text">
<button id="button">Button</button>
Edit
Another thing I've noticed, is that if you put your phone go to sleep, and open it again, the focus() works without the click.
Edit 2 - added link for mobile
Why does this happen?
Because mobile devices usually need to change the screen dimensions when a keyboard is shown, they come with some restrictions on when a focus event can be triggered. This is intentionally limited browser behavior on touch devices to guarantee a good UX and avoid performance issues of resizing the browser window ( = potentially very expensive style recalculation).
There's some cross browser differences in how far these restrictions go, and some browsers have bugs on top of that.
But in general they all require an actual user interaction to have happened not too long before the focus is programmatically triggered. Using btn.click() is not the same as an actual touch event, and so the browser will ignore it seeing there was no recent touch event.
On a tracking issue on this behavior for Webkit, Apple provides a motivation:
We (Apple) like the current behavior and do not want programmatic focus to bring up the keyboard when you do not have a hardware keyboard attached and the programmatic focus was not invoked in response to a user gesture. Why you may ask...because auto bringing up the software keyboard can be seen as annoying and a distraction to a user (not for your customers, but for everyone not using your app) given that:
We bring up the keyboard, which takes up valuable real estate on screen.
When we intent to bring up the software keyboard we zoom and scroll the page to give a pleasing input experience (or at least we hope it is pleasing; file bugs if not).
This similar issue with the autoplay attribute, which also requires a gesture (or page load) to have happened recently enough, could be helpful in understanding the kind of problem.
How to work around these limitations?
Most of the time
Likely you don't need to, as most code that would trigger focus is running as a response to a user action and will be allowed to trigger focus. I didn't find data yet on how big the window of time is, but I guess it's big enough that in regular cases it's not a problem (unless you set timeouts of course).
A possible problem for those cases is the script would run so long that the event is already considered too long ago. In fact that's what happened in the related autoplay issue, where the code would request some network resource, and only after the response would trigger the video to play. Depending on the speed of the network/device the video would sometimes auto play, and sometimes not.
Technically the same could happen with an input that is only focused after a network delay making it not show the keyboard. As long as your code doesn't do any network requests you won't have this kind of problem.
On page load
This is definitely not a "fix" for the problem, but you can do a best effort to manage focus on page load by using the attribute specifically made for it. This still won't make a keyboard appear when it otherwise wouldn't.
The autofocus attribute is at least partially supported on all browsers.
Perhaps just calling focus() directly in a script on page load works, but again there's a chance that this code runs too long after the page started being displayed, especially on slower devices. This probably also happens when adding HTML with the autofocus attribute programmatically (e.g. React). If the initial HTML contains the autofocus attribute on the right element that shouldn't occur.
There is deinfitely something weird happening here.
It seems "part" of the DOM thinks that the input element is in focus initially, but chrome does not complete the focusing. For exmaple, if the background is set with:
document.activeElement.style.backgroundColor = "pink";
Then the input element's background is pink. So, some part of chrome's DOM thinks the input element is in focus.
Initially, in my case, the input element is rendered by chrome in its default non-focus styling.
The alert() seems to be interfering with the process. In my case, taking the alert out had the effect of changing the styling of the input element from non-focus styling to in-focus styling, but the cursor did not appear in the input element, nor did the pop up keyboard appear.
By:
removing the alert
wrapping the click inside a function
calling that function on load
fixed the problem in my case. Initially now the element is in-focus styled, the cursor appears in the element's box, and the keyboard pops up.
The solution to the posting by #HJo, January 2019, is to replace:
btn.click();
with:
function load() { btn.click(); }
remove the alert(),
and make the body tag as:
<body onload="load()">
#Peter. If this does not fix your problem too, can you please provide minimal code for your context.
const event = new Event('tap');
const btn = document.getElementById('button')
const input = document.getElementById('input')
btn.addEventListener('click', () => {
prompt('clicked')
input.focus();
})
window.onload = function(){
btn.dispatchEvent(event);
}
}
The code above works when the website tab is just opened, but not on reload for some reason. I tested it on an Ipad and Iphone so hopefully it works well on your end too.
Here's a link to a repl:
https://r.hackinggo306.repl.co
Edit: This seems to be the closest I can get, but also acknowledge the fact that mobile devices might be deliberately preventing this. (It would be annoying if a website looped this.)
On the mobile, you will need to use touchstart event instead of click event.
You can find it here. Hope this helps.
I think, this problem can occur, because of the your JavaScript script is executed before the DOM is Mounted.
so you can do different things,
One Thing
add defer keyword to script tag. Basically it does is, that script is only run after the DOM is mounted. See
Second Thing
Wrap window.onload event with your input focus functionality.
<script type="text/javascript">
window.onload = function () {
const btn = document.getElementById('button');
const input = document.getElementById('input')
input.focus()
}
</script>
window.onload event is only fired when the DOM is finishing mounting.so that may be your JavaScript script run before the input element is mounting.so add onload event to your code.see this

IOS Bluetooth Keyboard - Inputs - Tab Event

Background:
I have a textarea. I capture the Tab key event when the user is typing, and I insert a Tab character (\t) and prevent the browser from focusing on the next input.
This works without issue on Mac and PC, on all browsers.
Problem:
When using a Bluetooth keyboard attached to an iPad, this doesn't work. The document registers the tab key event, but as soon as I focus on the textarea, all tab key events are ignored and not sent to the browser. I have tested with text inputs as well, and see the same result.
Example: https://plnkr.co/edit/NQvxijj3ISZ0B48fSHvi?p=preview
Simple listener:
$(function(){
$("body").bind("keydown",function(e){
$("#bodyLog").append($("<div/>").html(e.keyCode));
return e.preventDefault();
});
});
When you have the body selected (NOT THE TEXTAREA), the tab key event is registered and the number 9 appears. Any other key event appears as well.
When you have the textarea selected, all keydown events are registered on both the body listener and the textarea listener... EXCEPT the tab key.
If anyone has a solution, I would be eternally grateful.
EDIT
I have "fixed" the issue by watching for 5 spaces, then converting that to a tab character.
I have researched this and can only figure that iOS does not want to release control of the TAB key when focused on inputs/textareas. I have tried visiting sites like Google Docs to see if they have gotten around it, but they force you to download the App rather than allowing you to edit files inside of Safari on iOS. I am guessing it is because iOS wants to control the tab key entirely. I have tried Chrome on iOS, but it functions the same, so I would say this is not a Safari issue, but an iOS issue.
A possible, but untested, workaround is to code an entire <div> to act like a textarea, and then replace the textarea with the div. Since the tab key works on all other elements, it should in theory work, but it would require quite a bit of Javascript and CSS to make an element act like another.
EDIT 2
I have discovered that using Option+Tab allows the tab key to be captured in the textarea. I don't feel that is satisfactory though. When I am typing a paragraph on a normal keyboard, I don't type Option+Tab, I just type Tab. As far as I can tell there is no way to capture the Tab key alone inside a textarea.
You can try using this library in order to have these events:
previousbuttonclick
nextbuttonclick
Then when you detect the element next to textarea is focused you come back to your textarea and insert whatever you want.
I believe this is known problem with tabs in iOS. I found similar question on stackoverflow. Just add this hack before your code:
var oldAddEventListener = EventTarget.prototype.addEventListener;
EventTarget.prototype.addEventListener = function(eventName, eventHandler){
oldAddEventListener.call(this, eventName, function(e) {
if(e.target.id === "textarea" && e.keyCode===9){
e.preventDefault();
}
eventHandler(e);
});
};
Please check, it should work. Example

Show keyboard web application

I've a web application, then I need to work on mobile devices, mainly in Android.
The issue is that after some processing, the focus change to a text input then I need that when it happens automatically the virtual keyboard appear without the user need to tap over the input.
How can I do that?
The focus() and click() prevents that virtual keyboard appear to avoid annoying behavior. The only way to do that is to call the focus() or click() inside a user-evento context for example inside a click method callback.

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', '');
});

How to give a page focus again so that the space bar pages down in FF?

I have an ajax script with a "get more posts" button that inserts a couple screens/viewports worth of information. In doing this, the document looses focus at some point and thus the default behavior of the space bar (page down) doesn't work in firefox.
How can I focus the document again to regain the default behavior? What components control this behavior?
It works in Chrome and IE (surprisingly), but not FF.
I tried in a callback function: document.body.focus() and document.getElementById('someClickableElement').click(), but no luck.
If I actually click on the page after the content is displayed, then I can scroll again with the space bar.
Since this is a frequently used feature, it's annoying to click "load more", click again, then space to page down.
Thoughts? Suggestions?
EDIT:
Ok, so i was using a YUI button (just a nice looking html "button" element with some css styling) for the interface. i replaced it with a link, and i no longer have this problem.
Interesting that it works as expected in Chrome & IE, and I'm not even using YUI listeners for the event (just the nice-looking buttons). It's handled by jquery's live method (b/c of the event delegation).
Also interesting that I'm not able to programmatically do what I can do physically (ie. "click").
Even if there is some YUI bug, it seems like firefox should be able to regain focus via some javascript action.
VERY WEIRD. Still any input appreciated (more javascript suggestions to try?). I'm somewhat committed to my current interface.
It looks like you need to blur YUI button element. Or do something with tab order between whole document and the YUI button.
So - not to focus() document, but to blur() YUI button.
Alternatively, you may try to apply 'keypress' event simulating 'TAB' key.
I haven't tried this but how about doing a blur() on the body or the window.
window.blur();

Categories