Vue.js: Play CSS animation on JavaScript event - javascript

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>

Related

Uncall/reversing an 'onclick' function when another 'onclick' function is active

I have a problem where when I click an element with an 'onclick' function, it works just as normal but when I click another element with a different 'onclick' function, the first 'onclick' function will remain. Instead, I want to be able able to reverse(?) the first function so that it is no longer active.
These are h1 tags that are meant to act as nav and when I click on one of them they change their styles.
Here is my code:
function aboutActive() {
var about = document.querySelector('.about');
about.classList.toggle('about-active');
}
function contactActive() {
var contact = document.querySelector('.contact');
contact.classList.toggle('contact-active');
}
function discoverActive() {
var discover = document.querySelector('.discover');
discover.classList.toggle('discover-active');
}
function signUpActive() {
var signUp = document.querySelector('.sign-up');
signUp.classList.toggle('signUp-active');
}
.about {
position: absolute;
left: 70.8%;
top: 5%;
transition: transform 0.8s ease-in;
transition: 0.8s ease-in;
}
.contact {
position: absolute;
left: 56%;
top: 24%;
transition: transform 0.8s ease-in;
transition: 0.8s ease-in;
}
.discover {
position: absolute;
left: 52.7%;
top: 43%;
transition: transform 0.8s ease-in;
transition: 0.8s ease-in;
}
.sign-up {
width: 100%;
position: absolute;
left: 62.6%;
top: 63%;
transition: transform 0.8s ease-in;
transition: 0.8s ease-in;
}
/* New styles applied by JS */
.about-active {
transform: translateX(-30%);
color: #ffffff;
}
.contact-active {
transform: translateX(-22%);
color: #ffffff;
}
.discover-active {
transform: translateX(-24%);
color: #ffffff;
}
.signUp-active {
transform: translateX(-14.2%);
color: #ffffff;
}
<h1 class="about" onmouseover=cursorEnlargeLarge() onmouseout=cursorNormal() onclick="aboutActive()">ABOUT</h1>
<h1 class="contact" onmouseover=cursorEnlargeLarge() onmouseout=cursorNormal() onclick="contactActive()">CONTACT</h1>
<h1 class="discover" onmouseover=cursorEnlargeLarge() onmouseout=cursorNormal() onclick="discoverActive()">DISCOVER</h1>
<h1 class="sign-up" onmouseover=cursorEnlargeLarge() onmouseout=cursorNormal() onclick="signUpActive()">SIGN UP</h1>
These are the functions that toggle through the styles when clicked on.
To reiterate, when I click on one of the h1 element, it does its 'onclick' function normally but if I want to click on a second h1 element, the second element's function will activate but the first will stay. How would I change it so that any previous functions will be reversed/uncalled?
function undo(ele){
let cl = ele.classList;
ele.classList.remove(cl[cl.length - 1], cl[cl.length - 2]);
}
function aboutActive() {
let about = document.querySelector('.about');
let current = document.querySelector(".current");
if(current) undo(current);
about.classList.toggle('about-active');
about.classList.add("current");
}
function contactActive() {
let contact = document.querySelector('.contact');
let current = document.querySelector(".current");
if(current) undo(current);
contact.classList.toggle('contact-active');
contact.classList.add("current");
}
I'm just adding 'current' class to active element.
If 'current' already exists then remove last 2 classes of the 'current' element.
It's not the best one but it works.
(well it's my first answer on stackoverflow so don't hate on me please)
From what I understand, you want when you click on other function uncall function you clicked before
var about = document.querySelector('.about');
var contact = document.querySelector('.contact');
function aboutActive() {
about.classList.toggle('about-active', true);
}
function contactActive() {
about.classList.toggle('about-active', false);
contact.classList.toggle('contact-active');
}
Add a Reset function before click of any H1 which will reset all the h1 tag click
function aboutActive() {
resetAll();
var about = document.querySelector('.about');
about.classList.toggle('about-active');
}
function contactActive() {
resetAll();
var contact = document.querySelector('.contact');
contact.classList.toggle('contact-active');
}
function discoverActive() {
resetAll();
var discover = document.querySelector('.discover');
discover.classList.toggle('discover-active');
}
function signUpActive() {
resetAll();
var signUp = document.querySelector('.sign-up');
signUp.classList.toggle('signUp-active');
}
function resetAll() {
var getheading = document.getElementsByTagName("H1");
[].forEach.call(getheading, function(el) {
var classes = el.className.split(" ").filter(c => !c.endsWith("-active"));
el.className = classes.join(" ").trim();
})
}
.about-active {
transform: translateX(-30%);
color: #ffffff;
}
.contact-active {
transform: translateX(-22%);
color: #ffffff;
}
.discover-active {
transform: translateX(-24%);
color: #ffffff;
}
.signUp-active {
transform: translateX(-14.2%);
color: #ffffff;
}
<h1 class="about" onclick="aboutActive()">ABOUT</h1>
<h1 class="contact" onclick="contactActive()">CONTACT</h1>
<h1 class="discover" onclick="discoverActive()">DISCOVER</h1>
<h1 class="sign-up" onclick="signUpActive()">SIGN UP</h1>
So what I ended up doing is just removing the active class when I call the function:
function aboutActive() {
var about = document.querySelector('.about');
var contact = document.querySelector('.contact');
var discover = document.querySelector('.discover');
var signUp = document.querySelector('.sign-up');
about.classList.toggle('about-active');
contact.classList.remove('contact-active');
discover.classList.remove('discover-active');
signUp.classList.remove('signUp-active');
}
I have to this for every h1 element so it isn't the best way but it works.

Sidebar collapses for a second and expands on page load

I have this sidebar which expands or collapses on a button click. Now I've successfully stored it's state in localStorage and it's working fine except there's a slight issue.
When the page loads and there is no state saved in localStorage, the sidebar collapses for a split second and expands. Expand is supposed to be the default state when there is no state stored in localStorage. I don't want it to collapse first and then expand. I just want the page to load with the sidebar expanded.
I have been trying to solve the issue with my own code. But it didn't work then I combined my code with of of SO's posts. It still doesn't work.
Full Code: Codepen
Here's the code(please note that localStorage won't work in SO):
$('document').ready(function() {
if (typeof window.isMinified === "undefined") {
window.isMinified = false;
}
const body = $('#body');
$("#sidebar-toggler").on("click", function () {
if (window.isMinified === false) {
// localStorage.setItem('menu-closed', !$(body).hasClass("sidebar-minified"));
body.removeClass("sidebar-minified-out").addClass("sidebar-minified");
window.isMinified = true;
} else {
// localStorage.setItem('menu-closed', !$(body).hasClass("sidebar-minified"));
body.removeClass("sidebar-minified").addClass("sidebar-minified-out");
window.isMinified = false;
}
});
const state = // localStorage.getItem('menu-closed');
if (state === null) {
$(body).removeClass('sidebar-minified');
} else {
const closed = state === "true" ? true : false;
if (!closed) {
$(body).removeClass('sidebar-minified');
}
}
});
#body {
background: #fff;
transition: all 0.3s;
}
aside.left-sidebar{
background-color: #2c0963;
height: 100vh;
}
.sidebar-minified-out .left-sidebar {
width: 180px;
transition: width .3s ease-in;
}
.sidebar-minified .left-sidebar {
width: 75px;
transition: width .3s ease-in;
}
.sidebar-toggle {
font-weight: 300;
font-size: 15px;
cursor: pointer;
height: 30px;
position: absolute;
left: 20%;
top: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<body id="body" class="sidebar-minified sidebar-minified-out">
<aside class="left-sidebar"></aside>
<button id="sidebar-toggler" class="sidebar-toggle">Collapse/Expand</button>
</body>
You can minimize the the flashing effect, by telling the browser to repaint just only one time, in one shot. BUT there will be always one initial size for Your sidebar: the size which has been defined inside Your markup.
In my example, I am using two Observers to track the style and size changes. Please, note the initial sidebar width. You may set the initial sidebar width equal to 0, or let it unassigned, or maybe You can style it the same size as Your expanded sidebar, but there will be always an initial repaint.
Finally, I strongly believe You need to remove the two initial classes from the body.
$(function() {
/* avoid SO unsecure operation error */
var storage = (function () {
return {
setItem: function(k,v){try{return localStorage.setItem(k,v)}catch(e){return !1}},
getItem: function(k){try{return localStorage.getItem(k)}catch(e){return null}}
};
})();
log("jQuery DOM Ready");
$("#sidebar-toggler").on("click", function() {
var isMinified = !$("body").hasClass("sidebar-minified-out");
$("body")
.toggleClass("sidebar-minified", !isMinified)
.toggleClass("sidebar-minified-out", isMinified);
storage.setItem('menu-closed', +!isMinified);
});
var closed = +storage.getItem('menu-closed');
log('Closed: ' + !!closed);
$("body")
.addClass(closed ? "sidebar-minified" : "sidebar-minified-out")
.css({"visibility": "visible"});
});
body {
background: #fff;
transition: all 0.3s;
}
aside.left-sidebar{
background-color: #2c0963;
height: 100vh;
}
.sidebar-minified-out .left-sidebar {
width: 180px;
transition: width .3s ease-in;
}
.sidebar-minified .left-sidebar {
width: 75px;
transition: width .3s ease-in;
}
.sidebar-toggle {
font-weight: 300;
font-size: 15px;
cursor: pointer;
height: 30px;
position: absolute;
left: 20%;
top: 0;
}
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<title>Sidebar State</title>
<meta name="viewport" content="width=device-width,initial-scale=1">
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
</head>
<body style="visibility: hidden;">
<aside class="left-sidebar"></aside>
<button id="sidebar-toggler" class="sidebar-toggle">Collapse/Expand</button>
<div id="log" style="position:absolute;top:0;right:0;padding:1em;"></div>
<script>
/* only debug functions inside this script block */
function log(msg) {
$("<div>").appendTo("#log").text(msg);
}
var mo = new MutationObserver(function (ml){
for(var m of ml) {
if (m.type == 'attributes') log('Body ' + m.attributeName + ' changed');
}
});
mo.observe(document.getElementsByTagName('body')[0], {attributes: true});
var ro = new ResizeObserver(function (rl){
for(var r of rl) {
var w = r.contentRect.width;
if(w<=75 || w>=180) log('Sidebar width: ' + r.contentRect.width);
}
});
ro.observe(document.getElementsByClassName("left-sidebar")[0]);
</script>
</body>
</html>
EDIT:
If You look at the messages logged by the Observers, You will notice that there is always a repaint, as mentioned above.
After reading this solution of Your previous question: Dark mode flickers a white background for a millisecond on reload I believe You can implement Your Sidebar toggler the same way.
Instead of applying the CSS class to the body, You can apply it to the html. Here is the full code:
HTML
<!DOCTYPE html>
<html>
<head>
<script>
/* Render blocking script */
var c = +localStorage.getItem('menu-closed');
document.documentElement.classList.add(c ? 'sidebar-minified' : 'sidebar-minified-out');
</script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
</head>
<body>
<aside class="left-sidebar"></aside>
<button id="sidebar-toggler" class="sidebar-toggle">Collapse/Expand</button>
</body>
</html>
JS
$(function() {
$("#sidebar-toggler").on("click", function (e) {
var isMinified = !$("html").hasClass("sidebar-minified-out");
$("html")
.toggleClass("sidebar-minified", !isMinified)
.toggleClass("sidebar-minified-out", isMinified);
localStorage.setItem('menu-closed', +!isMinified);
});
});
Your CSS will remain untouched beside of a small change (I just only removed the #body id).
Now, if You compare the Observed changes, You will notice that the second solution, which is using the blocking JS script in head, is showing only the initial Sidebar size, i.e.: the initial repaint is gone:
1st solution 2nd solution
==============================================================
Sidebar width: 601 Closed: false
jQuery DOM Ready Sidebar width: 180
Closed: false jQuery DOM Ready
Body class changed
Body style changed
Sidebar width: 180
(Credits: Roko C. Buljan):
More information:
The debug functions in my first example are used just only to depict the sequence of the resize and restyle events inside the browser.
Here is some documentation about that Observers:
MutationObserver
ResizeObserver
It is the transition from the css that let the sidebar expand. If you remove the transistion you will see that the sidebar ist immediately expanded on page load. So for the first time you should set CSS classes without transitions.
You could disable the transition via Javascript and enable it again for the click event:
jsfiddle demo
First remove the classes in the body tag:
<body id="body" class="">
<aside class="left-sidebar"></aside>
<button id="sidebar-toggler" class="sidebar-toggle">Collapse/Expand</button>
</body>
Just a few lines to change in the javascript:
$('document').ready(function() {
if (typeof window.isMinified === "undefined") {
window.isMinified = false;
}
const body = $('#body');
$("#sidebar-toggler").on("click", function () {
document.querySelector('.left-sidebar').style.transition = 'inherit';
if (window.isMinified === false) {
localStorage.setItem('menu-closed', !body.hasClass('sidebar-minified'));
body.removeClass('sidebar-minified-out').addClass('sidebar-minified');
window.isMinified = true;
} else {
localStorage.setItem('menu-closed', !body.hasClass('sidebar-minified'));
body.removeClass('sidebar-minified').addClass('sidebar-minified-out');
window.isMinified = false;
}
});
const state = localStorage.getItem('menu-closed');
if (state === null) {
body.addClass('sidebar-minified');
} else {
const closed = state === "true" ? true : false;
if (!closed) {
body.addClass('sidebar-minified-out');
document.querySelector('.left-sidebar').style.transition = 'none';
}
else {
body.addClass('sidebar-minified');
}
}
});
The important changes in above code are two things:
// in the clickevent section: change the transistion to default behaviour
document.querySelector('.left-sidebar').style.transition = 'inherit';
Set the right class depending on state and disable transition:
// ...
if (state === null) {
body.addClass('sidebar-minified');
} else {
// ...
if (!closed) {
body.addClass('sidebar-minified-out');
document.querySelector('.left-sidebar').style.transition = 'none';
}
else {
body.addClass('sidebar-minified');
}
}
*** Update ***
I refactored the code and optimized it a bit. fiddle
HTML:
<body id="body">
<aside class="left-sidebar"></aside>
<button id="sidebar-toggler" class="sidebar-toggle">Collapse/Expand</button>
</body>
CSS:
#body {
background: #fff;
transition: all .3s;
}
aside.left-sidebar {
background-color: #2c0963;
height: 100vh;
width: 75px;
}
.sidebar-minified-out .left-sidebar {
width: 180px;
}
.sidebar-transitions .left-sidebar {
transition: width .3s ease-in;
}
.sidebar-toggle {
font-weight: 300;
font-size: 15px;
cursor: pointer;
height: 30px;
position: absolute;
left: 20%;
top: 0;
}
JS:
$('document').ready(function() {
$("#sidebar-toggler").on("click", function () {
localStorage.setItem('menu-closed', $('#body').hasClass('sidebar-minified-out'));
$('#body').addClass('sidebar-transitions').toggleClass('sidebar-minified-out');
});
localStorage.getItem('menu-closed') === "true" ? $('#body').removeClass('sidebar-minified-out') : $('#body').addClass('sidebar-minified-out');
});
How about moving the animation to a separate class lets say
.sidebar-animated{
transition: width: 0.3s ease-in;
}
and removing it from anywhere else and then adding that class via timeout, so it gets added after the transition is done, you can use useTimeout with 0 seconds, like so,
setTimeout(() => {
$('aside').addClass('sidebar-animated')
},0)
Plus CSS uses Specificity to reach its element, so
.sidebar-minified-out .left-sidebar {
width: 180px;
}
.sidebar-minified .left-sidebar {
width: 75px;
}
Should be changed to this.
.sidebar-minified .left-sidebar {
width: 75px;
}
.sidebar-minified-out .left-sidebar {
width: 180px;
}
because when you have both on the same element, it will take the later because they have the same specificity rule, give it a last shot, thats the last resort for me :D.
thats enough to make it work
https://codepen.io/menawer_cpe/pen/qBZbEdw
here is a working example,
Note: you have an issue with managing state when the sidebar collapsed at first, but thats something related to how you deal with the state.
Why useTimeout with 0? because it pushes the execution to what is called "event loop" making sure it executes after all javascript normal code is executed.
You can try this :
$('document').ready(function() {
if (window.isMinified === undefined) {
window.isMinified = false;
}
const body = $('#body');
$("#sidebar-toggler").on("click", function() {
$('#body .left-sidebar').removeAttr("style");
if (window.isMinified === false) {
body.removeClass("sidebar-minified-out").addClass("sidebar-minified");
window.isMinified = true;
} else {
body.removeClass("sidebar-minified").addClass("sidebar-minified-out");
window.isMinified = false;
}
});
var firstTime = true;
var sidebar = $('#body aside.left-sidebar');
const state = !(null); //localStorage.getItem('menu-closed');
if (state === null) {
$(body).removeClass('sidebar-minified');
} else {
if (firstTime) {
sidebar.css('transition', 'none');
firstTime = false;
}
const closed = state === "true" ? true : false;
if (!closed) {
$(body).removeClass('sidebar-minified');
}
}
});
#body {
background: #fff;
transition: all 0.3s;
}
aside.left-sidebar {
background-color: #2c0963;
height: 100vh;
}
.sidebar-minified-out .left-sidebar {
width: 180px;
transition: width .3s ease-in;
}
.sidebar-minified .left-sidebar {
width: 75px;
transition: width .3s ease-in;
}
.sidebar-toggle {
font-weight: 300;
font-size: 15px;
cursor: pointer;
height: 30px;
position: absolute;
left: 20%;
top: 0;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<body id="body" class="sidebar-minified sidebar-minified-out">
<aside class="left-sidebar"></aside>
<button id="sidebar-toggler" class="sidebar-toggle">Collapse/Expand</button>
</body>

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

setInterval is not adding .addClass

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);

Categories