.stop(true) doesn't seem to really clear the queue? - javascript

I've made this slideshow that pauses when you hover on it with .stop(true). When the mouse leaves the slideshow again it's supposed to play again. It really doesn't matter from where it runs. (meaning it can remove the old animation queue entirely and start over)
The thing is if I hover it now the animation stops, then resumes until it reaches its target. There it stops and wait the time it would take for the animation to finish. I'm not really sure what's going on.
Html:
<section class="photo-grid-slideshow">
<div class="photo-crop">
<h3>I wanna
<div class="xs-spacer"></div>
<a class="med-btn btn-white">Read more</a>
</h3>
<div class="photo-grid-container" style="background-image: url('Images and videos/odesza1.jpg');"></div>
</div>
<div class="photo-crop">
<h3>Dance
<div class="xs-spacer"></div>
<a class="med-btn btn-white">Read more</a>
</h3>
<div class="photo-grid-container" style="background-image: url('Images and videos/odesza3.jpg');"></div>
</div>
<div class="photo-crop">
<h3>With you
<div class="xs-spacer"></div>
<a class="med-btn btn-white">Read more</a>
</h3>
<div class="photo-grid-container" style="background-image: url('Images and videos/odesza2.png');"></div>
</div>
<div class="photo-crop">
<h3>With you
<div class="xs-spacer"></div>
<a class="med-btn btn-white">Read more</a>
</h3>
<div class="photo-grid-container" style="background-image: url('Images and videos/odesza4.jpg');"></div>
</div>
</section>
Css:
.photo-crop {
display: inline-block;
overflow: hidden;
float: left;
width: calc(100vw / 3);
height: 100%;
padding: 0;
position: relative;
background-position: center center;
background-size: cover;
text-align: left;
}
.photo-grid-slideshow {
height: 300px;
display: inline-block;
min-width: 300%;
position: relative;
background: black;
padding: none;
overflow: hidden;
background: #444;
margin-left: 0;
left: 0;
}
Script:
$(function(){
function animate(){
var p = $(".photo-grid-slideshow .photo-crop").css('width');
$(".photo-grid-slideshow .photo-crop:first-of-type").animate({marginLeft: '-=' + p}, 10000, "linear", function(){
$(this).css("margin-left", 0).appendTo('.photo-grid-slideshow');
animate(); // here we call it again
})
}
animate(); // start animation
})
$(".photo-grid-slideshow").mouseenter(function() {
$(".photo-grid-slideshow .photo-crop:first-of-type").stop().clearQueue();
})
$(".photo-grid-slideshow").mouseleave(function() {
$(function(){
function animate(){
var p = $(".photo-grid-slideshow .photo-crop").css('width');
$(".photo-grid-slideshow .photo-crop:first-of-type").animate({marginLeft: '-=' + p}, 10000, "linear", function(){
$(this).css("margin-left", 0).appendTo('.photo-grid-slideshow');
animate(); // here we call it again
})
}
animate(); // start animation
})
})

This is interesting a very tricky.
Well your main problem is not has caching the actual margin-left of the first
element, so that is because there is a small time waiting.
first.
the first element are animating, so when the first element is out of the
photo-grid-slideshow this continue animating after you hover in the photo-grid-slideshow, in other words, when you
hover the mouse, the animation stop, but for example, if you stop at -55px
margin-left, and suppose that the width of the image are 200px, then when you
run the animation again, and calculate the width of the first element, that have
255px of width because it takes the last margin-left set and the width of the
element, the reason of that stop some time the animation is for that, the first
element is animating but out of the photo-grid-slideshow, and this is when the second
element is in the start line this stop there and wait for the animation of the first
element finish, because the first element need 255px to finish the animating and this surpass the normal with.
// Get the width of the first element for once, not every time
var widthEl = parseInt($(".photo-crop").first().css('width'));
// Need an auxiliar because need cache the margin-left of the first element
var aux = 0;
// Separate the function animate it's better
function animate(p){
// With this selector you get the first element
$(".photo-crop").
first().
animate({marginLeft: '-=' + p}, 5000, "linear", function(){
$(this).css("margin-left", 0).appendTo('.photo-grid-slideshow');
// You need send the current margin-left
animate(p); // here we call it again
});
};
// with the chainnable option, you can chain the listeners
$(".photo-grid-slideshow").mouseenter(function() {
// Here calculate the margin-left of the first element
// then you can stop the animation
aux = widthEl - parseInt($(".photo-crop").first().stop().css("marginLeft"))*-1;
}).mouseleave(function() {
// and you can send the current margin-left of the first element.
animate(aux);
});
// here you can send the width of the first element.
animate(widthEl); // start animation

Related

javascript window scroll issue

I am working on javascript scroll. I have following html code
JSFIDDLE
<div class="wrapper">
<div class="red div current"></div>
<div class="blue div"></div>
<div class="green div"></div>
<div class="yellow div"></div>
</div>
In above code I have four div tags red, blue, green and yellow. All of them are position in following css.
html, body {
height: 100%;
}
.wrapper {
overflow: hidden;
height: 100%;
}
.div {
position: relative;
height: 100%;
}
.red {
background: red;
}
.blue {
background: blue;
}
.green {
background: green;
}
.yellow {
background: yellow;
}
In above html and css the red div tag is the current one which means user is seeing the red div tag on the screen. Now what I am trying to do is when user scroll over window once, then the next div tag i.e. blue will be animated and moved to the top and will become visible to the user whereas the red div tag will be behind the blue one. This same process goes for both green and yellow.
The problem is that when user scroll once then the div tag should animate however my current javascript code is keep reading the scroll and animating the div tags one after another. What I want is when user scroll once then scroll should be disabled until the blue div tag is animated. Then scroll should be enabled. Again when user scroll second time, the scroll should disable until the green div tag completes its animation. Same goes for yellow.
How can I achieve above?
Here is my javascript
$(window).on("scroll", function () {
var next = $('.current').next();
var height = next.outerHeight();
next.animate({top: '-=' + height}, 500, function () {
$(this).prev().removeClass('current');
$(this).addClass('current');
});
});
Please have a look on update JsFiddle
$(window).on("scroll", function () {
var next = $('.current').next();
var height = $('.current').outerHeight();
$('.current').prevAll().each(function(){
height += $(this).outerHeight();
});
next.animate({top: '-=' + height}, 500, function () {
$(this).prev().css('top','');
$(this).prev().toggleClass('current');
$(this).toggleClass('current');
});
});
The main reason your example wasn't working as expected is because you were relatively positioning the divs, and not moving them to the correct spot.
Working JSFiddle:
http://jsfiddle.net/seanjohnson08/rVVuc/6/
.wrapper {
overflow: hidden;
height: 100%;
position: relative;
}
.div {
position: absolute;
height: 100%;
width: 100%;
top: 100%;
}
.current{
top: 0;
}
If you are looking for a way to limit the amount of scroll events fired, try throttling: http://benalman.com/projects/jquery-throttle-debounce-plugin/. My solution doesn't require this, because no matter how many times it is firing the scroll event, it only ever tells jquery to animate to top:0, there's no chance of it animating past that.

Side-Scrolling img div using .scrollWidth

I have simple html document that contains divs which hold a series of images:
<div id="container">
<div id="imagelist">
<a href="images/1.jpg"><img src="images/1b.jpg"/>
<a href="images/2.jpg"><img src="images/2b.jpg"/>
<a href="images/3.jpg"><img src="images/3b.jpg"/>
<a href="images/4.jpg"><img src="images/4b.jpg"/>
<a href="images/5.jpg"><img src="images/5b.jpg"/>
<a href="images/6.jpg"><img src="images/6b.jpg"/>
</div>
</div>
I would like to be able to scroll horizontall through the images when hovering over the left or right edge of the div (I have multiple #imagelists all stacked vertically)
I'm trying to use the .scrollWidth() function as such (this is in my script.js file):
var imglist = $('#imagelist');
$(imglist).mousemove(function(e) {
var percent = e.clientX / $(imglist).width();
$(imglist).scrollWidth($(imglist).width() * percent);
});
This doesn't work at all, of course! I've been trying to model this after some good examples I've seen, such as This. What should I alter to make my #imagelist scrollable?
Here's a way to do it using offset and relative positioning.
demo
The HTML looks similar to yours, with the exception that we create elements for the edges. The benifit is that we can style them with CSS, should you ever decide you want :hover styles (example in the demo).
<div class="imagecontainer">
<div class="imagelist">
<img src="http://placehold.it/400x300">
...
<img src="http://placehold.it/400x300">
</div>
<div class="edge right"></div>
<div class="edge left"></div>
</div>
The entire CSS is in the demo, this is just the essentials.
.imagecontainer {
width: 100%;
height: 400px;
overflow-x: hidden;
position: relative;
}
.imagelist {
/* Width allows up to 100 screenfuls, feel free to add a 0
Limiting can be done in the JavaScript */
width: 10000%;
height: 400px;
position: relative;
/* Give it a default left of negative to allow scrolling in either direction */
left: -500px; top: 0;
clear: right;
}
.imagelist img {
float: left;
}
.edge {
position: absolute; top: 0;
width: 50px; height: 100%;
}
.edge.left { left: 0; }
.edge.right { right: 0; }
The JavaScript is the fun part. We find the edges and watch for hover and leave events. Considering only one may be hovered at once (both practically and due to mouseenter), we simply have one timer pointer. This timer controls our animation, and is used to stop the animation (clearInterval) on mouseleave. 20 times per second we move the .imagelist 5 pixels in one direction. That's determined based on which edge we're hovering over.
Instead of using $('.imagelist') we use .parent().find('.imagelist') so that there may be any number of image lists on the page.
var timer = 0;
$('.edge').mouseenter(function(){
var $self = $(this);
var $imglist = $self.parent().find('.imagelist');
timer = setInterval(function(){
var amount, changed;
if ($self.hasClass("left"))
amount = -5;
else
amount = 5;
changed = $imglist.offset().left + amount;
$imglist.offset({left: changed});
}, 50)
}).mouseleave(function(){
clearInterval(timer);
});
It's a little rough, but you can polish it up to suit your needs.

Horizontal slideshow with DIVs

I have a container div element, this should contain all child div elements.
I saw this thread: Slide a div offscreen using jQuery and I was wondering how to implement it (within a div element and not in the body).
The code is working fine, but what if the "wrapper" div element has 500px width, how am I supposed to wrap the child divs? Am I need to use iframe or ...?
For a better understanding I made this image:
The red rectangle would be a window and the grey background the wall. You can only see trough the window and see the current div element. If you push the right button -aqua- you will see the green div and if you push the left button you will see the yellow div.
Notice: Div elements should move and not the wall.
jQuery for the logic and CSS3 for transition and transform.
Multiple galleries + Auto-slide + Pause on hover:
$(function(){
$('.gallery').each(function() {
var $gal = $(this),
$movable = $(".movable", $gal),
$slides = $(">*", $movable),
N = $slides.length,
C = 0,
itv = null;
function play() { itv = setInterval(anim, 3000); }
function stop() { clearInterval(itv); }
function anim() {
C = ($(this).is(".prev") ? --C : ++C) <0 ? N-1 : C%N;
$movable.css({transform: "translateX(-"+ (C*100) +"%)"});
}
$(".prev, .next", this).on("click", anim);
$gal.hover(stop, play);
play();
});
});
.gallery{
position: relative;
overflow: hidden;
}
.gallery .movable{
display: flex;
height: 70vh;
transition: transform 0.4s;
}
.gallery .movable > div {
flex:1;
min-width:100%;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
Pause on hover and autoslide
<div class="gallery">
<div class="movable">
<div style="background:#0af">1 <p style="position:absolute; top:400px;">aaaa</p></div>
<div style="background:#af9">2</div>
<div style="background:#f0a">3</div>
</div>
<button class="prev">Prev</button>
<button class="next">Next</button>
</div>
As many galleries as you want
Count the number of slides and put into a counter C.
On prev/next click manipulate C
On autoslide $(this).is(".prev") will also evaluate as false so ++C will be used, just like clicking the Next button.
On mouseenter simply clearInterval the currently running itv and on mouseleave (the second .hover argument) reinitialize the itv
The animation is achieved by multiplying C*100 and translateX by - C * 100 %
Add all three div in a container div, then make the window wrap around the long div and hide the overflow.
Example if the window area is 960px then the div inside would be 3x 960 (2880)
You can center it by changing it's left position by increments of 960 (placing the long div in relative positioning and the window to overflow to hidden)
#window{
width:960px;
overflow: hidden;
}
#container{
position: relative;
left: -960px;
}
.content_box{
width:960px;
}
Then you can use javascript (jQuery) to animate the left position:
$('#arrow-left').click(function() {
$('#container').animate({
left: '-=960'
}, 5000, function() {
// Animation complete.
});
});
$('#arrow-right').click(function() {
$('#container').animate({
left: '+=960'
}, 5000, function() {
// Animation complete.
});
});
More on .animate can be found in the manual: http://api.jquery.com/animate/
<div id="parent">
<div id="container">
<div id="child1"></div>
<div id="child2"></div>
</div>
</div>
give the parent red div css properties:
position: relative;
overflow: hidden;
width: 500px;
height: somevalue;
wrap the children divs with another div "container for example" and give it the following css properties:
position: absolute;
width: ;/*overall width of all children divs including margins*/
top: 0;
left: 0;
height: ;/*same as parent*/
and finally for children divs:
float: left;
height: ;/*same as parent*/

Jquery transitions

i have a problem at this page http://ncca.co/indust.php
i would like the "contents" area to appear on selection of the appropriate a href and then the black footer to sweep across from the left. when link is selected i would like the "contents" to disappear and the new one appear and the black bar to sweep to the right have a mild gap and the new black boarder sweep in from the left.
how can i accomplish this?
i dont know how to post the code
Generically, what you will need to do is have a very wide div inside the "content" div which is set to overflow:hidden. Then you animate the offset of the x value to get the div you want into view.
<style>
#container {
width: 100px;
overflow: none;
position: relative;
}
#inner {
width: 300%;
position: relative;
left: 0;
}
#container div {
width: 100px;
float: left;
}
</style>
<div id="container">
<div id="inner">
<div>Foo</div>
<div>Bar</div>
<div>Baz</div>
</div>
</div>
<a id="show_1">Link 1</a>
<a id="show_2">Link 2</a>
<a id="show_3">Link 3</a>
<script>
$(document).ready(function() {
$("#show_1").click(function(){
$("#inner").animate(
{"left": 0}
1000 // Animate for 1 second
);
});
$("#show_2").click(function(){
$("#inner").animate(
{"left": 100}
1000 // Animate for 1 second
);
});
$("#show_3").click(function(){
$("#inner").animate(
{"left": 200}
1000 // Animate for 1 second
);
});
});
</script>
Docs on animate here: http://api.jquery.com/animate/
Live example here: http://www.volunteerspot.com/Organizer/Register
Hope that points you in the right direction!

Can't move element to end at right time

I am using jquery to slide images left inside a div set to hide overflows, and then remove the first image and append it to the end, so that I always have the same number of images in the list and they keep sliding left each time the function fires:
function xxx(){
var first = $('.ximg:first');
$('.ximg').animate({ left: '-=200'}, 2000, function(){ $('.ximg').css({left: '0'}); first.insertAfter($('.ximg:last'));});
}
setInterval(function(){ xxx () }, 8000);
<div style="position:relative; overflow:hidden; width: 400px; height: 150px;">
<div class="ximg" style="position: relative; width: 200px; min-height:150px; background:red"></div>
<div class="ximg" style="position: relative; width: 200px; min-height:150px; background:orange"></div>
<div class="ximg" style="position: relative; width: 200px; min-height:150px; background:green"></div>
<div class="ximg" style="position: relative; width: 200px; min-height:150px; background:yelow"></div>
</div>
But I only end up with 1 image in the container, the second only gets added when the function fires. I know there are read made plugins to do this kind of thing but I want it simple and prefer to try and write my own even thought I am relatively new with jquery !
http://jsfiddle.net/rgct2/6/
The container is 400 wide and as each div is 200 wide, there should always be 2 divs in view, even during animation when it will show a % of the first and 3rd divs.
A better way is probably to animate the width of the first element, so it doesn't require all elements to be animated.
function xxx() {
var origWidth = $('.ximg:first').width();
$('.ximg:first').animate({
width: 0
}, 2000, function() {$(this).insertAfter($('.ximg:last')).css({width: origWidth})});
}
There are also CSS problems with the elements. The parent element should have white-space: nowrap, so the elements are in the same line, even when they're not visible. The children elements should have display:inline-block, so they can be in a line (i.e. inline), and have configurable widths.
Another thing to be aware of is the space between <div>s. You need to make sure there is no unintentional spaces, which include newlines.
See the updated demo: http://jsfiddle.net/rgct2/7/.
Tested and its working, instead of use remove, use "detach"
function xxx(){
$('.ximg').css({left: '0'});
$('.ximg').animate({ left: '-=200'}, 2000, function(){ });
$('.ximg:first').detach().insertAfter( $('.ximg:last') );
}

Categories