Skip to content

Commit 985146a

Browse files
committed
Merge branch 'master' of https://github.com/nolimits4web/swiper
2 parents 9dad273 + 3999ddb commit 985146a

File tree

15 files changed

+189
-83
lines changed

15 files changed

+189
-83
lines changed

cypress/integration/modules/a11y.js

Lines changed: 19 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,13 +14,32 @@ context('Core', () => {
1414
cy.getSliderWrapper().should('have.attr', 'aria-live', 'polite');
1515
});
1616

17+
it('paginationBulletMessage', () => {
18+
cy.initSwiper({
19+
pagination: true,
20+
a11y: { paginationBulletMessage: 'Slide to {{index}}' },
21+
});
22+
cy.getPaginationBullet(1).should('have.attr', 'aria-label', 'Slide to 2');
23+
cy.getPaginationBullet(4).should('have.attr', 'aria-label', 'Slide to 5');
24+
cy.getPaginationBullet(9).should('have.attr', 'aria-label', 'Slide to 10');
25+
});
26+
1727
it('should add aria-role-description="slide" to swiper-slide', () => {
1828
cy.initSwiper({
1929
a11y: { itemRoleDescriptionMessage: 'test' },
2030
});
2131
cy.getSlides().should('have.attr', 'aria-role-description', 'test');
2232
});
2333

34+
it('should add aria-label="1 of 10" to swiper-slide', () => {
35+
cy.initSwiper({
36+
a11y: { slideLabelMessage: '{{index}} of {{slidesLength}}' },
37+
});
38+
cy.getSlide(0).should('have.attr', 'aria-label', '1 of 10');
39+
cy.getSlide(4).should('have.attr', 'aria-label', '5 of 10');
40+
cy.getSlide(9).should('have.attr', 'aria-label', '10 of 10');
41+
});
42+
2443
it('should add aria-role-description="slide" to swiper-container', () => {
2544
cy.initSwiper({
2645
a11y: { containerRoleDescriptionMessage: 'test' },

cypress/support/commands.js

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -30,6 +30,7 @@ Cypress.Commands.add('getSliderContainer', { prevSubject: 'optional' }, () => {
3030
Cypress.Commands.add('getSlide', { prevSubject: 'optional' }, (subject, slideIndex) => {
3131
return cy.get(`.swiper-slide:nth-child(${slideIndex + 1})`);
3232
});
33+
3334
Cypress.Commands.add('getSlideContains', { prevSubject: 'optional' }, (subject, content) => {
3435
cy.get('.swiper-container').contains(content);
3536
});
@@ -40,6 +41,10 @@ Cypress.Commands.add('swiperPage', { prevSubject: 'optional' }, () => {
4041
return cy.visit('cypress/test.html');
4142
});
4243

44+
Cypress.Commands.add('getPaginationBullet', { prevSubject: 'optional' }, (subject, bulletIndex) => {
45+
return cy.get(`.swiper-pagination-bullet:nth-child(${bulletIndex + 1})`);
46+
});
47+
4348
Cypress.Commands.add(
4449
'initSwiper',
4550
{ prevSubject: 'optional' },

playground/angular/src/app/app.component.html

Lines changed: 87 additions & 69 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,7 @@
55
[slidesPerView]="3"
66
[spaceBetween]="50"
77
[pagination]="{ type: 'fraction' }"
8-
virtual
8+
[virtual]="true"
99
slideActiveClass="swiper-active whyWouldIuseCustomClass"
1010
[centeredSlides]="true"
1111
navigation
@@ -16,6 +16,22 @@
1616
<ng-template swiperSlide>Slide</ng-template>
1717
<ng-template swiperSlide>Slide</ng-template>
1818
</swiper>
19+
20+
<swiper
21+
#swiperVirtualRef
22+
[slidesPerView]="3"
23+
[spaceBetween]="50"
24+
[pagination]="{ type: 'fraction' }"
25+
[virtual]="true"
26+
[centeredSlides]="true"
27+
navigation
28+
>
29+
<ng-template swiperSlide *ngFor="let slide of slides$ | async; index as i"
30+
>Slide {{ slide }}</ng-template
31+
>
32+
</swiper>
33+
<button (click)="getSlides()">Get slides</button>
34+
1935
<swiper [zoom]="true" [autoplay]="true">
2036
<ng-template swiperSlide class="custom-class" [zoom]="true">
2137
<img src="https://swiperjs.com/demos/images/nature-1.jpg" />
@@ -73,87 +89,89 @@
7389
<button (click)="exampleConfig = { slidesPerView: 2 }">changeConfig</button>
7490

7591
{{ exampleConfig | json }}
92+
</div>
93+
<div>
7694
<swiper
7795
#swiper
7896
[slidesPerView]="1"
7997
[centeredSlides]="true"
80-
[navigation]="{ prevEl: '.swiper-navigation-prev', nextEl: '.swiper-navigation-next' }"
98+
[navigation]="{ prevEl: prevEl, nextEl: nextEl }"
8199
[pagination]="pagination"
82100
>
83101
<ng-template swiperSlide *ngFor="let slide of slides2; index as i">
84102
{{ i }} - {{ slide }}
85103
</ng-template>
86104
</swiper>
87-
<button type="button" class="swiper-navigation-prev">&lt;</button>
88-
<button type="button" class="swiper-navigation-next">&gt;</button>
105+
<button type="button" #nextEl class="swiper-navigation-prev">&lt;</button>
106+
<button type="button" #prevEl class="swiper-navigation-next">&gt;</button>
89107
<hr />
90108
<button (click)="replaceSlides()">replace slides</button>
91109
<button (click)="togglePagination()">Toggle pagination</button>
92110
</div>
93111
<div>
94-
<swiper
95-
[slidesPerView]="1"
96-
[spaceBetween]="50"
97-
[navigation]="true"
98-
[pagination]="{ clickable: true }"
99-
[thumbs]="{ swiper: thumbsSwiper }"
100-
>
101-
<ng-template swiperSlide>Slide 1</ng-template>
102-
<ng-template swiperSlide>Slide 2</ng-template>
103-
<ng-template swiperSlide>Slide 3</ng-template>
104-
<ng-template swiperSlide>Slide 4</ng-template>
105-
<ng-template swiperSlide>Slide 5</ng-template>
106-
<ng-template swiperSlide>Slide 6</ng-template>
107-
</swiper>
108-
<swiper
109-
[slidesPerView]="3"
110-
[spaceBetween]="50"
111-
(swiper)="setThumbsSwiper($event)"
112-
[navigation]="{}"
113-
[pagination]="{ clickable: true }"
114-
[scrollbar]="{ draggable: true }"
115-
[watchSlidesVisibility]="true"
116-
[watchSlidesProgress]="true"
117-
>
118-
<ng-template swiperSlide>Slide 1</ng-template>
119-
<ng-template swiperSlide>Slide 2</ng-template>
120-
<ng-template swiperSlide>Slide 3</ng-template>
121-
<ng-template swiperSlide>Slide 4</ng-template>
122-
<ng-template swiperSlide>Slide 5</ng-template>
123-
<ng-template swiperSlide>Slide 6</ng-template>
124-
</swiper>
125-
</div>
126-
<div>
127-
<swiper
128-
[slidesPerView]="1"
129-
[spaceBetween]="50"
130-
[navigation]="true"
131-
[pagination]="{ clickable: true }"
132-
[controller]="{ control: controlledSwiper }"
133-
>
134-
<ng-template swiperSlide>Slide 1</ng-template>
135-
<ng-template swiperSlide>Slide 2</ng-template>
136-
<ng-template swiperSlide>Slide 3</ng-template>
137-
<ng-template swiperSlide>Slide 4</ng-template>
138-
<ng-template swiperSlide>Slide 5</ng-template>
139-
<ng-template swiperSlide>Slide 6</ng-template>
140-
</swiper>
141-
<swiper
142-
[slidesPerView]="3"
143-
[spaceBetween]="50"
144-
(swiper)="setControlledSwiper($event)"
145-
[navigation]="{}"
146-
[pagination]="{ clickable: true }"
147-
[scrollbar]="{ draggable: true }"
148-
[watchSlidesVisibility]="true"
149-
[watchSlidesProgress]="true"
150-
>
151-
<ng-template swiperSlide>Slide 1</ng-template>
152-
<ng-template swiperSlide>Slide 2</ng-template>
153-
<ng-template swiperSlide>Slide 3</ng-template>
154-
<ng-template swiperSlide>Slide 4</ng-template>
155-
<ng-template swiperSlide>Slide 5</ng-template>
156-
<ng-template swiperSlide>Slide 6</ng-template>
157-
</swiper>
158-
</div>
112+
<swiper
113+
[slidesPerView]="1"
114+
[spaceBetween]="50"
115+
[navigation]="true"
116+
[pagination]="{ clickable: true }"
117+
[thumbs]="{ swiper: thumbsSwiper }"
118+
>
119+
<ng-template swiperSlide>Slide 1</ng-template>
120+
<ng-template swiperSlide>Slide 2</ng-template>
121+
<ng-template swiperSlide>Slide 3</ng-template>
122+
<ng-template swiperSlide>Slide 4</ng-template>
123+
<ng-template swiperSlide>Slide 5</ng-template>
124+
<ng-template swiperSlide>Slide 6</ng-template>
125+
</swiper>
126+
<swiper
127+
[slidesPerView]="3"
128+
[spaceBetween]="50"
129+
(swiper)="setThumbsSwiper($event)"
130+
[navigation]="{}"
131+
[pagination]="{ clickable: true }"
132+
[scrollbar]="{ draggable: true }"
133+
[watchSlidesVisibility]="true"
134+
[watchSlidesProgress]="true"
135+
>
136+
<ng-template swiperSlide>Slide 1</ng-template>
137+
<ng-template swiperSlide>Slide 2</ng-template>
138+
<ng-template swiperSlide>Slide 3</ng-template>
139+
<ng-template swiperSlide>Slide 4</ng-template>
140+
<ng-template swiperSlide>Slide 5</ng-template>
141+
<ng-template swiperSlide>Slide 6</ng-template>
142+
</swiper>
143+
</div>
144+
<div>
145+
<swiper
146+
[slidesPerView]="1"
147+
[spaceBetween]="50"
148+
[navigation]="true"
149+
[pagination]="{ clickable: true }"
150+
[controller]="{ control: controlledSwiper }"
151+
>
152+
<ng-template swiperSlide>Slide 1</ng-template>
153+
<ng-template swiperSlide>Slide 2</ng-template>
154+
<ng-template swiperSlide>Slide 3</ng-template>
155+
<ng-template swiperSlide>Slide 4</ng-template>
156+
<ng-template swiperSlide>Slide 5</ng-template>
157+
<ng-template swiperSlide>Slide 6</ng-template>
158+
</swiper>
159+
<swiper
160+
[slidesPerView]="3"
161+
[spaceBetween]="50"
162+
(swiper)="setControlledSwiper($event)"
163+
[navigation]="{}"
164+
[pagination]="{ clickable: true }"
165+
[scrollbar]="{ draggable: true }"
166+
[watchSlidesVisibility]="true"
167+
[watchSlidesProgress]="true"
168+
>
169+
<ng-template swiperSlide>Slide 1</ng-template>
170+
<ng-template swiperSlide>Slide 2</ng-template>
171+
<ng-template swiperSlide>Slide 3</ng-template>
172+
<ng-template swiperSlide>Slide 4</ng-template>
173+
<ng-template swiperSlide>Slide 5</ng-template>
174+
<ng-template swiperSlide>Slide 6</ng-template>
175+
</swiper>
176+
</div>
159177
</main>

playground/angular/src/app/app.component.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
11
import { ChangeDetectorRef, Component, ViewChild } from '@angular/core';
2+
import { BehaviorSubject } from 'rxjs';
23
import { SwiperComponent } from 'src/angular/src/public-api';
34
import SwiperCore, {
45
Navigation,
@@ -34,9 +35,14 @@ export class AppComponent {
3435

3536
show: boolean;
3637
thumbs: any;
38+
slides$ = new BehaviorSubject<string[]>(['']);
3739
constructor(private cd: ChangeDetectorRef) {}
3840
ngOnInit() {}
3941

42+
getSlides() {
43+
this.slides$.next(Array.from({ length: 600 }).map((el, index) => `Slide ${index + 1}`));
44+
}
45+
4046
thumbsSwiper: any;
4147
setThumbsSwiper(swiper) {
4248
this.thumbsSwiper = swiper;

src/angular/src/swiper.component.ts

Lines changed: 17 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -164,7 +164,10 @@ export class SwiperComponent implements OnInit {
164164
});
165165
if (
166166
typeof this._navigation !== 'boolean' &&
167-
(typeof this._navigation?.nextEl === 'string' || typeof this._navigation?.prevEl === 'string')
167+
(typeof this._navigation?.nextEl === 'string' ||
168+
typeof this._navigation?.prevEl === 'string' ||
169+
typeof this._navigation?.nextEl === 'object' ||
170+
typeof this._navigation?.prevEl === 'object')
168171
) {
169172
this.showNavigation = false;
170173
}
@@ -181,7 +184,10 @@ export class SwiperComponent implements OnInit {
181184
this._pagination = setProperty(val, {
182185
el: current || null,
183186
});
184-
if (typeof this._pagination !== 'boolean' && typeof this._pagination?.el === 'string') {
187+
if (
188+
typeof this._pagination !== 'boolean' &&
189+
(typeof this._pagination?.el === 'string' || typeof this._pagination?.el === 'object')
190+
) {
185191
this.showPagination = false;
186192
}
187193
}
@@ -197,7 +203,10 @@ export class SwiperComponent implements OnInit {
197203
this._scrollbar = setProperty(val, {
198204
el: current || null,
199205
});
200-
if (typeof this._scrollbar !== 'boolean' && typeof this._scrollbar?.el === 'string') {
206+
if (
207+
typeof this._scrollbar !== 'boolean' &&
208+
(typeof this._scrollbar?.el === 'string' || typeof this._scrollbar?.el === 'object')
209+
) {
201210
this.showScrollbar = false;
202211
}
203212
}
@@ -471,6 +480,11 @@ export class SwiperComponent implements OnInit {
471480
if (!this.virtual) {
472481
this.prependSlides = of(this.slides.slice(this.slides.length - this.loopedSlides));
473482
this.appendSlides = of(this.slides.slice(0, this.loopedSlides));
483+
} else if (this.swiperRef && this.swiperRef.virtual) {
484+
this._ngZone.runOutsideAngular(() => {
485+
this.swiperRef.virtual.slides = this.slides;
486+
this.swiperRef.virtual.update(true);
487+
});
474488
}
475489
this._changeDetectorRef.detectChanges();
476490
};

src/angular/src/utils/utils.ts

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
export function isObject(o) {
2-
return typeof o === 'object' && o !== null && o.constructor && o.constructor === Object;
2+
return (
3+
typeof o === 'object' &&
4+
o !== null &&
5+
o.constructor &&
6+
Object.prototype.toString.call(o).slice(8, -1) === 'Object'
7+
);
38
}
49

510
export function extend(target, src) {

src/components/a11y/a11y.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,10 @@ const A11y = {
167167
swiper.a11y.addElRole($(swiper.slides), 'group');
168168
swiper.slides.each((slideEl) => {
169169
const $slideEl = $(slideEl);
170-
swiper.a11y.addElLabel($slideEl, `${$slideEl.index() + 1} / ${swiper.slides.length}`);
170+
const ariaLabelMessage = params.slideLabelMessage
171+
.replace(/\{\{index\}\}/, $slideEl.index() + 1)
172+
.replace(/\{\{slidesLength\}\}/, swiper.slides.length);
173+
swiper.a11y.addElLabel($slideEl, ariaLabelMessage);
171174
});
172175

173176
// Navigation
@@ -259,6 +262,7 @@ export default {
259262
firstSlideMessage: 'This is the first slide',
260263
lastSlideMessage: 'This is the last slide',
261264
paginationBulletMessage: 'Go to slide {{index}}',
265+
slideLabelMessage: '{{index}} / {{slidesLength}}',
262266
containerMessage: null,
263267
containerRoleDescriptionMessage: null,
264268
itemRoleDescriptionMessage: null,

src/components/core/core-class.js

Lines changed: 5 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -49,7 +49,11 @@ class Swiper {
4949
constructor(...args) {
5050
let el;
5151
let params;
52-
if (args.length === 1 && args[0].constructor && args[0].constructor === Object) {
52+
if (
53+
args.length === 1 &&
54+
args[0].constructor &&
55+
Object.prototype.toString.call(args[0]).slice(8, -1) === 'Object'
56+
) {
5357
params = args[0];
5458
} else {
5559
[el, params] = args;

src/components/core/update/updateSlides.js

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -167,7 +167,7 @@ export default function updateSlides() {
167167
const paddingRight = getDirectionPropertyValue(slideStyles, 'padding-right');
168168
const marginLeft = getDirectionPropertyValue(slideStyles, 'margin-left');
169169
const marginRight = getDirectionPropertyValue(slideStyles, 'margin-right');
170-
const boxSizing = slideStyles.getPropertyValue(slideStyles, 'box-sizing');
170+
const boxSizing = slideStyles.getPropertyValue('box-sizing');
171171
if (boxSizing && boxSizing === 'border-box') {
172172
slideSize = width + marginLeft + marginRight;
173173
} else {

src/components/keyboard/keyboard.js

Lines changed: 7 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -56,15 +56,19 @@ const Keyboard = {
5656
) {
5757
return undefined;
5858
}
59+
60+
const $el = swiper.$el;
61+
const swiperWidth = $el[0].clientWidth;
62+
const swiperHeight = $el[0].clientHeight;
5963
const windowWidth = window.innerWidth;
6064
const windowHeight = window.innerHeight;
6165
const swiperOffset = swiper.$el.offset();
6266
if (rtl) swiperOffset.left -= swiper.$el[0].scrollLeft;
6367
const swiperCoord = [
6468
[swiperOffset.left, swiperOffset.top],
65-
[swiperOffset.left + swiper.width, swiperOffset.top],
66-
[swiperOffset.left, swiperOffset.top + swiper.height],
67-
[swiperOffset.left + swiper.width, swiperOffset.top + swiper.height],
69+
[swiperOffset.left + swiperWidth, swiperOffset.top],
70+
[swiperOffset.left, swiperOffset.top + swiperHeight],
71+
[swiperOffset.left + swiperWidth, swiperOffset.top + swiperHeight],
6872
];
6973
for (let i = 0; i < swiperCoord.length; i += 1) {
7074
const point = swiperCoord[i];

src/react/utils.js

Lines changed: 6 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,5 +1,10 @@
11
function isObject(o) {
2-
return typeof o === 'object' && o !== null && o.constructor && o.constructor === Object;
2+
return (
3+
typeof o === 'object' &&
4+
o !== null &&
5+
o.constructor &&
6+
Object.prototype.toString.call(o).slice(8, -1) === 'Object'
7+
);
38
}
49

510
function extend(target, src) {

0 commit comments

Comments
 (0)