Angular Carousel

by jorgeherrera

HTML

<script src="//ajax.googleapis.com/ajax/libs/angularjs/1.2.10/angular.min.js"></script>
<link rel="stylesheet" href="//netdna.bootstrapcdn.com/bootstrap/3.1.0/css/bootstrap.min.css">
<script src="//netdna.bootstrapcdn.com/bootstrap/3.1.0/js/bootstrap.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular-touch/1.7.5/angular-touch.min.js"></script>
<div data-carousel="" class="col-xs-12">
    <div class="row">
        <button class="btn btn-link" ng-click="scrollTo(prevSlide())">Previous</button>
        <button class="btn btn-link" ng-click="scrollTo(nextSlide())">Next</button>
    </div>
    <div class="carousel slide multi-item-carousel">
          <ul ng-swipe-left="scrollTo(nextSlide())" ng-swipe-right="scrollTo(prevSlide())" class="carousel-inner">
        <li data-carousel-slide="first">
            <div class="item active">
               <div class="">
                  <div class="col-xs-4">
                    <a href="#" class="thumbnail">
                        <img src="http://placehold.it/200/f44336/000000" />
                    </a>
                </div>
               </div>
                <div class="item">
                  <div class="col-xs-4">
                    <a href="#" class="thumbnail">
                        <img src="http://placehold.it/200/f44336/0000001" />
                    </a>
                </div>
                </div>
                <div class="item">
                  <div class="col-xs-4">
                    <a href="#" class="thumbnail">
                        <img src="http://placehold.it/200/f44336/000000" />
                    </a>
                </div>
                </div>
            </div>

        </li>
        <li data-carousel-slide="second">
            <div class="">
               <div class="item">
                  <div class="col-xs-4">
                    <a href="#" class="thumbnail">
                        <img src="http://placehold.it/200/f44336/000000" />
         ...

SCSS

[data-carousel] {  
    position: relative;
    overflow: hidden;
    border: 1px solid black;
    
    ul {
        width: 766px;
        padding: 0;
        list-style: none;
        list-style-type: none;

        li {
            float: left;
            padding-right: 4rem;
                    overflow: hidden;
        }
    }
}

JavaScript

var m = angular.module('m', ['ngTouch']);

m.directive('carousel', function () {
    return {
        restrict: 'A',
        controller: function($scope, $element, $attrs, $transclude) {
            var listElem = $element.find('ul'),
                slidesTotalWidth = listElem.width();
            
            $scope.slides = {};
            
            this.registerSlide = function(id, element) {
                if (angular.isUndefined($scope.currentSlide)) {
                    $scope.currentSlide = id;
                }
                $scope.slides[id] = element;
                slidesTotalWidth += element.width();
                listElem.width(slidesTotalWidth);
            }
            
            $scope.scrollTo = function(slideId) {
                if (angular.isDefined(slideId)) {
                    var slideElem = $scope.slides[slideId],
                        leftMarginOffset = '-' + (slideElem.offset().left - slideElem.parent().offset().left) + 'px'; 
                    listElem.animate({
                        marginLeft: leftMarginOffset
                    });
                    $scope.currentSlide = slideId;
                }
            };
            
            $scope.prevSlide = function() {
                var keys = Object.keys($scope.slides),
                    currentIndex = keys.indexOf($scope.currentSlide);
                return keys[currentIndex - 1];
            }
            
            $scope.nextSlide = function() {
                var keys = Object.keys($scope.slides),
                    currentIndex = keys.indexOf($scope.currentSlide);
                return keys[currentIndex + 1];
            }
        }
    };
});

m.directive('carouselSlide', function () {
    return {
        restrict: 'A',
        require: '^carousel',
        scope: {
            slideId: '@carouselSlide'
        },
        link: function(scope, iElement, iAttrs, controller) {
            controller.registerSlide(scope.slideId, iElement);
    ...