Created
February 4, 2011 03:53
-
-
Save ColinCampbell/810718 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
| diff --git a/frameworks/amber/system/device.js b/frameworks/amber/system/device.js | |
| index 3e43239..177b2e8 100644 | |
| --- a/frameworks/amber/system/device.js | |
| +++ b/frameworks/amber/system/device.js | |
| @@ -10,6 +10,10 @@ require('system/ready'); | |
| require('system/root_responder'); | |
| require('system/platform'); | |
| +SC.PORTRAIT_ORIENTATION = 'portrait'; | |
| +SC.LANDSCAPE_ORIENTATION = 'landscape'; | |
| +SC.NO_ORIENTATION = 'desktop'; // value 'desktop' for backwards compatibility | |
| + | |
| /** | |
| The device object allows you to check device specific properties such as | |
| orientation and if the device is offline, as well as observe when they change | |
| @@ -36,13 +40,14 @@ require('system/platform'); | |
| SC.device = SC.Object.create({ | |
| /** | |
| - Sets the orientation for touch devices, either 'landscape' or 'portrait'. | |
| - Will be 'desktop' in the case of non-touch devices. | |
| + Sets the orientation for touch devices, either SC.LANDSCAPE_ORIENTATION | |
| + or SC.PORTRAIT_ORIENTATION. Will be SC.NO_ORIENTATION in the case of | |
| + non-touch devices that are also not simulating touch events. | |
| @property {String} | |
| - @default 'desktop' | |
| + @default SC.NO_ORIENTATION | |
| */ | |
| - orientation: 'desktop', | |
| + orientation: SC.NO_ORIENTATION, | |
| /** | |
| Indicates whether the device is currently online or offline. For browsers | |
| @@ -80,13 +85,10 @@ SC.device = SC.Object.create({ | |
| */ | |
| init: function() { | |
| sc_super(); | |
| - if(SC.platform.touch) this.orientationchange(); | |
| - if(navigator && navigator.onLine===false) { | |
| + if (navigator && navigator.onLine === false) { | |
| this.set('isOffline', YES); | |
| } | |
| - | |
| - this.panes = SC.Set.create(); | |
| }, | |
| /** | |
| @@ -95,37 +97,94 @@ SC.device = SC.Object.create({ | |
| */ | |
| setup: function() { | |
| var responder = SC.RootResponder.responder; | |
| - responder.listenFor('orientationchange'.w(), window, this); | |
| responder.listenFor('online offline'.w(), document, this); | |
| + | |
| + this.orientationHandlingShouldChange(); | |
| }, | |
| // .......................................................... | |
| - // EVENT HANDLING | |
| + // ORIENTATION HANDLING | |
| // | |
| - orientationchange: function(evt) { | |
| - if(window.orientation===0 || window.orientation===180) { | |
| - this.set('orientation', 'portrait'); | |
| + /** | |
| + Determines which method to use for orientation changes. | |
| + Either detects orientation changes via the current size | |
| + of the window, or by the window.onorientationchange event. | |
| + */ | |
| + orientationHandlingShouldChange: function() { | |
| + if (SC.platform.windowSizeDeterminesOrientation) { | |
| + SC.Event.remove(window, 'orientationchange', this, this.orientationchange); | |
| + this.windowSizeDidChange(SC.RootResponder.responder.get('currentWindowSize')); | |
| + } else if (SC.platform.supportsOrientationChange) { | |
| + SC.Event.add(window, 'orientationchange', this, this.orientationchange); | |
| + this.orientationchange(); | |
| } | |
| - else { | |
| - this.set('orientation', 'landscape'); | |
| + }, | |
| + | |
| + /** | |
| + @param {Hash} newSize The new size of the window | |
| + @returns YES if the method altered the orientation, NO otherwise | |
| + */ | |
| + windowSizeDidChange: function(newSize) { | |
| + if (SC.platform.windowSizeDeterminesOrientation) { | |
| + if (!SC.browser.mobileSafari || SC.browser.android) { | |
| + // in any browser other than iOS, use height vs. width test | |
| + if (SC.platform.touch) { | |
| + if (newSize.height >= newSize.width) { | |
| + this.set('orientation', SC.PORTRAIT_ORIENTATION); | |
| + } else { | |
| + this.set('orientation', SC.LANDSCAPE_ORIENTATION); | |
| + } | |
| + } else { | |
| + this.set('orientation', SC.NO_ORIENTATION); | |
| + } | |
| + } else { | |
| + // in mobile safari, because some of its chrome can make the | |
| + // above match landscape falsely, we compare to screen.width | |
| + if (newSize.width === window.screen.width) { | |
| + this.set('orientation', SC.PORTRAIT_ORIENTATION); | |
| + } else { | |
| + this.set('orientation', SC.LANDSCAPE_ORIENTATION); | |
| + } | |
| + } | |
| + return YES; | |
| + } | |
| + return NO; | |
| + }, | |
| + | |
| + /** | |
| + Called when the window.onorientationchange event is fired. | |
| + */ | |
| + orientationchange: function(evt) { | |
| + if (window.orientation === 0 || window.orientation === 180) { | |
| + this.set('orientation', SC.PORTRAIT_ORIENTATION); | |
| + } else { | |
| + this.set('orientation', SC.LANDSCAPE_ORIENTATION); | |
| } | |
| }, | |
| orientationObserver: function(){ | |
| var body = SC.$(document.body), | |
| - or = this.get('orientation'); | |
| + orientation = this.get('orientation'); | |
| - if(or === "portrait") { | |
| + if (orientation === SC.PORTRAIT_ORIENTATION) { | |
| body.addClass('portrait'); | |
| - body.removeClass('landscape'); | |
| - } | |
| - if( or === "landscape" ) { | |
| + } else { | |
| body.removeClass('portrait'); | |
| + } | |
| + | |
| + if (orientation === SC.LANDSCAPE_ORIENTATION) { | |
| body.addClass('landscape'); | |
| + } else { | |
| + body.removeClass('landscape'); | |
| } | |
| }.observes('orientation'), | |
| + | |
| + // .......................................................... | |
| + // CONNECTION HANDLING | |
| + // | |
| + | |
| online: function(evt) { | |
| this.set('isOffline', NO); | |
| }, | |
| diff --git a/frameworks/amber/system/platform.js b/frameworks/amber/system/platform.js | |
| index c5de692..8bd1ec9 100644 | |
| --- a/frameworks/amber/system/platform.js | |
| +++ b/frameworks/amber/system/platform.js | |
| @@ -115,6 +115,10 @@ SC.platform = { | |
| this.replaceEvent('mousemove', this._simtouch_mousemove); | |
| this.replaceEvent('mousedown', this._simtouch_mousedown); | |
| this.replaceEvent('mouseup', this._simtouch_mouseup); | |
| + | |
| + // fix orientation handling | |
| + SC.platform.windowSizeDeterminesOrientation = YES; | |
| + SC.device.orientationHandlingShouldChange(); | |
| }, | |
| /** @private | |
| @@ -252,7 +256,29 @@ SC.platform = { | |
| supportsCanvas: function() { | |
| return !!document.createElement('canvas').getContext; | |
| - }() | |
| + }(), | |
| + | |
| + supportsOrientationChange: ('onorientationchange' in window), | |
| + | |
| + /* | |
| + TODO [CC] On Android, SC.browser.mobileSafari returns YES, so we need to | |
| + explicitly check for non-Android mobileSafari browsers. There | |
| + is obviously a better way to handle this (ie. target the iOS | |
| + platform itself; we need more robust checking). Here's the kicker, | |
| + only certain Android devices support the onorientationchange | |
| + event, so those that don't need to fallback on the resize | |
| + */ | |
| + /** | |
| + Because iOS is slow to dispatch the window.onorientationchange event, | |
| + we use the window size to determine the orientation on iOS devices | |
| + and desktop environments when SC.platform.touch is YES (ie. when | |
| + SC.platform.simulateTouchEvents has been called) | |
| + | |
| + @property {Boolean} | |
| + @default NO | |
| + */ | |
| + windowSizeDeterminesOrientation: (SC.browser.mobileSafari && !SC.browser.android) || !('onorientationchange' in window) | |
| + | |
| }; | |
| /* Calculate CSS Prefixes */ | |
| diff --git a/frameworks/amber/system/root_responder.js b/frameworks/amber/system/root_responder.js | |
| index 6d2ab5f..08ec107 100644 | |
| --- a/frameworks/amber/system/root_responder.js | |
| +++ b/frameworks/amber/system/root_responder.js | |
| @@ -311,15 +311,8 @@ SC.RootResponder = SC.Object.extend({ | |
| if (!SC.rectsEqual(newSize, oldSize)) { | |
| //Notify orientation change. This is faster than waiting for the orientation | |
| //change event. | |
| - if(SC.platform.touch){ | |
| - var body = SC.$(document.body); | |
| - if(newSize.height>= newSize.width) { | |
| - SC.device.set('orientation', 'portrait'); | |
| - } | |
| - else { | |
| - SC.device.set('orientation', 'landscape'); | |
| - } | |
| - } | |
| + SC.device.windowSizeDidChange(newSize); | |
| + | |
| // notify panes | |
| if (this.panes) { | |
| SC.run(function() { | |
| @@ -766,22 +759,6 @@ SC.RootResponder = SC.Object.extend({ | |
| }; | |
| SC.RunLoop.prototype.endRunLoop = patch; | |
| } | |
| - | |
| - // Orientation changes are not being reliably reported with iPhone 0S 3 | |
| - // We do this initialization to double check the right orientation. | |
| - // This happens if the orientation has changed from the moment the app | |
| - // started loading until the app is set until isReady | |
| - if(SC.platform.touch){ | |
| - var newSize = this.computeWindowSize(), | |
| - body = SC.$(document.body); | |
| - | |
| - if(newSize.height>= newSize.width) { | |
| - SC.device.set('orientation', 'portrait'); | |
| - } | |
| - else { | |
| - SC.device.set('orientation', 'landscape'); | |
| - } | |
| - } | |
| }, | |
| // ................................................................................ |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment