diff --git a/src/scripts/directives/fa-deck.js b/src/scripts/directives/fa-deck.js
new file mode 100644
index 00000000..41bd8c4e
--- /dev/null
+++ b/src/scripts/directives/fa-deck.js
@@ -0,0 +1,164 @@
+/**
+ * @ngdoc directive
+ * @name faDeck
+ * @module famous.angular
+ * @restrict EA
+ * @description
+ * This directive will create a Famo.us Deck containing the
+ * specified child elements. The provided `options` object
+ * will pass directly through to the Famo.us faDeck's
+ * constructor. See [https://famo.us/docs/views/Deck]
+ *
+ * @usage
+ * ```html
+ *
+ *
+ *
+ * ```
+ * @example
+ * `Fa-deck` is a Famous SequentialLayout View that can be opened and closed with a transition. Pass options (such as `direction` and `transition`) by binding an object with the property to `fa-options`.
+ *
+ * In the example below, an `fa-surface` and an `fa-view` are added to the deck. ng-repeat is used on an `fa-view` and the elements nested below it. The size of each `fa-surface` is `[250, 50]`.
+ *
+ * The modifier applied to the `fa-deck` positions it 0.5 across in the X direction and 0.25 down in the Y direction.
+ *
+ * A clickHandler() is bound to ng-click on the first surface, which toggles the `fa-deck` open and close actions.
+ *
+
+
+
+
+
+
+ Click Me
+
+
+
+ {{ $index }}
+
+
+
+
+
+
+
+
+
+ fa-app {
+ position: fixed;
+ top: 0;
+ right: 0;
+ bottom: 0;
+ left: 0;
+ }
+
+
+ */
+
+angular.module('famous.angular')
+ .directive('faDeck', ["$famous", "$famousDecorator", function ($famous, $famousDecorator) {
+ return {
+ template: '
',
+ restrict: 'E',
+ transclude: true,
+ scope: true,
+ compile: function (tElem, tAttrs, transclude) {
+ window.$f = $famous;
+ return {
+ pre: function (scope, element, attrs) {
+ var isolate = $famousDecorator.ensureIsolate(scope);
+
+ var Deck = $famous["famous/views/Deck"];
+
+ var _children = [];
+
+ var options = scope.$eval(attrs.faOptions) || {};
+
+ isolate.renderNode = new Deck(options);
+
+ $famousDecorator.addRole('renderable',isolate);
+ isolate.show();
+
+ var _updateDeck = function() {
+ _children.sort(function(a, b) {
+ return a.index - b.index;
+ });
+ isolate.renderNode.sequenceFrom(function(_children) {
+ var _ch = [];
+ angular.forEach(_children, function(c, i) {
+ _ch[i] = c.renderGate;
+ });
+ return _ch;
+ }(_children));
+ };
+
+ $famousDecorator.sequenceWith(
+ scope,
+ function(data) {
+ _children.push(data);
+ _updateDeck();
+ },
+ function(childScopeId) {
+ _children = function (_children) {
+ var _ch = [];
+ angular.forEach(_children, function (c) {
+ if (c.id !== childScopeId) {
+ _ch.push(c);
+ }
+ });
+ return _ch;
+ }(_children);
+ _updateDeck();
+ }
+ );
+
+ },
+ post: function (scope, element, attrs) {
+ var isolate = $famousDecorator.ensureIsolate(scope);
+ var deckOpen = scope.$eval(attrs.faOpen);
+
+ scope.$watch(function(){
+ return scope.$eval(attrs.faOpen);
+ }, function () {
+ deckOpen = scope.$eval(attrs.faOpen);
+ (scope.$eval(deckOpen)
+ || attrs.faOpen == "true"
+ || deckOpen === true
+ || scope[attrs.faOpen] === true) ? isolate.renderNode.open() : isolate.renderNode.close();
+ });
+
+ transclude(scope, function (clone) {
+ element.find('div').append(clone);
+ });
+
+ $famousDecorator.registerChild(scope, element, isolate);
+ }
+ };
+ }
+ };
+ }]);
diff --git a/test/directives/faDeckSpec.js b/test/directives/faDeckSpec.js
new file mode 100644
index 00000000..bfdf0c36
--- /dev/null
+++ b/test/directives/faDeckSpec.js
@@ -0,0 +1,279 @@
+'use strict';
+
+describe('faDeck', function() {
+ var eventHandler, common, $compile, $timeout, $scope, $famous;
+
+ beforeEach(module('famous.angular'));
+
+ beforeEach(inject(function(_$compile_, _$timeout_, _$rootScope_, _$famous_) {
+ $compile = _$compile_;
+ $timeout = _$timeout_;
+ $scope = _$rootScope_.$new();
+ $famous = _$famous_;
+
+ eventHandler = new $famous['famous/core/EventHandler']();
+
+ common = window.famousAngularCommon($scope, $compile);
+ }));
+
+
+ it('should work with ng-repeated views', function() {
+ var app = common.createApp(
+ '' +
+ '' +
+ '' +
+ '' +
+ ''
+ );
+
+ $scope.eventHandler = eventHandler;
+ $scope.views = [0, 1];
+ $scope.$apply();
+
+ var deck = $famous.find('fa-deck')[0].renderNode;
+
+ expect(deck._items).not.toBeNull();
+
+ common.destroyApp(app);
+ });
+
+ it('should allow specification of a start index with fa-start-index', function() {
+ //not yet implemented in lib
+ pending();
+
+ var app = common.createApp(
+ '' +
+ '' +
+ '' +
+ '' +
+ ''
+ );
+
+ $scope.eventHandler = eventHandler;
+ $scope.views = [0, 1];
+ $scope.$apply();
+
+ var deck = $famous.find('fa-deck')[0].renderNode;
+ expect(deck._items.getIndex()).toBe(1);
+ common.destroyApp(app);
+ });
+
+ it('should unregister children when their scopes are destroyed', function() {
+ var app = common.createApp(
+ '' +
+ '' +
+ '' +
+ '' +
+ ''
+ );
+
+ $scope.eventHandler = eventHandler;
+ $scope.views = [0, 1, 2];
+ $scope.$apply();
+
+
+ var deck = $famous.find('fa-deck')[0].renderNode;
+
+ expect(deck._items._.array.length).toBe(3);
+
+ // Pop out the current index
+ $scope.views.splice(1, 1);
+ $scope.$apply();
+
+ expect(deck._items._.array.length).toBe(2);
+
+ common.destroyApp(app);
+ });
+ describe("hide and show", function() {
+
+ it("hide and show properties on the Deck", function() {
+ var deck = $compile(
+ '' +
+ '' +
+ '' +
+ '' +
+ ''
+ )($scope);
+ $scope.eventHandler = eventHandler;
+ $scope.views = [0, 1, 2];
+ $scope.$apply();
+
+ var scope = deck.scope();
+ var isolate = 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);
+ });
+ });
+
+ describe("open and close Deck", function(){
+
+ describe("open", function(){
+ it("using a direct value - fa-open=\"true\"", function() {
+ var app = common.createApp(
+ '' +
+ '' +
+ '' +
+ '' +
+ ''
+ );
+ $scope.views = [0, 1, 2];
+ $scope.$apply();
+
+ var deck = $famous.find('fa-deck')[0].renderNode;
+
+ expect(deck.isOpen()).toEqual(true);
+
+ common.destroyApp(app);
+ });
+
+ it("using the return value of a function - fa-open=\"open()\"", function() {
+ var app = common.createApp(
+ '' +
+ '' +
+ '' +
+ '' +
+ ''
+ );
+ $scope.views = [0, 1, 2];
+ $scope.open = function(){
+ return true;
+ }
+ $scope.$apply();
+
+ var deck = $famous.find('fa-deck')[0].renderNode;
+
+ expect(deck.isOpen()).toEqual(true);
+
+ common.destroyApp(app);
+ });
+
+ it("using a function name - fa-open=\"openFunc\"", function() {
+ var app = common.createApp(
+ '' +
+ '' +
+ '' +
+ '' +
+ ''
+ );
+ $scope.views = [0, 1, 2];
+ $scope.openFunc = function(){
+ return true;
+ }
+ $scope.$apply();
+
+ var deck = $famous.find('fa-deck')[0].renderNode;
+
+ expect(deck.isOpen()).toEqual(true);
+
+ common.destroyApp(app);
+ });
+
+ it("using a $scope variable - fa-open=\"openVal\"", function() {
+ var app = common.createApp(
+ '' +
+ '' +
+ '' +
+ '' +
+ ''
+ );
+ $scope.views = [0, 1, 2];
+ $scope.openVal = true;
+ $scope.$apply();
+
+ var deck = $famous.find('fa-deck')[0].renderNode;
+
+ expect(deck.isOpen()).toEqual(true);
+
+ common.destroyApp(app);
+ });
+ });
+
+ describe("close", function(){
+ it("using a direct value - fa-open=\"false\"", function() {
+ var app = common.createApp(
+ '' +
+ '' +
+ '' +
+ '' +
+ ''
+ );
+ $scope.views = [0, 1, 2];
+ $scope.$apply();
+
+ var deck = $famous.find('fa-deck')[0].renderNode;
+
+ expect(deck.isOpen()).toEqual(false);
+
+ common.destroyApp(app);
+ });
+
+ it("using the return value of a function - fa-open=\"open()\"", function() {
+ var app = common.createApp(
+ '' +
+ '' +
+ '' +
+ '' +
+ ''
+ );
+ $scope.views = [0, 1, 2];
+ $scope.open = function(){
+ return false;
+ }
+ $scope.$apply();
+
+ var deck = $famous.find('fa-deck')[0].renderNode;
+
+ expect(deck.isOpen()).toEqual(false);
+
+ common.destroyApp(app);
+ });
+
+ it("using a function name - fa-open=\"openFunc\"", function() {
+ var app = common.createApp(
+ '' +
+ '' +
+ '' +
+ '' +
+ ''
+ );
+ $scope.views = [0, 1, 2];
+ $scope.openFunc = function(){
+ return false;
+ }
+ $scope.$apply();
+
+ var deck = $famous.find('fa-deck')[0].renderNode;
+
+ expect(deck.isOpen()).toEqual(false);
+
+ common.destroyApp(app);
+ });
+
+ it("using a $scope variable - fa-open=\"openVal\"", function() {
+ var app = common.createApp(
+ '' +
+ '' +
+ '' +
+ '' +
+ ''
+ );
+ $scope.views = [0, 1, 2];
+ $scope.openVal = false;
+ $scope.$apply();
+
+ var deck = $famous.find('fa-deck')[0].renderNode;
+
+ expect(deck.isOpen()).toEqual(false);
+
+ common.destroyApp(app);
+ });
+ });
+ });
+});