Single page web application height issue on Android tablet - javascript

I'm working on an SPA which uses body height:100% and one of the pages contains a form with several fields for entering information. On an Android tablet when you tap on one of these fields the soft keyboard appears, which resizes the window element and subsequently the body element, subtracting the height of the soft keyboard. This results in the page being reduced to less than 300px high, making the form unusable. On iPad the keyboard is overlaid on top of the page, so the window height is unchanged.
I have found a partial fix, which involves setting the body height to equal the window height on page load, and also on orientationchange:
$("body").height($(window).height());
window.addEventListener("orientationchange",function(){
$("body").height($(window).height());
}
This fixes the height squishing issue and means that the form can be used, however there is an issue in the instance where the user changes the orientation while the soft-keyboard is open.
The keyboard remains open after the orientation change and the window height (and the body height) is changed to the height minus the keyboard. When the field is blurred and the keyboard disappears, the body remains the reduced height and has a nasty white bar at the bottom.
To illustrate the problem, here's some numbers:
Landscape - Closed Keyboard: 688px
Landscape - Open Keyboard: 273px
Portrait - Closed Keyboard: 1168px
Portrait - Open Keyboard: 716px
If you switch from Landscape - Open Keyboard to Portrait - Open Keyboard, and then close the keyboard, the body height remains at 716px, putting a white bar along the bottom. I need to somehow work out the height that it SHOULD be with Closed Keyboard, at the point of orientationchange, while the keyboard is still open. Bearing in mind the fact that the device resolution, application chrome and keyboard sizes will vary.

You can try the CSS vh unit, which is the percentage of the viewport.
E.g. CSS
body {
height: 100vh; /* The body element is always 100% of the viewport's height. */
}
You should not need the JS event handler in this case.

Related

How to dynamically adjust the height of a scrollable div when the keyboard is shown and dismissed on the mobile browser?

I have a scrollable div in the web page; it contains a list of elements that can be scrolled up and down.
On the mobile browser (such as Chrome on Android, Safari on iOS), when the keyboard is displayed, the problem I have is the bottom elements in the scrollable div are covered by the keyboard, and scrolling up cannot show all the elements above keyboard. There are always a couple of elements below the top edge of the keyboard.
What I want is:
the div adjusts its height when the keyboard is shown, and always above the top edge of the keyboard, so the list will not be covered by the keyboard. As demonstrated by "height 1" in the draft screenshot.
And when the keyboard is dismissed, I want the div height go back to full screen again. As demonstrated by "height 2" in the draft.
I tried to use window.visualViewport.height or window.innerHeight to retrieve the visible height, but the value seems not right.
Does anyone knows the correct way to listen to the keyboard show/dismiss event, and knows how to correctly adjust the height of the div?
I'm not sure there is a good way to do this with css only. it might be possible to use a media query and do something like
#media screen and (orientation: landscape) {
.scroll_div{height: 50% !important;}
}
Not sure that will work on all devices, because not all mobile devices switch to landscape when the kb is raised.
Another posibility with css might be to do something like
#media all and (max-height: 700px) {
.scroll_div{height: 50%;}
}
I chose 50% but that also might not work in your application. You can set a static value you know to be an acceptable height for your uses when the kb is displayed.
I could see a jquery option might look something like
$document.ready(function(){
$kb_shown = false;
$scrollDivHeight = $('.scroll_div').height();
$(window).resize(function(){
if(kb_shown == false){
$('.scroll_div').height($scrollDivHeight / 2));
$kb_shown = true;
}
else{
$('.scroll_div').height($scrollDivHeight);
$kb_shown = false;
}
});
});
I also use browserstack.com so that I can test things such as this on any/every mobile device I choose. Saves from having to keep a bucket of mobile devices around.
As far as I know, there is no way to detect the kb event directly, as it is part of the os and not the browser.
Hope this helps point you in the right direction. Let me know if you have any further questions.
Edit: There are some mobile responsive frameworks out there that already handle this like boostrap, Skeleton, Boilerplate, and many more.

HTML text input breaks positioning on Iphone 6/7 plus

I try to find some workarounds for mobile safari bug:
For example I have a clear html page with
Viewport settings width=device-width, noscalable
Body with position:fixed
Two HTMLInputs created by js and placed to center of screen
All works fine on ever devices but on Iphones 6 plus and 7 plus we have a great problem:
If I've focus input and then hide keyboard, all window positioning become diverged from rendered position. Input could be only focused if I've click ~100px higher of it visible position. Moreover, each additional elements on page (even canvas with webgl content) also will get wrong coordinates on each tap/touchstart and so on.
I've connect iphone for debug, and I can see that browser thinks that input placed not where it rendered. Also i can vertically scroll page with finger, and real rendered inputs will stay in place, but area from browser will moves up and down right up to his rendered position.
Bug could be reproduced only if few tabs opened in browser in landscape orientation (i'll highlight tabs red on screenshot).
Can't reproduced on iphones5-6, because there is no tabs, but also can't be reproduced on ipad, which has the same tabs.
Example is here: http://baker-feather-16713.bitballoon.com/
Problem is the fact that safari allow user to scroll page to fullscreen ever if you set html/body width and height to 100%. So, when keyboard showed content scrolls up despite that body has position "fixed" and it rendered with bug when keyboard becomes hidden.
Solution is very simple: just need to do scrollTo(0, 0) when keyboard hidden, e.g.:
document.addEventListener('focusout', function(e) { window.scrollTo(0, 0) });

iOS Chrome - How to calculate window height minus height of address bar

I am developing browser games that have only one full-size canvas element in body.
When run these games in iOS9.2(iPad) Chrome(Ver 47.0.2526.107), the bottom area of game screen is not shown. (It didn't happen several months ago. Even now this neither happen in Safari, nor Android 5.0.2 Chrome 47.0.2526.83)
These game programs first calculate size of window (the area showing html document when address bar is shown), and places a canvas element having the size.
Since some version of Chrome, the "size of window" is interpreted as the size of window when address bar is NOT shown.
I tried to get the height of window by:
screen.availHeight
window.innerHeight
$(window).height()
document.documentElement.clientHeight
document.height
$(document).height()
but they all returns the same value, the height when address bar is NOT shown.
Test code is shown in http://jsrun.it/hoge1e4/4Ygq I want to know the value of the scale at bottom of the screen when address bar is shown.
(see picture)
The problem seems to be solved by version-up.
I checked it on ver.49.0.2623.73

Event to detect "Tablet" mode transition in Chrome OS?

I recently purchased an ASUS c100p Chromebook and noticed that when the device is flipped all the way back into "tablet" mode that sizable windows are maximized by default. If they have fixed window bounds they are effectively treated as modal (centered, immovable, and peripheral areas are dimmed) when in the foreground, unless they are set to have the alwaysOnTop attribute in which case they can be moved freely. I want to be able to detect this change so I can have an app with fixed window bounds perform some sort of action (maximize, close, set to alwaysOnTop, etc.). Is there a some way of detecting this transition in Javascript?
I've tried the following events with no success:
chrome.app.window.onFullscreened - Nothing fires on transition.
chrome.app.window.onMaximized - Fires on resizable windows, but not windows with fixed bounds.
chrome.system.display.onDisplayChanged - Fires if device is rotated from landscape to portrait while transitioning, but not if going straight to landscape tablet mode.
You could detect to see if the inner width and height of the window is the same as the fixed bounds with this code:
if(window.innerWidth != 400 || window.innerHeight != 400) {
// some code, eg window.close()
}
Replace the 400s with the width and height the window is being opened with.

Refreshing page automatically when viewport size change

I'm using responsive and adaptive media queries for my website to accommodate smartphones...Now the problem is that my max-width mobile query ends at 480px, which is most phones rotated display width (when the phone is on its side...). Now some phones, like the HTC desire have a max screen width of 533px, now when the user first loads the page on vertical position (320px screen width) and he/she rotates rotates the screen to 533px width, it goes past my design specifications and it looks kinda crappy...(since the layout was meant for 480px max...)
Now the only way to solve that is to refresh the page once the viewport dimensions change. How do I force a refresh?
Thank you
if device rotate window resized.
window.onresize = function(event)
{
document.location.reload(true);
}

Categories