Skip to content

Commit

Permalink
Merge pull request #1733 from vinetsky/2.1/bug/carousel-paging
Browse files Browse the repository at this point in the history
Fix carousel paging
  • Loading branch information
stasguryev committed May 23, 2022
2 parents 77c0e85 + d8e81b0 commit 541c8f6
Show file tree
Hide file tree
Showing 3 changed files with 44 additions and 42 deletions.
67 changes: 36 additions & 31 deletions src/layout/carousel/CarouselView.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3,26 +3,28 @@ import CarouselDotsView from './CarouselDotsView';
import template from './carousel.hbs';
import Backbone from 'backbone';

const MIN_MARGIN = 5;
const PADDING = 15;
const TILE_MARGINS = 15;

const defaultOptions = {
slidesToShow: 3,
slidesPerPage: 3,
slidesToScroll: 1,
ContentView: CarouselContentView,
toggleUI: true,
isAutoFill: true,
childWidth: 240
childWidth: 285
};

export default Marionette.View.extend({
initialize() {
_.defaults(this.options, defaultOptions);
this.parentCollection = this.options.collection;

this.currentIndex = 0;
this.collection = new Backbone.Collection();
this.dotsCollection = new Backbone.Collection();
this.slidesToShow = this.options.slidesToShow;
this.slidesPerPage = this.options.slidesPerPage;
this.model.set('childWidth', this.options.childWidth);
const { collection, ...contentOptions } = this.options;
this.contentView = new this.options.ContentView({
collection: this.collection,
Expand All @@ -31,7 +33,7 @@ export default Marionette.View.extend({
});
this.dotsView = new CarouselDotsView({
collection: this.dotsCollection,
slidesToShow: this.slidesToShow,
slidesPerPage: this.slidesPerPage,
currentIndex: this.currentIndex
});
this.listenTo(this.parentCollection, 'add remove reset', this.__refreshCollections);
Expand Down Expand Up @@ -77,16 +79,18 @@ export default Marionette.View.extend({
}
},

__countSlidesToShow(containerWidth: number) {
this.slidesToShow = Math.floor((containerWidth - PADDING * 2) / (this.options.childWidth + 2 * MIN_MARGIN));
__countSlidesPerPage(containerWidth: number) {
const slidesFit = Math.floor((containerWidth - PADDING * 2) / (this.model.get('childWidth') + TILE_MARGINS * 2));
return Math.max(slidesFit, 1);
},

__onResize(entry: Array<ResizeObserverEntry>) {
const containerWidth = entry[0].contentRect.width;
if (containerWidth === 0) {
return;
}
this.__countSlidesToShow(containerWidth);
this.slidesPerPage = this.__countSlidesPerPage(containerWidth);
this.currentIndex = 0;
this.__refreshCollections();
},

Expand All @@ -97,64 +101,65 @@ export default Marionette.View.extend({
},

__updateUI() {
this.__inactivateArrows();
this.__updateArrows();
this.__updateDots();
},

__inactivateArrows() {
__updateArrows() {
const scrollLeftDisabled = this.currentIndex - this.slidesPerPage < 0;
const scrollRightDisabled = this.slidesPerPage + this.currentIndex > this.parentCollection.length - 1;
if (this.options.toggleUI) {
const isNothingToScroll = this.currentIndex - this.options.slidesToScroll < 0 && this.slidesToShow + this.currentIndex >= this.parentCollection.length;
const isNothingToScroll = scrollLeftDisabled && scrollRightDisabled;
this.ui.arrowLeft.toggle(!isNothingToScroll);
this.ui.arrowRight.toggle(!isNothingToScroll);
}
this.ui.arrowLeft.toggleClass('carousel__arrow_inactive', this.currentIndex - this.options.slidesToScroll < 0);
this.ui.arrowRight.toggleClass('carousel__arrow_inactive', this.slidesToShow + this.currentIndex >= this.parentCollection.length);
this.ui.arrowLeft.toggleClass('carousel__arrow_inactive', scrollLeftDisabled);
this.ui.arrowRight.toggleClass('carousel__arrow_inactive', scrollRightDisabled);
},

__onLeftArrowClick() {
if (this.currentIndex - this.options.slidesToScroll < 0) {
const newIndexVal = this.currentIndex - this.slidesPerPage;
if (newIndexVal < 0) {
return;
}
this.currentIndex -= this.options.slidesToScroll;
this.currentIndex = newIndexVal;

this.__resetCurrentCollection();
this.__updateUI();
},

__onRightArrowClick() {
if (this.slidesToShow + this.currentIndex >= this.parentCollection.length) {
const newIndexVal = this.currentIndex + this.slidesPerPage;
if (newIndexVal > this.parentCollection.length - 1) {
return;
}
this.currentIndex += this.options.slidesToScroll;
this.currentIndex = newIndexVal;
this.__resetCurrentCollection();
this.__updateUI();
},

__onSelectPage(index: number) {
this.currentIndex = index;
this.__resetCurrentCollection();
this.__updateUI();
},

__getCurrentCollection() {
return this.parentCollection.slice(Math.max(0, this.currentIndex), Math.min(this.slidesToShow + this.currentIndex, this.parentCollection.length));
return this.parentCollection.slice(Math.max(0, this.currentIndex), Math.min(this.slidesPerPage + this.currentIndex, this.parentCollection.length));
},

__resetCurrentCollection() {
this.collection.set(this.__getCurrentCollection(), { merge: true });
},

__getDots() {
const dots = this.parentCollection.reduce((dotsArray: Array<{ id: number }>, model: Backbone.Model, index: number) => {
const lastIndex = this.parentCollection.length - this.slidesToShow;
if (lastIndex === index) {
dotsArray.push({ id: lastIndex });
return dotsArray;
}

if (index % this.slidesToShow === 0 && index < lastIndex) {
dotsArray.push({ id: index });
}
return dotsArray;
}, []);
const dots: Array<{ id: number }> = [];
let startTileForPage = 0;
do {
dots.push({ id: startTileForPage });
startTileForPage += this.slidesPerPage;
} while (startTileForPage < this.parentCollection.length);

return dots;
},

Expand All @@ -164,7 +169,7 @@ export default Marionette.View.extend({

__updateDots() {
if (this.options.toggleUI) {
const isNothingToScroll = this.currentIndex - this.options.slidesToScroll < 0 && this.slidesToShow + this.currentIndex >= this.parentCollection.length;
const isNothingToScroll = this.currentIndex - this.options.slidesToScroll < 0 && this.slidesPerPage + this.currentIndex >= this.parentCollection.length;
this.dotsView.$el.toggle(!isNothingToScroll);
}
this.dotsView.updateActive(this.currentIndex);
Expand Down
4 changes: 2 additions & 2 deletions src/layout/carousel/carousel.hbs
Original file line number Diff line number Diff line change
@@ -1,7 +1,7 @@
<div class="carousel">
<div class="carousel__content-wrapper">
<div class="js-left-arrow carousel__arrow carousel__arrow_left"></div>
<div class="js-right-arrow carousel__arrow carousel__arrow_right"></div>
<div class="js-left-arrow carousel__arrow carousel__arrow_left"><i class="{{iconPrefixer 'angle-left'}}"></i></div>
<div class="js-right-arrow carousel__arrow carousel__arrow_right"><i class="{{iconPrefixer 'angle-right'}}"></i></div>
<div class="js-content-region"></div>
</div>
<div class="js-dots-region"></div>
Expand Down
15 changes: 6 additions & 9 deletions src/layout/resources/carousel.css
Original file line number Diff line number Diff line change
Expand Up @@ -42,6 +42,7 @@
}

.carousel__dot {
flex: 0 0 auto;
border-radius: 50%;
margin: 0 10px 0 10px;
cursor: pointer;
Expand All @@ -56,28 +57,24 @@

.carousel__arrow {
position: absolute;
font-size: 2rem;
color: var(--theme-colors__primary);
top: 50%;
width: 20px;
height: 20px;
z-index: 100;
border: 2px solid var(--theme-colors__primary);
border-right-color: transparent;
border-top-color: transparent;
cursor: pointer;
}

.carousel__arrow_left {
left: 5px;
margin-right: 5px;
transform: rotate(45deg);
left: -10px;
}

.carousel__arrow_right {
right: 5px;
margin-left: 5px;
transform: rotate(225deg);
right: -10px;
}

.carousel__arrow_inactive {
opacity: 0.5;
cursor: auto;
}

0 comments on commit 541c8f6

Please sign in to comment.