Jquery ui double image slider single command - javascript

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>

Related

JS Fiddle. Saved code but not working like JSFiddle example

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

Angular + jQuery, trigger scroll when src of image changes

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

jQuery queue does not work

What I'm trying to accomplish:
Let multiple cards in the queue slide in after each other on document ready and for the elements that arent visible on page load I want the same for them on scroll.
The problem:
All elements slide in at the same time. (Even though I'm using an each loop)
Example:
$( document ).ready(function(){
readyAnimation("slide-in-left");
readyAnimation("slide-in-cards");
});
$(window).scroll(function() {
readyAnimation("slide-in-left");
readyAnimation("slide-in-cards");
});
function readyAnimation (animationClass) {
var resetAnimationClass = "reset-animations";
$("." + animationClass).each(function() {
var elem = $(this);
if(elem.hasClass(animationClass)) {
if (isScrolledIntoView(elem) == true ) {
elem.delay(500).queue(function(){
elem.addClass(resetAnimationClass).dequeue();
})
}
}
});
}
function isScrolledIntoView(elem)
{
var docViewTop = $(window).scrollTop();
var docViewBottom = docViewTop + $(window).height();
var elemTop = $(elem).offset().top;
var elemBottom = elemTop + $(elem).height();
return (docViewBottom >= elemTop && docViewTop <= elemBottom);
}
.card {
float: left;
width: 25%;
background: $brand;
height: 300px;
border: 1px solid white;
background: #333;
}
.slide-in-cards {
transform: translate3d(0, 50px, 0);
opacity: 0;
transition: transform 600ms cubic-bezier(0.52, 1.61, 0.56, 1), opacity 600ms cubic-bezier(0.22, 0.61, 0.36, 1);
will-change: transform;
}
.reset-animations {
transform: translate3d(0, 0, 0);
opacity: 1;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="card slide-in-cards">
<img />
</div>
<div class="card slide-in-cards">
<img />
</div>
<div class="card slide-in-cards">
<img />
</div>
<div class="card slide-in-cards">
<img />
</div>
<div class="card slide-in-cards">
<img />
</div>
<div class="card slide-in-cards">
<img />
</div>
<div class="card slide-in-cards">
<img />
</div>
<div class="card slide-in-cards">
<img />
</div>
<div class="card slide-in-cards">
<img />
</div>
...
What I did so far:
My markup looks like this:
<div class="card slide-in-cards">
<img />
</div>
<div class="card slide-in-cards">
<img />
</div>
<div class="card slide-in-cards">
<img />
</div>
...
And I want them so slide in after each other by using something like this:
function readyAnimation (animationClass) {
var resetAnimationClass = "reset-animations";
$("." + animationClass).each(function() {
var elem = $(this);
if(elem.hasClass(animationClass)) {
if (isScrolledIntoView(elem) == true ) {
elem.delay(500).queue(function(){
elem.addClass(resetAnimationClass).dequeue();
})
}
}
});
}
I add a class that resets their css to normal, the elements have the transition property
This function is called like this
$( document ).ready(function(){
readyAnimation("slide-in-left");
readyAnimation("slide-in-cards");
});
$(window).scroll(function() {
readyAnimation("slide-in-left");
readyAnimation("slide-in-cards");
});
The isScrolledIntoView function is from stackoverflow and looks like this
function isScrolledIntoView(elem)
{
var docViewTop = $(window).scrollTop();
var docViewBottom = docViewTop + $(window).height();
var elemTop = $(elem).offset().top;
var elemBottom = elemTop + $(elem).height();
return (docViewBottom >= elemTop && docViewTop <= elemBottom);
}
Some thoughts:
Remember that animations on separate elements run in parallel; each element has its own animation queues.
You've said that you had an issue when more elements come into view. That's because you weren't eliminating them from the selection of elements to animate.
Your if (elem.hasClass(animationClass)) check is unnecessary, as you've selected only elements that have that class.
So (see *** commented lines):
function readyAnimation(animationClass) {
var resetAnimationClass = "reset-animations";
var counter = 0; // ***
$("." + animationClass).not("." + resetAnimationClass).each(function() { // ***
var elem = $(this);
// *** No `if (elem.hasClass(animationClass))` here, we know it does
if (isScrolledIntoView(elem) == true) {
++counter; // ***
elem.delay(500 * counter).queue(function() { // ***
elem.addClass(resetAnimationClass).dequeue();
})
}
});
}
$(document).ready(function() {
//readyAnimation("slide-in-left");
readyAnimation("slide-in-cards");
});
$(window).scroll(function() {
//readyAnimation("slide-in-left");
readyAnimation("slide-in-cards");
});
function readyAnimation(animationClass) {
var resetAnimationClass = "reset-animations";
var counter = 0;
$("." + animationClass).not("." + resetAnimationClass).each(function() {
var elem = $(this);
if (isScrolledIntoView(elem) == true) {
++counter;
elem.delay(500 * counter).queue(function() {
elem.addClass(resetAnimationClass).dequeue();
})
}
});
}
function isScrolledIntoView(elem) {
var docViewTop = $(window).scrollTop();
var docViewBottom = docViewTop + $(window).height();
var elemTop = $(elem).offset().top;
var elemBottom = elemTop + $(elem).height();
return (docViewBottom >= elemTop && docViewTop <= elemBottom);
}
.card {
float: left;
width: 25%;
background: $brand;
height: 300px;
border: 1px solid white;
background: #333;
}
.slide-in-cards {
transform: translate3d(0, 50px, 0);
opacity: 0;
transition: transform 600ms cubic-bezier(0.52, 1.61, 0.56, 1), opacity 600ms cubic-bezier(0.22, 0.61, 0.36, 1);
will-change: transform;
}
.reset-animations {
transform: translate3d(0, 0, 0);
opacity: 1;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="card slide-in-cards">
<img />
</div>
<div class="card slide-in-cards">
<img />
</div>
<div class="card slide-in-cards">
<img />
</div>
<div class="card slide-in-cards">
<img />
</div>
<div class="card slide-in-cards">
<img />
</div>
<div class="card slide-in-cards">
<img />
</div>
<div class="card slide-in-cards">
<img />
</div>
<div class="card slide-in-cards">
<img />
</div>
<div class="card slide-in-cards">
<img />
</div>
...

hide next button when last element reaches

I am creating a simple gallery with an overlay to display enlarged image when clicked.
In my gallery, every 3 images are grouped into a container as
<div class='overlay'>
<a class='next control'>Next</a>
</div>
<div class="container">
<div class="image">
<img src="http://dummyimage.com/100&text=Image1"/>
</div>
<div class="image">
<img src="http://dummyimage.com/100&text=Image2" />
</div>
<div class="image">
<img src="http://dummyimage.com/100&text=Image3"/>
</div>
</div>
<div class="container">
<div class="image">
<img src="http://dummyimage.com/100&text=Image4"/>
</div>
<div class="image">
<img src="http://dummyimage.com/100&text=Image5" />
</div>
<div class="image">
<img src="http://dummyimage.com/100&text=Image6"/>
</div>
</div>
JQuery
$(document).ready(function () {
var src;
var currentElement;
$(".image").click(function () {
currentElement = $(this);
src = $(currentElement).find("img").attr("src");
$(".overlay").css("background-image", "url('" + src + "')");
$(".overlay").show();
});
$(".next").click(function () {
if ($(currentElement).next().length) {
currentElement = currentElement.next();
src = $(currentElement).find("img").attr("src");
}
else {
currentElement = $(currentElement).parent().next().find(".image:first");
src = $(currentElement).find("img").attr("src");
}
$(".overlay").css("background-image", "url('" + src + "')");
});
});
I am able to get the next image on clicking next. But my problem is How to disable the next button when last image reaches ?.
I am unable to find a logic to get the last image.
Note: the images in last container may vary from 1 to 3
Here is the demo : https://jsfiddle.net/y5fwgz25/1/
here is my solution but i do not like this code, but works fine
<div class='overlay'>
<a class='next'></a>
</div>
<div id="gallery">
<div class="container">
<div class="image">
<img src="http://dummyimage.com/100&text=Image1"/>
</div>
<div class="image">
<img src="http://dummyimage.com/100&text=Image2" />
</div>
<div class="image">
<img src="http://dummyimage.com/100&text=Image3"/>
</div>
</div>
<div class="container">
<div class="image">
<img src="http://dummyimage.com/100&text=Image4"/>
</div>
<div class="image">
<img src="http://dummyimage.com/100&text=Image5" />
</div>
<div class="image">
<img src="http://dummyimage.com/100&text=Image6"/>
</div>
</div>
</div>
<script type="text/javascript">
$(document).ready(function () {
var src;
var currentElement;
var last_img = $("#gallery .container:last-child .image:last-child");
$(".image").click(function () {
currentElement = $(this);
src = $(currentElement).find("img").attr("src");
$(".overlay").css("background-image", "url('" + src + "')");
$(".overlay").show();
if ( $(currentElement)[0] == $(last_img)[0] ) {
$(".overlay .next").hide();
}
});
$(".next").click(function () {
if ( $(currentElement).next()[0] == $(last_img)[0] ) {
$(".overlay .next").hide();
}
if ($(currentElement).next().length) {
currentElement = currentElement.next();
src = $(currentElement).find("img").attr("src");
}else {
currentElement = $(currentElement).parent().next().find(".image:first");
src = $(currentElement).find("img").attr("src");
}
$(".overlay").css("background-image", "url('" + src + "')");
});
});
</script>
why don't you use jquery last method to get the last sibling and compare any of its attributes with the same attributes of the current element.
If they are the same, hide or disable the next button.
You can add one if condition. If the length of currentElement is zero then hide .next.
Updated Fiddle-
$(document).ready(function () {
var src;
var currentElement;
$(".image").click(function () {
currentElement = $(this);
src = $(currentElement).find("img").attr("src");
$(".overlay").css("background-image", "url('" + src + "')");
$(".overlay").show();
});
$(".next").click(function () {
if ($(currentElement).next().length) {
currentElement = currentElement.next();
src = $(currentElement).find("img").attr("src");
}
else {
currentElement = $(currentElement).parent().next().find(".image:first");
src = $(currentElement).find("img").attr("src");
}
if($(currentElement).length==0) {
$(".next").hide();
}
$(".overlay").css("background-image", "url('" + src + "')");
});
});
.overlay {
position: fixed;
top: 0;
left: 0;
display: none;
width: 100%;
height: 100%;
background: rgba(0, 0, 0, 0.9) no-repeat;
background-position: center;
}
.next {
position: absolute;
width: 50px;
height: 50px;
top: 50%;
background-image: url("http://dummyimage.com/50&text=Next");
right: 8em;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class='overlay'>
<a class='next'></a>
</div>
<div class="container">
<div class="image">
<img src="http://dummyimage.com/100&text=Image1"/>
</div>
<div class="image">
<img src="http://dummyimage.com/100&text=Image2" />
</div>
<div class="image">
<img src="http://dummyimage.com/100&text=Image3"/>
</div>
</div>
<div class="container">
<div class="image">
<img src="http://dummyimage.com/100&text=Image4"/>
</div>
<div class="image">
<img src="http://dummyimage.com/100&text=Image5" />
</div>
<div class="image">
<img src="http://dummyimage.com/100&text=Image6"/>
</div>
</div>

Angular js make slider with infinite effect

I created a simple photo slider but i does not how to make this infinite.
How can i make this effect with the angular way, please help.
I does not want to use jquery, but if it is the only way so whatever.
var app = angular.module('stack', []);
app.controller('MainCtrl', function($scope) {
$scope.images = ["http://lorempixel.com/600/200/sports/", "http://lorempixel.com/600/200/city/",
"http://lorempixel.com/600/200/nature/"
];
$scope.index = 0;
var IMG_WIDTH = -600;
$scope.next = function() {
++$scope.index;
if ($scope.images.length <= $scope.index) {
$scope.index = 0;
}
var pos = ($scope.index > 0) ? $scope.index * IMG_WIDTH : 0;
$scope.listPosition = {
transform: "translateX(" + pos + "px)"
};
}
$scope.prev = function() {
--$scope.index;
if ($scope.index < 0) {
$scope.index = $scope.images.length - 1;
}
var pos = ($scope.index > 0) ? $scope.index * IMG_WIDTH : 0;
$scope.listPosition = {
transform: "translateX(" + pos + "px)"
};
}
});
.mt {
margin-top: 2em;
}
.outer {
max-width: 600px;
overflow: hidden;
}
.slider {
width: 90000px;
position: relative;
transition: all 1s;
}
.slider div {
float: left;
}
<script src="https://ajax.googleapis.com/ajax/libs/angularjs/1.2.23/angular.min.js"></script>
<link data-require="bootstrap#3.3.2" data-semver="3.3.2" rel="stylesheet" href="//maxcdn.bootstrapcdn.com/bootstrap/3.3.2/css/bootstrap.min.css" />
<body ng-app="stack" ng-controller="MainCtrl">
<div class="container-fluid">
<div class="row mt">
<div class="col-sm-6 col-sm-push-3">
<div class="outer clearfix">
<div class="slider clearfix" ng-style="listPosition">
<div ng-repeat="image in images track by $index">
<img ng-src="{{image}}" />
</div>
</div>
</div>
</div>
</div>
</div>
<a class="btn btn-default" ng-click="next()">Next</a>
<a class="btn btn-default" ng-click="prev()">Prev</a>
<div></div>
</body>
Easiest way would be to shuffle $scope.images array.
Once transition has been done, disable them, either by creating something like .no-transition class and adding it to the slider or by any other way you can imagine
$scope.images.push($scope.images.shift()) should put first item to last position, $scope.images.unshift($scope.images.pop()) should reverse it.
After that, you'll probably have to re-adjust transform value and re-apply transitions
Hope that helps.

Categories