Skip to content

Commit

Permalink
A11y composant carousel (#609)
Browse files Browse the repository at this point in the history
  • Loading branch information
Clararigaud authored Sep 26, 2024
1 parent 5766be0 commit 85d4b0d
Show file tree
Hide file tree
Showing 20 changed files with 282 additions and 314 deletions.
2 changes: 1 addition & 1 deletion assets/js/theme/components/carousel.js
Original file line number Diff line number Diff line change
Expand Up @@ -12,4 +12,4 @@ import './carousel/manager';
import './carousel/paginationButton';
import './carousel/pagination';
import './carousel/slide';
import './carousel/slider';
import './carousel/slider';
26 changes: 12 additions & 14 deletions assets/js/theme/components/carousel/arrows.js
Original file line number Diff line number Diff line change
@@ -1,29 +1,27 @@
/* eslint-disable no-underscore-dangle */
window.osuny = window.osuny || {};
window.osuny.carousel = window.osuny.carousel || {};

window.osuny.carousel.Arrows = function (element) {
this.element = element;
if (!this.element) { return };
if (!this.element) {
return;
}
this._findElement = window.osuny.carousel.utils.findElement.bind(this);
this._dispatchEvent = window.osuny.carousel.utils.dispatchEvent.bind(this);
this.counter = this._findElement('arrowsCounter');
this.next = this._findElement('arrowsNext');
this.previous = this._findElement('arrowsPrevious');
this.next.addEventListener(
"click",
this._onNext.bind(this)
);
this.previous.addEventListener(
"click",
this._onPrevious.bind(this)
);
}
this.next.addEventListener('click', this._onNext.bind(this));
this.previous.addEventListener('click', this._onPrevious.bind(this));
};

window.osuny.carousel.Arrows.prototype = {
update: function (index, total) {
if (this.element) {
this.counter.innerHTML = (index + 1) + '/' + total;
this.next.disabled = index + 1 == total;
this.previous.disabled = index == 0;
this.counter.innerHTML = index + 1 + '/' + total;
this.next.disabled = index + 1 === total;
this.previous.disabled = index === 0;
}
},
_onNext: function () {
Expand All @@ -32,4 +30,4 @@ window.osuny.carousel.Arrows.prototype = {
_onPrevious: function () {
this._dispatchEvent('arrowsPrevious');
}
}
};
41 changes: 19 additions & 22 deletions assets/js/theme/components/carousel/autoplayer.js
Original file line number Diff line number Diff line change
@@ -1,13 +1,16 @@
/* eslint-disable no-underscore-dangle */
window.osuny = window.osuny || {};
window.osuny.carousel = window.osuny.carousel || {};

window.osuny.carousel.Autoplayer = function (element) {
this.element = element;
if (!this.element) { return };
if (!this.element) {
return;
}
this.icons = {
play: this.element.getElementsByClassName(window.osuny.carousel.classes.autoplayerToggleIconPlay).item(0),
pause: this.element.getElementsByClassName(window.osuny.carousel.classes.autoplayerToggleIconPause).item(0)
}
};
this.ariaLiveElement = null;
// Etat de l'autoplay
this.enabled = false;
Expand All @@ -21,17 +24,14 @@ window.osuny.carousel.Autoplayer = function (element) {
// Bouton toggle
this.classList = this.element.classList;
this.classList.add(window.osuny.carousel.classes.autoplayerPaused);
this.element.addEventListener(
"click",
this._onClick.bind(this)
);
this.element.addEventListener('click', this._onClick.bind(this));
this._dispatchEvent = window.osuny.carousel.utils.dispatchEvent.bind(this);
}
};
window.osuny.carousel.Autoplayer.prototype = {
setInterval: function (interval) {
this.interval = interval;
},
// enable() et disable() activent la boucle
// enable() et disable() activent la boucle
enable: function () {
this.enabled = true;
this._loop();
Expand All @@ -46,17 +46,15 @@ window.osuny.carousel.Autoplayer.prototype = {
pause: function () {
this.paused = true;
this._updateToggle();
this._updateAriaLiveElement();
},
unpause: function () {
this.paused = false;
this.softPaused = false;
this._updateToggle();
this._updateAriaLiveElement();
},
// Les méthodes soft se produisent quand on passe sur le carousel avec la souris.
// L'idée est de permettre aux personnes de lire une citation.
// Elles ne changent pas réellement l'état de l'autoplayer,
// Elles ne changent pas réellement l'état de l'autoplayer,
// mais elles l'arrêtent temporairement.
softPause: function () {
this.softPaused = true;
Expand All @@ -65,8 +63,10 @@ window.osuny.carousel.Autoplayer.prototype = {
this.softPaused = false;
},
_loop: function () {
if (!this.enabled) { return }
var now = Date.now();
if (!this.enabled) {
return;
}
if (!this.paused && !this.softPaused) {
this.elapsedSinceLastTrigger += now - this.lastLoopAt;
this.progression = this.elapsedSinceLastTrigger / this.interval;
Expand All @@ -90,13 +90,15 @@ window.osuny.carousel.Autoplayer.prototype = {
this.lastLoopAt = Date.now();
},
_dispatchTrigger: function () {
this._dispatchEvent("autoplayerTrigger");
this._dispatchEvent('autoplayerTrigger');
},
_dispatchProgression(){
this._dispatchEvent("autoplayerProgression", this.progression);
_dispatchProgression () {
this._dispatchEvent('autoplayerProgression', this.progression);
},
_updateToggle: function () {
if (!this.element) { return }
if (!this.element) {
return;
}
this.classList.remove(window.osuny.carousel.classes.autoplayerPlaying);
this.classList.remove(window.osuny.carousel.classes.autoplayerPaused);
if (this.paused) {
Expand All @@ -107,11 +109,6 @@ window.osuny.carousel.Autoplayer.prototype = {
this.icons.play.setAttribute('aria-hidden', !this.paused);
this.icons.pause.setAttribute('aria-hidden', this.paused);
},
_updateAriaLiveElement: function() {
if (!this.ariaLiveElement) { return }
var state = this.paused ? "off" : "polite";
this.ariaLiveElement.setAttribute("aria-live", state);
},
_onClick: function () {
if (this.paused) {
this.unpause();
Expand All @@ -120,4 +117,4 @@ window.osuny.carousel.Autoplayer.prototype = {
this.pause();
}
}
}
};
99 changes: 39 additions & 60 deletions assets/js/theme/components/carousel/carousel.js
Original file line number Diff line number Diff line change
@@ -1,3 +1,4 @@
/* eslint-disable no-underscore-dangle */
window.osuny = window.osuny || {};
window.osuny.carousel = window.osuny.carousel || {};

Expand All @@ -6,14 +7,15 @@ window.osuny.carousel.Carousel = function (element) {
this.slides = {
current: 0,
total: 0
}
};
this.state = {
initialized: false,
visible: false,
hasMouseOver: false
hasMouseOver: false,
hasFocus: false
};
this.windowResizeTimeout;
this.lastScrollXTimeout;
this.windowResizeTimeout = null;
this.lastScrollXTimeout = null;
this._findElement = window.osuny.carousel.utils.findElement.bind(this);
this._initializeConfig();
this._initializeSlider();
Expand All @@ -23,24 +25,22 @@ window.osuny.carousel.Carousel = function (element) {
this._initializeMouseEvents();
this.showSlide(0);
this.state.initialized = true;
}
};
window.osuny.carousel.Carousel.prototype = {
next: function () {
var index = this.slides.current + 1;
if (index >= this.slides.total) {
index = 0;
}
this.showSlide(index);
this.arrows.next.focus();
},
previous: function () {
var index = this.slides.current - 1;
if (index < 0) {
// -1 parce que 0-indexed
// -1 parce que 0-indexed
index = this.slides.total - 1;
}
this.showSlide(index);
this.arrows.previous.focus();
},
showSlide: function (index) {
this.slides.current = index;
Expand All @@ -61,7 +61,7 @@ window.osuny.carousel.Carousel.prototype = {
this.slider.recompute();
}.bind(this), 200);
},
isInViewPort: function(){
isInViewPort: function () {
var boundingRect = this.element.getBoundingClientRect(),
screenHeight = window.innerHeight || document.documentElement.clientHeight,
elementBottomInViewport = boundingRect.bottom >= 0,
Expand All @@ -78,80 +78,56 @@ window.osuny.carousel.Carousel.prototype = {
this.config.loadOptions(this.element.dataset.carousel);
},
_initializePagination: function () {
var paginationElement = this._findElement("pagination");
var paginationElement = this._findElement('pagination');
this.pagination = new window.osuny.carousel.Pagination(paginationElement);
if (paginationElement) {
paginationElement.addEventListener(
window.osuny.carousel.events.paginationButtonClicked,
this._onPaginationButtonClicked.bind(this)
);
paginationElement.addEventListener(window.osuny.carousel.events.paginationButtonClicked, this._onPaginationButtonClicked.bind(this));
}
},
_initializeArrows: function () {
var arrowsElement = this._findElement("arrows");
_initializeArrows: function () {
var arrowsElement = this._findElement('arrows');
this.arrows = new window.osuny.carousel.Arrows(arrowsElement);
if (arrowsElement) {
arrowsElement.addEventListener(
window.osuny.carousel.events.arrowsNext,
this.next.bind(this)
);
arrowsElement.addEventListener(
window.osuny.carousel.events.arrowsPrevious,
this.previous.bind(this)
);
arrowsElement.addEventListener(window.osuny.carousel.events.arrowsNext, this.next.bind(this));
arrowsElement.addEventListener(window.osuny.carousel.events.arrowsPrevious, this.previous.bind(this));
}
},
_initializeSlider: function () {
var sliderElement = this._findElement("slider");
var sliderElement = this._findElement('slider');
this.slider = new window.osuny.carousel.Slider(sliderElement);
this.slides.total = this.slider.length();
sliderElement.addEventListener(
"scroll",
this._onSliderScroll.bind(this)
);
sliderElement.addEventListener('scroll', this._onSliderScroll.bind(this));
},
_initializeAutoplayer(){
this.autoplayerElement = this._findElement("autoplayerToggle");
_initializeAutoplayer () {
this.autoplayerElement = this._findElement('autoplayerToggle');
this.autoplayer = new window.osuny.carousel.Autoplayer(this.autoplayerElement);
this.autoplayer.setInterval(this.config.autoplayinterval);
this.autoplayer.ariaLiveElement = this._findElement("container");
this.autoplayer.ariaLiveElement = this._findElement('container');
if (this.autoplayerElement) {
this.autoplayerElement.addEventListener(
window.osuny.carousel.events.autoplayerTrigger,
this.next.bind(this)
);
this.autoplayerElement.addEventListener(
window.osuny.carousel.events.autoplayerProgression,
this._onAutoplayerProgression.bind(this)
);
this.autoplayerElement.addEventListener(window.osuny.carousel.events.autoplayerTrigger, this.next.bind(this));
this.autoplayerElement.addEventListener(window.osuny.carousel.events.autoplayerProgression, this._onAutoplayerProgression.bind(this));
if (this.config.autoplay) {
this.autoplayer.enable();
}
}
},
_pointerStart: function() {
_pointerStart: function () {
this.autoplayer.softPause();
this.state.hasMouseOver = true;
},
_pointerEnd: function() {
_pointerEnd: function () {
this.autoplayer.softUnpause();
this.state.hasMouseOver = false;
},
_initializeMouseEvents: function(){
this.element.addEventListener(
"mouseenter", this._pointerStart.bind(this)
);
this.element.addEventListener(
"touchstart", this._pointerStart.bind(this)
);
this.element.addEventListener(
"mouseleave", this._pointerEnd.bind(this)
);
this.element.addEventListener(
"touchend", this._pointerEnd.bind(this)
);
},

_initializeMouseEvents: function () {
this.element.addEventListener('mouseenter', this._pointerStart.bind(this));
this.element.addEventListener('touchstart', this._pointerStart.bind(this));
this.element.addEventListener('mouseleave', this._pointerEnd.bind(this));
this.element.addEventListener('touchend', this._pointerEnd.bind(this));
this.element.addEventListener('focusin', function () {
this.autoplayer.pause();
}.bind(this));
},
_onAutoplayerProgression: function (event) {
this.pagination.setProgression(event.value);
},
Expand All @@ -163,16 +139,19 @@ window.osuny.carousel.Carousel.prototype = {
this.autoplayer.softPause();
clearTimeout(this.lastScrollXTimeout);
this.lastScrollXTimeout = setTimeout(function () {
if(!this.state.hasMouseOver){
if (!this.state.hasMouseOver) {
this.autoplayer.softUnpause();
}
this._onSliderScrollend();
}.bind(this), 100);
},
_onSliderScrollend: function () {
var index = this.slider.currentSlideIndex();
if (this.slides.current != index) {
if (this.state.hasFocus) {
this.slider.focusOnSlide(index);
}
if (this.slides.current !== index) {
this.showSlide(index);
}
}
}
};
40 changes: 20 additions & 20 deletions assets/js/theme/components/carousel/classes.js
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,23 @@ window.osuny = window.osuny || {};
window.osuny.carousel = window.osuny.carousel || {};

window.osuny.carousel.classes = {
arrows: "carousel__arrows",
arrowsCounter: "counter",
arrowsNext: "arrow-next",
arrowsPrevious: "arrow-prev",
autoplayerPaused: "toggle__paused",
autoplayerPlaying: "toggle__playing",
autoplayerToggle: "toggle",
autoplayerToggleIconPause: "pause",
autoplayerToggleIconPlay: "play",
carousel: "js-carousel",
container: "carousel__container",
pagination: "carousel__pagination__tabcontainer",
paginationPage: "carousel__pagination__page",
slider: "carousel__slider",
slideIsBefore: "is-before",
slideIsPrevious: "is-previous",
slideIsCurrent: "is-current",
slideIsNext: "is-next",
slideIsAfter: "is-after",
}
arrows: 'carousel__arrows',
arrowsCounter: 'counter',
arrowsNext: 'arrow-next',
arrowsPrevious: 'arrow-prev',
autoplayerPaused: 'toggle__paused',
autoplayerPlaying: 'toggle__playing',
autoplayerToggle: 'toggle',
autoplayerToggleIconPause: 'pause',
autoplayerToggleIconPlay: 'play',
carousel: 'js-carousel',
container: 'carousel__container',
pagination: 'carousel__pagination__tabcontainer',
paginationPage: 'carousel__pagination__page',
slider: 'carousel__slider',
slideIsBefore: 'is-before',
slideIsPrevious: 'is-previous',
slideIsCurrent: 'is-current',
slideIsNext: 'is-next',
slideIsAfter: 'is-after'
};
Loading

0 comments on commit 85d4b0d

Please sign in to comment.