OrientationChange acts weird - javascript

I have a website which should show an image when the browser is in portrait mode, and hide it again when in landscape. I have tested this feature with chrome responsive mode and there it acts fine, but when trying to run the site on iphone or ipad the feature acts up. Code looks like this
let mql = window.matchMedia("(orientation: portrait)")
window.onorientationchange = rotate;
function rotate() {
if(mql.matches) {
document.querySelector("#rotation").classList.remove("hide");
document.querySelector("#game").classList.add("hide");
} else {
document.querySelector("#rotation").classList.add("hide");
document.querySelector("#game").classList.remove("hide");
}
}
The way it acts on iphone and ipad is that #rotation shows when in landscape and hides when in portrait, which is basically the total opposite of the code, as I read it.
Is anyone familiar with this issue, and anyone know of a fix for it?
thanks in advance

I think instead calling that function window.onorientationchange = rotate;
you should do following
let mql = window.matchMedia("(orientation: portrait)")
function rotate(event) {
if(event.matches) {
document.querySelector("#rotation").classList.remove("hide");
document.querySelector("#game").classList.add("hide");
} else {
document.querySelector("#rotation").classList.add("hide");
document.querySelector("#game").classList.remove("hide");
}
}
// this addListner is going to deprecate soon
mql.addListner(rotate);
// you can use below if you don't want to support <= iOS 13 browsers
// Ref: https://developer.mozilla.org/en-US/docs/Web/API/MediaQueryList
mql.addEventListner("change", rotate);

Related

On iOS Safari, window.scrollTo doesn't work after orientation change

In short:
In iOS Safari, window.scrollTo method doesn't do anything if called from orientationchange event handler. It seems like a certain amount of time (500-1000ms) must pass before you can modify scroll position after orientation change.
Is there a workaround to change scroll position immediately and avoid the problem when user can see old scroll position for a moment after orientation change?
Detailed problem description:
I need to implement the following feature for mobile browsers:
When the user switches to landscape mode, he should see fullscreen video. When he switches back to portrait, he should be returned to exact same place where he left off.
The second part is the problem. Both iOS and Android will keep scroll position if you switch orientation back and forth, but only if you dont scroll the screen and dont make any adjustments to DOM. So if you just switch from portrait to landscape and back, everything works as expected. If you switch from portrait to landscape, adjust scroll position even by 1 pixel or make any changes to DOM, you will return to a different scroll position.
So I'm trying to pragmatically restore scroll position once the user returns to portrait orientation. Here's the simplified code I use:
var scrollPosition;
var savedScrollPosition;
window.addEventListener('scroll', function() {
scrollPosition = window.scrollY;
});
window.addEventListener('orientationchange', function(event) {
if (Math.abs(window.orientation) === 90) {
// This line will correctly save last scroll position for portrait orientation
savedScrollPosition = scrollPosition;
} else {
// This line will correctly try to restore previously saved scroll position
window.scrollTo(0, savedScrollPosition);
}
});
This works on android, but on iOS it doesn't. The problem is, window.scrollTo just doesn't seem to do anything until the certain time after orientation change has passed.
So if I change
window.scrollTo(0, savedScrollPosition);
to
setTimeout(function() {
window.scrollTo(0, savedScrollPosition);
}, 1000);
it works on iOS, but the user can see wrong portion of the page for a few moments, which leads to a poor user experience.
I was hoping that somebody knows a way to change scroll position on iOS immediately after orientationchage event.
Thank you.
In the end, I was forced to go with the following code:
var scrollPosition;
var savedScrollPosition;
window.addEventListener('scroll', function() {
scrollPosition = window.scrollY;
});
window.addEventListener('orientationchange', function(event) {
if (Math.abs(window.orientation) === 90) {
savedScrollPosition = scrollPosition;
} else {
if (isIOS()) {
var retryScroll = setInterval(function () {
if (window.scrollX === 0 && window.scrollY == savedScrollPosition) {
clearInterval(retryScroll);
} else {
window.scrollTo(0, savedScrollPosition);
}
}, 10 );
} else {
window.scrollTo(0, savedScrollPosition);
}
}
});
The user will see a small visual glitch, but it's still the best solution.

enhance javascript code for screen orientation

Having tried a load of different options found on SO, including jQuery mobile solutions (caused masses of conflicts with other jQuery) i found the following code would detect screen rotation and i could use it to add a class.
$(window).bind("resize", function(){
screenOrientation = ($(window).height() > $(window).width())? 90 : 0;
$('.centerBoxContentsSubCat').addClass('mobile_landscape');
});
However, I need to .removeClass when rotated the other way.
I tried duplicating the code, switching the positions of height and width, but this didn't work.
I tried changing the code to
$(window).bind("resize", function(){
if(screenOrientation = ($(window).height() > $(window).width())? 90 : 0){
$('.centerBoxContentsSubCat').addClass('mobile_landscape');
}else{
$('.centerBoxContentsSubCat').removeClass('mobile_landscape');
}
});
but that didn't work either.
I am actually using #media queries for css, but i need to force a change in a column count on screen rotate and all other attempts have failed to get even close.
Any suggestions on where I'm going wrong here?
There are two different ways you can handle this.
The first is with the event orientation change.
// Listen for orientation changes
window.addEventListener("orientationchange", function() {
// Announce the new orientation number
alert(window.orientation);
}, false);
The second is with matchMedia.
// Find matches
var mql = window.matchMedia("(orientation: portrait)");
// If there are matches, we're in portrait
if(mql.matches) {
// Portrait orientation
} else {
// Landscape orientation
}
// Add a media query change listener
mql.addListener(function(m) {
if(m.matches) {
// Changed to portrait
}
else {
// Changed to landscape
}
});
Source:
http://davidwalsh.name/orientation-change
If you need to support older browsers I recommend this library:
https://github.com/WickyNilliams/enquire.js/
You need to use the orientationchange event, not resize.

Using angularJs to modify css.height causes Internet Explorer to not scroll to the bottom of the page

When i try to dynamically set the height of a ngGrid component (using ngFlexibleHeightPlugin) I can't use the mousewheel to scroll to the bottom of the page in Internet Explorer 11 (and lower).
The issue only appears on heights larger than the screen size and only when using the mousewheel to scroll.
The critical line of code is:
self.grid.$viewport.css('height', newViewportHeight + 'px');
The mousewheel() function in the ng-grid.js is causing the issue for the Internet Explorer.
If you are comment the following block if (elm.focus) { elm.focus(); } from the ng-grid.js, it will solve the issue.
function mousewheel() {
isMouseWheelActive = true;
//if (elm.focus) { elm.focus(); }
return true;
}
Help from: https://stackoverflow.com/a/25171252/2451726

Hiding URL AddressBar on Android in Landscape Mode

Using JavaScript, how do I scroll past the URL bar in Landscape mode. On Portrait mode, you just do window.scrollTo(0,1) and that works, but not in Landscape mode. It goes part-way on the URL bar.
Any suggestions on what to try?
There is two ways of doing this. Depending on what kind of page you are displaying.
One thing to be aware of is that the mobile browser needs to have some content to scroll on. And by content to scroll on I mean that the content in the page needs to be higher then the window height. If not it's not going to scroll down at all.
Option1
Go for this if you know that your page content is more then the window height.
(function removeAddressBar(){
// Make sure it really scrolls down.
window.scrollTo(0, 10);
// Set a timeout to check that it has scrolled down.
setTimeout(function() {
if(window.scrollY == 0) {
removeAddressBar();
}else{
window.scrollTo(0, 1);
//launch();
}
}, 500);
})(this)
Option2
Go for this if you dont know if your content is more then the window height.
<div id='scroller' style='position:absolute;height:2000px;'></div>
(function removeAddressBar(){
window.scrollTo(0, 10);
setTimeout(function() {
if(window.scrollY == 0) {
removeAddressBar();
}else{
window.scrollTo(0, 1);
document.getElementById('scroller').style.height = window.innerHeight+'px';
//launch();
}
}, 500);
})(this)
This might look like a lot for such a simple thing. But I think this is the most reliable way so far.. I have tested this on iOS and Android in both orientations.
This is what worked for me:
window.screen.orientation.onchange = function() {
if (this.type.startsWith('landscape')) {
document.querySelector('#container').webkitRequestFullscreen();
} else {
document.webkitExitFullscreen();
}
};
Found that code snippet here:
https://mounirlamouri.github.io/sandbox/fullscreen-orientation.html
This works at least for Android Chrome Browsers.
It seems that that script would throw an error on IOS-Devices since they don't support the Fullscreen API. So the function should be wrapped in an if statement for checking if it's an IOS device:
var iOS = /iPad|iPhone|iPod/.test(navigator.userAgent) && !window.MSStream;

Feature detection for position: fixed

I am trying to find a script that detects if a device places position: fixed elements relative to the ViewPort and not to the entire document.
Currently, standard desktop browsers and Mobile Safari (for iOS 5) do so, whereas Android devices place the fixed elements relative to the entire document.
I have found a couple of tests to detect this, but none of the seem to work:
http://kangax.github.com/cft/ Gives me a false positive when I pass it from an Android device.
https://gist.github.com/1221602 Gives me a false negative when I pass it in an iPhone with iOS 5.
Does anybody know where to find / how to write a test that actually detects that? I don't want to rely on browser sniffing.
According to the contributors at Modernizr, you cannot do this without detecting the browser in use. The contributors are quite well-established in the field.
Testing for position: fixed on iOS and Android devices is listed under the Undetectables wiki page in the Modernizr project.
The MobileHTML5 website lists the support for position:fixed. http://mobilehtml5.org/
Actually, the guys from the Filament Group did a smart thing with their Fixedfixed putting the user agent string of known false positives in their test.
Check it # http://github.com/filamentgroup/fixed-fixed
Someone could complete it with some false negatives too, and make it a modernizr aditional featur test.
I've created another check if position:fixed is really supported in browser. It creates fixed div and try to scroll and check if the position of div changed.
function isPositionFixedSupported(){
var el = jQuery("<div id='fixed_test' style='position:fixed;top:1px;width:1px;height:1px;'></div>");
el.appendTo("body");
var prevScrollTop = jQuery(document).scrollTop();
var expectedResult = 1+prevScrollTop;
var scrollChanged = false;
//simulate scrolling
if (prevScrollTop === 0) {
window.scrollTo(0, 1);
expectedResult = 2;
scrollChanged = true;
}
//check position of div
suppoorted = (el.offset().top === expectedResult);
if (scrollChanged) {
window.scrollTo(0, prevScrollTop);
}
el.remove();
return suppoorted;
}
This function was tested in Firefox 22, Chrome 28, IE 7-10, Android Browser 2.3.

Categories

Resources