1 | import $ from '../../shared/dom.js';
|
2 | import classesToSelector from '../../shared/classes-to-selector.js';
|
3 | import createElementIfNotDefined from '../../shared/create-element-if-not-defined.js';
|
4 | export default function Pagination({
|
5 | swiper,
|
6 | extendParams,
|
7 | on,
|
8 | emit
|
9 | }) {
|
10 | const pfx = 'swiper-pagination';
|
11 | extendParams({
|
12 | pagination: {
|
13 | el: null,
|
14 | bulletElement: 'span',
|
15 | clickable: false,
|
16 | hideOnClick: false,
|
17 | renderBullet: null,
|
18 | renderProgressbar: null,
|
19 | renderFraction: null,
|
20 | renderCustom: null,
|
21 | progressbarOpposite: false,
|
22 | type: 'bullets',
|
23 |
|
24 | dynamicBullets: false,
|
25 | dynamicMainBullets: 1,
|
26 | formatFractionCurrent: number => number,
|
27 | formatFractionTotal: number => number,
|
28 | bulletClass: `${pfx}-bullet`,
|
29 | bulletActiveClass: `${pfx}-bullet-active`,
|
30 | modifierClass: `${pfx}-`,
|
31 | currentClass: `${pfx}-current`,
|
32 | totalClass: `${pfx}-total`,
|
33 | hiddenClass: `${pfx}-hidden`,
|
34 | progressbarFillClass: `${pfx}-progressbar-fill`,
|
35 | progressbarOppositeClass: `${pfx}-progressbar-opposite`,
|
36 | clickableClass: `${pfx}-clickable`,
|
37 | lockClass: `${pfx}-lock`,
|
38 | horizontalClass: `${pfx}-horizontal`,
|
39 | verticalClass: `${pfx}-vertical`
|
40 | }
|
41 | });
|
42 | swiper.pagination = {
|
43 | el: null,
|
44 | $el: null,
|
45 | bullets: []
|
46 | };
|
47 | let bulletSize;
|
48 | let dynamicBulletIndex = 0;
|
49 |
|
50 | function isPaginationDisabled() {
|
51 | return !swiper.params.pagination.el || !swiper.pagination.el || !swiper.pagination.$el || swiper.pagination.$el.length === 0;
|
52 | }
|
53 |
|
54 | function setSideBullets($bulletEl, position) {
|
55 | const {
|
56 | bulletActiveClass
|
57 | } = swiper.params.pagination;
|
58 | $bulletEl[position]().addClass(`${bulletActiveClass}-${position}`)[position]().addClass(`${bulletActiveClass}-${position}-${position}`);
|
59 | }
|
60 |
|
61 | function update() {
|
62 |
|
63 | const rtl = swiper.rtl;
|
64 | const params = swiper.params.pagination;
|
65 | if (isPaginationDisabled()) return;
|
66 | const slidesLength = swiper.virtual && swiper.params.virtual.enabled ? swiper.virtual.slides.length : swiper.slides.length;
|
67 | const $el = swiper.pagination.$el;
|
68 |
|
69 | let current;
|
70 | const total = swiper.params.loop ? Math.ceil((slidesLength - swiper.loopedSlides * 2) / swiper.params.slidesPerGroup) : swiper.snapGrid.length;
|
71 |
|
72 | if (swiper.params.loop) {
|
73 | current = Math.ceil((swiper.activeIndex - swiper.loopedSlides) / swiper.params.slidesPerGroup);
|
74 |
|
75 | if (current > slidesLength - 1 - swiper.loopedSlides * 2) {
|
76 | current -= slidesLength - swiper.loopedSlides * 2;
|
77 | }
|
78 |
|
79 | if (current > total - 1) current -= total;
|
80 | if (current < 0 && swiper.params.paginationType !== 'bullets') current = total + current;
|
81 | } else if (typeof swiper.snapIndex !== 'undefined') {
|
82 | current = swiper.snapIndex;
|
83 | } else {
|
84 | current = swiper.activeIndex || 0;
|
85 | }
|
86 |
|
87 |
|
88 | if (params.type === 'bullets' && swiper.pagination.bullets && swiper.pagination.bullets.length > 0) {
|
89 | const bullets = swiper.pagination.bullets;
|
90 | let firstIndex;
|
91 | let lastIndex;
|
92 | let midIndex;
|
93 |
|
94 | if (params.dynamicBullets) {
|
95 | bulletSize = bullets.eq(0)[swiper.isHorizontal() ? 'outerWidth' : 'outerHeight'](true);
|
96 | $el.css(swiper.isHorizontal() ? 'width' : 'height', `${bulletSize * (params.dynamicMainBullets + 4)}px`);
|
97 |
|
98 | if (params.dynamicMainBullets > 1 && swiper.previousIndex !== undefined) {
|
99 | dynamicBulletIndex += current - swiper.previousIndex;
|
100 |
|
101 | if (dynamicBulletIndex > params.dynamicMainBullets - 1) {
|
102 | dynamicBulletIndex = params.dynamicMainBullets - 1;
|
103 | } else if (dynamicBulletIndex < 0) {
|
104 | dynamicBulletIndex = 0;
|
105 | }
|
106 | }
|
107 |
|
108 | firstIndex = current - dynamicBulletIndex;
|
109 | lastIndex = firstIndex + (Math.min(bullets.length, params.dynamicMainBullets) - 1);
|
110 | midIndex = (lastIndex + firstIndex) / 2;
|
111 | }
|
112 |
|
113 | bullets.removeClass(['', '-next', '-next-next', '-prev', '-prev-prev', '-main'].map(suffix => `${params.bulletActiveClass}${suffix}`).join(' '));
|
114 |
|
115 | if ($el.length > 1) {
|
116 | bullets.each(bullet => {
|
117 | const $bullet = $(bullet);
|
118 | const bulletIndex = $bullet.index();
|
119 |
|
120 | if (bulletIndex === current) {
|
121 | $bullet.addClass(params.bulletActiveClass);
|
122 | }
|
123 |
|
124 | if (params.dynamicBullets) {
|
125 | if (bulletIndex >= firstIndex && bulletIndex <= lastIndex) {
|
126 | $bullet.addClass(`${params.bulletActiveClass}-main`);
|
127 | }
|
128 |
|
129 | if (bulletIndex === firstIndex) {
|
130 | setSideBullets($bullet, 'prev');
|
131 | }
|
132 |
|
133 | if (bulletIndex === lastIndex) {
|
134 | setSideBullets($bullet, 'next');
|
135 | }
|
136 | }
|
137 | });
|
138 | } else {
|
139 | const $bullet = bullets.eq(current);
|
140 | const bulletIndex = $bullet.index();
|
141 | $bullet.addClass(params.bulletActiveClass);
|
142 |
|
143 | if (params.dynamicBullets) {
|
144 | const $firstDisplayedBullet = bullets.eq(firstIndex);
|
145 | const $lastDisplayedBullet = bullets.eq(lastIndex);
|
146 |
|
147 | for (let i = firstIndex; i <= lastIndex; i += 1) {
|
148 | bullets.eq(i).addClass(`${params.bulletActiveClass}-main`);
|
149 | }
|
150 |
|
151 | if (swiper.params.loop) {
|
152 | if (bulletIndex >= bullets.length - params.dynamicMainBullets) {
|
153 | for (let i = params.dynamicMainBullets; i >= 0; i -= 1) {
|
154 | bullets.eq(bullets.length - i).addClass(`${params.bulletActiveClass}-main`);
|
155 | }
|
156 |
|
157 | bullets.eq(bullets.length - params.dynamicMainBullets - 1).addClass(`${params.bulletActiveClass}-prev`);
|
158 | } else {
|
159 | setSideBullets($firstDisplayedBullet, 'prev');
|
160 | setSideBullets($lastDisplayedBullet, 'next');
|
161 | }
|
162 | } else {
|
163 | setSideBullets($firstDisplayedBullet, 'prev');
|
164 | setSideBullets($lastDisplayedBullet, 'next');
|
165 | }
|
166 | }
|
167 | }
|
168 |
|
169 | if (params.dynamicBullets) {
|
170 | const dynamicBulletsLength = Math.min(bullets.length, params.dynamicMainBullets + 4);
|
171 | const bulletsOffset = (bulletSize * dynamicBulletsLength - bulletSize) / 2 - midIndex * bulletSize;
|
172 | const offsetProp = rtl ? 'right' : 'left';
|
173 | bullets.css(swiper.isHorizontal() ? offsetProp : 'top', `${bulletsOffset}px`);
|
174 | }
|
175 | }
|
176 |
|
177 | if (params.type === 'fraction') {
|
178 | $el.find(classesToSelector(params.currentClass)).text(params.formatFractionCurrent(current + 1));
|
179 | $el.find(classesToSelector(params.totalClass)).text(params.formatFractionTotal(total));
|
180 | }
|
181 |
|
182 | if (params.type === 'progressbar') {
|
183 | let progressbarDirection;
|
184 |
|
185 | if (params.progressbarOpposite) {
|
186 | progressbarDirection = swiper.isHorizontal() ? 'vertical' : 'horizontal';
|
187 | } else {
|
188 | progressbarDirection = swiper.isHorizontal() ? 'horizontal' : 'vertical';
|
189 | }
|
190 |
|
191 | const scale = (current + 1) / total;
|
192 | let scaleX = 1;
|
193 | let scaleY = 1;
|
194 |
|
195 | if (progressbarDirection === 'horizontal') {
|
196 | scaleX = scale;
|
197 | } else {
|
198 | scaleY = scale;
|
199 | }
|
200 |
|
201 | $el.find(classesToSelector(params.progressbarFillClass)).transform(`translate3d(0,0,0) scaleX(${scaleX}) scaleY(${scaleY})`).transition(swiper.params.speed);
|
202 | }
|
203 |
|
204 | if (params.type === 'custom' && params.renderCustom) {
|
205 | $el.html(params.renderCustom(swiper, current + 1, total));
|
206 | emit('paginationRender', $el[0]);
|
207 | } else {
|
208 | emit('paginationUpdate', $el[0]);
|
209 | }
|
210 |
|
211 | if (swiper.params.watchOverflow && swiper.enabled) {
|
212 | $el[swiper.isLocked ? 'addClass' : 'removeClass'](params.lockClass);
|
213 | }
|
214 | }
|
215 |
|
216 | function render() {
|
217 |
|
218 | const params = swiper.params.pagination;
|
219 | if (isPaginationDisabled()) return;
|
220 | const slidesLength = swiper.virtual && swiper.params.virtual.enabled ? swiper.virtual.slides.length : swiper.slides.length;
|
221 | const $el = swiper.pagination.$el;
|
222 | let paginationHTML = '';
|
223 |
|
224 | if (params.type === 'bullets') {
|
225 | let numberOfBullets = swiper.params.loop ? Math.ceil((slidesLength - swiper.loopedSlides * 2) / swiper.params.slidesPerGroup) : swiper.snapGrid.length;
|
226 |
|
227 | if (swiper.params.freeMode && swiper.params.freeMode.enabled && !swiper.params.loop && numberOfBullets > slidesLength) {
|
228 | numberOfBullets = slidesLength;
|
229 | }
|
230 |
|
231 | for (let i = 0; i < numberOfBullets; i += 1) {
|
232 | if (params.renderBullet) {
|
233 | paginationHTML += params.renderBullet.call(swiper, i, params.bulletClass);
|
234 | } else {
|
235 | paginationHTML += `<${params.bulletElement} class="${params.bulletClass}"></${params.bulletElement}>`;
|
236 | }
|
237 | }
|
238 |
|
239 | $el.html(paginationHTML);
|
240 | swiper.pagination.bullets = $el.find(classesToSelector(params.bulletClass));
|
241 | }
|
242 |
|
243 | if (params.type === 'fraction') {
|
244 | if (params.renderFraction) {
|
245 | paginationHTML = params.renderFraction.call(swiper, params.currentClass, params.totalClass);
|
246 | } else {
|
247 | paginationHTML = `<span class="${params.currentClass}"></span>` + ' / ' + `<span class="${params.totalClass}"></span>`;
|
248 | }
|
249 |
|
250 | $el.html(paginationHTML);
|
251 | }
|
252 |
|
253 | if (params.type === 'progressbar') {
|
254 | if (params.renderProgressbar) {
|
255 | paginationHTML = params.renderProgressbar.call(swiper, params.progressbarFillClass);
|
256 | } else {
|
257 | paginationHTML = `<span class="${params.progressbarFillClass}"></span>`;
|
258 | }
|
259 |
|
260 | $el.html(paginationHTML);
|
261 | }
|
262 |
|
263 | if (params.type !== 'custom') {
|
264 | emit('paginationRender', swiper.pagination.$el[0]);
|
265 | }
|
266 | }
|
267 |
|
268 | function init() {
|
269 | swiper.params.pagination = createElementIfNotDefined(swiper, swiper.originalParams.pagination, swiper.params.pagination, {
|
270 | el: 'swiper-pagination'
|
271 | });
|
272 | const params = swiper.params.pagination;
|
273 | if (!params.el) return;
|
274 | let $el = $(params.el);
|
275 | if ($el.length === 0) return;
|
276 |
|
277 | if (swiper.params.uniqueNavElements && typeof params.el === 'string' && $el.length > 1) {
|
278 | $el = swiper.$el.find(params.el);
|
279 |
|
280 | if ($el.length > 1) {
|
281 | $el = $el.filter(el => {
|
282 | if ($(el).parents('.swiper')[0] !== swiper.el) return false;
|
283 | return true;
|
284 | });
|
285 | }
|
286 | }
|
287 |
|
288 | if (params.type === 'bullets' && params.clickable) {
|
289 | $el.addClass(params.clickableClass);
|
290 | }
|
291 |
|
292 | $el.addClass(params.modifierClass + params.type);
|
293 | $el.addClass(params.modifierClass + swiper.params.direction);
|
294 |
|
295 | if (params.type === 'bullets' && params.dynamicBullets) {
|
296 | $el.addClass(`${params.modifierClass}${params.type}-dynamic`);
|
297 | dynamicBulletIndex = 0;
|
298 |
|
299 | if (params.dynamicMainBullets < 1) {
|
300 | params.dynamicMainBullets = 1;
|
301 | }
|
302 | }
|
303 |
|
304 | if (params.type === 'progressbar' && params.progressbarOpposite) {
|
305 | $el.addClass(params.progressbarOppositeClass);
|
306 | }
|
307 |
|
308 | if (params.clickable) {
|
309 | $el.on('click', classesToSelector(params.bulletClass), function onClick(e) {
|
310 | e.preventDefault();
|
311 | let index = $(this).index() * swiper.params.slidesPerGroup;
|
312 | if (swiper.params.loop) index += swiper.loopedSlides;
|
313 | swiper.slideTo(index);
|
314 | });
|
315 | }
|
316 |
|
317 | Object.assign(swiper.pagination, {
|
318 | $el,
|
319 | el: $el[0]
|
320 | });
|
321 |
|
322 | if (!swiper.enabled) {
|
323 | $el.addClass(params.lockClass);
|
324 | }
|
325 | }
|
326 |
|
327 | function destroy() {
|
328 | const params = swiper.params.pagination;
|
329 | if (isPaginationDisabled()) return;
|
330 | const $el = swiper.pagination.$el;
|
331 | $el.removeClass(params.hiddenClass);
|
332 | $el.removeClass(params.modifierClass + params.type);
|
333 | $el.removeClass(params.modifierClass + swiper.params.direction);
|
334 | if (swiper.pagination.bullets && swiper.pagination.bullets.removeClass) swiper.pagination.bullets.removeClass(params.bulletActiveClass);
|
335 |
|
336 | if (params.clickable) {
|
337 | $el.off('click', classesToSelector(params.bulletClass));
|
338 | }
|
339 | }
|
340 |
|
341 | on('init', () => {
|
342 | init();
|
343 | render();
|
344 | update();
|
345 | });
|
346 | on('activeIndexChange', () => {
|
347 | if (swiper.params.loop) {
|
348 | update();
|
349 | } else if (typeof swiper.snapIndex === 'undefined') {
|
350 | update();
|
351 | }
|
352 | });
|
353 | on('snapIndexChange', () => {
|
354 | if (!swiper.params.loop) {
|
355 | update();
|
356 | }
|
357 | });
|
358 | on('slidesLengthChange', () => {
|
359 | if (swiper.params.loop) {
|
360 | render();
|
361 | update();
|
362 | }
|
363 | });
|
364 | on('snapGridLengthChange', () => {
|
365 | if (!swiper.params.loop) {
|
366 | render();
|
367 | update();
|
368 | }
|
369 | });
|
370 | on('destroy', () => {
|
371 | destroy();
|
372 | });
|
373 | on('enable disable', () => {
|
374 | const {
|
375 | $el
|
376 | } = swiper.pagination;
|
377 |
|
378 | if ($el) {
|
379 | $el[swiper.enabled ? 'removeClass' : 'addClass'](swiper.params.pagination.lockClass);
|
380 | }
|
381 | });
|
382 | on('lock unlock', () => {
|
383 | update();
|
384 | });
|
385 | on('click', (_s, e) => {
|
386 | const targetEl = e.target;
|
387 | const {
|
388 | $el
|
389 | } = swiper.pagination;
|
390 |
|
391 | if (swiper.params.pagination.el && swiper.params.pagination.hideOnClick && $el.length > 0 && !$(targetEl).hasClass(swiper.params.pagination.bulletClass)) {
|
392 | if (swiper.navigation && (swiper.navigation.nextEl && targetEl === swiper.navigation.nextEl || swiper.navigation.prevEl && targetEl === swiper.navigation.prevEl)) return;
|
393 | const isHidden = $el.hasClass(swiper.params.pagination.hiddenClass);
|
394 |
|
395 | if (isHidden === true) {
|
396 | emit('paginationShow');
|
397 | } else {
|
398 | emit('paginationHide');
|
399 | }
|
400 |
|
401 | $el.toggleClass(swiper.params.pagination.hiddenClass);
|
402 | }
|
403 | });
|
404 | Object.assign(swiper.pagination, {
|
405 | render,
|
406 | update,
|
407 | init,
|
408 | destroy
|
409 | });
|
410 | } |
\ | No newline at end of file |