Card Deck AngularJS

Fiddling with the ngAnimate service

by Osman Cea

HTML

<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.8/angular.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.8/angular-animate.js"></script>
<body ng-app="demoApp">
  <div ng-controller="DemoCtrl as ctrl">
    <div class="card-container">
      <card class="card move-to-front" 
        card-index="{{$index}}" 
        stack-size="{{ctrl.cards.length}}"
        ng-class="{ 'move-to-back': card.animating }"
        ng-repeat="card in ctrl.cards | orderBy:'position'">
        <h2>{{card.name}}</h2>
        <button ng-click="ctrl.dismiss(card)" ng-disabled="">clickme</button>
      </card>

    </div>
  </div>
</body>

SCSS

.card {
  border: 1px solid #ddd;
  height: 180px;
  width: 100%;
  background-color: #f0f0f0;
  display: flex;
  flex-direction: column;
  transform: translate3d(0, 0, 0);
  position: absolute;
  top: 0;
  transition: all .25s;
  
  h2 {
    margin: auto;
  }
  &-container {
    margin-top: 90px;
    width: 400px;
    position: relative;
  }
}

@keyframes sendBack {
  0%    { left: 0; }
  40%   { left: 400px; }
  100%  { left: 0; }
}

JavaScript

var app = angular.module('demoApp', ['ngAnimate']);
  
app
	.config(configuration)
  .controller('DemoCtrl', DemoCtrl)
  .directive('card', card)
  .animation('.move-to-back', moveToBack)
  .animation('.move-to-front', moveToFront);

configuration.$inject = ['$provide'];
DemoCtrl.$inject = ['$scope', '$timeout'];
card.$inject = ['$animateCss'];
moveToFront.$inject = ['$animateCss'];
moveToBack.$inject = ['$animateCss'];

function configuration($provide) {
  $provide.decorator('ngClickDirective',['$delegate','$timeout', function ($delegate,$timeout) {
    var original = $delegate[0].compile;
    var delay = 500;
    $delegate[0].compile = function (element, attrs, transclude) {
      var disabled = false;
      function onClick(evt) {
        if (disabled) {
          evt.preventDefault();
          evt.stopImmediatePropagation();
        } 
        else {
          disabled = true;
          $timeout(function () { disabled = false; }, delay, false);
        }
      }
      //   scope.$on('$destroy', function () { iElement.off('click', onClick); });
      element.on('click', onClick);
      return original(element, attrs, transclude);
    };
    return $delegate;
	}]);
}

function card($animateCss) {
	return {
  	restrict: 'E',
    scope: {
    	index: '@cardIndex',
      size: '@stackSize'
    },
    link: function(scope, element, attrs) {
      
      var zindex = scope.size - scope.index;
      console.log(zindex);
      
      element.css({
      	'z-index': zindex,
        'transform': 'translate3d('+ scope.index*10 +'px,-'+ scope.index*10 +'px,0)'
      });
    }
  }
}

function DemoCtrl($scope, $timeout) {

  this.cards = [{
    name: "1",
    position: 1,
    id: 1,
    animating: false
  }, {
    name: "2",
    position: 2,
    id: 2,
    animating: false
  }, {
    name: "3",
    position: 3,
    id: 3,
    animating: false
  }, {
    name: "4",
    position: 4,
    id: 4,
    animating: false
  }, {
    name: "5",
    position: 5,
    id: 5,
   ...