How to detect the minimal-ui support? - javascript

iOS 8 removed "minimal-ui" viewport property support. How to detect if browser is iOS Safari and if it supports "minimal-ui"?
Adding "minimal-ui" to the viewport does not cause an error, making feature detection harder.
var meta = document.createElement('meta');
meta.setAttribute('name', 'viewport');
meta.setAttribute('content', 'minimal-ui');
document.head.appendChild(meta);
// No error.
I'd like to avoid version detection:
var version = navigator.appVersion.match(/OS (\d+)_(\d+)_?(\d+)?/);
version = [parseInt(version[1], 10), parseInt(version[2], 10), parseInt(version[3] || 0, 10)];
if (version[0] > 8) { /* [..] */ }
Because it is unknown what is the future of "minimal-ui".
The only reliable solution that I have found is adding "minimal-ui". Then on page load checking the window.innerHeight. If it is greater than the height with the chrome around, "minimal-ui" is supported. This will work, because even if page is displayed in "soft" full screen mode (when user touch-drag the page to enter the no-chrome view), window.innerHeight does not reflect the "soft" fullscreen height until after the implicit scroll/resize event, e.g.
Assuming iOS 8, iPhone 5s and page loaded in "soft" full screen:
<!DOCTYPE html>
<html>
<head>
<meta name="viewport" content="minimal-ui">
</head>
<body style="height: 1000px;"> <!-- Document height must be greater than the viewport to enter the soft fullscreen. -->
<script>
if (window.innerHeight == 460) {
// We know that minimal-ui is not supported because initial
// window hight is that of browser window with the chrome.
}
// This event is called instantly after page load.
window.addEventListener('resize', function () {
window.innerHeight; // 529
});
</script>
</body>
</html>

Related

Why "screen.height" works fine when using Chrome' DevTool to simulate mobile devices, but not on real mobile devices?

The screen.height I am talking about is described in https://www.w3schools.com/jsref/prop_screen_height.asp
I used screen.height < 560 ? true : false to determine whether the screen height is smaller than a threshold, so I can hide some UI elements in this case.
It works fine in Chrome's simulator for mobile devices (the feature highlighted below).
By "works fine", I mean when simulating a mobile device, like setting device to be iPhone X as shown above and displaying in landscape mode, the UI elements are hidden correctly due to screen.height < 560 = true.
However, on real mobile devices like a real iPhone X, the UI elements don't get hidden, which I guess is because that it is always screen.height < 560 = false, even if it is in landscape mode.
I am wondering why is that... Why iPhone X in DevTool has a different height from a real iPhone X?
Is the simulation in Chrome DevTool not accurate? Or is it because screen.height doesn't return the correct value on mobile device?
Any hints would be appreciated!
That's because the simulator takes the screen size according to the dimensions that you are setting there. But in reality, screen.height takes the height size of the whole screen, including elements that are outside of the viewport in the device. You should use window.innerHeight to get an accurate height size.
If you log in your console screen.height and window.innerHeight on the simulator, you will get the same size. If you do this in the normal viewport (deactivating the simulator), you will get different values.
More info: Screen Height - Window InnerHeight
UPDATE
screen.height doesn't update on screen rotation, always has the same value corresponding to the screen height in portrait mode, while window.innerHeight takes the current height of the device window either portrait or landscape. Just make sure to fire this in the event when the rotation happens.
For this, you could use the Window.matchMedia() like so:
// Breakpoints
const breakpoint = window.matchMedia('(max-height: 560px)');
// Breakpoint checker
const breakpointMutations = () => {
if (breakpoint.matches === true) {
// Do something
}
}
// Run breakpoint checker if media changes
breakpoint.onchange = function (event) {
breakpointMutations();
}
// Run breakpoint checker on load
breakpointMutations();
It might be because you are missing the response meta tag. Try adding this to your head tag:
<meta name="viewport" content="width=device-width, initial-scale=1">

How can I open a new popup window on Google Chrome that adjusts to any screen without going over Windows' taskbar?

I've been trying to create a popup launcher that fits the screen without overlapping Windows' taskbar, I've done some research, and even created the HTML file, but it doesn't quite work properly, it overlaps the taskbar and even goes beyond it. How can achieve such task, and what am I doing wrong?
Code: ( Run it on your desktop )
<!doctype html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>winds</title>
</head>
<body>
<script>
function fc()
{
window.open('http://www.google.com.br','window','menubar=yes,screenX=0,screenY=0,top=0,left=0,location=no,status=no,toolbar=no,scrollbars=yes,resizable=no,width=' + (screen.width - 10) + ',height=' + screen.availHeight);
}
</script>
Chrome
</body>
</html>
It turns out window.outerWidth and window.outerHeight have been around a while but did not show up in IE until IE9.
The following code example opens a window with maximum size but clear of task bars by first opening it with minimum size and then resizing the opened window to occupy all of the available area.
function splashOpen(url)
{
var winFeatures = 'screenX=0,screenY=0,top=0,left=0,scrollbars,width=100,height=100';
var winName = 'window';
var win = window.open(url,winName, winFeatures);
var extraWidth = win.screen.availWidth - win.outerWidth;
var extraHeight = win.screen.availHeight - win.outerHeight;
win.resizeBy(extraWidth, extraHeight);
return win;
}
// and test
splashOpen("javascript:'hello folks and world'");
Noting:
the MDN wiki example of a window features string appears to be incorrect: include the names of features required and omit those not required.
Users may have selectively disabled suppression of widow.open features. (In Mozilla Firefox see about:config under dom.disable_window_open_feature to prevent popups hiding location details or disabling other useful features.)

Wrong value for window.innerWidth during onload event in Firefox for Android?

Okay, so, the problem I am facing is this: my mobile Firefox browser is not retrieving the correct values for window.innerWidth, document.documentElement.clientWidth, or even the width of a div styled to take up the whole client window after page load.
I am not crazy, my code works just fine in every other browser! For some reason Firefox initializes these values with defaults and then gets the correct values later on. If at any point I interrupt my JavaScript with an alert(), these properties magically become accurate afterwards.
I have scoured the internet for an answer and all I can find is a hack workaround: use window.setTimeout to delay the use of these properties until they have time to populate correctly. That is crazy! Users want speed, not an extra delay just to view my site on a Firefox browser.
What I don't understand is that I can set a div up to fill the client window perfectly before the values become accurate. I do this in css by setting width and height of my div's id to 100%. document.documentElement is basically the same as document.getElementById("my_div"); after all the document elements have loaded, so, how does the browser know how big the div should be when it doesn't have the correct dimensions of the client window in the first place?
I have tried running my code inside a window.addEventListener("load",function(event_){ //My Code }); but still these values will not generate. Is there a page load event that comes after window.onload?
If anyone can tell me why only Firefox mobile seems to display this odd behavior I will give you a mental high five.
Here's a bit of sample code for recreating the problem:
<!DOCTYPE HTML>
<html>
<head>
<!-- Added " after javascript during edit. -->
<script type="text/javascript">
window.addEventListener("load",function(event_){
var output=document.getElementById("output");
/* Returns some default value like 980. */
output.innerHTML=window.innerWidth;
alert("After this alert, the value will change.");
/* Returns an accurate value like 511. */
output.innerHTML=window.innerWidth;
});
</script>
<!-- Added title during edit. -->
<title>Title</title>
</head>
<body>
<p id="output">Default Output</p>
</body>
</html>
My Firefox for android version is 35.0.1. My Android version is 4.4.4. On my device, Firefox displays "980" in the output p element, shows the alert, and then displays "980" again. After page refresh, the first two steps remain the same, but the output after the alert changes to 360. This happens with document.documentElement.clientWidth as well. No properties I try seem to get the correct values. It seems that Firefox has some sort of delay after page load before it has access to the client window's dimensions...
I tried the verge.airve.com plugin without JQuery and its initial feedback remained at 980. It also initialized as 980 on Chrome, which was weird, because Chrome worked as expected without it...
After much debate a solution was found! Firefox apparently resizes the window after it is loaded (I guess for good measure, who really knows)! So, by adding a resize event handler in addition to window.onload, this problem can be averted! See accepted answer below for more details.
Make sure your measurement is done when whole document is loaded and resized.
window.onload = showViewport;
window.onresize = showViewport;
function showViewport() {
var output=document.getElementById("output");
var width = Math.max(document.documentElement.clientWidth, window.innerWidth || 0);
var height= Math.max(document.documentElement.clientHeight, window.innerHeight || 0)
output.innerHTML = "Viewport size is " + width + "x" + height;
}
<body>
<p id="output">Default Output</p>
</body>
The problem (innerWidth === 980) persists for Firefox 40.0 under Android 4.4.4. A 1 msec wait is a circumvention. Replace window.onload = myProgram; by
window.onload = function() {setTimeout(myProgram, 1)};
In the meantime I encountered this problem while adapting a fairly elaborate site to small screens. Firefox obeys the CSS following "#media only screen and (max-width: 768px)". However, when one tries to set event handlers depending on device widths, Firefox fails miserably. I needed the above trick with 0.5 second wait at all spots where I picked up the device width. This wait time was necessary for Nexus 7 (2012), but who knows what is needed for other devices?
I can confirm the issue, for example in Firefox 38.0.1 on Android 4.1.2. Created a js bin for testing purposes.
I'd like to check window.innerWidth for custom DOM manipulations on different resolutions (mobile, tablet and desktop size), so it'd be important to get the correct window.innerWidth value already in the document.ready() state and not just only in the window.load().
$('#inline').html($(window).width());
$(document).ready(function() {
$('#ready').html(window.innerWidth);
});
$(window).load(function() {
$('#load').html(window.innerWidth);
});
setTimeout(function() {
$('#setTimeout').html(window.innerWidth);
}, 1000);
<!DOCTYPE html>
<html>
<head>
<script src="https://code.jquery.com/jquery-1.9.1.min.js"></script>
<meta charset="utf-8">
<meta name="viewport" content="width=device-width, initial-scale=1">
<title>JS Bin</title>
</head>
<body>
<p><span id="inline"></span></p>
<p>$(document).ready(): <span id="ready"></span></p>
<p>$(window).load(): <span id="load"></span></p>
<p>setTimeout(1000): <span id="setTimeout"></span></p>
</body>
</html>
(I wanted to add only a comment, and not answer, but no reputations yet to do so :-)
I was facing the same issue while using BrowserComponent in CodeNameOne and Android
My solution was to put the js inside a function like so
function runScripts()
{
//get width here
}
And listen to the onLoad event of the BrowserComponent to execute this script once the browser has been fully loaded
like so:
BrowserComponent browser = new BrowserComponent();
browser.addWebEventListener("onLoad", new ActionListener() {
public void actionPerformed(ActionEvent evt) {
browser.execute("runScripts()");
}
});
browser.setURL("http://www.URL.com");
Handling window.onload in the html wasn't enough to wait for the appropriate width to be served
Besides this solution I also found that window.setTimeout(runScripts, 500); works to get the right document width, at the expense of wasting half a second
window.setTimeout(yourFunction, 1);
This did the job for me, 1ms is enough.
A very hack solution I found is to invoke a fake link in the header. My guess is the time delay allows updating of window.innerWidth and window.innerHeight prior to script execution.
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/fake.css"/>
I had the same problem, getting varying width when fetching window.innerWidth on an android device with Firefox. I tried some of the suggestions above, but without success - possibly implementing the examples in a wrong way?
However, by using the code below, I got a system that seems to be working 100% as far as I have tested. It also makes little delay as it break the loop as soon as it get a stable result.
var canvasWidth = 0;
var canvasHeight = 0;
var previousWidth = -1;
var previousHeight = -1;
while ((canvasWidth != previousWidth) || (canvasHeight != previousHeight))
{
previousWidth = canvasWidth;
previousHeight = canvasHeight;
canvasWidth = window.innerWidth;
canvasHeight = window.innerHeight;
}

Browser width for mobile

I have a Nexus 5, and when I go to http://ryanve.com/lab/dimensions/, it tells me that my width 360. I understand that there is a difference between my phone's resolution and the width of my browser.
However, when I write a function to change at under 767:
function detectmob() {
if($(window).width() <= 767) {
return true;
}
else {
return false;
}
}
if (detectmob()){
}
else {
}
It doesn't work on my phone. If I resize my browser window width to be <= 767 on my laptop, the function works correctly. When I view it on my Nexus 5, it doesn't.
Could anyone help me write a function to target mobile devices using the browser width?
When you visit a website via a mobile browser it will assume that you're viewing a big desktop experience and that you want to see all of it, not just the top left corner. It will therefore set the viewport width at (in the case of iOS Safari) 980px, shoe-horning everything into its little display.
The Viewport Meta Tag
Enter the viewport meta tag, introduced by Apple, then adopted and developed further by others.
It looks like this:
<meta name="viewport" content="">
Within the content="" you can enter a load of comma delimited values, but we're going to to focus on the fundamental ones for now.
For example, if your mobile design is purposely laid out at 320px you can specify the viewport width:
<meta name="viewport" content="width=320">
http://webdesign.tutsplus.com/articles/quick-tip-dont-forget-the-viewport-meta-tag--webdesign-5972

What is the difference between window.innerWidth window.outerWidth?

I examined the window object in Firebug. window.innerWidth and window.outerWidth are both 1230.
What is the difference between these two values?
From Mozilla Developer Network:
window.outerWidth
window.outerWidth gets the width of the outside of the browser window.
It represents the width of the whole browser window including sidebar
(if expanded), window chrome and window resizing borders/handles.
and
window.innerWidth
Width (in pixels) of the browser window viewport including, if
rendered, the vertical scrollbar.
This is ostensibly how they work. A test page, however, shows they are both the same no matter how I resize them in Firefox 14.0.1 on Ubuntu 12.04. In Chromium, they return numbers that are 8 pixels different. Doing a bit of dead reckoning, it appears the window chrome on that particular app is about 4 pixels on the left side and 4 pixels on the right side and that this difference is being correctly picked up in that browser.
Code for the test page I used:
<!DOCTYPE html>
<html lang="en">
<head>
<title>12066093</title>
<meta charset="utf-8">
</head>
<body>
<div style="width:2000px; height: 2000px;">hi</div>
<script type="text/javascript">
alert("window.innerWidth: " + window.innerWidth + "\nwindow.outerWidth: " + window.outerWidth);
</script>
</body>
</html>
Check the Mozilla reference for window.innerWidth and window.outerWidth. If your operating system/window manager has them, window.outerWidth includes the window borders, resizing handles, and sidebars.
Try opening the bookmarks or history sidebar, then trying that again in Firebug.

Categories