diff --git a/js/angular/controller/sideMenuController.js b/js/angular/controller/sideMenuController.js index 4c628b020f..417ca3f401 100644 --- a/js/angular/controller/sideMenuController.js +++ b/js/angular/controller/sideMenuController.js @@ -4,8 +4,8 @@ IonicModule '$attrs', '$ionicSideMenuDelegate', '$ionicPlatform', - '$document', -function($scope, $attrs, $ionicSideMenuDelegate, $ionicPlatform, $document) { + '$ionicBody', +function($scope, $attrs, $ionicSideMenuDelegate, $ionicPlatform, $ionicBody) { var self = this; var rightShowing, leftShowing, isDragging; var startX, lastX, offsetX, isAsideExposed; @@ -132,11 +132,9 @@ function($scope, $attrs, $ionicSideMenuDelegate, $ionicPlatform, $document) { self.openAmount(self.right.width * p); } - if(percentage !== 0) { - $document[0].body.classList.add('menu-open'); - } else { - $document[0].body.classList.remove('menu-open'); - } + // add the CSS class "menu-open" if the percentage does not + // equal 0, otherwise remove the class from the body element + $ionicBody.enableClass( (percentage !== 0), 'menu-open'); }; /** @@ -269,11 +267,7 @@ function($scope, $attrs, $ionicSideMenuDelegate, $ionicPlatform, $document) { }; self.activeAsideResizing = function(isResizing) { - if(isResizing) { - $document[0].body.classList.add('aside-resizing'); - } else { - $document[0].body.classList.remove('aside-resizing'); - } + $ionicBody.enableClass(isResizing, 'aside-resizing'); }; // End a drag with the given event diff --git a/js/angular/directive/sideMenus.js b/js/angular/directive/sideMenus.js index d008b35e71..b885717438 100644 --- a/js/angular/directive/sideMenus.js +++ b/js/angular/directive/sideMenus.js @@ -64,10 +64,7 @@ IonicModule * with {@link ionic.service:$ionicSideMenuDelegate}. * */ -.directive('ionSideMenus', ['$document', function($document) { - - var ASIDE_OPEN_CSS = 'aside-open'; - +.directive('ionSideMenus', ['$ionicBody', function($ionicBody) { return { restrict: 'ECA', controller: '$ionicSideMenus', @@ -76,21 +73,15 @@ IonicModule return { pre: prelink }; function prelink($scope) { - var bodyClassList = $document[0].body.classList; $scope.$on('$ionicExposeAside', function(evt, isAsideExposed){ if(!$scope.$exposeAside) $scope.$exposeAside = {}; $scope.$exposeAside.active = isAsideExposed; - if(isAsideExposed) { - bodyClassList.add(ASIDE_OPEN_CSS); - } else { - bodyClassList.remove(ASIDE_OPEN_CSS); - } + $ionicBody.enableClass(isAsideExposed, 'aside-open'); }); $scope.$on('$destroy', function(){ - bodyClassList.remove('menu-open'); - bodyClassList.remove(ASIDE_OPEN_CSS); + $ionicBody.removeClass('menu-open', 'aside-open'); }); } diff --git a/js/angular/service/actionSheet.js b/js/angular/service/actionSheet.js index f69a7366de..17eabd26e6 100644 --- a/js/angular/service/actionSheet.js +++ b/js/angular/service/actionSheet.js @@ -51,13 +51,13 @@ IonicModule .factory('$ionicActionSheet', [ '$rootScope', - '$document', '$compile', '$animate', '$timeout', '$ionicTemplateLoader', '$ionicPlatform', -function($rootScope, $document, $compile, $animate, $timeout, $ionicTemplateLoader, $ionicPlatform) { + '$ionicBody', +function($rootScope, $compile, $animate, $timeout, $ionicTemplateLoader, $ionicPlatform, $ionicBody) { return { show: actionSheet @@ -119,7 +119,7 @@ function($rootScope, $document, $compile, $animate, $timeout, $ionicTemplateLoad scope.removed = true; sheetEl.removeClass('action-sheet-up'); - $document[0].body.classList.remove('action-sheet-open'); + $ionicBody.removeClass('action-sheet-open'); scope.$deregisterBackButton(); stateChangeListenDone(); @@ -135,8 +135,8 @@ function($rootScope, $document, $compile, $animate, $timeout, $ionicTemplateLoad scope.showSheet = function(done) { if (scope.removed) return; - $document[0].body.appendChild(element[0]); - $document[0].body.classList.add('action-sheet-open'); + $ionicBody.append(element) + .addClass('action-sheet-open'); $animate.addClass(element, 'active', function() { if (scope.removed) return; diff --git a/js/angular/service/body.js b/js/angular/service/body.js new file mode 100644 index 0000000000..05d4fd451a --- /dev/null +++ b/js/angular/service/body.js @@ -0,0 +1,80 @@ +/** + * @ngdoc service + * @name $ionicBody + * @module ionic + * @description An angular utility service to easily and efficiently + * add and remove CSS classes from the document's body element. + */ +IonicModule +.factory('$ionicBody', ['$document', function($document) { + return { + /** + * @ngdoc method + * @name $ionicBody#add + * @description Add a class to the document's body element. + * @param {string} class Each argument will be added to the body element. + * @returns {$ionicBody} The $ionicBody service so methods can be chained. + */ + addClass: function() { + for(var x=0; x')($rootScope.$new()); + $rootScope.$apply(); + var sideMenuController = el.controller('ionSideMenus'); + + expect($document[0].body.classList.contains('aside-resizing')).toEqual(false); + sideMenuController.activeAsideResizing(true); + expect($document[0].body.classList.contains('aside-resizing')).toEqual(true); + sideMenuController.activeAsideResizing(false); + expect($document[0].body.classList.contains('aside-resizing')).toEqual(false); + })); + it('should emit $ionicexposeAside', inject(function($compile, $rootScope) { var el = $compile('')($rootScope.$new()); $rootScope.$apply(); diff --git a/test/unit/angular/service/body.unit.js b/test/unit/angular/service/body.unit.js new file mode 100644 index 0000000000..493f845e94 --- /dev/null +++ b/test/unit/angular/service/body.unit.js @@ -0,0 +1,71 @@ +describe('Ionic Body Class Service', function() { + var ionicBody, doc; + + beforeEach(module('ionic')); + + beforeEach(inject(function($ionicBody, $document) { + ionicBody = $ionicBody; + body = $document[0].body; + })); + + it('Should add/remove one class the body tag', function() { + ionicBody.addClass('class1'); + expect(body.classList.contains('class1')).toEqual(true); + ionicBody.removeClass('class1'); + expect(body.classList.contains('class1')).toEqual(false); + }); + + it('Should add/remove multiple classes the body tag', function() { + ionicBody.addClass('class1', 'class2', 'class3'); + expect(body.classList.contains('class1')).toEqual(true); + expect(body.classList.contains('class2')).toEqual(true); + expect(body.classList.contains('class3')).toEqual(true); + ionicBody.removeClass('class1', 'class2', 'class3'); + expect(body.classList.contains('class1')).toEqual(false); + expect(body.classList.contains('class2')).toEqual(false); + expect(body.classList.contains('class3')).toEqual(false); + }); + + it('Should add/remove classes by chaining methods', function() { + ionicBody.addClass('class1').addClass('class2').addClass('class3'); + expect(body.classList.contains('class1')).toEqual(true); + expect(body.classList.contains('class2')).toEqual(true); + expect(body.classList.contains('class3')).toEqual(true); + ionicBody.removeClass('class1').removeClass('class2').removeClass('class3'); + expect(body.classList.contains('class1')).toEqual(false); + expect(body.classList.contains('class2')).toEqual(false); + expect(body.classList.contains('class3')).toEqual(false); + }); + + it('Should add/false one class using addTo and boolean first arg', function() { + ionicBody.enableClass(true, 'class1'); + expect(body.classList.contains('class1')).toEqual(true); + ionicBody.enableClass(false, 'class1'); + expect(body.classList.contains('class1')).toEqual(false); + }); + + it('Should add/false multiple classes using addTo and boolean first arg', function() { + ionicBody.enableClass(true, 'class1', 'class2', 'class3'); + expect(body.classList.contains('class1')).toEqual(true); + expect(body.classList.contains('class2')).toEqual(true); + expect(body.classList.contains('class3')).toEqual(true); + ionicBody.enableClass(false, 'class1', 'class2', 'class3'); + expect(body.classList.contains('class1')).toEqual(false); + expect(body.classList.contains('class2')).toEqual(false); + expect(body.classList.contains('class3')).toEqual(false); + }); + + it('Should append a jqLite element to the body', function() { + var jqLiteElement = angular.element('
jqLite
'); + ionicBody.append(jqLiteElement); + expect(body.lastChild.outerHTML).toEqual('
jqLite
'); + }); + + it('Should append a DOM element to the body', function() { + var domElement = document.createElement('span'); + domElement.innerText = 'domElement' + ionicBody.append(domElement); + expect(body.lastChild.outerHTML).toEqual('domElement'); + }); + +});