UNPKG

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