Skip to content

Instantly share code, notes, and snippets.

@hellobrian
Created September 5, 2017 19:25
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save hellobrian/43c4eb5f8a1bf4fb20abeed616e94228 to your computer and use it in GitHub Desktop.
Save hellobrian/43c4eb5f8a1bf4fb20abeed616e94228 to your computer and use it in GitHub Desktop.
carousel and lightbox
@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;
}
}
<!-- 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>
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