display a div at different interval using javascript - javascript

I have 2 different div, i want the div1 to fade in after 20s and fade-out after 10s and after 30s i want div2 to fade in and after 10s div2 should also fade out. this should keep happening on load of page
bubbleMessage1 = document.getElementById("bubbleMessage1");
bubbleMessage2 = document.getElementById("bubbleMessage2");
bubbleMessage1.style.display = "none";
bubbleMessage2.style.display = "none";
$(function () {
// Different timeouts for each divs
setTimeout(function(){
var times = [20000, 50000];
var counter = 0;
divs = $('#bubbleMessage1, #bubbleMessage2');
function showDiv() {
// hide all divs, filter current index, and fadeIn
divs.hide().eq(counter).fadeIn(500, "linear");
// set time out duration from array of times
setTimeout(showDiv, times[counter]);
// cycle the counter
counter = (counter + 1) % divs.length;
};
showDiv();
}, 20000)
// show first div
});
.chat-bubble-1{
width: 230px;
height: 65px;
background-color: #486622;
text-align: center;
padding: 0.5rem;
line-height: 66px;
color: #fff;
border-radius: 22px;
position: relative;
}
.chat-bubble-1::after{
content: '';
position: absolute;
height: 32px;
width: 32px;
border-bottom: 2px solid #486622;
border-right: 2px solid #486622;
border-left: 0px solid #486622;
border-top: 0px solid #486622;
top : 100%;
left: 74%;
transform: rotate(45deg);
margin-top: -22px;
background: #486622;
}
#keyframes fadeOut {
0% {
opacity: 1;
}
100% {
opacity: 0;
}
}
#-webkit-keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
.fade-in{
animation: fadeIn ease-in 1;
}
.fade-out{
animation: fadeOut ease-in 1;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="chat-container">
<div class="chat-bubble-1" id="bubbleMessage1">
Hi i'm bot How can i help you?
</div>
<div class="chat-bubble-1" id="bubbleMessage2">
I'm still here How can i help you?
</div>
</div>
I tried to use setTimeout loop to achieve this but i was getting error.then i found this jquery method.the problem is the div will not fade-out after 10s. div1 fades and div2 comes immediately. Can anyone please give a solution really appreciate it.thanks

The setTimeout() method of the WindowOrWorkerGlobalScope mixin (and
successor to Window.setTimeout()) sets a timer which executes a
function or specified piece of code once the timer expires.
setTimeout gets extra args you can use in your code.
Change for instance from:
setTimeout(showDiv);
to:
setTimeout(showDiv, times[counter], times, (i+1)%2);
instead of using local vars.
Working demo:
bubbleMessage1 = document.getElementById("bubbleMessage1");
bubbleMessage2 = document.getElementById("bubbleMessage2");
bubbleMessage1.style.display = "none";
bubbleMessage2.style.display = "none";
// Different timeouts for each divs
setTimeout(function(t, i){
var times = t;
var counter = i;
divs = $('#bubbleMessage1, #bubbleMessage2');
function showDiv(t, i) {
var times = t;
var counter = i;
// hide all divs, filter current index, and fadeIn
divs.hide().eq(counter).fadeIn(500, "linear");
// set time out duration from array of times
setTimeout(showDiv, times[counter], times, (i+1)%2);
// ^^^^^^^^^^^^^^^^^^
// params added...
// cycle the counter
counter = (counter + 1) % divs.length;
};
showDiv(times, counter);
}, 2000, [2000, 5000], 0);
// ^^^^^^^^^^^^^^^^^^
// params added...
.chat-bubble-1{
width: 230px;
height: 65px;
background-color: #486622;
text-align: center;
padding: 0.5rem;
line-height: 66px;
color: #fff;
border-radius: 22px;
position: relative;
}
.chat-bubble-1::after{
content: '';
position: absolute;
height: 32px;
width: 32px;
border-bottom: 2px solid #486622;
border-right: 2px solid #486622;
border-left: 0px solid #486622;
border-top: 0px solid #486622;
top : 100%;
left: 74%;
transform: rotate(45deg);
margin-top: -22px;
background: #486622;
}
#keyframes fadeOut {
0% {
opacity: 1;
}
100% {
opacity: 0;
}
}
#-webkit-keyframes fadeIn {
from {
opacity: 0;
}
to {
opacity: 1;
}
}
.fade-in{
animation: fadeIn ease-in 1;
}
.fade-out{
animation: fadeOut ease-in 1;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div class="chat-container">
<div class="chat-bubble-1" id="bubbleMessage1">
Hi i'm bot How can i help you?
</div>
<div class="chat-bubble-1" id="bubbleMessage2">
I'm still here How can i help you?
</div>
</div>

Related

How can i disappear my popup when my condition satisfies?

I have made a popup whenever the image was not loaded but the problem scenario was, I am getting my popup even the image is loaded for the first time. So, I need to refresh it for disappearing it. How can I resolve it?
enter image description here
The problem is that I have included the condition to check the image is loaded or not after the code of popup .so for the first time the popup was appearing even it satisfies the condition.
Help me out of it.
You should edit your question so as to include your code, so your problem is reproducible.
You can store your image as a variable and pass a function that hides your pop-up once the image is loaded.
var img1 = document.createElement("img");
img1.onload = function() {
document.getElementById("**popup_ID").style.display='none';
};
img1.src = "**your_image_path**"; //Edit suggested by #vanowm
Change "your_image_path" and "popup_ID" to match your code.
Image has complete property that would tell if it finished loading or not. You can use that to show/hide popup on startup.
However to detect if image was successfully loaded or error occur, you'd need setup event listeners.
Here is a little example that does that:
let timer;
const elLoadGood = document.getElementById("loadGood"),
elLoadBad = document.getElementById("loadBad"),
elPopup = document.getElementById("popup"),
elImg = document.getElementById("myimage"),
imgSrc = "https://cdn.spacetelescope.org/archives/images/publicationjpg/heic1502a.jpg?";
//set event handlers
elImg.onload = imageOnLoad;
elImg.onerror = imageOnError;
//load image
imageLoad(imgSrc);
elLoadGood.addEventListener("click", e=>
{
//hide image
elImg.removeAttribute("src");
//load image
imageLoad(imgSrc + Date());
});
elLoadBad.addEventListener("click", e=>
{
//hide image
elImg.removeAttribute("src");
//load image
imageLoad(Date());
});
function imageLoad(src)
{
elPopup.classList.add("loading");
elImg.classList.remove("error");
elPopup.firstChild.textContent = "loading... please wait";
//show popup
imageFinished({});
//load image
elImg.src = src;
}
function imageFinished(img)
{
//check if image finished loading
if (img.complete)
{
elPopup.firstChild.textContent = "Finished loading. Close popup in 2 seconds";
elPopup.classList.remove("loading");
}
clearTimeout(timer);
//hide popup
timer = setTimeout(() => elPopup.classList.toggle("hidden", !!img.complete), ~~img.complete * 2000);
}
function imageOnLoad(e)
{
e.target.classList.remove("error");
imageFinished(e.target);
}
function imageOnError(e)
{
e.target.classList.add("error");
imageFinished(e.target);
}
div.img
{
position: absolute;
left: 0;
top: 0;
line-height: 100vh;
text-align: center;
width: 100%;
z-index: -2;
}
img
{
vertical-align: middle;
max-height: 100%;
max-width: 100%;
}
img.error
{
animation: error infinite 1s ease-in-out alternate;
padding: 1em;
border-radius: 100%;
}
#popup
{
position: fixed;
top: 0;
bottom: 0;
left: 0;
right: 0;
line-height: 100vh;
text-align: center;
z-index: -1;
background-color: transparent;
opacity: 1;
transition: background-color 1s, opacity .5s;
}
#popup>span
{
background-color: #ffffff7f;
color: black;
border: 1px solid;
padding: 1em;
}
#popup.loading
{
background-color: #0000007f;
}
#popup:not(.hidden) ~ *
{
filter: blur(5px);
}
#popup.loading ~ *
{
filter: blur(10px);
}
#popup.loading>span::before
{
content: "🗘";
width: 1em;
height: 1em;
line-height: 1em;
vertical-align: middle;
text-align: center;
animation: rotate infinite 1s linear;
display: inline-block;
}
#popup.hidden
{
opacity: 0;
}
#keyframes rotate {
from {transform: rotate(0deg);}
to {transform: rotate(360deg);}
}
#keyframes error {
to {box-shadow: 0 0 30px 0 red}
from {box-shadow: 0 0 1px 0 red}
}
<button id="loadGood">load good image</button>
<button id="loadBad">load bad image</button>
<div id="popup" class="hidden"><span></span></div>
<div class="img"><img id="myimage"></div>

How can I repeatedly toggle a CSS animation class without a second click?

I want the colour and size of a div box to animate and return to its original values when a button is clicked. Here is my code example:
document.getElementById("andAction").addEventListener("click", function() {
document.getElementById("box").classList.toggle("animi");
})
.thing {
transform: translate(150px, 100px);
}
.box {
background-color: #999;
padding: 2px;
color: black;
width:20px;
margin: 0 auto;
text-align: center;
color: #fff;
}
#keyframes blob {
0% {
background-color: #999;
}
50% {
background-color: #F9086D;
transform: scale(2);
background-color: red;
border-radius: 20px;
}
100% {
background-color: #999;
}
}
.animi {
animation-name: blob;
animation-duration:3s;
animation-iteration-count:1;
}
<button id="andAction" class="button">button</button>
<div id="box" class="box">1</div>
Problem
My problem is that I am doing it with toggle. Which means I have to click twice on the second time. Another variety was classList.add and then remove again. This leads to no result because the animation is not started for the user. the only thing I could do would be to work with timeout.
Question
I have the feeling there is another way?
You can listen to the onanimationend event to remove the class when the animation ended without relying on timers that are harder to maintain:
const boxElement = document.getElementById("box")
boxElement.addEventListener('animationend', (e) => {
// if the target it the box (it's triggered by animations on children too)
// and the animation name is `blob` (it's triggered by any animation)
// remove the class
if (e.target === boxElement && e.animationName === "blob") {
boxElement.classList.remove('animi');
}
})
document.getElementById("andAction").addEventListener("click", function() {
boxElement.classList.add("animi");
})
Just add some js to remove the class automatically after the animation finished and change your initial behaviour to not toggle but just add the class. You can achieve that by using https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/animationend_event.
const box=document.getElementById("box");
document.getElementById("andAction").addEventListener("click", function() {
box.classList.add("animi");
});
box.addEventListener('animationend', () => {
box.classList.remove("animi");
});
.thing {
transform: translate(150px, 100px);
}
.box {
background-color: #999;
padding: 2px;
color: black;
width: 20px;
margin: 0 auto;
text-align: center;
color: #fff;
}
#keyframes blob {
0% {
background-color: #999;
}
50% {
background-color: #F9086D;
transform: scale(2);
background-color: red;
border-radius: 20px;
}
100% {
background-color: #999;
}
}
.animi {
animation-name: blob;
animation-duration: 3s;
animation-iteration-count: 1;
}
<button id="andAction" class="button">button</button>
<div id="box" class="box">1</div>

Carousel prev and next button logic does not work

I am trying to a make carousel using pure Javascript. I successfully manage to slide the carousel and have created left and right buttons.
I took my slide functions and added them to the button on-click event-listener, but I have problems when I implement the function on my buttons. It does not behave as expected. My code is below, how can I fix this?
const images = document.getElementById('imgs'); //here
const allImages = document.querySelectorAll('#imgs img');
const leftBtn = document.getElementById('left');
const rightBtn = document.getElementById('right');
let index = 0;
function changeSliderPage() {
const dot = [...document.getElementsByClassName('star')];
index++;
if (index > allImages.length - 1) {
index = 0
}
imgs.style.transform = `translateX(${-index * 500}px)`;
dot.forEach((dot, i) => {
if (i === index) {
dot.classList.add('active')
} else {
dot.classList.remove('active')
}
});
};
allImages.forEach(i => {
const elem = document.createElement('div');
elem.classList.add('star');
document.body.appendChild(elem)
});
rightBtn.onclick = () => {
changeSliderPage(index + 1);
}
leftBtn.onclick = () => {
changeSliderPage(index - 1);
}
let x = setInterval(changeSliderPage, 100000);
images.onmouseover = () => {
clearInterval(x)
}
images.onmouseout = () => {
x = setInterval(changeSliderPage, 2000);
}
*{
box-sizing: border-box;
}
body {
margin: 0;
display: flex;
justify-content: center;
align-items: center;
min-height: 100vh;
}
.carousel {
overflow: hidden;
width: 500px;
height: 500px;
box-shadow: 2px 2px 5px rgba(0, 0, 0, .3);
border-radius: 5px;
}
.image-container {
display: flex;
transition: transform 300ms linear;
transform: translateX(0);
}
img {
width:500px;
height: 500px;
object-fit: cover;
}
.star{
cursor: pointer;
height: 15px;
width: 15px;
margin: 0 10px;
border-radius: 50%;
display: inline-block;
transition: background-color 0.6s ease;
background-color: #eeeeee;
}
.star.active{
background-color: red;
}
button{
cursor: pointer;
position: relative;
font-size: 18px;
transition: 0.6s ease;
user-select: none;
height: 50px;
width: 40px;
display: flex;
justify-content: center;
align-items: center;
align-content: center;
top: calc(50% - 25px);
}
button:hover {
background-color: rgba(0,0,0,0.8);
};
button.left {
border-radius: 3px 0 0 3px;
right: 0;
}
button.left {
border-radius: 3px 0 0 3px;
left: 0;
}
<button id="left">❮</button>
<button id="right">❯</button>
<div class="carousel">
<div class="image-container" id="imgs" >
<img src="https://images.unsplash.com/photo-1599736375341-51b0a848f3c7?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=800&q=60" alt="">
<img src="https://images.unsplash.com/photo-1516026672322-bc52d61a55d5?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=800&q=60" alt="">
<img src="https://images.unsplash.com/photo-1573081586928-127ecc7948b0?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=800&q=60" alt="">
<img src="https://images.unsplash.com/flagged/photo-1572850005109-f4ac7529bf9f?ixlib=rb-1.2.1&ixid=eyJhcHBfaWQiOjEyMDd9&auto=format&fit=crop&w=800&q=60" alt="">
</div>
</div>
Logic that I use with carousels:
for example you have 4 images:
[1][2][3][4]
I have an animation for sliding every image, I add 5th image which is same as image no 1:
[1][2][3][4][1]
Imagine cursor which shows what image is currently displayed, Ill mark cursor as ! !
So at begin:
[!1!][2][3][4][1]
Now the slider moves on...
[1][!2!][3][4][1]
etc...
It moves to last image:
[1][2][3][4][!1!]
And now it has to move under the hood from last image to first image, but without any animation so the whole change is not visible by user:
[!1!][2][3][4][5]
This way you can get inifinite carousel, just need to check in javascript if current image is last one and you want to slide right -> no animation. Same if you are on 1st image and want to slide left.

CSS Transition Triggered by JavaScript

I want to have the following JavaScript function to transition function between from have none display to block when generate_loading_screen() is called to to when it finishes transition between display block to none. How do I do this?
function generate_loading_screen() {
window.setInterval(function(){
if (progress_percent < 75) {
document.getElementById("loading_screen").style.display = "block";
document.getElementById("body_of").style.filter = "grayscale(1)";
}
else {
document.getElementById("loading_screen").style.display = "none";
document.getElementById("body_of").style.filter = "none";
stop_generating_loading();
}
}, 50);
};
function stop_generating_loading() {
clearInterval(generate_loading_screen);
};
.loading {
position: fixed;
border: 16px solid #dbdbdb;
border-radius: 50%;
border-top: 16px solid #53f442;
margin-left: 44%;
margin-top: 10%;
width: 120px;
height: 120px;
animation: spin 2s linear infinite;
}
#keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
<div class="loading" id="loading_screen" style="display: none;"></div>
Just extra info: progress_percent is a variable that determines how much of the rest of the web-app has loaded. The grayscale filter does not affect the whole page, just the ID body_of
Thanks in advance
Probably better to use a opacity transition by adding a class when your percent reaches 100.
Codepen for working example or see below.
HTML:
<div class="loading" id="loading_screen"></div>
CSS:
.loading {
position: fixed;
border: 16px solid #dbdbdb;
border-radius: 50%;
border-top: 16px solid #53f442;
margin-left: 44%;
margin-top: 10%;
width: 120px;
height: 120px;
animation: spin 2s linear infinite;
opacity: 100%;
transition: opacity 1s ease-in-out;
}
.done_loading {
opacity: 0;
}
#keyframes spin {
0% { transform: rotate(0deg); }
100% { transform: rotate(360deg); }
}
Javascript:
var progress_percent = 25;
var interval;
function generate_loading_screen() {
interval = window.setInterval(function(){
progress_percent += 1; //totest
if (progress_percent > 75) {
document.getElementById("loading_screen").className = "loading done_loading";
//stop_generating_loading();
}
//TESTING
if(progress_percent > 100){
console.log("Reached 100%");
document.getElementById("loading_screen").className = 'loading';
progress_percent = 0;
}
//
}, 50);
};
function stop_generating_loading() {
clearInterval(interval);
};
document.addEventListener('DOMContentLoaded', function(){
generate_loading_screen();
});
Remove all the testing code to get this to work once, you might need to add additional code for your body div. Let me know if you need me to add more to this example!
window.setInterval returns an intervalId which you need to cancel in order to stop the interval
let timer;
function generate_loading_screen() {
timer = window.setInterval(function(){
if (progress_percent < 75) {
document.getElementById("loading_screen").style.display = "block";
document.getElementById("body_of").style.filter = "grayscale(1)";
}
else {
document.getElementById("loading_screen").style.display = "none";
document.getElementById("body_of").style.filter = "none";
stop_generating_loading();
}
}, 50);
};
function stop_generating_loading() {
clearInterval(timer);
};

Bug when trying to recreate a ripple effect animation in a button (Material design)

I'm trying to emulate a ripple effect when clicking in a button, but I got weird behaviour when happy clicking. I'm coding in vanilla JS for learning purposes. Please could anybody tell me where I've got it wrong?
Here's the full code:
Html
<button class="button button--ok ripple">Button</button>
<button class="button button--cancel ripple">Button</button>
Css
body {
width: 800px;
margin: 0 auto;
padding: 30px 0 0 0;
font: "Helvetica neue", Helvetica, sans-serif;
}
.button {
position: relative;
padding: 10px 20px;
color: #fff;
border: none;
outline: none;
cursor: pointer;
box-shadow: 0 0 4px rgba(0,0,0,.4);
overflow: hidden;
font-size: 16px;
letter-spacing: 1px;
}
.button--ok {
background-color: #65DE65;
}
.button--cancel {
background-color: tomato;
}
.circle {
width: 10px;
height: 10px;
position: absolute;
transform: translate(-50%, -50%);
border-radius: 5px;
background-color: #fff;
}
.ripple.animate .circle {
animation: ripple 2s;
}
#keyframes ripple {
from {
transform: scale(1);
opacity: .4;
}
to {
transform: scale(100);
opacity: 0;
}
}
Js
var ripple = document.getElementsByClassName("ripple");
for (var i = 0; i < ripple.length; i++) {
ripple[i].addEventListener("click", function(e) {
// Store this for later
var self = this;
// Get x and y coordinates
var x = e.offsetY+"px";
var y = e.offsetX+"px";
// Create the layer effect and apply a circle class,
// then set coordinates
var circle = document.createElement("div");
circle.setAttribute("class", "circle");
circle.style.top = x;
circle.style.left = y;
// Append layer effect to parent and add animate class
// to start the animation
self.appendChild(circle);
self.className += " animate";
// Remove layer effect once is done animating (2 seconds)
setTimeout(function() {
var elements = self.getElementsByClassName("circle");
for (var i = 0; i < elements.length; i++) {
self.removeChild(elements[i]);
}
}, 2000);
}, false);
}
Mine: Codepen
Disired: Codepen
Hi I see what you are trying to do and I too tried to explain the bizzare effect. Anyway I tried to do something and it worked, made the .circle .animate to simply .animate and changed the scale(1) to scale(1,1), scale(width,height) setting.
Inside style the changes are:
.animate {
animation: ripple 2s forwards;
-webkit-animation-name:ripple;
-webkit-animation-duration: 2s;
}
#keyframes ripple {
from {
transform: scale(1,1);
opacity: 0.4;
}
to {
transform: scale(100,100);
opacity: 0;
}
}
Here is the jsfiddle. For chrome and safari support added the -webkit- property.

Categories