From b31f4e8e3f2f39bd5bd1de887f74f5907183b2b8 Mon Sep 17 00:00:00 2001 From: Adam Bradley Date: Wed, 20 Aug 2014 11:09:35 -0500 Subject: [PATCH] refactor(sideMenu): move controller logic to $ionicSideMenus --- js/angular/controller/sideMenuController.js | 320 +++++++++++++++++- js/controllers/sideMenuController.js | 313 ----------------- js/controllers/viewController.js | 16 - js/views/sideMenuView.js | 5 +- .../controller/sideMenuController.unit.js | 214 +++++++++++- .../controllers/sideMenuController.unit.js | 212 ------------ 6 files changed, 509 insertions(+), 571 deletions(-) delete mode 100644 js/controllers/sideMenuController.js delete mode 100644 js/controllers/viewController.js delete mode 100644 test/unit/controllers/sideMenuController.unit.js diff --git a/js/angular/controller/sideMenuController.js b/js/angular/controller/sideMenuController.js index e9ddc02658..01b58b17f4 100644 --- a/js/angular/controller/sideMenuController.js +++ b/js/angular/controller/sideMenuController.js @@ -6,37 +6,314 @@ IonicModule '$ionicPlatform', function($scope, $attrs, $ionicSideMenuDelegate, $ionicPlatform) { var self = this; - extend(this, ionic.controllers.SideMenuController.prototype); + var rightShowing, leftShowing, isDragging; + var startX, lastX, offsetX; - this.$scope = $scope; + self.$scope = $scope; - ionic.controllers.SideMenuController.call(this, { - left: { width: 275 }, - right: { width: 275 } - }); + self.initialize = function(options) { + self.left = options.left; + self.right = options.right; + self.setContent(options.content); + self.dragThresholdX = options.dragThresholdX || 10; + }; - this.canDragContent = function(canDrag) { + /** + * Set the content view controller if not passed in the constructor options. + * + * @param {object} content + */ + self.setContent = function(content) { + if(content) { + self.content = content; + + self.content.onDrag = function(e) { + self._handleDrag(e); + }; + + self.content.endDrag = function(e) { + self._endDrag(e); + }; + } + }; + + self.isOpenLeft = function() { + return self.getOpenAmount() > 0; + }; + + self.isOpenRight = function() { + return self.getOpenAmount() < 0; + }; + + /** + * Toggle the left menu to open 100% + */ + self.toggleLeft = function(shouldOpen) { + var openAmount = self.getOpenAmount(); + if (arguments.length === 0) { + shouldOpen = openAmount <= 0; + } + self.content.enableAnimation(); + if(!shouldOpen) { + self.openPercentage(0); + } else { + self.openPercentage(100); + } + }; + + /** + * Toggle the right menu to open 100% + */ + self.toggleRight = function(shouldOpen) { + var openAmount = self.getOpenAmount(); + if (arguments.length === 0) { + shouldOpen = openAmount >= 0; + } + self.content.enableAnimation(); + if(!shouldOpen) { + self.openPercentage(0); + } else { + self.openPercentage(-100); + } + }; + + /** + * Close all menus. + */ + self.close = function() { + self.openPercentage(0); + }; + + /** + * @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; + }; + + /** + * @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. + */ + self.getOpenRatio = function() { + var amount = self.getOpenAmount(); + if(amount >= 0) { + return amount / self.left.width; + } + return amount / self.right.width; + }; + + self.isOpen = function() { + return self.getOpenAmount() !== 0; + }; + + /** + * @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. + */ + self.getOpenPercentage = function() { + return self.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. + */ + self.openPercentage = function(percentage) { + var p = percentage / 100; + + if(self.left && percentage >= 0) { + self.openAmount(self.left.width * p); + } else if(self.right && percentage < 0) { + var maxRight = self.right.width; + self.openAmount(self.right.width * p); + } + + if(percentage !== 0) { + document.body.classList.add('menu-open'); + } else { + document.body.classList.remove('menu-open'); + } + }; + + /** + * 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). + */ + self.openAmount = function(amount) { + var maxLeft = self.left && self.left.width || 0; + var maxRight = self.right && self.right.width || 0; + + // 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); + return; + } + + if(!(self.right && self.right.isEnabled) && amount < 0) { + self.content.setTranslateX(0); + return; + } + + if(leftShowing && amount > maxLeft) { + self.content.setTranslateX(maxLeft); + return; + } + + if(rightShowing && amount < -maxRight) { + self.content.setTranslateX(-maxRight); + return; + } + + self.content.setTranslateX(amount); + + if(amount >= 0) { + leftShowing = true; + rightShowing = false; + + if(amount > 0) { + // Push the z-index of the right menu down + self.right && self.right.pushDown && self.right.pushDown(); + // Bring the z-index of the left menu up + self.left && self.left.bringUp && self.left.bringUp(); + } + } else { + rightShowing = true; + leftShowing = false; + + // Bring the z-index of the right menu up + self.right && self.right.bringUp && self.right.bringUp(); + // Push the z-index of the left menu down + self.left && self.left.pushDown && self.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 + */ + self.snapToRest = function(e) { + // We want to animate at the end of this + self.content.enableAnimation(); + isDragging = false; + + // Check how much the panel is open after the drag, and + // what the drag velocity is + var ratio = self.getOpenRatio(); + + if(ratio === 0) { + // Just to be safe + self.openPercentage(0); + return; + } + + var velocityThreshold = 0.3; + var velocityX = e.gesture.velocityX; + var direction = e.gesture.direction; + + // Going right, less than half, too slow (snap back) + if(ratio > 0 && ratio < 0.5 && direction == 'right' && velocityX < velocityThreshold) { + self.openPercentage(0); + } + + // Going left, more than half, too slow (snap back) + else if(ratio > 0.5 && direction == 'left' && velocityX < velocityThreshold) { + self.openPercentage(100); + } + + // Going left, less than half, too slow (snap back) + else if(ratio < 0 && ratio > -0.5 && direction == 'left' && velocityX < velocityThreshold) { + self.openPercentage(0); + } + + // Going right, more than half, too slow (snap back) + else if(ratio < 0.5 && direction == 'right' && velocityX < velocityThreshold) { + self.openPercentage(-100); + } + + // Going right, more than half, or quickly (snap open) + else if(direction == 'right' && ratio >= 0 && (ratio >= 0.5 || velocityX > velocityThreshold)) { + self.openPercentage(100); + } + + // Going left, more than half, or quickly (span open) + else if(direction == 'left' && ratio <= 0 && (ratio <= -0.5 || velocityX > velocityThreshold)) { + self.openPercentage(-100); + } + + // Snap back for safety + else { + self.openPercentage(0); + } + }; + + // End a drag with the given event + self._endDrag = function(e) { + if(isDragging) { + self.snapToRest(e); + } + startX = null; + lastX = null; + offsetX = null; + }; + + // Handle a drag event + self._handleDrag = function(e) { + + // If we don't have start coords, grab and store them + if(!startX) { + startX = e.gesture.touches[0].pageX; + lastX = startX; + } else { + // Grab the current tap coords + lastX = e.gesture.touches[0].pageX; + } + + // Calculate difference from the tap points + if(!isDragging && Math.abs(lastX - startX) > self.dragThresholdX) { + // if the difference is greater than threshold, start dragging using the current + // point as the starting point + startX = lastX; + + isDragging = true; + // Initialize dragging + self.content.disableAnimation(); + offsetX = self.getOpenAmount(); + } + + if(isDragging) { + self.openAmount(offsetX + (lastX - startX)); + } + }; + + self.canDragContent = function(canDrag) { if (arguments.length) { $scope.dragContent = !!canDrag; } return $scope.dragContent; }; - this.edgeThreshold = 25; - this.edgeThresholdEnabled = false; - this.edgeDragThreshold = function(value) { + self.edgeThreshold = 25; + self.edgeThresholdEnabled = false; + self.edgeDragThreshold = function(value) { if (arguments.length) { if (angular.isNumber(value) && value > 0) { - this.edgeThreshold = value; - this.edgeThresholdEnabled = true; + self.edgeThreshold = value; + self.edgeThresholdEnabled = true; } else { - this.edgeThresholdEnabled = !!value; + self.edgeThresholdEnabled = !!value; } } - return this.edgeThresholdEnabled; + return self.edgeThresholdEnabled; }; - this.isDraggableTarget = function(e) { + self.isDraggableTarget = function(e) { //Only restrict edge when sidemenu is closed and restriction is enabled var shouldOnlyAllowEdgeDrag = self.edgeThresholdEnabled && !self.isOpen(); var startX = e.gesture.startEvent && e.gesture.startEvent.center && @@ -56,9 +333,9 @@ function($scope, $attrs, $ionicSideMenuDelegate, $ionicPlatform) { $scope.sideMenuContentTranslateX = 0; - var deregisterBackButtonAction = angular.noop; - var closeSideMenu = angular.bind(this, this.close); + var closeSideMenu = angular.bind(self, self.close); + $scope.$watch(function() { return self.getOpenAmount() !== 0; }, function(isOpen) { @@ -72,10 +349,17 @@ function($scope, $attrs, $ionicSideMenuDelegate, $ionicPlatform) { }); var deregisterInstance = $ionicSideMenuDelegate._registerInstance( - this, $attrs.delegateHandle + self, $attrs.delegateHandle ); + $scope.$on('$destroy', function() { deregisterInstance(); deregisterBackButtonAction(); }); + + self.initialize({ + left: { width: 275 }, + right: { width: 275 } + }); + }]); diff --git a/js/controllers/sideMenuController.js b/js/controllers/sideMenuController.js deleted file mode 100644 index 2fbc20b156..0000000000 --- a/js/controllers/sideMenuController.js +++ /dev/null @@ -1,313 +0,0 @@ -(function(ionic) { -'use strict'; - -/** - * 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 = ionic.controllers.ViewController.inherit({ - initialize: function(options) { - var self = this; - - this.left = options.left; - this.right = options.right; - this.content = options.content; - this.dragThresholdX = options.dragThresholdX || 10; - - this._rightShowing = false; - this._leftShowing = false; - this._isDragging = false; - - if(this.content) { - this.content.onDrag = function(e) { - self._handleDrag(e); - }; - - this.content.onEndDrag =function(e) { - self._endDrag(e); - }; - } - }, - /** - * 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); - }; - }, - - isOpenLeft: function() { - return this.getOpenAmount() > 0; - }, - - isOpenRight: function() { - return this.getOpenAmount() < 0; - }, - - /** - * Toggle the left menu to open 100% - */ - toggleLeft: function(shouldOpen) { - var openAmount = this.getOpenAmount(); - if (arguments.length === 0) { - shouldOpen = openAmount <= 0; - } - this.content.enableAnimation(); - if(!shouldOpen) { - this.openPercentage(0); - } else { - this.openPercentage(100); - } - }, - - /** - * Toggle the right menu to open 100% - */ - toggleRight: function(shouldOpen) { - var openAmount = this.getOpenAmount(); - if (arguments.length === 0) { - shouldOpen = openAmount >= 0; - } - this.content.enableAnimation(); - if(!shouldOpen) { - this.openPercentage(0); - } else { - this.openPercentage(-100); - } - }, - - /** - * Close all menus. - */ - close: function() { - this.openPercentage(0); - }, - - /** - * @return {float} The amount the side menu is open, either positive or negative for left (positive), or right (negative) - */ - getOpenAmount: function() { - return this.content && 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) { - return amount / this.left.width; - } - return amount / this.right.width; - }, - - isOpen: function() { - return this.getOpenAmount() !== 0; - }, - - /** - * @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; - - if(this.left && percentage >= 0) { - this.openAmount(this.left.width * p); - } else if(this.right && percentage < 0) { - var maxRight = this.right.width; - this.openAmount(this.right.width * p); - } - - if(percentage !== 0) { - document.body.classList.add('menu-open'); - } else { - document.body.classList.remove('menu-open'); - } - }, - - /** - * 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 && this.left.width || 0; - var maxRight = this.right && this.right.width || 0; - - // Check if we can move to that side, depending if the left/right panel is enabled - if(!(this.left && this.left.isEnabled) && amount > 0) { - this.content.setTranslateX(0); - return; - } - - if(!(this.right && this.right.isEnabled) && amount < 0) { - this.content.setTranslateX(0); - return; - } - - if(this._leftShowing && amount > maxLeft) { - this.content.setTranslateX(maxLeft); - return; - } - - if(this._rightShowing && amount < -maxRight) { - this.content.setTranslateX(-maxRight); - return; - } - - this.content.setTranslateX(amount); - - if(amount >= 0) { - this._leftShowing = true; - this._rightShowing = false; - - if(amount > 0) { - // Push the z-index of the right menu down - this.right && this.right.pushDown && this.right.pushDown(); - // Bring the z-index of the left menu up - this.left && this.left.bringUp && this.left.bringUp(); - } - } else { - this._rightShowing = true; - this._leftShowing = false; - - // Bring the z-index of the right menu up - this.right && this.right.bringUp && this.right.bringUp(); - // Push the z-index of the left menu down - this.left && this.left.pushDown && 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(); - this._isDragging = false; - - // Check how much the panel is open after the drag, and - // what the drag velocity is - var ratio = this.getOpenRatio(); - - if(ratio === 0) { - // Just to be safe - this.openPercentage(0); - return; - } - - var velocityThreshold = 0.3; - var velocityX = e.gesture.velocityX; - var direction = e.gesture.direction; - - // Less than half, going left - //if(ratio > 0 && ratio < 0.5 && direction == 'left' && velocityX < velocityThreshold) { - //this.openPercentage(0); - //} - - // Going right, less than half, too slow (snap back) - if(ratio > 0 && ratio < 0.5 && direction == 'right' && velocityX < velocityThreshold) { - this.openPercentage(0); - } - - // Going left, more than half, too slow (snap back) - else if(ratio > 0.5 && direction == 'left' && velocityX < velocityThreshold) { - this.openPercentage(100); - } - - // Going left, less than half, too slow (snap back) - else if(ratio < 0 && ratio > -0.5 && direction == 'left' && velocityX < velocityThreshold) { - this.openPercentage(0); - } - - // Going right, more than half, too slow (snap back) - else if(ratio < 0.5 && direction == 'right' && velocityX < velocityThreshold) { - this.openPercentage(-100); - } - - // Going right, more than half, or quickly (snap open) - else if(direction == 'right' && ratio >= 0 && (ratio >= 0.5 || velocityX > velocityThreshold)) { - this.openPercentage(100); - } - - // Going left, more than half, or quickly (span open) - else if(direction == 'left' && ratio <= 0 && (ratio <= -0.5 || velocityX > velocityThreshold)) { - this.openPercentage(-100); - } - - // Snap back for safety - else { - this.openPercentage(0); - } - }, - - // End a drag with the given event - _endDrag: function(e) { - if(this._isDragging) { - this.snapToRest(e); - } - this._startX = null; - this._lastX = null; - this._offsetX = null; - }, - - // Handle a drag event - _handleDrag: function(e) { - - // If we don't have start coords, grab and store them - if(!this._startX) { - this._startX = e.gesture.touches[0].pageX; - this._lastX = this._startX; - } else { - // Grab the current tap coords - this._lastX = e.gesture.touches[0].pageX; - } - - // Calculate difference from the tap points - if(!this._isDragging && Math.abs(this._lastX - this._startX) > this.dragThresholdX) { - // if the difference is greater than threshold, start dragging using the current - // point as the starting point - this._startX = this._lastX; - - this._isDragging = true; - // Initialize dragging - this.content.disableAnimation(); - this._offsetX = this.getOpenAmount(); - } - - if(this._isDragging) { - this.openAmount(this._offsetX + (this._lastX - this._startX)); - } - } - }); - -})(ionic); diff --git a/js/controllers/viewController.js b/js/controllers/viewController.js deleted file mode 100644 index 036e6c0a1e..0000000000 --- a/js/controllers/viewController.js +++ /dev/null @@ -1,16 +0,0 @@ -(function(ionic) { -'use strict'; - ionic.controllers.ViewController = function(options) { - this.initialize.apply(this, arguments); - }; - - ionic.controllers.ViewController.inherit = ionic.inherit; - - ionic.extend(ionic.controllers.ViewController.prototype, { - initialize: function() {}, - // Destroy this view controller, including all child views - destroy: function() { - } - }); - -})(window.ionic); diff --git a/js/views/sideMenuView.js b/js/views/sideMenuView.js index 890e690dd7..3e772b343c 100644 --- a/js/views/sideMenuView.js +++ b/js/views/sideMenuView.js @@ -12,7 +12,6 @@ this.isEnabled = (typeof opts.isEnabled === 'undefined') ? true : opts.isEnabled; this.setWidth(opts.width); }, - getFullWidth: function() { return this.width; }, @@ -37,12 +36,10 @@ ionic.views.SideMenuContent = ionic.views.View.inherit({ initialize: function(opts) { - var _this = this; - ionic.extend(this, { animationClass: 'menu-animated', onDrag: function(e) {}, - onEndDrag: function(e) {}, + onEndDrag: function(e) {} }, opts); ionic.onGesture('drag', ionic.proxy(this._onDrag, this), this.el); diff --git a/test/unit/angular/controller/sideMenuController.unit.js b/test/unit/angular/controller/sideMenuController.unit.js index faabaf71cd..ff9e20dd98 100644 --- a/test/unit/angular/controller/sideMenuController.unit.js +++ b/test/unit/angular/controller/sideMenuController.unit.js @@ -1,25 +1,224 @@ describe('$ionicSideMenus controller', function() { + var ctrl; + + var Controller = function(opts) { + this.el = opts.el; + this.animateClass = opts.animateClass; + }; + Controller.prototype = { + getTranslateX: function() { + var r = /translate3d\((-?.+)px/; + var d = r.exec(this.el.style.webkitTransform); + + if(d && d.length > 0) { + return parseFloat(d[1]); + } + return 0; + }, + setTranslateX: function(amount) { + this.el.style.webkitTransform = 'translate3d(' + amount + 'px, 0, 0)'; + }, + enableAnimation: function() { + this.el.classList.add(this.animateClass); + }, + disableAnimation: function() { + this.el.classList.remove(this.animateClass); + } + }; + beforeEach(module('ionic')); - function setup(locals, props) { - var ctrl; + beforeEach(function(){ + inject(function($controller, $rootScope) { var scope = $rootScope.$new(); ctrl = $controller('$ionicSideMenus', angular.extend({ $scope: scope, $attrs: {} - }, locals || {})); - angular.extend(ctrl, props || {}); + }, {})); + angular.extend(ctrl, {}); + ctrl.left = new ionic.views.SideMenu({ + width: 270, + el: document.createElement('div'), + isEnabled: true + }); + ctrl.right = new ionic.views.SideMenu({ + width: 270, + el: document.createElement('div'), + isEnabled: true + }); + ctrl.setContent(new Controller({ el: document.createElement('div') })); }); - return ctrl; - } + + }); + + // Menu enable/disable + it('should set enabled/disabled', function() { + ctrl.left.setIsEnabled(false); + ctrl.right.setIsEnabled(false); + expect(ctrl.left.isEnabled).toEqual(false); + expect(ctrl.right.isEnabled).toEqual(false); + ctrl.left.setIsEnabled(true); + ctrl.right.setIsEnabled(true); + expect(ctrl.left.isEnabled).toEqual(true); + expect(ctrl.right.isEnabled).toEqual(true); + }); + + // Menu widths + it('should init widths', function() { + expect(ctrl.left.width).toEqual(270); + expect(ctrl.right.width).toEqual(270); + }); + + it('should have amount and percentage correct', function() { + ctrl.openAmount(ctrl.left.width/2); + expect(ctrl.getOpenAmount()).toEqual(ctrl.left.width/2); + expect(ctrl.getOpenPercentage()).toEqual(50); + + ctrl.openAmount(ctrl.left.width/4); + expect(ctrl.getOpenAmount()).toEqual(ctrl.left.width/4); + expect(ctrl.getOpenPercentage()).toEqual(25); + + ctrl.openAmount(-ctrl.right.width/2); + expect(ctrl.getOpenAmount()).toEqual(-ctrl.right.width/2); + expect(ctrl.getOpenPercentage()).toEqual(-50); + }); + + // Open + it('should toggle left', function() { + ctrl.toggleLeft(); + expect(ctrl.getOpenPercentage()).toEqual(100); + ctrl.toggleLeft(); + expect(ctrl.getOpenPercentage()).toEqual(0); + ctrl.toggleLeft(); + expect(ctrl.getOpenPercentage()).toEqual(100); + ctrl.toggleLeft(); + expect(ctrl.getOpenPercentage()).toEqual(0); + }); + + it('should toggle right', function() { + ctrl.toggleRight(); + expect(ctrl.getOpenPercentage()).toEqual(-100); + ctrl.toggleRight(); + expect(ctrl.getOpenPercentage()).toEqual(0); + ctrl.toggleRight(); + expect(ctrl.getOpenPercentage()).toEqual(-100); + ctrl.toggleRight(); + expect(ctrl.getOpenPercentage()).toEqual(0); + }); + + it('should isOpen', function() { + expect(ctrl.isOpen()).toEqual(false); + ctrl.toggleLeft(); + expect(ctrl.isOpen()).toEqual(true); + ctrl.toggleLeft(); + expect(ctrl.isOpen()).toEqual(false); + ctrl.toggleLeft(); + expect(ctrl.isOpen()).toEqual(true); + ctrl.toggleLeft(); + + expect(ctrl.isOpen()).toEqual(false); + ctrl.toggleRight(); + expect(ctrl.isOpen()).toEqual(true); + ctrl.toggleRight(); + expect(ctrl.isOpen()).toEqual(false); + ctrl.toggleRight(); + expect(ctrl.isOpen()).toEqual(true); + }); + + + it('should isOpenLeft', function() { + expect(ctrl.isOpenLeft()).toEqual(false); + ctrl.toggleLeft(); + expect(ctrl.isOpenLeft()).toEqual(true); + ctrl.toggleLeft(); + expect(ctrl.isOpenLeft()).toEqual(false); + ctrl.toggleLeft(); + expect(ctrl.isOpenLeft()).toEqual(true); + }); + + it('should isOpenRight', function() { + expect(ctrl.isOpenRight()).toEqual(false); + ctrl.toggleRight(); + expect(ctrl.isOpenRight()).toEqual(true); + ctrl.toggleRight(); + expect(ctrl.isOpenRight()).toEqual(false); + ctrl.toggleRight(); + expect(ctrl.isOpenRight()).toEqual(true); + }); + + // Snap + it('should snap', function() { + + // Center to right, Going right, less than half, too slow (snap back) + ctrl.openAmount(10); + ctrl.snapToRest({ + gesture: { + velocityX: 0, + direction: 'right' + } + }); + expect(ctrl.getOpenPercentage()).toEqual(0); + + // Right to left, Going left, more than half, too slow (snap back) + ctrl.openPercentage(51); + ctrl.snapToRest({ + gesture: { + velocityX: 0, + direction: 'left' + } + }); + expect(ctrl.getOpenPercentage()).toEqual(100); + + // Right to left, Going left, less than half, too slow (snap back) + ctrl.openAmount(10); + ctrl.snapToRest({ + gesture: { + velocityX: 0, + direction: 'left' + } + }); + expect(ctrl.getOpenPercentage()).toEqual(0); + + // Left to right, Going right, more than half, too slow (snap back) + ctrl.openPercentage(-51); + ctrl.snapToRest({ + gesture: { + velocityX: 0, + direction: 'right' + } + }); + expect(ctrl.getOpenPercentage()).toEqual(-100); + + // Going right, more than half, or quickly (snap open) + ctrl.openPercentage(-51); + ctrl.snapToRest({ + gesture: { + velocityX: 1, + direction: 'right' + } + }); + expect(ctrl.getOpenPercentage()).toEqual(0); + + // Going left, more than half, or quickly (snap open) + ctrl.openPercentage(-51); + ctrl.snapToRest({ + gesture: { + velocityX: 1, + direction: 'left' + } + }); + expect(ctrl.getOpenPercentage()).toEqual(-100); + }); + + it('Should test content drag events', function() { + }); it('should register with backButton on open and dereg on close', inject(function($ionicPlatform) { var openAmount = 0; var deregSpy = jasmine.createSpy('deregister'); spyOn($ionicPlatform, 'registerBackButtonAction').andReturn(deregSpy); - var ctrl = setup(); spyOn(ctrl, 'getOpenAmount').andCallFake(function() { return openAmount; }); expect($ionicPlatform.registerBackButtonAction).not.toHaveBeenCalled(); @@ -40,7 +239,6 @@ describe('$ionicSideMenus controller', function() { var deregSpy = jasmine.createSpy('deregister'); spyOn($ionicPlatform, 'registerBackButtonAction').andReturn(deregSpy); - var ctrl = setup(); spyOn(ctrl, 'getOpenAmount').andCallFake(function() { return openAmount; }); expect($ionicPlatform.registerBackButtonAction).not.toHaveBeenCalled(); diff --git a/test/unit/controllers/sideMenuController.unit.js b/test/unit/controllers/sideMenuController.unit.js deleted file mode 100644 index 82c969f111..0000000000 --- a/test/unit/controllers/sideMenuController.unit.js +++ /dev/null @@ -1,212 +0,0 @@ -describe('SideMenuController', function() { - var ctrl, l, r, c; - - var Controller = function(opts) { - this.el = opts.el; - this.animateClass = opts.animateClass; - }; - Controller.prototype = { - getTranslateX: function() { - var r = /translate3d\((-?.+)px/; - var d = r.exec(this.el.style.webkitTransform); - - if(d && d.length > 0) { - return parseFloat(d[1]); - } - return 0; - }, - setTranslateX: function(amount) { - this.el.style.webkitTransform = 'translate3d(' + amount + 'px, 0, 0)'; - }, - enableAnimation: function() { - this.el.classList.add(this.animateClass); - }, - disableAnimation: function() { - this.el.classList.remove(this.animateClass); - } - }; - - beforeEach(function() { - l = new ionic.views.SideMenu({ el: document.createElement('div'), width: 270 }); - r = new ionic.views.SideMenu({ el: document.createElement('div'), width: 270 }); - c = new Controller({ el: document.createElement('div') }); - - ctrl = new ionic.controllers.SideMenuController({ - left: l, - right: r, - content: c - }); - }); - - // Init - it('Should init', function() { - expect(ctrl.left).toBe(l); - expect(ctrl.right).toBe(r); - expect(ctrl.content).toBe(c); - }); - - // Menu enable/disable - it('Should set enabled/disabled', function() { - var left = ctrl.left; - var right = ctrl.right; - left.setIsEnabled(false); - right.setIsEnabled(false); - expect(left.isEnabled).toEqual(false); - expect(right.isEnabled).toEqual(false); - left.setIsEnabled(true); - right.setIsEnabled(true); - expect(left.isEnabled).toEqual(true); - expect(right.isEnabled).toEqual(true); - }); - - // Menu widths - it('Should init widths', function() { - var left = ctrl.left; - var right = ctrl.right; - expect(left.width).toEqual(270); - expect(right.width).toEqual(270); - }); - - it('Should have amount and percentage correct', function() { - ctrl.openAmount(l.width/2); - expect(ctrl.getOpenAmount()).toEqual(l.width/2); - expect(ctrl.getOpenPercentage()).toEqual(50); - - ctrl.openAmount(l.width/4); - expect(ctrl.getOpenAmount()).toEqual(l.width/4); - expect(ctrl.getOpenPercentage()).toEqual(25); - - ctrl.openAmount(-r.width/2); - expect(ctrl.getOpenAmount()).toEqual(-r.width/2); - expect(ctrl.getOpenPercentage()).toEqual(-50); - }); - - // Open - it('Should toggle left', function() { - ctrl.toggleLeft(); - expect(ctrl.getOpenPercentage()).toEqual(100); - ctrl.toggleLeft(); - expect(ctrl.getOpenPercentage()).toEqual(0); - ctrl.toggleLeft(); - expect(ctrl.getOpenPercentage()).toEqual(100); - ctrl.toggleLeft(); - expect(ctrl.getOpenPercentage()).toEqual(0); - }); - - it('should toggle right', function() { - ctrl.toggleRight(); - expect(ctrl.getOpenPercentage()).toEqual(-100); - ctrl.toggleRight(); - expect(ctrl.getOpenPercentage()).toEqual(0); - ctrl.toggleRight(); - expect(ctrl.getOpenPercentage()).toEqual(-100); - ctrl.toggleRight(); - expect(ctrl.getOpenPercentage()).toEqual(0); - }); - - it('should isOpen', function() { - expect(ctrl.isOpen()).toEqual(false); - ctrl.toggleLeft(); - expect(ctrl.isOpen()).toEqual(true); - ctrl.toggleLeft(); - expect(ctrl.isOpen()).toEqual(false); - ctrl.toggleLeft(); - expect(ctrl.isOpen()).toEqual(true); - ctrl.toggleLeft(); - - expect(ctrl.isOpen()).toEqual(false); - ctrl.toggleRight(); - expect(ctrl.isOpen()).toEqual(true); - ctrl.toggleRight(); - expect(ctrl.isOpen()).toEqual(false); - ctrl.toggleRight(); - expect(ctrl.isOpen()).toEqual(true); - }); - - it('should isOpenLeft', function() { - expect(ctrl.isOpenLeft()).toEqual(false); - ctrl.toggleLeft(); - expect(ctrl.isOpenLeft()).toEqual(true); - ctrl.toggleLeft(); - expect(ctrl.isOpenLeft()).toEqual(false); - ctrl.toggleLeft(); - expect(ctrl.isOpenLeft()).toEqual(true); - }); - - it('should isOpenRight', function() { - expect(ctrl.isOpenRight()).toEqual(false); - ctrl.toggleRight(); - expect(ctrl.isOpenRight()).toEqual(true); - ctrl.toggleRight(); - expect(ctrl.isOpenRight()).toEqual(false); - ctrl.toggleRight(); - expect(ctrl.isOpenRight()).toEqual(true); - }); - - // Snap - it('Should snap', function() { - - // Center to right, Going right, less than half, too slow (snap back) - ctrl.openAmount(10); - ctrl.snapToRest({ - gesture: { - velocityX: 0, - direction: 'right' - } - }); - expect(ctrl.getOpenPercentage()).toEqual(0); - - // Right to left, Going left, more than half, too slow (snap back) - ctrl.openPercentage(51); - ctrl.snapToRest({ - gesture: { - velocityX: 0, - direction: 'left' - } - }); - expect(ctrl.getOpenPercentage()).toEqual(100); - - // Right to left, Going left, less than half, too slow (snap back) - ctrl.openAmount(10); - ctrl.snapToRest({ - gesture: { - velocityX: 0, - direction: 'left' - } - }); - expect(ctrl.getOpenPercentage()).toEqual(0); - - // Left to right, Going right, more than half, too slow (snap back) - ctrl.openPercentage(-51); - ctrl.snapToRest({ - gesture: { - velocityX: 0, - direction: 'right' - } - }); - expect(ctrl.getOpenPercentage()).toEqual(-100); - - // Going right, more than half, or quickly (snap open) - ctrl.openPercentage(-51); - ctrl.snapToRest({ - gesture: { - velocityX: 1, - direction: 'right' - } - }); - expect(ctrl.getOpenPercentage()).toEqual(0); - - // Going left, more than half, or quickly (snap open) - ctrl.openPercentage(-51); - ctrl.snapToRest({ - gesture: { - velocityX: 1, - direction: 'left' - } - }); - expect(ctrl.getOpenPercentage()).toEqual(-100); - }); - - it('Should test content drag events', function() { - }); -});