Slider

<div class="slider" data-autoplay="false" data-playing="false">
    <div class="slider__inner">
        <div class="slider__slides-wrap">
            <div class="slider__slides">
                <div class="slider__slide"><a class="card" href="#">
                        <div class="card__image">
                            <div class="image loading" style="padding-top: 100%;"><noscript><img class="image__fallback" alt="Alternativ-Text" width="610" height="610" src="https://via.placeholder.com/610x610/A0A0A6/FFFFFF.png?text=610x610" /></noscript><img class="image__img js-lazyload" alt="Alternativ-Text" width="610" height="610" data-src="https://via.placeholder.com/610x610/A0A0A6/FFFFFF.png?text=610x610" /></div>
                        </div>
                        <div class="card__play"><svg class="icon icon--play-box" viewBox="0 0 200 200" role="presentation">
                                <use xlink:href="#icon-play-box"></use>
                            </svg></div>
                        <div class="card__body">
                            <div class="card__body__inner">
                                <div class="card__headline">
                                    <h2 class="headline headline--2">Heiling durch Gentherapie</h2>
                                </div>
                                <div class="card__subline">19.01.2021</div>
                                <div class="card__icons"><span class="card__icons__item"><svg class="icon icon--arrow-right" viewBox="0 0 200 200" role="presentation">
                                            <use xlink:href="#icon-arrow-right"></use>
                                        </svg></span></div>
                            </div>
                        </div>
                    </a></div>
                <div class="slider__slide"><a class="microcard microcard--has-text" href="#">
                        <div class="microcard__inner">
                            <div class="microcard__image"><img class="microcard__image__img" src="https://via.placeholder.com/400x400/A0A0A6/ffffff.png?text=400x400" width="400" height="400" alt="Alternativ-Text" /></div>
                            <div class="microcard__bottom">
                                <div class="microcard__headline">
                                    <h3 class="headline headline--3">Neue Partner: DASHH und HAW Hamburg</h3>
                                </div>
                                <div class="microcard__subline">19.01.2021</div>
                                <div class="microcard__text">220 Zeichen max. Lorem ipsum dolor sit amet consectetur adipisicing elit. Quam sed vitae harum dolore corrupti a molestias blanditiis, deserunt, nostrum nemo distinctio rerumess qui necessitatibus sequi laudantium ipsum.</div>
                                <div class="microcard__icons"><span class="microcard__icons__item"><svg class="icon icon--arrow-right" viewBox="0 0 200 200" role="presentation">
                                            <use xlink:href="#icon-arrow-right"></use>
                                        </svg></span></div>
                            </div>
                        </div>
                    </a></div>
                <div class="slider__slide"><a class="microcard microcard--has-text" href="#">
                        <div class="microcard__inner">
                            <div class="microcard__image"><img class="microcard__image__img" src="https://via.placeholder.com/400x400/A0A0A6/ffffff.png?text=400x400" width="400" height="400" alt="Alternativ-Text" /></div>
                            <div class="microcard__bottom">
                                <div class="microcard__headline">
                                    <h3 class="headline headline--3">Neue Partner: DASHH und HAW Hamburg</h3>
                                </div>
                                <div class="microcard__subline">19.01.2021</div>
                                <div class="microcard__text">220 Zeichen max. Lorem ipsum dolor sit amet consectetur adipisicing elit. Quam sed vitae harum dolore corrupti a molestias blanditiis, deserunt, nostrum nemo distinctio rerumess qui necessitatibus sequi laudantium ipsum.</div>
                                <div class="microcard__icons"><span class="microcard__icons__item"><svg class="icon icon--arrow-right" viewBox="0 0 200 200" role="presentation">
                                            <use xlink:href="#icon-arrow-right"></use>
                                        </svg></span></div>
                            </div>
                        </div>
                    </a></div>
                <div class="slider__slide"><a class="microcard microcard--has-text" href="#">
                        <div class="microcard__inner">
                            <div class="microcard__image"><img class="microcard__image__img" src="https://via.placeholder.com/400x400/A0A0A6/ffffff.png?text=400x400" width="400" height="400" alt="Alternativ-Text" /></div>
                            <div class="microcard__bottom">
                                <div class="microcard__headline">
                                    <h3 class="headline headline--3">Neue Partner: DASHH und HAW Hamburg</h3>
                                </div>
                                <div class="microcard__subline">19.01.2021</div>
                                <div class="microcard__text">220 Zeichen max. Lorem ipsum dolor sit amet consectetur adipisicing elit. Quam sed vitae harum dolore corrupti a molestias blanditiis, deserunt, nostrum nemo distinctio rerumess qui necessitatibus sequi laudantium ipsum.</div>
                                <div class="microcard__icons"><span class="microcard__icons__item"><svg class="icon icon--arrow-right" viewBox="0 0 200 200" role="presentation">
                                            <use xlink:href="#icon-arrow-right"></use>
                                        </svg></span></div>
                            </div>
                        </div>
                    </a></div>
                <div class="slider__slide"><a class="microcard microcard--has-text" href="#">
                        <div class="microcard__inner">
                            <div class="microcard__image"><img class="microcard__image__img" src="https://via.placeholder.com/400x400/A0A0A6/ffffff.png?text=400x400" width="400" height="400" alt="Alternativ-Text" /></div>
                            <div class="microcard__bottom">
                                <div class="microcard__headline">
                                    <h3 class="headline headline--3">Neue Partner: DASHH und HAW Hamburg</h3>
                                </div>
                                <div class="microcard__subline">19.01.2021</div>
                                <div class="microcard__text">220 Zeichen max. Lorem ipsum dolor sit amet consectetur adipisicing elit. Quam sed vitae harum dolore corrupti a molestias blanditiis, deserunt, nostrum nemo distinctio rerumess qui necessitatibus sequi laudantium ipsum.</div>
                                <div class="microcard__icons"><span class="microcard__icons__item"><svg class="icon icon--arrow-right" viewBox="0 0 200 200" role="presentation">
                                            <use xlink:href="#icon-arrow-right"></use>
                                        </svg></span></div>
                            </div>
                        </div>
                    </a></div>
            </div>
        </div>
    </div>
</div>
//- Render slider
#{tag || 'div'}.slider(
  data-autoplay=autoplay && 'true' || 'false',
  data-playing=autoplay && 'true' || 'false',
)&attributes(attr)
  .slider__inner: .slider__slides-wrap
    if slides
      .slider__slides
        each item in slides
          .slider__slide
            +include(`@${item.use}`, item.settings || {})
{
  "slides": [
    {
      "use": "card--news"
    },
    {
      "use": "microcard--news"
    },
    {
      "use": "microcard--news"
    },
    {
      "use": "microcard--news"
    },
    {
      "use": "microcard--news"
    }
  ]
}
  • Content:
    import { lory } from '@rsm/allfarblori';
    import h from 'hyperscript';
    import icon from 'components/_particles/icon/generate-icon';
    
    export default class Slider {
      constructor($el) {
        this.$el = $el;
        this.$slides = this.$el.querySelectorAll('.slider__slide');
        this.$inner = this.$el.querySelector('.slider__inner');
        this.$slidesContainer = this.$el.querySelector('.slider__slides-wrap');
    
        // Don't init slider, if only one slide exists
        if (this.$slides.length === 1) {
          return;
        }
    
        this.$el.addEventListener('before.lory.init', () => {
          this.$slidesContainer.scrollLeft = 0;
          this.initControls();
        });
    
        this.$el.addEventListener('after.lory.init', () => {
          window.console.log('[Slider] Initialized', $el);
          this.$el.classList.add('slider--initialized');
          this.initAutoplay();
        });
    
        this.$el.addEventListener('after.lory.slide', () => {
          window.console.log('[Slider] Slide', $el);
          this.updateDots();
          this.updatePagination();
        });
    
        this.lory = lory(this.$el, {
          rewind: true,
          slideSpeed: 250,
          ease: 'cubic-bezier(0.455, 0.03, 0.515, 0.955)',
          classNameFrame: 'slider__slides-wrap',
          classNameSlideContainer: 'slider__slides',
          classNamePrevCtrl: 'slider__arrow--prev',
          classNameNextCtrl: 'slider__arrow--next',
          classNameDisabledPrevCtrl: 'slider__arrow--disabled',
          classNameDisabledNextCtrl: 'slider__arrow--disabled',
        });
    
        this.$slidesContainer.addEventListener('focusin', (event) => {
          this.$slidesContainer.scrollLeft = 0;
          const $slide = event.target.closest('.slider__slide');
          const index = Array.prototype.indexOf.call(this.$slides, $slide);
          this.lory.slideTo(index);
        });
      }
    
      initControls() {
        this.$controlPrev = h(
          'button.slider__arrow.slider__arrow--prev',
          {
            type: 'button',
            tabIndex: '-1',
            title: 'Vorheriger Slide',
          },
          icon({
            icon: 'arrow-left-box',
            className: 'slider__arrow-icon',
          }),
          h('span.u-hidden-visually', 'Vorheriger Slide'),
        );
    
        this.$controlNext = h(
          'button.slider__arrow.slider__arrow--next',
          {
            type: 'button',
            tabIndex: '-1',
            title: 'Nächster Slide',
          },
          icon({
            icon: 'arrow-right-box',
            className: 'slider__arrow__icon',
          }),
          h('span.u-hidden-visually ', 'Nächster Slide'),
        );
    
        this.$dots = h(
          '.slider__dots',
          [...this.$slides].map((_, index) => h(
            `button.slider__dots__dot${index === 0 ? '.slider__dots__dot--active' : ''}`,
            {
              type: 'button',
              tabIndex: '-1',
              title: (index + 1),
              onclick: () => this.lory.slideTo(index),
            },
            h('span.u-hidden-visually', (index + 1)),
          )),
        );
    
        this.$pagination = h(
          '.slider__pagination',
          h('span.u-hidden-visually', 'Aktuelle Seite'),
          h('span.slider__pagination__current-page', '1'),
          '/',
          h('span.u-hidden-visually', 'Seitenanzahl'),
          h('span.slider__pagination__total-page-count', this.$slides.length),
        );
    
        this.$controlPlay = h(
          'button.slider__play-control',
          {
            type: 'button',
            title: 'Slides automatisch abspielen',
            attrs: {
              'aria-pressed': this.isAutoplay() ? 'true' : 'false',
            },
          }, icon({
            icon: 'play',
            className: 'slider__play-control__icon slider__play-control__icon--play',
          }), icon({
            icon: 'pause',
            className: 'slider__play-control__icon slider__play-control__icon--stop',
          }),
          h('span.u-hidden-visually', 'Slides automatisch abspielen'),
        );
    
        this.$controls = h('.slider__controls');
        this.$controls.appendChild(this.$controlPrev);
        this.$controls.appendChild(this.$controlPlay);
        this.$controls.appendChild(this.$pagination);
        this.$controls.appendChild(this.$dots);
        this.$controls.appendChild(this.$controlNext);
    
        this.$inner.appendChild(this.$controls);
      }
    
      isPlaying() {
        return (this.$el.getAttribute('data-playing') === 'true');
      }
    
      isAutoplay() {
        return (this.$el.getAttribute('data-autoplay') === 'true');
      }
    
      initAutoplay() {
        // Touch kill
        let hasTouched = false;
    
        // Init timer
        const timerInit = () => setInterval(() => this.lory.next(), 5000);
        let timer = this.isPlaying() ? timerInit() : false;
    
        // Kill timer if a mouse enters the slider
        this.$el.addEventListener('mouseover', () => {
          // this.$el.setAttribute('data-playing', 'false');
          clearInterval(timer);
        });
    
        // Restart timer if a mouse leaves the slider
        this.$el.addEventListener('mouseleave', () => {
          if (!hasTouched && this.isPlaying()) timer = timerInit();
        });
    
        // Kill the timer if at least on touch interaction happend
        this.$el.addEventListener('touchstart', function killOnTouchStart() {
          clearInterval(timer);
          this.$el.revomeEventListener('touchstart', killOnTouchStart);
          hasTouched = true;
        }, { passive: true });
    
        // Autoplay toggle button (play/pause)
        this.$controlPlay.addEventListener('click', () => {
          if (this.isPlaying()) {
            this.$controlPlay.setAttribute('aria-pressed', 'false');
            this.$el.setAttribute('data-playing', 'false');
            clearInterval(timer);
          } else {
            this.$controlPlay.setAttribute('aria-pressed', 'true');
            this.$el.setAttribute('data-playing', 'true');
            if (!hasTouched) timer = timerInit();
            setTimeout(() => this.lory.next(), 500);
          }
        });
      }
    
      updateDots() {
        this.$el.querySelector('.slider__dots__dot--active')
          .classList.remove('slider__dots__dot--active');
    
        this.$el.querySelectorAll('.slider__dots__dot')[this.lory.returnIndex()]
          .classList.add('slider__dots__dot--active');
      }
    
      updatePagination() {
        this.$el.querySelector('.slider__pagination__current-page').innerHTML = this.lory.returnIndex() + 1;
        this.$el.querySelector('.slider__pagination__total-page-count').innerHTML = this.$slides.length;
      }
    }
    
    document.querySelectorAll('.slider').forEach($slider => new Slider($slider));
    
  • URL: /components/raw/slider/slider.js
  • Filesystem Path: src/components/molecules/slider/slider.js
  • Size: 6.2 KB
  • Content:
    // Slider
    .slider {
      position: relative;
      width: 100%;
    }
    
    .slider__inner {
      position: relative;
    }
    
    .slider__slides-wrap {
      position: relative;
      width: 100%;
    
      .no-js & {
        overflow-x: scroll;
        overflow-y: hidden;
      }
    
      .slider--initialized & {
        overflow: visible;
      }
    }
    
    .slider__slides {
      display: flex;
      transition-property: transform;
      z-index: 1;
    }
    
    // Single Slide
    .slider__slide {
      flex-shrink: 0;
      position: relative;
      transition: opacity 0.35s;
      width: 100%;
    
      @include mq($from: m) {
        flex-shrink: 1;
        padding-right: 4rem;
      }
    }
    
    // Arrows
    .slider__arrow {
      color: #fff;
      cursor: pointer;
      font-size: 1.6rem;
      height: 4rem;
      // opacity: 0;
      // pointer-events: none;
      position: absolute;
      top: 45%;
      transform: translateY(-50%);
      transition: 0.2s;
      transition-property: opacity;
      width: 4rem;
      z-index: 2;
    
      @include mq($until: xl) {
        display: none;
      }
    }
    
    .slider__arrow .icon {
      color: $color-dark;
      cursor: pointer;
      height: 5.2rem;
      left: 50%;
      opacity: 0.5;
      position: absolute;
      top: 50%;
      transform: translate(-50%, -50%);
      width: 5.2rem;
    }
    
    .slider__arrow--prev .icon {
      cursor: pointer;
      left: 46%;
    }
    
    .slider__arrow--disabled {
      opacity: 0;
      pointer-events: none;
    }
    
    .slider__arrow--prev {
      left: -6.5rem;
    }
    
    .slider__arrow--next {
      right: 2.5rem;
    
      @include mq($from:xxl) {
        right: 4.5rem;
      }
    }
    
    // Dots
    .slider__dots {
      bottom: -5rem;
      display: inline-block;
      left: 50%;
      position: absolute;
      transform: translateX(-50%);
    
      &__dot {
        background: $color-gray;
        border-radius: 0.35rem;
        display: inline-block;
        height: 0.7rem;
        margin: 0 0.5rem;
        transition: background 0.2s, width 0.2s;
        width: 0.7rem;
      }
    
      &__dot--active {
        background: $color-dark;
        width: 3rem;
      }
    }
    
    // Pagination
    .slider__pagination {
      display: none;
    }
    
    // Play Control
    .slider__play-control {
      display: none;
    }
    
    // Custom styles
    .slider .card {
      @include mq($from: m) {
        margin-right: 4rem;
      }
    }
    
    .slider .microcard {
      @include mq($until: m) {
        margin: 0 2rem;
        width: calc(100% - 4rem);
      }
    }
    
  • URL: /components/raw/slider/slider.scss
  • Filesystem Path: src/components/molecules/slider/slider.scss
  • Size: 2.1 KB

There are no notes for this item.