Skip to content

Commit

Permalink
Carousel Example with Tabs for Slide Control: Make JavaScript easier …
Browse files Browse the repository at this point in the history
…to understand (pull #1503)

This commit does not include any functional changes.
It changes things like variable names to make it easier to understand, implementing guidance from the APG code guide.
The code for this carousel now follows the same patterns as the code for the carousel with buttons for slide control.
  • Loading branch information
jongund authored Sep 5, 2020
1 parent 43e7440 commit 8bc72c9
Showing 1 changed file with 44 additions and 98 deletions.
142 changes: 44 additions & 98 deletions examples/carousel/js/carousel-tablist.js
Original file line number Diff line number Diff line change
Expand Up @@ -30,21 +30,20 @@ var CarouselTablist = function (node, options) {
this.tabpanelNodes = [];

this.liveRegionNode = node.querySelector('.carousel-items');
this.pauseButtonNode = null;
this.pausePlayButtonNode = document.querySelector('.carousel-tablist .controls button.rotation');

this.playLabel = 'Start automatic slide show';
this.pauseLabel = 'Stop automatic slide show';

/* State properties */
this.forcePlay = false; // set once the user activates the play/pause button
this.playState = !options.paused; // state of the play/pause button
this.rotate = !options.paused; // state of rotation
this.hasUserActivatedPlay = false; // set when the user activates the play/pause button
this.isAutoRotationDisabled = options.norotate // This property for disabling auto rotation
this.isPlayingEnabled = !options.paused; // This property is also set in updatePlaying method
this.timeInterval = 5000; // length of slide rotation in ms
this.currentIndex = 0; // index of current slide
this.slideTimeout = null; // save reference to setTimeout

// initialize tabs

this.tablistNode.addEventListener('focusin', this.handleTabFocus.bind(this));
this.tablistNode.addEventListener('focusout', this.handleTabBlur.bind(this));

Expand Down Expand Up @@ -75,46 +74,33 @@ var CarouselTablist = function (node, options) {
imageLink.addEventListener('focus', this.handleImageLinkFocus.bind(this));
imageLink.addEventListener('blur', this.handleImageLinkBlur.bind(this));
}

}
else {
this.tabpanelNodes.push(null);
}

}

// Pause Button
var elem = document.querySelector('.carousel-tablist .controls button.rotation');
if (elem) {
this.pauseButtonNode = elem;
this.pauseButtonNode.addEventListener('click', this.handlePauseButtonClick.bind(this));
}

// initialize behavior based on options

this.updatePlayState(this.rotate && !options.norotate);

if (this.rotate && !options.norotate) {
this.rotateSlides(false);
}

if (options.norotate) {
this.disableRotation(true);
if (this.pausePlayButtonNode) {
this.pausePlayButtonNode.addEventListener('click', this.handlePausePlayButtonClick.bind(this));
}

this.setAccessibleStyling(options.moreaccessible);

// Handle hover events
this.domNode.addEventListener('mouseover', this.handleMouseOver.bind(this));
this.domNode.addEventListener('mouseout', this.handleMouseOut.bind(this));

// initialize behavior based on options

this.enableOrDisableAutoRotation(options.norotate);
this.updatePlaying(!options.paused && !options.norotate);
this.setAccessibleStyling(options.moreaccessible);
this.rotateSlides();
}

/* Public function to disable or enable rotation */
CarouselTablist.prototype.disableRotation = function(disable) {
if (disable) {
this.updatePlayState(false);
}
this.pauseButtonNode.hidden = disable;
/* Public function to disable/enable rotation and if false, hide pause/play button*/
CarouselTablist.prototype.enableOrDisableAutoRotation = function(disable) {
this.isAutoRotationDisabled = disable;
this.pausePlayButtonNode.hidden = disable;
}

/* Public function to update controls/caption styling */
Expand Down Expand Up @@ -188,53 +174,34 @@ CarouselTablist.prototype.setSelectedToNextTab = function (moveFocus) {
this.setSelectedTab(nextIndex, moveFocus);
}

CarouselTablist.prototype.rotateSlides = function (changeSlide) {
if (changeSlide !== false) {
this.setSelectedToNextTab();
CarouselTablist.prototype.rotateSlides = function () {
if (!this.isAutoRotationDisabled ) {
if ((!this.hasFocus &&
!this.hasHover &&
this.isPlayingEnabled) ||
this.hasUserActivatedPlay) {
this.setSelectedToNextTab(false);
}
}

this.slideTimeout = setTimeout(this.rotateSlides.bind(this), this.timeInterval);
}

CarouselTablist.prototype.resetTimeout = function() {
clearTimeout(this.slideTimeout);
this.rotate = false;
this.updateRotation();
}
CarouselTablist.prototype.updatePlaying = function (play) {
this.isPlayingEnabled = play;

CarouselTablist.prototype.updateRotation = function() {

var shouldRotate = !this.hasFocus && !this.hasHover && this.playState;
if (shouldRotate === this.rotate) {
return;
}

this.rotate = shouldRotate;

if (shouldRotate) {
this.rotateSlides(false);
if (play) {
this.pausePlayButtonNode.setAttribute('aria-label', this.pauseLabel);
this.pausePlayButtonNode.classList.remove('play');
this.pausePlayButtonNode.classList.add('pause');
this.liveRegionNode.setAttribute('aria-live', 'off');
}
else {
clearTimeout(this.slideTimeout);
}
}

CarouselTablist.prototype.updatePlayState = function (play) {
this.playState = play;
this.updateRotation();

if (!play) {
this.pauseButtonNode.setAttribute('aria-label', this.playLabel);
this.pauseButtonNode.classList.remove('pause');
this.pauseButtonNode.classList.add('play');
this.pausePlayButtonNode.setAttribute('aria-label', this.playLabel);
this.pausePlayButtonNode.classList.remove('pause');
this.pausePlayButtonNode.classList.add('play');
this.liveRegionNode.setAttribute('aria-live', 'polite');
}
else {
this.pauseButtonNode.setAttribute('aria-label', this.pauseLabel);
this.pauseButtonNode.classList.remove('play');
this.pauseButtonNode.classList.add('pause');
this.liveRegionNode.setAttribute('aria-live', 'off');
}
}

/* Event Handlers */
Expand All @@ -248,26 +215,20 @@ CarouselTablist.prototype.handleImageLinkBlur = function () {
}

CarouselTablist.prototype.handleMouseOver = function (event) {
if (!this.forcePlay) {
if (!this.pauseButtonNode.contains(event.target)) {
this.hasHover = true;
}
this.updateRotation();
if (!this.pausePlayButtonNode.contains(event.target)) {
this.hasHover = true;
}
}

CarouselTablist.prototype.handleMouseOut = function () {
if (!this.forcePlay) {
this.hasHover = false;
this.updateRotation();
}
this.hasHover = false;
}

/* EVENT HANDLERS */

CarouselTablist.prototype.handlePauseButtonClick = function () {
this.forcePlay = true;
this.updatePlayState(!this.playState);
CarouselTablist.prototype.handlePausePlayButtonClick = function () {
this.hasUserActivatedPlay = !this.isPlayingEnabled;
this.updatePlaying(!this.isPlayingEnabled);
}

/* Event Handlers for Tabs*/
Expand All @@ -279,25 +240,21 @@ CarouselTablist.prototype.handleTabKeydown = function (event) {

case 'ArrowRight':
this.setSelectedToNextTab(true);
this.resetTimeout();
flag = true;
break;

case 'ArrowLeft':
this.setSelectedToPreviousTab(true);
this.resetTimeout();
flag = true;
break;

case 'Home':
this.setSelectedTab(0, true);
this.resetTimeout();
flag = true;
break;

case 'End':
this.setSelectedTab(this.tabNodes.length - 1, true);
this.resetTimeout();
flag = true;
break;

Expand All @@ -314,17 +271,12 @@ CarouselTablist.prototype.handleTabKeydown = function (event) {
CarouselTablist.prototype.handleTabClick = function (event) {
var index = this.tabNodes.indexOf(event.currentTarget);
this.setSelectedTab(index, true);
this.resetTimeout();
}

CarouselTablist.prototype.handleTabFocus = function () {
this.tablistNode.classList.add('focus');
this.liveRegionNode.setAttribute('aria-live', 'polite');

if (!this.forcePlay) {
this.hasFocus = true;
this.updateRotation();
}
this.hasFocus = true;
}

CarouselTablist.prototype.handleTabBlur = function () {
Expand All @@ -333,23 +285,17 @@ CarouselTablist.prototype.handleTabBlur = function () {
this.liveRegionNode.setAttribute('aria-live', 'off');
}

if (!this.forcePlay) {
this.hasFocus = false;
this.updateRotation();
}
this.hasFocus = false;
}


/* Event Handlers for Tabpanels*/

CarouselTablist.prototype.handleTabpanelFocusIn = function () {
this.hasFocus = true;
this.updateRotation();
}

CarouselTablist.prototype.handleTabpanelFocusOut = function () {
this.hasFocus = false;
this.updateRotation();
}

/* Iniitalize Carousel Tablists and options */
Expand Down Expand Up @@ -394,7 +340,7 @@ window.addEventListener('load', function () {
updateEvent = 'setAccessibleStyling';
break;
case 'norotate':
updateEvent = 'disableRotation';
updateEvent = 'enableOrDisableAutoRotation';
break;
}

Expand Down

0 comments on commit 8bc72c9

Please sign in to comment.