Stopping all other animations using no selector in $.animate with step()? - javascript

I'm animating objects using arrays in my selector which I am stuck using for a specific reason in another SO post I made.
How am I able to stop other animations that have been started from arbitrary array values? E.g: $({ x: 0 }).animate({
For example:
$({ x: 0 }).animate({
x: 500
}, {
easing: 'linear',
duration: 15000,
step: function(now, fx) {
// $(this).stop();
var current_styles = $(selector).attr('style'),
current_styles = string = current_styles.split(" ");
var x = parseFloat(current_styles[1].replace('px', '').replace(';', ''));
if ('x' === fx.prop) {
x = now;
}
$(selector).attr({ style: 'margin-left: ' + x + 'px;' });
},
complete: function() {
//
}
});
HTML:
<div class="row row_1"><button data-id="1">GO</button><div class="box" style="margin-left: 0;"></div></div>
<div class="row row_2"><button data-id="2">GO</button><div class="box" style="margin-left: 0;"></div></div>
<div class="row row_3"><button data-id="3">GO</button><div class="box" style="margin-left: 0;"></div></div>
<div class="row row_4"><button data-id="4">GO</button><div class="box" style="margin-left: 0;"></div></div>
<div class="row row_5"><button data-id="5">GO</button><div class="box" style="margin-left: 0;"></div></div>
<div class="row row_6"><button data-id="6">GO</button><div class="box" style="margin-left: 0;"></div></div>
CSS:
.row {
background-color: green;
margin-bottom: 1px;
width: 600px;
}
.box {
background-color: red;
height: 20px;
width: 20px;
display: inline-block;
}
button {
float: left;
}
I want to stop all other animations when I start this one. However, I cannot use $(selector).stop(); as it does not work.
JSFiddle & gif of issue:
JSFiddle of desired results (Using incorrect formatting for my purpose):
You can stop an animation from within a step() using $(this).stop(); but that only stops the one animation you are inside.
Basically, I need to be able to stop all other animations and then continue with the animation that was just started. The JS itself works exactly as intended, I just need to stop the old animations in their tracks as the new one starts.
It's not clear to me of an elegant nor easy way to do this when using:
$({ x: 0 }).animate({
Thank you for taking the time to consider my question

Store the previous started animation in a variable so you can access it (to retrieve the current value and to stop it):
var prevAnimation;
function runAnimation(selector) {
var start = 0;
if (prevAnimation) {
start = prevAnimation.get(0).x;
prevAnimation.stop();
}
prevAnimation = $({ x: start }).animate({
x: 500
}, {
easing: 'linear',
// And so on
Updated fiddle: https://jsfiddle.net/7vk9d2te/9/
-- Update --
If your animation is just about the margin-left, you could really simplify your code by removing the step function and letting jQuery do the magic with
function runAnimation(selector) {
var start = 0;
if (prevAnimation) {
start = parseFloat(prevAnimation.css('margin-left'));
prevAnimation.stop();
}
prevAnimation = $(selector)
.css('margin-left', start + 'px')
.animate({ 'margin-left': 500 }, {
easing: 'linear',
duration: 15000,
});
}
Fiddle: https://jsfiddle.net/7vk9d2te/10/

Related

jQuery get dynamic nested element to call animate method

I am dynamically adding data to a div by pressing a button called view.
That is working fine, however I decided to take it a step further and another nested dynamic element.
I can make the call just fine from the dynamic div. The issue I am running into now is when I call the dynamic div to expand the all-views it only expands one; it will not expand any others.
I have verified that my call is correct by adding a var d = Date() and calling the milliseconds as a data-value.
I did some searching and found the parents() and find() methods. I can find the div but it still calls only one.
I have dynamically added 100 divs and it still only calls the newest one. I have also tried another on() with the resize and other triggered events.
What am I missing here?
$("#view").click(function() {
var d = new Date();
$("#dynamic-div-post").prepend('<div class="dynamic-div" style="width: 100%; background-color: red"><div class="col-6"><button id="btn-view" type="button" data-value="test-view" class="btn btn-outline-dark w-100 border-0 d-none d-sm-block"><img class="" src="/img/like.png" style="height: 18px;">view</button></div></div><div class="row dynamic-div" style="width: 100%; background-color: blue;"><div class="col-6 p-0"><div class="all-views" style="background-color: blue; width: 100%; display: none"></div></div></div>');
});
$("#dynamic-div-post").on('click', "#btn-view", function() {
//alert($(this).parents('#dynamic-div-post').find('.all-views').css('display'));
switch ($(this).parents('#dynamic-div-post').find('.all-views').css('display')) {
case 'none':
$(this).parents('#dynamic-div-post').find('.all-views').css({
'border-top': "1px solid rgba(0, 0, 0, 0.2)",
'display': 'block'
}).animate({
"min-height": "150px"
}, 1000, function() {
// Animation complete.
});
break;
case 'block':
$(this).parents('#dynamic-div-post').find('.all-views').animate({
borderWidth: 0,
"min-height": "0",
display: "none"
}, 1000, function() {
$(this).parents('#dynamic-div-post').find('.all-views').css({
'border-top': "none",
'display': 'none'
})
});
break;
}
//$(this).blur();
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id='dynamic-div-post' class='static-div'>
</div>
<div id='div-view' class='static-div'>
<button id='view'>view</button>
</div>
Found it. The button parent div was not a parent of the allViews
Change all dynamic elements from having ID to a class
Give the parent container a class we can recognise. Too many dynamic-div classes
You needed the NEXT div to open and close.
I simplified the animation
$("#view").click(function() {
var d = new Date();
$("#dynamic-div-post").prepend('<div class="dynamic-div container" style="width: 100%; background-color: red"><div class="col-6"><button type="button" data-value="test-view" class="btn-view btn btn-outline-dark w-100 border-0 d-none d-sm-block"><img class="" src="https://img.icons8.com/pastel-glyph/2x/facebook-like.png" style="height: 18px;">view</button></div></div><div class="row dynamic-div" style="width: 100%; background-color: blue;"><div class="col-6 p-0"><div class="all-views" style="background-color: yellow; width: 100%;">Here is some text</div></div></div>');
});
$("#dynamic-div-post").on('click', ".btn-view", function() {
const $allViews = $(this).closest('.container').next().find('.all-views');
if (!$allViews.is(".open")) {
$allViews.css({
'border-top': "1px solid rgba(0, 0, 0, 0.2)",
'display': 'block'
}).animate({
"min-height": "150px"
}, 1000, function() {
$allViews.addClass("open")
});
} else {
$allViews.animate({
"borderWidth": 0,
"min-height": 0,
"display": "none"
},function() { $allViews.removeClass("open") });
}
});
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id='dynamic-div-post' class='static-div'>
</div>
<div id='div-view' class='static-div'>
<button id='view'>view</button>
</div>

Flexslider fullscreen is not centered in mobile

I have this fullscreen background that I'm using and it works correctly on my laptop and big screens. The problem is when I enter the website from a mobile device. The background image (and the buttons above it) move to the side. I do not know why is this. I think it has to be with the bootstrap.min.
The HTML:
<!-- Intro Section -->
<section id="intro">
<!-- Hero Slider Section -->
<div class="flexslider fullscreen-carousel hero-slider-1 ">
<ul class="slides">
<!--Slide-->
<li data-slide="dark-slide">
<div class="slide-bg-image overlay-light dark-bg parallax" data-background-img="images/connexion_background.jpg">
<div class="js-Slide-fullscreen-height container">
<div class="intro-content">
<div class="intro-content-inner">
<br />
<div><a class="btn btn-md btn-white" href="contact.php">Request a Quote</a><span class="btn-space-10"></span><a class="btn btn-md btn-white " href="research-solutions.html">View Our Solutions</a></div>
</div>
</div>
</div>
</div>
</li>
</ul>
</div>
<!-- End Hero Slider Section -->
</section>
<div class="clearfix"></div>
<!-- End Intro Section -->
The JS:
var pageSection = $('.slide-bg-image, .bg-image');
pageSection.each(function (indx) {
if ($(this).attr("data-background-img")) {
$(this).css("background-image", "url(" + $(this).data("background-img") + ")");
}
});
function fullScreenSlider() {
if ($('.fullscreen-carousel').length > 0) {
$('.fullscreen-carousel').flexslider({
animation: "slide",
// startAt: 0,
animationSpeed: 700,
animationLoop: true,
slideshow: true,
easing: "swing",
controlNav: false,
before: function (slider) {
//Slide Caption Animate
$('.fullscreen-carousel .intro-content-inner').fadeOut().animate({ top: '80px' }, { queue: false, easing: 'easeOutQuad', duration: 700 });
slider.slides.eq(slider.currentSlide).delay(400);
slider.slides.eq(slider.animatingTo).delay(400);
},
after: function (slider) {
//Slide Caption Animate
$('.fullscreen-carousel .flex-active-slide').find('.intro-content-inner').fadeIn(2000).animate({ top: '0' }, { queue: false, easing: 'easeOutQuad', duration: 1200 });
// Header Dark Light
headerDarkLight_with_flexslider();
},
start: function (slider) {
$('body').removeClass('loading');
// Header Dark Light
headerDarkLight_with_flexslider();
},
useCSS: true,
});
};
// Header Dark Light
function headerDarkLight_with_flexslider() {
var color = $('.fullscreen-carousel').find('li.flex-active-slide').attr('data-slide');
if (color == 'dark-slide') {
$('#header').addClass('header').removeClass('header-light');
$('#header').removeClass('header-default');
}
if (color == 'light-slide') {
$('#header').addClass('header-light').removeClass('header-dark');
$('#header').removeClass('header-default');
}
if (color == 'default-slide') {
$('#header').removeClass('header-dark');
$('#header').removeClass('header-light');
$('#header').addClass('header');
}
};
// "fullscreen-carousel" height
fullScreenCarousel();
function fullScreenCarousel() {
var windowWidth = $(window).width();
var windowHeight = $(window).height();
if ($(window).width() > 767) {
$('.hero-slider-1 .slides .js-Slide-fullscreen-height').css("height", windowHeight);
}
else {
$('.hero-slider-1 .slides .js-Slide-fullscreen-height').css("height", '400px');
}
};
$(window).resize(function () {
fullScreenCarousel();
});
};
This is the result in mobile:
The buttons and the background image are moved to the right. They are not centered and the background picture repeat itself.
I can see this on the development tool of Mozilla:
Any help would be appreciated.
Thank you.
center the images in your slides add this in your css
.flexslider img { margin: 0 auto; }
OR
.flexslider .slides > li{
background-size: cover;
background-repeat: no-repeat;
background-position: center;
}
can you try to add following css at last of the css document
.flexslider ul.slides {
padding: 0 !important;
}
Your flex slider left position is not right , You can simply fix this with left property, try with the below code
.fullscreen-carousel .slides li {
height: 100%;
left: -40px; /* newly added */
overflow: hidden;
position: relative;
}
can you try this also , remove the left:-40px and add this jquery to the page
$(window).load(function() {
$('.flexslider').flexslider();
$(window).trigger('resize');
});

JS counter when scroll to a div stop counting

I want to make a counter on javascript that when you go to certain div, start counting and when you reach the specified number it stops, and if I continue scrolling, the counter no longer keep counting
I have made a Pen with the idea, but when I continue scrolling the counter do not stop, and start to count down, and then stop when reach a low number.
Any idea to make this work?
Thanks in advance.
HTML
<!-- Counter section -->
<div id="counter" class="Wrapper-counter">
<!-- Counter_item -->
<div class="Counter_item">
<h3 class="Counter_h3 right">
<span class="count">
123
</span>
</h3>
<p class="Counter_paragraph right">
<strong>Lorem ipsum</strong>
</p>
</div>
<!-- /Counter_item -->
<!-- Counter_item -->
<div class="Counter_item">
<h3 class="Counter_h3 left">
<span class="count">
123
</span>
</h3>
<p class="Counter_paragraph left">
<strong>Lorem ipsum</strong>
</p>
</div>
<!-- /Counter_item -->
</div>
<!-- /Counter section -->
JS
$(window).on('scroll', function() {
var div_counter = window.pageYOffset;
var scroll_pos_test = $('#counter').offset().top - window.innerHeight; // set to whatever you want it to be
if(div_counter < scroll_pos_test) {
//do stuff
$('.count').each(function () {
$(this).prop('Counter',0).animate({
Counter: $(this).text()
}, {
duration: 3000,
easing: 'swing',
step: function (now) {
$(this).text(Math.ceil(now));
}
});
});
}
});
codepen here
I didn't understand your code, but I created an example of what you are looking for which might give you a new perspective of how to tackle this problem in an easier way. Check out the working example on CODEPEN.
HTML
<div class="container">
<p data-counter="100">100</p>
</div>
CSS
p {
font-size: 3em;
position: fixed;
color: blue;
}
.container {
position: relative;
height: 700px;
background: #ccc;
}
JS
$(document).ready(function() {
var topCount = 100;
var maxCount = 50;
var startCount = 200;
var endCount = 400;
var currCount = 0;
$(window).scroll(function() {
if (($(window).scrollTop() >= startCount) && ($(window).scrollTop() <= endCount)) {
currCount = Math.floor(maxCount + (maxCount - topCount) * ($(window).scrollTop() - endCount) / (endCount - startCount));
$("p").attr("data-counter",currCount).text(currCount);
}
});
});
It should be pretty straight-forward. I don't have a resetting mechanism since I don't know how you want to do it or if you want to have it at all. but it is easy to add any modification
thanks for the code but it is not what I was looking; I solved the problem by adding the plugin INVIEW JQUERY and the following script, thanks anyway
CODEPEN DEMO
$('#counter').bind('inview', function(event, visible, visiblePartX, visiblePartY) {
if (visible) {
$(this).find('.count').each(function () {
var $this = $(this);
$({ Counter: 0 }).animate({ Counter: $this.text() }, {
duration: 2000,
easing: 'swing',
step: function () {
$this.text(Math.ceil(this.Counter));
}
});
});
$(this).unbind('inview');
}
});

Shrink div's then restore them on click

Ideally I want a windows 7 style minimize the div then restore. I want a method that literally takes the div, shrinks and move it to the bottom left of the screen, then can be clicked on to restore it to the center. Please help! Here is my jsfiddle for the basic operation of moving the divs using buttons:
http://jsfiddle.net/UqWC6/1/
var clicked = 0;
var restored = 0;
$("#go").click(function () {
if ($(".box" + clicked)) {
$(".box" + clicked).animate({
top: 400,
width: "20px;",
height: "20px;",
opacity: 0.4,
});
clicked++;
} else {
clicked = 0;
}
});
$('#go2').click(function () {
if ($(".box" + restored)) {
$(".box" + restored).animate({
top: -20,
width: "140px;",
height: "140px;",
opacity: 1,
});
restored++;
} else {
restored = 0;
}
});
http://jsfiddle.net/UqWC6/2/
I removed the incorrect semicolons. And linked to jqueryUI in the fiddle.
So changed these lines from
width: "20px;",
height: "20px;",
width: "140px;",
height: "140px;",
To this
width: "20px",
height: "20px",
width: "140px",
height: "140px",
Seems to work great now. Let me know if that's what you want.
EDIT: http://jsfiddle.net/UqWC6/3/ I fixed it so the third one only needs one click, instead of two.
I changed your html from this
<p>
<button id="go">Save »</button>
<button id="go2">Restore Next</button>
</p>
<div class="box0">box 1</div>
<div class="box1">box 2</div>
<div class="box3">box 2</div>
To this
<p>
<button id="go">Save »</button>
<button id="go1">Restore Next</button>
</p>
<div class="box0">box 1</div>
<div class="box1">box 2</div>
<div class="box2">box 3</div>
And changed this script line from
$('#go2').click(function () {
To this
$('#go1').on('click', function () {
EDIT http://jsfiddle.net/UqWC6/4/ I made it so that you can continue to loop through the clicks once they hit 3 clicks (reset them to 0)
added
if (clicked === 3) {
clicked = 0;
}
if (restored === 3) {
restored = 0;
}

jquery slider with controls and automatic scrolling

Basically I am just trying to do random jQuery stuff for educational purpose, and here is my very simple slider. I want it to work automatically and also with controls (little arrows to scroll to next/previous slider). The only problem that I have right now is that when you press the arrow, the function that automatically switches slides every 5 seconds is still counting these 5000 ms, so the next slide appears faster then desired. What I want is to make those arrows reset the timer, so you press the arrow -> next slide appears -> only after 5 seconds later the slide switches again.
Sorry for sloppy explanation, hope I made it clear enough.
Here's the jsfiddle: http://jsfiddle.net/cA9aW/
and here is the code
HTML
<body>
<div id="wrapper">
<header>
<h1>Simplest Sliding Image Slider</h1>
</header>
<div id="content">
<div id="slider_container">
<div id="slider">
<div class="slides" id="slide1">
<img src="http://s2.postimg.org/5uxqi0mgl/cats1.jpg" alt="" />
</div>
<div class="slides" id="slide2">
<img src="http://s2.postimg.org/66f6us2wl/cats2.jpg" alt="" />
</div>
<div class="slides" id="slide3">
<img src="http://s2.postimg.org/ai3sjs9th/cats3.jpg" alt="" />
</div>
</div>
</div>
</div>
<footer></footer>
</div>
</body>
JS
jQuery(document).ready(function($) {
// start slider function
startSlider();
// set width and step variables and add active class to first slider
var slideWidth = $('.slides').width();
$('#slide1').addClass('slides active');
// actual function
function startSlider() {
looper = setInterval(function() {
// remove and add class active
$('.active').removeClass('active').next().addClass('active');
// animation expression
$('.active').animate({'left': '-=' + (slideWidth) + 'px'}, 500);
$('.active').siblings().animate({'left': '-=' + (slideWidth) + 'px'}, 500);
// return to first slide after the last one
if($('.active').length == 0) {
$('#slide1').addClass('active');
$('.slides').animate({'left': 0}, 500);
}
}, 5000); // interval
// adding controls
$('.slides').append("<div class='controls'><a class='control_left' href='#'></a><a class='control_right' href='#'></a></div>");
// remove unnecessary controlls on first and last slides
$('.slides:nth-child(1) a.control_left').remove();
$(".slides:nth-child(" + $('.slides').length + ") a.control_right").remove();
// add functionality to controls
$('.control_left').on('click', function() {
$('.active').removeClass('active').prev().addClass('active');
$('.active').animate({'left': '+=' + (slideWidth) + 'px'}, 500);
$('.active').siblings().animate({'left': '+=' + (slideWidth) + 'px'}, 500);
});
$('.control_right').on('click', function() {
$('.active').removeClass('active').next().addClass('active');
$('.active').animate({'left': '-=' + (slideWidth) + 'px'}, 500);
$('.active').siblings().animate({'left': '-=' + (slideWidth) + 'px'}, 500);
});
}
});
Thx a lot in advance
Slideshow with prev/next buttons, autoslide, pause on hover
Instead of jQuery's .animate() and animating the left CSS property, use the GPU accelerated CSS transform: translateX for the animation on a common slides wrapper element
$(".SlideShow").each((i, EL) => {
const
$parent = $(EL),
$slides = $(".SlideShow-slides", EL),
$item = $(".SlideShow-item", EL),
$prevNext = $(".SlideShow-btn", EL),
tot = $item.length,
mod = (n, m) => ((n % m) + m) % m;
let
c = 0,
itv;
const prev = () => {c = mod(--c, tot); anim();};
const next = () => {c = mod(++c, tot); anim();};
const anim = () => $slides.css({transform: `translateX(-${c * 100}%)`});
const stop = () => clearInterval(itv);
const play = () => itv = setInterval(next, 4000);
$prevNext.on("click", (ev) => $(ev.currentTarget).is(".next") ? next() : prev());
$parent.hover(stop, play);
play(); // start
});
.SlideShow {
position: relative;
overflow: hidden;
width: 100%;
height: 180px;
}
.SlideShow-slides {
display: flex;
flex-flow: row-nowrap;
height: 100%;
width: 100%;
transition: transform 0.7s; /* Animation duration here */
}
.SlideShow-item {
min-width: 100%;
}
.SlideShow-item>img {
display: block;
width: 100%;
height: 100%;
object-fit: cover;
}
.SlideShow-btn {
position: absolute;
top: 0;
z-index: 1;
width: 50px;
height: 100%;
background: rgba(255, 255, 255, 0.5);
opacity: 0.5;
border: 0;
cursor: pointer;
}
.SlideShow-btn:hover {
opacity: 1;
}
.SlideShow-btn.next {
right: 0px;
}
<div class="SlideShow">
<div class="SlideShow-slides">
<div class="SlideShow-item"><img src="http://placehold.it/600x400/0bf?text=A" alt=""></div>
<div class="SlideShow-item"><img src="http://placehold.it/600x400/fb0?text=B" alt=""></div>
<div class="SlideShow-item"><img src="http://placehold.it/600x400/0fb?text=C" alt=""></div>
</div>
<button type="button" class="SlideShow-btn prev"></button>
<button type="button" class="SlideShow-btn next"></button>
</div>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.5.1/jquery.min.js"></script>
What you need to do it to clear the interval in the button clicks and start interval again.
function resetInterval(){ //add this method which wil reset the timer
window.clearInterval(looper); //clear current interval
looper = setInterval(autoSlide, 5000); //start auto slide again.
}
function autoSlide(){ //move this to a function from being anonymous
// remove and add class active
$('.active').removeClass('active').next().addClass('active');
// animation expression
$('.active').animate({
'left': '-=' + (slideWidth) + 'px'
}, 500);
$('.active').siblings().animate({
'left': '-=' + (slideWidth) + 'px'
}, 500);
// return to first slide after the last one
if ($('.active').length === 0) {
$('#slide1').addClass('active');
$('.slides').animate({
'left': 0
}, 500);
}
}
and
$('.control_left').on('click', function () {
resetInterval(); //reset it
....
$('.control_right').on('click', function () {
resetInterval(); //reset it
....
Demo

Categories

Resources