From 7b9698e8b7df88ba53ed9496360202e4b41265e4 Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Tue, 5 Nov 2013 11:12:21 -0600 Subject: [PATCH] Added hardware back button abstraction and nav support. Fixes #80 --- dist/js/ionic-angular.js | 54 ++++++++++++++++++--- js/ext/angular/src/directive/ionicNav.js | 18 ++++++- js/ext/angular/src/ionicAngular.js | 2 +- js/ext/angular/src/service/ionicPlatform.js | 34 +++++++++++-- 4 files changed, 92 insertions(+), 16 deletions(-) diff --git a/dist/js/ionic-angular.js b/dist/js/ionic-angular.js index a4e3cb9b74..3c054ba8b5 100644 --- a/dist/js/ionic-angular.js +++ b/dist/js/ionic-angular.js @@ -3,6 +3,7 @@ * modules. */ angular.module('ionic.service', [ + 'ionic.service.platform', 'ionic.service.actionSheet', 'ionic.service.gesture', 'ionic.service.loading', @@ -22,7 +23,6 @@ angular.module('ionic.ui', [ ]); angular.module('ionic', [ - 'ionic.platform', 'ionic.service', 'ionic.ui', ]); @@ -195,7 +195,7 @@ angular.module('ionic.service.modal', ['ionic.service.templateLoad']) (function() { 'use strict'; -angular.module('ionic.platform', []) +angular.module('ionic.service.platform', []) /** * The platformProvider makes it easy to set and detect which platform @@ -204,16 +204,14 @@ angular.module('ionic.platform', []) * initializing some defaults that depend on the platform, such as the * height of header bars on iOS 7. */ -.provider('platform', function() { - var platform = 'unknown'; +.provider('Platform', function() { + var platform = 'web'; var isPlatformReady = false; if(window.cordova || window.PhoneGap || window.phonegap) { platform = 'cordova'; } - console.log('Detected platform', platform); - var isReady = function() { if(platform == 'cordova') { return window.device; @@ -237,6 +235,32 @@ angular.module('ionic.platform', []) }, $get: ['$q', '$timeout', function($q, $timeout) { return { + /** + * Some platforms have hardware back buttons, so this is one way to bind to it. + * + * @param {function} cb the callback to trigger when this event occurs + */ + onHardwareBackButton: function(cb) { + this.ready(function() { + document.addEventListener('backbutton', cb, false); + }); + }, + + /** + * Remove an event listener for the backbutton. + * + * @param {function} fn the listener function that was originally bound. + */ + offHardwareBackButton: function(fn) { + this.ready(function() { + document.removeEventListener('backbutton', fn); + }); + }, + + /** + * Trigger a callback once the device is ready, or immediately if the device is already + * ready. + */ ready: function(cb) { var self = this; var q = $q.defer(); @@ -641,9 +665,9 @@ angular.module('ionic.ui.loading', []) (function() { 'use strict'; -angular.module('ionic.ui.nav', ['ionic.service.templateLoad', 'ionic.service.gesture', 'ngAnimate']) +angular.module('ionic.ui.nav', ['ionic.service.templateLoad', 'ionic.service.gesture', 'ionic.service.platform', 'ngAnimate']) -.controller('NavCtrl', ['$scope', '$element', '$animate', '$compile', 'TemplateLoader', function($scope, $element, $animate, $compile, TemplateLoader) { +.controller('NavCtrl', ['$scope', '$element', '$animate', '$compile', 'TemplateLoader', 'Platform', function($scope, $element, $animate, $compile, TemplateLoader, Platform) { var _this = this; angular.extend(this, ionic.controllers.NavController.prototype); @@ -668,6 +692,15 @@ angular.module('ionic.ui.nav', ['ionic.service.templateLoad', 'ionic.service.ges } }); + // Support Android hardware back button (native only, not mobile web) + var onHardwareBackButton = function(e) { + $scope.$apply(function() { + _this.pop(); + }); + } + Platform.onHardwareBackButton(onHardwareBackButton); + + this.handleDrag = function(e) { }; @@ -702,6 +735,11 @@ angular.module('ionic.ui.nav', ['ionic.service.templateLoad', 'ionic.service.ges }; $scope.navController = this; + + $scope.$on('$destroy', function() { + // Remove back button listener + Platform.offHardwareBackButton(onHardwareBackButton); + }); }]) .directive('navs', function() { diff --git a/js/ext/angular/src/directive/ionicNav.js b/js/ext/angular/src/directive/ionicNav.js index 7938e60a0a..bbc3266c07 100644 --- a/js/ext/angular/src/directive/ionicNav.js +++ b/js/ext/angular/src/directive/ionicNav.js @@ -1,9 +1,9 @@ (function() { 'use strict'; -angular.module('ionic.ui.nav', ['ionic.service.templateLoad', 'ionic.service.gesture', 'ngAnimate']) +angular.module('ionic.ui.nav', ['ionic.service.templateLoad', 'ionic.service.gesture', 'ionic.service.platform', 'ngAnimate']) -.controller('NavCtrl', ['$scope', '$element', '$animate', '$compile', 'TemplateLoader', function($scope, $element, $animate, $compile, TemplateLoader) { +.controller('NavCtrl', ['$scope', '$element', '$animate', '$compile', 'TemplateLoader', 'Platform', function($scope, $element, $animate, $compile, TemplateLoader, Platform) { var _this = this; angular.extend(this, ionic.controllers.NavController.prototype); @@ -28,6 +28,15 @@ angular.module('ionic.ui.nav', ['ionic.service.templateLoad', 'ionic.service.ges } }); + // Support Android hardware back button (native only, not mobile web) + var onHardwareBackButton = function(e) { + $scope.$apply(function() { + _this.pop(); + }); + } + Platform.onHardwareBackButton(onHardwareBackButton); + + this.handleDrag = function(e) { }; @@ -62,6 +71,11 @@ angular.module('ionic.ui.nav', ['ionic.service.templateLoad', 'ionic.service.ges }; $scope.navController = this; + + $scope.$on('$destroy', function() { + // Remove back button listener + Platform.offHardwareBackButton(onHardwareBackButton); + }); }]) .directive('navs', function() { diff --git a/js/ext/angular/src/ionicAngular.js b/js/ext/angular/src/ionicAngular.js index 4ab2e1a4be..52fd3812aa 100644 --- a/js/ext/angular/src/ionicAngular.js +++ b/js/ext/angular/src/ionicAngular.js @@ -3,6 +3,7 @@ * modules. */ angular.module('ionic.service', [ + 'ionic.service.platform', 'ionic.service.actionSheet', 'ionic.service.gesture', 'ionic.service.loading', @@ -22,7 +23,6 @@ angular.module('ionic.ui', [ ]); angular.module('ionic', [ - 'ionic.platform', 'ionic.service', 'ionic.ui', ]); diff --git a/js/ext/angular/src/service/ionicPlatform.js b/js/ext/angular/src/service/ionicPlatform.js index 10771a986a..fc8b43cca8 100644 --- a/js/ext/angular/src/service/ionicPlatform.js +++ b/js/ext/angular/src/service/ionicPlatform.js @@ -1,7 +1,7 @@ (function() { 'use strict'; -angular.module('ionic.platform', []) +angular.module('ionic.service.platform', []) /** * The platformProvider makes it easy to set and detect which platform @@ -10,16 +10,14 @@ angular.module('ionic.platform', []) * initializing some defaults that depend on the platform, such as the * height of header bars on iOS 7. */ -.provider('platform', function() { - var platform = 'unknown'; +.provider('Platform', function() { + var platform = 'web'; var isPlatformReady = false; if(window.cordova || window.PhoneGap || window.phonegap) { platform = 'cordova'; } - console.log('Detected platform', platform); - var isReady = function() { if(platform == 'cordova') { return window.device; @@ -43,6 +41,32 @@ angular.module('ionic.platform', []) }, $get: ['$q', '$timeout', function($q, $timeout) { return { + /** + * Some platforms have hardware back buttons, so this is one way to bind to it. + * + * @param {function} cb the callback to trigger when this event occurs + */ + onHardwareBackButton: function(cb) { + this.ready(function() { + document.addEventListener('backbutton', cb, false); + }); + }, + + /** + * Remove an event listener for the backbutton. + * + * @param {function} fn the listener function that was originally bound. + */ + offHardwareBackButton: function(fn) { + this.ready(function() { + document.removeEventListener('backbutton', fn); + }); + }, + + /** + * Trigger a callback once the device is ready, or immediately if the device is already + * ready. + */ ready: function(cb) { var self = this; var q = $q.defer();