diff --git a/js/angular/controller/sideMenuController.js b/js/angular/controller/sideMenuController.js index 6a120259d..ce7ecebab 100644 --- a/js/angular/controller/sideMenuController.js +++ b/js/angular/controller/sideMenuController.js @@ -11,7 +11,7 @@ IonicModule '$rootScope', function($scope, $attrs, $ionicSideMenuDelegate, $ionicPlatform, $ionicBody, $ionicHistory, $ionicScrollDelegate, IONIC_BACK_PRIORITY, $rootScope) { var self = this; - var rightShowing, leftShowing, isDragging; + var isDragging; var startX, lastX, offsetX, isAsideExposed; var enableMenuWithBackViews = true; @@ -61,7 +61,11 @@ function($scope, $attrs, $ionicSideMenuDelegate, $ionicPlatform, $ionicBody, $io if (arguments.length === 0) { shouldOpen = openAmount <= 0; } - self.content.enableAnimation(); + if (self.left.displayType == 'overlay') { + self.left.enableAnimation(); + } else { + self.content.enableAnimation(); + } if (!shouldOpen) { self.openPercentage(0); $rootScope.$emit('$ionicSideMenuClose', 'left'); @@ -80,7 +84,11 @@ function($scope, $attrs, $ionicSideMenuDelegate, $ionicPlatform, $ionicBody, $io if (arguments.length === 0) { shouldOpen = openAmount >= 0; } - self.content.enableAnimation(); + if (self.right.displayType == 'overlay') { + self.right.enableAnimation(); + } else { + self.content.enableAnimation(); + } if (!shouldOpen) { self.openPercentage(0); $rootScope.$emit('$ionicSideMenuClose', 'right'); @@ -111,7 +119,17 @@ function($scope, $attrs, $ionicSideMenuDelegate, $ionicPlatform, $ionicBody, $io * @return {float} The amount the side menu is open, either positive or negative for left (positive), or right (negative) */ self.getOpenAmount = function() { - return self.content && self.content.getTranslateX() || 0; + var retOpenAmount = 0; + if ((isNaN(retOpenAmount) || retOpenAmount === 0) && self.right && self.right.displayType == 'overlay') { + retOpenAmount = self.right.getTranslateX(); + } + if ((isNaN(retOpenAmount) || retOpenAmount === 0) && self.left && self.left.displayType == 'overlay') { + retOpenAmount = self.left.getTranslateX(); + } + if ((isNaN(retOpenAmount) || retOpenAmount === 0) && self.content) { + retOpenAmount = self.content.getTranslateX(); + } + return retOpenAmount; }; /** @@ -181,6 +199,18 @@ function($scope, $attrs, $ionicSideMenuDelegate, $ionicPlatform, $ionicBody, $io var maxLeft = self.left && self.left.width || 0; var maxRight = self.right && self.right.width || 0; + var overlayLeft = self.left && self.left.displayType == 'overlay' || false; + var overlayRight = self.right && self.right.displayType == 'overlay' || false; + var openLeft = overlayLeft && self.left.getTranslateX() || 0; + var openRight = overlayRight && self.right.getTranslateX() || 0; + var openContent = self.content.getTranslateX() || 0; + + if (amount > maxLeft) { + amount = maxLeft; + } else if (amount < -maxRight) { + amount = -maxRight; + } + // Check if we can move to that side, depending if the left/right panel is enabled if (!(self.left && self.left.isEnabled) && amount > 0) { self.content.setTranslateX(0); @@ -192,31 +222,30 @@ function($scope, $attrs, $ionicSideMenuDelegate, $ionicPlatform, $ionicBody, $io return; } - if (leftShowing && amount > maxLeft) { - self.content.setTranslateX(maxLeft); - return; - } - - if (rightShowing && amount < -maxRight) { - self.content.setTranslateX(-maxRight); - return; + if (amount > 0) { + if (overlayLeft) { self.left.setTranslateX(amount); } + if (overlayRight && openRight) { self.right.setTranslateX(0); } + if (!(overlayLeft && openLeft)) { self.content.setTranslateX(overlayLeft ? 0 : amount); } + } else if (amount < 0) { + if (overlayRight) { self.right.setTranslateX(amount); } + if (overlayLeft && openLeft) { self.left.setTranslateX(0); } + if (!(overlayRight && openRight)) { self.content.setTranslateX(overlayRight ? 0 : amount); } + } else /* if (amount === 0) */ { + if (overlayLeft && openLeft) { self.left.setTranslateX(amount); } + if (overlayRight && openRight) { self.right.setTranslateX(amount); } + if (!(overlayRight && openRight) && openContent) { self.content.setTranslateX(amount); } } - self.content.setTranslateX(amount); - - leftShowing = amount > 0; - rightShowing = amount < 0; - if (amount > 0) { // Push the z-index of the right menu down - self.right && self.right.pushDown && self.right.pushDown(); + self.right && self.right.displayType != 'overlay' && self.right.pushDown && self.right.pushDown(); // Bring the z-index of the left menu up - self.left && self.left.bringUp && self.left.bringUp(); + self.left && self.left.displayType != 'overlay' && self.left.bringUp && self.left.bringUp(); } else { // Bring the z-index of the right menu up - self.right && self.right.bringUp && self.right.bringUp(); + self.right && self.right.displayType != 'overlay' && self.right.bringUp && self.right.bringUp(); // Push the z-index of the left menu down - self.left && self.left.pushDown && self.left.pushDown(); + self.left && self.left.displayType != 'overlay' && self.left.pushDown && self.left.pushDown(); } }; @@ -348,6 +377,12 @@ function($scope, $attrs, $ionicSideMenuDelegate, $ionicPlatform, $ionicBody, $io isDragging = true; // Initialize dragging self.content.disableAnimation(); + if (self.left.displayType == 'overlay') { + self.left.disableAnimation(); + } + if (self.right.displayType == 'overlay') { + self.right.disableAnimation(); + } offsetX = self.getOpenAmount(); } diff --git a/js/angular/directive/sideMenu.js b/js/angular/directive/sideMenu.js index 1ab736794..688581acd 100644 --- a/js/angular/directive/sideMenu.js +++ b/js/angular/directive/sideMenu.js @@ -13,7 +13,8 @@ * + * is-enabled="shouldLeftSideMenuBeEnabled()" + * display-type="push"> * * ``` * For a complete side menu example, see the @@ -22,6 +23,7 @@ * @param {string} side Which side the side menu is currently on. Allowed values: 'left' or 'right'. * @param {boolean=} is-enabled Whether this side menu is enabled. * @param {number=} width How many pixels wide the side menu should be. Defaults to 275. + * @param {string} display-type Which type of display the menu should have. Allowed values: 'push' or 'overlay'. Defaults to 'push'. */ IonicModule .directive('ionSideMenu', function() { @@ -32,8 +34,14 @@ IonicModule compile: function(element, attr) { angular.isUndefined(attr.isEnabled) && attr.$set('isEnabled', 'true'); angular.isUndefined(attr.width) && attr.$set('width', '275'); + angular.isUndefined(attr.displayType) && attr.$set('displayType', 'push'); element.addClass('menu menu-' + attr.side); + if (attr.displayType == 'overlay') { + element.addClass('menu-animated'); + element[0].style[attr.side] = '-' + attr.width + 'px'; + element[0].style.zIndex = 2147483647; // top most, maximum zIndex value + } return function($scope, $element, $attr, sideMenuCtrl) { $scope.side = $attr.side || 'left'; @@ -41,7 +49,8 @@ IonicModule var sideMenu = sideMenuCtrl[$scope.side] = new ionic.views.SideMenu({ width: attr.width, el: $element[0], - isEnabled: true + isEnabled: true, + displayType: attr.displayType }); $scope.$watch($attr.width, function(val) { @@ -53,8 +62,12 @@ IonicModule $scope.$watch($attr.isEnabled, function(val) { sideMenu.setIsEnabled(!!val); }); + $scope.$watch($attr.displayType, function(val) { + if (val == 'push' || val == 'overlay') { + sideMenu.setDisplayType(val); + } + }); }; } }; }); - diff --git a/js/views/sideMenuView.js b/js/views/sideMenuView.js index 0bb600d22..14af2e7d6 100644 --- a/js/views/sideMenuView.js +++ b/js/views/sideMenuView.js @@ -11,6 +11,7 @@ this.el = opts.el; this.isEnabled = (typeof opts.isEnabled === 'undefined') ? true : opts.isEnabled; this.setWidth(opts.width); + this.displayType = (typeof opts.displayType === 'undefined') ? 'push' : opts.displayType; }, getFullWidth: function() { return this.width; @@ -31,7 +32,24 @@ if(this.el.style.zIndex !== '-1') { this.el.style.zIndex = '-1'; } - } + }, + setDisplayType: function(displayType) { + this.displayType = displayType; + }, + enableAnimation: function() { + this.animationEnabled = true; + this.el.classList.add('menu-animated'); + }, + disableAnimation: function() { + this.animationEnabled = false; + this.el.classList.remove('menu-animated'); + }, + getTranslateX: function() { + return parseFloat(this.el.style[ionic.CSS.TRANSFORM].replace('translate3d(', '').split(',')[0]); + }, + setTranslateX: ionic.animationFrameThrottle(function(x) { + this.el.style[ionic.CSS.TRANSFORM] = 'translate3d(' + x + 'px, 0, 0)'; + }) }); ionic.views.SideMenuContent = ionic.views.View.inherit({ diff --git a/test/unit/angular/controller/sideMenuController.unit.js b/test/unit/angular/controller/sideMenuController.unit.js index 039f5605c..16ea5c978 100644 --- a/test/unit/angular/controller/sideMenuController.unit.js +++ b/test/unit/angular/controller/sideMenuController.unit.js @@ -69,6 +69,18 @@ describe('$ionicSideMenus controller', function() { expect(ctrl.right.isEnabled).toEqual(true); }); + // Menu displayType + it('should set displayType', function() { + ctrl.left.setDisplayType('overlay'); + ctrl.right.setDisplayType('overlay'); + expect(ctrl.left.displayType).toEqual('overlay'); + expect(ctrl.right.displayType).toEqual('overlay'); + ctrl.left.setDisplayType('push'); + ctrl.right.setDisplayType('push'); + expect(ctrl.left.displayType).toEqual('push'); + expect(ctrl.right.displayType).toEqual('push'); + }); + // Menu widths it('should init widths', function() { expect(ctrl.left.width).toEqual(270); diff --git a/test/unit/views/sideMenu.unit.js b/test/unit/views/sideMenu.unit.js index d412770d4..0d4346eb9 100644 --- a/test/unit/views/sideMenu.unit.js +++ b/test/unit/views/sideMenu.unit.js @@ -12,5 +12,6 @@ describe('SideMenu', function() { it('Should init', function() { expect(menu.width).toEqual(270); expect(menu.isEnabled).toEqual(true); + expect(menu.displayType).toEqual('push'); }); });