Skip to content

Commit

Permalink
feat: add DrawerLayout directive
Browse files Browse the repository at this point in the history
Closes #296
  • Loading branch information
adelyte-chris committed Feb 7, 2015
1 parent 8cffa42 commit 9ff8b1b
Show file tree
Hide file tree
Showing 4 changed files with 231 additions and 1 deletion.
2 changes: 1 addition & 1 deletion famous-angular-examples
117 changes: 117 additions & 0 deletions src/scripts/directives/fa-drawer-layout.js
@@ -0,0 +1,117 @@
/**
* @ngdoc directive
* @name faDrawerLayout
* @module famous.angular
* @restrict EA
* @description
* This directive will create a Famo.us DrawerLayout containing
* a Content and a Drawer based on the order of its child elements.
* See [https://famo.us/docs/views/DrawerLayout]
*
* @usage
* ```html
* <fa-drawer-layout>
* <!-- content rendernode -->
* <!-- drawer rendernode -->
* </fa-drawer-layout>
* ```
* @example
* `fa-drawer-layout` is a View that arranges two renderables into a drawer area with a defined size and a content area that fills up the remaining space.
*
* To use it, declare it in the html and nest 2 renderables.
*
*
*/

angular.module('famous.angular')
.directive('faDrawerLayout', ["$famous", "$famousDecorator", function ($famous, $famousDecorator) {
return {
template: '<div></div>',
restrict: 'E',
transclude: true,
scope: true,
compile: function (tElem, tAttrs) {
return {
pre: function (scope, element, attrs) {
var DrawerLayout = $famous["famous/views/DrawerLayout"];
var isolate = $famousDecorator.ensureIsolate(scope);

var options = scope.$eval(attrs.faOptions) || {};

if (options.drawerLength == null) {
options.drawerLength = scope.$eval(attrs.faDrawerLength);
}

if (options.side == null) {
options.side = scope.$eval(attrs.faSide);
}
switch (options.side) {
case 'left':
options.side = DrawerLayout.SIDES.LEFT;
break;
case 'top':
options.side = DrawerLayout.SIDES.TOP;
break;
case 'right':
options.side = DrawerLayout.SIDES.RIGHT;
break;
case 'bottom':
options.side = DrawerLayout.SIDES.BOTTOM;
break;
}

isolate.renderNode = new DrawerLayout(options);
$famousDecorator.addRole('renderable', isolate);
isolate.show();

isolate.toggle = function (overrideOptions) {
isolate.renderNode.toggle(overrideOptions || scope.$eval(attrs.faOptions));
};

isolate.open = function (overrideOptions) {
isolate.renderNode.open(overrideOptions || scope.$eval(attrs.faOptions));
};

isolate.close = function (overrideOptions) {
isolate.renderNode.close(overrideOptions || scope.$eval(attrs.faOptions));
};

var _numberOfChildren = 0;

$famousDecorator.sequenceWith(
scope,
function addChild(data) {
_numberOfChildren++;

if (_numberOfChildren === 1) {
isolate.renderNode.content.add(data.renderGate);
} else if (_numberOfChildren === 2){
isolate.renderNode.drawer.add(data.renderGate);
} else {
throw new Error('fa-drawer-layout can accept no more than 2 children');
}
},
function removeChild(childScopeId) {
if (_numberOfChildren === 1) {
isolate.renderNode.content.set({});
} else if (_numberOfChildren === 2) {
isolate.renderNode.drawer.set({});
}

_numberOfChildren--;
}
);
},
post: function (scope, element, attrs, ctrl, transclude) {
var isolate = $famousDecorator.ensureIsolate(scope);

transclude(scope, function (clone) {
element.find('div').append(clone);
});

$famousDecorator.registerChild(scope, element, isolate);
}
};
}
};
}]);
1 change: 1 addition & 0 deletions src/scripts/services/famous.js
Expand Up @@ -67,6 +67,7 @@ ngFameApp.provider('$famous', function() {
"famous/utilities/Timer": famous.utilities.Timer,
"famous/utilities/Utility": famous.utilities.Utility,
"famous/views/Deck": famous.views.Deck,
"famous/views/DrawerLayout": famous.views.DrawerLayout,
"famous/views/EdgeSwapper": famous.views.EdgeSwapper,
"famous/views/FlexibleLayout": famous.views.FlexibleLayout,
"famous/views/Flipper": famous.views.Flipper,
Expand Down
112 changes: 112 additions & 0 deletions test/directives/faDrawerLayoutSpec.js
@@ -0,0 +1,112 @@
'use strict';

describe('faDrawerLayout', function () {
var common, element, $compile, $scope, $famous, DrawerLayout, Surface, View;

beforeEach(module('famous.angular'));

beforeEach(inject(function(_$compile_, _$rootScope_, _$famous_) {
$compile = _$compile_;
$scope = _$rootScope_.$new();
$famous = _$famous_;

common = window.famousAngularCommon($scope, $compile);
DrawerLayout = $famous['famous/views/DrawerLayout'];
Surface = $famous['famous/core/Surface'];
View = $famous['famous/core/View'];
}));

it("should create an instance of Famo.us DrawerLayout", function () {
var faDrawerLayout = $compile('<fa-drawer-layout></fa-drawer-layout>')($scope);
var drawerLayout = common.getIsolateFromElement(faDrawerLayout).renderNode;

expect(typeof drawerLayout).toBe('object');
expect(drawerLayout instanceof DrawerLayout).toBe(true);
});

it("should set its children as the content and drawer properties of the DrawerLayout", function () {
var surfaceContent;
$scope.$on('registerChild', function(event, isolate) {
surfaceContent = angular.element(isolate.renderNode.content)[0];
});
var faDrawerLayout = $compile('<fa-drawer-layout><fa-surface></fa-surface><fa-view></fa-view></fa-drawer-layout>')($scope);
var drawerLayout = common.getIsolateFromElement(faDrawerLayout).renderNode;

expect(drawerLayout.content._child._object instanceof Surface).toBe(true);
expect(drawerLayout.drawer._child._object instanceof View).toBe(true);

});

it("should throw an exception if more than two child elements are added", function () {
expect(function () {
var faDrawerLayout = $compile('<fa-drawer-layout><fa-surface></fa-surface><fa-view></fa-view><fa-view></fa-view></fa-drawer-layout>')($scope);
}).toThrow();
});

describe("hide and show", function () {
it("hide and show properties on the DrawerLayout", function () {
var faDrawerLayout = $compile('<fa-drawer-layout><fa-surface></fa-surface><fa-view></fa-view></fa-drawer-layout>')($scope);
var scope = faDrawerLayout.scope();
var isolate = faDrawerLayout.scope().isolate[scope.$id];

expect(isolate.renderGate._object === isolate.renderNode).toEqual(true);
isolate.hide()
$scope.$apply();
expect(isolate.renderGate._object === isolate.emptyNode).toEqual(true);

isolate.show()
$scope.$apply();
expect(isolate.renderGate._object === isolate.renderNode).toEqual(true);
});
});

it("should unregister a child when it is destroyed", function () {
var faDrawerLayout = $compile('<fa-drawer-layout><fa-surface></fa-surface><fa-surface class="destroy-me"></fa-surface></fa-drawer-layout>')($scope);
var drawerLayout = common.getIsolateFromElement(faDrawerLayout).renderNode;
var children = common.getIsolateFromElement(faDrawerLayout).children;
var destroyMe = faDrawerLayout[0].querySelectorAll('.destroy-me');

expect(drawerLayout.drawer._child).not.toBe(null);
angular.element(destroyMe[0]).remove();
expect(drawerLayout.drawer._child).toBe(null);
});

describe('should accept attribute', function () {
it('fa-drawer-length - to set the size of the concealed drawer', function () {
var faDrawerLayout = $compile('<fa-drawer-layout fa-drawer-length="240"><fa-surface></fa-surface><fa-surface></fa-surface></fa-drawer-layout>')($scope);
var drawerLayout = common.getIsolateFromElement(faDrawerLayout).renderNode;

expect(drawerLayout.options.drawerLength).toEqual(240);
});

describe('fa-side - to set the position of the concealed drawer', function () {
it('\'left\' - aligns to the LEFT side', function () {
var faDrawerLayout = $compile('<fa-drawer-layout fa-side="\'left\'"><fa-surface></fa-surface><fa-surface></fa-surface></fa-drawer-layout>')($scope);
var drawerLayout = common.getIsolateFromElement(faDrawerLayout).renderNode;

expect(drawerLayout.options.side).toEqual(DrawerLayout.SIDES.LEFT);
});

it('\'top\' - aligns to the TOP side', function () {
var faDrawerLayout = $compile('<fa-drawer-layout fa-side="\'top\'"><fa-surface></fa-surface><fa-surface></fa-surface></fa-drawer-layout>')($scope);
var drawerLayout = common.getIsolateFromElement(faDrawerLayout).renderNode;

expect(drawerLayout.options.side).toEqual(DrawerLayout.SIDES.TOP);
});

it('\'right\' - aligns to the RIGHT side', function () {
var faDrawerLayout = $compile('<fa-drawer-layout fa-side="\'right\'"><fa-surface></fa-surface><fa-surface></fa-surface></fa-drawer-layout>')($scope);
var drawerLayout = common.getIsolateFromElement(faDrawerLayout).renderNode;

expect(drawerLayout.options.side).toEqual(DrawerLayout.SIDES.RIGHT);
});

it('\'bottom\' - aligns to the BOTTOM side', function () {
var faDrawerLayout = $compile('<fa-drawer-layout fa-side="\'bottom\'"><fa-surface></fa-surface><fa-surface></fa-surface></fa-drawer-layout>')($scope);
var drawerLayout = common.getIsolateFromElement(faDrawerLayout).renderNode;

expect(drawerLayout.options.side).toEqual(DrawerLayout.SIDES.BOTTOM);
});
});
});
});

0 comments on commit 9ff8b1b

Please sign in to comment.