I have found a very nice example on JSFiddle
http://jsfiddle.net/zra6fvtt/2/
When I try to save that, it does not work in my file which I created with the JSFiddle information. Here is my code:
/* =========================================================
* imageimageviewer.js
* =========================================================
* Controls the interaction with the product images on the PDP and collection PDP. A large image is presented with a
* series of thumbnails. If there are more than X (configurable) thumbnails, a scroller allows the user to see the
* others. Clicking on a thumbnail will change the large image. If the user scolls past the active thumbnail, the first thumbnail in the visible set will become active and the main image will update. If the user navigates by swiping the large image, the thumbnail strip will update to reflect the user's selection.
* ========================================================= */
(function(global, $, namespace) {
"use strict";
var Imageviewer = function Imageviewer(element, options) {
this.init('imageviewer', element, options);
},
loggingDebug = true;
//PUBLIC
Imageviewer.prototype = {
constructor: Imageviewer,
init: function init(type, element, options) {
if (loggingDebug) {
console.debug('init imageviewer with options:');
console.debug(Array.prototype.slice.call(arguments));
}
var self = this;
this.options = $.extend({}, $.fn[type].defaults, options);
this.$element = $(element);
this.$navigation = this.$element.find(this.options.thumbnail_container_class);
this.$mainView = this.$element.find(this.options.large_container_class);
this.totalSlides = this.$navigation.find(this.options.thumbnail_class).length;
this.slidesToShow = self.options.slider_min;
this.$navigation.find(this.options.thumbnail_class).first().addClass('active');
this.$mainView.slick({
slidesToShow: 1,
slidesToScroll: 1,
arrows: false,
fade: true,
infinite: false,
onAfterChange: function() {
var index = self.$mainView.slickCurrentSlide();
// catch when user has dragged the main image and update the nav to match
if (self.getActiveSlide() != index) {
self.setActiveSlide(index);
if (!self.isSlideVisible(index, self.$navigation.slickCurrentSlide())) {
self.$navigation.slickGoTo(Math.floor(index / self.slidesToShow) * self.slidesToShow);
}
}
}
});
this.$navigation.slick({
slidesToShow: self.options.slider_min,
slidesToScroll: self.options.slider_min,
dots: false,
infinite: false,
onAfterChange: function() {
var index = self.$mainView.slickCurrentSlide();
if (!self.isSlideVisible(index, self.$navigation.slickCurrentSlide())) {
self.$mainView.slickGoTo(self.getFirstVisibleSlide(self.$navigation.slickCurrentSlide()));
self.setActiveSlide(self.getFirstVisibleSlide(self.$navigation.slickCurrentSlide()));
}
}
});
this.$navigation.find(this.options.thumbnail_class).click(function(e) {
var index = parseInt(this.getAttribute('index'));
self.setActiveSlide(index);
self.$mainView.slickGoTo(index);
});
},
getFirstVisibleSlide: function(currentSlide) {
var firstSlide = currentSlide;
if (currentSlide + this.slidesToShow >= this.totalSlides) {
firstSlide = this.totalSlides - this.slidesToShow;
}
return firstSlide;
},
isSlideVisible: function(slideIndex, currentSlide) {
var isVisible = false;
if (currentSlide + this.slidesToShow > this.totalSlides) {
isVisible = (slideIndex >= this.totalSlides - this.slidesToShow) && (slideIndex <= this.totalSlides - 1);
} else {
isVisible = (slideIndex >= currentSlide) && (slideIndex <= currentSlide + this.slidesToShow - 1);
}
return isVisible;
},
getActiveSlide: function() {
var slideIndex = this.$navigation.find('.active').index() || 0;
return slideIndex;
},
setActiveSlide: function(index) {
this.$navigation.find(this.options.thumbnail_class).removeClass('active').end()
.find("[index='" + index + "']").addClass('active')
}
};
$.fn.imageviewer = function imageviewer(option) {
var el = this,
options = $.extend({}, $.fn.imageviewer.defaults, typeof option === 'object' && option);
return el.each(function() {
var data = $.data(this, 'imageviewer');
if (!data) {
$.data(this, 'imageviewer', (data = new Imageviewer(this, options)));
} else {
if (typeof option === 'object') {
$.extend(data.options, option);
}
}
});
};
$.fn.imageviewer.defaults = {
large_container_class: ".viewer-main",
thumbnail_container_class: ".viewer-thumbnails",
thumbnail_class: ".viewer-thumb",
slider_min: 5
};
$.fn.imageviewer.Constructor = Imageviewer;
$(function() {
$('[data-imageviewer]').imageviewer();
});
}(this, window.jQuery, "CLIENT"));
.viewer-thumbnails-container {
margin: 0 40px;
}
.viewer-thumb {
border: solid 2px transparent;
margin: 2px;
}
.viewer-thumb.active {
border: solid 2px black;
}
img {
max-width: 100%;
}
.slick-prev:before,
.slick-next:before {
color: black;
}
<script type="text/javascript" src="//cdn.jsdelivr.net/jquery.slick/1.3.15/slick.min.js"></script>
<link rel="stylesheet" type="text/css" href="//cdn.jsdelivr.net/jquery.slick/1.3.15/slick.css">
<div class="product-image-viewer" data-imageviewer>
<div class="viewer-main">
<div>
<img class="viewer-main-image" src="http://placehold.it/576x390&text=image+1" />
</div>
<div>
<img class="viewer-main-image" src="http://placehold.it/576x390&text=image+2" />
</div>
<div>
<img class="viewer-main-image" src="http://placehold.it/576x390&text=image+3" />
</div>
<div>
<img class="viewer-main-image" src="http://placehold.it/576x390&text=image+4" />
</div>
<div>
<img class="viewer-main-image" src="http://placehold.it/576x390&text=image+5" />
</div>
<div>
<img class="viewer-main-image" src="http://placehold.it/576x390&text=image+6" />
</div>
<div>
<img class="viewer-main-image" src="http://placehold.it/576x390&text=image+7" />
</div>
<div>
<img class="viewer-main-image" src="http://placehold.it/576x390&text=image+8" />
</div>
</div>
<div class="viewer-thumbnails-container">
<div class="viewer-thumbnails">
<div class="viewer-thumb">
<img class="viewer-thumb-image" src="http://placehold.it/96x65&text=image+1" />
</div>
<div class="viewer-thumb">
<img class="viewer-thumb-image" src="http://placehold.it/96x65&text=image+2" />
</div>
<div class="viewer-thumb">
<img class="viewer-thumb-image" src="http://placehold.it/96x65&text=image+3" />
</div>
<div class="viewer-thumb">
<img class="viewer-thumb-image" src="http://placehold.it/96x65&text=image+4" />
</div>
<div class="viewer-thumb">
<img class="viewer-thumb-image" src="http://placehold.it/96x65&text=image+5" />
</div>
<div class="viewer-thumb">
<img class="viewer-thumb-image" src="http://placehold.it/96x65&text=image+6" />
</div>
<div class="viewer-thumb">
<img class="viewer-thumb-image" src="http://placehold.it/96x65&text=image+7" />
</div>
<div class="viewer-thumb">
<img class="viewer-thumb-image" src="http://placehold.it/96x65&text=image+8" />
</div>
</div>
</div>
</div>
Add this tag <script
src="https://code.jquery.com/jquery-2.2.4.min.js"
integrity="sha256-BbhdlvQf/xTY9gja0Dq3HiwQF8LaCRTXxZKRutelT44="
crossorigin="anonymous"></script>
jQuery is imported in the fiddle
Related
I think I made a mistake in js code because it doesn't work when I click . There are no actions . What should I change in js code?Thanks. My js code:
const slides = document.querySelector(".slides");
const slidesCount = slides.childElementCount;
console.log(slidesCount)
const nextBtn=document.querySelector(".next-slide");
const prevBtn=document.querySelector(".prev-slide");
const container = document.querySelector('.slider-container')
//Controls
prevBtn.addEventListener('click', () => {
changeSlide('prev')
})
nextBtn.addEventListener('click', () => {
changeSlide('next')
})
let activeSlideIndex = 0
function changeSlide(direction) {
if(direction === 'prev') {
activeSlideIndex++
if(activeSlideIndex === slidesCount) {
activeSlideIndex = 0
}
} else if(direction === 'next') {
activeSlideIndex--
if(activeSlideIndex < 0) {
activeSlideIndex = slidesCount - 1
}
}
}
Here my html code.
<button class="prev-slide">◁</button>
<button class="next-slide">▷</button>
</div>
<div class="slides">
<img class="slide" src="images/picture1.jpg" alt="slide image">
<img class="slide" src="images/picture2.jpg" alt="slide image">
<img class="slide" src="images/picture3.jpg" alt="slide image">
</div>
I think the only thing missing was the actual rendering. You have to somehow hide or show the active slide. I've done that by adding active class and only showing that (through CSS). Then your changeSlide function does not only calculate the active slide, but also set the class on the appropriate element.
const slides = document.querySelector(".slides");
const slidesCount = slides.childElementCount;
console.log(`Showing ${slidesCount} slides.`)
const nextBtn=document.querySelector(".next-slide");
const prevBtn=document.querySelector(".prev-slide");
const container = document.querySelector('.slider-container')
//Controls
prevBtn.addEventListener('click', () => {
changeSlide('prev')
})
nextBtn.addEventListener('click', () => {
changeSlide('next')
})
let activeSlideIndex = 0
function changeSlide(direction) {
if(direction === 'prev') {
activeSlideIndex++
if(activeSlideIndex === slidesCount) {
activeSlideIndex = 0
}
} else if(direction === 'next') {
activeSlideIndex--
if(activeSlideIndex < 0) {
activeSlideIndex = slidesCount - 1
}
}
Array.from(slides.children).forEach((slide, idx) => {
if (idx === activeSlideIndex) {
slide.classList.add('active');
} else {
slide.classList.remove('active');
}
});
}
.controls {
margin-bottom: 2em;
}
.slides .slide {
display: none
}
.slides .slide.active {
display: block;
}
<section class="controls">
<button class="prev-slide">◁</button>
<button class="next-slide">▷</button>
</section>
<div class="slides">
<img class="slide active" src="https://via.placeholder.com/450x250" alt="slide image">
<img class="slide" src="https://loremflickr.com/640/250" alt="slide image">
<img class="slide" src="https://www.fillmurray.com/640/250" alt="slide image">
</div>
I'm using the code below to create a 'rotation' of images for display on a website. I wish for the images to display within a 'div' element...and i'm having trouble accomplishing that. It seems the problem is when I attempt to set each image as the 'background image' for the element (the line that reads "document.getElementById("rotation").style.backgroundImage = "url(toString(ImgName[number]))";). Only the initial image displays, without any 'rotation' of other images. Any help appreciated, this is becoming very frustrating.
<!DOCTYPE html>
<html>
<title>test page</title>
<meta name="viewport" content="width=device-width, initial-scale=1">
<link rel="stylesheet" href="https://www.w3schools.com/w3css/4/w3.css">
<head>
<style>
div.rotation {
height: 256px;
width: 100%;
padding: 0px;
background-color: powderblue;
border-style: solid;
border-width: 5px;
border-radius: 25px;
}
</style>
</head>
<body>
<div class="w3-quarter">
<div class="w3-padding-small">
<div class="w3-center">
<div class="rotation">
<p>
<img src='images/rotation/LA_Panel.png' id='rotateImg0' alt='image rotation' />
<img src='images/rotation/McCulloch_256.png' id='rotateImg1' style='display:none;' alt='image rotation' />
<img src='images/rotation/MO_Panel.png' id='rotateImg2' style='display:none;' alt='image rotation' />
<img src='images/rotation/Rommel.png' id='rotateImg3' style='display:none;' alt='image rotation' />
</p>
</div>
</div>
</div>
</div>
</body>
</html>
<script type='text/javascript'>
var rotation = function () {
var currentImage,
images = [],
ImgName = [],
count,
hideImages,
showImage,
fn;
count = (function () {
// Figure out how many images we have on the rotation
var x = 0;
while (document.getElementById('rotateImg' + (x + 1).toString())) {
images[x] = document.getElementById('rotateImg' + x.toString());
ImgName[x] = document.getElementById('rotateImg' + x.toString()).src;
x++;
}
return images.length;
})();
hideImages = function () {
// Hide all the images
for (var i = 0; i < count; i++) {
images[i].style.display = 'none';
}
};
showImage = function (number) {
document.getElementById("rotation").style.backgroundImage = "url(toString(ImgName[number]))";
images[number].style.display = 'block';
};
fn = {};
fn.setupRotation = function () {
// Show the first image
currentImage = 0;
showImage(currentImage);
// Start the rotation
var interval = setInterval(rotation.advanceRotation, 4000);
};
fn.advanceRotation = function () {
if (currentImage + 1 == count)
currentImage = 0;
else
currentImage++;
hideImages();
showImage(currentImage);
};
return fn;
} ();
rotation.setupRotation();
</script>
One thought might be to pluck off the first child and slam him to the end of the line.
let images = document.querySelector('#images');
setInterval(() => {
let el = images.removeChild(images.childNodes[0]);
images.appendChild(el);
}, 1000);
#images {
font-size: 0;
}
.img {
display: inline-block;
width: 30px;
height: 30px;
}
<div id="images">
<div class="img" style="background-color: red"></div>
<div class="img" style="background-color: orange"></div>
<div class="img" style="background-color: yellow"></div>
<div class="img" style="background-color: green"></div>
<div class="img" style="background-color: blue"></div>
</div>
I'm trying to make a double image slider commanded by the same button, but, with the code I have, I can't find how to select two different elements or all the instance on an element
html:
<div class="slider-box">
<div class="slider" id="slider">
<div class="slider__item">
<img src="https://placeimg.com/960/540/animals" alt="">
<h2 class="slider__item__title">Slide 1 Title</h2>
</div>
<div class="slider__item">
<img src="https://placeimg.com/960/540/arch" alt="">
<h2 class="slider__item__title">Slide 2 Title</h2>
</div>
<div class="slider__item">
<img src="https://placeimg.com/960/540/nature" alt="">
<h2 class="slider__item__title">Slide 3 Title</h2>
</div>
<div class="slider__item">
<img src="https://placeimg.com/960/540/people" alt="">
<h2 class="slider__item__title">Slide 4 Title</h2>
</div>
<div class="slider__item">
<img src="https://placeimg.com/960/540/tech" alt="">
<h2 class="slider__item__title">Slide 5 Title</h2>
</div>
</div>
<div class="slider" id="slider">
<div class="slider__item">
<img src="https://placeimg.com/960/540/animals" alt="">
<h2 class="slider__item__title">Slide 1 Title</h2>
</div>
<div class="slider__item">
<img src="https://placeimg.com/960/540/arch" alt="">
<h2 class="slider__item__title">Slide 2 Title</h2>
</div>
<div class="slider__item">
<img src="https://placeimg.com/960/540/nature" alt="">
<h2 class="slider__item__title">Slide 3 Title</h2>
</div>
<div class="slider__item">
<img src="https://placeimg.com/960/540/people" alt="">
<h2 class="slider__item__title">Slide 4 Title</h2>
</div>
<div class="slider__item">
<img src="https://placeimg.com/960/540/tech" alt="">
<h2 class="slider__item__title">Slide 5 Title</h2>
</div>
</div>
</div>
<div class="slider-nav">
<div class="slider-nav__prev" id="prev"><i class="fa fa-angle-left"></i></div>
<div class="slider-nav__next" id="next"><i class="fa fa-angle-right"></i></div>
<div class="slider-nav__dots" id="dots"></div>
</div>
Js:
(function($) {
'use strict';
var pluginName = 'slider',
defaults = {
next: '.slider-nav__next',
prev: '.slider-nav__prev',
item: '.slider__item',
dots: false,
dotClass: 'slider__dot',
};
function slider(element, options) {
this.$document = $(document);
this.$window = $(window);
this.$element = $(element);
this.options = $.extend({}, defaults, options);
this.init();
}
slider.prototype.init = function() {
this.setup();
this.attachEventHandlers();
this.update();
}
slider.prototype.setup = function(argument) {
this.$slides = this.$element.find(this.options.item);
this.count = this.$slides.length;
this.index = 0;
this.$next = $(this.options.next);
this.$prev = $(this.options.prev);
this.$canvas = $(document.createElement('div'));
this.$canvas.addClass('slider__canvas').appendTo(this.$element);
this.$slides.appendTo(this.$canvas);
this.$dots = $(this.options.dots);
this.$dots.length && this.createDots();
};
slider.prototype.createDots = function() {
var dots = [];
for (var i = 0; i < this.count; i += 1) {
dots[i] = '<span data-index="' + i + '" class="' + this.options.dotClass + '"></span>';
}
this.$dots.append(dots);
}
slider.prototype.attachEventHandlers = function() {
this.$element.on('prev.slider', this.prev.bind(this));
this.$document.on('click', this.options.prev, (function(e) {
this.$element.trigger('prev.slider');
}).bind(this));
this.$element.on('next.slider', this.next.bind(this));
this.$document.on('click', this.options.next, (function(e) {
this.$element.trigger('next.slider');
}).bind(this));
this.$element.on('update.slider', this.update.bind(this));
this.$window.on('resize load', (function(e) {
this.$element.trigger('update.slider');
}).bind(this));
this.$element.on('jump.slider', this.jump.bind(this));
this.$document.on('click', ('.' + this.options.dotClass), (function(e) {
var index = parseInt($(e.target).attr('data-index'));
this.$element.trigger('jump.slider', index);
}).bind(this));
};
slider.prototype.next = function(e) {
this.index = (this.index + 1) % this.count;
this.slide();
};
slider.prototype.prev = function(e) {
this.index = Math.abs(this.index - 1 + this.count) % this.count;
this.slide();
};
slider.prototype.jump = function(e, index) {
this.index = index % this.count;
this.slide();
}
slider.prototype.slide = function(index) {
undefined == index && (index = this.index);
var position = index * this.width * -1;
this.$canvas.css({
'transform': 'translate3d(' + position + 'px, 0, 0)',
});
this.updateCssClass();
};
slider.prototype.update = function() {
this.width = this.$element.width();
this.$canvas.width(this.width * this.count);
this.$slides.width(this.width);
this.slide();
};
slider.prototype.updateCssClass = function() {
this.$slides
.removeClass('active')
.eq(this.index)
.addClass('active');
this.$dots
.find('.' + this.options.dotClass)
.removeClass('active')
.eq(this.index)
.addClass('active');
}
$.fn[pluginName] = function(options) {
return this.each(function() {
!$.data(this, pluginName) && $.data(this, pluginName, new slider(this, options));
});
};
})(window.jQuery);
$('#slider').slider({
prev: '#prev',
next: '#next',
dots: '#dots',
autoplay: true,
});
I'm a javascript noob, I understand what I'm reading/using, but not sure when it's time to write.
Here is my fiddle : https://jsfiddle.net/Fromager/zkgfzbcv/
1) id should be unique, so replace both id="slider" with id="slider1" and id="slider2".
2) Replace #slider with .slider at
$('.slider').slider({
prev: '#prev',
next: '#next',
dots: '#dots',
autoplay: true,
});
to set the slider() to both slides you have.
(function($) {
'use strict';
var pluginName = 'slider',
defaults = {
next: '.slider-nav__next',
prev: '.slider-nav__prev',
item: '.slider__item',
dots: false,
dotClass: 'slider__dot',
};
function slider(element, options) {
this.$document = $(document);
this.$window = $(window);
this.$element = $(element);
this.options = $.extend({}, defaults, options);
this.init();
}
slider.prototype.init = function() {
this.setup();
this.attachEventHandlers();
this.update();
}
slider.prototype.setup = function(argument) {
this.$slides = this.$element.find(this.options.item);
this.count = this.$slides.length;
this.index = 0;
this.$next = $(this.options.next);
this.$prev = $(this.options.prev);
this.$canvas = $(document.createElement('div'));
this.$canvas.addClass('slider__canvas').appendTo(this.$element);
this.$slides.appendTo(this.$canvas);
this.$dots = $(this.options.dots);
this.$dots.length && this.createDots();
};
let isInit = false; // check if the first slider is initialized
slider.prototype.createDots = function() {
if(isInit){
return; // if the first slider is initialized, do nothing.
}
var dots = [];
for (var i = 0; i < this.count; i += 1) {
dots[i] = '<span data-index="' + i + '" class="' + this.options.dotClass + '">';
// $(this.$slides[i]) is the slider__item div
dots[i] += i + '/' + $(this.$slides[i]).find('img').attr('src') + '</span>';
}
this.$dots.append(dots);
isInit = true; // after the first slider is initialized, set to true
}
slider.prototype.attachEventHandlers = function() {
this.$element.on('prev.slider', this.prev.bind(this));
this.$document.on('click', this.options.prev, (function(e) {
this.$element.trigger('prev.slider');
}).bind(this));
this.$element.on('next.slider', this.next.bind(this));
this.$document.on('click', this.options.next, (function(e) {
this.$element.trigger('next.slider');
}).bind(this));
this.$element.on('update.slider', this.update.bind(this));
this.$window.on('resize load', (function(e) {
this.$element.trigger('update.slider');
}).bind(this));
this.$element.on('jump.slider', this.jump.bind(this));
this.$document.on('click', ('.' + this.options.dotClass), (function(e) {
var index = parseInt($(e.target).attr('data-index'));
this.$element.trigger('jump.slider', index);
}).bind(this));
};
slider.prototype.next = function(e) {
this.index = (this.index + 1) % this.count;
this.slide();
};
slider.prototype.prev = function(e) {
this.index = Math.abs(this.index - 1 + this.count) % this.count;
this.slide();
};
slider.prototype.jump = function(e, index) {
this.index = index % this.count;
this.slide();
}
slider.prototype.slide = function(index) {
undefined == index && (index = this.index);
var position = index * this.width * -1;
this.$canvas.css({
'transform': 'translate3d(' + position + 'px, 0, 0)',
});
this.updateCssClass();
};
slider.prototype.update = function() {
this.width = this.$element.width();
this.$canvas.width(this.width * this.count);
this.$slides.width(this.width);
this.slide();
};
slider.prototype.updateCssClass = function() {
this.$slides
.removeClass('active')
.eq(this.index)
.addClass('active');
this.$dots
.find('.' + this.options.dotClass)
.removeClass('active')
.eq(this.index)
.addClass('active');
}
$.fn[pluginName] = function(options) {
return this.each(function() {
!$.data(this, pluginName) && $.data(this, pluginName, new slider(this, options));
});
};
})(window.jQuery);
let isInitialized = false;
$('.slider').slider({
prev: '#prev',
next: '#next',
dots: '#dots',
autoplay: true,
});
img {
max-width: 100%;
height: auto;
}
.slider-box,
.slider__item {
position: relative;
}
.slider-box{
display:flex;
}
.slider {
width:40vw;
display:inline-block;
overflow: hidden;
}
.slider__canvas {
transition: transform 0.5s;
}
.slider__item {
float: left;
}
.slider__item__title {
opacity: 0;
position: absolute;
top: 50px;
left: 50px;
/*transition: opacity 0.3s, transform 0.3s;
transform: translate3d(-50%, -60%, 0);*/
}
.active .slider__item__title {
opacity: 1;
/*transition-delay: 0.5s;
transform: translate3d(-50%, -50%, 0);*/
}
.slider-nav {
color: #fff;
text-align: center;
}
.slider-nav__dots {
position: absolute;
bottom: 20px;
left: 20px;
right: 20px;
}
.slider-nav__prev,
.slider-nav__next,
.slider__dot {
background:green;
/*backface-visibility: hidden;
transition: transform 0.3s, box-shadow 0.3s;*/
}
.slider-nav__prev,
.slider-nav__next {
position: absolute;
top: 50%;
width: 3rem;
height: 3rem;
margin-top: -1.5rem;
line-height: 3rem;
}
.slider-nav__prev {
left: 7%;
}
.slider-nav__next {
right: 7%;
}
.slider__dot {
display: inline-block;
width: 1rem;
height: 1rem;
margin: 0 1rem;
}
/*
.slider-nav__prev:hover,
.slider-nav__next:hover,
.slider__dot.active,
.slider__dot:hover {
transform: scale3d(1.5, 1.5, 1);
}*/
<script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="slider-box">
<div class="slider" id="slider1">
<div class="slider__item">
<img src="https://placeimg.com/960/540/animals" alt="">
<h2 class="slider__item__title">Slide 1 Title</h2>
</div>
<div class="slider__item">
<img src="https://placeimg.com/960/540/arch" alt="">
<h2 class="slider__item__title">Slide 2 Title</h2>
</div>
<div class="slider__item">
<img src="https://placeimg.com/960/540/nature" alt="">
<h2 class="slider__item__title">Slide 3 Title</h2>
</div>
<div class="slider__item">
<img src="https://placeimg.com/960/540/people" alt="">
<h2 class="slider__item__title">Slide 4 Title</h2>
</div>
<div class="slider__item">
<img src="https://placeimg.com/960/540/tech" alt="">
<h2 class="slider__item__title">Slide 5 Title</h2>
</div>
</div>
<div class="slider" id="slider2">
<div class="slider__item">
<img src="https://placeimg.com/960/540/animals" alt="">
<h2 class="slider__item__title">Slide 1 Title</h2>
</div>
<div class="slider__item">
<img src="https://placeimg.com/960/540/arch" alt="">
<h2 class="slider__item__title">Slide 2 Title</h2>
</div>
<div class="slider__item">
<img src="https://placeimg.com/960/540/nature" alt="">
<h2 class="slider__item__title">Slide 3 Title</h2>
</div>
<div class="slider__item">
<img src="https://placeimg.com/960/540/people" alt="">
<h2 class="slider__item__title">Slide 4 Title</h2>
</div>
<div class="slider__item">
<img src="https://placeimg.com/960/540/tech" alt="">
<h2 class="slider__item__title">Slide 5 Title</h2>
</div>
</div>
</div>
<div class="slider-nav">
<div class="slider-nav__prev" id="prev"><i class="fa fa-angle-left"></i></div>
<div class="slider-nav__next" id="next"><i class="fa fa-angle-right"></i></div>
<div class="slider-nav__dots" id="dots"></div>
</div>
I'm trying to create an image slideshow with setInterval which starts playing when the mouse is over .project-img and pauses when the mouse leaves .project-img. The problem i'm having is calling clear interval on to pause the slideshow when the mouse leaves, I'm currently receiving the error:
Uncaught ReferenceError: cycle is not defined
Where am I going wrong?
var Image = {
init: function() {
Image.setupImages();
Image.bindEvents();
},
bindEvents: function() {
$('.project-img').hover(function() {
var hovered = $(this);
var thumbnailIndex = 0
var thumbnailArray = hovered.children()
console.log(thumbnailArray);
var cycle = setInterval(function(){
thumbnailIndex++
if (thumbnailIndex === thumbnailArray.length) {
thumbnailIndex = 0;
thumbnailArray.removeClass('active');
thumbnailArray.eq(0).addClass('active');
} else {
var $visible = thumbnailArray.eq(thumbnailIndex);
thumbnailArray.removeClass('active');
$visible.addClass('active');
}
}, 700);
}, function() {
clearInterval(cycle);
});
},
setupImages: function() {
var projectImage = $('.project-img');
projectImage.each(function(project) {
$(this).find('.project-thumbnail:eq(0)').addClass('active');
});
}
}
$(document).ready(function() {
Image.init();
});
.project-thumbnail {
visibility: hidden;
display: none;
}
.active {
visibility: visible;
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="project-img">
<div class="project-thumbnail">
<img src="http://via.placeholder.com/250/000000">
</div>
<div class="project-thumbnail">
<img src="http://via.placeholder.com/250/ffffff/000000">
</div>
<div class="project-thumbnail">
<img src="http://via.placeholder.com/250/000000">
</div>
<div class="project-thumbnail">
<img src="http://via.placeholder.com/250/ffffff/000000">
</div>
</div>
<div class="project-img">
<div class="project-thumbnail">
<img src="http://via.placeholder.com/250/ffffff/000000">
</div>
<div class="project-thumbnail">
<img src="http://via.placeholder.com/250/000000">
</div>
</div>
This is a scope issue, you have defined cycle within a function, so it can't leave. Put var cycle above var Image and your problems will be solved! Alternatively if you wanted to keep it scoped inside the Image var, you can replace cycle with Image.cycle and that will also work.
The variable cycle is in a different scope. Instead of using hover use each, declaring the cycle variable in an outer scope of hover like so:
var Image = {
init: function() {
Image.setupImages();
Image.bindEvents();
},
bindEvents: function() {
$('.project-img').each(function() {
var hovered = $(this);
var cycle;
hovered.hover(function() {
var thumbnailIndex = 0;
var thumbnailArray = hovered.children();
cycle = setInterval(function() {
thumbnailIndex++
if (thumbnailIndex === thumbnailArray.length) {
thumbnailIndex = 0;
thumbnailArray.removeClass('active');
thumbnailArray.eq(0).addClass('active');
} else {
var $visible = thumbnailArray.eq(thumbnailIndex);
thumbnailArray.removeClass('active');
$visible.addClass('active');
}
}, 700);
}, function() {
clearInterval(cycle);
});
});
},
setupImages: function() {
var projectImage = $('.project-img');
projectImage.each(function(project) {
$(this).find('.project-thumbnail:eq(0)').addClass('active');
});
}
}
$(document).ready(function() {
Image.init();
});
.project-thumbnail {
visibility: hidden;
display: none;
}
.active {
visibility: visible;
display: block;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="project-img">
<div class="project-thumbnail">
<img src="http://via.placeholder.com/250/000000">
</div>
<div class="project-thumbnail">
<img src="http://via.placeholder.com/250/ffffff/000000">
</div>
<div class="project-thumbnail">
<img src="http://via.placeholder.com/250/000000">
</div>
<div class="project-thumbnail">
<img src="http://via.placeholder.com/250/ffffff/000000">
</div>
</div>
<div class="project-img">
<div class="project-thumbnail">
<img src="http://via.placeholder.com/250/ffffff/000000">
</div>
<div class="project-thumbnail">
<img src="http://via.placeholder.com/250/000000">
</div>
</div>
I am trying to use jQuery to scroll to a particular thumbnail (inside a modal) when right/left arrows have been pressed (modal should pop up when user clicks on a image). I was able to make the scroll working when user clicks on a thumbnail but I could not trigger a click when variable current2 changes. Any help would be appreciated.
I am new in Angular.js so if there are other suggestions to improve the code, it would be appreciated.
jsbin link
<body ng-app="mediaGallery" class="ng-cloak" ng-controller="mediaGalleryCtrl">
<div class="row">
<div class="small-8 columns">
<div class="small-3 columns">
<div ng-repeat="obj in array">
<div ng-if="$index < 4">
<img ng-click="changeMainMedia($index, 'current1')" class="thumbnail" ng-src="{{obj.src}}" />
</div>
<div ng-if="$index == 4">
<div class="thumbnail" data-open="media-gallery">
<label class="text-right success label">{{array.length - 3}} +</label>
</div>
</div>
</div>
</div>
<div class="small-9 columns">
<img data-open="media-gallery" class="main-gallery" ng-src="{{array[current1].src}}" />
</div>
</div>
</div>
<div ng-keydown="key($event)" id="media-gallery" class="small reveal text-center media-gallery" data-reveal>
<div class="modal-body">
<div class="main-media">
<img class="main-gallery media-gallery-main" ng-src="{{array[current2].src}}" />
<hr>
<div class="nested-media" scroll-thumbnail>
<img ng-click="changeMainMedia($index, 'current2')" ng-repeat="obj in array" class="thumbnail media-gallery-thumbnail" ng-src="{{obj.src}}" />
</div>
</div>
<button class="close-button" data-close aria-label="Close reveal" type="button">
<span aria-hidden="true">x</span>
</button>
</div>
</div>
<script>
var app = angular.module("mediaGallery", []);
app.controller("mediaGalleryCtrl", ['$scope', function(scope) {
var array = [{
src: "https://placeimg.com/640/480/any"
}, {
src: "https://placeimg.com/640/480/tech"
}, {
src: "https://placeimg.com/640/480/animals"
}, {
src: "https://placeimg.com/640/480/nature"
}, {
src: "https://placeimg.com/640/480/arch"
}, {
src: "https://placeimg.com/640/480/people"
}];
scope.array = array;
scope.current1 = 0
scope.current2 = 0;
scope.changeMainMedia = function(index, key) {
scope[key] = index;
}
scope.key = function($event) {
var previous = -1;
var current = scope.current2;
if ($event.keyCode == "39") {
previous = current;
current = (current + 1) % array.length;
} else if ($event.keyCode == "37") {
previous = current;
current = (current - 1) % array.length;
}
current = current < 0 ? (array.length + current) : current;
scope.current2 = current;
}
}]);
app.directive('scrollThumbnail', function() {
return {
link: function(scope, elem, attrs) {
elem.on("click", function(event) {
$(this).animate({
scrollLeft: $(event.target).position().left
}, "slow");
});
}
};
});
$(document).foundation()
</script>
</body>
This is a solution which does not need jQuery. I commented the changes that I have made to your code.
<!DOCTYPE HTML>
<html>
<head>
<title>index</title>
<meta name="viewport" content="width=device-width, initial-scale=1.0" />
<meta http-equiv="content-type" content="text/html; charset=utf-8" />
<meta name="description" />
<meta name="author">
<link rel="stylesheet" href="https://cdnjs.cloudflare.com/ajax/libs/foundation/6.3.0/css/foundation.css" />
<script src="https://cdnjs.cloudflare.com/ajax/libs/angular.js/1.5.6/angular.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/foundation/6.3.0/js/foundation.js"></script>
<style>
.media-gallery .media-gallery-thumbnail {
max-height: 5em;
display: inline-block
}
.media-gallery .media-gallery-main {
height: auto;
width: auto;
max-height: 20em;
}
.media-gallery .nested-media {
overflow-x: scroll;
white-space: nowrap;
}
.media-gallery .media-gallery-main {
max-width: 100%;
-moz-transition: all 0.3s;
-webkit-transition: all 0.3s;
transition: all 0.3s;
}
.media-gallery .media-gallery-main:hover {
-moz-transform: scale(1.5);
-webkit-transform: scale(1.5);
transform: scale(1.5);
}
[ng\:cloak],
[ng-cloak],
[data-ng-cloak],
[x-ng-cloak],
.ng-cloak,
.x-ng-cloak {
display: none !important;
}
</style>
</head>
<body ng-app="mediaGallery" class="ng-cloak" ng-controller="mediaGalleryCtrl">
<div class="row">
<div class="small-8 columns">
<div class="small-3 columns">
<div ng-repeat="obj in array">
<div ng-if="$index < 4">
<img ng-click="changeMainMedia($index, 'current1', $event)" class="thumbnail" ng-src="{{obj.src}}" />
</div>
<div ng-if="$index == 4">
<div class="thumbnail" data-open="media-gallery">
<label class="text-right success label">{{array.length - 3}} +</label>
</div>
</div>
</div>
</div>
<div class="small-9 columns">
<img data-open="media-gallery" class="main-gallery" ng-src="{{array[current1].src}}" />
</div>
</div>
</div>
<div ng-keydown="key($event)" id="media-gallery" class="small reveal text-center media-gallery" data-reveal>
<div class="modal-body">
<div class="main-media">
<img class="main-gallery media-gallery-main" ng-src="{{array[current2].src}}" />
<hr>
<div class="nested-media" scroll-thumbnail>
<img ng-click="changeMainMedia($index, 'current2', $event)" ng-repeat="obj in array" class="thumbnail media-gallery-thumbnail" ng-src="{{obj.src}}" />
</div>
</div>
<button class="close-button" data-close aria-label="Close reveal" type="button">
<span aria-hidden="true">x</span>
</button>
</div>
</div>
<script>
var app = angular.module("mediaGallery", []);
app.controller("mediaGalleryCtrl", ['$scope', function (scope) {
var array = [{
src : "https://placeimg.com/640/480/any"
}, {
src : "https://placeimg.com/640/480/tech"
}, {
src : "https://placeimg.com/640/480/animals"
}, {
src : "https://placeimg.com/640/480/nature"
}, {
src : "https://placeimg.com/640/480/arch"
}, {
src : "https://placeimg.com/640/480/people"
}
];
scope.array = array;
scope.current1 = 0
scope.current2 = 0;
scope.changeMainMedia = function (index, key, $event) {
scope[key] = index;
// Use scroll function to scroll to element after click
// $event parameter is added to retrieve the node value
scope.scroll($event.target);
}
// Animate scrolling
// Midified from: http://stackoverflow.com/a/8918062/529024
scope.scrollTo = function (element, to, duration) {
if (duration <= 0)
return;
var difference = to - element.scrollLeft;
var perTick = difference / duration * 10;
setTimeout(function () {
element.scrollLeft = element.scrollLeft + perTick;
if (element.scrollLeft === to)
return;
scope.scrollTo(element, to, duration - 10);
}, 10);
}
// calculate scroll position and starting scroll animation
scope.scroll = function (element) {
// Get center of parent
var left = element.offsetLeft;
var scroll = left - element.parentElement.scrollLeft;
// Start scroll
scope.scrollTo(element.parentElement, scroll, 300);
}
scope.key = function ($event) {
var previous = -1;
var current = scope.current2;
if ($event.keyCode == "39") {
previous = current;
current = (current + 1) % array.length;
} else if ($event.keyCode == "37") {
previous = current;
current = (current - 1) % array.length;
}
current = current < 0 ? (array.length + current) : current;
scope.current2 = current;
// Scroll to element
scope.scroll(scope.getElement());
}
// get the element that is matching current2 value
scope.getElement = function () {
var parent = scope.parentElement;
var children = parent.children();
return children.eq(scope.current2)[0];
}
// This function is used by directive scrollThumbnail to set the parent element
// and use it to get element sibilings
scope.setElement = function (element) {
scope.parentElement = element;
}
}
]);
app.directive('scrollThumbnail', function () {
return {
scope : true,
link : function (scope, elem, attrs) {
// set element to scope.parentElement.
scope.setElement(elem);
}
};
});
$(document).foundation()
</script>
</body>
</html>
And this a JSBin link: https://jsbin.com/ruzikilexe/1/edit?html,output