Skip to content
This repository

get_orientation() and hence getScreenHeight() doesn't work on some devices #2933

Closed
dmfallak opened this Issue November 04, 2011 · 19 comments

4 participants

Devin Fallak Todd Parker claudiuchetan Kin Blas
Devin Fallak

This problem is reproducible only in the JQueryMobile 1.0RC2 release, and wasn't reproducible in beta 2.

On iPad 2 with iOS 5, I observe that window.orientation is -90 when in landscape mode. However on Thinkpad running Android 3.1, window.orientation is 0 when in landscape mode. When running Playbook OS 2, window.orientation is also 0 when in landscape mode. Because of this, jQuery.event.special.orientationchange.orientation() returns the wrong value on Android and Playbook but the right value on iPad.

It seems like using window.orientation to determine whether the device is in landscape or portrait is not a reliable way of doing it. Maybe it would be best to determine this by checking whether the windows dimensions are wider or taller?

Here is a test page that demonstrates this issue:

<html>
   <head>
      <link href="jquery.mobile.css" rel="stylesheet"></link>
      <script src="jquery-1.6.3.js"></script>
      <script src="jquery.mobile.js"></script>
      <script type="text/javascript">
         $(document).ready(function(){
            $('#text').text("Orientation is: " + jQuery.event.special.orientationchange.orientation() + ", window.orientation is " + window.orientation)

            $(window).bind('resize', function(){
               $('#text').text("Orientation is: " + jQuery.event.special.orientationchange.orientation() + ",     window.orientation is " + window.orientation)
            })
         })
      </script>
      <title>Test Orientation</title>
   </head>
   <body>
      <h1 id="text"></h1>
   </body>
</head>
Todd Parker

Thanks for reporting. Can you please use this template to create a test page:
http://jsbin.com/okuqug/edit

Devin Fallak

Thanks, I have created a test page at:

http://jsbin.com/okuqug/5

claudiuchetan

This happens also on iPhone 4 with iOS 4.3 . Issue #3003 referenced above.

claudiuchetan

Any updates on this issue? I've retested it with 1.0 and its still there. Seems like a pretty important bug since the application is rendered unusable after an orientation switch.

Todd Parker

Just bumped up the priority on this, we'll take a look soon.

Kin Blas

Ok just an update on this. @toddparker and I have been playing around with orientation on some devices:

http://goo.gl/ZoQ4u

And it seems with the devices in question, the default orientation for the devices in question seem to be landscape instead of portrait (as with iOS devices and smartphones). What I mean by this is that for all iOS devices and smartphones, the window.orientation value of 0 and 180 mean portrait, while -90 and 90 mean landscape. For the devices in question, including the Motorola Xoom (running Android 3.2), 0 and 180 mean landscape, and -90 and 90 mean portrait which is the direct opposite.

Now our first instinct is to rely on dimensions to determine orientation, but the problem is that even dimensions can be unreliable depending on when you access/query them. For example on some devices, at the time orientationchange is fired, the viewport and document dimensions have not been updated to reflect the new orientation, instead, they might be updated when the resize event fires.

Another possible wrinkle is that from previous testing (maybe about a year or so ago) I seem to remember that the width and zoom settings of the viewport meta tag also had some influence on whether or not a resize event was dispatched after an orientationchange ... because the viewport just gets visually scaled/zoomed to fit the new device width, so the document width/height does not change.

The ideal solution would be to figure out if there is a way to get the "default" orientation and map that to 0 and 180. Barring that, I think we may be able to figure out what the default orientation mapping is with a bit of supports hackery learned from @scottjehl and the modernizr crew ... it goes something like this:

At load time, we inject a dummy element along with a media query that sets one of its dimensions based on orientation:

@media all and (orientation: portrait) { #dummy { width: 5px } }

If we then read the width of the dummy element and it is 5px, we know it is in portrait mode, and whatever the current value of window.orientation is will map to portrait. That is if it is currently 90 or -90, then we know we should be using flipped values when determining orientation.

@toddparker @scottjehl @Wilto thoughts?

Kin Blas

@toddparker @scottjehl @Wilto

Ok, the trick I described above seems to work. You can see it in action here:

http://goo.gl/WvGyx

The test above reports the correct orientation for all the devices I tried. I'll work it into a real fix in a bit. The code used in the sample above looks like this:

$.mobile.portraitOrientationVals = { "0": true, "180": true };

if ( $.support.orientation ) {
    var isPortraitMode = $.mobile.media("all and (orientation: portrait)"),
        orientation = window.orientation,
        portraitVal = $.mobile.portraitOrientationVals[ orientation ];

    if ( ( isPortraitMode && !portraitVal ) || ( !isPortraitMode && portraitVal ) ) {
        $.mobile.portraitOrientationVals = { "-90": true, "90": true };
    }
}

function updateOrientation()
{
    if ( $.support.orientation ) {
        $( "#orientationText" ).text( $.mobile.portraitOrientationVals[ window.orientation ] ? "portrait" : "landscape" );
    }
}

$(function() {
    updateOrientation();

    $( window ).bind( "orientationchange", function() {
        updateOrientation();
    });
});
Kin Blas

@toddparker @scottjehl @Wilto

I forgot my plea to test on your devices in my previous comment. :-) Can you guys give it a whirl on the PlayBook? I tested it out on the various Android devices I have (including Xoom) and iOS. Thanks!

claudiuchetan

Why not use the same method that worked a few version ago (in beta 2)?

Kin Blas

@claudiuchetan

Because the beta2 version determined the orientation based on the document element's clientWidth and clientHeight which is problematic because on some platforms they get updated before the orientationchange is fired, but on other platforms they get updated after.

The newer code tries to rely on the window.orientation value if it's available/supported.

I already have a fix for this in my local tree. We just need to test it.

Todd Parker

I just tested this:

Playbook, on load in portrait shows "orientation = -90", same for ready. When I rotate to landscape, orientationchange, resize, resize ( why twice?) "orientation = 180"

Same result for my Galaxy Tab 10.1 running 3.1

Kin Blas jblas referenced this issue from a commit January 06, 2012
Kin Blas Fix for issue #2933 - get_orientation() and hence getScreenHeight() d…
…oesn't work on some devices

It seems that some device/browser vendors use window.orientation values 0 and 180 to denote the "default" orientation. For iOS devices, and most other smart-phones tested, the default orientation is always "portrait", but in some Android and RIM based tablets, the default orientation is "landscape".

- Modified the orientationchange plugin so that it injects a landscape orientation media query into the document to figure out what the initial orientation is, it then makes adjustments to a portrait_map if necessary, so that we can properly decode the window.orientation value whenever get_orientation() is called.
1a52240
Kin Blas

Ok, so I landed a fix for the problem where we decode window.orientation incorrectly for devices/browsers that use "landscape" as their default orientation. Note that the test case posted by @dmfallak :

http://jsbin.com/okuqug/5

has some problems. Specifically, it relies on resize events to tell when the orientation changes. This is problematic because some settings of the viewport meta tag don't result in resize events being generated, but rather the document being scaled when rotated. I placed an updated test case here:

http://jquerymobile.com/test/tests/functional/orientation.html

Which seems to work everywhere, even on devices/browsers that don't support window.orientation.

Kin Blas

@dmfallak @claudiuchetan

If you guys could give the fix a whirl and report back, that would be great! Thanks for reporting/helping out.

Todd Parker

Closing as fixed, but we can re-open is you all find an issue.

Todd Parker toddparker closed this January 06, 2012
Kin Blas

@toddparker @johnbender

Should this fix be made to the 1.0-stable branch so that it is in 1.0.1?

Todd Parker

Yes please.

Kin Blas jblas referenced this issue from a commit January 06, 2012
Kin Blas Fix for issue #2933 - get_orientation() and hence getScreenHeight() d…
…oesn't work on some devices

It seems that some device/browser vendors use window.orientation values 0 and 180 to denote the "default" orientation. For iOS devices, and most other smart-phones tested, the default orientation is always "portrait", but in some Android and RIM based tablets, the default orientation is "landscape".

- Modified the orientationchange plugin so that it injects a landscape orientation media query into the document to figure out what the initial orientation is, it then makes adjustments to a portrait_map if necessary, so that we can properly decode the window.orientation value whenever get_orientation() is called.
d4c7123
Kin Blas jblas referenced this issue from a commit January 06, 2012
Kin Blas Fix for issue #2933 - get_orientation() and hence getScreenHeight() d…
…oesn't work on some devices.
8303055
claudiuchetan

Just got the 1.0.1 stable build, and the issue is still there. When an orientationChange occurs from landscape to portrait, the height of the page remains as in landscape. It seems to fix itself after a page switch occurs (after the orientation change).

Kin Blas

@claudiuchetan

If you load this page in your mobile browser of choice, does it report the correct results as you rotate the device?

http://jquerymobile.com/test/tests/functional/orientation.html

@toddparker @johnbender

Something seems weird, because if I load the above URL, which is based on the HEAD, it reports different results than 1.0.1 on the desktop, when they should be identical:

http://jquerymobile.com/demos/1.0.1/tests/functional/orientation.html

claudiuchetan

@jblas Testing the links on an iphone 4 shows "orientation not supported" for the first link, and the right results for the second link. But this is ios 5, and the orientation bug was on ios 4.3. I'll retest on monday.

Kin Blas jblas referenced this issue from a commit April 05, 2012
Kin Blas Fix for issue #3707 - iOS4 reports landscape when it's in portrait
- This was a regression caused by the fix for issue #2933:

#2933
1a52240

This triggered a bug on iPhone/iPod Touch devices running iOS 4.2 - 5.1 where the browser *ALWAYS* applies a landscape media query. This bug does not exist on iPad.

- Removed the use of the landscape media query, and switched to using window.innerWidth/innerHeight w ith a threshold to determine if the device is currently in landscape mode. A threshold is necessary because on small form factors like the iPhone, the user can enable the developer console which takes up more vertical space, making the useable width of the browser window larger than the height.
e1d8f3f
Kin Blas jblas referenced this issue from a commit April 05, 2012
Kin Blas Fix for issue #3707 - iOS4 reports landscape when it's in portrait
- This was a regression caused by the fix for issue #2933:

#2933
1a52240

This triggered a bug on iPhone/iPod Touch devices running iOS 4.2 - 5.1 where the browser *ALWAYS* applies a landscape media query. This bug does not exist on iPad.

- Removed the use of the landscape media query, and switched to using window.innerWidth/innerHeight w ith a threshold to determine if the device is currently in landscape mode. A threshold is necessary because on small form factors like the iPhone, the user can enable the developer console which takes up more vertical space, making the useable width of the browser window larger than the height.
0837c4a
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Something went wrong with that request. Please try again.