futura.js
Version:
A small JavaScript library for common tasks such as Carousel, Exception, Animation handler and more...
198 lines (180 loc) • 7.4 kB
JavaScript
/*---------------------------------------------------------------------
FvCarousel v1.0.0 (FuturaJS)
-----------------------------------------------------------------------*/
/**
* @class : FvCarousel
* @classdesc : Easily build your Carousel
* @site : https://github.com/BlakvGhost/FuturaJS.git
* @tutorial :
* @licence : MIT
* @version : v1.0.0
*/
const DATA_VISIBLE = `data-fv-visible`;
const DATA_POSITION = `data-fv-position`;
const SLIDE_ITEM_LABEL = `aria-label`
const DIV_NODE = `div`;
const DOT_CLASS = `fv-carousel-dots-item`
const DEFAULT_PARAM = {
items: 2,
margin: '5px',
prev: '.fv-carousel-control-prev',
next: '.fv-carousel-control-next',
autoplay: true,
autoplaySpeed: '500ms',
autoplayHoverPause: true,
timeout: 5000,
allowDrag: true,
keyDirection: true,
direction: 'horizontal',
dots: {
el: '.fv-dots',
direction: 'vertical'
}
}
const CAROUSEL_STYLE = `
.fv-carousel {overflow: hidden;max-width:100%;height: 100%;}
.fv-carousel-inner {width: 100%;height: 100%;overflow: hidden;padding: 0;}
.fv-carousel-group {width: 100%;height: 100%;display: flex;flex-wrap: nowrap;}
.fv-carousel-item {flex: 0 0 auto;width: 100%;height: 100%;display: block; }
.direction-horizontal {flex-direction: row}
.direction-vertical {flex-direction: column}
.fv-carousel-dots {z-index: 6}
.fv-carousel-dots-group {display: flex;justify-content: space-between;height: 100%;width: 100%;}
.fv-carousel-dots-item {margin: .5rem!important;height:10px;width:10px;border-radius:50%;}
.fv-dot-active {background-color: red;}
.fv-dot-inactive {background-color: silver;}
`
export default class FvCarousel {
constructor(elt,b = DEFAULT_PARAM) {
this._itemClass = `.fv-carousel-item`;
this.___i = 0;
this.__ = document.querySelector(elt);
this.___ = this.__.querySelectorAll(this._itemClass);
this.prevBtn = document.querySelector(b.prev);
this.nextBtn = document.querySelector(b.next);
this.dotsContainer = document.querySelector(b.dots.el);
this.dotsDirection = b.dots.direction;
this.slideDirection = b.direction;
this.timeout = b.timeout ?? 5000;
this.itemsCount = b.items ?? 2;
this.autoplaySpeed = b.autoplaySpeed ?? '500ms';
this.elementMargin = b.margin;
this.allowKeyDirection = b.keyDirection === undefined ? true : b.keyDirection;
this.autoplay = b.autoplay === undefined ? true : b.autoplay;
this.autoplayHoverPause = b.autoplayHoverPause === undefined ? true : b.autoplayHoverPause;
this.allowDrag = b.allowDrag === undefined ? true : b.allowDrag;
this.elementWidth = b.direction === 'vertical' ? this.__.offsetWidth : this.__.offsetWidth / this.itemsCount;
this.elementHeight = this.___[0].getBoundingClientRect().height;
this.start();
}
start() {
let __m = document.createElement('style');
__m.innerHTML = CAROUSEL_STYLE;
document.querySelector('head').append(__m);
this.__.classList.add('fv-carousel');
let _m = document.createElement(DIV_NODE);
_m.classList.add('fv-carousel-inner');
this.__.appendChild(_m);
let __y = document.createElement(DIV_NODE);
__y.classList.add('fv-carousel-group',`direction-${this.slideDirection}`);
_m.appendChild(__y);
this.___.forEach( (__t,_i) => {
__y.appendChild(__t) && __t.classList.add('fv-carousel-item');
__t.setAttribute(SLIDE_ITEM_LABEL,`${_i + 1}/${this.___.length}`) ;
__t.style.width = `${this.elementWidth}px`;
__t.style.margin = this.elementMargin;
});
this.rowMain = __y;
this.autoplay ? this.autoPlay() : null;
this.autoplayHoverPause ? this.stopOnHover() : false;
this.dotsContainer ? this.dots() : null;
this.allowDrag ? this.drag() : null;
this.allowKeyDirection ? this.keyDirection() : null;
this.prevBtn ? this.prevBtn.addEventListener('click',() => this.prev()) : null
this.nextBtn ? this.nextBtn.addEventListener('click',() => this.next()) : null
}
autoPlay() {
this.__autoplayId = setInterval(() => {
this.next();
},this.timeout);
}
toIndex(_i) {
this.rowMain.style.transition = `${this.autoplaySpeed} ease-in`;
this.rowMain.style.transform = this.slideDirection.includes('horizontal') ? `translate3d(-${_i * this.elementWidth}px,0px,0px)` : `translate3d(0px,-${_i * 100}%,0px)`;
this.rowMain.setAttribute(DATA_VISIBLE,_i);
this.dotsBgColor();
}
prev() {
this.___i = this.___i > 0 ? this.___i - 1 : this.___.length - 1
this.toIndex(this.___i);
this.dotsBgColor();
}
next() {
this.___i = this.___i < this.___.length - 1 ? this.___i + 1 : 0 ;
this.toIndex(this.___i);
this.dotsBgColor();
}
drag() {
this.__.addEventListener('drag',(e) => {
let _x = e.pageX;
_x !== 0 ? this.toIndex(_x/1000) : false;
});
this.__.addEventListener('dragend',(e) => {
let _x = e.pageX,_m = this.elementWidth/2;
_x < _m ? this.prev() : this.next();
});
}
keyDirection() {
this.__.addEventListener('keyup', (e) => {
switch (e.code) {
case 'ArrowRight': this.next()
break
case 'ArrowLeft': this.prev()
break
}
})
}
touchmove() {
this.__.addEventListener('touchmove',(e) => {
let _x = e.pageX;
_x !== 0 ? this.toIndex(_x/1000) : false;
});
}
stopOnHover() {
this.__.addEventListener('mouseenter',() => {
clearInterval(this.__autoplayId);
});
this.__.addEventListener('mouseleave',() => {
//this.next();
this.autoPlay();
});
}
dots() {
this.dotsContainer.classList.add('fv-carousel-dots');
let _m = document.createElement(DIV_NODE);
_m.classList.add('fv-carousel-dots-group',`direction-${this.dotsDirection}`)
this.___.forEach((item,i) => {
let _d = document.createElement(DIV_NODE);
_d.classList.add(DOT_CLASS);
_d.setAttribute(DATA_POSITION,i);
i === 0? _d.classList.add('fv-dot-active') : _d.classList.add('fv-dot-inactive');
_m.appendChild(_d);
_d.addEventListener('click', () => {
this.toIndex(i) ;
this.___i = i;
});
});
this.dotsContainer.appendChild(_m);
}
dotsBgColor() {
if (this.dotsContainer) {
let _d = this.dotsContainer.querySelectorAll(`.${DOT_CLASS}`);
_d.forEach((item,_i) => {
let __i = parseInt(this.rowMain.getAttribute(DATA_VISIBLE));
let _c = __i === _i ? 'active' : 'inactive';
item.setAttribute('class',`${DOT_CLASS} fv-dot-${_c}`);
})
}
}
}
window.FvCarousel = FvCarousel;