Skip to content

Commit

Permalink
feat(rxApp): Add in Collapsible Flag for rxApp
Browse files Browse the repository at this point in the history
  • Loading branch information
Stephen Golub committed Apr 16, 2014
1 parent a54206e commit 91d666d
Show file tree
Hide file tree
Showing 8 changed files with 251 additions and 10 deletions.
11 changes: 10 additions & 1 deletion src/rxApp/docs/rxApp.html
Expand Up @@ -13,6 +13,15 @@ <h3>Customized rxApp</h3>
<button ng-click="changeSubtitle()" class="changeSubtitle">Change Subtitle</button>
</rx-page>
</rx-app>

<h3>Collapsible rxApp</h3>
<rx-app collapsible-nav="true" id="collapsible-rxApp">
<rx-page>
<p>Click the toggle to hide the menu</p>
</rx-page>
</rx-app>


</div>

<!--
Expand All @@ -25,4 +34,4 @@ <h3>Customized rxApp</h3>
<rx-page title="'Example Page'">
Example content
</rx-page>
-->
-->
24 changes: 24 additions & 0 deletions src/rxApp/docs/rxApp.midway.js
Expand Up @@ -16,6 +16,30 @@ describe('rxApp', function () {
it('should show element', function () {
expect(rxApp.rootElement.isDisplayed()).to.eventually.eq.true;
});

describe('Collapsible Navigation', function () {
before(function () {
rxApp = rxAppPage.initialize(ptor.findElement(protractor.By.css('#collapsible-rxApp')));
});

it('should have a collapsible navigation menu', function () {
expect(rxApp.isCollapsible()).to.be.true;
});

it('should be expanded by default', function () {
expect(rxApp.isExpanded()).to.eventually.be.true;
});

it('should collapse the navigation', function () {
rxApp.collapse();
expect(rxApp.isCollapsed()).to.eventually.be.true;
});

it('should expand the navigation', function () {
rxApp.expand();
expect(rxApp.isExpanded()).to.eventually.be.true;
});
});
});

describe('rxPage', function () {
Expand Down
15 changes: 13 additions & 2 deletions src/rxApp/rxApp.js
Expand Up @@ -85,23 +85,34 @@ angular.module('encore.ui.rxApp', ['encore.ui.rxEnvironment', 'ngSanitize', 'ngR
*
* @param {string} [siteTitle] Title of site to use in upper right hand corner
* @param {object} [menu] Menu items used for left-hand navigation
* @param {string} [collapsibleNav] Set to 'true' if the navigation menu should be collapsible
* @param {string} [collapsedNav] Binding for the collapsed state of the menu.
*
* @example
* <pre>
* <rx-app site-title="Custom Title"></rx-app>
* </pre>
*/
.directive('rxApp', function (encoreNav) {
.directive('rxApp', function ($rootScope, encoreNav) {
return {
restrict: 'E',
transclude: true,
templateUrl: 'templates/rxApp.html',
scope: {
siteTitle: '@?',
menu: '=?'
menu: '=?',
collapsibleNav: '@',
collapsedNav: '=?',
},
link: function (scope) {
scope.menu = scope.menu || encoreNav;
if (!_.isBoolean(scope.collapsedNav)) {
scope.collapsedNav = false;
}

scope.collapseMenu = function () {
scope.collapsedNav = !scope.collapsedNav;
};
}
};
})
Expand Down
73 changes: 72 additions & 1 deletion src/rxApp/rxApp.less
Expand Up @@ -12,6 +12,35 @@
font-size: @appFontSize;
color: @appTextColor;

&.collapsible {
&.collapsed {
.rx-app-menu {
.flexbox(0 0 0px);
}

.collapsible-toggle {
top: -3px;
left: 4px;
}

.site-branding {
height: 15px;

.site-title, .site-options {
display: none;
}
}

.rx-app-nav {
display: none;
}

.rx-app-content .page-header {
margin-left: 25px;
}
}
}

.rx-app-menu {
color: #fff;
font-size: 15px;
Expand All @@ -23,6 +52,48 @@
input {
color: @inputColor;
}

.collapsible-toggle {
position: relative;
left: 13px;
width: 25px;
float: right;
background: none;
border: 0px;
cursor: pointer;
text-align: center;
padding: 2px;
}

.double-chevron {
width: 15px;
height: 10px;
margin: 0px 0px 2px 2px;
font-size: 20px;

&:hover {
&::before {
color: #FFF;
}
}

&::before {
color: #666;
display: block;
content: "\00bb";
position: relative;
top: -6px;
left: 1px;

}

&.double-chevron-left::before {
content: "\00ab";
top: -7px;
left: 0px;
}
}

}

.rx-app-content {
Expand Down Expand Up @@ -218,4 +289,4 @@
color: #aaa;
}
}
}
}
76 changes: 75 additions & 1 deletion src/rxApp/rxApp.page.js
Expand Up @@ -9,6 +9,80 @@ var rxApp = {
siteNav: {
get: function () { return this.rootElement.findElement(this.by.css('.rx-app-nav')); }
},

collapseToggleButton: {
get: function () { return this.rootElement.findElement(this.by.css('.collapsible-toggle')); }
},

toggleCollapse: {
value: function () {
if (!this.isCollapsible()) {
this.NotCollapsibleException.thro();
}

this.collapseToggleButton.click();
}
},

expand: {
value: function () {
var page = this;
return this.isCollapsed().then(function (collapsed) {
if (collapsed) {
page.toggleCollapse();
}
});
}
},

collapse: {
value: function () {
var page = this;
return this.isExpanded().then(function (expanded) {
if (expanded) {
page.toggleCollapse();
}
});
}
},

isCollapsed: {
value: function () {
if (!this.isCollapsible()) {
this.NotCollapsibleException.thro();
}

return this.rootElement.$('.rx-app').getAttribute('class').then(function (classNames) {
return (classNames.indexOf('collapsed') >= 0);
});
}
},

isExpanded: {
value: function () {
return this.isCollapsed().then(function (result) {
return !result;
});
}
},

isCollapsible: {
value: function () {
try {
this.collapseToggleButton.isDisplayed();
} catch (err) {
return false;
}

return true;
}
},

NotCollapsibleException: {
get: function () {
return this.exception('The navigation menu is not collapsible');
}
}
};

exports.rxApp = {
Expand Down Expand Up @@ -43,4 +117,4 @@ exports.rxPage = {

help: function () { return Object.keys(rxPage); }

};
};
52 changes: 50 additions & 2 deletions src/rxApp/rxApp.spec.js
@@ -1,8 +1,10 @@
/* jshint node: true */

describe('rxApp', function () {
var scope, compile, rootScope, el, elCustom, defaultNav;
var scope, compile, rootScope, el, elCustom, elCollapsible, elCollapsibleVar, defaultNav;
var standardTemplate = '<rx-app></rx-app>';
var collapsibleTemplate = '<rx-app collapsible-nav="true"></rx-app>';
var collapsibleExternalVarTemplate = '<rx-app collapsible-nav="true" collapsed-nav="collapsed"></rx-app>';
var customTemplate = '<rx-app site-title="My App" menu="customNav"></rx-app>';

var customNav = [{
Expand Down Expand Up @@ -32,12 +34,16 @@ describe('rxApp', function () {
scope = $rootScope.$new();
compile = $compile;
defaultNav = encoreNav;

scope.collapsed = false;
});

scope.customNav = customNav;

el = helpers.createDirective(standardTemplate, compile, scope);
elCustom = helpers.createDirective(customTemplate, compile, scope);
elCollapsible = helpers.createDirective(collapsibleTemplate, compile, scope);
elCollapsibleVar = helpers.createDirective(collapsibleExternalVarTemplate, compile, scope);
});

it('should have a default title', function () {
Expand Down Expand Up @@ -71,6 +77,48 @@ describe('rxApp', function () {
// validate it matches custom nav title
expect(navTitle.textContent).to.equal(customNav[0].title);
});

it('should not show the collapsible toggle if collapsible is not true', function () {
var collapsibleToggle = el[0].querySelector('.collapsible-toggle');

expect(collapsibleToggle).to.be.null;
});

it('should allow you to set the menu as collapsible', function () {
var collapsibleToggle = elCollapsible[0].querySelector('.collapsible-toggle');

expect(collapsibleToggle).to.be.ok;
});

it('should set the external collapsedNav value when you toggle the collapsed button', function () {
var elScope = elCollapsibleVar.isolateScope();

expect(scope.collapsed).to.be.not.ok;
elScope.collapseMenu();

// Have to run the digest cycle manually to get the var to propagate up
scope.$digest();
expect(scope.collapsed).to.be.ok;
});

it('should apply the classes to the menu for collapsible status', function () {
var collapsibleMenu = elCollapsible[0].querySelector('.collapsible');

expect(collapsibleMenu).to.be.not.null;
});

it('should apply the classes to the menu for collapsed status', function () {
var elScope = elCollapsible.isolateScope();
var collapsibleMenu = elCollapsible[0].querySelector('.collapsed');

expect(collapsibleMenu).to.be.null;
elScope.collapseMenu();

// We need to run the digest to update the classes
scope.$digest();
collapsibleMenu = elCollapsible[0].querySelector('.collapsed');
expect(collapsibleMenu).to.be.not.null;
});
});

describe('rxAppNav', function () {
Expand Down Expand Up @@ -359,4 +407,4 @@ describe('rxPage', function () {
expect(el).to.have.length.of.at.least(1);
expect(el.children()).to.have.length.of.at.least(1);
});
});
});
8 changes: 6 additions & 2 deletions src/rxApp/templates/rxApp.html
@@ -1,7 +1,11 @@
<div class="rx-app">
<div class="rx-app" ng-class="{collapsible: collapsibleNav === 'true', collapsed: collapsedNav}">
<nav class="rx-app-menu">
<header class="site-branding">
<h1 class="site-title">{{ siteTitle || 'Encore' }}</h1>
<button class="collapsible-toggle" ng-if="collapsibleNav === 'true'" ng-click="collapseMenu()">
<span class="visually-hidden">{{ (collapsedNav) ? 'Show' : 'Hide' }} Main Menu</span>
<div class="double-chevron" ng-class="{'double-chevron-left': !collapsedNav}"></div>
</button>
<div class="site-options">
<!-- <a href="settings" class="site-settings">Settings</a> -->
<a href="#" rx-logout class="site-logout">Logout</a>
Expand All @@ -15,4 +19,4 @@ <h2 class="nav-section-title">{{ section.title }}</h2>
</nav>
</nav>
<div class="rx-app-content" ng-transclude></div>
</div>
</div>
2 changes: 1 addition & 1 deletion src/rxApp/templates/rxAppNav.html
Expand Up @@ -2,4 +2,4 @@
<ul class="rx-app-nav-group">
<rx-app-nav-item ng-repeat="item in items"></rx-app-nav-item>
</ul>
</div>
</div>

0 comments on commit 91d666d

Please sign in to comment.