circular carousel

by alimills

HTML

<script src="http://code.angularjs.org/1.0.0rc6/angular-1.0.0rc6.js"></script>
<div ng-app="foo" ng-controller="FooCtrl">

  <script type="text/ng-template"  id="carouselView.html">
    <div class="carousel">
      <a ng-click="goBack()" class="back">back</a>
      <div ng-repeat="item in displayableItems" class="items item-{{$index}}">{{$index}}. {{item}}</div>
      <a ng-click="goNext()" class="next">next</a>
    </div>
  </script>

  <carousel model="foobarModel" itemsToShow="3"></carousel>

</div>

CSS

.carousel {
  padding: 10px;
  position: relative;
}

.carousel .back {
  position: absolute;
  left: 0px;
}

.carousel .next {
  position: absolute;
  left: 240px;
}

.carousel .items {
  position: absolute;
  width: 60px;
}

.item-0 {
  -webkit-transform: translateX(40px);
}

.item-1 {
  -webkit-transform: translateX(100px);
}

.item-2 {
  -webkit-transform: translateX(160px);
}

.item-3 {
}

.item-4 {
}

JavaScript

var foo = angular.module("foo", []);


foo.directive("carousel", function() {
    return {
        restrict: 'E',
        scope: true,
        templateUrl: "carouselView.html",
        controller: CarouselCtrl
    };
});


CarouselCtrl = function($scope, $attrs) {
  this.items = [];
  this.currentIndex = 0;
  this.itemsToShow = 0;

  var self = this;
    
  $scope.$watch($attrs.model, function(value) {
    if (value) {
      self.items = value;
      if (self.itemsToShow > 0) {
        self.updateDisplayableItems();
      }
    }
  });

  $scope.$watch($attrs.itemstoshow, function(value) {
    if (value) {
      self.itemsToShow = value;
      if (self.items.length > 0) {
        self.updateDisplayableItems();
      }
    }
  });

  $scope.goBack = function() {
    self.currentIndex--;
    self.updateDisplayableItems();
  };

  $scope.goNext = function() {
    self.currentIndex++;
    self.updateDisplayableItems();
  };
    
  this.updateDisplayableItems = function() {
    var startIndex = this.currentIndex % this.items.length;
    if (startIndex < 0) {
      startIndex = this.items.length + startIndex;
    }
      
    var endIndex = startIndex + this.itemsToShow;
    if (endIndex > this.items.length) {
      var offIndex = endIndex - this.items.length;
      endIndex = this.items.length;
      $scope.displayableItems = this.items.slice(startIndex, endIndex).concat(this.items.slice(0, offIndex));
    } else {
      $scope.displayableItems = this.items.slice(startIndex, endIndex);
    }
  };    
};


FooCtrl = function($scope) {
  $scope.foobarModel = ['frog','cat','car','dog','bike','fish'];
};