Skip to content

Instantly share code, notes, and snippets.

@richtr
Last active February 26, 2021 09:11
Show Gist options
  • Save richtr/2966043 to your computer and use it in GitHub Desktop.
Save richtr/2966043 to your computer and use it in GitHub Desktop.
JavaScript shim of iOS's window.orientation + orientationchange events for other (typically mobile) browsers
/*
* OrientationChange Event Shim
* http://github.com/richtr
*
* Copyright (c) 2012, Rich Tibbett
*
* Licensed under the Apache License, Version 2.0 (the "License");
* you may not use this file except in compliance with the License.
* You may obtain a copy of the License at
*
* http://www.apache.org/licenses/LICENSE-2.0
*
* Unless required by applicable law or agreed to in writing, software
* distributed under the License is distributed on an "AS IS" BASIS,
* WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
* See the License for the specific language governing permissions and
* limitations under the License.
*/
/*
* DESCRIPTION:
* ------------
*
* JavaScript shim of iOS's window.orientation + orientationchange events
* for other (typically mobile) browsers.
*
* Documentation URL @
* http://developer.apple.com/library/IOS/#documentation/AppleApplications/Reference/SafariWebContent/HandlingEvents/HandlingEvents.html
*
* Demo page @
* http://people.opera.com/richt/release/demos/orientation/orientationchange_shim/test.html
*
* USAGE:
* ------
*
* 1. Add this file to the <head> of your web page:
*
* <script type="text/javascript" src="orientationChange.js"></script>
*
* 2. Register for 'orientationchange' events in the usual way:
*
* window.addEventListener('orientationchange', function(e) {
* console.log( window.orientation );
* }, true);
*
* or:
*
* window.onorientationchange = function(e) {
* console.log( window.orientation );
* }
*
* or:
*
* <body onorientationchange="checkOrientation()">
*
* *********************************************************************
* NOTE: Adding e.g. <body onorientationchange="checkOrientation()"> is
* partially supported but is not recommended. Please consider using one
* of the scripting approaches shown above instead.
* *********************************************************************
*
* KNOWN ISSUES:
* --------------
*
* 21-06-2012:
* The native orientationchange implementation in Android's Native Browser
* and Chrome Beta for Android is borked. Note that this shim is not loaded
* in these browsers. This shims does not replace these broken native
* implementations.
*
*/
!(function( window, undefined ) {
var supportsOrientation = ( typeof window.orientation == 'number' && typeof window.onorientationchange == 'function' );
// Do nothing if we don't need to shim
if ( supportsOrientation ) return;
/* START: requestAnimationFrame shim
*
* By: Eric Möller
* URL: http://my.opera.com/emoller/blog/2011/12/20/requestanimationframe-for-smart-er-animating
*/
(function() {
var lastTime = 0;
var vendors = ['ms', 'moz', 'webkit', 'o'];
for (var x = 0; x < vendors.length && !window.requestAnimationFrame; ++x) {
window.requestAnimationFrame = window[vendors[x] + 'RequestAnimationFrame'];
window.cancelRequestAnimationFrame = window[vendors[x] +
'CancelRequestAnimationFrame'];
}
if (!window.requestAnimationFrame)
window.requestAnimationFrame = function(callback, element) {
var currTime = new Date().getTime();
var timeToCall = Math.max(0, 16 - (currTime - lastTime));
var id = window.setTimeout(function() {
callback(currTime + timeToCall);
},
timeToCall);
lastTime = currTime + timeToCall;
return id;
};
if (!window.cancelAnimationFrame)
window.cancelAnimationFrame = function(id) {
clearTimeout(id);
};
} ());
/* END: requestAnimationFrame shim */
var cOrientationChange = function() {
this.currentOrientationAngle = -1;
this.lastOrientationAngle = -2;
this.currentOrientationState = this.lastOrientationState = ( window.innerWidth > window.innerHeight ) ? 'landscape': 'portrait';
var self = this;
// Setup deviceorientation listener (if it is available)
window.addEventListener( 'deviceorientation', function( e ) {
// Don't use unless we have a 3-axis implementation of device orientation
if ( e.alpha === null || e.alpha === undefined ) {
self.currentOrientationAngle = 0;
return;
}
// set orientation angle to nearest 90 degrees
self.currentOrientationAngle = Math.round( -e.gamma / 90) * 90;
// correction for holding the device upside down
if ( self.currentOrientationAngle == 0 && e.beta < 0 ) {
self.currentOrientationAngle = 180;
}
}, true );
this.manualOrientationChange = function() {
// landscape when width is biggest, otherwise portrait
self.currentOrientationState = ( window.innerWidth > window.innerHeight ) ? 'landscape': 'portrait';
if ( ( self.currentOrientationState !== self.lastOrientationState ) ||
( self.lastOrientationAngle === -2 && self.currentOrientationAngle !== -1 ) ||
( self.currentOrientationAngle !== 0 && self.currentOrientationAngle === -self.lastOrientationAngle ) ) {
if ( self.currentOrientationAngle === -1 ) self.currentOrientationAngle = 0;
// Update static window.orientation value
window.orientation = self.currentOrientationAngle;
// Create and dispatch pseudo-orientationchange event
var orientationEvent = window.document.createEvent( 'Event' );
orientationEvent.initEvent( 'orientationchange', true, true );
orientationEvent.orientation = this.currentOrientationAngle;
orientationEvent.mode = this.currentOrientationState;
window.dispatchEvent( orientationEvent );
// Fire event to window.onorientationchange assigned handler (if any)
if ( typeof window.onorientationchange == 'function' ) {
window.onorientationchange.call( this, orientationEvent );
}
// Check for onorientationevent handler on body element and execute
var body = document.body;
if( body && body.getAttribute('onorientationchange')) {
// Create new script and run function
var onorientationchange_script = document.createElement('script');
onorientationchange_script.type = "text/javascript";
onorientationchange_script.textContent = "//<![CDATA[\n" + body.getAttribute('onorientationchange') + "\n//]]>";
body.appendChild(onorientationchange_script);
onorientationchange_script.parentNode.removeChild( onorientationchange_script );
}
self.lastOrientationAngle = self.currentOrientationAngle;
self.lastOrientationState = self.currentOrientationState;
}
window.requestAnimationFrame( self.manualOrientationChange.bind( self ) );
};
this.manualOrientationChange();
};
//*** WINDOW EVENTLISTENER SHIM
var orientationHandler = new cOrientationChange();
window.orientation = orientationHandler.currentOrientationAngle === -1 ? 0: orientationHandler.currentOrientationAngle;
window.onorientationchange = function( e ) {};
})( window );
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment