Your IP : 18.224.0.57


Current Path : /var/www/www-root/data/www/www.monolith-realty.ru/bitrix/js/ui/carousel/src/
Upload File :
Current File : /var/www/www-root/data/www/www.monolith-realty.ru/bitrix/js/ui/carousel/src/carousel.js

import { Tag, Dom, Event } from 'main.core';
import { EventEmitter } from 'main.core.events';
import { Loader } from "main.loader";

export class Carousel
{
	constructor(options = {})
	{
		this.offsetCache = 0;

		this.target = options.target || null;
		this.content = options.content || null;
		this.responsive = options.responsive || null;
		this.autoPlaySpeed = options.autoPlaySpeed || 1000;
		this.autoPlay = options.autoPlay || false;
		this.dots = options.dots || false;
		this.dotsClass = options.dotsClass || '--default';
		this.arrows = options.arrows || false;
		this.arrowsClass = options.arrowsClass || '--default';
		this.vertical = options.vertical || false;
		this.infinite = options.infinite || false;

		//node
		this.carouselContainer = null;
		this.wrapper = null;
		this.track = null;
		this.nodeDots = null;
		this.nodeArrows = null;

		this.arrayDotsItem = [];
		this.arrayItems = [];
		this.arrayItemsWidth = 0;
		this.arrayItemsHeight = 0;
		this.isLastSlide = 0;
		this.arrayArrowsItem = [];
		this.slidActive = 1;
		this.sliderInterval = null;
		this.sliderAllCount = this.content.length;

		// this.draggable = true;
		this.defaultSettings();
	}

	defaultSettings() {
		this.defaultParameters = {};

		for (let key in this) {
			this.defaultParameters[key] = this[key];
		}
	}

	getItem(item, index)
	{
		let itemClass = this.slidActive -1 === index
			? '--active'
			: ''
		;

		let slideItem = Tag.render`
			<div class="ui-carousel__slide ${itemClass}">
				${item.html}
			</div>
		`

		Event.bind(slideItem, 'mouseenter', this.stopSlide.bind(this));
		Event.bind(slideItem, 'mouseleave', this.runSlide.bind(this));

		if (this.arrayItems.indexOf(item) === -1)
		{
			this.arrayItems.push(slideItem);
		}

		return slideItem;
	}

	setTrackCharacteristics()
	{
		if (this.arrayItemsWidth === 0 && this.arrayItemsHeight === 0)
		{
			for (let i = 0; i < this.arrayItems.length; i++) {
				this.arrayItemsWidth += this.arrayItems[i].offsetWidth;
				this.arrayItemsHeight += this.arrayItems[i].offsetHeight;
			}
		}
	}

	initSlider()
	{
		this.runSlide();
	}

	stopSlide()
	{
		clearInterval(this.sliderInterval);
	}

	changeActivePoint()
	{
		if (this.arrayDotsItem.length > 1)
		{
			for (let i = 0; i < this.arrayDotsItem.length; i++)
			{
				if (this.arrayDotsItem[i].classList.contains('--active'))
				{
					this.arrayDotsItem[i].classList.remove('--active');
				}
			}

			this.arrayDotsItem[this.slidActive - 1].classList.add('--active');
		}
	}

	changeActiveSlide()
	{
		if (this.arrayItems.length > 1)
		{
			for (let i = 0; i < this.arrayItems.length; i++)
			{
				if (this.arrayItems[i].classList.contains('--active'))
				{
					this.arrayItems[i].classList.remove('--active');
				}
			}

			this.arrayItems[this.slidActive - 1].classList.add('--active');
		}
	}

	changeActiveArrow(id)
	{
		if (!this.infinite)
		{
			this.arrayArrowsItem.map((item)=> {
				item.classList.remove('--disabled');
			});

			if(this.slidActive === this.sliderAllCount || id >= this.isLastSlide && this.isLastSlide > 0)
			{
				this.arrayArrowsItem[this.arrayArrowsItem.length - 1].classList.add('--disabled');
			}
			else if(this.slidActive === 1)
			{
				this.arrayArrowsItem[0].classList.add('--disabled');
			}
		}

	}

	changeActive(id)
	{
		this.changeActivePoint();
		this.changeActiveSlide();

		if (!this.infinite)
		{
			this.changeActiveArrow(id);
		}
	}

	runSlide()
	{
		if(this.sliderAllCount > 1 && this.autoPlay)
		{
			this.trackOffsetStep();

			this.sliderInterval = setInterval(() => {
				let sliderNum = this.slidActive + 1 > this.sliderAllCount
					? 1
					: this.slidActive + 1;

				this.showSlide(sliderNum);
			}, this.autoPlaySpeed);
		}
	}

	trackOffsetStep()
	{
		if (this.offsetCache === 0)
		{
			this.offsetCache = this.wrapper ? this.wrapper.offsetWidth : 0
		}

		return this.offsetCache;
	}

	getTrackShift(id)
	{
		let shift = 0;

		if (id > 1)
		{
			let cycleLength = 0;

			if (id >= this.isLastSlide && this.isLastSlide > 0)
			{
				cycleLength = this.isLastSlide - 1;
			}
			else
			{
				cycleLength = id - 1;
			}

			if (this.vertical)
			{
				let sumShift = this.arrayItemsHeight;

				for (let i = 0; i < cycleLength; i++)
				{
					sumShift -= this.arrayItems[i].offsetHeight;

					if (sumShift < this.wrapper.offsetHeight)
					{
						this.isLastSlide = id;
						shift += (sumShift +  this.arrayItems[i].offsetHeight - this.wrapper.offsetHeight);
					}
					else
					{
						shift += this.arrayItems[i].offsetHeight;
					}
				}
			}
			else
			{
				let sumShift = this.arrayItemsWidth;

				for (let i = 0; i < cycleLength; i++)
				{
					sumShift -= this.arrayItems[i].offsetWidth;

					if (sumShift < this.wrapper.offsetWidth)
					{
						this.isLastSlide = id;
						shift += (sumShift +  this.arrayItems[i].offsetWidth - this.wrapper.offsetWidth);
					}
					else
					{
						shift += this.arrayItems[i].offsetWidth;
					}
				}
			}
		}

		return shift;
	}

	showSlide(id)
	{
		this.setTrackCharacteristics();

		if (id > 0 && id <= this.sliderAllCount)
		{
			this.slidActive = id;

			if (this.track)
			{
				if (this.vertical)
				{
					this.track.style.transform = 'translateY(' + -(this.getTrackShift(id)) + 'px)';
				}
				else
				{
					this.track.style.transform = 'translateX(' + -(this.getTrackShift(id)) + 'px)';
				}

			}
		}

		clearInterval(this.sliderInterval);
		this.runSlide();
		this.changeActive(id);
	}

	nextSlide()
	{
		if (this.infinite)
		{
			if (this.slidActive === this.sliderAllCount)
			{
				this.slidActive = 1;
				this.showSlide(this.slidActive);
			}
			else if (this.slidActive < this.sliderAllCount)
			{
				this.slidActive += 1;
				this.showSlide(this.slidActive);
			}
		}
		else
		{
			if (this.slidActive < this.sliderAllCount)
			{
				this.slidActive += 1;
				this.showSlide(this.slidActive);
			}
		}
	}

	prevSlide()
	{
		if (this.infinite)
		{
			if (this.slidActive === 1)
			{
				this.slidActive = this.sliderAllCount;
				this.showSlide(this.slidActive);
			}
			else if (this.slidActive > 1)
			{
				this.slidActive -= 1;
				this.showSlide(this.slidActive);
			}
		}
		else
		{
			if (this.slidActive > 1)
			{
				this.slidActive -= 1;
				this.showSlide(this.slidActive);
			}
		}
	}

	getArrows()
	{
		let verticalClass = this.vertical
			? '--vertical'
			: ''
		;

		this.nodeArrows = Tag.render`
			<div class="ui-carousel__arrows--container ${verticalClass}"></div>
		`
		let arrowDisabledClass = this.infinite
			? ''
			: '--disabled'
		;

		let arrowPrev = Tag.render`
			<div class="ui-carousel__arrow ${this.arrowsClass} --prev ${arrowDisabledClass} ${verticalClass}"></div>
		`

		let arrowNext = Tag.render`
			<div class="ui-carousel__arrow ${this.arrowsClass} --next ${verticalClass}"></div>
		`

		Event.bind(arrowPrev, 'click', this.prevSlide.bind(this));
		Event.bind(arrowNext, 'click', this.nextSlide.bind(this));

		this.arrayArrowsItem.push(arrowPrev);
		this.arrayArrowsItem.push(arrowNext);
		this.nodeArrows.append(arrowPrev);
		this.nodeArrows.append(arrowNext);

		return this.nodeArrows;
	}

	getDots()
	{
		this.nodeDots = Tag.render`
			<div class="ui-carousel__dots ${this.dotsClass}"></div>
		`

		for (let i = 0; i < this.sliderAllCount; i++)
		{
			let dotClassActive= this.slidActive === i+1
				? '--active'
				: ''
			;

			let nodeDotsItem = Tag.render`
				<div class="ui-carousel__dots--item ${this.dotsClass} ${dotClassActive}">
				</div>
			`;

			Event.bind(nodeDotsItem, 'click', this.showSlide.bind(this, i+1));

			this.arrayDotsItem.push(nodeDotsItem);
			this.nodeDots.append(nodeDotsItem);
		}

		return this.nodeDots;
	}

	getCarouselContent(): HTMLElement
	{
		let verticalClass = this.vertical
			? '--vertical'
			: ''
		;

		this.track = Tag.render`
			<div class="ui-carousel__track ${verticalClass}"></div>
		`;

		this.content.map((item, index)=> {
			this.track.appendChild(this.getItem(item, index));
		});

		this.wrapper = Tag.render`
			<div class="ui-carousel__wrapper">
				${this.track}
			</div>
		`;

		this.carouselContainer = Tag.render`
			<div class="ui-carousel__container ui-carousel__scope ${verticalClass}">
				${this.wrapper}
			</div>
		`;

		if (this.dots && this.sliderAllCount > 1)
		{
			this.carouselContainer.appendChild(this.getDots());
		}

		if (this.arrows && this.sliderAllCount > 1)
		{
			this.carouselContainer.appendChild(this.getArrows());
		}

		return this.carouselContainer;
	}

	responsiveCarousel()
	{
		if(this.responsive)
		{
			for (let i = 0; i < this.responsive.length; i++)
			{
				if (window.innerWidth > this.responsive[0].breakpoint)
				{
					let newData = this.defaultParameters;

					for (let key in newData)
					{
						this[key] = newData[key];
					}

					break;
				}
				else if (window.innerWidth <= this.responsive[i].breakpoint)
				{
					let newData = this.responsive[i].settings;

					for (let key in newData)
					{
						this[key] = newData[key];
					}
				}
			}
		}
	}

	carouselResize()
	{
		if(this.responsive)
		{
			window.addEventListener('resize', () =>
			{
				for (let i = 0; i < this.responsive.length; i++)
				{
					if (this.windowWidth > this.responsive[i].breakpoint && window.innerWidth < this.responsive[i].breakpoint)
					{
						this.windowWidth = window.innerWidth;
						this.init();
					}
					else if (this.windowWidth < this.responsive[i].breakpoint && window.innerWidth > this.responsive[i].breakpoint)
					{
						this.windowWidth = window.innerWidth;
						this.init();
					}
				}
			});
		}
	}

	init()
	{
		if (this.target && this.content)
		{
			this.windowWidth = window.innerWidth;
			Dom.clean(this.target);
			this.responsiveCarousel();
			this.target.appendChild(this.getCarouselContent());
			this.initSlider();

			this.carouselResize();
		}
	}
}