Problems with CSS changes in JavaScript - javascript

I am trying do a CSS change via JavaScript. I have a quiz site where, when the user marks the correct option, the option will become green, and when the user marks the incorrect option, the option will become red, but I have to change the color and redirect the user for another page, but the CSS change is very slow and, at certain times, doesn't work. This is my code:
CSS:
.choice{
white-space: normal;
word-wrap: break-word;
margin: 20px;
width: calc(40% + 100px);
height: calc(10% + 10px);
border-style: solid;
border-color: rgba(0, 0, 0, 0.4);
border-radius: 7px;
background-color: rgba(255,255,255,0.6);
cursor: pointer;
font-size: 20px;
transition: 0.4s;
}
JS:
function sleep(ms) {
var d = new Date();
var d2 = null;
do { d2 = new Date(); }
while(d2-d < ms);
}
function govariable(page,variable,valor,id,color) {
document.getElementById(id).style.backgroundColor = color
sleep(3000)
window.location.replace(`${page}?${variable}=${valor}`)
}

When you change something in the DOM (in this case, your background color) JavaScript won't update your screen until the event it is processing has finished.
This is because JavaScript runs in only one thread - it can't be looping around and around and re-displaying your background colour at the same time! It needs to finish looping first.
Instead of trying to implement a "sleep" function that will never work well in a single-threaded javascript world, you should try using setTimeout().
function govariable(page,variable,valor,id,color) {
document.getElementById(id).style.backgroundColor = color
setTimeout(function() {
window.location.replace(`${page}?${variable}=${valor}`)
}, 3000);
}
Instead of looping around again and again until time is up, at a very simplistic level this does something more like setting an internal "wake-up alarm" inside the JavaScript engine, that in 3000 milliseconds will go off, and tell JavaScript to run the code inside it. In this case, to call window.location.redirect.

Related

Detect system time and set css animation start time in browser

I have a html page that has a simple CSS animation, nothing fancy just a background transition between two colors.
Currently I cannot seem to figure out how to get the system time and fire the animation trigger at a specified time
I want to load it in chrome on several mobile devices. Get the system time and then when a preset time is reached the animation plays on a loop.
I made an example using animation-play-state according to second. This adaptable any specific time.
const div = document.querySelector("div");
function getTime(){
let date = new Date();
let second = date.getSeconds();
console.log(second);
if(second == 10){
div.style.animationPlayState = "running";
}
}
setInterval(function(){
getTime();
},1);
div {
width: 300px;
height: 100px;
background-color: red;
animation:animate 2s linear infinite;
animation-play-state:paused;
}
#keyframes animate {
from {
background-color: red;
}
to {
background-color: blue;
}
}
<div></div>

"Tick" issue while using cookies to maintain a persistent countdown timer

The following question requires a look into the following external resources:
jQuery Countdown
JavaScript Cookie
No, this isn't one of the other "Cookie Timer not working" questions here on SO. ;)
I have crafted a persistent countdown timer that uses cookies to save a particular user's countdown state regardless of browser reloads or reboots. Everything is working great, except for when I use jQuery Countdown's "ticks" to create callbacks…
Actually, the callbacks do work if I let the timer run without reloading the page. But as soon as the page reloads, one of the callbacks doesn't work — and one of them does.
The callback that works regardless is the one that checks for the end of the timer. The one that doesn't work (after reload) is the one that checks for the "halfway" point.
Here's the code…
$(document).ready(function()
{
if (!Cookies.get('cdTime'))
{
var now = $.now(); // First time on page
var timerSet = 30; // Amout of time (sec)
var halfway = timerSet / 2;
Cookies.set('firstTime', now,
{
expires: 7,
path: '/'
});
Cookies.set('cdTime', timerSet,
{
expires: 7,
path: '/'
});
var runTimer = Cookies.get('cdTime');
}
else
{
var currentTime = $.now();
var usedTime = (currentTime - Cookies.get('firstTime')) / 1000; // Calculate and convert to sec
var runTimer = Cookies.get('cdTime') - usedTime;
}
$('#cd').countdown({
until: runTimer,
compact: true,
onExpiry: endCountdown,
onTick: callBacks,
layout: '{sn} seconds left...'
});
function callBacks(periods)
{
if ($.countdown.periodsToSeconds(periods) <= halfway)
{
$('#cd').addClass('halfway');
}
else if ($.countdown.periodsToSeconds(periods) === 0)
{
endCountdown();
}
}
function endCountdown()
{
$('#cd').removeClass('halfway').addClass('ended');
$('#cd').html('♥');
}
});
body {
margin: 1em;
font: 2em/1.4em 'Helvetica Neue', 'Helvetica','Arial', sans-serif;
color: #333;
}
#cd {
margin-top: 2em;
font-family: 'Source Code Pro','Andale Mono',Monaco,'Courier New',monospace;
font-size: 30px;
font-weight: 100;
}
.halfway {
color: #0000ff;
}
.ended {
color: #ff0000;
font-size: 125% !important;
line-height: 0;
}
header, footer
{
width:66%;
font-size: 18px;
line-height: 1.4em;
}
footer
{
position: absolute;
bottom: 0;
margin-bottom: 1.5em;
font-style: italic;
color: #ffa500;
}
.highlight
{
background: #FFFBCC;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.1.1/jquery.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-countdown/2.0.2/jquery.plugin.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery-countdown/2.0.2/jquery.countdown.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/js-cookie/2.1.3/js.cookie.min.js"></script>
<header>This countdown timer uses jQuery Countdown, by Keith Wood, and JavaScript Cookie to work — it will continue itsa countdown regardless of browser reloads or reboots (really, try it!). <span class="highlight">Oh, and it works on mobile too</span>.</header>
<div id="cd"></div>
<footer>(Clear the “firstTime” and “cdTime" Cookies and then reload the page to start the timer over.)</footer>
A working example can be found here:
http://codepen.io/ProfessorSamoff/pen/xqXrgx
Watch it through once without reloading the page and then follow the onscreen instructions in order to start the timer again and play around with reloading.
Any ideas about why this might be happening?
Thank you!
Tim
I'm not 100%, but I think halfway is undefined. It only gets sets when the page is loaded for the first time.
Instead of if ($.countdown.periodsToSeconds(periods) <= halfway) try just if ($.countdown.periodsToSeconds(periods) <= halftime)
At the top, instead of var timerSet = 30; before the first if statement put totalTime = 30; and also halftime = Math.floor(totalTime / 2)

Trigger jQuery events one after another

Hi I am trying to create an animation where one class is added only after the one before it is finished triggered.
$('.flipper').click(function(){
$('#first').addClass('first-flip');
$('#second').addClass('second-flip');
$('#fourth').addClass('fourth-flip');
});
so
$('#second').addClass('second-flip');
would only trigger when
$('#first').addClass('first-flip');
has finished its process.
so another way of explaining this would be.
Block A has a rotate effect added to it, after Block A is rotated, only then will Block B move 20 px right.
I basically just want to know how to create Jquery effects that trigger in sequential order.
You want to tie into transitionend or animationend. Here is an example using transitionend. After the box has finished moving, a new class is added which begins the next transition to turn the box blue.
var mydiv = document.querySelector("#mydiv");
document.querySelector("button").addEventListener("click", buttonHandler);
mydiv.addEventListener("transitionend", onEndHandler)
function buttonHandler() {
mydiv.classList.add("move-left");
}
function onEndHandler() {
mydiv.classList.add("turn-blue");
}
#mydiv {
background: red;
width: 10em;
height: 10em;
transition: 1s;
}
#mydiv.move-left {
transform: translateX(100px);
}
#mydiv.turn-blue {
background: blue;
}
<div id="mydiv"></div>
<button>Move div</button>
If you need the jQuery version, it's here:
var mydiv = $("#mydiv");
$("button").on("click", buttonHandler);
mydiv.on("transitionend", onEndHandler)
function buttonHandler() {
mydiv.addClass("move-left");
}
function onEndHandler() {
mydiv.addClass("turn-blue");
}
Nice resource: https://davidwalsh.name/css-animation-callback

Slow down, console. (javascript/jquery)

I'm working on a console game and I don't like the speed at which the console.logs and how little time there is in between prompts and such. Is there a javascript/jquery method to slow down the game? To that effect, can I simply delay() every line (which sounds tedious), or if I were to use setTimeout(), would I theoretically have to split my game into a lot of different functions and set timeouts or intervals? What are your suggestions?
snippet for example:
alert('~~ WELCOME TO [x] ~~');
console.log('Before we get started, let\'s find out a little about you.');
var usr = {
name : prompt('What\'s your name?'),
age : prompt('How old are you?'),
clr : prompt('What\'s your favorite color?'),
pref : prompt('Which [x] is your favorite?'),
}
console.log('The air smells pungent today, and the weather is perfect.');
console.log(''); console.log('');
console.log('Did you hear that? I think something may be following us down the path to the [x]...');
console.log('');
var alpha = prompt('');
There will be if/elses, switches, all sorts of functions and choices. But I want the feel of a text-based console game.
I plan on adding a lot of different routes, features, and hopefully movement at some point. But that's all beside the point. If anyone knows a way or two to slow down a game that would follow this guideline, post any suggestion.
Most users consider prompts to be annoying and ugly. A user won't be able to interact with anything else including other tabs or console during the execution of prompts. Moreover, it is very inconvenient to work with it as a developer, because they are not configurable and they are hard in development, support and, especially, debugging.
It is a better idea to implement an HTML page which will interace with a user. So, you will be able to customize it and look nice.
For example, you can create a page which looks like chat - text window and input at the bottom. Like this:
function tell(text)
{
$("<p/>").text(text).appendTo($('#chat'));
}
function ask(text, callback)
{
$("<p/>").text(text).addClass('question').appendTo($('#chat'));
$('#send')
.prop('disabled', false)
.one('click', function() {
var text = $("#message").val();
callback(text);
$("#message").val("");
$(this).prop('disabled', true);
});
}
tell("Hi");
ask("What is your name?", function(x) {
tell("So strange...my name is " + x + ", as well...");
});
#chat {
padding: 20px;
position: absolute;
top: 0px;
bottom: 20px;
left: 0px;
right: 0px;
background-color: #DDDDDD;
}
#message {
position: absolute;
bottom: 0px;
left: 0px;
height: 14px;
width: 80%;
}
#send {
position: absolute;
bottom: 0px;
left: 80%;
width: 20%;
height: 20px;
}
.question {
font-weight: bold;
color: red;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id="chat"></div>
<input type="text" id="message"/>
<input type="submit" id="send" disabled/>
It is just an example. You may add any things like delays or CSS styling.
Create your own console, alert and prompt methods wrapping the natives.
For instance:
function logConsole(text, delay) {
window.setTimeout(function() {
console.log(text);
}, delay || 0);
};
You can change the 0 value in above to be a default delay if no delay argument is passed in.
logConsole('The air smells pungent today, and the weather is perfect.', 1000);
Just an idea

Unfold animation on DIV with Oridomi (JS)

I'm using the Oridomi (oridomi.com) Javascript plugin to achieve a paper folding animation. Specifically, I would like to have a div unfold on page load (picture a book opening).
However I am having difficulty getting the unfold() method to work, despite being a method which can be called on with the plugin.
You can see from this example, that I can only get the div to fold back, rather than unfold from a folded state (in effect, I would like the animation to be reversed).
My javascript function -
(function(){ function init(){
var $domi = $('.unfold').oriDomi({ vPanels: 2, hPanels: 1, speed: 500, shading: false });
setTimeout(function(){
$domi.oriDomi('reveal', -90);
}, 600);}
document.addEventListener('DOMContentLoaded', init, false);
})();
And CSS -
.unfold {
font-family: "Abril Fatface", "Hoefler Text", Constantia, Palatino, Georgia, serif;
font-size: 4.5rem;
width: 25rem;
height: 10rem;
text-align: center;
line-height: 1;
color: #ff676d;
background-color: #6ac1ff;
padding: 2.5rem 0;
}
The documentation on http://oridomi.com is not very clear on how this can be implemented. Any help would be very much appreciated. Thanks
If the Oridomi does not supports reverse you have 2 options. One would be to know the END stare and domi.oriDomi('reveal', 0);. The other would be to reverse it first on a speed of 0 and then reveal at 0deg to unfold. Here is a fiddle with this:
http://jsfiddle.net/Av6cD/2/
(function fold() {
var $domi = $('.unfold').oriDomi({
vPanels: 2,
hPanels: 1,
speed: 500,
shading: false
});
$domi.oriDomi('reveal', -90);
setTimeout(function () {
$domi.oriDomi('reveal', 0);
}, 1000);
})();
Please note that even if this is a nice effect, oriDomi is making a really mess to your DOM. CSS shaders would be the way to go once they get proper support.

Categories