From 1212945df83feddf4a8b9bbe0a6fe09fe2252cdc Mon Sep 17 00:00:00 2001 From: Max Lynch Date: Fri, 4 Oct 2013 10:16:50 -0500 Subject: [PATCH] Side menu content scoping fix --- dist/ionic-angular.js | 56 ++++----- dist/ionic.js | 113 ++++++++++++++---- example/toderp2/js/app.js | 2 - js/controllers/sideMenuController.js | 24 +++- js/ext/angular/src/directive/ionicSideMenu.js | 56 ++++----- 5 files changed, 147 insertions(+), 104 deletions(-) diff --git a/dist/ionic-angular.js b/dist/ionic-angular.js index fd14016ac3..35c749476e 100644 --- a/dist/ionic-angular.js +++ b/dist/ionic-angular.js @@ -165,33 +165,6 @@ angular.module('ionic.ui.sideMenu', []) bringUp: function() { $scope.rightZIndex = 0; } - }, - content: { - onDrag: function(e) {}, - endDrag: function(e) {}, - getTranslateX: function() { - /* - var r = /translate3d\((-?.+)px/; - var d = r.exec(this.el.style.webkitTransform); - - if(d && d.length > 0) { - return parseFloat(d[1]); - } - */ - return $scope.contentTranslateX || 0; - }, - setTranslateX: function(amount) { - $scope.contentTranslateX = amount; - $scope.$apply(); - }, - enableAnimation: function() { - //this.el.classList.add(this.animateClass); - $scope.animationEnabled = true; - }, - disableAnimation: function() { - //this.el.classList.remove(this.animateClass); - $scope.animationEnabled = false; - } } }); @@ -204,7 +177,7 @@ angular.module('ionic.ui.sideMenu', []) controller: 'SideMenuCtrl', replace: true, transclude: true, - template: '
', + template: '
', } }) @@ -212,6 +185,7 @@ angular.module('ionic.ui.sideMenu', []) return { restrict: 'CA', require: '^sideMenuCtrl', + scope: true, compile: function(element, attr, transclude) { return function($scope, $element, $attr, sideMenuCtrl) { window.ionic.onGesture('drag', function(e) { @@ -222,17 +196,27 @@ angular.module('ionic.ui.sideMenu', []) sideMenuCtrl._endDrag(e); }, $element[0]); - $scope.$watch('contentTranslateX', function(value) { - $element[0].style.webkitTransform = 'translate3d(' + value + 'px, 0, 0)'; - }); - - $scope.$watch('animationEnabled', function(isAnimationEnabled) { - if(isAnimationEnabled) { + sideMenuCtrl.setContent({ + onDrag: function(e) {}, + endDrag: function(e) {}, + getTranslateX: function() { + return $scope.contentTranslateX || 0; + }, + setTranslateX: function(amount) { + $scope.contentTranslateX = amount; + $scope.$apply(); + $element[0].style.webkitTransform = 'translate3d(' + amount + 'px, 0, 0)'; + }, + enableAnimation: function() { + //this.el.classList.add(this.animateClass); + $scope.animationEnabled = true; $element[0].classList.add('menu-animated'); - } else { + }, + disableAnimation: function() { + //this.el.classList.remove(this.animateClass); + $scope.animationEnabled = false; $element[0].classList.remove('menu-animated'); } - }); }; } diff --git a/dist/ionic.js b/dist/ionic.js index 396486f639..c2840417da 100644 --- a/dist/ionic.js +++ b/dist/ionic.js @@ -2341,38 +2341,57 @@ ionic.controllers.NavController.prototype = { ; (function(ionic) { - + /** + * The SideMenuController is a controller with a left and/or right menu that + * can be slid out and toggled. Seen on many an app. + * + * The right or left menu can be disabled or not used at all, if desired. + */ ionic.controllers.SideMenuController = function(options) { var self = this; - self.left = options.left; - self.right = options.right; - self.content = options.content; + this.left = options.left; + this.right = options.right; + this.content = options.content; - self._rightShowing = false; - self._leftShowing = false; + this._rightShowing = false; + this._leftShowing = false; + this._isDragging = false; - this.content.onDrag = function(e) { - self._handleDrag(e); - }; + if(this.content) { + this.content.onDrag = function(e) { + self._handleDrag(e); + }; - this.content.endDrag = function(e) { - self._endDrag(e); - }; - - /* - // Bind release and drag listeners - window.ion.onGesture('release', function(e) { - self._endDrag(e); - }, self.center); - - window.ion.onGesture('drag', function(e) { - self._handleDrag(e); - }, self.center); - */ + this.content.endDrag = function(e) { + self._endDrag(e); + }; + } }; ionic.controllers.SideMenuController.prototype = { + /** + * Set the content view controller if not passed in the constructor options. + * + * @param {object} content + */ + setContent: function(content) { + var self = this; + + this.content = content; + + this.content.onDrag = function(e) { + self._handleDrag(e); + }; + + this.content.endDrag = function(e) { + self._endDrag(e); + }; + }, + + /** + * Toggle the left menu to open 100% + */ toggleLeft: function() { var openAmount = this.getOpenAmount(); if(openAmount > 0) { @@ -2381,6 +2400,10 @@ ionic.controllers.NavController.prototype = { this.openPercentage(100); } }, + + /** + * Toggle the right menu to open 100% + */ toggleRight: function() { var openAmount = this.getOpenAmount(); if(openAmount < 0) { @@ -2389,9 +2412,20 @@ ionic.controllers.NavController.prototype = { this.openPercentage(-100); } }, + + + /** + * @return {float} The amount the side menu is open, either positive or negative for left (positive), or right (negative) + */ getOpenAmount: function() { return this.content.getTranslateX() || 0; }, + + /** + * @return {float} The ratio of open amount over menu width. For example, a + * menu of width 100 open 50 pixels would be open 50% or a ratio of 0.5. Value is negative + * for right menu. + */ getOpenRatio: function() { var amount = this.getOpenAmount(); if(amount >= 0) { @@ -2399,9 +2433,20 @@ ionic.controllers.NavController.prototype = { } return amount / this.right.width; }, + + /** + * @return {float} The percentage of open amount over menu width. For example, a + * menu of width 100 open 50 pixels would be open 50%. Value is negative + * for right menu. + */ getOpenPercentage: function() { return this.getOpenRatio() * 100; }, + + /** + * Open the menu with a given percentage amount. + * @param {float} percentage The percentage (positive or negative for left/right) to open the menu. + */ openPercentage: function(percentage) { var p = percentage / 100; var maxLeft = this.left.width; @@ -2412,6 +2457,12 @@ ionic.controllers.NavController.prototype = { this.openAmount(maxRight * p); } }, + + /** + * Open the menu the given pixel amount. + * @param {float} amount the pixel amount to open the menu. Positive value for left menu, + * negative value for right menu (only one menu will be visible at a time). + */ openAmount: function(amount) { var maxLeft = this.left.width; var maxRight = this.right.width; @@ -2445,6 +2496,14 @@ ionic.controllers.NavController.prototype = { this.left.pushDown(); } }, + + /** + * Given an event object, find the final resting position of this side + * menu. For example, if the user "throws" the content to the right and + * releases the touch, the left menu should snap open (animated, of course). + * + * @param {Event} e the gesture event to use for snapping + */ snapToRest: function(e) { // We want to animate at the end of this this.content.enableAnimation(); @@ -2501,9 +2560,13 @@ ionic.controllers.NavController.prototype = { this.openPercentage(0); } }, + + // End a drag with the given event _endDrag: function(e) { this.snapToRest(e); }, + + // Initialize a drag with the given event _initDrag: function(e) { this.content.disableAnimation(); this._isDragging = true; @@ -2511,6 +2574,8 @@ ionic.controllers.NavController.prototype = { this._offsetX = 0; this._lastX = 0; }, + + // Handle a drag event _handleDrag: function(e) { if(!this._isDragging) { this._initDrag(e); @@ -2520,7 +2585,7 @@ ionic.controllers.NavController.prototype = { this._offsetX = this.getOpenAmount(); } - //console.log('Dragging page', this._startX, this._lastX, this._offsetX, e); + var newX = this._offsetX + (this._lastX - this._startX); this.openAmount(newX); diff --git a/example/toderp2/js/app.js b/example/toderp2/js/app.js index f93657899c..5dea6d87ce 100644 --- a/example/toderp2/js/app.js +++ b/example/toderp2/js/app.js @@ -2,8 +2,6 @@ angular.module('ionic.todo', [ 'ionic.todo.services', 'ionic.todo.controllers', - 'ionic.service', - 'ionic.ui.nav', 'ionic.ui.sideMenu', diff --git a/js/controllers/sideMenuController.js b/js/controllers/sideMenuController.js index 71b2b1a853..89683f4872 100644 --- a/js/controllers/sideMenuController.js +++ b/js/controllers/sideMenuController.js @@ -17,13 +17,15 @@ this._leftShowing = false; this._isDragging = false; - this.content.onDrag = function(e) { - self._handleDrag(e); - }; + if(this.content) { + this.content.onDrag = function(e) { + self._handleDrag(e); + }; - this.content.endDrag = function(e) { - self._endDrag(e); - }; + this.content.endDrag = function(e) { + self._endDrag(e); + }; + } }; ionic.controllers.SideMenuController.prototype = { @@ -33,7 +35,17 @@ * @param {object} content */ setContent: function(content) { + var self = this; + this.content = content; + + this.content.onDrag = function(e) { + self._handleDrag(e); + }; + + this.content.endDrag = function(e) { + self._endDrag(e); + }; }, /** diff --git a/js/ext/angular/src/directive/ionicSideMenu.js b/js/ext/angular/src/directive/ionicSideMenu.js index 940bb48c3c..8ed683edec 100644 --- a/js/ext/angular/src/directive/ionicSideMenu.js +++ b/js/ext/angular/src/directive/ionicSideMenu.js @@ -25,33 +25,6 @@ angular.module('ionic.ui.sideMenu', []) bringUp: function() { $scope.rightZIndex = 0; } - }, - content: { - onDrag: function(e) {}, - endDrag: function(e) {}, - getTranslateX: function() { - /* - var r = /translate3d\((-?.+)px/; - var d = r.exec(this.el.style.webkitTransform); - - if(d && d.length > 0) { - return parseFloat(d[1]); - } - */ - return $scope.contentTranslateX || 0; - }, - setTranslateX: function(amount) { - $scope.contentTranslateX = amount; - $scope.$apply(); - }, - enableAnimation: function() { - //this.el.classList.add(this.animateClass); - $scope.animationEnabled = true; - }, - disableAnimation: function() { - //this.el.classList.remove(this.animateClass); - $scope.animationEnabled = false; - } } }); @@ -64,7 +37,7 @@ angular.module('ionic.ui.sideMenu', []) controller: 'SideMenuCtrl', replace: true, transclude: true, - template: '
', + template: '
', } }) @@ -72,6 +45,7 @@ angular.module('ionic.ui.sideMenu', []) return { restrict: 'CA', require: '^sideMenuCtrl', + scope: true, compile: function(element, attr, transclude) { return function($scope, $element, $attr, sideMenuCtrl) { window.ionic.onGesture('drag', function(e) { @@ -82,17 +56,27 @@ angular.module('ionic.ui.sideMenu', []) sideMenuCtrl._endDrag(e); }, $element[0]); - $scope.$watch('contentTranslateX', function(value) { - $element[0].style.webkitTransform = 'translate3d(' + value + 'px, 0, 0)'; - }); - - $scope.$watch('animationEnabled', function(isAnimationEnabled) { - if(isAnimationEnabled) { + sideMenuCtrl.setContent({ + onDrag: function(e) {}, + endDrag: function(e) {}, + getTranslateX: function() { + return $scope.contentTranslateX || 0; + }, + setTranslateX: function(amount) { + $scope.contentTranslateX = amount; + $scope.$apply(); + $element[0].style.webkitTransform = 'translate3d(' + amount + 'px, 0, 0)'; + }, + enableAnimation: function() { + //this.el.classList.add(this.animateClass); + $scope.animationEnabled = true; $element[0].classList.add('menu-animated'); - } else { + }, + disableAnimation: function() { + //this.el.classList.remove(this.animateClass); + $scope.animationEnabled = false; $element[0].classList.remove('menu-animated'); } - }); }; }