\ No newline at end of file
diff --git a/tests/spec/slider/sliderSpec.js b/tests/spec/slider/sliderSpec.js
new file mode 100644
index 0000000000..72ae0fdac0
--- /dev/null
+++ b/tests/spec/slider/sliderSpec.js
@@ -0,0 +1,78 @@
+describe("Slider Plugin", () => {
+
+ beforeEach(async () => {
+ await XloadFixtures(["slider/sliderFixture.html"]);
+ });
+ afterEach(() => {
+ XunloadFixtures();
+ });
+
+ describe("Slider", () => {
+
+ let slider;
+
+ beforeEach(() => {
+ slider = M.Slider.init(document.querySelector(".slider"), {
+ interval: 1000,
+ pauseOnFocus: true,
+ indicatorLabelFunc: (idx) => "Slide " + idx
+ });
+ });
+
+ afterEach(() => {
+ if (slider) slider.destroy();
+ slider = null;
+ });
+
+ it("Slider should change after 1 second", (done) => {
+ const O_INDEX = slider.activeIndex;
+ setTimeout(() => {
+ setTimeout(() => {
+ expect(slider.activeIndex).not.toBe(O_INDEX);
+ done();
+ }, 1500);
+ }, 1);
+ });
+
+ it("Slider should not change if paused", (done) => {
+ const O_INDEX = slider.activeIndex;
+ slider.pause();
+ setTimeout(() => {
+ setTimeout(() => {
+ expect(slider.activeIndex).toBe(O_INDEX);
+ done();
+ }, 2000);
+ }, 1);
+ });
+
+ it("Slider should not change if focused", (done) => {
+ const O_INDEX = slider.activeIndex;
+ slider.start();
+ slider.el.querySelector("li").focus();
+
+ setTimeout(() => {
+ setTimeout(() => {
+ expect(slider.eventPause).toBe(true);
+ expect(slider.activeIndex).toBe(O_INDEX);
+ done();
+ }, 2000);
+ }, 1);
+ });
+
+ it("Label of indicators must start with 'Slide '", () => {
+ expect(Array.from(document.querySelectorAll("button")).map((btn) =>
+ btn.getAttribute("aria-label").startsWith("Slide ")
+ )).toEqual([true, true, true, true]);
+ });
+
+ it("Slider should change current index and focus its respective item on indicator click", () => {
+ const IDX = 2;
+ document.querySelectorAll("button")[IDX].click();
+
+ expect(slider.activeIndex).toBe(IDX);
+ expect(document.activeElement).toBe(document.querySelectorAll(".slides > li")[IDX]);
+ });
+
+ });
+
+});
\ No newline at end of file
From 731efeefce5bc3b088be38444d09ee7b4da77b23 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Mauro=20Mascarenhas=20de=20Ara=C3=BAjo?=
Date: Wed, 7 Dec 2022 19:15:32 -0300
Subject: [PATCH 3/7] docs(slider): slider accessibility
- Add description for new initialization options;
- Add description for new instance properties;
- Add alternative text for images (updating code samples);
- Update Slider init code sample to include indicatorLabelFunc example.
---
pug/page-contents/media_content.html | 69 +++++++++++++++++++++++-----
1 file changed, 58 insertions(+), 11 deletions(-)
diff --git a/pug/page-contents/media_content.html b/pug/page-contents/media_content.html
index 8e55057db4..a31c922c71 100644
--- a/pug/page-contents/media_content.html
+++ b/pug/page-contents/media_content.html
@@ -8,12 +8,12 @@
Material Box
Material box is a material design implementation of the Lightbox plugin. When a user clicks on an image that can
be enlarged, Material box centers the image and enlarges it in a smooth, non-jarring manner. To dismiss the image,
the user can either click on the image again, scroll away, or press the ESC key.
-
+
Creating the above image with the effect is as simple as adding a
materialboxed class to the image tag.
- <img class="materialboxed" data-caption="A picture of a way with a group of trees in a park" width="250" src="images/placeholder/800x400_d.jpg">
+ <img class="materialboxed" data-caption="A picture of a way with a group of trees in a park" width="250" alt="Sample image for Material Box with caption" src="images/placeholder/800x400_d.jpg">
@@ -204,7 +204,7 @@
Slider
-
+
This is our big Tagline!
@@ -212,7 +212,7 @@
Here's our small slogan.
-
+
Left Aligned Caption
@@ -220,7 +220,7 @@
Here's our small slogan.
-
+
Right Aligned Caption
@@ -228,7 +228,7 @@
Here's our small slogan.
-
+
This is our big Tagline!
@@ -243,28 +243,28 @@
Here's our small slogan.
<div class="slider">
<ul class="slides">
<li>
- <img src="images/placeholder/800x400_a.jpg">
+ <img src="images/placeholder/800x400_a.jpg" alt="Sample image for first slide">
<div class="caption center-align">
<h3>This is our big Tagline!</h3>
<h5 class="light grey-text text-lighten-3">Here's our small slogan.</h5>
</div>
</li>
<li>
- <img src="images/placeholder/800x400_b.jpg">
+ <img src="images/placeholder/800x400_b.jpg" alt="Sample image for second slide">
<div class="caption left-align">
<h3>Left Aligned Caption</h3>
<h5 class="light grey-text text-lighten-3">Here's our small slogan.</h5>
</div>
</li>
<li>
- <img src="images/placeholder/800x400_c.jpg">
+ <img src="images/placeholder/800x400_c.jpg" alt="Sample image for third slide">
<div class="caption right-align">
<h3>Right Aligned Caption</h3>
<h5 class="light grey-text text-lighten-3">Here's our small slogan.</h5>
</div>
</li>
<li>
- <img src="images/placeholder/800x400_d.jpg">
+ <img src="images/placeholder/800x400_d.jpg" alt="Sample image for fourth slide">
<div class="caption center-align">
<h3>This is our big Tagline!</h3>
<h5 class="light grey-text text-lighten-3">Here's our small slogan.</h5>
@@ -281,6 +281,13 @@
Initialization
var elems = document.querySelectorAll('.slider');
var instances = M.Slider.init(elems, {
// specify options here
+ indicatorLabelFunc: (idx, current) => {
+ let label = "Go to slide " + idx;
+ if (current){
+ label = label + " (Current)";
+ }
+ return label;
+ }
});
});
@@ -289,6 +296,13 @@
// Or with jQuery
- $(document).ready(function(){
+ $(document).ready(function() {
$('.materialboxed').materialbox({
// specify options here
});
@@ -283,7 +283,7 @@
Initialization
// specify options here
indicatorLabelFunc: (idx, current) => {
let label = "Go to slide " + idx;
- if (current){
+ if (current) {
label = label + " (Current)";
}
return label;
@@ -293,12 +293,12 @@
Initialization
// Or with jQuery
- $(document).ready(function(){
+ $(document).ready(function() {
$('.slider').slider({
// specify options here
indicatorLabelFunc: (idx, curr) => {
let label = "Go to slide " + idx;
- if (current){
+ if (current) {
label = label + " (Current)";
}
return label;
From 26bbe22e6f9cd810020df03662ec79665480d3f4 Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Mauro=20Mascarenhas=20de=20Ara=C3=BAjo?=
Date: Sat, 28 Jan 2023 21:40:37 -0300
Subject: [PATCH 5/7] refactor(slider accessibility): adapt code style to
guidelines
- Replace double quotes string by single quotes;
- Replace vanilla JS calls by jQuery functions.
---
js/slider.js | 26 ++++++++++++--------------
1 file changed, 12 insertions(+), 14 deletions(-)
diff --git a/js/slider.js b/js/slider.js
index fba838c65e..55eb41a63a 100644
--- a/js/slider.js
+++ b/js/slider.js
@@ -85,7 +85,7 @@
});
this.$slides.each((el) => {
// Sets slide as focusable by code
- if (!el.hasAttribute("tabindex")) el.setAttribute("tabindex", -1);
+ if (!el.hasAttribute('tabindex')) el.setAttribute('tabindex', -1);
// Removes initial visibility from "inactive" slides
el.style.visibility = 'hidden';
});
@@ -169,11 +169,11 @@
this._handleAutoPauseHoverBound = this._handleAutoPauseHover.bind(this);
this._handleAutoStartHoverBound = this._handleAutoStartHover.bind(this);
- if (this.options.pauseOnFocus){
+ if (this.options.pauseOnFocus) {
this.el.addEventListener('focusin', this._handleAutoPauseFocusBound);
this.el.addEventListener('focusout', this._handleAutoStartFocusBound);
}
- if (this.options.pauseOnHover){
+ if (this.options.pauseOnHover) {
this.el.addEventListener('mouseenter', this._handleAutoPauseHoverBound);
this.el.addEventListener('mouseleave', this._handleAutoStartHoverBound);
}
@@ -187,18 +187,16 @@
* Remove Event Handlers
*/
_removeEventHandlers() {
- if (this.options.pauseOnFocus){
+ if (this.options.pauseOnFocus) {
this.el.removeEventListener('focusin', this._handleAutoPauseFocusBound);
this.el.removeEventListener('focusout', this._handleAutoStartFocusBound);
}
- if (this.options.pauseOnHover){
+ if (this.options.pauseOnHover) {
this.el.removeEventListener('mouseenter', this._handleAutoPauseHoverBound);
this.el.removeEventListener('mouseleave', this._handleAutoStartHoverBound);
}
if (this.options.indicators) {
- this.$indicators.each((el) => {
- el.children[0].removeEventListener('click', this._handleIndicatorClickBound);
- });
+ this.$indicators.children().off('click', this._handleIndicatorClickBound);
}
}
@@ -217,7 +215,7 @@
*/
_handleAutoPauseHover() {
this._hovered = true;
- if (this.interval != null){
+ if (this.interval != null) {
this._pause(true);
}
}
@@ -227,7 +225,7 @@
*/
_handleAutoPauseFocus() {
this._focused = true;
- if (this.interval != null){
+ if (this.interval != null) {
this._pause(true);
}
}
@@ -237,7 +235,7 @@
*/
_handleAutoStartHover() {
this._hovered = false;
- if (!(this.options.pauseOnFocus && this._focused) && this.eventPause){
+ if (!(this.options.pauseOnFocus && this._focused) && this.eventPause) {
this.start();
}
}
@@ -247,7 +245,7 @@
*/
_handleAutoStartFocus() {
this._focused = false;
- if (!(this.options.pauseOnHover && this._hovered) && this.eventPause){
+ if (!(this.options.pauseOnHover && this._hovered) && this.eventPause) {
this.start();
}
}
@@ -421,7 +419,7 @@
});
this.$slides.eq(index).addClass('active');
- if (this._focusCurrent){
+ if (this._focusCurrent) {
this.$slides.eq(index)[0].focus();
this._focusCurrent = false;
}
@@ -429,7 +427,7 @@
// Reset interval, if allowed. This check prevents autostart
// when slider is paused, since it can be changed though indicators.
- if (this.interval != null){
+ if (this.interval != null) {
this.start();
}
}
From 6b2ec14d226296263b13c6e9ac43ee73e2683d1c Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Mauro=20Mascarenhas=20de=20Ara=C3=BAjo?=
Date: Thu, 16 Feb 2023 15:27:12 -0300
Subject: [PATCH 6/7] style(slider): remove extra spaces
---
js/slider.js | 4 ++--
1 file changed, 2 insertions(+), 2 deletions(-)
diff --git a/js/slider.js b/js/slider.js
index 55eb41a63a..fa9e27f059 100644
--- a/js/slider.js
+++ b/js/slider.js
@@ -371,11 +371,11 @@
// Update indicators
if (this.options.indicators) {
- let activeIndicator = this.$indicators
+ let activeIndicator = this.$indicators
.eq(this.activeIndex)
.children()
.first();
- let nextIndicator = this.$indicators
+ let nextIndicator = this.$indicators
.eq(index)
.children()
.first();
From df94e9ecd82c9fac7555efa466846cb4b83aedbd Mon Sep 17 00:00:00 2001
From: =?UTF-8?q?Mauro=20Mascarenhas=20de=20Ara=C3=BAjo?=
Date: Thu, 16 Feb 2023 15:29:07 -0300
Subject: [PATCH 7/7] docs(slider): identify indicatorLabelFunc as optional
Mark "indicatorLabelFunc" as optional in docs description and code samples.
---
pug/page-contents/media_content.html | 6 ++++--
1 file changed, 4 insertions(+), 2 deletions(-)
diff --git a/pug/page-contents/media_content.html b/pug/page-contents/media_content.html
index 861b03ea7f..8c74c37354 100644
--- a/pug/page-contents/media_content.html
+++ b/pug/page-contents/media_content.html
@@ -281,6 +281,7 @@
Initialization
var elems = document.querySelectorAll('.slider');
var instances = M.Slider.init(elems, {
// specify options here
+ /** Optional function which generates ARIA label for each indicator */
indicatorLabelFunc: (idx, current) => {
let label = "Go to slide " + idx;
if (current) {
@@ -296,7 +297,8 @@
Initialization
$(document).ready(function() {
$('.slider').slider({
// specify options here
- indicatorLabelFunc: (idx, curr) => {
+ /** Optional function which generates ARIA label for each indicator */
+ indicatorLabelFunc: (idx, current) => {
let label = "Go to slide " + idx;
if (current) {
label = label + " (Current)";
@@ -362,7 +364,7 @@
Options
null
- Function used to generate ARIA label to indicators (for accessibility purposes).
+ Optional function used to generate ARIA label to indicators (for accessibility purposes).
It receives the current index, starting from "1", and a boolean indicating whether it is the current element or not.