Skip to content

Commit

Permalink
feat(splitView): expose side menu on large viewport
Browse files Browse the repository at this point in the history
Ability to keep a left menu exposed on larger viewports, such as a
landscape tablet. Added the `expose-aside-menu` attribute directive.
  • Loading branch information
adamdbradley committed Aug 26, 2014
1 parent 853fad1 commit b69aa54
Show file tree
Hide file tree
Showing 11 changed files with 216 additions and 47 deletions.
6 changes: 6 additions & 0 deletions config/docs/templates/api_menu_version.template.html
Original file line number Diff line number Diff line change
Expand Up @@ -469,6 +469,12 @@
</a>
</li>

<li>
<a href="{{ page.versionHref }}/api/directive/exposeAsideWhen/">
expose-aside-when
</a>
</li>

<li>
<a href="{{ page.versionHref }}/api/directive/menuToggle/">
menu-toggle
Expand Down
34 changes: 30 additions & 4 deletions js/angular/controller/sideMenuController.js
Original file line number Diff line number Diff line change
Expand Up @@ -4,10 +4,11 @@ IonicModule
'$attrs',
'$ionicSideMenuDelegate',
'$ionicPlatform',
function($scope, $attrs, $ionicSideMenuDelegate, $ionicPlatform) {
'$document',
function($scope, $attrs, $ionicSideMenuDelegate, $ionicPlatform, $document) {
var self = this;
var rightShowing, leftShowing, isDragging;
var startX, lastX, offsetX;
var startX, lastX, offsetX, isAsideExposed;

self.$scope = $scope;

Expand Down Expand Up @@ -132,9 +133,9 @@ function($scope, $attrs, $ionicSideMenuDelegate, $ionicPlatform) {
}

if(percentage !== 0) {
document.body.classList.add('menu-open');
$document[0].body.classList.add('menu-open');
} else {
document.body.classList.remove('menu-open');
$document[0].body.classList.remove('menu-open');
}
};

Expand Down Expand Up @@ -253,8 +254,32 @@ function($scope, $attrs, $ionicSideMenuDelegate, $ionicPlatform) {
}
};

self.isAsideExposed = function() {
return !!isAsideExposed;
};

self.exposeAside = function(shouldExposeAside) {
isAsideExposed = shouldExposeAside;

// set the left marget width if it should be exposed
// otherwise set false so there's no left margin
self.content.setMarginLeft( isAsideExposed ? self.left.width : 0 );

self.$scope.$emit('$ionicExposeAside', isAsideExposed);
};

self.activeAsideResizing = function(isResizing) {
if(isResizing) {
$document[0].body.classList.add('aside-resizing');
} else {
$document[0].body.classList.remove('aside-resizing');
}
};

// End a drag with the given event
self._endDrag = function(e) {
if(isAsideExposed) return;

if(isDragging) {
self.snapToRest(e);
}
Expand All @@ -265,6 +290,7 @@ function($scope, $attrs, $ionicSideMenuDelegate, $ionicPlatform) {

// Handle a drag event
self._handleDrag = function(e) {
if(isAsideExposed) return;

// If we don't have start coords, grab and store them
if(!startX) {
Expand Down
77 changes: 77 additions & 0 deletions js/angular/directive/exposeAsideWhen.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,77 @@
/**
* @ngdoc directive
* @name exposeAsideWhen
* @module ionic
* @restrict A
* @parent ionic.directive:ionSideMenus
*
* @description
* It is common for a tablet application to hide a menu when in portrait mode, but to show the
* same menu on the left side when the tablet is in landscape mode. The `exposeAsideWhen` attribute
* directive can be used to accomplish a similar interface.
*
* By default, side menus are hidden underneath its side menu content, and can be opened by either
* swiping the content left or right, or toggling a button to show the side menu. However, by adding the
* `exposeAsideWhen` attribute directive to an {@link ionic.directive:ionSideMenu} element directive,
* a side menu can be given instructions on "when" the menu should be exposed (always viewable). For
* example, the `expose-aside-when="large"` attribute will keep the side menu hidden when the viewport's
* width is less than `768px`, but when the viewport's width is `768px` or greater, the menu will then
* always be shown and can no longer be opened or closed like it could when it was hidden for smaller
* viewports.
*
* Using `large` as the attribute's value is a shortcut value to `(min-width:768px)` since it is
* the most common use-case. However, for added flexibility, any valid media query could be added
* as the value, such as `(min-width:600px)` or even multiple queries such as
* `(min-width:750px) and (max-width:1200px)`.
* @usage
* ```html
* <ion-side-menus>
* <!-- Center content -->
* <ion-side-menu-content>
* </ion-side-menu-content>
*
* <!-- Left menu -->
* <ion-side-menu expose-aside-when="large">
* </ion-side-menu>
* </ion-side-menus>
* ```
* For a complete side menu example, see the
* {@link ionic.directive:ionSideMenus} documentation.
*/
IonicModule
.directive('exposeAsideWhen', ['$window', function($window) {
return {
restrict: 'A',
require: '^ionSideMenus',
link: function($scope, $element, $attr, sideMenuCtrl) {

function checkAsideExpose() {
var mq = $attr.exposeAsideWhen == 'large' ? '(min-width:768px)' : $attr.exposeAsideWhen;
sideMenuCtrl.exposeAside( $window.matchMedia(mq).matches );
sideMenuCtrl.activeAsideResizing(false);
}

function onResize() {
sideMenuCtrl.activeAsideResizing(true);
debouncedCheck();
}

var debouncedCheck = ionic.debounce(function() {
$scope.$apply(function(){
checkAsideExpose();
});
}, 300, false);

checkAsideExpose();

ionic.on('resize', onResize, $window);

$scope.$on('$destroy', function(){
ionic.off('resize', onResize, $window);
});

}
};
}]);

26 changes: 21 additions & 5 deletions js/angular/directive/sideMenuContent.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,7 +30,8 @@ IonicModule
.directive('ionSideMenuContent', [
'$timeout',
'$ionicGesture',
function($timeout, $ionicGesture) {
'$window',
function($timeout, $ionicGesture, $window) {

return {
restrict: 'EA', //DEPRECATED 'A'
Expand Down Expand Up @@ -126,28 +127,43 @@ function($timeout, $ionicGesture) {
}
}

sideMenuCtrl.setContent({
var content = {
element: element[0],
onDrag: function(e) {},
endDrag: function(e) {},
getTranslateX: function() {
return $scope.sideMenuContentTranslateX || 0;
},
setTranslateX: ionic.animationFrameThrottle(function(amount) {
$element[0].style[ionic.CSS.TRANSFORM] = 'translate3d(' + amount + 'px, 0, 0)';
var xTransform = content.offsetX + amount;
$element[0].style[ionic.CSS.TRANSFORM] = 'translate3d(' + xTransform + 'px,0,0)';
$timeout(function() {
$scope.sideMenuContentTranslateX = amount;
});
}),
setMarginLeft: ionic.animationFrameThrottle(function(amount) {
if(amount) {
$element[0].style[ionic.CSS.TRANSFORM] = 'translate3d(' + amount + 'px,0,0)';
$element[0].style.width = ($window.innerWidth - amount) + 'px';
content.offsetX = amount;
} else {
$element[0].style[ionic.CSS.TRANSFORM] = 'translate3d(0,0,0)';
$element[0].style.width = '';
content.offsetX = 0;
}
}),
enableAnimation: function() {
$scope.animationEnabled = true;
$element[0].classList.add('menu-animated');
},
disableAnimation: function() {
$scope.animationEnabled = false;
$element[0].classList.remove('menu-animated');
}
});
},
offsetX: 0
};

sideMenuCtrl.setContent(content);

// add gesture handlers
var dragRightGesture = $ionicGesture.on('dragright', onDragX, $element);
Expand Down
30 changes: 27 additions & 3 deletions js/angular/directive/sideMenus.js
Original file line number Diff line number Diff line change
Expand Up @@ -17,13 +17,20 @@ IonicModule
* links and buttons within `ion-side-menu` content, so that when the element is
* clicked then the opened side menu will automatically close.
*
* By default, side menus are hidden underneath its side menu content, and can be opened by
* either swiping the content left or right, or toggling a button to show the side menu. However,
* by adding the {@link ionic.directive:exposeAsideWhen} attribute directive to an
* {@link ionic.directive:ionSideMenu} element directive, a side menu can be given instructions
* on "when" the menu should be exposed (always viewable).
*
* ![Side Menu](http://ionicframework.com.s3.amazonaws.com/docs/controllers/sidemenu.gif)
*
* For more information on side menus, check out:
*
* - {@link ionic.directive:ionSideMenuContent}
* - {@link ionic.directive:ionSideMenu}
* - {@link ionic.directive:menuClose}
* - {@link ionic.directive:exposeAsideWhen}
*
* @usage
* To use side menus, add an `<ion-side-menus>` parent element,
Expand Down Expand Up @@ -58,18 +65,35 @@ IonicModule
*
*/
.directive('ionSideMenus', ['$document', function($document) {

var ASIDE_OPEN_CSS = 'aside-open';

return {
restrict: 'ECA',
controller: '$ionicSideMenus',
compile: function(element, attr) {
attr.$set('class', (attr['class'] || '') + ' view');

return function($scope) {
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);
}
});

$scope.$on('$destroy', function(){
$document[0].body.classList.remove('menu-open');
bodyClassList.remove('menu-open');
bodyClassList.remove(ASIDE_OPEN_CSS);
});

};
}
}
};
}]);
4 changes: 4 additions & 0 deletions scss/_menu.scss
Original file line number Diff line number Diff line change
Expand Up @@ -55,6 +55,10 @@
right: 0;
}

.aside-open.aside-resizing .menu-right {
display: none;
}

.menu-animated {
@include transition-transform($menu-animation-speed ease);
}
29 changes: 0 additions & 29 deletions scss/_split-pane.scss

This file was deleted.

3 changes: 0 additions & 3 deletions scss/_variables.scss
Original file line number Diff line number Diff line change
Expand Up @@ -543,9 +543,6 @@ $menu-animation-speed: 200ms !default;

$menu-side-shadow: -1px 0px 2px rgba(0, 0, 0, 0.2), 1px 0px 2px rgba(0,0,0,0.2) !default;

$split-pane-menu-width: 320px !default;
$split-pane-menu-border-color: #eee !default;


// Modals
// -------------------------------
Expand Down
1 change: 0 additions & 1 deletion scss/ionic.scss
Original file line number Diff line number Diff line change
Expand Up @@ -27,7 +27,6 @@
"list",
"badge",
"slide-box",
"split-pane",

// Forms
"form",
Expand Down
4 changes: 2 additions & 2 deletions test/html/sideMenu.html
Original file line number Diff line number Diff line change
Expand Up @@ -15,7 +15,7 @@

<ion-side-menu-content edge-drag-threshold="true" drag-content="!$root.disableDrag">
<header class="bar bar-header bar-positive">
<button class="button button-icon ion-navicon" ng-click="toggleLeft()"></button>
<button class="button button-icon ion-navicon" ng-click="toggleLeft()" ng-hide="$exposeAside.active"></button>
<h1 class="title">Slide me</h1>
<button class="button button-icon ion-navicon" ng-click="toggleRight()"></button>
</header>
Expand All @@ -32,7 +32,7 @@ <h1>Content</h1>
</ion-content>
</ion-side-menu-content>

<ion-side-menu side="left" width="$root.menuWidth || 270" ng-controller="LeftCtrl">
<ion-side-menu side="left" width="$root.menuWidth || 275" ng-controller="LeftCtrl" expose-aside-when="(min-width:750px) and (max-width:1200px)">
<header class="bar bar-header bar-assertive">
<h1 class="title">Left</h1>
</header>
Expand Down
Loading

0 comments on commit b69aa54

Please sign in to comment.