swiper
Version:
Most modern mobile touch slider and framework with hardware accelerated transitions
291 lines (255 loc) • 9.55 kB
JavaScript
function _extends() { _extends = Object.assign || function (target) { for (var i = 1; i < arguments.length; i++) { var source = arguments[i]; for (var key in source) { if (Object.prototype.hasOwnProperty.call(source, key)) { target[key] = source[key]; } } } return target; }; return _extends.apply(this, arguments); }
import $ from '../../utils/dom';
import { bindModuleMethods, classesToSelector } from '../../utils/utils';
var A11y = {
getRandomNumber: function getRandomNumber(size) {
if (size === void 0) {
size = 16;
}
var randomChar = function randomChar() {
return Math.round(16 * Math.random()).toString(16);
};
return 'x'.repeat(size).replace(/x/g, randomChar);
},
makeElFocusable: function makeElFocusable($el) {
$el.attr('tabIndex', '0');
return $el;
},
makeElNotFocusable: function makeElNotFocusable($el) {
$el.attr('tabIndex', '-1');
return $el;
},
addElRole: function addElRole($el, role) {
$el.attr('role', role);
return $el;
},
addElRoleDescription: function addElRoleDescription($el, description) {
$el.attr('aria-roledescription', description);
return $el;
},
addElControls: function addElControls($el, controls) {
$el.attr('aria-controls', controls);
return $el;
},
addElLabel: function addElLabel($el, label) {
$el.attr('aria-label', label);
return $el;
},
addElId: function addElId($el, id) {
$el.attr('id', id);
return $el;
},
addElLive: function addElLive($el, live) {
$el.attr('aria-live', live);
return $el;
},
disableEl: function disableEl($el) {
$el.attr('aria-disabled', true);
return $el;
},
enableEl: function enableEl($el) {
$el.attr('aria-disabled', false);
return $el;
},
onEnterOrSpaceKey: function onEnterOrSpaceKey(e) {
if (e.keyCode !== 13 && e.keyCode !== 32) return;
var swiper = this;
var params = swiper.params.a11y;
var $targetEl = $(e.target);
if (swiper.navigation && swiper.navigation.$nextEl && $targetEl.is(swiper.navigation.$nextEl)) {
if (!(swiper.isEnd && !swiper.params.loop)) {
swiper.slideNext();
}
if (swiper.isEnd) {
swiper.a11y.notify(params.lastSlideMessage);
} else {
swiper.a11y.notify(params.nextSlideMessage);
}
}
if (swiper.navigation && swiper.navigation.$prevEl && $targetEl.is(swiper.navigation.$prevEl)) {
if (!(swiper.isBeginning && !swiper.params.loop)) {
swiper.slidePrev();
}
if (swiper.isBeginning) {
swiper.a11y.notify(params.firstSlideMessage);
} else {
swiper.a11y.notify(params.prevSlideMessage);
}
}
if (swiper.pagination && $targetEl.is(classesToSelector(swiper.params.pagination.bulletClass))) {
$targetEl[0].click();
}
},
notify: function notify(message) {
var swiper = this;
var notification = swiper.a11y.liveRegion;
if (notification.length === 0) return;
notification.html('');
notification.html(message);
},
updateNavigation: function updateNavigation() {
var swiper = this;
if (swiper.params.loop || !swiper.navigation) return;
var _swiper$navigation = swiper.navigation,
$nextEl = _swiper$navigation.$nextEl,
$prevEl = _swiper$navigation.$prevEl;
if ($prevEl && $prevEl.length > 0) {
if (swiper.isBeginning) {
swiper.a11y.disableEl($prevEl);
swiper.a11y.makeElNotFocusable($prevEl);
} else {
swiper.a11y.enableEl($prevEl);
swiper.a11y.makeElFocusable($prevEl);
}
}
if ($nextEl && $nextEl.length > 0) {
if (swiper.isEnd) {
swiper.a11y.disableEl($nextEl);
swiper.a11y.makeElNotFocusable($nextEl);
} else {
swiper.a11y.enableEl($nextEl);
swiper.a11y.makeElFocusable($nextEl);
}
}
},
updatePagination: function updatePagination() {
var swiper = this;
var params = swiper.params.a11y;
if (swiper.pagination && swiper.params.pagination.clickable && swiper.pagination.bullets && swiper.pagination.bullets.length) {
swiper.pagination.bullets.each(function (bulletEl) {
var $bulletEl = $(bulletEl);
swiper.a11y.makeElFocusable($bulletEl);
if (!swiper.params.pagination.renderBullet) {
swiper.a11y.addElRole($bulletEl, 'button');
swiper.a11y.addElLabel($bulletEl, params.paginationBulletMessage.replace(/\{\{index\}\}/, $bulletEl.index() + 1));
}
});
}
},
init: function init() {
var swiper = this;
var params = swiper.params.a11y;
swiper.$el.append(swiper.a11y.liveRegion); // Container
var $containerEl = swiper.$el;
if (params.containerRoleDescriptionMessage) {
swiper.a11y.addElRoleDescription($containerEl, params.containerRoleDescriptionMessage);
}
if (params.containerMessage) {
swiper.a11y.addElLabel($containerEl, params.containerMessage);
} // Wrapper
var $wrapperEl = swiper.$wrapperEl;
var wrapperId = $wrapperEl.attr('id') || "swiper-wrapper-" + swiper.a11y.getRandomNumber(16);
var live = swiper.params.autoplay && swiper.params.autoplay.enabled ? 'off' : 'polite';
swiper.a11y.addElId($wrapperEl, wrapperId);
swiper.a11y.addElLive($wrapperEl, live); // Slide
if (params.itemRoleDescriptionMessage) {
swiper.a11y.addElRoleDescription($(swiper.slides), params.itemRoleDescriptionMessage);
}
swiper.a11y.addElRole($(swiper.slides), params.slideRole);
swiper.slides.each(function (slideEl) {
var $slideEl = $(slideEl);
var ariaLabelMessage = params.slideLabelMessage.replace(/\{\{index\}\}/, $slideEl.index() + 1).replace(/\{\{slidesLength\}\}/, swiper.slides.length);
swiper.a11y.addElLabel($slideEl, ariaLabelMessage);
}); // Navigation
var $nextEl;
var $prevEl;
if (swiper.navigation && swiper.navigation.$nextEl) {
$nextEl = swiper.navigation.$nextEl;
}
if (swiper.navigation && swiper.navigation.$prevEl) {
$prevEl = swiper.navigation.$prevEl;
}
if ($nextEl && $nextEl.length) {
swiper.a11y.makeElFocusable($nextEl);
if ($nextEl[0].tagName !== 'BUTTON') {
swiper.a11y.addElRole($nextEl, 'button');
$nextEl.on('keydown', swiper.a11y.onEnterOrSpaceKey);
}
swiper.a11y.addElLabel($nextEl, params.nextSlideMessage);
swiper.a11y.addElControls($nextEl, wrapperId);
}
if ($prevEl && $prevEl.length) {
swiper.a11y.makeElFocusable($prevEl);
if ($prevEl[0].tagName !== 'BUTTON') {
swiper.a11y.addElRole($prevEl, 'button');
$prevEl.on('keydown', swiper.a11y.onEnterOrSpaceKey);
}
swiper.a11y.addElLabel($prevEl, params.prevSlideMessage);
swiper.a11y.addElControls($prevEl, wrapperId);
} // Pagination
if (swiper.pagination && swiper.params.pagination.clickable && swiper.pagination.bullets && swiper.pagination.bullets.length) {
swiper.pagination.$el.on('keydown', classesToSelector(swiper.params.pagination.bulletClass), swiper.a11y.onEnterOrSpaceKey);
}
},
destroy: function destroy() {
var swiper = this;
if (swiper.a11y.liveRegion && swiper.a11y.liveRegion.length > 0) swiper.a11y.liveRegion.remove();
var $nextEl;
var $prevEl;
if (swiper.navigation && swiper.navigation.$nextEl) {
$nextEl = swiper.navigation.$nextEl;
}
if (swiper.navigation && swiper.navigation.$prevEl) {
$prevEl = swiper.navigation.$prevEl;
}
if ($nextEl) {
$nextEl.off('keydown', swiper.a11y.onEnterOrSpaceKey);
}
if ($prevEl) {
$prevEl.off('keydown', swiper.a11y.onEnterOrSpaceKey);
} // Pagination
if (swiper.pagination && swiper.params.pagination.clickable && swiper.pagination.bullets && swiper.pagination.bullets.length) {
swiper.pagination.$el.off('keydown', classesToSelector(swiper.params.pagination.bulletClass), swiper.a11y.onEnterOrSpaceKey);
}
}
};
export default {
name: 'a11y',
params: {
a11y: {
enabled: true,
notificationClass: 'swiper-notification',
prevSlideMessage: 'Previous slide',
nextSlideMessage: 'Next slide',
firstSlideMessage: 'This is the first slide',
lastSlideMessage: 'This is the last slide',
paginationBulletMessage: 'Go to slide {{index}}',
slideLabelMessage: '{{index}} / {{slidesLength}}',
containerMessage: null,
containerRoleDescriptionMessage: null,
itemRoleDescriptionMessage: null,
slideRole: 'group'
}
},
create: function create() {
var swiper = this;
bindModuleMethods(swiper, {
a11y: _extends({}, A11y, {
liveRegion: $("<span class=\"" + swiper.params.a11y.notificationClass + "\" aria-live=\"assertive\" aria-atomic=\"true\"></span>")
})
});
},
on: {
afterInit: function afterInit(swiper) {
if (!swiper.params.a11y.enabled) return;
swiper.a11y.init();
swiper.a11y.updateNavigation();
},
toEdge: function toEdge(swiper) {
if (!swiper.params.a11y.enabled) return;
swiper.a11y.updateNavigation();
},
fromEdge: function fromEdge(swiper) {
if (!swiper.params.a11y.enabled) return;
swiper.a11y.updateNavigation();
},
paginationUpdate: function paginationUpdate(swiper) {
if (!swiper.params.a11y.enabled) return;
swiper.a11y.updatePagination();
},
destroy: function destroy(swiper) {
if (!swiper.params.a11y.enabled) return;
swiper.a11y.destroy();
}
}
};