cssAudio - Activefile-genericCSS - ActiveGeneric - ActiveHTML - ActiveImage - ActiveJS - ActiveSVG - ActiveText - Activefile-genericVideo - ActiveLovehtmlicon-new-collectionicon-personicon-teamlog-outoctocatpop-outspinnerstartv

Pen Settings

CSS Base

Vendor Prefixing

Add External Stylesheets/Pens

Any URL's added here will be added as <link>s in order, and before the CSS in the editor. If you link to another Pen, it will include the CSS from that Pen. If the preprocessor matches, it will attempt to combine them before processing.

+ add another resource

You're using npm packages, so we've auto-selected Babel for you here, which we require to process imports and make it all work. If you need to use a different JavaScript preprocessor, remove the packages in the npm tab.

Add External Scripts/Pens

Any URL's added here will be added as <script>s in order, and run before the JavaScript in the editor. You can use the URL of any other Pen and it will include the JavaScript from that Pen.

+ add another resource

Use npm Packages

We can make npm packages available for you to use in your JavaScript. We use webpack to prepare them and make them available to import. We'll also process your JavaScript with Babel.

⚠️ This feature can only be used by logged in users.

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.

            
              <nav class="navbar navbar-inverse">
  <div class="container-fluid">
    <div class="navbar-header">
      <a class="navbar-brand" href="#">
        otto.slider
      </a>
    </div>
  </div>
</nav>
<div id="otto-slider-container"></div>
<div class="container">
  <div class="row">
    <div class="col-md-6">
      <h2>otto.slider</h2>
      <p>jQuery responsive slideshow with endless animation.</p>
      <p>This example uses bootstrap and FA, not mandatory.</p>
      <p>Options:</p>
      <ul>
        <li>autostart</li>
        <li>auto interval</li>
        <li>read_all_text</li>
      </ul>
    </div>
    <div class="col-md-6">
      <h2>Usage</h2>
      <p>Check the js code after "USAGE".</p>
      <p>Create items setting image, title, text, url.</p>
      <p>
        <a href="http://www.abidibo.net" target="_blank">
          <img alt="abidibo" src="http://www.abidibo.net/static/abidibo_net/img/abidibo_30px.png">
        </a>
        <a href="http://www.otto.to.it" target="_blank">
          <img src="https://avatars2.githubusercontent.com/u/1119279?v=3&s=200" style="height: 40px" />
        </a>
      </p>
    </div>
  </div>
</div>
            
          
!
            
              /** main */
body {
  background: #000;
}
.container {
  background: #222;
  color: #fff;
}
h2 {
  color: #ff6600;
}
/** navbar */
.navbar {
    border-radius: 0;
    margin-bottom: 0;
}

/** otto.slider */
.os-rail {
    position: relative;
}
.os-arrow {
    position: absolute;
    top: 50%;
    margin-top: -20px;
    font-size: 60px;
    color: #000;
    text-shadow: 0px 0px 1px #fff;
}
.os-arrow:hover {
    text-decoration: none;
    cursor: pointer;
    display: inline-block;
}
.os-slide {
    display: inline-block;
    position: relative;
    margin: 0;
    padding: 0;
}
.os-slide .caption {
    position: absolute;
    display: none;
    top: 20px;
    left: 20px;
    width: 400px;
    max-width: 80%;
}
.os-slide.os-active .caption {
    display: block;
}
.os-slide h1 span {
    background: #fff;
    display: inline-block;
    padding: 0 5px;
    font-size: 36px;
    line-height: 46px;
}
.os-slide .text {
    padding: 5px;
    background: rgba(255, 255, 255, 0.8);
}
.os-slide img {
    opacity: 0.5;
    transition: 0.8s opacity ease;
}
.os-slide.os-active img {
    opacity: 1;
}
.os-slide .readall {
    display: none;
    position: absolute;
    bottom: 0px;
    right: 0px;
    width: 228px;
    height: 30px;
    text-align: center;
    background: rgba(0, 0, 0, 0.5);
}
.os-slide .readall a {
    font-size: 20px;
    color: #fff;
    line-height: 30px;
}
.os-slide .readall a:after {
    content: 
}
.os-slide.os-active .readall {
    display: block;
}
            
          
!
            
              /**
 * otto.slider
 * Horizontal slider banner with circular animation
 * @author abidibo <abidibo@gmail.com>
 * @copyright 2015 Otto srl
 * @license MIT
 */
(function($) {
    window.OttoSlider = function(container, items, opts) {
        var options = {
            autostart: true,
            autointerval: 5000,
            read_all_text: 'read all'
        };

        /**
         * Inits the component
         */
        this.init = function() {
            this.container = $(container);
            // create items for circular structure, the first item is appended at the end of the stack
            var last = items.pop();
            this.items = $.merge([last], $.merge(items, [last, items[0]]));
            this.cnt_loaded = 0;

            this.slides = [];
            this.active_index = 1;

            this.options = $.extend({}, options, opts);

            this.width = this.container.width();
            console.info('os: container width: ', this.width);

            // set some style on the container
            this.container.css('overflow', 'hidden');
            this.container.css('position', 'relative');

            // render the component
            this.render();
            // when resizing update the component
            var self = this;
            $(window).on('resize', function() {
                console.info('os: resizing window');
                self.size();
            })
            // set the active slider
            this.setActiveSlider(1);

            this.interval = null;
            if(this.options.autostart) {
                var self = this;
                self.interval = setInterval(function() {
                    self.gonext('auto');
                }, this.options.autointerval);
            }

        };

        this.loaded = function() {
            console.log('loaded');
            this.cnt_loaded++;
            if(this.cnt_loaded == this.items.length) {
                this.size();
            }
        }

        /**
         * Renders the component
         */
        this.render = function() {
            var self = this;
            // the rail keeps all the slides
            this.rail = $('<div/>', { 'class': 'os-rail' }).appendTo(this.container);
            this.rail.css('transition-duration', '0s');
            for (var i = 0, len = this.items.length; i < len; i++) {
                var item = this.items[i];
                var slide = $('<section/>', { 'class': 'os-slide' }).appendTo(this.rail);
                this.slides.push(slide);
                slide.img = $('<img/>', {
                    src: item.img_url
                }).appendTo(slide);
                slide.img.on('load', function() { self.loaded() });
                var caption = $('<div/>', { 'class': 'caption' }).appendTo(slide);
                slide.title = $('<h1/>').html(item.title).appendTo(caption);
                slide.text = $('<div/>', { 'class': 'text' }).html(item.text).appendTo(caption);
                slide.readall = $('<div/>', { 'class': 'readall' }).html('<a href="' + item.url + '">' + this.options.read_all_text + '</a>').appendTo(slide);
            }
            // navigation buttons
            this.prev = $('<a/>', { 'class': 'fa fa-chevron-left os-arrow os-prev' }).appendTo(this.container).click($.proxy(this.goprev, this));
            this.next = $('<a/>', { 'class': 'fa fa-chevron-right os-arrow os-next' }).appendTo(this.container).click($.proxy(this.gonext, this));

            var self = this;
            setTimeout(function() {
                self.rail.css('transition-duration', '0.5s');
            })
        };

        /**
         * Sets all the component dimensions
         * Called at the beginning and when resizing the window
         */
        this.size = function() {
            // update container width
            this.width = this.container.width();
            // update img max-width
            this.container.find('img').css('max-width', (this.width - 80) + 'px');
            // update rail width (maybe img width has changed)
            var width = 0;
            for (var i = 0, len = this.slides.length; i < len; i++) {
                width += this.slides[i].img.width();
            }
            this.rail.width = width;
            this.rail.css('width', (width * 2) + 'px');
            // slide width
            this.slide_width = width / this.items.length;
            // I use margin left as animation property
            // I store the calculated margin left value in order to have right calculation when the nav button
            // is pressed before the animation ends (in such case a live calculation of the margin will create problems)
            this.rail.margin_left = this.calculateMargin();
            this.rail.init_margin_left = this.calculateMargin();
            this.rail.css('margin-left', this.rail.margin_left + 'px');
            // reposition navigation buttons
            this.prev.css('right', (this.width + this.slide_width + 10) / 2 + 'px');
            this.next.css('left', (this.width + this.slide_width +10) / 2 + 'px');
        };

        /**
         * Calculates the rail left margin in order to show the active_index slide
         */
        this.calculateMargin = function() {
            var margin = (-(3 * this.slide_width - this.width) / 2) + (1 - this.active_index) * this.slide_width;
            return margin;
        };

        /**
         * Sets the active slide
         * @param {Number} index
         */
        this.setActiveSlider = function(index) {
            $('.os-slide').removeClass('os-active');
            this.active_index = index < 0 ? this.items.length - 1 : index % this.items.length;
            this.rail.css('margin-left', this.calculateMargin() + 'px');
            this.slides[this.active_index].addClass('os-active');
        };

        /**
         * Show prev slide
         */
        this.goprev = function(clearinterval) {
            if(arguments[0] !== 'auto') {
                clearInterval(this.interval);
            }
            this.setActiveSlider(this.active_index - 1);
            // if the shown slide is the first one, then traslate all as we're seeing the penultimate slide
            // without animation
            if(this.active_index == 0) {
                var self = this;
                setTimeout(function() {
                    self.rail.css('transition-duration', '0s'); // no animation!
                    self.setActiveSlider(self.items.length - 2);
                    setTimeout(function() {self.rail.css('transition-duration', '0.5s');}, 100);
                }, 500);
            }
        };

        /**
         * Show next slide
         */
        this.gonext = function() {
            if(arguments[0] !== 'auto') {
                clearInterval(this.interval);
            }
            this.setActiveSlider(this.active_index + 1);
            // if the shown slide is the last one, then reset to the initial state
            // without animation
            if(this.active_index == this.items.length - 1) {
                var self = this;
                setTimeout(function() { 
                    self.rail.css('transition-duration', '0s'); // no animation!
                    self.setActiveSlider(1);
                    setTimeout(function() {self.rail.css('transition-duration', '0.5s');}, 100);
                }, 500);
            }
        };

        this.init();

    }
})(jQuery)

/** end otto.slider */

/**
 * USAGE
 */
var items = [];
items.push({
    'img_url': 'http://lorempixel.com/1000/298/nature',
    'title': '<span>My</span> <span>title</span> <span>1</span>',
    'text': 'Lorem ipsum dolor sit amet, consectetur adipiscing elit. Suspendisse dapibus hendrerit purus, in pellentesque enim viverra accumsan. Donec id tincidunt mi. Aenean ultrices vulputate niosl, at convallis ipsum auctor sit amet. Vestibulum ac vestibulum massa, nec venenatis urna',
    'url': 'http://www.abidibo.net/blog/2015/01/27/responsive-menu-bootstrap/'
});
items.push({
    'img_url': 'http://lorempixel.com/1000/300/nature',
    'title': '<span>My</span> <span>title</span> <span>2</span>',
    'text': 'Donec volutpat mauris quis leo tempor vulputate. Proin in efficitur lacus. Praesent ex libero, posuere eu libero eu, consectetur ornare leo. In venenatis posuere lectus. Mauris eu ligula nec enim pellentesque eleifend eleifend eu dolor. Vestibulum mattis lectus non erat lacinia aliquam. Etiam egestas nunc ut mi fringilla eleifend',
    'url': 'http://www.abidibo.net/blog/2012/01/26/the-importance-of-semantics-in-html-documents/'
});
items.push({
    'img_url': 'http://lorempixel.com/1000/301/nature',
    'title': '<span>My</span> <span>title</span> <span>3</span>',
    'text': 'In iaculis tempus eros vitae iaculis. Suspendisse laoreet quis orci at fermentum. Nam condimentum, lorem gravida interdum varius, mi dolor egestas quam',
    'url': 'http://www.abidibo.net/blog/2013/09/20/ajsut-abidibos-javascript-unit-testing-library/'
});
items.push({
    'img_url': 'http://lorempixel.com/1000/299/nature',
    'title': '<span>My</span> <span>title</span> <span>4</span>',
    'text': 'In iaculis tempus eros vitae iaculis. Suspendisse laoreet quis orci at fermentum. Nam condimentum, lorem gravida interdum varius, mi dolor egestas quam',
    'url': 'http://www.abidibo.net'
});
var slider = new OttoSlider('#otto-slider-container', items, { autostart: true, read_all_text: 'read all »' });


            
          
!
999px
🕑 One or more of the npm packages you are using needs to be built. You're the first person to ever need it! We're building it right now and your preview will start updating again when it's ready.
Loading ..................

Console