This may be a little too specific, but I have a jquery slider that I am using <p> classes instead of images to cycle through customer quotes. Basically the problem I am running into right now is when it is static and non moving (JS code is commeneted out) they are aligned how I want them to be. As soon as the JS is un commented, they stretch out of view and you just see a white box?
Any ideas?
How I want each panel to look like:
jsfiddle
So I sort of made this my Friday project. I've changed a whole lot of your code, and added a vertical-align to the quotes and authors.
Here's the fiddle http://jsfiddle.net/qLca2fz4/49/
I added a whole lot of variables to the top of the script so you could less typing throughout.
$(document).ready(function () {
//rotation speed and timer
var speed = 5000;
var run = setInterval(rotate, speed);
var slides = $('.slide');
var container = $('#slides ul');
var elm = container.find(':first-child').prop("tagName");
var item_width = container.width();
var previous = 'prev'; //id of previous button
var next = 'next'; //id of next button
Since you used a % based width I'm setting the pixel widths of the elements in case the screen is reszed
slides.width(item_width); //set the slides to the correct pixel width
container.parent().width(item_width);
container.width(slides.length * item_width); //set the slides container to the correct total width
As you had, I'm rearranging the slides in the event the back button is pressed
container.find(elm + ':first').before(container.find(elm + ':last'));
resetSlides();
I combined the prev and next click events into a single function. It checks for the ID of the element targeted in the click event, then runs the proper previous or next functions. If you reset the setInterval after the click event your browser has trouble stopping it on hover.
//if user clicked on prev button
$('#buttons a').click(function (e) {
//slide the item
if (container.is(':animated')) {
return false;
}
if (e.target.id == previous) {
container.stop().animate({
'left': 0
}, 1500, function () {
container.find(elm + ':first').before(container.find(elm + ':last'));
resetSlides();
});
}
if (e.target.id == next) {
container.stop().animate({
'left': item_width * -2
}, 1500, function () {
container.find(elm + ':last').after(container.find(elm + ':first'));
resetSlides();
});
}
//cancel the link behavior
return false;
});
I've found mouseenter and mouseleave to be a little more reliable than hover.
//if mouse hover, pause the auto rotation, otherwise rotate it
container.parent().mouseenter(function () {
clearInterval(run);
}).mouseleave(function () {
run = setInterval(rotate, speed);
});
I broke this in to its own function because it gets called in a number of different places.
function resetSlides() {
//and adjust the container so current is in the frame
container.css({
'left': -1 * item_width
});
}
});
//a simple function to click next link
//a timer will call this function, and the rotation will begin :)
And here's your rotation timer.
function rotate() {
$('#next').click();
}
It took me a little bit, but I think I figured out a few things.
http://jsfiddle.net/qLca2fz4/28/
First off, your console was throwing a few errors: first, that rotate wasn't defined and that an arrow gif didn't exist. Arrow gif was probably something you have stored locally, but I changed the 'rotate' error by changing the strings in the code here to your actual variables.
So, from:
run = setInterval('rotate()', speed);
We get:
run = setInterval(rotate, speed);
(No () based on the examples here: http://www.w3schools.com/jsref/met_win_setinterval.asp)
But I think a more important question is why your text wasn't showing up at all. It's because of the logic found here:
$('#slides ul').css({'left' : left_value});
You even say that this is setting the default placement for the code. But it isn't..."left_vaule" is the amount that you've calculated to push left during a slide. So if you inspect the element, you can see how the whole UL is basically shifted one slide's worth too far left, unable to be seen. So we get rid of 'left_value', and replace it with 0.
$('#slides ul').css({'left' : 0});
Now, there's nothing really handling how the pictures slide in, so that part's still rough, but this should be enough to start on.
Let me know if I misunderstood anything, or if you have any questions.
So, a few things:
1) I believe you are trying to get all of the lis to be side-by-side, not arranged up and down. There are a few ways to do this. I'd just make the ul have a width of 300%, and then make the lis each take up a third of that:
#slides ul {
....
width: 300%;
}
#slides li {
width: calc(100% / 3);
height:250px;
float:left;
}
2) You got this right, but JSFiddle automatically wraps all your JS inside a $(document).ready() handler, and your function, rotate needs to be outside, in the normal DOM. Just change that JSFiddle setting from 'onload' to 'no wrap - in head'
3) Grabbing the CSS value of an element doesn't always work, especially when you're dealing with animating elements. You already know the width of the li elements with your item_width variable. I'd just use that and change your code:
var left_indent = parseInt($('#slides ul').css('left')) - item_width;
$('#slides ul').animate({'left' : left_indent}, 1500, function () {
to:
$('#slides ul').stop().animate({'left' : -item_width * 2}, 1500, function () {
4) Throw in the .stop() as seen in the above line. This prevents your animations from overlapping. An alternative, and perhaps cleaner way to do this, would be to simply return false at the beginning of your 'next' and 'prev' functions if #slides ul is being animated, like so:
if ($('#slides ul').is(':animated')) return false;
And I think that's everything. Here's the JSFiddle. Cheers!
EDIT:
Oh, and you may also want to clearInterval at the beginning of the next and prev functions and then reset it in the animation callback functions:
$('#prev').click(function() {
if ($('#slides ul').is(':animated')) return false;
clearInterval(run);
$('#slides ul').stop().animate({'left' : 0}, 1500,function(){
....
run = setInterval('rotate()', speed);
});
});
Related
I'm pretty new with Jquery. I would like that my animations with Wow.js could run more than once time. For instance: i scroll to the bottom of my page and see all the animations, and if i scroll back to the top i see again the animations like when you scroll down. I hope that I explained myself. I have already seen many websites that repeats the animations on theirs pages but unfortunately I don't remember them and I can't provide a link.
I have already tried this:
$(window).scroll(function(){
new WOW().init();
}
But it repeat the animations also if you scroll a little and it's pretty ugly to see. I try to explain me better: I have a with my animation and if it is focused the animation is triggered, then i scroll down to another div and the previous div is no more visible(not in the window viewport), then again i scroll back to my div with animation and the animation is triggered again.
I'm sorry for this messy question but I really don't know how to explain it.
Thanks in advance!
This example by Benoît Boucart shows how the animation can be "reset" when the user scrolls out of view and back in. The key here is the second function that removes the animation css class when the element scrolls out of view. I wish WOW.js would implement this, but they've indicated that they don't plan to.
http://codepen.io/benske/pen/yJoqz
Snippet:
// Showed...
$(".revealOnScroll:not(.animated)").each(function () {
var $this = $(this),
offsetTop = $this.offset().top;
if (scrolled + win_height_padded > offsetTop) {
if ($this.data('timeout')) {
window.setTimeout(function(){
$this.addClass('animated ' + $this.data('animation'));
}, parseInt($this.data('timeout'),10));
} else {
$this.addClass('animated ' + $this.data('animation'));
}
}
});
// Hidden...
$(".revealOnScroll.animated").each(function (index) {
var $this = $(this),
offsetTop = $this.offset().top;
if (scrolled + win_height_padded < offsetTop) {
$(this).removeClass('animated fadeInUp flipInX lightSpeedIn')
}
});
If a user wants to repeat the animation on both the events i.e.
onScrollUp
onScrollDown
then this will be a good solution for it:
First create an addBox function, it will help to push new elements into the WOW boxes array.
WOW.prototype.addBox = function(element){
this.boxes.push(element);
};
Then use jQuery and scrollspy plugin that helps to detect which element is out of the view and then push WOW as:
$('.wow').on('scrollSpy:exit',function(){
var element = $(this);
element.css({
'visibility' : 'hidden',
'animation-name' : 'none'
}).removeClass('animated');
wow.addBox(this);
});
Solution Courtesy: ugurerkan
Answer by #vivekk is correct I m just adding a working example so that people can easily get this
see the Demo fiddle
<script>
// Repeat demo content
var $body = $('body');
var $box = $('.box');
for (var i = 0; i < 20; i++) {
$box.clone().appendTo($body);
}
// Helper function for add element box list in WOW
WOW.prototype.addBox = function(element) {
this.boxes.push(element);
};
// Init WOW.js and get instance
var wow = new WOW();
wow.init();
// Attach scrollSpy to .wow elements for detect view exit events,
// then reset elements and add again for animation
$('.wow').on('scrollSpy:exit', function() {
$(this).css({
'visibility': 'hidden',
'animation-name': 'none'
}).removeClass('animated');
wow.addBox(this);
}).scrollSpy();
</script>
I want to create a webpage that contains several sections. In one of those sections are something like progress bars. These progress bars are 'animated' so that the user sees them loading on the screen as shown in the example.
Example here
Now this is working as it is but my problem is this:
I want the progress bars to start loading when the bars become visible on the screen.
Once the user scrolls down and gets them in the middle of the screen, the 'animation' should start. The way it is now the animation starts on page load, but the bars are not yet visible as in the following fiddle:
Fiddle
A little extra would be that each bar starts loading after the previous is finished.
I found some similar questions on stack but the answer does not suffice to my needs:
Animate progress bar on scroll & Run animation when element is visible on screen
I tried stuff like (it's not the actual code but it's what I remember of it):
var target = $("#third").offset().top;
var interval = setInterval(function() {
if ($(window).scrollTop() >= target) {
//start loading progress bar
}
}, 250);
But without any good results.
Can anyone help me on this matter?
Thanks in advance!
Here is a fiddle: http://jsfiddle.net/rAQev/4/
I've used a comparison of scroll offset and your special section offset to detect a moment when this section becomes visible.
Animations are queued to be processed one after another using jQuery queue function, you can read about it in jQuery docs (http://api.jquery.com/queue/).
Also scroll event is unbinded when the first 'loading' happens, not to run 'loading' again and again on scroll event when section is visible.
Here is an updated fiddle http://jsfiddle.net/9ybUv/
This one allows for all the progress bars to run at the same time. If you were like me and had 5 or more it takes a long time to do one, then the next, then the next.
$(function() {
var $section = $('#third');
function loadDaBars() {
$(".meter > span").each(function() {
$(this)
.data("origWidth", $(this).width())
.width(0)
.animate({
width: $(this).data("origWidth")
}, 1200);
});
}
$(document).bind('scroll', function(ev) {
var scrollOffset = $(document).scrollTop();
var containerOffset = $section.offset().top - window.innerHeight;
if (scrollOffset > containerOffset) {
loadDaBars();
// unbind event not to load scrolsl again
$(document).unbind('scroll');
}
});
});
Let me try something
function startProgressBar() {
$(".meter > span").each(function() {
$(this)
.data("origWidth", $(this).width())
.width(0)
.animate({
width: $(this).data("origWidth")
}, 1200);
});
}
$(window).scroll(function() {
var target = $('#third');
var targetPosTop = target.position().top; // Position in page
var targetHeight = target.height(); // target's height
var $target = targetHeight + targetPosTop; // the whole target position
var $windowst = $(window).scrollTop()-($(window).height()/2); // yes divided by 2 to get middle screen view.
if (($windowst >= $targetPosTop) && ($windowst < $target)){
// start progressbar I guess
startProgressBar();
}
});
Give it a try, let me know.
I made a simple content/box slider which uses the following javascript:
$('#left').click(function () {
$('#videos').animate({
marginLeft: '-=800px'
}, 500);
});
$('#right').click(function () {
$('#videos').animate({
marginLeft: '+=800px'
}, 500);
});
Here is the demo: http://jsfiddle.net/tjset/2/
What I want to do and I can't figure out how to show and hide arrows(left and right box) as the all the boxes slided.
So I clicked 4 time to the LEFT and slided all the boxes! then hide "left" so that you can't give more -800px
What can I do?
What you can do is check after the animation completes to see if the margin-left property is smaller or larger than the bounds of the video <div>. If it is, depending on which navigation button was clicked, hide the appropriate navigation link.
Check out the code below:
$('#left').click(function () {
// reset the #right navigation button to show
$('#right').show();
$('#videos').animate({
marginLeft: '-=800px'
}, 500, 'linear', function(){
// grab the margin-left property
var mLeft = parseInt($('#videos').css('marginLeft'));
// store the width of the #video div
// invert the number since the margin left is a negative value
var videoWidth = $('#videos').width() * -1;
// if the left margin that is set is less than the videoWidth var,
// hide the #left navigation. Otherwise, keep it shown
if(mLeft < videoWidth){
$('#left').hide();
} else {
$('#left').show();
}
});
});
// do similar things if the right button is clicked
$('#right').click(function () {
$('#left').show();
$('#videos').animate({
marginLeft: '+=800px'
}, 500, 'linear', function(){
var mRight = parseInt($('#videos').css('marginLeft'));
if(mRight > 100){
$('#right').hide();
} else {
$('#right').show();
}
});
});
Check out the jsfiddle:
http://jsfiddle.net/dnVYW/1/
There are many jQuery plugins for this. First determine how many results there are, then determine how many you want visible, then use another variable to keep track with how many are hidden to the left and how many are hidden to the right. So...
var total = TOTAL_RESULTS;
var leftScrolled = 0;
var rightScrolled = total - 3; // minus 3, since you want 3 displayed at a time.
instead of using marginLeft I would wrap all of these inside of a wrapper and set the positions to absolute. Then animate using "left" property or "right". There's a lot of code required to do this, well not MUCH, but since there are many plugins, I think you'd be better off searching jquery.com for a plugin and look for examples on how to do this. marginLeft is just not the way to go, since it can cause many viewing problems depending on what version of browser you are using.
I have two pagination links which trigger a jQuery animation.
A callback function on the animation triggers a second animation.
This works fine, however, it only works the first time the function is called.
Each time after, the first of the 2 animations works and the second one does not, it merely changes the CSS without the effect.
I'm racking my brain here, to no effect (pun intended).
function switchItem(e) {
e.preventDefault();
// If not current piece
if($(this).hasClass('light')) {
/* VARIABLES */
var container = $('.portfolio footer .portfolio_content');
var link = $(this).attr('id');
var newItem = $(this).html();
/*===================================================
* This is the Key part here
===================================================*/
/* FIRST ANIMATION */
container.animate({
'right':'-100%'
}, 300, 'swing',
// Callback Function
function() {
$(this).html('').css({'left':'-100%'});
$.get('inc/portfolio/'+link+'.php', function(data) {
container.html(data);
/* SECOND ANIMATION */
container.animate({
'left':'0%'
}, 300, 'swing');
});
});
}
}
Here is the demonstration: http://eoghanoloughlin.com/my_site/#portfolio
See working sample here, your left is conflicting with your first right -100% animation and at the end if you don't reset the right then it will conflict with your second left animation
http://jsfiddle.net/PAdr3/2/
reset left before animating
container.css('left', 'auto');
and reset right when complete
container.animate({
'left':'0%'
}, 300, 'swing', function() {
$(this).css('right', 'auto');
});
When you replace the html in a page with new content, it will not automatically add listeners or other jquery enhancements that are added via javascript.
I suspect you need to apply these again after you put the content you fetched with $.get into the page.
Another alternative, is to add all the content in one load, but make the second page hidden. This is probably a nicer alternative than using $.get
I think that the animate function does not string until the first animate is ready. The docs say:
If supplied, the complete callback function is fired once the
animation is complete. This can be useful for stringing different
animations together in sequence.
Something like this might work:
function switchItem(e) {
e.preventDefault();
// If not current piece
if($(this).hasClass('light')) {
/* VARIABLES */
var container = $('.portfolio footer .portfolio_content');
var link = $(this).attr('id');
var newItem = $(this).html();
/*===================================================
* This is the Key part here
===================================================*/
/* FIRST ANIMATION */
container.animate({
'right':'-100%'
}, 300, 'swing',
// Callback Function
function() {
$(this).html('').css({'left':'-100%'});
$.get('inc/portfolio/'+link+'.php', function(data) {
container.html(data);
});
}).complete(
/* SECOND ANIMATION */
container.animate({
'left':'0%'
}, 300, 'swing');
);
}
}
I am implementing an image slider in javascript/jquery.
The demo should work like this.
http://londatiga.net/tutorials/scrollable/
Anyway I don't won't to rely on jquery.tools.min.js because this lib is out of date (the last update is about 8 months ago ).
I decide to make the js code by me.
When clicking on next or prev button I would like to shift the images on the list of one item/image.
The script shifts the items but the display is quite crappy, because the next items is not displayed.
The list is made of 4 images. At the beginning only the first two images are displayed, then when clicking on the next button I would like to display the second and the third image.
Actually the script shows just the first and the second image even if I click on the next button.
Here is the demo: http://jsfiddle.net/xRQBS/5/
Here is the code (1)
Any hints how should I fix it?
thanks
(1)
/*global jQuery */
(function ($) {
var imgs = [
'https://encrypted-tbn2.gstatic.com/images?q=tbn:ANd9GcSsarNmO4Vdo5QwHfznbyxPmOyiYQ-KmBKUFsgEirvjW6Kbm7tj8w',
'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcRfIAfLXj3oK1lso1_0iQploSKsogfJFey3NnR0nSD9AfpWjU7egA',
'https://encrypted-tbn0.gstatic.com/images?q=tbn:ANd9GcR1dO4FVDDitdS85aLOCsOpQyHHTysDhD4kHQ749bMtNxaj5GMKnA',
'https://encrypted-tbn1.gstatic.com/images?q=tbn:ANd9GcRAPO77sVu-Xk80S_txagySoTq8gKHgeiS63a9TYtKbPpGYVI5X'
];
var $list = $('.list-images');
var $slider = $('.slider');
var slideImage = function (direction) {
var unit = 150;
var left = parseInt($slider.attr('left'), 10) || 0;
left = (direction === 'prev') ? left - 150 : left + 150;
$slider.css('left', left + 'px');
};
$(function () {
$.each(imgs, function (i, img) {
$list.append($('<li>').append($('<img>').attr('src', img)));
});
$('body').on('click', '.direction', function () {
slideImage($(this).attr('data-tid'));
});
});
}(jQuery));
With the animate function:
$slider.animate({'left': left + 'px'}, 1000);
http://jsfiddle.net/xRQBS/6/
I'm assuming that you want the shift to be more of an animation. If so, take a look at jQuery's animate. Something like this:
$slider.animate({left: left + 'px'});
That will give it a sliding effect, which what I'm assuming you want :)