clearInterval to stop hover animation in jQuery - javascript

I have the below fiddle
When I hover over prev I want it to move as it is doing and when I stop hovering I want it to stop.
See the code below. The alert works when I stop hovering but the clearInterval does not?
What am I doing wrong here?
<div> <span id="prev">prev</span>
<div class="scroll-container">
<div class="img-container">
<img src="http://dummyimage.com/100x100/000000/fff">
<img src="http://dummyimage.com/100x100/f33636/fff">
<img src="http://dummyimage.com/100x100/0c5b9e/fff">
<img src="http://dummyimage.com/100x100/0c9e0c/fff">
</div>
</div>
</div>
var hoverInterval;
function goLeft() {
if (!$('.img-container').is(':animated')) {
var first = $('.img-container img:first-child');
var firstClone = first.clone();
$('.img-container').append(firstClone);
$('.img-container').animate({
"left": "-=110px"
}, "slow", function () {
first.remove();
$('.img-container').css("left", "0");
});
}
}
$('#prev').hover(
function () {
hoverInterval = setInterval(goLeft, 100);
},
function () {
alert(1);
clearInterval(goLeft);
}
);

Change it to
clearInterval(hoverInterval);

Related

Remove one image after another when onclick

i have a div that contains 5 of the same image. i'm trying to make a button that can make one of the images disappear one after another when onclick. i've tried the style.visibility but it makes them all disappear together. This is my code
document.getElementById("btn1").onclick = function() {
document.getElementById("output").style.visibility = "hidden";
}
<input id="btn1" type="button" value="Click me" onclick="onClick1()" style="height: 100px; width: 100px;">
<div style="margin-top: 40px;"></div>
<div id="output">
<img src="/images/person1.jpg">
<img src="/images/person1.jpg">
<img src="/images/person1.jpg">
<img src="/images/person1.jpg">
<img src="/images/person1.jpg">
</div>
You are targeting the image container and then hiding it so all the images disappear at once.
It's not really clear from your question whether you want to click the button once and have the images disappear, or to click the button repeatedly and have one image disappear on each click. This solution answers the first problem.
If you want to hide the images one-by-one you're going to need to use setInterval or setTimeout to manage that. In this example I've used setTimeout.
document.getElementById('btn1').onclick = function() {
// Get all the images
const images = Array.from(document.querySelectorAll('#output img'));
// Loop over the images
function loop(images) {
// If there are images left remove the first one,
// hide it, and then call the function again with the
// reduced image array until all images are gone.
if (images.length) {
const image = images.shift();
image.style.visibility = 'hidden';
setTimeout(loop, 1000, images);
}
}
loop(images);
}
<input id="btn1" type="button" value="Click me" onclick="onClick1()" style="height: 100px; width: 100px;">
<div style="margin-top: 40px;"></div>
<div id="output">
<img src="https://dummyimage.com/30x30/000/fff">
<img src="https://dummyimage.com/30x30/000/fff">
<img src="https://dummyimage.com/30x30/000/fff">
<img src="https://dummyimage.com/30x30/000/fff">
<img src="https://dummyimage.com/30x30/000/fff">
<img src="https://dummyimage.com/30x30/000/fff">
</div>
Additional documentation
shift
setTimeout
Array.from
If you want to make the images disappear on each click, cache the images, and return a function that the listener calls when you click the button.
const button = document.getElementById('btn1')
button.addEventListener('click', handleClick(), false);
// Cache the image elements, and then return a new
// function to your listener that removes an image on each click
function handleClick() {
const images = Array.from(document.querySelectorAll('#output img'));
return function() {
if (images.length) {
const image = images.shift();
image.style.visibility = 'hidden';
}
}
}
<input id="btn1" type="button" value="Click me" style="height: 100px; width: 100px;">
<div style="margin-top: 40px;"></div>
<div id="output">
<img src="https://dummyimage.com/30x30/000/fff">
<img src="https://dummyimage.com/30x30/000/fff">
<img src="https://dummyimage.com/30x30/000/fff">
<img src="https://dummyimage.com/30x30/000/fff">
<img src="https://dummyimage.com/30x30/000/fff">
<img src="https://dummyimage.com/30x30/000/fff">
</div>
You should give id's to image tag instead of parent div.
Created variable which which will work as a counter.
On each click increase counter and hide the specific image tag.
Your code will look like:
let imageToDelete = 1;
document.getElementById("btn1").onclick = function() {
document.getElementById("image_" + imageToDelete).style.visibility = "hidden";
imageToDelete++;
}
<input id="btn1" type="button" value="Click me" onclick="onClick1()" style="height: 100px; width: 100px;">
<div style="margin-top: 40px;"></div>
<div>
<img id="image_1" src="/images/person1.jpg">
<img id="image_2" src="/images/person1.jpg">
<img id="image_3" src="/images/person1.jpg">
<img id="image_4" src="/images/person1.jpg">
<img id="image_5" src="/images/person1.jpg">
</div>
With that script, all you are doing is hiding the parent of all the images, which results in all the images "seemingly disappearing" at once. You have to remove each separately to achieve your desired result.
const RemoveImage = Event => {
const Target = Event.target;
const ImgPos = Target.getAttribute("data-remove");
const Selector = `#image-parent > img:${ImgPos}-of-type`;
const ImgToRemove = document.querySelector(Selector);
if(!ImgToRemove) return false;
ImgToRemove.parentElement.removeChild(ImgToRemove);
return true;
};
const Buttons = document.querySelectorAll("button[data-remove]");
Buttons.forEach(btn => btn.addEventListener("click", RemoveImage));
#image-parent > img:hover {
filter: brightness(92%);
}
#first {outline: 2px solid #a00;}
#last {outline: 2px solid #0a0;}
<div id="image-parent">
<img src="https://via.placeholder.com/70" id="first">
<img src="https://via.placeholder.com/70">
<img src="https://via.placeholder.com/70">
<img src="https://via.placeholder.com/70" id="last">
</div>
<button data-remove="first">Remove first img</button>
<button data-remove="last">Remove last img</button>
If you don't want the images to be removed fully, but rather just hidden:
Rreplce the line ImgToRemove.parentElement.removeChild(ImgToRemove); with something like ImgToRemove.classList.add("hidden-by-css");
Then declare this CSS class with opacity: 0; pointer-events: none;.
We know manipulating HTML DOM is not popular option. But this will work with your problem.
document.getElementById("btn1").onclick = function() {
let imageNode = document.getElementById("output").getElementsByTagName('img')[0];
imageNode.parentNode.removeChild(imageNode)
}
I have found that using the queue() and dequeue() methods from jQuery library is a very good option for resolving this step by step scenarios. This is the stated description of this in the official page:
"Queues allow a sequence of actions to be called on an element asynchronously, without halting program execution. "
I will leave an brief example of how I have implemented it in the past:
$('#anchoredToElement')
.queue("steps", function (next) {
console.log("Step 1");
//In case you want to hold the execution for a bit depending on the scenario you're running
setTimeout(function () { console.log("Action within timeout") }, 500);
next();
})
.queue("steps", function (next) {
console.log("Step 2");
setTimeout(function () {
//Execution example
UploadFile(fileUpload))
}, 500);
next();
})
.dequeue("steps");
Here an example of how I think the logic could be for your needs:
var removeImage = function (index) {
//Logic here to remove image within div according to passed index
};
var index = 0;
$('#output')
.queue("steps", function (next) {
console.log("Remove Image 1");
setTimeout(function () { removeImage(index); }, 250);
index++;
next();
})
.queue("steps", function (next) {
console.log("Remove Image 2");
setTimeout(function () { removeImage(index); }, 250);
index++;
next();
})
.queue("steps", function (next) {
console.log("Remove Image 3");
setTimeout(function () { removeImage(index); }, 250);
index++;
next();
})
.queue("steps", function (next) {
console.log("Remove Image 4");
setTimeout(function () { removeImage(index); }, 250);
index++;
next();
})
.queue("steps", function (next) {
console.log("Remove Image 5");
setTimeout(function () { removeImage(index); }, 250);
index++;
next();
})
.dequeue("steps");
Of course you can improve the JS code as I was just focusing on the step by step process.
This is just a first glance of how $.queue can help you to achieve the step by step process. I recommend to go check the documentation to learn the details and so apply it to your logic as needed.

Displaying an image after clicking 100 times on a button

I'm new here and I still have some difficulties in coding.
I'm trying to create an html page for some friends and I managed to create a click counter, an image which appear and disapear after some time etc
However the only thing that I can't manage to do is how I can make an image appear after clicking on the button for 100 or 1000 times. I can make the image appear after clicking on the button one time, but I don't know how to make it appear only after some clicking.
If someone can help me I'll be very glad!
$button = document.querySelector('button')
$span = document.querySelector('span')
function increment() {
$span.innerHTML++;
}
$button.addEventListener('click', increment);
document.addEventListener("DOMContentLoaded", function() {
setTimeout(function() {
showImage();
setInterval(hideImage, 8000);
}, 5000);
});
function hideImage() {
document.getElementById("imgHideShow").style.display = "none";
}
function showImage() {
document.getElementById("imgHideShow").style.display = "block";
}
<img class="prayme" src="https://upload.wikimedia.org/wikipedia/commons/thumb/2/21/Tram_icon_black_and_transparent_background.svg/1024px-Tram_icon_black_and_transparent_background.svg.png">
<p>You prayed <span id='count'>0</span> times</p>
<div id="image">
<img src="https://pbs.twimg.com/profile_images/998926585691451392/WlkEVV7x_400x400.jpg">
</div>
<div class="text-center">
<button><img class="imgbutton" src="https://www.nicepng.com/png/detail/980-9803933_emoji-emoji-pray-thankyou-thanks-praying-hands-emoji.png">
Afficher l'image
</button>
</div>
<div>
<img src="https://i.stack.imgur.com/1dpmw.gif" class="browse-tip" id="imgHideShow">
</div>
You just need to add an if statement, checking if the innerHTML is more or equal to 100, and then call showImage().
I removed code that wasn't relevant.
I added declarations to the variables by adding let in front the name.
I removed the button, and put an event listener directly on the image instead.
I think the rest of the code is self-explanatory.
let spanElement = document.querySelector('span');
let imgButton = document.getElementById('imgbutton');
function increment() {
spanElement.innerHTML++;
if (spanElement.innerHTML >= 5) {
showImage();
}
}
imgButton.addEventListener('click', increment);
document.addEventListener("DOMContentLoaded", function() {
setInterval(hideImage, 8000);
});
function hideImage() {
document.getElementById("imgHideShow").style.display = "none";
}
function showImage() {
document.getElementById("imgHideShow").style.display = "block";
}
img {
height: 3rem;
}
#imgHideShow.hidden {
display: none;
}
<img class="prayme" src="https://upload.wikimedia.org/wikipedia/commons/thumb/2/21/Tram_icon_black_and_transparent_background.svg/1024px-Tram_icon_black_and_transparent_background.svg.png">
<p>You prayed <span id='count'>0</span> times</p>
<div class="text-center">
<img id="imgbutton" src="https://www.nicepng.com/png/detail/980-9803933_emoji-emoji-pray-thankyou-thanks-praying-hands-emoji.png">
Afficher l'image
</div>
<div>
<img src="https://i.stack.imgur.com/1dpmw.gif" class="hidden browse-tip" id="imgHideShow">
</div>
To make the code even more readable, I would also add the following it it like this:
Add a constant for how many times the user need to click.
Declare variables for all the elements that are affected.
Use a class (.hidden) to hide the image, and add/remove that class, instead of adding a style. You should only add a style if you can't toggle classes.
const TARGET_TO_SHOW_IMAGE = 5;
let spanElement = document.querySelector('span');
let imgButton = document.getElementById('imgbutton');
let imgHideShow = document.getElementById("imgHideShow");
let numberOfTimesClicked = 0;
function increment() {
numberOfTimesClicked++;
if (numberOfTimesClicked >= TARGET_TO_SHOW_IMAGE) {
showImage();
numberOfTimesClicked = 0; // resets
}
spanElement.innerHTML = numberOfTimesClicked;
}
imgButton.addEventListener('click', increment);
document.addEventListener("DOMContentLoaded", function() {
setInterval(hideImage, 8000);
});
function hideImage() {
imgHideShow.classList.add('hidden');
}
function showImage() {
imgHideShow.classList.remove('hidden');
}
img {
height: 3rem;
}
#imgHideShow.hidden {
display: none;
}
<img class="prayme" src="https://upload.wikimedia.org/wikipedia/commons/thumb/2/21/Tram_icon_black_and_transparent_background.svg/1024px-Tram_icon_black_and_transparent_background.svg.png">
<p>You prayed <span id='count'>0</span> times</p>
<div class="text-center">
<img id="imgbutton" src="https://www.nicepng.com/png/detail/980-9803933_emoji-emoji-pray-thankyou-thanks-praying-hands-emoji.png">
Afficher l'image
</div>
<div>
<img src="https://i.stack.imgur.com/1dpmw.gif" class="hidden browse-tip" id="imgHideShow">
</div>

Loop a click event function on "animationend"

I have a question on how to loop a click event itself on animation end
I have 3 pictures i want to rotate on click with an order :
first click on first picture-> first picture rotates,
second click on second picture-> second picture rotates,
third click on third picture-> third picture rotates
the add event listener is the same so i'm trying to loop the function on itself with myEndFunction() but it seems to not be alright
On second click the second picture is moving but i still have to click on first picture
here is the html (very classic one):
<body>
<img id ="first" src= "https://i.ibb.co/bPWLLjV/bookermini.png" alt="booker">
<img id ="second" src= "https://i.ibb.co/KKKqrBp/bobafettmini.png" alt="boba">
<img id ="third" src= "https://i.ibb.co/2yXfmvJ/hommemini.png" alt="joxer">
</body>
here is the css (moving part):
.move {
position : relative;
animation: mymove 1s ;
}
#keyframes mymove {
100%{transform: rotate(360deg); }
}
here is the js code :
var x = document.getElementById("first");
x.addEventListener('click', event => {
x.classList.add("move");
x.addEventListener("webkitAnimationEnd", myEndFunction);
x.addEventListener("animationend", myEndFunction);
function myEndFunction() {
x = document.getElementById("second");
}
});
here is a codepen if you want to try : https://codepen.io/minise/pen/vYGpqJZ
plz i need your help !
It seem that you are using an #id selector which returns always the first occurrence, and stops.
My suggestion would be, to use class identifiers instead and reuse your action function.
var version1 = function () {
// get all containers that has the class rotate-me
var rotateMe = document.querySelectorAll('.version-1 .rotate-me');
// define animation duration, this is better than css animationend
var animationDuration = 1000; // milliseconds
// recursive animation sequence
var startSequence = function (classname, items) {
var [first, ...rest] = items;
first.classList.add('rotate');
setTimeout(function () {
if (rest.length > 0) {
startSequence(classname, rest)
}
}, animationDuration);
};
// click handle that starts the sequence
var handleClick = function () {
startSequence('rotate', rotateMe);
};
// check if one rotateMe was matched
if (rotateMe.length > 0) {
// add you action callback to the first match
rotateMe[0].addEventListener('click', handleClick);
}
}
// this version is blocking click before previeous element was clicked
var version2 = function () {
// get all containers that has the class rotate-me
var rotateMe = document.querySelectorAll('.version-2 .rotate-me');
// define animation duration, this is better than css animationend
var animationDuration = 1000; // milliseconds
// active index
var activeElement = 0;
// click handle that starts the sequence
var handleClick = function (index, item) {
if (index === activeElement) {
item.classList.add('rotate');
activeElement += 1;
}
};
for (var i = 0, l = rotateMe.length; i < l; i += 1) {
// add you action callback to the first match
rotateMe[i].addEventListener('click', (function (index, item) {
return function () {
handleClick(index, item);
};
})(i, rotateMe[i]));
}
}
window.onload = function() {
version1();
version2();
}
.wrapper {
display: flex;
}
.rotate-me {
border-radius: 50%;
overflow: hidden;
font-size: 0;
}
.rotate-me:first-child {
cursor: pointer;
}
.rotate-me.rotate {
cursor: initial;
}
.rotate-me.rotate {
transition: transform 1s;
transform: rotate(360deg);
}
<h2>Version 1</h2>
<div class="wrapper version-1">
<div class="rotate-me">
<img src="http://placekitten.com/150/150" alt="kitten placeholder">
</div>
<div class="rotate-me">
<img src="http://placekitten.com/150/150" alt="kitten placeholder">
</div>
<div class="rotate-me">
<img src="http://placekitten.com/150/150" alt="kitten placeholder">
</div>
<div class="rotate-me">
<img src="http://placekitten.com/150/150" alt="kitten placeholder">
</div>
</div>
<h2>Version 2</h2>
<div class="wrapper version-2">
<div class="rotate-me">
<img src="http://placekitten.com/150/150" alt="kitten placeholder">
</div>
<div class="rotate-me">
<img src="http://placekitten.com/150/150" alt="kitten placeholder">
</div>
<div class="rotate-me">
<img src="http://placekitten.com/150/150" alt="kitten placeholder">
</div>
<div class="rotate-me">
<img src="http://placekitten.com/150/150" alt="kitten placeholder">
</div>
</div>
var x = document.getElementById("first");x.addEventListener('click', event => {
x.classList.add("move");
x.addEventListener("webkitAnimationEnd",myEndFunction);
x.addEventListener("animationend",myEndFunction);});
var y = document.getElementById("second");y.addEventListener('click', event => {
y.classList.add("move");
y.addEventListener("webkitAnimationEnd",myEndFunction);
y.addEventListener("animationend",myEndFunction);});
Is this some thing what u are asking for?/
Well might has well put the event listener to the picture itself.
So you know what to rotate.
Yeah even a div can have an event listener.
Query for the div. add an event listener that onclick the animationPlayState should be running. Else by default put it has paused in css.

How do I stop clicking next too many times from breaking my image rotator?

Im new to jquery and have been trying to code a simple image rotator, it works well at the moment except for the fact that if you click the "next" of "prev" buttons too many times very quickly it will break the image rotator.
Here is the html:
<div id="viewport">
<div id="imageContainer">
<div class="image" style="background-color:red;">
<div class="title"><p>This is the title of the post</p></div>
</div>
<div class="image" style="background-color:green;">
<div class="title"><p>This is the title of the post</p></div>
</div>
<div class="image" style="background-color:yellow;">
<div class="title"><p>This is the title of the post</p></div>
</div>
<div class="image" style="background-color:brown;">
<div class="title"><p>This is the title of the post</p></div>
</div>
<div class="image" style="background-color:purple;">
<div class="title"><p>This is the title of the post</p></div>
</div>
</div>
</div>
<input type="button" name="prev" id="prev" value="prev" />
<input type="button" name="next" id="next" value="next" />
and jquery:
var ic = $('#imageContainer');
var numItems = $('.image').size();
var position = 0;
ic.css('left', '0px');
var inter;
var rotateTimeout;
function rotate(){
inter = setInterval(function(){
if (position == (numItems - 1)) {
console.log(position);
$('.image').first().insertAfter($('.image').last());
ic.css('left', '+=400px');
position--;
}
ic.animate({opacity: 0.2, left: "-=400px"}, 1500, function(){
ic.animate({opacity: 1.0}, 1000);
});
position += 1;
}, 6000);
}
rotate();
$('#prev').click(function () {
console.log(position);
if (position == 0) {
$('.image').last().insertBefore($('.image').first());
ic.css('left', '-=400px');
position++;
}
ic.animate({
left: "+=400px"
});
position -= 1;
clearInterval(inter);
clearTimeout(rotateTimeout);
rotateTimeout = setTimeout(rotate, 10000);
});
$('#next').click(function () {
if (position == (numItems - 1)) {
console.log(position);
$('.image').first().insertAfter($('.image').last());
ic.css('left', '-400px');
position--;
}
ic.animate({
left: "-=400px"
});
position += 1;
clearInterval(inter);
clearTimeout(rotateTimeout);
rotateTimeout = setTimeout(rotate, 10000);
});
Here is a demo of the rotator.
So how can I either stop the user from clicking the button too quickly, or perhaps only account for a click per two seconds to allow the rotator to do what it needs?
To limit function call frequency you can use some "Throttle" function. For example _.throttle from Underscore.js or any other implementation. It is not necessary to use whole library, only required function could be copied from there.
The event handler attachment will look like this:
$('#prev').click( _.throttle(function () { yours code... }, 2000) );

jquery image gallery slide animation

I am trying to make a simple image gallery like this. http://dimsemenov.com/plugins/royal-slider/#image-gallery When I click a thumbnail image, image element will create and loading image will appear a little time and created element will slide in the visible area.At last old image elment will remove.
<div id="imageGallery" style="overflow:visible;display:block;">
<div class="preview">
<div id="content" style="width:640px;height:420px;">
<img id="main-Image" alt="" src="../../baContent/image1.jpg" style="display:inline; top:0;left:0;" />
</div>
</div>
<div id="thumbnails">
<a class="thumbnail" href="../../baContent/image1.jpg"><img alt="Image 1" src="../../baContent/image1-thumb.jpg"></a>
<a class="thumbnail" href="../../baContent/image2.jpg"><img alt="Image 2" src="../../baContent/image2-thumb.jpg"></a>
</div>
$(document).ready(function () {
$(".thumbnail").click(function () {
$("#mainImage").animate({ "left": "-640px" }, "fast");
$('#preview').css('background-image', "url('../../baContent/spinner.gif')");
var img = $("<img style='left:640px;display:none;' />").attr('src', this.href).load(function () {
$('#mainImage').attr('src', img.attr('src'));
$('#preview').css('background-image', 'none');
$(this).parent().prevAll().remove();
$("#mainImage").animate({ "left": "-640px" }, "fast");
});
});
});
I wrote a few code but had no success. Any ideas or tutorials?
Try :
$(document).ready(function () {
$(".thumbnail").click(function () {
$('#main-Image').hide();
$('#preview').css('background-image', "url('../../baContent/spinner.gif')");
var imgSrc = $(this).attr('href');
var img = $("<img style='left:640px;display:none;' />").attr('src', imgSrc).load(function () {
$('#main-Image').attr('src', imgSrc);
$('#preview').css('background-image', 'none');
$('#main-Image').fadeIn();
});
return false;
});
});​
You can add all animations you want.
For a good slider, see http://bxslider.com/.

Categories