Can`t move element on setInterval function - javascript

I have a small image that may change his background-position-x on hover event. And stop moving on mouseleave. But even with setInterval my fuctuin run just 1 time. Here`s my code. Could someone help me?
let wave = document.querySelector('.wave');
wave.onmouseover = moveWave();
function moveWave() {
setInterval(function () {
wave.style.backgroundPositionX += 10 + 'px';
}, 100)
}

The problem is with below line:
wave.style.backgroundPositionX += 10 + 'px';
After first call, the wave.style.backgroundPositionX will be:
10px
After next call, the wave.style.backgroundPositionX will be:
10px10px -> which is incorrect format.
The right way is:
var count = 10;
let wave = document.querySelector('.wave');
wave.onmouseover = moveWave();
function moveWave() {
setInterval(function () {
count += 10;
wave.style.backgroundPositionX = count + 'px';
}, 100)
}

var count = 10;
let wave = document.querySelector('.wave');
wave.onmouseover = moveWave();
wave.onmouseleave = moveLeave();
var id;
function moveWave() {
id = setInterval(function () {
count += 10;
wave.style.backgroundPositionX = count + 'px';
}, 100)
}
function moveLeave() {
clearInterval(id);
}

Related

Issue linking images to dynamically created jquery elements

So, I'm very new, so apologies if this is a silly question. I have worked out a Trivia Quiz for my learning to code classes I'm taking. I want to display an image on the confirmation screen that shows whether the user was right or wrong. I think the code is correct-ish? I'm not sure what isn't working.
I left out the main Question and answer object for space. Sorry if I didn't format this ideally? I'm still kinda figuring out how things work here.
Here is my code for reference:
//array to help me iterate and insert images
var imgArray = ["question1", "question2", "question3", "question4", "question5", "question6", "question7", "question8", "question9", "question10", "question11", "question12", "question13"];
var currentQuestion = 0;
var win = 0;
var lose = 0;
var unanswered = 0;
var time = 30;
//set up divs to contain our info
var rightDiv = $("<div class='rightAns'></div>");
var timerDiv = $("<div class='countdown'><h3></h3></div>");
var questionDiv = $("<div class='question'><h1></h1></div><br>");
var answerDiv = $("<div class='answers'></div>");
//object keys to return questions in order
var keys = Object.keys(questions);
var key = keys[n];
var n = 0;
//function to setup and restart game
function reset() {
$("#start-button").hide("slow");
$("#start-here").hide("slow");
win = 0;
lose = 0;
unanswered = 0;
n = 0;
key = keys[n];
currentQuestion = 0;
$("#question-block").empty();
var reset = function () {
time = 30;
$(".rightAns").empty();
$(".rightAns").remove();
// $("#image").empty();
$("#time-remaining").append(timerDiv);
$(".countdown h3").html("Time Remaining: " + time);
$("#question-block").append(questionDiv);
$("#question-block").append(answerDiv);
}
reset();
//function to show questions
function showQuestion() {
$(".question h1").html(questions[key].question);
for (var i = 0; i < questions[key].answers.length; i++) {
$(".answers").append("<button class='answer btn btn-danger btn-lg m-1'>" + questions[key].answers[i] + "</button>");
}
$(".answers button").on("click", function () {
var selected = $(this).text();
//if then to check question correctness
if (selected === questions[key].correct) {
clearInterval(counter);
$(timerDiv).remove();
$(questionDiv).remove();
$(".answers button").remove();
$(answerDiv).remove();
$("#correct-answer").append(rightDiv);
$(".rightAns").text("That's Correct!!");
$("#image").html('<img src = ".assets/images/' + imgArray[currentQuestion] + '" width = "400px">');
win++;
currentQuestion++;
} else {
clearInterval(counter);
$(timerDiv).remove();
$(questionDiv).remove();
$(".answers button").remove();
$(answerDiv).remove();
$("#correct-answer").append(rightDiv);
$(".rightAns").text("Nope! The correct answer was: " + questions[key].correct);
$("#image").html('<img src = ".assets/images/' + imgArray[currentQuestion] + '" width = "400px">');
lose++;
currentQuestion++;
}
n++;
key = keys[n];
//checking to see if there are more questions left
if (checkForLast()) {
finalScore();
} else {
setTimeout(countReset, 3 * 1000);
setTimeout(reset, 3 * 1000);
setTimeout(showQuestion, 3 * 1000);
}
});
}
showQuestion();
var counter = setInterval(count, 1000);
//show time remaining for each question
function count() {
time--;
$(".countdown h3").html("Time Remaining: " + time);
if (time < 1) {
clearInterval(counter);
$(timerDiv).remove();
$(questionDiv).remove();
$(".answers button").remove();
$("#correct-answer").append(rightDiv);
$(".rightAns").html("You took too long! The correct answer was: " + questions[key].correct);
unanswered++;
n++;
key = keys[n];
if (checkForLast()) {
finalScore();
} else {
setTimeout(countReset, 3 * 1000);
setTimeout(reset, 3 * 1000);
setTimeout(showQuestion, 3 * 1000);
}
}
}
function checkForLast() {
if (key === undefined) {
return true;
}
return false;
}
//timer for the message after you choose your answer
function countReset() {
counter = setInterval(count, 1000);
}
//showthe final score screen
function finalScore() {
$(".rightAns").remove();
$("#image").empty();
$("#question-block").prepend("<h2>Unanswered: " + unanswered + "</h2>");
$("#question-block").prepend("<h2>Incorrect: " + lose + "</h2>");
$("#question-block").prepend("<h2>Correct: " + win + "</h2>");
$("#start-button").show();
$("#start-here").show();
}
};
//function to start game on button click
$(document).on("click", "#start-button", reset);
});
After tinkering for a bit, I dropped the "." at the beginning of the call and added the .jpg to the section after imgArray[currentQuestion]. That solved it. Thanks for the suggestions.

Increase and decrease SVG shape - JS

I would like you to help me for a thing here, for a function to increase and then decrease SVG shape when it hits limit.
It should go from 3 to 6 and then 6 to 3 and so on... but instead it goes from 3 to 6 and then 6 to minus infinite. And I don't understand why.
Here is my code :
var size = 3;
var sizeManager = 1;
function increaseAnimation(el){
var elem = document.getElementById(el);
elem.style.transform = "scale("+size+")";
timer = setTimeout('increaseAnimation(\''+el+'\',3000)');
size=size+0.005*sizeManager;
if(size >= 6){
sizeManager=sizeManager*-1;
}
if (size <= 3){
sizeManager=sizeManager*+1;
}
}
Your weird setTimeout implementation, with bound was broken.
There's also the issue that your sizeManager is not properly reflecting:
function increaseAnimation(id, interval) {
var size = 1;
var velocity = 0.05;
var elem = document.getElementById(id);
function iterate() {
elem.style.transform = "scale(" + size + ")";
size += velocity;
if (size > 2 || size < 1) {
velocity *= -1; // velocity reflected
}
}
var timer = setInterval(iterate, interval);
return function stop() {
clearInterval(timer)
}
}
I also added a stop function which you can call at a later point.
var stopper = increaseAnimation("content", 16);
setTimeout(stopper, 5000);
The error is with the line sizeManager=sizeManager*+1; Multiplying a number by one doesn't change it. You basically want to toggle sizeManager between -1 and +1, and you can do so by multiplying by -1, regardless of whether it is currently negative or positive.
I've tested this code and it seems to work:
var size = 3;
var sizeManager = 1;
function increaseAnimation(el) {
var elem = document.getElementById(el);
elem.style.transform = "scale(" + size + ")";
timer = setTimeout("increaseAnimation('" + el + "', 3000)");
size += 0.005 * sizeManager;
if (size >= 6 || size <= 3) {
sizeManager *= -1;
}
}
Full HTML for a POC demo at: https://pastebin.com/GW0Ncr9A
Holler, if you have questions.
function Scaler(elementId, minScale, maxScale, deltaScale, direction, deltaMsecs) {
var scale = (1 == direction)?minScale:maxScale;
var timer = null;
function incrementScale() {
var s = scale + deltaScale*direction;
if (s < minScale || s > maxScale) direction *= -1;
return scale += deltaScale*direction;
};
function doScale(s) {
document.getElementById(elementId).style.transform = 'scale(' + s + ')';
};
this.getDeltaMsecs = function() {return deltaMsecs;};
this.setTimer = function(t) {timer = t;};
this.run = function() {doScale(incrementScale());};
this.stop = function() {
clearInterval(timer);
this.setTimer(null);
};
};
var scaler = new Scaler('avatar', 3, 6, .05, 1, 50);
function toggleScaler(ref) {
if ('run scaler' == ref.value) {
ref.value = 'stop scaler';
scaler.setTimer(setInterval('scaler.run()', scaler.getDeltaMsecs()));
}
else {
scaler.stop();
ref.value = 'run scaler';
}
};

How can I make my outputs cycle up or down to the final answer?

I've got a simple simulator code where the user selects buttons to vary the inputs, and the outputs change in response (an example extract of which is shown below).
However, the outputs update automatically to the solution, and I was wondering if there's a way to show the numbers ticking over and increasing from what was previously displayed to the new number?
html
<button onClick = "IncTHR()">Increase Throttle</button>
<button onClick = "DecTHR()">Decrease Throttle</button>
<input type="text" id="THR">
<div id="CoolantTemp1"></p>
javascript
var CoolantTemp1 = 366;
var Throttle = 5;
var ControlRodHeight = 50;
var PrimaryPump = 1;
function IncTHR(){
user = ++Throttle;
if (Throttle > 10){
Throttle = 10;
}
CoolantTemp1 = (220+(ControlRodHeight*2.2)+(PrimaryPump*20)+(Throttle*3.2));
update();
displayResults();
function DecTHR(){
user = --Throttle;
if (Throttle < 0){
Throttle = 0;
}
CoolantTemp1 = (220+(ControlRodHeight*2.2)+(PrimaryPump*20)+(Throttle*3.2));
update();
displayResults();
function update() {
document.getElementById("THR").value = Throttle;
}
function displayResults() {
document.getElementById("CoolantTemp1").innerHTML = "Coolant Temperature 1 is " + CoolantTemp1;
}
So currently, as soon as the user clicks either throttle button, the Coolant Temperature is updated immediately to the solution - is there a way for the output to cycle through from the number it previously was to the new number it will become as a result of the calculation change?
Hope that makes sense!
Thank you.
Something like this should work:
var CoolantTemp1 = 366;
var tempCounter = 366;
var Throttle = 5;
var ControlRodHeight = 50;
var PrimaryPump = 1;
function IncTHR(){
Throttle++;
if (Throttle > 10){
Throttle = 10;
}
CoolantTemp1 = (220+(ControlRodHeight*2.2)+(PrimaryPump*20)+(Throttle*3.2));
update();
var incInt = setInterval(function (){
if (tempCounter < CoolantTemp1){
displayResults(tempCounter);
tempCounter++;
} else {
displayResults(CoolantTemp1);
tempCounter = CoolantTemp1;
clearInterval(incInt);
}
}, 1000);
}
function DecTHR(){
Throttle--;
if (Throttle < 0){
Throttle = 0;
}
CoolantTemp1 = (220+(ControlRodHeight*2.2)+(PrimaryPump*20)+(Throttle*3.2));
update();
var decInt = setInterval(function (){
if (tempCounter > CoolantTemp1){
displayResults(tempCounter);
tempCounter--;
} else {
displayResults(CoolantTemp1);
tempCounter = CoolantTemp1;
clearInterval(decInt);
}
}, 1000);
}
function update() {
document.getElementById("THR").value = Throttle;
}
function displayResults(temp) {
document.getElementById("CoolantTemp1").innerHTML = "Coolant Temperature 1 is " + temp;
}

Javascript gradual width increase

I'm trying to gradually increase the elements of 2 id's in javascript using a Timeout. I can get one working but when trying to call another element into the same function it only does one iteration then crashes after the first recursive call.
I'm passing two id's for the elements. and I want the left element to gradually increase while the right element gradually increases in width.
Heres what ive got
function grow(elementL, elementR)
{
var htL = parseInt(document.getElementById(elementL).style.width,10);
var htR = parseInt(document.getElementById(elementR).style.width,10);
var movementL = htL + 5;
var movementR = htR - 5;
document.getElementById(elementL).style.width = movementL + 'px';
document.getElementById(elementR).style.width = movementR + 'px';
if (movementL > 1000) {
clearTimeout(loopTimer);
return false;
}
var loopTimer = setTimeout('grow(\''+elementL+','+elementR+'\')',50);
}
You could simplify this (removing the script-generation) by using setInterval -- this repeats the function call until you cancel it.
function grow(elementL, elementR)
{
var loopTimer = setInterval(function() {
if (!growStep(elementL, elementR)) {
clearInterval(loopTimer);
}
}, 50);
}
function growStep(elementL, elementR) {
var htL = parseInt(document.getElementById(elementL).style.width,10);
var htR = parseInt(document.getElementById(elementR).style.width,10);
var movementL = htL + 5;
var movementR = htR - 5;
document.getElementById(elementL).style.width = movementL + 'px';
document.getElementById(elementR).style.width = movementR + 'px';
if (movementL > 1000) {
return false;
}
return true;
}
(Fiddle)
Edit
Yeah, I guess the only problem with the OP code is that it passes a string to setTimeout, rather than the function itself:
var loopTimer = setTimeout(function() {
grow(elementL, elementR);
},50);
setTimeout('grow(\''+elementL+','+elementR+'\')',50)
would need to be
setTimeout('grow(\''+elementL+'\',\''+elementR+'\')',50)
// ^^ ^^
to work. But don't do that. Pass a function expression to setTimeout:
setTimeout(function() {
grow(elementL, elementR);
}, 50)

Event on margin change

I have an element with animated top margin. I need to detect if it isn't too close from the border, and if it is, scroll parent div to lower position, to prevent animated element from hiding. Here is an example:
http://jsfiddle.net/zYYBR/5/
This green box shouldn't be below the red line after clicking the "down" button.
Do you mean this?
var new_margin;
var step = 75;
var limit = $("#max")[0].offsetTop;
$('#down').click(function() {
var goStep = step;
var elHeight = $("#animated")[0].offsetTop + $("#animated")[0].offsetHeight;
if((elHeight + step) > limit)
{
goStep = limit - elHeight;
}
new_margin = goStep + parseInt($('#animated').css('margin-top'));
$("#animated").animate({marginTop: new_margin}, 1000);
});
http://jsfiddle.net/zYYBR/8/
EDIT: Or maybe something like that (of course you can improve the calculation, because currently it's very buggy with scroll):
var new_margin;
var step = 75;
$('#down').click(function () {
scroll(1000);
});
var scrollTimer = null;
$("#container").bind("scroll", function () {
clearTimeout(scrollTimer);
scrollTimer = setTimeout(function () { scroll(1); }, 10);
});
function scroll(speed) {
var scrollStep, animationStep = step;
var currentBoxBottom = $("#animated")[0].offsetTop + $("#animated")[0].offsetHeight;
var nextCurrentBoxBottom = currentBoxBottom + step;
var limit = $("#max")[0].offsetTop + $("#container")[0].scrollTop;
if (nextCurrentBoxBottom > limit) {
if (limit >= $("#container")[0].scrollTop) {
scrollStep = $("#container")[0].scrollTop + nextCurrentBoxBottom - limit;
}
else {
scrollStep = $("#container")[0].scrollTop - nextCurrentBoxBottom - limit;
animationStep = nextCurrentBoxBottom - limit;
}
$("#container")[0].scrollTop = scrollStep;
}
new_margin = animationStep + parseInt($('#animated').css('margin-top'));
$("#animated").animate({ marginTop: new_margin }, speed);
}
http://jsfiddle.net/zYYBR/13/
Do you mean something like this?
I have the same visual result as Alex Dn did, but I added a little extra direction to what I think you're talking about. If it's what you're looking for I'll make updates:
var new_margin;
var step = 75;
var limit = $("#max")[0].offsetTop;
$('#down2').click(function() {
var anim = $("#animated");
var hrOff = $("#max").offset();
var thOff = anim.offset();
new_margin = Math.min(hrOff.top - thOff.top - anim.height(), 75);
console.log(new_margin, hrOff.top, thOff.top);
var st = 0;
if (new_margin < 75) {
st = 75 - new_margin;
//have container scroll by this much?
}
anim.animate({
marginTop: "+=" + new_margin
}, 1000);
});​
​
http://jsfiddle.net/zYYBR/10/

Categories

Resources