I'm creating a product hover effect where I used mouseover and mouseleave functions. However, I'm currently having problems with the clearInterval function on Javascript.
Do I miss on something? The structure is also aligned.
Here's my code:
<script>
document.addEventListener("DOMContentLoaded", ()=>{
// //get img url from span
// const src = spanElem.attr('data-original');
// //change span to img using the value from data-original
// spanElem.replaceWith('<img class="product-img-toadd w3-animate-fading" src="' + src + '"/>');
const imgGallery = document.querySelectorAll('.product-img-gallery');
const imageDiv = document.querySelectorAll('.product-tile__image');
let interval
imageDiv.forEach(el=>{
//img
const imgGalleryItem = el.querySelectorAll('.product-img-gallery__item')
el.addEventListener("mouseenter", ()=>{
imgGalleryItem.forEach(item=>{
const src = item.getAttribute('data-original')
const img = `<img class="product-img-toadd w3-animate-fading" src="${src}"/>`
item.insertAdjacentHTML('beforeend',img)
//slider
const imgSlides = el.querySelectorAll('.product-img-toadd');
let currentIndex = 0
interval = setInterval(() => {
imgSlides.forEach((item) => {
item.style.opacity = 0;
});
imgSlides[currentIndex].style.opacity = 1;
if (currentIndex === imgSlides.length - 1) {
currentIndex = 0;
} else {
currentIndex = currentIndex + 1;
}
console.log("tick")
}, 750);
})
})
el.addEventListener("mouseleave", ()=>{
const imgSlides = el.querySelectorAll('.product-img-toadd');
imgSlides.forEach((item) => {
item.style.opacity = 0;
});
clearInterval(interval);
})
})
})
You're assiging interval in a loop, overriding each previous element with the next.
A possible solution would be to push each interval to a array, then iterate through all elements and clear it's elements.
let intervals = [];
intervals.push( setInterval(() => { ... });
...
intervals.forEach((iv) => clearInterval(iv));
Related
let left = document.querySelector('.left');
let right = document.querySelector('.right');
let img = document.querySelector('.imgs');
let imgs = document.querySelectorAll('img');
let index = 0;
function rightimg() {
right.addEventListener('click', function () {
index++;
if (index > imgs.length - 1) {
index = 0;
}
img.style.transform = `translateX(${-index * 500}px)`;
console.log(img);
});
}
// setInterval(rightimg, 2000);
left.addEventListener('click', function () {
index--;
if (index < 0) {
index = imgs.length - 1;
}
img.style.transform = `translateX(${-index * 500}px)`;
console.log(img);
});
Hi friends,
I want to make autoplay image in this slider but setInterval is not working,
can you say what is wrong in here?
Thank you
Your function adds an eventlistener but it will only work when there will be an event(which is click in this case)
You can use swiperjs, it has many types of features and framework/library implentations. https://swiperjs.com/swiper-api
hi everyone!
i have a map with dots MAP which every 3 seconds shows a block with info
a function that is already in progress, and I want the function to stop when clicking on a point and display an infoblock for me(and i did it).
sorry in advance below is my code
// map with dots
var isActive = 0;
var isLoading = 1;
const count = document.querySelectorAll("[data-id]");//circle svg around dot
function removeClass() {
let infoCards = document.querySelectorAll("[data-info-id]");// info page name of the project
infoCards.forEach((el) => {
el.classList.remove("show");
});
}
function removeCircle() {
count.forEach((el) => {
el.style.display = "none";
});
}
function ready() {
function setAround(percent, idx) {
removeCircle();
let beforeElemIdx = idx === 0 ? count.length - 1 : idx - 1;
let beforeElem = document.querySelector(
'[data-id="' + beforeElemIdx + '"]'
);
let elem = document.querySelector('[data-id="' + idx + '"]');
elem.style.display = "block";
elem.classList.remove('active-circle');
beforeElem.style.display = "block";
const math = 2 * Math.PI * elem.r.baseVal.value;
elem.style.strokeDasharray = `${math} 1000`;
let a = math * (1 - percent / 100);
elem.style.strokeDashoffset = a;
if (percent >= 99.5) {
removeClass();
let infoShow = document.querySelector(`[data-info-id="${idx}"]`);
infoShow.classList.add("show");
isLoading++;
if (isLoading === count.length) {
isLoading = 0;
}
}
}
requestAnimationFrame(draw);
function draw(t) {
let idx = isLoading;
requestAnimationFrame(draw);
setAround((t / 30) % 100, idx);//timer 3sec
}
}
document.addEventListener("DOMContentLoaded", ready);
and i did this
var dots = document.querySelectorAll(".dota");
var infoCards = document.querySelectorAll("[data-info-id]");
let circle = document.querySelectorAll('[data-id]');
dots.forEach((el) => {
el.addEventListener('click', () => {
let idx = el.dataset.dota;
let circle = el.dataset.dota;
showInfo(idx);
addCircle(idx);
});
});
function showInfo(idx) {
removeClass();
let elem = document.querySelector(`[data-info-id='${idx}']`);
elem.classList.add('show');
}
function addCircle(idx) {
let circle = document.querySelector(`[data-id='${idx}']`);
circle.classList.add('active-circle');
}
and if u want my site pls dm me i'll send my github page
PUG CODE
TY ALL!
Have you tried making a condition into the drawing function that pauses it?
If it's paused you can call another function that will draw the info of the specific dot only once and then create a condition in which it will resume the drawing normally.
When I used drawing function I've simply added a bool variable that stored if paused or not in the recursive function.
I am just playing around with the setInterval function in JavaScript.
I am wondering if there is a way to toggle the setInterval with an HTML button
This is my code.
let x = 0;
const listener = document.getElementById('listener');
const numberPlace = document.getElementById('numberPlace');
const numberCounter = setInterval(() => {
x++;
numberPlace.innerHTML = x;
}, 100);
listener.addEventListener('click', numberCounter);
The problem is that the number starts counting when the page loads and not on a button click.
Please help
const numberCounter = () => setInterval(() => {
x++;
numberPlace.innerHTML = x;
}, 100);
setInterval can be cancelled using clearInterval and the integer identifier returned when setInterval was called.
To toggle a setInterval-based counter, you simply need to toggle on the presence (or absence) of this identifier.
let counter = 0;
let intervalId = null;
const btn = document.getElementById('btn');
const numberPlace = document.getElementById('numberPlace');
const numberCounter = () => intervalId === null
? intervalId = setInterval(() => numberPlace.innerHTML = ++counter, 100)
: (clearInterval(intervalId), intervalId = null)
btn.addEventListener('click', numberCounter);
<button id="btn">toggle</button>
<div id="numberPlace"></div>
I have this javascript that outputs an action to the elements on class="link_mainhub"
<script>
const el = document.querySelector('.link_mainhub')
const fx = new TextScramble(el)
let counter = 0
const next = () => {
fx.setText(phrases[counter]).then(() => {
setTimeout(next, 800)
})
counter = (counter + 1) % phrases.length
}
next()
</script>
However, I just want to run the script whenever class="link_mainhub" is hovered.
I tried changing the const el = document.querySelector('.link_mainhub') to const el = document.querySelector('.link_mainhub:hover') but it didn't work.
How can I reproduce the script only when my class is being hovered?
Thanks.
Why not add eventListener of Mouseover to the element.
el.addEventListener('mouseOver', next)
I'm trying to add stars (images) to a class with JS.
function putStars(){
if(test){
for(var i = 0; i < 5; i++){
var star = document.createElement("img");
star.src = "star.png";
var element = document.querySelector(".java");
element.append(star);
}
test = false;
}
}
So as you can see I add images to the class Java, but what I want to do is adding images but a waiting effect between each image and not just a block of 5 images.
I found the setTimeOut function but I'm not sut if it's the best way to do this.
You can basically replace your for-loop with setInterval like this to achieve a time delay between each iteration.
let i = 0;
const interval = setInterval(() => {
i++;
var star = document.createElement("img");
star.src = "star.png";
var element = document.querySelector(".java");
element.append(star);
if (i === 5) { clearInterval(interval); } // <- after 5 iterations clear the interval
}, 1000); // <- this 1000 is 1 sec. delay
Although you can move var element = document.querySelector(".java"); outside of the interval so that you don't search for it more than once since it is unnecessary.
let i = 0;
var element = document.querySelector(".java");
const interval = setInterval(() => {
i++;
var star = document.createElement("img");
star.src = "star.png";
element.append(star);
if (i === 5) { clearInterval(interval); } // <- after 5 iterations clear the interval
}, 1000); // <- this 1000 is 1 sec. delay
Use setinterval this way, so your images will most likely already be loaded before you append them to your element.
const listToAppend = [];
const element = document.querySelector(".java");
const start = () => {
let si = setInterval(()=>{
if(listToAppend.length === 0){
clearInterval(si);
return;
}
element.append(listToAppend.shift());
}, 1000);
}
function putStars(){
if(test){
for(var i = 0; i < 5; i++){
var star = document.createElement("img");
star.src = "star.png";
listToAppend.push(star);
}
start();
test = false;
}
}