Skip to content

Instantly share code, notes, and snippets.

@ColinCampbell
Created February 4, 2011 03:53
Show Gist options
  • Select an option

  • Save ColinCampbell/810718 to your computer and use it in GitHub Desktop.

Select an option

Save ColinCampbell/810718 to your computer and use it in GitHub Desktop.
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