setInterval is not adding .addClass - javascript

I have a CSS marquee that displays values from a DB. After x minutes it refreshes and new data is pulled. The colors change based on their numerical value (if x < 50000 make it red ...etc).
My issue is once my setInterval runs the data is updated but the color classes don't get added. Any idea why? I saw this post and changed my remove/add class to a toggle but it was the same issue, the toggle wasn't being called after the initial run.
Javascript
$(document).ready(function () {
setColors();
setInterval(function () {
$('.marquee').addClass("paused");
$('.marquee').load('/Home/GetMarquee');
setColors();
$('.marquee').removeClass("paused");
}, 30000);
});
function setColors() {
$('.totalSales').each(function () {
var final = $(this).text();
//removes all the pervious classes
$(this).removeClass('ok');
$(this).removeClass('down');
$(this).removeClass('up');
if (final > 100000) {
$(this).addClass('up');
} else if (final < 50000) {
$(this).addClass('down');
} else {
$(this).addClass('ok');
}
});
}
Razor HTML
<div class="marquee">
<span>
#for (var i = 0; i < Model.tickerData.Count(); i++)
{
<span class="totalSales">
#Html.DisplayFor(x => x.tickerData[i].GroupName): #Html.DisplayFor(x => x.tickerData[i].Sales).....
</span>
}
</span>
</div>
CSS Colors
.down {
color:#AB2218;
}
.up {
color: #4F692A;
}
.ok {
color:#FABF03;
}
CSS Marquee
.marquee {
width: 800px;
margin: 0 auto;
overflow: hidden;
white-space: nowrap;
box-sizing: border-box;
background-color:black;
border: 1px black solid;
font-size:50px;
-webkit-animation: marquee 30s linear infinite alternate;
animation: marquee 30s linear infinite;
}
.paused {
animation-play-state: paused;
}
.marquee span {
display: inline-block;
text-indent: 0;
}
/* Make it move */
#keyframes marquee {
0% { text-indent: 17.5em }
100% { text-indent: -57.5em }
}
#-webkit-keyframes marquee{
0% { text-indent: 17.5em }
100% { text-indent: -57.5em }
}

.load is an async ajax function, so it doesn't block until it finishes, and the class adding and removing happens too quickly to notice. Try using the .load callback:
setInterval(function () {
$('.marquee').addClass("paused");
$('.marquee').load('/Home/GetMarquee', function() {
setColors();
$('.marquee').removeClass("paused");
});
}, 30000);

Related

Vue.js: Play CSS animation on JavaScript event

In my Vue.js app, I have a login form, which I want to shake whenever login attempt fails.
I achieved the desired effect, but I'm not happy with my solution. Here's my simplified code:
const Home = {
data() {
return {
shakeForm: false
}
},
template: `
<div>
<form :class="{'form-shaking': shakeForm}"
#submit.prevent="login"
#animationend="shakeForm = false;"
>
form fields
</form>
</div>
`,
methods: {
async login() {
// ...
const rawResponse = await fetchLogin();
if (!rawResponse.ok) {
this.shakeForm = true;
return;
}
// login ok
}
}
};
.form-shaking {
position: relative;
animation: shake-horizontally .2s ease-out 2;
}
#keyframes shake-horizontally {
from {
left: 0;
}
25% {
left: 25px;
}
75% {
left: -25px;
}
to {
left: 0;
}
}
So basically, I'm playing with the shakeForm boolean property, which adds the form-shaking class to the <form>. Then I remove the class on #animationend event (to be able to play it again).
Is there a dedicated Vue.js feature to handle scenarios like this? I looked up the transition/animation features, but couldn't find anything suitable.
You could always manually edit the styles.animation attribute of the form on the fly, to make it shake, like so:
function shake() {
document.getElementsByClassName('form-shaking')[0].style.animation = 'shake-horizontally .2s ease-out 2';
// stop the animation after the animation ends
window.setTimeout(function() {
document.getElementsByClassName('form-shaking')[0].style.animation = 'unset';
}, 400);
}
(In order for the function to work, the animation must be unset at the time of function call.)
As an example, you could use the following as a demo (driver code):
function shake() {
console.log('Incorrect Login: shaking form...')
document.getElementsByClassName('form-shaking')[0].style.animation = 'shake-horizontally .2s ease-out 2';
// stop the animation after the animation ends
window.setTimeout(function() {
document.getElementsByClassName('form-shaking')[0].style.animation = 'unset';
console.log('Incorrect Login: form shake state reset.')
}, 400);
}
window.setTimeout(shake, 1000)
window.setTimeout(shake, 2000)
window.setTimeout(shake, 3000)
.form-shaking {
position: relative;
/* animation: shake-horizontally .2s ease-out 2; */
}
#keyframes shake-horizontally {
from {
left: 0;
}
25% {
left: 25px;
}
75% {
left: -25px;
}
to {
left: 0;
}
}
<!DOCTYPE html>
<html lang="en" dir="ltr">
<head>
<meta charset="utf-8">
<title>CSS Animation on JS Event</title>
</head>
<body>
<div class="form-shaking" style="margin: 32px; display: inline-block; background-color: black; min-width: 100px; min-height: 100px;"> </div>
</body>
</html>

How to retrigger function (translate animation )

My animation function only runs once. I've tried removing and adding classes, as well as running a animationend function to create a retrigger. But still no luck. Any vanilla JS ideas?
CSS:
#element {
width: 10px;
height: 10px;
animation: "";
#keyframes movedown {
100% {
transform: translateY(10px);
}
}
JS:
btn_button.onclick = () => {
element.style.animation = "movedown 10s";
};
HTML:
<div id="element"></div>
You can use setTimeout to set element.style.animation to "". Then, you can add animation name again upon button click.
let btn = document.querySelector("#btn");
btn.onclick = () => {
element.style.animation = "movedown 2s";
setTimeout(() => element.style.animation = "", 2000)
};
#element {
width: 10px;
height: 10px;
background-color: red;
}
#keyframes movedown {
100% {
transform: translateY(50px);
}
}
<div id="element"></div>
<button id="btn">Trigger</button>

requestAnimationFrame is not triggering the function supplied to it

I implemented a infinite loop animation using setInterval. I now like to change the implementation to requestAnimationFrame() so that I will have performance which I am after. For some reasons, requestAnimationFrame() does not call the function supplied to it.
My code looks like this;
var index = 0;
var $btn = $('.btn');
function btnBlinkRun() {
if (index < 2) {
index = index + 1;
} else {
index = 0;
}
$('#ani--scaleinout').removeAttr('id');
$($btn[index]).attr('id', 'ani--scaleinout');
window.requestAnimationFrame(btnBlinkRun);
}
btnBlinkRun();
.btn{
width: 30px;
height: 30px;
background: blue;
border-radius: 100%;
margin-bottom: 10px;
}
#ani--scaleinout {
animation: zoominout 1s ease-in;
}
#keyframes zoominout {
50% {
transform: scale(1.4);
}
100% {
transform: scale(1);
}
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div>
<div class="btn" id="ani--scaleinout"></div>
<div class="btn"></div>
<div class="btn"></div>
</div>
It looks like what's going on is you are firing requestAnimationFrame multiple times per second. Your css animation has a duration of 1s. But you are removing the attribute every x ms.
It is triggering, it's just happening so fast you can't see it. To demonstrate change your call to window.requestAnimationFrame to use a setTimeout and you'll notice the animation:
setTimeout(function() {
window.requestAnimationFrame(btnBlinkRun);
}, 1000);
Not saying this is a preferred solution, but explaining why this is happening.
It executes alright. But it does not do what you want it to, i presume.
Animation frame fires on every single rending frame (e.g. 60fps) and not on CSS animation keyframes.
The animationend event is your friend here.
var index = 0;
var buttons = document.querySelectorAll('.btn');
function btnBlinkRun() {
if (index < 2) {
index = index + 1;
} else {
index = 0;
}
const element = document.querySelector('#ani--scaleinout');
element.id = null;
buttons[index].id = 'ani--scaleinout';
buttons[index].addEventListener("animationend", btnBlinkRun, { once: true });
}
btnBlinkRun();
.btn{
width: 30px;
height: 30px;
background: blue;
border-radius: 100%;
margin-bottom: 10px;
}
#ani--scaleinout {
animation: zoominout 1s ease-in;
}
#keyframes zoominout {
50% {
transform: scale(1.4);
}
100% {
transform: scale(1);
}
}
<div>
<div class="btn" id="ani--scaleinout"></div>
<div class="btn"></div>
<div class="btn"></div>
</div>

how to give fadeout effect to a page in javascript without using jQuery

.. i tried using the code in which the loading will keep on increasing till 100 until a new page will open..
if(loading==90){
preload.style.animation = "fadeOut 2s ease";
}
but its not working
Use css opacity, 1 is full visible, 0 is hidden and 0.5 is half visible.
document.getElementById("yourId").style.opacity = "0.5";
You can append class to preload element
if (window.addEventListener) {
window.addEventListener('load', cool, false);
}
function cool() {
var preload = document.getElementById("preload");
var loading = 0;
var id = setInterval(frame,64);
function frame() {
if(loading == 100) {
clearInterval(id);
// window.open("test1.html","_self");
}
if(++loading == 90){
preload.className = "ld";
}
}
};
#preload {
position: absolute;
display: block;
left: 0;
top: 0;
background: tomato;
width: 100%;
height: 200px;
transition: all 2s ease;
}
.ld {
opacity: 0;
}
<div id="preload"></div>
test string

Flashing Table Row

I have a dynamic table, and set conditions to make the table row background color changed based on time comparison. I want to add a second logic that will make the table row flash/blink every 2 seconds if cells are not matching. I understand that I need to create the "Flash/Blink" function but how do I integrate that function into my logic below?
for (i = 0; i < rows.length; i++) {
cells = rows[i].getElementsByTagName('td');
if (cells[10].innerText != cells[11].innterText) {
rows[i].className = "blink/Flash";
}
}
Look ma, no JavaScript!
HTML
<table>
<tr>
<td>true</td>
<td class="invalid">false</td>
<td>true</td>
<td>true</td>
</tr>
</table>
CSS
#-webkit-keyframes invalid {
from { background-color: red; }
to { background-color: inherit; }
}
#-moz-keyframes invalid {
from { background-color: red; }
to { background-color: inherit; }
}
#-o-keyframes invalid {
from { background-color: red; }
to { background-color: inherit; }
}
#keyframes invalid {
from { background-color: red; }
to { background-color: inherit; }
}
.invalid {
-webkit-animation: invalid 1s infinite; /* Safari 4+ */
-moz-animation: invalid 1s infinite; /* Fx 5+ */
-o-animation: invalid 1s infinite; /* Opera 12+ */
animation: invalid 1s infinite; /* IE 10+ */
}
Live demo
http://jsfiddle.net/bikeshedder/essxz/
For those poor souls who are forced to use an outdated browser
CSS
.invalid-blink {
background-color: red;
}
JavaScript
$(function() {
var on = false;
window.setInterval(function() {
on = !on;
if (on) {
$('.invalid').addClass('invalid-blink')
} else {
$('.invalid-blink').removeClass('invalid-blink')
}
}, 2000);
});
Live demo
http://jsfiddle.net/bikeshedder/SMwAn/
Try this:
<style type="text/css">
/* styles to make cells red when under row with class "blink" */
tr.blink td {background-color:#ff0000;}
</style>
var blinking_rows = []; //array to store rows that must blink
if (cells[10].innerText != cells[11].innterText)
{
rows[i].className = "blink"; //this makes cells background color red
blinking_rows[blinking_rows.length] = rows[i]; //saving row DOM object into array
}
//Running a timer that makes the row blinks every 2 seconds by changing their class
window.setInterval(function()
{
for(var i = 0, len = blinking_rows.length; i < len; ++i)
if(blinking_rows[i].className === "blink") //I'm supposing you do not add other classes
blinking_rows[i].className = ""; //removing class, this makes the row not red anymore
else
blinking_rows[i].className = "blink"; //this makes the row red again
}, 2000);

Categories