Created
September 5, 2017 19:25
-
-
Save hellobrian/43c4eb5f8a1bf4fb20abeed616e94228 to your computer and use it in GitHub Desktop.
carousel and lightbox
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
@import '../../globals/scss/colors'; | |
@import '../../globals/scss/typography'; | |
@import '../../globals/scss/helper-mixins'; | |
@import '../../globals/scss/import-once'; | |
@import '../../globals/scss/css--reset'; | |
@import '../../globals/scss/css--typography'; | |
@include exports('carousel') { | |
.bx--carousel { | |
display: flex; | |
align-items: center; | |
} | |
.bx--carousel-container { | |
max-width: rem(808px); | |
overflow: hidden; | |
padding: 0 1px; | |
} | |
.bx--filmstrip { | |
display: flex; | |
justify-content: space-between; | |
transition: transform 100ms $bx--ease-in; | |
padding: rem(24px) 0; | |
} | |
.bx--filmstrip-btn { | |
@include button-reset; | |
height: rem(20px); | |
width: rem(20px); | |
margin-bottom: 1rem; | |
margin-right: rem(3px); | |
margin-left: rem(3px); | |
&:hover { | |
cursor: pointer; | |
} | |
&:focus { | |
@include focus-outline; | |
} | |
} | |
.bx--filmstrip-indicator-ctn { | |
display: flex; | |
flex-direction: row; | |
justify-content: center; | |
} | |
.bx--filmstrip-indicator { | |
position: relative; | |
left: -1px; | |
height: rem(10px); | |
width: rem(10px); | |
border: 1px solid $brand-01; | |
background: transparent; | |
border-radius: 50%; | |
} | |
.bx--filmstrip-indicator--active { | |
background: $brand-01; | |
} | |
.bx--carousel__btn { | |
@include button-reset(false); | |
cursor: pointer; | |
padding: 0; | |
&:first-child { | |
margin-right: 1.25rem; | |
} | |
&:last-child { | |
margin-left: 1.25rem; | |
} | |
&:focus { | |
@include focus-outline; | |
} | |
&:last-of-type { | |
transform: rotate(180deg); | |
} | |
svg { | |
height: rem(24px); | |
width: rem(16px); | |
fill: $brand-01; | |
} | |
} | |
.bx--carousel__item { | |
@include button-reset; | |
padding: 0; | |
line-height: 0; | |
margin-right: rem(20px); | |
cursor: pointer; | |
&:hover, | |
&:focus { | |
@include focus-outline; | |
} | |
} | |
.bx--carousel__item--active { | |
@include focus-outline; | |
} | |
} |
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
@import '../../globals/scss/colors'; | |
@import '../../globals/scss/typography'; | |
@import '../../globals/scss/helper-mixins'; | |
@import '../../globals/scss/import-once'; | |
@import '../../globals/scss/css--reset'; | |
@import '../../globals/scss/css--typography'; | |
@include exports('lightbox') { | |
.bx--lightbox { | |
width: rem(1056px); | |
// height: rem(594px); | |
height: rem(786px); | |
@include layer('pop-out'); | |
} | |
.bx--lightbox__main { | |
position: relative; | |
} | |
.bx--lightbox__btn { | |
border: 0; | |
background: transparent; | |
cursor: pointer; | |
position: absolute; | |
top: 50%; | |
&:first-of-type { | |
left: rem(-32px); | |
} | |
&:last-of-type { | |
right: rem(-32px); | |
transform: rotate(180deg); | |
} | |
svg { | |
height: rem(24px); | |
fill: $ui-05; | |
} | |
} | |
.bx--lightbox__item { | |
display: none; | |
width: 100%; | |
} | |
.bx--lightbox__item--shown { | |
display: block; | |
} | |
.bx--lightbox__footer { | |
background: $ui-01; | |
overflow: hidden; | |
} | |
} |
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
<div class="bx--type-omega">Carousel Title</div> | |
<div class="bx--carousel" data-carousel> | |
<button class="bx--carousel__btn" data-scroll-left> | |
<svg class="bx--pagination__button-icon" width="8" height="12" viewBox="0 0 8 12" fill-rule="evenodd"> | |
<path d="M7.5 10.6L2.8 6l4.7-4.6L6.1 0 0 6l6.1 6z"></path> | |
</svg> | |
</button> | |
<div class="bx--carousel-container"> | |
<div class="bx--filmstrip" tabindex="-1"> | |
<button class="bx--carousel__item" data-modal-target="#carousel-lightbox" data-carousel-item-index="0"> | |
<img src="http://via.placeholder.com/256x144?text=/0"> | |
</button> | |
<button class="bx--carousel__item" data-modal-target="#carousel-lightbox" data-carousel-item-index="1"> | |
<img src="http://via.placeholder.com/256x144?text=1"> | |
</button> | |
<button class="bx--carousel__item" data-modal-target="#carousel-lightbox" data-carousel-item-index="2"> | |
<img src="http://via.placeholder.com/256x144?text=2"> | |
</button> | |
<button class="bx--carousel__item" data-modal-target="#carousel-lightbox" data-carousel-item-index="3"> | |
<img src="http://via.placeholder.com/256x144?text=3"> | |
</button> | |
<button class="bx--carousel__item" data-modal-target="#carousel-lightbox" data-carousel-item-index="4"> | |
<img src="http://via.placeholder.com/256x144?text=4"> | |
</button> | |
<button class="bx--carousel__item" data-modal-target="#carousel-lightbox" data-carousel-item-index="5"> | |
<img src="http://via.placeholder.com/256x144?text=5"> | |
</button> | |
</div> | |
</div> | |
<button class="bx--carousel__btn" data-scroll-right> | |
<svg class="bx--pagination__button-icon" width="8" height="12" viewBox="0 0 8 12" fill-rule="evenodd"> | |
<path d="M7.5 10.6L2.8 6l4.7-4.6L6.1 0 0 6l6.1 6z"></path> | |
</svg> | |
</button> | |
</div> | |
<div id="carousel-lightbox" class="bx--modal" data-modal> | |
<div class="bx--lightbox" data-lightbox data-lightbox-index="0"> | |
<div class="bx--lightbox__main"> | |
<button class="bx--lightbox__btn" data-scroll-left> | |
<svg class="bx--pagination__button-icon" width="8" height="12" viewBox="0 0 8 12" fill-rule="evenodd"> | |
<path d="M7.5 10.6L2.8 6l4.7-4.6L6.1 0 0 6l6.1 6z"></path> | |
</svg> | |
</button> | |
<img src="http://via.placeholder.com/1056x594?text=/0" class="bx--lightbox__item"> | |
<img src="http://via.placeholder.com/1056x594?text=1" class="bx--lightbox__item"> | |
<img src="http://via.placeholder.com/1056x594?text=2" class="bx--lightbox__item"> | |
<img src="http://via.placeholder.com/1056x594?text=3" class="bx--lightbox__item"> | |
<img src="http://via.placeholder.com/1056x594?text=4" class="bx--lightbox__item"> | |
<img src="http://via.placeholder.com/1056x594?text=5" class="bx--lightbox__item"> | |
<button class="bx--lightbox__btn" data-scroll-right> | |
<svg class="bx--pagination__button-icon" width="8" height="12" viewBox="0 0 8 12" fill-rule="evenodd"> | |
<path d="M7.5 10.6L2.8 6l4.7-4.6L6.1 0 0 6l6.1 6z"></path> | |
</svg> | |
</button> | |
</div> | |
<div class="bx--lightbox__footer"> | |
<div class="bx--filmstrip"> | |
<button class="bx--carousel__item" data-carousel-item-index="0"> | |
<img src="http://via.placeholder.com/256x144?text=/0"> | |
</button> | |
<button class="bx--carousel__item" data-carousel-item-index="1"> | |
<img src="http://via.placeholder.com/256x144?text=1"> | |
</button> | |
<button class="bx--carousel__item" data-carousel-item-index="2"> | |
<img src="http://via.placeholder.com/256x144?text=2"> | |
</button> | |
<button class="bx--carousel__item" data-carousel-item-index="3"> | |
<img src="http://via.placeholder.com/256x144?text=3"> | |
</button> | |
<button class="bx--carousel__item" data-carousel-item-index="4"> | |
<img src="http://via.placeholder.com/256x144?text=4"> | |
</button> | |
<button class="bx--carousel__item" data-carousel-item-index="4"> | |
<img src="http://via.placeholder.com/256x144?text=5"> | |
</button> | |
</div> | |
<div class="bx--filmstrip-indicator-ctn"> | |
<button class="bx--filmstrip-btn"><div class="bx--filmstrip-indicator bx--filmstrip-indicator--active"></div></button> | |
<button class="bx--filmstrip-btn"><div class="bx--filmstrip-indicator"></div></button> | |
<button class="bx--filmstrip-btn"><div class="bx--filmstrip-indicator"></div></button> | |
</div> | |
</div> | |
</div> | |
</div> |
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
import mixin from '../../globals/js/misc/mixin'; | |
import createComponent from '../../globals/js/mixins/create-component'; | |
import initComponentBySearch from '../../globals/js/mixins/init-component-by-search'; | |
class Carousel extends mixin(createComponent, initComponentBySearch) { | |
/** | |
* Carousel. | |
* @extends CreateComponent | |
* @extends InitComponentBySearch | |
* @param {HTMLElement} element The element working as an carousel. | |
*/ | |
constructor(element, options) { | |
super(element, options); | |
this.filmstrip = this.element.querySelector(this.options.selectorFilmstrip); | |
this.carouselItem = this.element.querySelector(this.options.selectorCarouselItem); | |
this.element.addEventListener('click', evt => { | |
if (evt.target.matches(this.options.selectorScrollRight)) { | |
this.sideScroll('right'); | |
} | |
if (evt.target.matches(this.options.selectorScrollLeft)) { | |
this.sideScroll('left'); | |
} | |
}); | |
} | |
sideScroll = direction => { | |
const filmstripWidth = this.filmstrip.getBoundingClientRect().width; | |
const itemWidth = this.carouselItem.getBoundingClientRect().width + 20; | |
const re = /\.*translateX\((.*)px\)/i; | |
const translateXValue = this.filmstrip.style.transform | |
? Number(this.filmstrip.style.transform.split(re)[1]) | |
: 0; | |
direction = direction === 'right' ? -1 : 1; | |
const itemWidthDirection = itemWidth * direction; | |
let newTranslateValue = itemWidthDirection + translateXValue; | |
if (newTranslateValue > 0) { | |
newTranslateValue = 0; | |
} | |
if (newTranslateValue < filmstripWidth * -1) { | |
newTranslateValue = filmstripWidth * -1; | |
} | |
this.filmstrip.style.transform = `translateX(${newTranslateValue}px)`; | |
}; | |
static options = { | |
selectorInit: '[data-carousel]', | |
selectorFilmstrip: '.bx--filmstrip', | |
selectorScrollRight: '[data-scroll-right]', | |
selectorScrollLeft: '[data-scroll-left]', | |
selectorCarouselBtn: '.bx--carousel__btn', | |
selectorCarouselItem: '.bx--carousel__item', | |
}; | |
/** | |
* The map associating DOM element and accordion UI instance. | |
* @type {WeakMap} | |
*/ | |
static components = new WeakMap(); | |
} | |
export default Carousel; |
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
<!-- Already included in carousel.html --> | |
<button class="bx--btn bx--btn--primary" type="button" data-modal-target="#lightbox" data-carousel-item-index="0">Open Lightbox</button> | |
<div id="lightbox" class="bx--modal" data-modal> | |
<div class="bx--lightbox" data-lightbox data-lightbox-index="0"> | |
<div class="bx--lightbox__main"> | |
<button class="bx--lightbox__btn" data-scroll-left> | |
<svg class="bx--pagination__button-icon" width="8" height="12" viewBox="0 0 8 12" fill-rule="evenodd"> | |
<path d="M7.5 10.6L2.8 6l4.7-4.6L6.1 0 0 6l6.1 6z"></path> | |
</svg> | |
</button> | |
<img src="http://via.placeholder.com/1056x594?text=/0" class="bx--lightbox__item"> | |
<img src="http://via.placeholder.com/1056x594?text=1" class="bx--lightbox__item"> | |
<img src="http://via.placeholder.com/1056x594?text=2" class="bx--lightbox__item"> | |
<img src="http://via.placeholder.com/1056x594?text=3" class="bx--lightbox__item"> | |
<img src="http://via.placeholder.com/1056x594?text=4" class="bx--lightbox__item"> | |
<button class="bx--lightbox__btn" data-scroll-right> | |
<svg class="bx--pagination__button-icon" width="8" height="12" viewBox="0 0 8 12" fill-rule="evenodd"> | |
<path d="M7.5 10.6L2.8 6l4.7-4.6L6.1 0 0 6l6.1 6z"></path> | |
</svg> | |
</button> | |
</div> | |
<div class="bx--lightbox__footer"> | |
<div class="bx--filmstrip"> | |
<button class="bx--carousel__item" data-carousel-item-index="0"> | |
<img src="http://via.placeholder.com/256x144?text=/0"> | |
</button> | |
<button class="bx--carousel__item" data-carousel-item-index="1"> | |
<img src="http://via.placeholder.com/256x144?text=1"> | |
</button> | |
<button class="bx--carousel__item" data-carousel-item-index="2"> | |
<img src="http://via.placeholder.com/256x144?text=2"> | |
</button> | |
<button class="bx--carousel__item" data-carousel-item-index="3"> | |
<img src="http://via.placeholder.com/256x144?text=3"> | |
</button> | |
<button class="bx--carousel__item" data-carousel-item-index="4"> | |
<img src="http://via.placeholder.com/256x144?text=4"> | |
</button> | |
</div> | |
<div class="bx--filmstrip-indicator-ctn"> | |
<div class="bx--filmstrip-indicator bx--filmstrip-indicator--active"></div> | |
<div class="bx--filmstrip-indicator"></div> | |
<div class="bx--filmstrip-indicator"></div> | |
</div> | |
</div> | |
</div> | |
</div> |
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
import mixin from '../../globals/js/misc/mixin'; | |
import createComponent from '../../globals/js/mixins/create-component'; | |
import initComponentBySearch from '../../globals/js/mixins/init-component-by-search'; | |
// import eventedShowHideState from '../../globals/js/mixins/evented-show-hide-state'; | |
import eventMatches from '../../globals/js/misc/event-matches'; | |
// import on from '../../globals/js/misc/on'; | |
class Lightbox extends mixin(createComponent, initComponentBySearch) { | |
constructor(element, options) { | |
super(element, options); | |
this.activeIndex = this.element.dataset.lightboxIndex; | |
this.totalSlides = | |
[...this.element.querySelectorAll(this.options.selectorLightboxItem)].length - 1; | |
this.filmstrip = this.element.querySelector(this.options.selectorFilmstrip); | |
this.filmstripItem = this.element.querySelector(this.options.selectorFilmstripItem); | |
this.updateSlide(); | |
this.updateFilmstrip(); | |
this.element.addEventListener('click', evt => this.handleClick(evt)); | |
this.element.parentNode.addEventListener('modal-beingshown', evt => { | |
if (!evt.detail.launchingElement.dataset.carouselItemIndex) { | |
throw new Error( | |
'launchingElement must have carouselItemIndex data attribute to indicated what item to display' | |
); | |
} | |
this.activeIndex = evt.detail.launchingElement.dataset.carouselItemIndex; | |
this.updateSlide(); | |
this.updateFilmstrip(); | |
}); | |
} | |
handleClick = evt => { | |
if (evt.target.matches(this.options.selectorScrollRight)) { | |
if (this.activeIndex < this.totalSlides) { | |
this.activeIndex++; | |
this.updateSlide(); | |
this.updateFilmstrip(); | |
} | |
} | |
if (evt.target.matches(this.options.selectorScrollLeft)) { | |
if (this.activeIndex > 0) { | |
this.activeIndex--; | |
this.updateSlide(); | |
this.updateFilmstrip(); | |
} | |
} | |
const filmstripItem = eventMatches(evt, this.options.selectorFilmstripItem); | |
if (filmstripItem) { | |
this.activeIndex = filmstripItem.dataset.carouselItemIndex; | |
this.updateSlide(); | |
this.updateFilmstrip(); | |
} | |
const filmstripBtn = eventMatches(evt, this.options.selectorFilmstripBtn); | |
if (filmstripBtn) { | |
this.activeIndex = filmstripBtn.dataset.carouselItemIndex; | |
this.updateSlide(); | |
this.updateFilmstrip(); | |
this.updateFilmstripIndicator(); | |
// this.sideScroll('right'); | |
} | |
}; | |
updateFilmstripIndicator = () => { | |
const activeIndex = parseInt(this.activeIndex, 10); | |
const activeClass = this.options.classFilmstripIndicatorActiveItem; | |
const items = [ | |
...this.element.querySelectorAll(this.options.selectorFilmstripIndicator), | |
]; | |
items.forEach(item => { | |
item.classList.remove(activeClass); | |
}); | |
if (activeIndex === 0) { | |
items[0].classList.add(activeClass); | |
} | |
if (activeIndex > 0 && activeIndex >= items.length) { | |
items[items.length - 1].classList.add(activeClass); | |
} else { | |
items[1].classList.add(activeClass); | |
} | |
}; | |
updateSlide = () => { | |
const items = [...this.element.querySelectorAll(this.options.selectorLightboxItem)]; | |
items.forEach(item => item.classList.remove(this.options.classActiveItem)); | |
items[this.activeIndex].classList.add(this.options.classActiveItem); | |
}; | |
updateFilmstrip = () => { | |
const items = [...this.element.querySelectorAll(this.options.selectorFilmstripItem)]; | |
items.forEach(item => item.classList.remove(this.options.classFilmstripActiveItem)); | |
items[this.activeIndex].classList.add(this.options.classFilmstripActiveItem); | |
}; | |
sideScroll = direction => { | |
console.log('sideScroll'); | |
const filmstripWidth = this.filmstrip.getBoundingClientRect().width; | |
const itemWidth = this.filmstripItem.getBoundingClientRect().width + 20; | |
const re = /\.*translateX\((.*)px\)/i; | |
const translateXValue = this.filmstrip.style.transform | |
? Number(this.filmstrip.style.transform.split(re)[1]) | |
: 0; | |
direction = direction === 'right' ? -1 : 1; | |
const itemWidthDirection = itemWidth * direction; | |
let newTranslateValue = itemWidthDirection + translateXValue; | |
if (newTranslateValue > 0) { | |
newTranslateValue = 0; | |
} | |
if (newTranslateValue < filmstripWidth * -1) { | |
newTranslateValue = filmstripWidth * -1; | |
} | |
this.filmstrip.style.transform = `translateX(${newTranslateValue}px)`; | |
}; | |
static options = { | |
selectorInit: '[data-lightbox]', | |
selectorScrollRight: '[data-scroll-right]', | |
selectorScrollLeft: '[data-scroll-left]', | |
selectorLightboxItem: '.bx--lightbox__item', | |
selectorFilmstrip: '.bx--filmstrip', | |
selectorFilmstripBtn: '.bx--filmstrip-btn', | |
selectorFilmstripIndicator: '.bx--filmstrip-indicator', | |
selectorFilmstripItem: '.bx--carousel__item', | |
classActiveItem: 'bx--lightbox__item--shown', | |
classFilmstripActiveItem: 'bx--carousel__item--active', | |
classFilmstripIndicatorActiveItem: 'bx--filmstrip-indicator--active', | |
}; | |
/** | |
* The map associating DOM element and accordion UI instance. | |
* @type {WeakMap} | |
*/ | |
static components = new WeakMap(); | |
} | |
export default Lightbox; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment