From 792761861c08125fcb30a9aa595b8e6e221e4451 Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Mon, 4 Nov 2013 16:51:12 -0600 Subject: [PATCH 1/6] Renamed files to CSS convention. Fixes #71 --- scss/ionic/{_actionSheet.scss => _action-sheet.scss} | 0 scss/ionic/{_slideBox.scss => _slide-box.scss} | 0 scss/ionic/{_splitPane.scss => _split-pane.scss} | 0 scss/ionic/ionic-scoped.scss | 4 ++-- scss/ionic/ionic.scss | 6 +++--- 5 files changed, 5 insertions(+), 5 deletions(-) rename scss/ionic/{_actionSheet.scss => _action-sheet.scss} (100%) rename scss/ionic/{_slideBox.scss => _slide-box.scss} (100%) rename scss/ionic/{_splitPane.scss => _split-pane.scss} (100%) diff --git a/scss/ionic/_actionSheet.scss b/scss/ionic/_action-sheet.scss similarity index 100% rename from scss/ionic/_actionSheet.scss rename to scss/ionic/_action-sheet.scss diff --git a/scss/ionic/_slideBox.scss b/scss/ionic/_slide-box.scss similarity index 100% rename from scss/ionic/_slideBox.scss rename to scss/ionic/_slide-box.scss diff --git a/scss/ionic/_splitPane.scss b/scss/ionic/_split-pane.scss similarity index 100% rename from scss/ionic/_splitPane.scss rename to scss/ionic/_split-pane.scss diff --git a/scss/ionic/ionic-scoped.scss b/scss/ionic/ionic-scoped.scss index 9954897519..cfb68703ab 100644 --- a/scss/ionic/ionic-scoped.scss +++ b/scss/ionic/ionic-scoped.scss @@ -15,7 +15,7 @@ "type", // Action Sheet - "actionSheet", + "action-sheet", // Nav "bar", @@ -50,4 +50,4 @@ "util", "platform"; -} \ No newline at end of file +} diff --git a/scss/ionic/ionic.scss b/scss/ionic/ionic.scss index e5db8ef8d9..84a476baa4 100644 --- a/scss/ionic/ionic.scss +++ b/scss/ionic/ionic.scss @@ -13,7 +13,7 @@ "type", // Action Sheet - "actionSheet", + "action-sheet", // Nav "bar", @@ -41,9 +41,9 @@ // Components "alerts", - "slideBox", + "slide-box", - "splitPane", + "split-pane", "scroll", From 7f4147ea06af320b7eace517eccd9b587f79646a Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Mon, 4 Nov 2013 18:43:08 -0600 Subject: [PATCH 2/6] Added alternative $scope inherit for Modal --- dist/js/ionic-angular.js | 21 +++++++++++++++------ js/ext/angular/src/ionicAngular.js | 13 +++++++++++-- js/ext/angular/src/service/ionicModal.js | 8 ++++---- 3 files changed, 30 insertions(+), 12 deletions(-) diff --git a/dist/js/ionic-angular.js b/dist/js/ionic-angular.js index b265a7a279..cb57ce5804 100644 --- a/dist/js/ionic-angular.js +++ b/dist/js/ionic-angular.js @@ -2,6 +2,14 @@ * Create a wrapping module to ease having to include too many * modules. */ +angular.module('ionic.service', [ + 'ionic.service.actionSheet', + 'ionic.service.gesture', + 'ionic.service.loading', + 'ionic.service.modal', + 'ionic.service.popup', + 'ionic.service.templateLoad' +]); angular.module('ionic.ui', [ 'ionic.ui.content', @@ -15,8 +23,9 @@ angular.module('ionic.ui', [ angular.module('ionic', [ 'ionic.platform', - 'ionic.ui' -]) + 'ionic.service', + 'ionic.ui', +]); ; angular.module('ionic.service.actionSheet', ['ionic.service.templateLoad', 'ionic.ui.actionSheet']) @@ -153,9 +162,9 @@ angular.module('ionic.service.modal', ['ionic.service.templateLoad']) * A new isolated scope will be created for the * modal and the new element will be appended into the body. */ - fromTemplate: function(templateString) { + fromTemplate: function(templateString, $scope) { // Create a new isolated scope for the modal - var scope = $rootScope.$new(true); + var scope = $scope && $scope.$new() || $rootScope.$new(true); // Compile the template var element = $compile(templateString)(scope); @@ -165,10 +174,10 @@ angular.module('ionic.service.modal', ['ionic.service.templateLoad']) scope.modal = modal; return modal; }, - fromTemplateUrl: function(url, cb) { + fromTemplateUrl: function(url, cb, $scope) { TemplateLoader.load(url).then(function(templateString) { // Create a new isolated scope for the modal - var scope = $rootScope.$new(true); + var scope = $scope && $scope.$new() || $rootScope.$new(true); // Compile the template var element = $compile(templateString)(scope); diff --git a/js/ext/angular/src/ionicAngular.js b/js/ext/angular/src/ionicAngular.js index 23c10eabfb..4ab2e1a4be 100644 --- a/js/ext/angular/src/ionicAngular.js +++ b/js/ext/angular/src/ionicAngular.js @@ -2,6 +2,14 @@ * Create a wrapping module to ease having to include too many * modules. */ +angular.module('ionic.service', [ + 'ionic.service.actionSheet', + 'ionic.service.gesture', + 'ionic.service.loading', + 'ionic.service.modal', + 'ionic.service.popup', + 'ionic.service.templateLoad' +]); angular.module('ionic.ui', [ 'ionic.ui.content', @@ -15,5 +23,6 @@ angular.module('ionic.ui', [ angular.module('ionic', [ 'ionic.platform', - 'ionic.ui' -]) + 'ionic.service', + 'ionic.ui', +]); diff --git a/js/ext/angular/src/service/ionicModal.js b/js/ext/angular/src/service/ionicModal.js index 5bf276cae1..90318c8cf6 100644 --- a/js/ext/angular/src/service/ionicModal.js +++ b/js/ext/angular/src/service/ionicModal.js @@ -9,9 +9,9 @@ angular.module('ionic.service.modal', ['ionic.service.templateLoad']) * A new isolated scope will be created for the * modal and the new element will be appended into the body. */ - fromTemplate: function(templateString) { + fromTemplate: function(templateString, $scope) { // Create a new isolated scope for the modal - var scope = $rootScope.$new(true); + var scope = $scope && $scope.$new() || $rootScope.$new(true); // Compile the template var element = $compile(templateString)(scope); @@ -21,10 +21,10 @@ angular.module('ionic.service.modal', ['ionic.service.templateLoad']) scope.modal = modal; return modal; }, - fromTemplateUrl: function(url, cb) { + fromTemplateUrl: function(url, cb, $scope) { TemplateLoader.load(url).then(function(templateString) { // Create a new isolated scope for the modal - var scope = $rootScope.$new(true); + var scope = $scope && $scope.$new() || $rootScope.$new(true); // Compile the template var element = $compile(templateString)(scope); From 11e0e478d13496eadd250da45d835b9569475b68 Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Mon, 4 Nov 2013 21:24:28 -0600 Subject: [PATCH 3/6] List item updates --- dist/css/ionic-ios7.css | 28 +++++++++++---------- dist/css/ionic-scoped.css | 30 ++++++++++++----------- dist/css/ionic.css | 30 ++++++++++++----------- dist/js/ionic-angular.js | 3 +++ js/ext/angular/src/directive/ionicList.js | 3 +++ js/ext/angular/test/list.html | 15 ++++++------ scss/ionic/_list.scss | 7 ++++-- 7 files changed, 65 insertions(+), 51 deletions(-) diff --git a/dist/css/ionic-ios7.css b/dist/css/ionic-ios7.css index 9e66b263df..b23f88008b 100644 --- a/dist/css/ionic-ios7.css +++ b/dist/css/ionic-ios7.css @@ -182,7 +182,7 @@ sub { fieldset { margin: 0 2px; padding: 0.35em 0.625em 0.75em; - border: 1px solid #c0c0c0; } + border: 1px solid silver; } /** * 1. Correct `color` not being inherited in IE 8/9. @@ -1465,11 +1465,13 @@ button.item-button-right:after { * "edit mode" */ .list-editing .item-content { - margin-right: 30px; - margin-left: 30px; } + margin-right: 50px; + margin-left: 50px; } .list-editing .item-edit { left: 0px; opacity: 1; } + .list-editing .item-edit i { + left: 5px; } .list-header { margin-top: 20px; @@ -1721,7 +1723,7 @@ input[type="file"] { line-height: 34px; } select { - border: 1px solid #ccc; + border: 1px solid #cccccc; background-color: white; } select[multiple], @@ -1793,7 +1795,7 @@ input[type="checkbox"][readonly] { right: 20px; transition: 0.2s ease; transition-property: left, right; - transition-delay: 0s, .05s; } + transition-delay: 0s, 0.05s; } .toggle :checked + .track { /* When the toggle is "on" */ @@ -1808,7 +1810,7 @@ input[type="checkbox"][readonly] { right: 0; left: 20px; -webkit-transform: none; - transition-delay: .05s, 0s; } + transition-delay: 0.05s, 0s; } .item-radio { padding: 0; } @@ -2093,7 +2095,7 @@ input[type="range"] { .button.button-icon:active, .button.button-icon.active { background: none; box-shadow: none; - text-shadow: 0px 0px 10px #fff; } + text-shadow: 0px 0px 10px white; } .button.block, .button.button-full { margin-top: 10px; margin-bottom: 10px; } @@ -2437,9 +2439,9 @@ a.button { line-height: 1; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; - -webkit-animation: spin .75s linear infinite; - -moz-animation: spin .75s linear infinite; - animation: spin .75s linear infinite; } + -webkit-animation: spin 0.75s linear infinite; + -moz-animation: spin 0.75s linear infinite; + animation: spin 0.75s linear infinite; } .ion-loading:before { content: "\e144"; } @@ -2452,9 +2454,9 @@ a.button { line-height: 1; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; - -webkit-animation: spin .75s linear infinite; - -moz-animation: spin .75s linear infinite; - animation: spin .75s linear infinite; } + -webkit-animation: spin 0.75s linear infinite; + -moz-animation: spin 0.75s linear infinite; + animation: spin 0.75s linear infinite; } .ion-refreshing:before { content: "\e144"; } diff --git a/dist/css/ionic-scoped.css b/dist/css/ionic-scoped.css index 5c007de34d..9c8ea44d93 100644 --- a/dist/css/ionic-scoped.css +++ b/dist/css/ionic-scoped.css @@ -210,7 +210,7 @@ transform: rotate(360deg); } } } .ionic .ion { - font-family: 'Ionicons' !important; + font-family: "Ionicons" !important; speak: none !important; font-style: normal !important; font-weight: normal !important; @@ -1192,7 +1192,7 @@ .ionic fieldset { margin: 0 2px; padding: 0.35em 0.625em 0.75em; - border: 1px solid #c0c0c0; } + border: 1px solid silver; } .ionic legend { padding: 0; /* 2 */ @@ -2311,11 +2311,13 @@ padding-bottom: 1px; padding-left: 0; } .ionic .list-editing .item-content { - margin-right: 30px; - margin-left: 30px; } + margin-right: 50px; + margin-left: 50px; } .ionic .list-editing .item-edit { left: 0px; opacity: 1; } + .ionic .list-editing .item-edit i { + left: 5px; } .ionic .list-header { margin-top: 20px; padding: 5px 15px; @@ -2538,7 +2540,7 @@ .ionic input[type="file"] { line-height: 34px; } .ionic select { - border: 1px solid #ccc; + border: 1px solid #cccccc; background-color: white; } .ionic select[multiple], .ionic select[size] { @@ -2587,7 +2589,7 @@ border-radius: 50%; background: white; content: ' '; - transition: background-color .1s ease-in-out; } + transition: background-color 0.1s ease-in-out; } .ionic .checkbox input:after { position: absolute; top: 34%; @@ -2600,7 +2602,7 @@ border-right: 0; content: ' '; opacity: 0; - transition: opacity .05s ease-in-out; + transition: opacity 0.05s ease-in-out; -webkit-transform: rotate(-45deg); transform: rotate(-45deg); } .ionic .checkbox input:checked:before { @@ -2952,7 +2954,7 @@ .ionic .button.button-icon:active, .ionic .button.button-icon.active { background: none; box-shadow: none; - text-shadow: 0px 0px 10px #fff; } + text-shadow: 0px 0px 10px white; } .ionic .button.block, .ionic .button.button-full { margin-top: 10px; margin-bottom: 10px; } @@ -3202,9 +3204,9 @@ line-height: 1; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; - -webkit-animation: spin .75s linear infinite; - -moz-animation: spin .75s linear infinite; - animation: spin .75s linear infinite; } + -webkit-animation: spin 0.75s linear infinite; + -moz-animation: spin 0.75s linear infinite; + animation: spin 0.75s linear infinite; } .ionic .ion-loading:before { content: "\e144"; } .ionic .ion-refreshing { @@ -3216,9 +3218,9 @@ line-height: 1; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; - -webkit-animation: spin .75s linear infinite; - -moz-animation: spin .75s linear infinite; - animation: spin .75s linear infinite; } + -webkit-animation: spin 0.75s linear infinite; + -moz-animation: spin 0.75s linear infinite; + animation: spin 0.75s linear infinite; } .ionic .ion-refreshing:before { content: "\e144"; } .ionic .hidden, diff --git a/dist/css/ionic.css b/dist/css/ionic.css index d3ca1f4d45..40360946bd 100644 --- a/dist/css/ionic.css +++ b/dist/css/ionic.css @@ -7,7 +7,7 @@ font-style: normal; } .ion { - font-family: 'Ionicons' !important; + font-family: "Ionicons" !important; speak: none !important; font-style: normal !important; font-weight: normal !important; @@ -1521,7 +1521,7 @@ sub { fieldset { margin: 0 2px; padding: 0.35em 0.625em 0.75em; - border: 1px solid #c0c0c0; } + border: 1px solid silver; } /** * 1. Correct `color` not being inherited in IE 8/9. @@ -2868,11 +2868,13 @@ button.item-button-right:after { * "edit mode" */ .list-editing .item-content { - margin-right: 30px; - margin-left: 30px; } + margin-right: 50px; + margin-left: 50px; } .list-editing .item-edit { left: 0px; opacity: 1; } + .list-editing .item-edit i { + left: 5px; } .list-header { margin-top: 20px; @@ -3124,7 +3126,7 @@ input[type="file"] { line-height: 34px; } select { - border: 1px solid #ccc; + border: 1px solid #cccccc; background-color: white; } select[multiple], @@ -3179,7 +3181,7 @@ input[type="checkbox"][readonly] { border-radius: 50%; background: white; content: ' '; - transition: background-color .1s ease-in-out; } + transition: background-color 0.1s ease-in-out; } /* the checkmark within the box */ .checkbox input:after { @@ -3194,7 +3196,7 @@ input[type="checkbox"][readonly] { border-right: 0; content: ' '; opacity: 0; - transition: opacity .05s ease-in-out; + transition: opacity 0.05s ease-in-out; -webkit-transform: rotate(-45deg); transform: rotate(-45deg); } @@ -3574,7 +3576,7 @@ input[type="range"] { .button.button-icon:active, .button.button-icon.active { background: none; box-shadow: none; - text-shadow: 0px 0px 10px #fff; } + text-shadow: 0px 0px 10px white; } .button.block, .button.button-full { margin-top: 10px; margin-bottom: 10px; } @@ -4096,9 +4098,9 @@ a.button { line-height: 1; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; - -webkit-animation: spin .75s linear infinite; - -moz-animation: spin .75s linear infinite; - animation: spin .75s linear infinite; } + -webkit-animation: spin 0.75s linear infinite; + -moz-animation: spin 0.75s linear infinite; + animation: spin 0.75s linear infinite; } .ion-loading:before { content: "\e144"; } @@ -4111,9 +4113,9 @@ a.button { line-height: 1; -webkit-font-smoothing: antialiased; -moz-osx-font-smoothing: grayscale; - -webkit-animation: spin .75s linear infinite; - -moz-animation: spin .75s linear infinite; - animation: spin .75s linear infinite; } + -webkit-animation: spin 0.75s linear infinite; + -moz-animation: spin 0.75s linear infinite; + animation: spin 0.75s linear infinite; } .ion-refreshing:before { content: "\e144"; } diff --git a/dist/js/ionic-angular.js b/dist/js/ionic-angular.js index cb57ce5804..cc4f8de823 100644 --- a/dist/js/ionic-angular.js +++ b/dist/js/ionic-angular.js @@ -411,6 +411,9 @@ angular.module('ionic.ui.list', ['ngAnimate']) buttons: '=', }, template: '\ +
\ + \ +
\
\
\
\ diff --git a/js/ext/angular/src/directive/ionicList.js b/js/ext/angular/src/directive/ionicList.js index d2c43438d8..0b5ebebfb8 100644 --- a/js/ext/angular/src/directive/ionicList.js +++ b/js/ext/angular/src/directive/ionicList.js @@ -19,6 +19,9 @@ angular.module('ionic.ui.list', ['ngAnimate']) buttons: '=', }, template: '\ +
\ + \ +
\
\
\
\ diff --git a/js/ext/angular/test/list.html b/js/ext/angular/test/list.html index 39af0decec..c0ebbb5432 100644 --- a/js/ext/angular/test/list.html +++ b/js/ext/angular/test/list.html @@ -63,17 +63,16 @@ - + - + buttons="item.buttons" + can-delete="true" + can-reorder="true" + can-swipe="true" + on-delete="deleteProject(project)" + on-select="selectProject(project)"> {{item.text}} diff --git a/scss/ionic/_list.scss b/scss/ionic/_list.scss index 3d36afdde2..a3231692b7 100644 --- a/scss/ionic/_list.scss +++ b/scss/ionic/_list.scss @@ -17,12 +17,15 @@ */ .list-editing { .item-content { - margin-right: 30px; - margin-left: 30px; + margin-right: 50px; + margin-left: 50px; } .item-edit { left: 0px; opacity: 1; + i { + left: 5px; + } } } From 489b673ea4fe37e7cb09df68b18394221c1d871d Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Mon, 4 Nov 2013 22:04:57 -0600 Subject: [PATCH 4/6] Fixed #74 --- dist/js/ionic-angular.js | 8 ++++---- js/ext/angular/src/service/ionicActionSheet.js | 4 ++-- js/ext/angular/src/service/ionicPopup.js | 4 ++-- 3 files changed, 8 insertions(+), 8 deletions(-) diff --git a/dist/js/ionic-angular.js b/dist/js/ionic-angular.js index cc4f8de823..1f25e54959 100644 --- a/dist/js/ionic-angular.js +++ b/dist/js/ionic-angular.js @@ -39,8 +39,8 @@ angular.module('ionic.service.actionSheet', ['ionic.service.templateLoad', 'ioni * * @param {object} opts the options for this ActionSheet (see docs) */ - show: function(opts) { - var scope = $rootScope.$new(true); + show: function(opts, $scope) { + var scope = $scope && $scope.$new() || $rootScope.$new(true); angular.extend(scope, opts); @@ -209,7 +209,7 @@ angular.module('ionic.service.popup', ['ionic.service.templateLoad']) }; return { - alert: function(message) { + alert: function(message, $scope) { // If there is an existing popup, just show that one var existing = getPopup(); @@ -224,7 +224,7 @@ angular.module('ionic.service.popup', ['ionic.service.templateLoad']) opts = angular.extend(defaults, opts); - var scope = $rootScope.$new(true); + var scope = $scope && $scope.$new() || $rootScope.$new(true); angular.extend(scope, opts); // Compile the template diff --git a/js/ext/angular/src/service/ionicActionSheet.js b/js/ext/angular/src/service/ionicActionSheet.js index 5267b1fbc8..1c9db95766 100644 --- a/js/ext/angular/src/service/ionicActionSheet.js +++ b/js/ext/angular/src/service/ionicActionSheet.js @@ -10,8 +10,8 @@ angular.module('ionic.service.actionSheet', ['ionic.service.templateLoad', 'ioni * * @param {object} opts the options for this ActionSheet (see docs) */ - show: function(opts) { - var scope = $rootScope.$new(true); + show: function(opts, $scope) { + var scope = $scope && $scope.$new() || $rootScope.$new(true); angular.extend(scope, opts); diff --git a/js/ext/angular/src/service/ionicPopup.js b/js/ext/angular/src/service/ionicPopup.js index 5071d1961b..e771a24bae 100644 --- a/js/ext/angular/src/service/ionicPopup.js +++ b/js/ext/angular/src/service/ionicPopup.js @@ -15,7 +15,7 @@ angular.module('ionic.service.popup', ['ionic.service.templateLoad']) }; return { - alert: function(message) { + alert: function(message, $scope) { // If there is an existing popup, just show that one var existing = getPopup(); @@ -30,7 +30,7 @@ angular.module('ionic.service.popup', ['ionic.service.templateLoad']) opts = angular.extend(defaults, opts); - var scope = $rootScope.$new(true); + var scope = $scope && $scope.$new() || $rootScope.$new(true); angular.extend(scope, opts); // Compile the template From d1099e61a3b867bc8fa3015a62e263c5426f37b8 Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Tue, 5 Nov 2013 09:32:11 -0600 Subject: [PATCH 5/6] Moved platform service to services folder --- dist/js/ionic-angular.js | 136 +++++++++--------- .../{directive => service}/ionicPlatform.js | 0 2 files changed, 68 insertions(+), 68 deletions(-) rename js/ext/angular/src/{directive => service}/ionicPlatform.js (100%) diff --git a/dist/js/ionic-angular.js b/dist/js/ionic-angular.js index 1f25e54959..a4e3cb9b74 100644 --- a/dist/js/ionic-angular.js +++ b/dist/js/ionic-angular.js @@ -192,6 +192,74 @@ angular.module('ionic.service.modal', ['ionic.service.templateLoad']) }; }]); ; +(function() { +'use strict'; + +angular.module('ionic.platform', []) + +/** + * The platformProvider makes it easy to set and detect which platform + * the app is currently running on. It has some auto detection built in + * for PhoneGap and Cordova. This provider also takes care of + * initializing some defaults that depend on the platform, such as the + * height of header bars on iOS 7. + */ +.provider('platform', function() { + var platform = 'unknown'; + 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; + } + return true; + }; + + // We need to do some stuff as soon as we know the platform, + // like adjust header margins for iOS 7, etc. + setTimeout(function afterReadyWait() { + if(isReady()) { + ionic.Platform.detect(); + } else { + setTimeout(afterReadyWait, 50); + } + }, 10); + + return { + setPlatform: function(p) { + platform = p; + }, + $get: ['$q', '$timeout', function($q, $timeout) { + return { + ready: function(cb) { + var self = this; + var q = $q.defer(); + + $timeout(function readyWait() { + if(isReady()) { + isPlatformReady = true; + q.resolve(); + cb(); + } else { + $timeout(readyWait, 50); + } + }, 50); + + return q.promise; + } + }; + }] + }; +}); + +})(ionic); +; angular.module('ionic.service.popup', ['ionic.service.templateLoad']) @@ -763,74 +831,6 @@ angular.module('ionic.ui.nav', ['ionic.service.templateLoad', 'ionic.service.ges })(); ; -(function() { -'use strict'; - -angular.module('ionic.platform', []) - -/** - * The platformProvider makes it easy to set and detect which platform - * the app is currently running on. It has some auto detection built in - * for PhoneGap and Cordova. This provider also takes care of - * initializing some defaults that depend on the platform, such as the - * height of header bars on iOS 7. - */ -.provider('platform', function() { - var platform = 'unknown'; - 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; - } - return true; - }; - - // We need to do some stuff as soon as we know the platform, - // like adjust header margins for iOS 7, etc. - setTimeout(function afterReadyWait() { - if(isReady()) { - ionic.Platform.detect(); - } else { - setTimeout(afterReadyWait, 50); - } - }, 10); - - return { - setPlatform: function(p) { - platform = p; - }, - $get: ['$q', '$timeout', function($q, $timeout) { - return { - ready: function(cb) { - var self = this; - var q = $q.defer(); - - $timeout(function readyWait() { - if(isReady()) { - isPlatformReady = true; - q.resolve(); - cb(); - } else { - $timeout(readyWait, 50); - } - }, 50); - - return q.promise; - } - }; - }] - }; -}); - -})(ionic); -; ; (function() { 'use strict'; diff --git a/js/ext/angular/src/directive/ionicPlatform.js b/js/ext/angular/src/service/ionicPlatform.js similarity index 100% rename from js/ext/angular/src/directive/ionicPlatform.js rename to js/ext/angular/src/service/ionicPlatform.js From 7b9698e8b7df88ba53ed9496360202e4b41265e4 Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Tue, 5 Nov 2013 11:12:21 -0600 Subject: [PATCH 6/6] 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();