Created
January 16, 2018 20:18
-
-
Save styks1987/23ce58f12a3f1ec2167d233f6c197162 to your computer and use it in GitHub Desktop.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
ready(function(){ | |
/** | |
* Discover any fancy slideshows that exist on the page | |
*/ | |
function fancySlideshows () { | |
this.discover = function () { | |
var slideshows = document.querySelectorAll('.fancy-slideshow'); | |
if (slideshows.length > 0 ){ | |
slideshows.forEach(function(s){ | |
new fancySlideshow(s); | |
}.bind(this)) | |
} | |
}; | |
this.discover(); | |
}; | |
/** | |
* Manage a single fancy slideshow instance | |
* @param instance - the slideshow element to start working from | |
*/ | |
function fancySlideshow (instance) { | |
this.refs = {}; | |
this.state = { | |
active_slide: null, | |
active_content: null, | |
current: 0, //the current slide index | |
count: 0 //how many slides there are | |
}; | |
this.__construct = function () { | |
this.discover(); | |
this.listen(); | |
}; | |
this.discover = function () { | |
this.refs = { | |
slide_container : instance.querySelector('.fancy-slideshow__slides-container'), | |
slides : instance.querySelectorAll('.fancy-slideshow__slide'), | |
content_container : instance.querySelector('.fancy-slideshow__content-container'), | |
content : instance.querySelectorAll('.fancy-slideshow__content'), | |
numbers : instance.querySelector('.fancy-slideshow__progress-numbers'), | |
slider : instance.querySelector('.fancy-slideshow__progress-slider'), | |
arrow_right : instance.querySelector('.fancy-slideshow__arrow-right'), | |
arrow_left: instance.querySelector('.fancy-slideshow__arrow-left') | |
}; | |
//count the slides | |
this.state.count = this.refs.slides.length; | |
this.state.active_slide = this.refs.slides[0]; | |
this.state.active_content = this.refs.content[0]; | |
//update the numbers | |
this.updateNumbers(); | |
//add a class to the bar that changes the width of the slider | |
this.refs.slider.classList.add('n' + this.state.count); | |
//update the content height | |
this.updateContentContainer(); | |
}; | |
this.listen = function () { | |
var hammer = new Hammer(this.refs.slide_container), | |
throttle = PointUtility.throttle(this.updateContentContainer.bind(this), 100, true); | |
//handle clicks on the controls | |
this.refs.arrow_left.addEventListener('click', this.handleBackward.bind(this)); | |
this.refs.arrow_right.addEventListener('click', this.handleForward.bind(this)); | |
//handle swiping actions on the slideshow container to update slides (Using hammer JS to detect the swipes) | |
hammer.on('swiperight', this.handleBackward.bind(this, 'left')); | |
hammer.on('swipeleft', this.handleForward.bind(this, 'right')); | |
window.addEventListener('resize', throttle); | |
}; | |
/** | |
* Move the slideshow backward | |
* Transitions use CSS and rely on class changes | |
*/ | |
this.handleBackward = function (direction) { | |
var go_to = null, | |
next_slide, | |
current_slide; | |
if(this.state.current === 0){ | |
go_to = this.state.count - 1; | |
} else { | |
go_to = this.state.current - 1; | |
} | |
next_slide = this.refs.slides[go_to]; | |
current_slide = this.refs.slides[this.state.current]; | |
//update the content | |
this.updateContent(this.state.current, go_to); | |
if(direction === 'left') { | |
this.transitionLeft(current_slide, next_slide); | |
} else { | |
this.transitionRight(current_slide, next_slide); | |
} | |
this.state.current = go_to; | |
this.state.active_slide = next_slide; | |
this.updateBar(); | |
this.updateNumbers(); | |
}; | |
/** | |
* Move the slideshow forward | |
* Transitions use CSS and rely on class changes | |
*/ | |
this.handleForward = function (direction) { | |
var go_to = null, | |
next_slide, | |
current_slide; | |
if(this.state.current === this.state.count - 1){ | |
go_to = 0; | |
} else { | |
go_to = this.state.current + 1; | |
} | |
next_slide = this.refs.slides[go_to]; | |
current_slide = this.refs.slides[this.state.current]; | |
//update the content | |
this.updateContent(this.state.current, go_to); | |
if(direction === 'right') { | |
this.transitionRight(current_slide, next_slide); | |
} else { | |
this.transitionLeft(current_slide, next_slide); | |
} | |
this.state.current = go_to; | |
this.state.active_slide = next_slide; | |
this.updateBar(); | |
this.updateNumbers(); | |
}; | |
this.transitionRight = function (current_slide, next_slide) { | |
//set up slide to come from right | |
next_slide.classList.remove('animating'); | |
next_slide.classList.add('right'); | |
//create a tiny time hiccup for the effect to work | |
//this allows the slide to get off the screen before starting the animation | |
setTimeout(function () { | |
//send active back left | |
current_slide.classList.remove('right'); | |
current_slide.classList.add('animating'); | |
current_slide.classList.remove('active'); | |
//bring next slide in from right | |
next_slide.classList.add('animating'); | |
next_slide.classList.add('active'); | |
}.bind(this), 1); | |
}; | |
this.transitionLeft = function (current_slide, next_slide) { | |
//set up slide to come from left | |
next_slide.classList.remove('animating'); | |
next_slide.classList.remove('right'); | |
//create a tiny time hiccup for the effect to work | |
//this allows the slide to get off the screen before starting the animation | |
setTimeout(function () { | |
//send active back left | |
current_slide.classList.add('right'); | |
current_slide.classList.add('animating'); | |
current_slide.classList.remove('active'); | |
//bring next slide in from right | |
next_slide.classList.add('animating'); | |
next_slide.classList.add('active'); | |
}.bind(this), 1); | |
}; | |
/** | |
* Adds or removes the active class to the respective slide content section | |
* @param current_index | |
* @param next_index | |
*/ | |
this.updateContent = function (current_index, next_index) { | |
this.refs.content[current_index].classList.remove('active'); | |
this.refs.content[next_index].classList.add('active'); | |
}; | |
/** | |
* Update the slide count numbers | |
* Shows which slide out of how many the user is on | |
*/ | |
this.updateNumbers = function () { | |
var nums = document.createElement('span'); | |
nums.textContent = (this.state.current + 1 < 9 ? '0' + (this.state.current + 1) : this.state.current) + ' / ' + (this.state.count < 9 ? '0' + this.state.count : this.state.count); | |
this.refs.numbers.innerHTML = ''; | |
this.refs.numbers.appendChild(nums); | |
}; | |
/** | |
* Update the slider bar to show how far along the slideshow is | |
*/ | |
this.updateBar = function () { | |
var percentage_advanced = this.state.current * 100; | |
this.refs.slider.style.transform = 'translateX(' + percentage_advanced + '%)'; | |
}; | |
/** | |
* Update the content container to be the height of the tallest bit of content | |
* This method is a little gross, but its what works | |
* @param e | |
*/ | |
this.updateContentContainer = function (e) { | |
var tallest = 0, | |
clone_container = document.createElement('div'); | |
//set up a container to hold clones of the side content parts | |
clone_container.style.position = 'absolute'; | |
clone_container.style.top = '-10000px'; | |
clone_container.style.left = '-10000px'; | |
clone_container.style.width = this.refs.content_container.offsetWidth + 'px'; | |
document.body.appendChild(clone_container); | |
//for each slide content bit, make a copy and then check the height | |
this.refs.content.forEach(function(item){ | |
var clone = item.cloneNode(true); | |
clone.style.height = 'auto'; | |
clone.style.position = 'relative'; | |
clone_container.appendChild(clone); | |
if(clone.offsetHeight > tallest){ | |
tallest = clone.offsetHeight; | |
} | |
clone_container.removeChild(clone); | |
}); | |
//remove the clone container | |
clone_container.parentNode.removeChild(clone_container); | |
this.refs.content_container.style.minHeight = tallest + 'px'; | |
}; | |
this.__construct(); | |
} | |
new fancySlideshows(); | |
}); |
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
.fancy-slideshow | |
position: relative | |
.fancy-slideshow__slides-container | |
position: relative | |
background: #333 | |
.fancy-slideshow__slides | |
position: relative | |
padding-bottom: 0 | |
min-height: 300px | |
@include bp(medium) | |
height: auto | |
padding-bottom: 40% | |
.fancy-slideshow__slide | |
position: absolute | |
top: 0 | |
left: 0 | |
height: 100% | |
width: 100% | |
z-index: 1 | |
overflow: hidden | |
transform: translateX(-100%) | |
img | |
display: block | |
position: absolute | |
top: 50% | |
left: 0 | |
transform: translateY(-50%) translateX(-10%) | |
height: 100% | |
width: auto | |
max-width: none | |
pointer-events: none | |
@include bp(small) | |
left: 50% | |
transform: translateY(-50%) translateX(-50%) | |
@include bp(medium) | |
width: 100% | |
height: auto | |
max-width: 100% | |
&.right | |
transform: translateX(100%) | |
&.active | |
transform: translateX(0) | |
&.animating | |
transition: all 0.5s | |
.fancy-slideshow__controls | |
padding: 1.25em | |
position: absolute | |
bottom: 0 | |
left: 0 | |
width: 100% | |
display: flex | |
justify-content: space-between | |
align-items: center | |
z-index: 2 | |
.fancy-slideshow__progress-bar | |
flex-grow: 1 | |
display: block | |
height: 2px | |
background: #FFF | |
position: relative | |
.fancy-slideshow__progress-slider | |
width: 25% | |
position: absolute | |
bottom: -2px | |
height: 6px | |
background: $point-yellow | |
transition: all 0.5s | |
@for $i from 1 through 20 | |
&.n#{$i} | |
width: 100%/$i | |
.fancy-slideshow__arrows | |
flex-grow: 0 | |
padding: 0.5em 1em | |
display: flex | |
.fancy-slideshow__arrow-left, | |
.fancy-slideshow__arrow-right | |
width: 40px | |
height: 40px | |
border: 2px solid #ffffff | |
display: flex | |
justify-content: center | |
align-items: center | |
transition: all 0.2s | |
&:hover | |
background: #ffffff | |
cursor: pointer | |
svg | |
fill: $point-blue | |
svg | |
width: 25px | |
height: 25px | |
fill: #FFF | |
.fancy-slideshow__arrow-left | |
margin-right: 0.5em | |
svg | |
transform: rotate(180deg) | |
.fancy-slideshow__progress-numbers | |
flex-grow: 0 | |
padding: 0.5em 1em | |
color: #FFF | |
font-weight: bold | |
.fancy-slideshow__content-container | |
height: 300px | |
position: relative | |
@include bp(large) | |
position: absolute | |
bottom: 100px | |
//roughly height of controls | |
right: 2em | |
width: 45% | |
z-index: 3 | |
.fancy-slideshow__content | |
padding: 1.5em | |
opacity: 0 | |
position: absolute | |
width: 100% | |
height: 100% | |
display: flex | |
flex-direction: column | |
justify-content: space-between | |
transition: all 0.5s | |
@include bp(large) | |
display: block | |
bottom: 100px | |
right: 0 | |
background: rgba(255, 255, 255, 0.8) | |
width: 600px | |
height: auto | |
&:hover | |
background: rgba(255, 255, 255, 1) | |
&.active | |
opacity: 1 | |
bottom: 0 | |
z-index: 5 | |
@include bp(large) | |
bottom: 0 | |
.fancy-slideshow__headline | |
font-size: 1.5em | |
@include bp(medium) | |
font-size: 2.5em | |
.fancy-slideshow__copy | |
margin-bottom: 1em | |
.fancy-slideshow__byline | |
color: $point-blue | |
font-style: italic | |
margin-bottom: 0.875em | |
display: block | |
.fancy-slideshow__cta | |
padding-top: 0.25em | |
border-top: 1px solid $point-blue | |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment