Detecting if a browser is in full screen mode - javascript

Is there any way of reliably detecting if a browser is running in full screen mode? I'm pretty sure there isn't any browser API I can query, but has anyone worked it out by inspecting and comparing certain height/width measurements exposed by the DOM? Even if it only works for certain browsers I'm interested in hearing about it.

Chrome 15, Firefox 10, and Safari 5.1 now provide APIs to programmatically trigger fullscreen mode. Fullscreen mode triggered this way provides events to detect fullscreen changes and CSS pseudo-classes for styling fullscreen elements.
See this hacks.mozilla.org blog post for details.

What about determining the distance between the viewport width and the resolution width and likewise for height. If it is a small amount of pixels (especially for height) it may be at fullscreen.
However, this will never be reliable.

Opera treats full screen as a different CSS media type. They call it Opera Show, and you can control it yourself easily:
#media projection {
/* these rules only apply in full screen mode */
}
Combined with Opera#USB, I've personally found it extremely handy.

You can check if document.fullscreenElement is not null to determine if fullscreen mode is on. You'll need to vendor prefix fullscreenElement accordingly. I would use something like this:
var fullscreenElement = document.fullscreenElement || document.mozFullScreenElement ||
document.webkitFullscreenElement || document.msFullscreenElement;
https://msdn.microsoft.com/en-us/library/dn312066(v=vs.85).aspx has a good example for this which I quote below:
document.addEventListener("fullscreenChange", function () {
if (fullscreenElement != null) {
console.info("Went full screen");
} else {
console.info("Exited full screen");
}
});

The Document read-only property returns the Element that is currently being presented in full-screen mode in this document, or null if full-screen mode is not currently in use.
if(document.fullscreenElement){
console.log("Fullscreen");
}else{
console.log("Not Fullscreen");
};
Supports in all major browsers.

Firefox 3+ provides a non-standard property on the window object that reports whether the browser is in full screen mode or not: window.fullScreen.

Just thought I'd add my thruppence to save anyone banging their heads. The first answer is excellent if you have complete control over the process, that is you initiate the fullscreen process in code. Useless should anyone do it thissen by hitting F11.
The glimmer of hope on the horizon come in the form of this W3C recommendation http://www.w3.org/TR/view-mode/ which will enable detection of windowed, floating (without chrome), maximized, minimized and fullscreen via media queries (which of course means window.matchMedia and associated).
I've seen signs that it's in the implementation process with -webkit and -moz prefixes but it doesn't appear to be in production yet.
So no, no solutions but hopefully I'll save someone doing a lot of running around before hitting the same wall.
PS *:-moz-full-screen does doo-dah as well, but nice to know about.

While searching high & low I have found only half-solutions.
So it's better to post here a modern, working approach to this issue:
var isAtMaxWidth = (screen.availWidth - window.innerWidth) === 0;
var isAtMaxHeight = (screen.availHeight - window.outerHeight <= 1);
if (!isAtMaxWidth || !isAtMaxHeight) {
alert("Browser NOT maximized!");
}
Tested and working properly in Chrome, Firefox, Edge and Opera* (*with Sidebar unpinned) as of 10.11.2019.
Testing environment (only desktop):
CHROME - Ver. 78.0.3904.97 (64-bit)
FIREFOX - Ver. 70.0.1 (64-bit)
EDGE - Ver. 44.18362.449.0 (64-bit)
OPERA - Ver. 64.0.3417.92 (64-bit)
OS - WIN10 build 18362.449 (64-bit)
Resources:
https://developer.mozilla.org/en-US/docs/Web/API/Screen/availWidth
https://developer.mozilla.org/en-US/docs/Web/API/Window/innerWidth
https://developer.mozilla.org/en-US/docs/Web/API/Screen/availHeight
https://developer.mozilla.org/en-US/docs/Web/API/Window/outerHeight

In Chrome at least:
onkeydown can be used to detect the F11 key being pressed to enter fullscreen.
onkeyup can be used to detect the F11 key being pressed to exit fullscreen.
Use that in conjunction with checking for keyCode == 122
The tricky part would be to tell the keydown/keyup not to execute its code if the other one just did.

Right. Totally late on this one...
As of 25th Nov, 2014 (Time of writing), it is possible for elements to request fullscreen access, and subsequently control entering/exiting fullscreen mode.
MDN Explanation here: https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Using_full_screen_mode
Straightforward explanation by David Walsh: http://davidwalsh.name/fullscreen

For Safari on iOS can use:
if (window.navigator.standalone) {
alert("Full Screen");
}
More:
https://developer.apple.com/library/archive/documentation/AppleApplications/Reference/SafariWebContent/ConfiguringWebApplications/ConfiguringWebApplications.html

This works for all new browsers :
if (!window.screenTop && !window.screenY) {
alert('Browser is in fullscreen');
}

There is my NOT cross-browser variant:
<!DOCTYPE html>
<html>
<head>
<title>Fullscreen</title>
</head>
<body>
<script src="//ajax.googleapis.com/ajax/libs/jquery/1.11.0/jquery.min.js"></script>
<script type="text/javascript">
var fullscreen = $(window).height() + 1 >= screen.height;
$(window).on('resize', function() {
if (!fullscreen) {
setTimeout(function(heightStamp) {
if (!fullscreen && $(window).height() === heightStamp && heightStamp + 1 >= screen.height) {
fullscreen = true;
$('body').prepend( "<div>" + $( window ).height() + " | " + screen.height + " | fullscreen ON</div>" );
}
}, 500, $(window).height());
} else {
setTimeout(function(heightStamp) {
if (fullscreen && $(window).height() === heightStamp && heightStamp + 1 < screen.height) {
fullscreen = false;
$('body').prepend( "<div>" + $( window ).height() + " | " + screen.height + " | fullscreen OFF</div>" );
}
}, 500, $(window).height());
}
});
</script>
</body>
</html>
Tested on:
Kubuntu 13.10:
Firefox 27 (<!DOCTYPE html> is required, script correctly works with dual-monitors), Chrome 33, Rekonq - pass
Win 7:
Firefox 27, Chrome 33, Opera 12, Opera 20, IE 10 - pass
IE < 10 - fail

My solution is:
var fullscreenCount = 0;
var changeHandler = function() {
fullscreenCount ++;
if(fullscreenCount % 2 === 0)
{
console.log('fullscreen exit');
}
else
{
console.log('fullscreened');
}
}
document.addEventListener("fullscreenchange", changeHandler, false);
document.addEventListener("webkitfullscreenchange", changeHandler, false);
document.addEventListener("mozfullscreenchange", changeHandler, false);
document.addEventListener("MSFullscreenChanges", changeHandler, false);

This is the solution that I've come to...
I wrote it as an es6 module but the code should be pretty straightforward.
/**
* Created by sam on 9/9/16.
*/
import $ from "jquery"
function isFullScreenWebkit(){
return $("*:-webkit-full-screen").length > 0;
}
function isFullScreenMozilla(){
return $("*:-moz-full-screen").length > 0;
}
function isFullScreenMicrosoft(){
return $("*:-ms-fullscreen").length > 0;
}
function isFullScreen(){
// Fastist way
var result =
document.fullscreenElement ||
document.mozFullScreenElement ||
document.webkitFullscreenElement ||
document.msFullscreenElement;
if(result) return true;
// A fallback
try{
return isFullScreenMicrosoft();
}catch(ex){}
try{
return isFullScreenMozilla();
}catch(ex){}
try{
return isFullScreenWebkit();
}catch(ex){}
console.log("This browser is not supported, sorry!");
return false;
}
window.isFullScreen = isFullScreen;
export default isFullScreen;

2021, the Fullscreen API is available. It's a Living Standard and is supported by all browsers (except the usual suspects - IE11 and iOS Safari).
// toggle fullscreen
if (!document.fullscreenElement) {
// enter fullscreen
if (docElm.requestFullscreen) {
console.log('entering fullscreen')
docElm.requestFullscreen()
}
} else {
// exit fullscreen
if (document.exitFullscreen) {
console.log('exiting fullscreen')
document.exitFullscreen()
}
}

User window.innerHeight and screen.availHeight. Also the widths.
window.onresize = function(event) {
if (window.outerWidth === screen.availWidth && window.outerHeight === screen.availHeight) {
console.log("This is your MOMENT of fullscreen: " + Date());
}

To detect whether browser is in fullscreen mode:
document.webkitIsFullScreen || document.mozFullScreen || document.msFullscreenElement
according to caniuse you should be fine for majority of browsers.

This property returns the Element that is currently in fullscreen mode.
document.fullscreenElement; // HTML Element or null
Also, you can subscribe to fullscreen change events with this method
addEventListener('fullscreenchange', (event) => { });
You can combine both to detect the nature of the change
addEventListener('fullscreenchange', () => {
if (document.fullscreenElement) {
// Your Logic if fullscreen
}
});
More on this here.

You can detect full screen using CSS like this:
#media all and (display-mode: fullscreen) {
// Regular CSS to be applied in full-screen mode
}

Related

Detecting the opening or closing of a virtual keyboard on a touchscreen device

I have an inelegant workaround for this issue, and am hoping that others may already have more robust solutions.
On a touchscreen, tapping on an editable text field will bring up an on-screen keyboard, and this will change the amount of screen space available. Left untreated, this may hide key elements, or push a footer out of place.
On a laptop or desktop computer, opening an editable text field creates no such layout changes.
In my current project, I want to ensure that certain key items are visible even when a virtual keyboard is open, so I need to detect when such a change occurs. I can then add a class to the body element, to change the layout to suit the presence of the keyboard.
When searching for existing solutions online, I discovered that:
There is no perfect way of knowing that your code is running on a mobile device
There are non-mobile devices that have touchscreens, and which may also have keyboards
A focus element may not be editable
contentEditable elements will open the on-screen keyboard
The address bar may decide to reappear and take up essential screen space at the same time the virtual keyboard appears, squeezing the available space even more.
I have posted the solution that I have come up with below. It relies on detecting a change in height of the window within a second of the keyboard focus changing. I am hoping that you might have a better solution to propose that has been tested cross-platform, cross-browser and across devices.
I've created a repository on GitHub.
You can test my solution here.
In my tests, this may give a false positive if the user is using a computer with a touchscreen and a keyboard and mouse, and uses the mouse first to (de-)select an editable element and then immediately changes the window height. If you find other false positives or negatives, either on a computer or a mobile device, please let me know.
;(function (){
class Keyboard {
constructor () {
this.screenWidth = screen.width // detect orientation
this.windowHeight = window.innerHeight // detect keyboard change
this.listeners = {
resize: []
, keyboardchange: []
, focuschange: []
}
this.isTouchScreen = 'ontouchstart' in document.documentElement
this.focusElement = null
this.changeFocusTime = new Date().getTime()
this.focusDelay = 1000 // at least 600 ms is required
let focuschange = this.focuschange.bind(this)
document.addEventListener("focus", focuschange, true)
document.addEventListener("blur", focuschange, true)
window.onresize = this.resizeWindow.bind(this)
}
focuschange(event) {
let target = event.target
let elementType = null
let checkType = false
let checkEnabled = false
let checkEditable = true
if (event.type === "focus") {
elementType = target.nodeName
this.focusElement = target
switch (elementType) {
case "INPUT":
checkType = true
case "TEXTAREA":
checkEditable = false
checkEnabled = true
break
}
if (checkType) {
let type = target.type
switch (type) {
case "color":
case "checkbox":
case "radio":
case "date":
case "file":
case "month":
case "time":
this.focusElement = null
checkEnabled = false
default:
elementType += "[type=" + type +"]"
}
}
if (checkEnabled) {
if (target.disabled) {
elementType += " (disabled)"
this.focusElement = null
}
}
if (checkEditable) {
if (!target.contentEditable) {
elementType = null
this.focusElement = null
}
}
} else {
this.focusElement = null
}
this.changeFocusTime = new Date().getTime()
this.listeners.focuschange.forEach(listener => {
listener(this.focusElement, elementType)
})
}
resizeWindow() {
let screenWidth = screen.width;
let windowHeight = window.innerHeight
let dimensions = {
width: innerWidth
, height: windowHeight
}
let orientation = (screenWidth > screen.height)
? "landscape"
: "portrait"
let focusAge = new Date().getTime() - this.changeFocusTime
let closed = !this.focusElement
&& (focusAge < this.focusDelay)
&& (this.windowHeight < windowHeight)
let opened = this.focusElement
&& (focusAge < this.focusDelay)
&& (this.windowHeight > windowHeight)
if ((this.screenWidth === screenWidth) && this.isTouchScreen) {
// No change of orientation
// opened or closed can only be true if height has changed.
//
// Edge case
// * Will give a false positive for keyboard change.
// * The user has a tablet computer with both screen and
// keyboard, and has just clicked into or out of an
// editable area, and also changed the window height in
// the appropriate direction, all with the mouse.
if (opened) {
this.keyboardchange("shown", dimensions)
} else if (closed) {
this.keyboardchange("hidden", dimensions)
} else {
// Assume this is a desktop touchscreen computer with
// resizable windows
this.resize(dimensions, orientation)
}
} else {
// Orientation has changed
this.resize(dimensions, orientation)
}
this.windowHeight = windowHeight
this.screenWidth = screenWidth
}
keyboardchange(change, dimensions) {
this.listeners.keyboardchange.forEach(listener => {
listener(change, dimensions)
})
}
resize(dimensions, orientation) {
this.listeners.resize.forEach(listener => {
listener(dimensions, orientation)
})
}
addEventListener(eventName, listener) {
// log("*addEventListener " + eventName)
let listeners = this.listeners[eventName] || []
if (listeners.indexOf(listener) < 0) {
listeners.push(listener)
}
}
removeEventListener(eventName, listener) {
let listeners = this.listeners[eventName] || []
let index = listeners.indexOf(listener)
if (index < 0) {
} else {
listeners.slice(index, 1)
}
}
}
window.keyboard = new Keyboard()
})()
There is a new experimental API that is meant exactly to track size changes due to the keyboard appearing and other mobile weirdness like that.
window.visualViewport
https://developer.mozilla.org/en-US/docs/Web/API/Visual_Viewport_API
By listening to resize events and comparing the height to the height to the so called "layout viewport". See that it changed by a significant amount, like maybe 30 pixels. You might deduce something like "the keyboard is showing".
if('visualViewport' in window) {
window.visualViewport.addEventListener('resize', function(event) {
if(event.target.height + 30 < document.scrollElement.clientHeight) {
console.log("keyboard up?");
} else {
console.log("keyboard down?");
}
});
}
(code above is untested and I suspect zooming might trigger false positive, might have to check for scaling changes as well)
As no direct way to detect the keyboard opening, you can only detect by the height and width. See more
In javascript screen.availHeight and screen.availWidth maybe help.
Using visualViewPort
This was inspired by on-screen-keyboard-detector. It works on Android and iOS.
if ('visualViewport' in window) {
const VIEWPORT_VS_CLIENT_HEIGHT_RATIO = 0.75;
window.visualViewport.addEventListener('resize', function (event) {
if (
(event.target.height * event.target.scale) / window.screen.height <
VIEWPORT_VS_CLIENT_HEIGHT_RATIO
)
console.log('keyboard is shown');
else console.log('keyboard is hidden');
});
}
Another approach using virtualKeyboard
This worked, but isn't supported in iOS yet.
if ('virtualKeyboard' in navigator) {
// Tell the browser you are taking care of virtual keyboard occlusions yourself.
navigator.virtualKeyboard.overlaysContent = true;
navigator.virtualKeyboard.addEventListener('geometrychange', (event) => {
const { x, y, width, height } = event.target.boundingRect;
if (height > 0) console.log('keyboard is shown');
else console.log('keyboard is hidden');
});
Source: https://developer.chrome.com/docs/web-platform/virtual-keyboard/
This is a difficult problem to get 'right'. You can try and hide the footer on input element focus, and show on blur, but that isn't always reliable on iOS. Every so often (one time in ten, say, on my iPhone 4S) the focus event seems to fail to fire (or maybe there is a race condition with JQuery Mobile), and the footer does not get hidden.
After much trial and error, I came up with this interesting solution:
<head>
...various JS and CSS imports...
<script type="text/javascript">
document.write( '<style>#footer{visibility:hidden}#media(min-height:' + ($( window ).height() - 10) + 'px){#footer{visibility:visible}}</style>' );
</script>
</head>
Essentially: use JavaScript to determine the window height of the device, then dynamically create a CSS media query to hide the footer when the height of the window shrinks by 10 pixels. Because opening the keyboard resizes the browser display, this never fails on iOS. Because it's using the CSS engine rather than JavaScript, it's much faster and smoother too!
Note: I found using 'visibility:hidden' less glitchy than 'display:none' or 'position:static', but your mileage may vary.
I'm detecting the visibility of a virtual keyboard as follows:
window.addEventListener('resize', (event) => {
// if current/available height ratio is small enough, virtual keyboard is probably visible
const isKeyboardHidden = ((window.innerHeight / window.screen.availHeight) > 0.6);
});

Mobile Safari, scrollIntoView doesn't work

I have a problem with scroll to element on mobile Safari in iframe (it works on other browsers, including Safari on mac).
I use scrollIntoView. I want to scroll when all content has been rendered. Here is my code:
var readyStateCheckInterval = setInterval(function () {
if (document.readyState === "complete") {
clearInterval(readyStateCheckInterval);
$browser.notifyWhenNoOutstandingRequests(function () {
if (cinemaName != null && eventId == null) {
scrollToCinema();
} else {
scrollToEvent();
}
});
}
}, 10);
function scrollToEvent() {
var id = eventId;
var delay = 100;
if (cinemaName != null) {
id = cinemaName + "#" + eventId;
}
if ($rootScope.eventId != null) {
id = $rootScope.cinemaId + "#" + $rootScope.eventId;
}
$timeout(function () {
var el = document.getElementById(id);
if (el != null)
el.scrollIntoView(true);
$rootScope.eventId = null;
}, delay);
}
ScrollIntoView does not work (currently). But you can manually calculate the position of the element and scroll to it. Here is my solution
const element = document.getElementById('myId')
Pass the element to this function
/** Scrolls the element into view
* Manually created since Safari does not support the native one inside an iframe
*/
export const scrollElementIntoView = (element: HTMLElement, behavior?: 'smooth' | 'instant' | 'auto') => {
let scrollTop = window.pageYOffset || element.scrollTop
// Furthermore, if you have for example a header outside the iframe
// you need to factor in its dimensions when calculating the position to scroll to
const headerOutsideIframe = window.parent.document.getElementsByClassName('myHeader')[0].clientHeight
const finalOffset = element.getBoundingClientRect().top + scrollTop + headerOutsideIframe
window.parent.scrollTo({
top: finalOffset,
behavior: behavior || 'auto'
})
}
Pitfalls: Smooth scroll also does not work for ios mobile, but you can complement this code with this polyfill
In my experience scrollIntoView() fails sometimes on my iphone and my ipad and sometimes it works (on my own web sites). I'm not using iframes. This is true both with safari and firefox on the above devices.
The solution that works for me is to pop the element you need to scroll to inside a DIV eg. as the first element in that DIV. Hey presto it then works fine!
Seems like a dodgy implementation by Apple.
Your most likely having the exact same issue I just debugged. Safari automatically resizes the frame to fit it's contents. Therefore, the parent of the Iframe will have the scrollbars in Safari. So calling scrollintoview from within the Iframe itself 'fails'.
If Iframe is cross domain accessing the parent document via window.parent.document will be denied.
If you need a cross domain solution check my answer here.
Basically I use post message to tell the parent page to do the scrolling itself when inside Mobile Safari cross domain.

Detect if user is using webview for android/iOS or a regular browser

How to detect if the user is browsing the page using webview for android or iOS?
There are various solutions posted all over stackoverflow, but we don't have a bulletproof solution yet for both OS.
The aim is an if statement, example:
if (android_webview) {
jQuery().text('Welcome webview android user');
} else if (ios_webview) {
jQuery().text('Welcome webview iOS user');
} else if (ios_without_webview) {
// iOS user who's running safari, chrome, firefox etc
jQuery().text('install our iOS app!');
} else if (android_without_webview) {
// android user who's running safari, chrome, firefox etc
jQuery().text('install our android app!');
}
What I've tried so far
Detect iOS webview (source):
if (navigator.platform.substr(0,2) === 'iP'){
// iOS (iPhone, iPod, iPad)
ios_without_webview = true;
if (window.indexedDB) {
// WKWebView
ios_without_webview = false;
ios_webview = true;
}
}
Detect android webview, we have a number of solutions like this and this. I'm not sure what's the appropriate way to go because every solution seems to have a problem.
Detecting browser for iOS devices is different from the Android one. For iOS devices you can do it by checking user agent using JavaScript:
var userAgent = window.navigator.userAgent.toLowerCase(),
safari = /safari/.test( userAgent ),
ios = /iphone|ipod|ipad/.test( userAgent );
if( ios ) {
if ( safari ) {
//browser
} else if ( !safari ) {
//webview
};
} else {
//not iOS
};
For Android devices, you need to do it through server side coding to check for a request header.
PHP:
if ($_SERVER['HTTP_X_REQUESTED_WITH'] == "your.app.id") {
//webview
} else {
//browser
}
JSP:
if ("your.app.id".equals(req.getHeader("X-Requested-With")) ){
//webview
} else {
//browser
}
Ref:detect ipad/iphone webview via javascript
Note: This solution is PHP-based. HTTP headers can be faked so this is not the nicest solution but you can have a start with this.
//For iOS
if ((strpos($_SERVER['HTTP_USER_AGENT'], 'Mobile/') !== false) && (strpos($_SERVER['HTTP_USER_AGENT'], 'Safari/') == false) {
echo 'WebView';
} else{
echo 'Not WebView';
}
//For Android
if ($_SERVER['HTTP_X_REQUESTED_WITH'] == "com.company.app") {
echo 'WebView';
} else{
echo 'Not WebView';
}
For me this code worked:
var standalone = window.navigator.standalone,
userAgent = window.navigator.userAgent.toLowerCase(),
safari = /safari/.test(userAgent),
ios = /iphone|ipod|ipad/.test(userAgent);
if (ios) {
if (!standalone && safari) {
// Safari
} else if (!standalone && !safari) {
// iOS webview
};
} else {
if (userAgent.includes('wv')) {
// Android webview
} else {
// Chrome
}
};
This is the extended version of rhavendc's answer. It can be used for showing app install banner when a website is visited from browser, and hiding the banner when a website is opened in a webview.
$iPhoneBrowser = stripos($_SERVER['HTTP_USER_AGENT'], "iPhone");
$iPadBrowser = stripos($_SERVER['HTTP_USER_AGENT'], "iPad");
$AndroidBrowser = stripos($_SERVER['HTTP_USER_AGENT'], "Android");
$AndroidApp = $_SERVER['HTTP_X_REQUESTED_WITH'] == "com.company.app";
$iOSApp = (strpos($_SERVER['HTTP_USER_AGENT'], 'Mobile/') !== false) && (strpos($_SERVER['HTTP_USER_AGENT'], 'Safari/') == false);
if ($AndroidApp) {
echo "This is Android application, DONT SHOW BANNER";
}
else if ($AndroidBrowser) {
echo "This is Android browser, show Android app banner";
}
else if ($iOSApp) {
echo "This is iOS application, DONT SHOW BANNER";
}
else if($iPhoneBrowser || $iPadBrowser) {
echo "This is iOS browser, show iOS app banner";
}
Complementing the above answers,
to find out if it's webview on newer versions of android, you can use the expression below:
const isWebView = navigator.userAgent.includes ('wv')
See details of this code at https://developer.chrome.com/multidevice/user-agent#webview_user_agent.
For anyone out there who is having issues in year 2022 with apple deciding to drop 'ipad' in the useragent, I had to tweak the script a little to make it work:
function isWebview() {
if (typeof window === undefined) { return false };
let navigator = window.navigator;
const standalone = navigator.standalone;
const userAgent = navigator.userAgent.toLowerCase();
const safari = /safari/.test(userAgent);
const ios = /iphone|ipod|ipad/macintosh.test(userAgent);
const ios_ipad_webview = ios && !safari;
return ios ? ( (!standalone && !safari) || ios_ipad_webview ) : userAgent.includes('wv');
}
I found this simple-to-use package is-ua-webview
intall: $ npm install is-ua-webview
Javascript:
var isWebview = require('is-ua-webview');
var some_variable = isWebview(navigator.userAgent);
Angular2+:
import * as isWebview from 'is-ua-webview';
const some_variable = isWebview(navigator.userAgent);
If you're using Flask (and not PHP), you can check to see if "wv" is in the string for the "User-Agent" header. Feel free to edit / add a more precise way of checking it, but basically "wv" is put there if it's a web view; otherwise, it is not there.
user_agent_header = request.headers.get('User-Agent', None)
is_web_view = "wv" in str(header_request) if user_agent_header is not None else False
Chrome Developer Docs:
WebView UA in Lollipop and Above
In the newer versions of WebView, you can differentiate the WebView by
looking for the wv field as highlighted below.
Mozilla/5.0 (Linux; Android 5.1.1; Nexus 5 Build/LMY48B; wv)
AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Chrome/43.0.2357.65
Mobile Safari/537.36
A simple solution that is found for this issue is passing a parameter in url when hitting webview and check if the parameter exists and is it from android or IOS. It works only when you have access to App source code.
otherwise you can check for user agent of request.
I came to decision, that instead of detection, more efficient solution simply specify platform in AppConfig.
const appConfig = {
appID: 'com.example.AppName.Web'
//or
//appID: 'com.example.AppName.MobileIOS'
//or
//appID: 'com.example.AppName.MobileAndroid'
}
The following works for me as well: (in case you get puzzled and undefined index for $_SERVER['HTTP_X_REQUESTED_WITH'])
if (isset($_SERVER['HTTP_X_REQUESTED_WITH']) && $_SERVER['HTTP_X_REQUESTED_WITH'] == "com.systechdigital.bgmea") {
// web view Android
} else if ( (strpos($_SERVER['HTTP_USER_AGENT'], 'Mobile/') !== false) && (strpos($_SERVER['HTTP_USER_AGENT'], 'Safari/') == false) ) {
// web view iOS
}
else {
// responsive mobile view or others (e.g. desktop)
}
WebView UA in Lollipop and Above
In the newer versions of WebView, you can differentiate the WebView by
looking for the wv field as highlighted below.
More Details - https://developer.chrome.com/docs/multidevice/user-agent/
Updated the solution using TypeScript: https://codepen.io/davidrl1000/pen/YzeaMem
const isWebview = () => {
if (typeof window === undefined) { return false };
let navigator: any = window.navigator;
const standalone = navigator.standalone;
const userAgent = navigator.userAgent.toLowerCase();
const safari = /safari/.test(userAgent);
const ios = /iphone|ipod|ipad/.test(userAgent);
return ios ? !standalone && !safari : userAgent.includes('wv');
}
Previous answers doesn't take into consideration the Android Version being used
I tried to make a script that is valid for all android versions
<script>
var isWebView = false;
var userAgent = navigator.userAgent;
if (/Android/.test(userAgent)) {
// Check the Android version to determine how to differentiate WebView from Chrome
var androidVersion = parseFloat(userAgent.slice(userAgent.indexOf("Android")+8));
if (androidVersion >= 10) {
// For Android 10 and above, check for the "wv" field in the user-agent string
isWebView = /(wv)/.test(userAgent);
} else {
// For versions of Android below 10, check for the "Version/_X.X_" string in the user-agent string
isWebView = userAgent.includes("Version/");
}
}
if (isWebView) {
// user is viewing page from WebView
} else {
//user is not using WebView
}
</script>
For iOS I've found that you can reliably identify if you're in a webview (WKWebView or UIWebView) with the following:
var isiOSWebview = (navigator.doNotTrack === undefined && navigator.msDoNotTrack === undefined && window.doNotTrack === undefined);
Why it works:
All modern browsers (including webviews on Android) seem to have some sort of implementation of doNotTrack except webviews on iOS. In all browsers that support doNotTrack, if the user has not provided a value, the value returns as null, rather than undefined - so by checking for undefined on all the various implementations, you ensure you're in a webview on iOS.
Note:
This will identify Chrome, Firefox, & Opera on iOS as being a webview - that is not a mistake. As noted in various places online, Apple restricts 3rd party browser developers on iOS to UIWebView or WKWebView for rendering content - so all browsers on iOS are just wrapping standard webviews except Safari.
If you need to know you're in a webview, but not in a 3rd party browser, you can identify the 3rd party browsers by their respective user agents:
(isiOSWebview && !(/CriOS/).test(navigator.userAgent) && !(/FxiOS/).test(navigator.userAgent) && !(/OPiOS/).test(navigator.userAgent)

JQuery scrollTop - cross browser compatibility issues

Yesterday I had an issue with a JQuery scrolling script that worked in Chrome but not in IE and Firefox. I asked this query (JQuery scroll() / scrollTop() not working in IE or Firefox) yesterday which I marked as being the correct answer only to realise today that it doesn't work in Chrome anymore!
Can anyone help me get this working on all modern browsers?
HTML
<div id="dotted-line">
<div id="up-arrow">^up</div>
</div>
JQuery
//get window size values (cross browser compatible)
(function(undefined) {
var container = $("html,body");
$.windowScrollTop = function(newval) {
if( newval === undefined) {
return container.scrollTop();
}
else {
return container.scrollTop(newval);
}
}
})();
//draw dotted line on scroll
$(window).scroll(function(){
if ($.windowScrollTop() > 10) {
var pos = $.windowScrollTop();
$('#dashes').css('height',pos/4);
$('#footer-dot').css('top',pos/4);
} else {
$('#dashes').css('height','6px');
$('#footer-dot').css('top','-150px');
}
});
scrollTop() will return value of only first matched element in set
$('html,body'), that's why it no more works on chrome
I think your best bet would be to use:
var container = $(document.scrollingElement || "html");

JavaScript Full Screen in Window Mode

There is a site that I go on and it requires me to be in full screen mode and if I leave full screen it cancels out what I am doing on the site. Is there a way I could modify my FireFox or Safari browser to trick the JavaScript to let me have it in a window mode so I can leave it without it knowing?
Thanks!
This should help:
window.onload = maxWindow;
function maxWindow() {
window.moveTo(0, 0);
if (document.all) {
top.window.resizeTo(screen.availWidth, screen.availHeight);
}
else if (document.layers || document.getElementById) {
if (top.window.outerHeight < screen.availHeight || top.window.outerWidth < screen.availWidth) {
top.window.outerHeight = screen.availHeight;
top.window.outerWidth = screen.availWidth;
}
}
}
I believe this will be useful for you this website that does exactly what you wanna.
http://sindresorhus.com/screenfull.js/

Categories