quick-start
wm-atomic-docs
installation
css-classes
colors
colors-row-themes
javascript-modules
row-components
git-usage
git-fixing-mistakes
git-cheatsheet
how-tos
site-structure
site-variables
bem-resources
sass-resources
link-elements
list-elements
normalize
fancybox
print
cheatsheet-functions-and-mixins
function-color
function-font
function-px-to-rem
function-remove-unit
function-spacing
mixin-banner-heights
mixin-breakpoints
mixin-button-styles
mixin-color-theme
mixin-fluid-anything
mixin-link-styles
mixin-menu-open-closed-styles
mixin-right-arrow
mixin-social-media-icons
wm-breakpoints
breakpoint-cheatsheet
wm-colors
vims-colors
wm-font-families
wm-spacing
wm-widths-and-heights
wm-z-indexes
wm-border
wm-element-styles
location-array
heading-specs
listing-specs
background-image
heights
switch
sr-only
theme-colors
wm-helper-min-js
wm-plugins-js
wm-shortcodes-js
perfect-scrollbar
wm-main-js
wm-secondary-js
adjust-row-card-height
event-row-js
news-feed-js
tiny-slider-js
wm-row-slideshow-js
global
headings
text-treatments
buttons
links
lists
tables
forms
images
svg-caret-white
wm-row-base-component
wm-split-layout-component
wm-row-buttons
wm-cards-component
wm-description-text-component
wm-card-component
wm-text-card-component
wm-image-card
wm-statnum-component
themes
listing-layout
main-layout
sharebar
alert
boxcopy
breadcrumbs
broadcast-bar
buttons-wm
bxSlider
default-extra-announcements
default-extra-events
default-extra-features
default-extra-news
directory-with-photo-grid
dropdown
emergency-info
figure
figure-responsive
figure-icon
galleria-gallery-slideshow
header
horiz-nav
lightbox
lightbox-content
listing-page-item
news-home-latest-news
news-home-top-stories
photoset
rrssb
search-form
search-results
sidebar-listboxes
sidebar-news-events-rss
sidebar-news-home-video
sidebar-news-press-releases
sidebar-news-wminthenews
sidebar-widgets
table-collapsible
tables-wm
text
wysiwg-photos
youtube-embeds
examples-listboxes-widgets
examples-listings
examples-headings
-user-content-styles
announcement-content
atoz-listing
campus-map-content
content-page-content
directory-content
_experts-content
feature-page-content
full-page-content
gallery-page-content
gateway-page-content
grid-classic
grid-classic-right-col
grid-classic-rows
grid-classic-multisize
grid-classic-multisize-right-col
grid-flow
grid-flow-right-col
grid-flow-titles
grid-flow-captions
_ideation-story-content
_ideation-story-header-content
listing-page-announcements
listing-page-children
listing-page-directory
listing-page-features
listing-page-files
listing-page-news-stories
listing-page-portfolio
multimedia-grid-content
news-home
news-story-content
portfolio
row
sidebar
slideshow-research
tr-form-content
youtube-playlist
embed-row
button-bar-row
_base-row
accordion-list-row
announcements-row
callout
contact-place
content-row
events
fiftyfifty
icons
links-row
news-feed-row
search-row
statistics
video-feature
homepage-hero
homepage-admission
homepage-programs
homepage-stats
topbar-logo-homepage
menu-banner
topbar-logo-section
topbar
banner
banner-medium
banner-tall
banner-super
chosen
footer
info-for-menu
page-nav
page-nav-ideation
page-nav-news
page-nav-social-buttons
site-menu
AtoZ-Listing-template
Campus-Map-Location-template
Content-Page-template
_Experts-Page-template
Feature-Page-template
Full-Page-template
Gallery-Page-template
Gateway-Page-template
Gateway-Page-left-nav-template
_Ideation-story-template
Landing-Page-template
Multimedia-Grid-template
News-Media-Home-template
News-Story-template
Slideshow-Page-template
Paste-N-Test-template
WM-Homepage-template
Announcement
AtoZ-Listing
Campus-Map-Location
Content-Page
Content-Page-2-Columns
Content-Page-Grid-all-versions
Content-Page-Grid-Classic
Content-Page-Grid-Masonry
Directory-Page
_Experts-Page
Feature-Page
Full-Page
Gallery-Page
Gateway-Page
Gateway-Page-left-nav
_Ideation-Story
Landing-Page
Listing-Page-Announcements
Listing-Page-Children
Listing-Page-Directory
Listing-Page-Features
Listing-Page-Files
Listing-Page-News-Stories
Listing-Page-Portfolio
Multimedia-Grid
_News-Media-Home
News-Story
Portfolio-Page
Slideshow-Page
YouTube-Playlist
Paste-N-Test
WM-Homepage
wm-cheatsheet
vims-cheatsheet
3-row-js
edit
wm-row-slideshow-js
edit
Slideshow Class for sliding row slideshows
HTML
Output
SCSS
( ) Javascript
Expand
Copy
Edit
<!-- components/3-row-js/wm-row-slideshow-js.php -->
Copy
Copy
Edit
/* scss/3-row-js/_wm-row-slideshow-js.scss */ .wm-slideshow { margin: 0 auto; overflow: hidden; position: relative; } .wm-slideshow__track { display: block; transition: transform 0.1s ease-in-out; overflow-y: hidden; overflow-x: scroll; &::-webkit-scrollbar { width: 0 !important; } overflow: -moz-scrollbars-none; -ms-overflow-style: none; scrollbar-width: none; .-full-width & { display: grid; place-content: center; padding-left: 44px; padding-right: 44px; } } .wm-slideshow__slides { transition: transform 0.1s ease-in-out; max-width: 100%; margin: 0; padding: 0; padding-left: 22px !important; list-style: none; display: flex; justify-content: flex-start; flex-wrap: nowrap; width: 100%; gap: 20px; position: relative; left: 0; @include breakpoint($mobile-to-wide-mobile-breakpoint) { padding-left: 44px !important; } .-full-width & { padding-left: 0 !important; margin: 0 auto; width: 100%; max-width: 1288px; position: relative; } } .wm-slideshow__slide { // overwrite card styles flex: 0 0 auto !important; max-height: 100% !important; // width: 307px; // widths set in js min-width: auto !important; // max-width: 416px; .-full-width & { flex: 0 1 auto; } } .wm-slideshow__fake-slide { width: 2px !important; min-width: 2px !important; flex: 0 0 2px; .-full-width & { display: none; } @include breakpoint($mobile-to-wide-mobile-breakpoint) { width: 24px !important; min-width: 24px !important; flex: 0 0 24px; } } .wm-slideshow__dots { margin-top: 30px !important; height: 20px; width: 100%; max-width: 500px; display: flex; place-content: center; .-full-width & { display: none !important; } } .wm-slideshow__dot { display: inline-block; border-radius: 50%; height: 10px; width: 10px; margin: 0 10px; background-color: rgba(var(--theme-dot-button-inactive-rgb-color), 0.25); &.currentDot { background-color: var(--theme-dot-button-active-color); } .no-touch &:hover { cursor: pointer; background-color: rgba($color: var(--theme-dot-button-inactive-rgb-color), $alpha: 0.45); } }
Copy
Edit
/* js/wm-row-slideshow-js.js */ let numSlideshows = 0; class wmRowSlideshow { // set constants SLIDE_CLASS_STRING = "wm-slideshow"; SLIDE_CLASS = "." + this.SLIDE_CLASS_STRING; GAP_SM = 20; GAP_LG = 20; INTERVAL_DURATION = 5000; MIN_SLIDEWIDTH = 277; MAX_SLIDEWIDTH = 416; MAX_SLIDEWIDTH_FULLSCREEN = 307; FAKE_SLIDEWIDTH = 24; MAX_FULL_SLIDESHOW_WIDTH = 1288; MAX_INNERCONTAINER_WIDTH_WIDESCREEN = 1288; DOT_ELEMENT = "div" DOT_CLASS = this.SLIDE_CLASS_STRING + "__dot"; DOT_CURRENT_CLASS = "currentDot"; currentGapWidth = this.GAP_LG; constructor(slideshowID) { // get references to slide container and elements this.SLIDESHOW = document.getElementById(slideshowID); this.CONTAINER = this.SLIDESHOW.querySelector(this.SLIDE_CLASS); this.INNERTRACK = this.SLIDESHOW.querySelector(this.SLIDE_CLASS + "__track"); this.SLIDE_LIST = this.SLIDESHOW.querySelector(this.SLIDE_CLASS + "__slides"); this.SLIDE_ARRAY = this.SLIDESHOW.querySelectorAll(this.SLIDE_CLASS + "__slide"); this.TOTAL_SLIDES = this.SLIDE_ARRAY.length; this.LAST_SLIDEINDEX = this.TOTAL_SLIDES - 1; this.DOTS_CONTAINER = this.SLIDESHOW.querySelector(this.SLIDE_CLASS + "__dots"); this.DOTS_CONTAINER.innerHTML = ""; this.NARROW_BREAKPOINTS = this.getNarrowestSlideBreakpoints(); this.SIDEPEEK_WIDTH = 44; this.MAX_VISIBLEWIDTH = this.MAX_FULL_SLIDESHOW_WIDTH; this.MAX_FULL_TRACK_WIDTH = this.MAX_FULL_SLIDESHOW_WIDTH + (this.SIDEPEEK_WIDTH * 2); // set tracker variables this.currentViewWidth = this.CONTAINER.offsetWidth; this.currentSlideWidth = this.MIN_SLIDEWIDTH; this.newSlideWidth = this.currentSlideWidth; this.slideIndex = 1; this.currentMinimumSidePeekWidth = this.SIDEPEEK_WIDTH; this.currentSidePeekWidth = this.SIDEPEEK_WIDTH; this.DOT_ARRAY = []; this.currentSlideIndex = 0; this.currentEndIndex = 2; this.maxScrollPos = 0; this.numDots = 0; this.numFullSlidesThatCanFitInView = 1; this.currentFirstVisibleSlideIndex = 0; this.currentLastVisibleSlideIndex = 0; this.visibilityArray = [1]; this.observer; this.isLoaded = false; this.clickMove = false; // this.scrolling = false; this.IMAGE_CARD_CLASS = '.wm-image-card'; this.IMAGE_CARDS = document.querySelectorAll(this.IMAGE_CARD_CLASS); this.IMAGE_CARD_IMAGE_SECTION = this.IMAGE_CARD_CLASS + '__image-section'; } // sets image card image section to 3:2 ratio setImageCardImageHeight() { // get 3:2 image height // let imageHeight = this.currentSlideWidth / 1.5; // this.IMAGE_CARDS.forEach(card => { // card.querySelector(this.IMAGE_CARD_IMAGE_SECTION).setAttribute('style', 'flex-basis: ' + imageHeight + 'px;'); // }); } // checks in visiblityArray for first visible slide // returns index of first visible slide setFirstVisibleSlideIndex() { this.currentFirstVisibleSlideIndex = this.visibilityArray.findIndex((element) => element > 0); return this.visibilityArray.findIndex((element) => element > 0); } // checks in visiblityArray for last visible slide // returns index of last visible slide setLastVisibleSlideIndex() { this.currentLastVisibleSlideIndex = this.visibilityArray.findLastIndex((element) => element > 0); return this.visibilityArray.findLastIndex((element) => element > 0); } // returns width of visible portion of the slideshow getCurrentViewWidth() { if (this.INNERTRACK.offsetWidth === 0) { return this.CONTAINER.offsetWidth; } else { return this.INNERTRACK.offsetWidth; } } fullWidthCheck() { let maxWidth = this.calculateCurrentSlideshowWidth(); this.currentViewWidth = this.getCurrentViewWidth(); if (maxWidth > this.MAX_INNERCONTAINER_WIDTH_WIDESCREEN) maxWidth = this.MAX_INNERCONTAINER_WIDTH_WIDESCREEN; if (this.currentViewWidth >= maxWidth) { this.SLIDESHOW.classList.add('-full-width') } else { this.SLIDESHOW.classList.remove('-full-width') } } // calculates current total width of the slides + gaps calculateCurrentSlideshowWidth() { let sumOfSlideWidths = this.TOTAL_SLIDES * this.currentSlideWidth; let sumOfGaps = (this.TOTAL_SLIDES - 1) * this.currentGapWidth; return sumOfSlideWidths + sumOfGaps; } // calculates current total width of the slides + gaps + fake slide calculateFullSlideshowWidth() { let sumOfSlideWidths = this.TOTAL_SLIDES * this.currentSlideWidth; let sumOfGaps = (this.TOTAL_SLIDES - 1) * this.currentGapWidth; let fakeSlideWidth = this.FAKE_SLIDEWIDTH + this.currentGapWidth; return sumOfSlideWidths + sumOfGaps + fakeSlideWidth; } // calculates current total width of the slides + gaps that are before a slide calculateFullSlideshowWidthBeforeIndex(index) { let sumOfSlideWidths = index * this.currentSlideWidth; let sumOfGaps = index * this.currentGapWidth; let sidepeek = this.SIDEPEEK_WIDTH; return sumOfSlideWidths + sumOfGaps + sidepeek; } // calculates max width of slideshow at narrowest slide width + gaps + sidepeeks calculateMaxSlideshowWidth() { let sumOfSlideWidths = this.TOTAL_SLIDES * this.MIN_SLIDEWIDTH; let sumOfGaps = (this.TOTAL_SLIDES - 1) * this.currentGapWidth; let sumOfSidePeeks = this.SIDEPEEK_WIDTH * 2; let calcWidth = sumOfSlideWidths + sumOfGaps + sumOfSidePeeks; this.MAX_VISIBLEWIDTH = calcWidth > this.MAX_FULL_SLIDESHOW_WIDTH ? 1288 : calcWidth; return this.MAX_VISIBLEWIDTH; } setSidePeekWidth() { if (window.innerWidth < 700) { this.SIDEPEEK_WIDTH = 22; } else { this.SIDEPEEK_WIDTH = 44; } } // calculates screen widths where slides can't get narrower per minimum width // returns array getNarrowestSlideBreakpoints() { let narrowBreakpointsArray = []; // narrowest slide width (x n), plus gap(x n), plus peek (x2) let numSlides = 1; while (narrowBreakpointsArray.length === 0 || narrowBreakpointsArray.at(-1) < this.MAX_VISIBLEWIDTH) { let gap = this.GAP_LG; let breakpoint = (numSlides * this.MIN_SLIDEWIDTH) + ((numSlides + 1) * gap) + (this.currentMinimumSidePeekWidth * 2); if (breakpoint < this.MAX_VISIBLEWIDTH) { narrowBreakpointsArray.push(breakpoint); numSlides += 1; } else { break; } } return narrowBreakpointsArray; } // takes the narrow breakpoint array and currentViewWidth // returns number of slides that should be showing getNumSlidesThatCanFitTheCurrentViewWidth() { this.currentViewWidth = this.getCurrentViewWidth(); for (let index = 0; index < this.NARROW_BREAKPOINTS.length; index++) { // currently there are max 4 slides if (this.currentViewWidth >= this.MAX_VISIBLEWIDTH) { return 4; } if (this.currentViewWidth > this.NARROW_BREAKPOINTS.at(-1)) { return 3; } if (this.currentViewWidth >= this.NARROW_BREAKPOINTS[1] && this.currentViewWidth < this.NARROW_BREAKPOINTS[2]) { return 2; } if (this.currentViewWidth < this.NARROW_BREAKPOINTS[1]) { return 1; } } } // calculates width of slides to fit the current view // returns width as number calculateSlideWidth() { this.numFullSlidesThatCanFitInView = this.getNumSlidesThatCanFitTheCurrentViewWidth(); let slideWidth = (this.currentViewWidth - (this.currentGapWidth * (this.numFullSlidesThatCanFitInView + 1)) - (this.currentMinimumSidePeekWidth * 2)) / this.numFullSlidesThatCanFitInView; if (slideWidth > this.MAX_SLIDEWIDTH) { slideWidth = this.MAX_SLIDEWIDTH; } else if (slideWidth < this.MIN_SLIDEWIDTH) { slideWidth = this.MIN_SLIDEWIDTH; } return parseInt(slideWidth, 10); } // updates width of slides // updates currentSlideWidth variable // returns width as number setSlideWidth() { this.newSlideWidth = this.calculateSlideWidth(); if (this.currentViewWidth < this.MAX_FULL_TRACK_WIDTH && this.currentViewWidth >= this.MAX_VISIBLEWIDTH) { this.newSlideWidth = (this.currentViewWidth - (this.currentGapWidth * (this.TOTAL_SLIDES - 1)) - (this.SIDEPEEK_WIDTH * 2)) / this.TOTAL_SLIDES; this.newSlideWidth = this.newSlideWidth > this.MAX_SLIDEWIDTH_FULLSCREEN ? this.MAX_SLIDEWIDTH_FULLSCREEN : this.newSlideWidth; } else if (this.currentViewWidth >= this.MAX_FULL_TRACK_WIDTH) { this.newSlideWidth = this.MAX_SLIDEWIDTH_FULLSCREEN; } for (let index = 0; index < this.TOTAL_SLIDES; index++) { const slide = this.SLIDE_ARRAY[index]; slide.style.width = this.newSlideWidth + "px"; } this.currentSlideWidth = this.newSlideWidth; return this.newSlideWidth; } moveSlideshow(index) { let newLeftPos = 0; this.clickMove = true; // called from first dot or at full 4-card view if (index === 0 || index === -1) { newLeftPos = 0; this.currentSlideIndex = 0; this.updateCurrentDot(0, "move"); } else if (index === (this.numDots - 1)) { // if last dot clicked go to end this.maxScrollPos = (this.calculateFullSlideshowWidth() - this.currentViewWidth + this.SIDEPEEK_WIDTH) * -1; newLeftPos = this.maxScrollPos * -1; this.currentSlideIndex = this.setFirstVisibleSlideIndex(); this.updateCurrentDot(this.numDots - 1, "move"); } else if (this.numFullSlidesThatCanFitInView === 1) { // if one slide per view // get distance from start then center in view // get the (currentViewWidth - currentSlideWidth) / 2 // and subtract from the previous number let calculatedOffsetFromStart = this.calculateFullSlideshowWidthBeforeIndex(index); let offsetFromSide = (this.currentViewWidth - this.newSlideWidth) / 2; newLeftPos = calculatedOffsetFromStart - offsetFromSide; this.currentSlideIndex = index; this.updateCurrentDot(index, "move"); } this.INNERTRACK.scrollTo({ left: newLeftPos, behavior: 'smooth' }); } // add dot navigation to page // appends dot elements based on number of slides createDotNav() { let numOfDots = Math.ceil(this.TOTAL_SLIDES / this.numFullSlidesThatCanFitInView); this.DOTS_CONTAINER.innerHTML = ""; // make sure there are at least 2 dots numOfDots === 1 ? numOfDots = 2 : null; for (let index = 0; index < numOfDots; index++) { this.createDot(index); } // console.log("this.DOTS_CONTAINER: " + this.DOTS_CONTAINER.closest('.wm-slideshow').getAttribute('id')); this.DOT_ARRAY = Array.from(this.SLIDESHOW.querySelectorAll(this.SLIDE_CLASS + '__dot')); this.numDots = this.SLIDESHOW.querySelectorAll('.' + this.DOT_CLASS).length; } // create dot elements createDot(index) { let dotElement = document.createElement(this.DOT_ELEMENT); dotElement.classList.add(this.DOT_CLASS); if (index === 0) { dotElement.classList.add(this.DOT_CURRENT_CLASS); } dotElement.dataset.wmSlideshowDir = index; dotElement.addEventListener("click", e => this.moveSlideshow(index)); this.DOTS_CONTAINER.appendChild(dotElement); } // update dot navigation after resize // shows or hides dot elements based on number of slides updateNumDots() { this.DOT_ARRAY = this.DOTS_CONTAINER.querySelectorAll(this.SLIDE_CLASS + '__dot'); this.numFullSlidesThatCanFitInView = this.getNumSlidesThatCanFitTheCurrentViewWidth(); // remove or add dots depending on how many are needed let oldNumDots = this.numDots; let newNumDots = Math.ceil(this.TOTAL_SLIDES / this.numFullSlidesThatCanFitInView); // hide if 4+ slides can show if (this.numFullSlidesThatCanFitInView >= this.TOTAL_SLIDES) { this.DOTS_CONTAINER.style.display = 'none'; } else { // if resizing from 4 wide, show dots and set first dot to current if (oldNumDots === 1) { // show dots again this.DOTS_CONTAINER.style.display = 'flex'; } // if number of dots is changing if (newNumDots != oldNumDots) { // clean out dots this.DOTS_CONTAINER.innerHTML = ""; // add new dots for (let i = 0; i < newNumDots; i++) { this.createDot(i); } } } // update dot array and numDots variable this.DOT_ARRAY = this.DOTS_CONTAINER.querySelectorAll(this.SLIDE_CLASS + '__dot'); this.numDots = newNumDots; } // updates active dot based on current visible slides updateCurrentDot(dotIndex, source = "intersect") { // if called from clicked dot, wait until slides have scrolled // then restart observer if (source === "move") { setTimeout(() => { this.clickMove = false; }, "500"); } this.DOT_ARRAY = Array.from(this.DOTS_CONTAINER.querySelectorAll(this.SLIDE_CLASS + '__dot')); let newDotIndex = dotIndex; if (this.DOT_ARRAY.length != 0) { // remove current from all dots and add on correct dot for (let i = 0; i < this.DOT_ARRAY.length; i++) { const dot = this.DOT_ARRAY[i]; dot.classList.remove(this.DOT_CURRENT_CLASS); } this.DOT_ARRAY[newDotIndex].classList.add(this.DOT_CURRENT_CLASS); } } // appends a fake slide at the end of the slideshow to easily apply the correct right-hand padding createFakeSlide() { // create fake end slide to make padding easy let fakeSlideElement = document.createElement('LI'); fakeSlideElement.innerHTML = " "; fakeSlideElement.classList.add(this.SLIDE_CLASS_STRING + '__fake-slide'); this.SLIDE_LIST.appendChild(fakeSlideElement); } // called by intersection observer // if loaded and slideshow not being moved by dot click // update current dot based on slide visibility updateCurrentDotOnIntersect(scope) { if (scope.isLoaded && !scope.clickMove) { scope.numFullSlidesThatCanFitInView = scope.getNumSlidesThatCanFitTheCurrentViewWidth(); scope.DOT_ARRAY = Array.from(scope.DOTS_CONTAINER.querySelectorAll(scope.SLIDE_CLASS + '__dot')); const visibilityArray = scope.visibilityArray; scope.SLIDE_ARRAY = scope.SLIDESHOW.querySelectorAll(scope.SLIDE_CLASS + "__slide"); scope.TOTAL_SLIDES = scope.SLIDE_ARRAY.length; scope.LAST_SLIDEINDEX = scope.TOTAL_SLIDES - 1; scope.updateNumDots(); // for any number of cards on the screen // if first card is more visible than second if (visibilityArray[0] === 1 || visibilityArray[0] > visibilityArray[1]) { // set dot to first dot scope.updateCurrentDot(0); return; } // if last card is more visible than the one before it if (visibilityArray[scope.LAST_SLIDEINDEX] === 1 || visibilityArray[scope.LAST_SLIDEINDEX] > visibilityArray[scope.LAST_SLIDEINDEX - 1]) { // set dot to last dot scope.updateCurrentDot(scope.DOT_ARRAY.length - 1); return; } // if one card is visible on the screen if (scope.numFullSlidesThatCanFitInView === 1) { for (let index = 0; index < scope.visibilityArray.length; index++) { // if it's the most visible card, set current dot to index if (visibilityArray[index] > visibilityArray[index - 1] && visibilityArray[index] > visibilityArray[index + 1]) { scope.updateCurrentDot(index); return; } } } // if two cards are visible on the screen and there are 4 slides total // if the visibility sum of the first two slides is greater than // the visibility sum of the second two slides if (scope.numFullSlidesThatCanFitInView === 2 && scope.TOTAL_SLIDES === 4) { if (visibilityArray[0] + visibilityArray[1] > visibilityArray[2] + visibilityArray[3]) { scope.updateCurrentDot(0); return; } } // if 2 cards are visible on the screen and there are 3 slides total if (scope.numFullSlidesThatCanFitInView === 2 && scope.TOTAL_SLIDES === 3) { if (visibilityArray[0] + visibilityArray[1] > visibilityArray[1] + visibilityArray[2]) { scope.updateCurrentDot(0); return; } } // if three cards are visible on the screen if (scope.numFullSlidesThatCanFitInView === 3 && scope.TOTAL_SLIDES === 4) { // if the visibility sum of the first two slides is greater than // the visibility sum of the second two slides if (visibilityArray[0] + visibilityArray[1] + visibilityArray[2] > visibilityArray[1] + visibilityArray[2] + visibilityArray[3]) { scope.updateCurrentDot(0); return; } } // otherwise... scope.updateCurrentDot(1); return; } } // called on resize // updates dot nav depending on which slide is first visible // updates maxScrollPos variable updateSlideshowAfterResize() { this.setSidePeekWidth(); this.setSlideWidth(); this.fullWidthCheck(); this.numFullSlidesThatCanFitInView = this.getNumSlidesThatCanFitTheCurrentViewWidth(); if (this.numFullSlidesThatCanFitInView < this.TOTAL_SLIDES) { // update dot nav depending on which slide is first visible this.updateCurrentDotOnIntersect(this); this.maxScrollPos = (this.calculateFullSlideshowWidth() - this.currentViewWidth + this.SIDEPEEK_WIDTH) * -1; } this.setImageCardImageHeight(); } // called on initialization // sets up slide widths, initial position, dot nav, image heights, fake slide, and intersection observer setupSlideshow() { this.setSidePeekWidth(); this.NARROW_BREAKPOINTS = this.getNarrowestSlideBreakpoints(); this.MAX_VISIBLEWIDTH = this.calculateMaxSlideshowWidth(); this.fullWidthCheck(); this.numFullSlidesThatCanFitInView = this.getNumSlidesThatCanFitTheCurrentViewWidth(); this.setSlideWidth(); this.INNERTRACK.scrollTo({ left: 0, behavior: 'smooth' }); // we are ready to show the slideshow this.SLIDESHOW.classList.remove('-loading'); this.SLIDE_ARRAY.forEach((slide) => { slide.setAttribute('aria-hidden', 'false'); }); // this.INNERTRACK.addEventListener('scroll', () => { // console.log('scrolling'); // this.scrolling = true; // }, false) this.createDotNav(); // this.DOT_ARRAY = Array.from(this.DOTS_CONTAINER.querySelectorAll(this.SLIDE_CLASS + '__dot')); // for (let i = 0; i < this.DOT_ARRAY.length; i++) { // const dot = this.DOT_ARRAY[i]; // dot.addEventListener("click", e => this.moveSlideshow(i)); // this.DOTS_CONTAINER.appendChild(dot); // this.DOT_ARRAY[i] = dot; // } this.setImageCardImageHeight(); this.createFakeSlide(); // INTERSECTION OBSERVER // watches for when slides go on and off the screen // calls updateCurrentDotOnIntersect let scope = this; let slideTrack = this.INNERTRACK; let slideArray = Array.from(scope.SLIDESHOW.querySelectorAll(scope.SLIDE_CLASS + "__slide")); let visibilityArray = this.visibilityArray; let updateCurrentDotOnIntersectFn = this.updateCurrentDotOnIntersect; this.observer = new IntersectionObserver(entries => { entries.forEach((entry) => { let slideIndex = slideArray.indexOf(entry.target); // console.log("entry: " + slideIndex + ": " + `${Math.round(entry.intersectionRatio * 100)}%`); visibilityArray[slideIndex] = entry.intersectionRatio; updateCurrentDotOnIntersectFn(scope) }); // threshold 0 means completely out of view // 1 means slide is 100% in view }, { root: slideTrack, threshold: [0, .1, .2, .3, .4, .5, .6, .7, .8, .9, 1], delay: 100 }) // add observer slideArray.forEach(element => { this.observer.observe(element); }); // this.startIntersectionObserver(); this.isLoaded = true; } } let jsIsInit = false; function initWMRowSlideshow() { if (!jsIsInit) { let slideshowsOnPage = document.querySelectorAll('.wm-slideshow'); for (let index = 0; index < slideshowsOnPage.length; index++) { const slideshow = slideshowsOnPage[index]; let noSlides = slideshow.closest('.wm-row').classList.contains('-no-slides'); if (!noSlides) { let slideshowId = slideshow.closest('.wm-row').getAttribute('id'); // init slideshow let wmSlideshow = new wmRowSlideshow(slideshowId); wmSlideshow.setupSlideshow(); // bind resize function wmSlideshow.updateSlideshowAfterResize.bind(wmSlideshow); let timeout; // update slideshow after resize window.addEventListener('resize', function () { if (timeout) { window.cancelAnimationFrame(timeout); } timeout = window.requestAnimationFrame(function () { wmSlideshow.updateSlideshowAfterResize(); }); }) } } jsIsInit = true; } }