Repeat number of galleries without duplicating code for gallery - javascript

I'm using a free jquery gallery and I want to make as many galleries as I want on the page. Problem is how the javascript is written will require to duplicate and rename, the code. Here's what the javascript that renders the gallery looks like
$(document).ready(function(){
var slideShow = $('#slideShow'),
ul = slideShow.find('ul'),
li = ul.find('li'),
cnt = li.length;
// As the images are positioned absolutely, the last image will be shown on top.
// This is why we force them in the correct order by assigning z-indexes:
updateZindex();
if($.support.transform){
// Modern browsers with support for css3 transformations
li.find('img').css('rotate',function(i){
// Rotating the images counterclockwise
return (-90*i) + 'deg';
});
// Binding a custom event. the direction and degrees parameters
// are passed when the event is triggered later on in the code.
slideShow.bind('rotateContainer',function(e,direction,degrees){
// Enlarging the slideshow and photo:
slideShow.animate({
width : 510,
height : 510,
marginTop : 0,
marginLeft : 0
},'fast',function(){
if(direction == 'next'){
// Moving the topmost image containing Li at
// the bottom after a fadeOut animation
$('li:first').fadeOut('slow',function(){
$(this).remove().appendTo(ul).show();
updateZindex();
});
}
else {
// Showing the bottomost Li element on top
// with a fade in animation. Notice that we are
// updating the z-indexes.
var liLast = $('li:last').hide().remove().prependTo(ul);
updateZindex();
liLast.fadeIn('slow');
}
// Rotating the slideShow. css('rotate') gives us the
// current rotation in radians. We are converting it to
// degress so we can add 90 or -90 to rotate it to its new value.
slideShow.animate({
rotate:Math.round($.rotate.radToDeg(slideShow.css('rotate'))+degrees) + 'deg'
},'slow').animate({
width : 490,
height : 490,
marginTop : 10,
marginLeft : 10
},'fast');
});
});
// By triggering the custom events below, we can
// show the previous / next images in the slideshow.
slideShow.bind('showNext',function(){
slideShow.trigger('rotateContainer',['next',90]);
});
slideShow.bind('showPrevious',function(){
slideShow.trigger('rotateContainer',['previous',-90]);
});
}
else{
// Fallback for Internet Explorer and older browsers
slideShow.bind('showNext',function(){
$('li:first').fadeOut('slow',function(){
$(this).remove().appendTo(ul).show();
updateZindex();
});
});
slideShow.bind('showPrevious',function(){
var liLast = $('li:last').hide().remove().prependTo(ul);
updateZindex();
liLast.fadeIn('slow');
});
}
// Listening for clicks on the arrows, and
// triggering the appropriate event.
$('#previousLink').click(function(){
if(slideShow.is(':animated')){
return false;
}
slideShow.trigger('showPrevious');
return false;
});
$('#nextLink').click(function(){
if(slideShow.is(':animated')){
return false;
}
slideShow.trigger('showNext');
return false;
});
// This function updates the z-index properties.
function updateZindex(){
// The CSS method can take a function as its second argument.
// i is the zero-based index of the element.
ul.find('li').css('z-index',function(i){
return cnt-i;
});
}
});
the var slideShow gets referenced all over the script, I was thinking of using an onclick but this would be better if it was wrapped in a function and called on the go for all classes with a name.
Here's the html
<div id="slideShowContainer">
<div id="slideShow">
<ul>
<li><img src="img/photos/1.jpg" width="100%" alt="Fish" /></li>
<li><img src="img/photos/2.jpg" width="100%" alt="Ancient" /></li>
<li><img src="img/photos/3.jpg" width="100%" alt="Industry" /></li>
<li><img src="img/photos/4.jpg" width="100%" alt="Rain" /></li>
</ul>
</div>
<a id="previousLink" href="#">»</a>
<a id="nextLink" href="#">«</a>
</div>

I think one easy solution is to use a wrap all galleries in an element, then use classes instead of IDs to target them like
$(document).ready(function() {
$('.slide-container').each(function() {
var slideShow = $('.slide-show', this),
ul = slideShow.find('ul'),
li = ul.find('li'),
cnt = li.length;
// As the images are positioned absolutely, the last image will be shown on top.
// This is why we force them in the correct order by assigning z-indexes:
updateZindex();
if ($.support.transform) {
// Modern browsers with support for css3 transformations
li.find('img').css('rotate', function(i) {
// Rotating the images counterclockwise
return (-90 * i) + 'deg';
});
// Binding a custom event. the direction and degrees parameters
// are passed when the event is triggered later on in the code.
slideShow.bind('rotateContainer', function(e, direction, degrees) {
// Enlarging the slideshow and photo:
slideShow.animate({
width: 510,
height: 510,
marginTop: 0,
marginLeft: 0
}, 'fast', function() {
if (direction == 'next') {
// Moving the topmost image containing Li at
// the bottom after a fadeOut animation
ul.find('li:first').fadeOut('slow', function() {
$(this).remove().appendTo(ul).show();
updateZindex();
});
} else {
// Showing the bottomost Li element on top
// with a fade in animation. Notice that we are
// updating the z-indexes.
var liLast = ul.find('li:last').hide().remove().prependTo(ul);
updateZindex();
liLast.fadeIn('slow');
}
// Rotating the slideShow. css('rotate') gives us the
// current rotation in radians. We are converting it to
// degress so we can add 90 or -90 to rotate it to its new value.
slideShow.animate({
rotate: Math.round($.rotate.radToDeg(slideShow.css('rotate')) + degrees) + 'deg'
}, 'slow').animate({
width: 490,
height: 490,
marginTop: 10,
marginLeft: 10
}, 'fast');
});
});
// By triggering the custom events below, we can
// show the previous / next images in the slideshow.
slideShow.bind('showNext', function() {
slideShow.trigger('rotateContainer', ['next', 90]);
});
slideShow.bind('showPrevious', function() {
slideShow.trigger('rotateContainer', ['previous', -90]);
});
} else {
// Fallback for Internet Explorer and older browsers
slideShow.bind('showNext', function() {
ul.find('li:first').fadeOut('slow', function() {
$(this).remove().appendTo(ul).show();
updateZindex();
});
});
slideShow.bind('showPrevious', function() {
var liLast = ul.find('li:last').hide().remove().prependTo(ul);
updateZindex();
liLast.fadeIn('slow');
});
}
// Listening for clicks on the arrows, and
// triggering the appropriate event.
$('.previous', this).click(function() {
if (slideShow.is(':animated')) {
return false;
}
slideShow.trigger('showPrevious');
return false;
});
$('.next', this).click(function() {
if (slideShow.is(':animated')) {
return false;
}
slideShow.trigger('showNext');
return false;
});
// This function updates the z-index properties.
function updateZindex() {
// The CSS method can take a function as its second argument.
// i is the zero-based index of the element.
ul.find('li').css('z-index', function(i) {
return cnt - i;
});
}
});
});
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div class="slide-container">
<div class="slide-show">
<ul>
<li>
<img src="img/photos/1.jpg" width="100%" alt="Fish" />
</li>
<li>
<img src="img/photos/2.jpg" width="100%" alt="Ancient" />
</li>
<li>
<img src="img/photos/3.jpg" width="100%" alt="Industry" />
</li>
<li>
<img src="img/photos/4.jpg" width="100%" alt="Rain" />
</li>
</ul>
</div>
<a class="previous" href="#">»</a>
<a class="next" href="#">«</a>
</div>
<div class="slide-container">
<div class="slide-show">
<ul>
<li>
<img src="img/photos/1.jpg" width="100%" alt="Fish" />
</li>
<li>
<img src="img/photos/2.jpg" width="100%" alt="Ancient" />
</li>
<li>
<img src="img/photos/3.jpg" width="100%" alt="Industry" />
</li>
<li>
<img src="img/photos/4.jpg" width="100%" alt="Rain" />
</li>
</ul>
</div>
<a class="previous" href="#">»</a>
<a class="next" href="#">«</a>
</div>

Related

Run function on load and resize & get height of class

I have created this function but there are two things that are not working and, after a while trying to find why, I can't find the reason.
First, it should take the height from .bar-info, but is not. It gets -10, instead of 100px
Second, when the page loads (and on resize), it should run this function and get the height, but it doesn't. It works on resize, but not on ready
onResize = function() {
if($(window).width() < 1000) {
//Set height based in number of bars
$('.vert .bars').each(function(){
var length = $(this).find(".bar-info").length;
var info = $(this).find(".bar-info").height(); // 1. Not taking the correct height
var height = (info * length) + 1270 + "px";
$(this).parent().css({"height":height}); // 2. Wrong height just on load
});
} else {
$('.vert .bars').each(function(){
$(this).parent().css({"height":"1200px"});
});
}
}
$(document).ready(onResize); // Why it doesn't work?
$(window).resize(onResize); // This works
HTML:
<div class="container vertical flat vert">
<div class="bars">
<div class="bar-general">
<div class="bar-info">Content</div>
</div>
</div>
</div>

getBoundingClientRect() returns same values for all children if first child has any negative value

The Context
I'm building an infinite horizontal scroll of images:
<div class="infinite-thumbs">
<img src="1.jpg" class="thumb thumb-one">
<img src="2.jpg" class="thumb thumb-two">
<img src="3.jpg" class="thumb thumb-three">
...
<img src="10.jpg" class="thumb thumb-ten">
</div>
<style lang="stylus">
.infinite-thumbs
position absolute
width 100%
height 180px
bottom 40px
white-space nowrap
overflow auto
overflow-y hidden
.thumb
position relative
display inline-block
width 200px
height 180px
</style>
Learn more about Stylus here: stylus-lang.com
And then I've got some jQuery/JS to handle the cloning and appending of images when they're off-screen:
function scrollUpdate() {
$('.thumb').each(function() {
var bounding = $(this)[0].getBoundingClientRect();
if (bounding.right < 0) {
var $el = $(this);
$el.clone(true).appendTo('.infinite-thumbs');
$el.remove();
}
});
}
$('.infinite-thumbs').on('scroll', function () {
window.requestAnimationFrame(scrollUpdate);
});
So scrollUpdate() loops over each of the .thumb elements and checks to see if it's visible on-screen. If it's not (bounding.right < 0) then it gets cloned and appended to the end of the .infinite-thumbs element.
The Problem
The problem I have is that once one of the .thumb elements returns a negative value for bounding.right all the .thumb elements return the exact same set of bounding values.
So when all are visible, I get this in my console:
.thumb-one: { top : 0, right : 200, ... }
.thumb-two: { top : 0, right : 400, ... }
.thumb-three: { top : 0, right : 600, ... }
...
.thumb-ten: { top : 0, right : 2000, ... }
But as soon as the first child element (.thumb-one) obtains a negative bounding.right value, I get this in my console:
.thumb-one: { top : 0, right : -1, ... }
.thumb-two: { top : 0, right : -1, ... }
.thumb-three: { top : 0, right : -1, ... }
...
.thumb-ten: { top : 0, right : -1, ... }
What gives? Why would they all return a bounding object with the exact same values just because one of them is off-screen?
Anyone have any idea what's going on here?
NOTE:
Both $.fn.offset() and $.fn.position() behave in the same way as
getBoundingClientRect(); they return the same set of values for each
.thumb once .thumb-one has a negative value in its result.
It happens because you remove the element before check all the thumbs' positions. Removing the first element causes that the next element becomes the first, going off-screen. This way, every thumb will assume the same 'right' position.
The solution
Create a temporary array outside the 'each' cycle and use it to save the off-screen thumbs. Then, after the cycle, clone, remove and append elements in the same way as before. Something like this:
function scrollUpdate() {
var offScreenElements = [];
$('.thumb').each(function() {
var bounding = $(this)[0].getBoundingClientRect();
if (bounding.right < 0) {
offScreenElements.push($(this));
}
});
$.each(offScreenElements, function(index, element) {
element.clone(true).appendTo('.infinite-thumbs');
element.remove();
});
}

infinite horizontal image gallery in jquery

Im trying to do infinite horizontal image gallery but cannot figure out few problems.I got a div that has 100% width and inside second div that has very big width so the images can be next to each other.Im in testing phase so function is running immediately after page loads so the gallery is moved left by margin of width first image and then it has to be appended as last child and its looks like thats working but right after first append its happening on and on with another images.How can i avoid it?And my second question is when i want to do the moving on hover for example on some arrow as long as im over that how can i cycle this function correctly?Thanks very much.
Here is the fiddle.
HTML
<div id="slider">
<div id="slide-container">
<div class="slide" id="slide"><img src="clique.jpg"></div>
<div class="slide"><img src="rollyx.jpg"></div>
<div class="slide"><img src="grafrollyx.jpg"></div>
<div class="slide"><img src="grafagent.jpg"></div>
<div class="slide"><img src="grafrollyx.jpg"></div>
</div>
</div>
JavaScript
function slider(){
var what = $('#slide').width();
$('.slide').first().animate({marginLeft: -(what)}, 0, setTimeout(function() {
$('.slide')
.first()
.appendTo($('.slide').parent())
.css({ marginLeft: 0 });
}, 1000))
}
i guss this is a better way of doing that
Here is a FIDDLE of the gallery.
Put all your images in a hidden div
Clone them and put them in the visible div
Animate the image by changing the left margin
You can adjust the time between images by the set interval function
You can adjust the slidein time by the animate time.
JS
var pictxtnumber = 1;
loadpictxt(pictxtnumber);
var fadeintime = 500;
animatediv();
function animatediv()
{
var number = 0;
var interval = setInterval(function() {
pictxtnumber = pictxtnumber + 1;
if(pictxtnumber > 6)
{
pictxtnumber = 1;
}
loadpictxt(pictxtnumber);
}, 1000);
}
function loadpictxt(num)
{
$('.picturediv').html('');
$(".hiddenimage img:nth-child(" + num + ") ").clone().appendTo('.picturediv');
$('.picturediv img').css('margin-left', '100px');
$('.picturediv img').animate({marginLeft: "0"}, 100);
}

Multiple slide shows on one html page

I have tried to put two side shows onto one page, I cannot get the second one to work, I have tried multiple fixes I found on line and none of them work and make it worse. Here is my code
$(document).ready(function()
// execute the slideShow, set 4 seconds (4000) for each image
slideShow(6000);
});
function slideShow(speed) {
// append an 'li' item to the 'ul' list for displaying the caption
$('ul.images').append('<li id="slideshow-caption" class="caption"><div class="slideshow-caption-container"><p></p></div></li>');
// set the opacity of all images to 0
$('ul.images li').css({opacity: 0.0});
// get the first image and display it
$('ul.images li:first').css({opacity: 1.0}).addClass('show');
// call the gallery function to run the slideshow
var timer = setInterval('gallery()',speed);
// pause the slideshow on mouse over
$('ul.images').hover(
function () {
clearInterval(timer);
},
function () {
timer = setInterval('gallery()',speed);
}
);
}
function gallery() {
//if no images have the show class, grab the first image
var current = ($('ul.images li.show')? $('ul.images li.show') : $('#ul.images li:first'));
// trying to avoid speed issue
if(current.queue('fx').length == 0) {
// get the next image, if it reached the end of the slideshow, rotate it back to the first image
var next = ((current.next().length) ? ((current.next().attr('id') == 'slideshow-caption')? $('ul.images li:first') :current.next()) : $('ul.images li:first'));
// get the next image caption
var desc = next.find('img').attr('alt');
// set the fade in effect for the next image, show class has higher z-index
next.css({opacity: 0.0}).addClass('show').animate({opacity: 1.0}, 1000);
// hide the current image
current.animate({opacity: 0.0}, 1000).removeClass('show');
}
}
function slideShow(speed) {
// append an 'li' item to the 'ul' list for displaying the caption
$('ul.images1').append('<li id="slideshow-caption" class="caption"><div class="slideshow-caption-container"><p></p></div></li>');
// set the opacity of all images to 0
$('ul.images1 li').css({opacity: 0.0});
// get the first image and display it
$('ul.images1 li:first').css({opacity: 1.0}).addClass('show');
// call the gallery function to run the slideshow
var timer = setInterval('gallery2()',speed);
// pause the slideshow on mouse over
$('ul.images1').hover(
function () {
clearInterval(timer);
},
function () {
timer = setInterval('gallery2()',speed);
}
);
}
function gallery2() {
//if no images have the show class, grab the first image
var current = ($('ul.images1 li.show')? $('ul.images1 li.show') : $('#ul.images1 li:first'));
// trying to avoid speed issue
if(current.queue('fx').length == 0) {
// get the next image, if it reached the end of the slideshow, rotate it back to the first image
var next = ((current.next().length) ? ((current.next().attr('id') == 'slideshow-caption')?$('ul.images1 li:first') :current.next()) : $('ul.images1 li:first'));
// get the next image caption
var desc = next.find('img').attr('alt');
// set the fade in effect for the next image, show class has higher z-index
next.css({opacity: 0.0}).addClass('show').animate({opacity: 1.0}, 1000);
// hide the current image
current.animate({opacity: 0.0}, 1000).removeClass('show');
}
}
This is my HTML
First gallery
<div class="gallery">
<ul class="images1">
<li class="show"><img width="880" height="100" src="images\imageedit_6_7692684616.gif" alt="photo1" /></li>
<li><img width="880" height="100" src="images\imageedit_20_2328314159.gif" alt="photo2" /></li>
</ul>
</div>
This is the second gallery
<div class="gallery2">
<ul class="images">
<li class="show"><img width="930" height="400" src="images/offshore banner pic writing.png" alt="photo_one" /></li>
<li><img width="930" height="400" src="images/Drillig Pipe travels under the sea writing.jpg" alt="photo_two" /></li>
<li><img width="930" height="400" src="images/shutterstock_71875879_writing.jpg" alt="photo_three" /></li>
<li><img width="930" height="400" src="images/shutterstock_92549716_writing.jpg" alt="photo_four" /></li>
<li><img width="930" height="400" src="images/shutterstock_64614868_writing.jpg" alt="photo_five" /></li>
</ul>
</div>

obligatory dummy slider - using jQuery dynamically

I created a slider with 2 buttons, previous and next, allowing the user to interact with images by going forward or back. If at the first image and previous is fired, the last image is slid left into view. Opposite goes for the end of images case.
The problem I'm having is getting the width of the static images dynamically. When I use the browser console with the exact same selector and methods, I get the correct width, but when i console.log(width), the value is 0, which throws off the animation to slide 0px, hence no interaction.
Here is my JS:
$(document).ready(function () {
//initialize/cache variables needed in program
var sliderUL = $('div.content5').css('overflow', 'hidden').children('ul'); //we can chain variables, for example: we are setting the overflow of an element to hidden, and then we are getting the selected elements of 'ul'.
var imgs = sliderUL.find('img');
var imgWidth = imgs.eq(0).width(); //*SHOULD BE 400, but is 0*
var imgsLen = imgs.length; //5
var current = 1;
var totalImgsWidth = imgsLen * imgWidth; //2000
$('#slider-nav').show().find('button').on('click', function () {
//direction tells us what button is clicked, previous or next. This is needed for moving forward or backwards
var direction = $(this).data('dir'),
loc = imgWidth; //400, the amount needed to shift to new image, which also is the width of an image
//update current value
//if the user clicks on the next button, increase current by 1. else, decrease current by 1, meaning they clicked on the previous button.
(direction === 'next') ? ++current : --current;
//if on the first image and the user presses previous, set current equal to the last image
if (current === 0) {
current = imgsLen;
loc = totalImgsWidth - imgWidth;
//direction next means that it will animate left all the way over to the last image
direction = 'next';
} else if (current - 1 === imgsLen) {
//if the user is on the very last image and they press next, send them back to the first image
current = 1;
//send the img location back to 0 pixels, or the first image
loc = 0;
}
transition(sliderUL, loc, direction);
});
//params: 1.what we are animating 2.the location (margin) we're moving to 3.the direction we are moving
function transition(container, loc, direction) {
var unit; // -= OR +=
//as long as the user isn't trying to reset, the unit is either going to be equal to -= or +=
console.log(loc + ' and ' + direction);
if (direction && loc !== 0) {
//does direction equal next?
//if so, increment left sign, else, increment right sign
if (direction == 'next') {
unit = '-=';
} else {
unit = '+=';
}
// unit = (direction === 'next') ? '-=' : '+=';
}
console.log("you are on image: " + current + ", going " + unit);
container.animate({
//if unit isn't undefined, animate container. else, reset to 0/first img
'margin-left': unit ? (direction + loc) : loc // if true, -=400 OR +=400 if false, reset back to first image at 0
});
}
});
Here is my HTML:
<div class="content5">
<h1 class="content5_h1">Content #5 - The Obligatory Slider</h1>
<ul class="content5_imgs">
<li><img src="imgs/img1.jpg" alt="/" /></li>
<li><img src="imgs/img2.jpg" alt="/" /></li>
<li><img src="imgs/img3.jpg" alt="/" /></li>
<li><img src="imgs/img4.jpg" alt="/" /></li>
<li><img src="imgs/img5.jpg" alt="/" /></li>
</ul>
</div>
<div id="slider-nav">
<button data-dir="prev">Previous</button>
<button data-dir="next">Next</button>
</div>
and finally, here is my CSS:
.content5 {
width:400px;
margin:auto;
height: 368px;
overflow: scroll;
}
.content5_imgs {
width:10000px;
height: 250px;
list-style: none;
padding: 0px;
}
.content5_imgs li {
float:left;
}
#slider-nav {
display: none;
margin-top: 1em;
width:170px;
margin:auto;
padding-top: 10px;
}
#slider-nav button {
padding:1em;
margin-right: 1em;
border-radius:10px;
cursor: pointer;
background-color: Lime;
}
I tried chaining the variables, and I tried even changing the selectors for imgWidth including first() and [0].
Any insight is helpful.
JavaScript will return a width of 0 if the image hasn't loaded yet.
To work around this, any code that depends on content to be loaded, rather than just the DOM being ready, needs to be called on
$(window).load()
Instead of $(document).ready().
More information: Official way to ask jQuery wait for all images to load before executing something

Categories