cssAudio - Activefile-genericCSS - ActiveGeneric - ActiveHTML - ActiveImage - ActiveJS - ActiveSVG - ActiveText - Activefile-genericVideo - Activehtmlicon-personicon-teamoctocatspinnerstartv

Pen Settings

CSS Base

Vendor Prefixing

Add External CSS

These stylesheets will be added in this order and before the code you write in the CSS editor. You can also add another Pen here, and it will pull the CSS from it. Try typing "font" or "ribbon" below.

Quick-add: + add another resource

Add External JavaScript

These scripts will run in this order and before the code in the JavaScript editor. You can also link to another Pen here, and it will run the JavaScript from it. Also try typing the name of any popular library.

Quick-add: + add another resource

Code Indentation

     

Save Automatically?

If active, Pens will autosave every 30 seconds after being saved once.

Auto-Updating Preview

If enabled, the preview panel updates automatically as you code. If disabled, use the "Run" button to update.

            
              a,abbr,address,area,article,aside,audio,b,base,bdi,bdo,blockquote,body,br,button,canvas,caption,cite,code,col,colgroup,command,datalist,dd,del,details,dfn,dir,div,dl,dt,em,embed,fieldset,figcaption,figure,font,footer,form,frame,frameset,head,header,hgroup,hr,html,i,iframe,img,input
,ins,kbd,keygen,label,legend,li,link,map,mark,menu,meta,meter,nav,noframes,noscript,object,ol,optgroup,option,output,p,param,pre,progress,q,rp,rt,ruby,s,samp,script,section,select,small,source,span,strong,style,sub,summary,sup,table,tbody,td,textarea,tfoot,th,thead,time,title,tr
,track,tt,u,ul,var,video,wbr {
    border: 0;
    border-image-width: 0;
    -webkit-box-sizing: border-box;
    -moz-box-sizing: border-box;
    box-sizing: border-box;
    margin: 0;
    outline: 0;
    padding: 0;
}

body {
    padding: 40px;
}

button,
button i {
    cursor: pointer; 
    -moz-user-select: none;
    -ms-user-select: none;
    -webkit-user-select: none;
    user-select: none;
}

.carousel {
    background-color: rgb(50, 50 , 50);
    color: rgb(255, 255, 255);
    height: 100px;
    margin: 50px auto 50px auto;
    overflow: hidden;
    position: relative;
    width: 1000px;
}

.carousel button {
    background-color: transparent;
    border: 0;
    border-image-width: 0;
    outline: 0;
    cursor: pointer;
    -moz-user-select: none;
    -ms-user-select: none;
    -webkit-user-select: none;
    user-select: none;
    z-index: 1;
}

.carousel button.previous {
    left: 20px;
}

.carousel button.next {
    right: 20px;
}

.carousel button.previous,
.carousel button.next {
    bottom: 0;
    color: rgba(255, 255, 255, 0.6);
    position: absolute;
    top: 0;
}

.carousel button.previous i,
.carousel button.next i {
    font-family: 'FontAwesome';
    font-size: 36px;
    font-style: normal;
    text-rendering: auto;
}

.carousel .pager {
    bottom: 20px;
    left: 0;
    position: absolute;
    right: 0;
    text-align: center;
}

.carousel .pager button.item {
    color: rgb(255, 255, 255);
    display: inline-block;
    float: none;
    margin-right: 10px;
    padding: 4px;
}

.carousel .pager button.item i {
    font-family: 'FontAwesome';
    font-size: 14px;
    font-style: normal;
    text-rendering: auto;
}

.carousel .slide {
    float: left;
    height: 100%;
    margin: 0;
    padding: 0;
    width: 1000px;
}

.carousel .slides {
    bottom: 0;
    clear: both;
    height: 100%;
    margin: 0;
    overflow: hidden;
    padding: 0;
    position: absolute;
    top: 0;
}
            
          
!
            
              namespace poc {
    'use strict';
    angular.module('poc', ['ngAnimate']);
  
    const _defaultAnimiationDuration = 1000;
    const _slideWidth = 1000;

    angular.module('poc').directive('carousel', ['$animate', '$timeout', ($animate, $timeout) => new CarouselDirective($animate, $timeout)]);

    class CarouselDirective implements ng.IDirective {
        public link: ($scope: ICarouselScope, $element: ng.IAugmentedJQuery, attrs: ng.IAttributes) => void;
        public restrict = 'EA';
        public scope = {
            options: '=?carousel'
        };
        public template = `
<div class="carousel">
    <button type="button" class="previous" ng-click="slideAnimationInProgress || onPreviousClick()">
        <i class="fa-angle-left"></i>
    </button>
    <div class="slides"
         ng-style="{ width: slidesWidth }">
        <div class="slide"
             ng-repeat="slide in slides track by $index"
             ng-style="{ background: slide.background }"></div>
    </div>
    <div class="pager">
        <button type="button"
                class="item"
                title="item.title"
                ng-click="slideAnimationInProgress || onPagerItemClick($index)"
                ng-repeat="item in options.items">
            <i ng-class="{'fa-circle': $index === currentPagerItemIndex, 'fa-circle-o': $index !== currentPagerItemIndex}"></i>
        </button>
    </div>
    <button type="button" class="next" ng-click="slideAnimationInProgress || onNextClick()">
        <i class="fa-angle-right"></i>
    </button>
</div>
        `;

        constructor(public $animate: ng.animate.IAnimateService, public $timeout: ng.ITimeoutService) {
            const self: CarouselDirective = this;

            self.link = self.unboundLink.bind(self);
        }

        unboundLink($scope: ICarouselScope, $element: ng.IAugmentedJQuery, attrs: ng.IAttributes) {
            const self: CarouselDirective = this;
            const slidesJqueryElement = $element.find('.slides').first();

            $scope.onNextClick = onNextClick;
            $scope.onPagerItemClick = onPagerItemClick;
            $scope.onPreviousClick = onPreviousClick;

            if (!$scope.options) {
                $scope.options = getStubOptions();
            }
            createSlides();
            moveToSecondSlide(false);

            function createSlides() {
                const items = $scope.options.items;
                const slides: Array<ICarouselItem> = [];
                const totalItemCount = items.length;

                // Create a "clone"" of the last slide and use it, as first slide, to prevent flikkering, when cycling the carousel. 
                slides.unshift(items[totalItemCount - 1]);
                for(let i = 0, length = totalItemCount; i < length; i++) {
                    slides.push(items[i]);
                }
                // Create a "clone" of the first slide and use it, as last slide, to prevent flikkering, when cycling the carousel.
                slides.push(items[0]);
                $scope.slidesWidth = `${slides.length * _slideWidth}px`;
                $scope.slides = slides;
            }

            function move(direction: Direction) {
                const total = $scope.slides.length;
                const incrementor = (direction === Direction.forward) ? 1 : -1;

                const firstPagerItemIndex = (direction === Direction.forward) ? 0 : total - 3;
                const lastPagerItemIndex = (direction === Direction.forward) ? total - 3 : 0;
                setPagerItemIndex(firstPagerItemIndex, lastPagerItemIndex, incrementor);

                const firstSlideIndex = (direction === Direction.forward) ? 0 : total - 1;
                const lastSlideIndex = (direction === Direction.forward) ? total - 1 : 0;
                setSlideIndexAndMove(firstSlideIndex, lastSlideIndex, incrementor);
            }

            function moveSlide(offset: number, duration?: number, cb?: Function) {
                const useAnimation = duration !== 0;
                duration = duration || _defaultAnimiationDuration;
                cb = cb || onSlideAnimationEnd;

                if(useAnimation) {
                    $scope.slideAnimationInProgress = true;
                    slidesJqueryElement.animate({ left: `${offset}px` }, duration,'swing', cb);
                } else {
                    slidesJqueryElement.css("left", `${offset}px`);
                }
            }

            function moveToSecondSlide(useAnimation: boolean) {
                const duration = useAnimation ? _defaultAnimiationDuration : 0;
                const total = $scope.slides.length;
                moveSlide(0 - (1  * _slideWidth), duration);
                $scope.currentPagerItemIndex = 0;
                $scope.currentSlideIndex = 1;
            }
            
            function onNextClick() {
                move(Direction.forward);
            }

            function onPagerItemClick(index: number) {
                $scope.currentPagerItemIndex = index;
                $scope.currentSlideIndex = index + 1;
                moveSlide(0 - ($scope.currentSlideIndex * _slideWidth));
            }

            function onPreviousClick() {
                move(Direction.backward);
            }

            function onSlideAnimationEnd() {
                $scope.slideAnimationInProgress = false;
            }
            
            function setPagerItemIndex(first: number, last: number, incrementor: number) {
                if($scope.currentPagerItemIndex === last) {
                    $scope.currentPagerItemIndex = first;
                } else {
                    $scope.currentPagerItemIndex = $scope.currentPagerItemIndex + incrementor;
                }
            }

            function setSlideIndexAndMove(first: number, last: number, incrementor: number) {
                if($scope.currentSlideIndex === last) {
                    $scope.currentSlideIndex = first + incrementor;
                    moveSlide(0 - ($scope.currentSlideIndex * _slideWidth), 0);
                    $scope.currentSlideIndex = $scope.currentSlideIndex  + incrementor;
                    moveSlide(0 - ($scope.currentSlideIndex * _slideWidth));
                } else {
                    $scope.currentSlideIndex = $scope.currentSlideIndex + incrementor;
                    moveSlide(0 - ($scope.currentSlideIndex * _slideWidth));
                }
            }
        }
    }

    enum Direction {
        backward = 0,
        forward = 1
    }

    interface ICarouselScope extends ng.IScope {
        currentPagerItemIndex: number;
        currentSlideIndex: number;
        onNextClick: () => void;
        onPagerItemClick: (index: number) => void;
        onPreviousClick: () => void;
        options: ICarouselOptions;
        slides: Array<ICarouselItem>;
        slideAnimationInProgress: boolean;
        slidesWidth: string;
    }

    interface ICarouselOptions {
        items: Array<ICarouselItem>;
    }

    interface ICarouselItem {
        background: string;
        title: string;
    }

    function getStubOptions(): ICarouselOptions {
        const items = [
                { title: 'title 1', background: 'url(https://raw.githubusercontent.com/roelvanlisdonk/dev/master/ng1/poc/carousel/img1_small.png)' },
                { title: 'title 2', background: 'url(https://raw.githubusercontent.com/roelvanlisdonk/dev/master/ng1/poc/carousel/img2_small.png)' },
                { title: 'title 3', background: 'url(https://raw.githubusercontent.com/roelvanlisdonk/dev/master/ng1/poc/carousel/img3_small.png)' }
            ];

        const options: ICarouselOptions = {
            items: items
        }
        return options;
    } 
  
  
  angular.bootstrap(document, ['poc']);
}
            
          
!
999px
Close

Asset uploading is a PRO feature.

As a PRO member, you can drag-and-drop upload files here to use as resources. Images, Libraries, JSON data... anything you want. You can even edit them anytime, like any other code on CodePen.

Go PRO

Loading ..................

Console