Skip to content

Commit

Permalink
feat(slidesPerColumn): init (#4508)
Browse files Browse the repository at this point in the history
  • Loading branch information
vltansky authored Jul 11, 2021
1 parent 38682bb commit c469d29
Show file tree
Hide file tree
Showing 6 changed files with 235 additions and 86 deletions.
93 changes: 93 additions & 0 deletions cypress/integration/modules/core.js
Original file line number Diff line number Diff line change
Expand Up @@ -146,6 +146,99 @@ context('Core', () => {
cy.getSlide(1).expectToBeActiveSlide();
});

it('slidesPerColumn', () => {
cy.initSwiper({
slidesPerView: 2,
slidesPerColumn: 2,
spaceBetween: 30,
});
cy.injectStyles(`
.swiper-container {
width: 100%;
height: 100%;
margin-left: auto;
margin-right: auto;
}
.swiper-slide {
text-align: center;
font-size: 18px;
background: #fff;
height: calc((100% - 30px) / 2);
/* Center slide text vertically */
display: -webkit-box;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
-webkit-box-pack: center;
-ms-flex-pack: center;
-webkit-justify-content: center;
justify-content: center;
-webkit-box-align: center;
-ms-flex-align: center;
-webkit-align-items: center;
align-items: center;
}
`);
cy.getSlide(1).should(($el) => {
expect($el[0].getBoundingClientRect().y).to.be.greaterThan(100);
});
cy.getSlide(2).should(($el) => {
expect($el[0].getBoundingClientRect().x).to.be.greaterThan(100);
});
});

it.only('slidesPerColumnFill', () => {
cy.initSwiper({
slidesPerView: 2,
slidesPerColumnFill: 'row',
slidesPerColumn: 2,
spaceBetween: 30,
});
cy.injectStyles(`
.swiper-container {
width: 100%;
height: 100%;
margin-left: auto;
margin-right: auto;
}
.swiper-slide {
text-align: center;
font-size: 18px;
background: #fff;
height: calc((100% - 30px) / 2);
/* Center slide text vertically */
display: -webkit-box;
display: -ms-flexbox;
display: -webkit-flex;
display: flex;
-webkit-box-pack: center;
-ms-flex-pack: center;
-webkit-justify-content: center;
justify-content: center;
-webkit-box-align: center;
-ms-flex-align: center;
-webkit-align-items: center;
align-items: center;
}
`);
cy.getSlide(1).should(($el) => {
expect($el[0].offsetTop).not.to.be.greaterThan(100);
expect($el[0].offsetLeft).to.be.greaterThan(100);
});
cy.getSlide(2).should(($el) => {
expect($el[0].offsetTop).not.to.be.greaterThan(100);
expect($el[0].offsetLeft).to.be.greaterThan(100);
});
cy.getSlide(6).should(($el) => {
expect($el[0].offsetTop).to.be.greaterThan(100);
expect($el[0].offsetLeft).to.be.greaterThan(100);
});
});

it('spaceBetween', () => {
cy.initSwiper({
spaceBetween: 10,
Expand Down
8 changes: 8 additions & 0 deletions playground/core/main.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,3 +19,11 @@ window.swiper = new Swiper({
itemRoleDescriptionMessage: 'slide',
},
});

// uncomment to test SlidesPerColumn module TODO: remove
// window.swiper = new Swiper({
// el: '.swiper-container',
// slidesPerView: 3,
// slidesPerColumn: 2,
// spaceBetween: 30,
// });
1 change: 1 addition & 0 deletions scripts/build-config.js
Original file line number Diff line number Diff line change
Expand Up @@ -19,6 +19,7 @@ module.exports = {
'effect-flip',
'effect-coverflow',
'thumbs',
'slides-per-column',
],
themeColor: '#007aff',
colors: {
Expand Down
2 changes: 0 additions & 2 deletions src/components/core/defaults.js
Original file line number Diff line number Diff line change
Expand Up @@ -56,8 +56,6 @@ export default {
// Slides grid
spaceBetween: 0,
slidesPerView: 1,
slidesPerColumn: 1,
slidesPerColumnFill: 'column',
slidesPerGroup: 1,
slidesPerGroupSkip: 0,
centeredSlides: false,
Expand Down
97 changes: 13 additions & 84 deletions src/components/core/update/updateSlides.js
Original file line number Diff line number Diff line change
Expand Up @@ -63,80 +63,18 @@ export default function updateSlides() {
if (rtl) slides.css({ marginLeft: '', marginTop: '' });
else slides.css({ marginRight: '', marginBottom: '' });

let slidesNumberEvenToRows;
if (params.slidesPerColumn > 1) {
if (
Math.floor(slidesLength / params.slidesPerColumn) ===
slidesLength / swiper.params.slidesPerColumn
) {
slidesNumberEvenToRows = slidesLength;
} else {
slidesNumberEvenToRows =
Math.ceil(slidesLength / params.slidesPerColumn) * params.slidesPerColumn;
}
if (params.slidesPerView !== 'auto' && params.slidesPerColumnFill === 'row') {
slidesNumberEvenToRows = Math.max(
slidesNumberEvenToRows,
params.slidesPerView * params.slidesPerColumn,
);
}
}

// Calc slides
let slideSize;
const slidesPerColumn = params.slidesPerColumn;
const slidesPerRow = slidesNumberEvenToRows / slidesPerColumn;
const numFullColumns = Math.floor(slidesLength / params.slidesPerColumn);
const slidesPerColumnEnabled = params.slidesPerColumn > 1;
if (slidesPerColumnEnabled) {
swiper.slidesPerColumn.updateSlides(slidesLength);
}
for (let i = 0; i < slidesLength; i += 1) {
slideSize = 0;
const slide = slides.eq(i);
if (params.slidesPerColumn > 1) {
// Set slides order
let newSlideOrderIndex;
let column;
let row;
if (params.slidesPerColumnFill === 'row' && params.slidesPerGroup > 1) {
const groupIndex = Math.floor(i / (params.slidesPerGroup * params.slidesPerColumn));
const slideIndexInGroup = i - params.slidesPerColumn * params.slidesPerGroup * groupIndex;
const columnsInGroup =
groupIndex === 0
? params.slidesPerGroup
: Math.min(
Math.ceil(
(slidesLength - groupIndex * slidesPerColumn * params.slidesPerGroup) /
slidesPerColumn,
),
params.slidesPerGroup,
);
row = Math.floor(slideIndexInGroup / columnsInGroup);
column = slideIndexInGroup - row * columnsInGroup + groupIndex * params.slidesPerGroup;

newSlideOrderIndex = column + (row * slidesNumberEvenToRows) / slidesPerColumn;
slide.css({
'-webkit-box-ordinal-group': newSlideOrderIndex,
'-moz-box-ordinal-group': newSlideOrderIndex,
'-ms-flex-order': newSlideOrderIndex,
'-webkit-order': newSlideOrderIndex,
order: newSlideOrderIndex,
});
} else if (params.slidesPerColumnFill === 'column') {
column = Math.floor(i / slidesPerColumn);
row = i - column * slidesPerColumn;
if (column > numFullColumns || (column === numFullColumns && row === slidesPerColumn - 1)) {
row += 1;
if (row >= slidesPerColumn) {
row = 0;
column += 1;
}
}
} else {
row = Math.floor(i / slidesPerRow);
column = i - row * slidesPerRow;
}
slide.css(
getDirectionLabel('margin-top'),
row !== 0 ? params.spaceBetween && `${params.spaceBetween}px` : '',
);
if (slidesPerColumnEnabled) {
swiper.slidesPerColumn.updateSlidesLoop(i, slide, slidesLength, getDirectionLabel);
}
if (slide.css('display') === 'none') continue; // eslint-disable-line

Expand Down Expand Up @@ -232,22 +170,13 @@ export default function updateSlides() {
});
}

if (params.slidesPerColumn > 1) {
swiper.virtualSize = (slideSize + params.spaceBetween) * slidesNumberEvenToRows;
swiper.virtualSize =
Math.ceil(swiper.virtualSize / params.slidesPerColumn) - params.spaceBetween;
$wrapperEl.css({
[getDirectionLabel('width')]: `${swiper.virtualSize + params.spaceBetween}px`,
});
if (params.centeredSlides) {
newSlidesGrid = [];
for (let i = 0; i < snapGrid.length; i += 1) {
let slidesGridItem = snapGrid[i];
if (params.roundLengths) slidesGridItem = Math.floor(slidesGridItem);
if (snapGrid[i] < swiper.virtualSize + snapGrid[0]) newSlidesGrid.push(slidesGridItem);
}
snapGrid = newSlidesGrid;
}
if (slidesPerColumnEnabled) {
snapGrid = swiper.slidesPerColumn.updateSlidesLoop2(
slideSize,
snapGrid,
newSlidesGrid,
getDirectionLabel,
);
}

// Remove last grid elements depending on width
Expand Down
120 changes: 120 additions & 0 deletions src/components/slides-per-column/slides-per-column.js
Original file line number Diff line number Diff line change
@@ -0,0 +1,120 @@
import { bindModuleMethods } from '../../utils/utils';

const SlidesPerColumn = {
getSlidesNumberEvenToRows(slidesLength) {
const swiper = this;
const { params } = swiper;
if (params.slidesPerColumn <= 1) {
return null;
}
const slidesNumberEvenToRows =
Math.floor(slidesLength / params.slidesPerColumn) ===
slidesLength / swiper.params.slidesPerColumn
? slidesLength
: Math.ceil(slidesLength / params.slidesPerColumn) * params.slidesPerColumn;

if (params.slidesPerView !== 'auto' && params.slidesPerColumnFill === 'row') {
return Math.max(slidesNumberEvenToRows, params.slidesPerView * params.slidesPerColumn);
}
return slidesNumberEvenToRows;
},
updateSlides(slidesLength) {
const swiper = this;
const { params } = swiper;

swiper.slidesPerColumn.slidesNumberEvenToRows =
swiper.slidesPerColumn.getSlidesNumberEvenToRows(slidesLength);
swiper.slidesPerColumn.slidesPerRow =
swiper.slidesPerColumn.slidesNumberEvenToRows / params.slidesPerColumn;
swiper.slidesPerColumn.numFullColumns = Math.floor(slidesLength / params.slidesPerColumn);
},
updateSlidesLoop(i, slide, slidesLength, getDirectionLabel) {
const swiper = this;
const { params } = swiper;
const { slidesNumberEvenToRows, slidesPerRow, numFullColumns } = swiper.slidesPerColumn;
// Set slides order
let newSlideOrderIndex;
let column;
let row;
if (params.slidesPerColumnFill === 'row' && params.slidesPerGroup > 1) {
const groupIndex = Math.floor(i / (params.slidesPerGroup * params.slidesPerColumn));
const slideIndexInGroup = i - params.slidesPerColumn * params.slidesPerGroup * groupIndex;
const columnsInGroup =
groupIndex === 0
? params.slidesPerGroup
: Math.min(
Math.ceil(
(slidesLength - groupIndex * params.slidesPerColumn * params.slidesPerGroup) /
params.slidesPerColumn,
),
params.slidesPerGroup,
);
row = Math.floor(slideIndexInGroup / columnsInGroup);
column = slideIndexInGroup - row * columnsInGroup + groupIndex * params.slidesPerGroup;

newSlideOrderIndex = column + (row * slidesNumberEvenToRows) / params.slidesPerColumn;
slide.css({
'-webkit-box-ordinal-group': newSlideOrderIndex,
'-moz-box-ordinal-group': newSlideOrderIndex,
'-ms-flex-order': newSlideOrderIndex,
'-webkit-order': newSlideOrderIndex,
order: newSlideOrderIndex,
});
} else if (params.slidesPerColumnFill === 'column') {
column = Math.floor(i / params.slidesPerColumn);
row = i - column * params.slidesPerColumn;
if (
column > numFullColumns ||
(column === numFullColumns && row === params.slidesPerColumn - 1)
) {
row += 1;
if (row >= params.slidesPerColumn) {
row = 0;
column += 1;
}
}
} else {
row = Math.floor(i / slidesPerRow);
column = i - row * slidesPerRow;
}
slide.css(
getDirectionLabel('margin-top'),
row !== 0 ? params.spaceBetween && `${params.spaceBetween}px` : '',
);
},
updateSlidesLoop2(slideSize, snapGrid, newSlidesGrid, getDirectionLabel) {
const swiper = this;
const { params, $wrapperEl } = swiper;
swiper.virtualSize =
(slideSize + params.spaceBetween) * swiper.slidesPerColumn.slidesNumberEvenToRows;
swiper.virtualSize =
Math.ceil(swiper.virtualSize / params.slidesPerColumn) - params.spaceBetween;
$wrapperEl.css({
[getDirectionLabel('width')]: `${swiper.virtualSize + params.spaceBetween}px`,
});
if (params.centeredSlides) {
newSlidesGrid = [];
for (let i = 0; i < snapGrid.length; i += 1) {
let slidesGridItem = snapGrid[i];
if (params.roundLengths) slidesGridItem = Math.floor(slidesGridItem);
if (snapGrid[i] < swiper.virtualSize + snapGrid[0]) newSlidesGrid.push(slidesGridItem);
}
return newSlidesGrid;
}
return snapGrid;
},
};

export default {
name: 'slides-per-column',
params: {
slidesPerColumn: 1,
slidesPerColumnFill: 'column',
},
create() {
const swiper = this;

bindModuleMethods(swiper, { slidesPerColumn: SlidesPerColumn });
},
on: {},
};

0 comments on commit c469d29

Please sign in to comment.