how to change the the margin value with a count down? - javascript

Would anyone be able to help me with this?
Here is what I have now
http://jsfiddle.net/fergu0516/GAVDA/
var leave = 200;
if(leave > 0)
{
CounterTimer();
}
function CounterTimer()
{
var minute = Math.floor(leave / 60);
var second = Math.floor(leave) - (minute*60);
minute=minute<10 ? "0" + minute : minute;
second=second<10 ? "0" + second : second;
var remain = minute + ":" + second;
leave = leave-1 ;
document.getElementById("clkTimer").innerHTML = remain;
if(leave >= 0)
{
setTimeout(CounterTimer,1000);
}
else
{
alert("Your cart is expired!")
window.location = "#";
}
}
$(document).ready(function(){
// The relative URL of the submit.php script.
// You will probably have to change it.
// Caching the feedback object:
var feedback = $('#feedback');
$('#feedback').click(function(){
// We are storing the values of the animated
// properties in a separate object:
var anim = {
mb : 207, // Margin Bottom
pt : 0 // Padding Top
};
var el = $(this).find('.arrow');
if(el.hasClass('buttonright')){
anim = {
mb : 0,
pt : 0
};
}
// The first animation moves the form up or down, and the second one
// moves the "Feedback heading" so it fits in the minimized version
feedback.stop().animate({marginRight: anim.mb});
feedback.find('.section').stop().animate({paddingTop:anim.pt},function(){
el.toggleClass('buttonright buttonleft');
});
});
});
I need to have the same effect as the sample: what happens now is that when I press the red box the timer shows by giving the (div id="feedback") a margin-right of 207px.
What I need here is this to happen automatically when the time hits 1:00. So when the timer hits 1:00 the window will show, by adding margin-right:207px to the object.
Thank you so much, anything would help.

Demo
do something like this:
if(leave == 60){
$('#feedback').trigger('click');
}

Add
if (leave == 60)
{
$('#feedback').stop().animate({marginRight: 207});
}
to the CounterTimer() function. Maybe after the leave = leave - 1; line.

All you need to do is add an if statement to find out if(leave == 60), and if so you can then animate the element to its "visible" margin-right value.

Related

Dom element infinitely incrementing

I'm in my first steps of creating an auto aim system for the enemy bot but I can't even seem to get him to shoot properly.
I create a div element, and move it in a direction. This happens every 4 seconds. I delete the div before the next one gets created. This works. But somehow it creates more and more elements over time and soon turns into a massive amount of divs all flying in the same direction.
** make the bullet here **
function makeBullet() {
if (player.enemy) {
if (player.enemyBullet.bulletInterval == true) {
console.log("working");
player.enemyBullet.bullet = document.createElement('div');
player.enemyBullet.bullet.className = 'bullet';
gameArea.appendChild(player.enemyBullet.bullet);
player.enemyBullet.bullet.x = player.enemy.x;
player.enemyBullet.bullet.y = player.enemy.y;
player.enemyBullet.bullet.style.left = player.enemyBullet.bullet.x + 'px';
player.enemyBullet.bullet.style.top = player.enemyBullet.bullet.y + 'px';
player.enemyBullet.bulletInterval = false;
setInterval(function () {
player.enemyBullet.bulletInterval = true;
}, 4000);
}
}
}
** Move Bullet **
function moveBullet() {
let bullets = document.querySelectorAll('.bullet');
bullets.forEach(function (item) {
item.x += 3;
item.y -= 3;
item.style.left = item.x + 'px';
item.style.top = item.y + 'px';
if(item.y < 200){
item.parentElement.removeChild(item);
player.enemyBullet.bullet = null;
}
})
}
** invoked in request Animation function **
function playGame() {
if (player.inplay) {
moveBomb();
moveBullet();
makeBullet();
window.requestAnimationFrame(playGame);
}
}
** Initiate interval boolean here **
let player = {
enemyBullet: {
bulletInterval: true
}
}
** LINK TO JS FIDDLE FULL PROJECT ** (click here to see what's happening)
https://jsfiddle.net/mugs17/j7f12a0n/
You are using setInterval like set timeout. However setInterval does not only execute one time. Once you've called setInterval the first time, calling it again makes a new different interval that also executes every 4 seconds.
So each time your function gets invoked its creating a new Interval which is why your div elements are increasing as time goes on
Instead wrap the entire create bullet code inside setInterval and make it execute only once by setting a boolean conditional and then immediately changing that conditional to false. Like this:
if (player.enemy) {
if (player.enemyBullet.bulletInterval == true) {
player.enemyBullet.bulletInterval = false;
console.log("working");
setInterval(function () {
player.enemyBullet.bullet = document.createElement('div');
player.enemyBullet.bullet.className = 'bullet';
gameArea.appendChild(player.enemyBullet.bullet);
player.enemyBullet.bullet.x = player.enemy.x;
player.enemyBullet.bullet.y = player.enemy.y;
player.enemyBullet.bullet.style.left = player.enemyBullet.bullet.x + 'px';
player.enemyBullet.bullet.style.top = player.enemyBullet.bullet.y + 'px';
}, 4000);
}
}
}

How to stop javascript from executing after clicking stop button?

<script>
function timer(duration, elementId, scoreID, mistakesID){
var start = Date.now();
var min, sec, diff;
var scoreComputed = false;
function timerCompute(){
diff = duration - (((Date.now() - start) / 1000) | 0);
min = ( diff / 60 ) | 0;
sec = ( diff % 60 ) | 0;
//If less than 10, add zero in front of it to keep tens place
min = min < 10 ? "0" + min : min;
sec = sec < 10 ? "0" + sec : sec;
elementId.textContent = min + ":" + sec;
if ( diff <= 0 ){
elementId.textContent = "0:00";
if (!scoreComputed){
score /= (duration / 60);
score = Math.round(score);
scoreComputed = true;
}
scoreID.textContent = score;
document.getElementById("usertext").readOnly = true;
$("#resultsContainer").fadeIn(1500);
if(mistakes.length > 0){
var mistakesStr = "";
for(var i = 0; i < mistakes.length; i++){
mistakesStr += i > 0 ? ", " : "";
usertextArr[mistakes[i]] = usertextArr[mistakes[i]] === "" ? "blank" : usertextArr[mistakes[i]];
mistakesStr += usertextArr[mistakes[i]] + " instead of " + textArr[mistakes[i]];;
}
mistakesID.textContent = mistakesStr;
$("#mistakesContainer").fadeIn(1500);
$('.type-test-wrapper').css("filter","blur(3px)");
}
return;
}
};
timerCompute();
setInterval(timerCompute, 1000);
}
var timerStarted = false;
$('#usertext').on('keydown', function() {
var time = 60 * 0.1,
display = document.querySelector('#time');
scoreDisplay = document.querySelector('#score');
mistakesDisplay = document.querySelector('#mistakes');
if ( timerStarted === false ){
timer(time, display, scoreDisplay, mistakesDisplay);
typeTest();
timerStarted = true;
}
});
</script>
The above script is from a typing test. When the typing test ends, the above script fades in a result box. I was trying to modify the code. I want to add a close button to the result box so that user can close the box after he viewed the result. So I added the below code to close the result box.
<script type='text/javascript'>
jQuery(document).ready(function($){
$('.close-btn, body').click(function(){
$('.type-test-wrapper').css("filter","blur(0px)");
$('#resultsContainer, #mistakesContainer').stop().fadeOut('medium');
});
});
</script>
The problem I am facing is that when I click on close button, the box fades out #resultContainer, #mistakesContainer but as soon the box gets faded, it again fades in. No matter how many times i close the box, it fades in again and again. I want that once user click on close button the box should not get displayed again. How to fix the code so that once the the box fades out, the first code doesn't again fades in the box. I am new at javascript. Thank you for help.
Live webpage here https://htmlpreview.github.io/?https://raw.githubusercontent.com/dp121112/type-testing/master/test.html
I think you're not clearing the interval
try to assing interval as follow.
var intrvl= setInterval(timerCompute, 1000);
and clear it when its done
scoreID.textContent = score;
document.getElementById("usertext").readOnly = true;
$("#resultsContainer").fadeIn(1500);
clearInterval(intrvl);

jQuery: How to properly pause a recursion?

I know there are a lot of questions on the topic, but it seems none of the answers works for me (or maybe I don't see something obvious). I am building a featured content slider that should pause on hover. However, if I move over with the mouse 5-6 times, it goes through the loop 5-6 times at once and it becomes buggy. The previous recursion doesn't stop and a new one is initiated too.
My function:
gravityFeatured.prototype.loop = function(slide) {
// Begin
var self = this;
if(typeof slide == 'undefined') {
slide = 0;
}
self.slidesWrapper.find('.slide-wrapper').removeClass('current next prev');
self.navigation.find('.navigation-item').removeClass('current');
// Current slide
currentSlide = self.slidesWrapper.find('.slide-wrapper[data-slide="' + slide + '"]');
currentNav = self.navigation.find('.navigation-item[data-slide="' + slide + '"]');
// Next slide
var nextSlide = self.slidesWrapper.find('.slide-wrapper[data-slide="' + (slide + 1) + '"]');
var next = slide+1;
if(!nextSlide.length) {
nextSlide = self.slidesWrapper.find('.slide-wrapper[data-slide="0"]');
next = 0;
}
// Prev slide
var prevSlide = self.slidesWrapper.find('.slide-wrapper[data-slide="' + (slide - 1) + '"]');
if(!prevSlide.length) {
prevSlide = self.slidesWrapper.find('.slide-wrapper[data-slide="' + (self.slides.length - 1) + '"]');
}
// Assign classes
currentSlide.addClass('current');
currentNav.addClass('current');
nextSlide.addClass('next');
prevSlide.addClass('prev');
self.scrollNavigation(slide);
// Loop
var timeout = setTimeout(function(){
self.loop(next);
}, self.options['delay']);
self.slidesWrapper.hover(function(){
clearTimeout(timeout);
}, function(){
timeout = setTimeout(function(){self.loop(next);});
});
}
So with the current setup every time you mouseout you trigger a move. Thus in and out 5 times is going to trigger 5 moves. Perhaps better behavious is to pause the countdown while the mouse is in the hovering. This would look something like:
gravityFeatured.countdown = null,
gravityFeatured.isPaused = false,
gravityFeatured.prototype.loop = function(slide) {
...
self.scrollNavigation(slide);
self.countdown = self.options['delay'] * 1000;
var timeout = null; /* need this in loopCheck */
var loopCheck = function() {
if (!this.isPaused)
this.countdown -= 500;
if (this.countdown <= 0)
this.loop(next);
else
timeout = setTimeout(loopCheck,500); /* check every half sec */
}
timeout = setTimeout(loopCheck,500);
self.slidesWrapper.hover(function(){
self.isPaused = true
}, function(){
self.isPaused = false;
});
}
A half second timeout might be a little long, could probably go down to 250ms if necessary. Should handle lots of mouse movement okay though.

How to execute something only once within if-loop?

EDIT (more specific):
I have the following situation. I am building an experimental synthesizer interface with JavaScript. I am using the howler.js plugin to handle audio.
The idea is that a sound is played if a certain condition is met. I have a number stored variable whose value changes via the heading of an iPhone compass.
I use compass.js. It has a variable called heading.
$(function(){
Compass.watch(function (heading) {
$('.degrees').text(Math.floor(heading) + '°');
$('#rotate').css('-webkit-transform', 'rotate(' + (-heading) + 'deg)');
if (heading >= 10 && heading <= 30) {
sound.play("myFirstSound");
}
else if (heading >= 31 && heading <= 60) {
sound.play("mySecondSound");
} else { etc etc...
});
});
Even if heading is constant the .play command is executed not once but over and over again causing the audio engine to run out of memory. How can I execute the commands within the if loops only once? I can not access the value of heading outside the compass function. I always get var heading does not exist error.
Take a Boolean variable like
var checkOnce= false;
if (myVariable >= 10 && myVariable <= 30) {
checkOnce=true;
sound.play("myFirstSound");
}
else if (myVariable >= 31 && myVariable <= 60) {
checkOnce=true;
sound.play("mySecondSound");
} else { etc etc...
In loop check the value of checkOnce. Loop will run till checkOnce=false
Create a boolean flag and play the sound only when false.
var isPlayed = false;
var oldValue = myVariable;
if (myVariable >= 10 && myVariable <= 30 && !isPlayed) {
sound.play("myFirstSound");
isPlayed = false;
}
Then initialize variable when needed... For what you say i guess you will need a variable to compare the values inside the loop and set isPlayed flag to false:
if (myVariable != oldValue)
isPlayed = false;
Just use a boolean variable.
var alreadyPlayed = false;
for(somecondition){
if(alreadyPlayed) continue;
sound.play("myFirstSound");
alreadyPlayed = true;
}
You get the idea.
The boolean value is a good idea. You could also make a use of the onend property of the sound object, so you will know when you can start playing the sound again. Like this:
var playing = false;
sound.onend = function () { playing = false; };
while (condition) {
if (!playing & ...)
...
...
}
Saw your edit to the question, add a delay to the next trigger, the compass might be firing too rapidly. Not familiar with compass.js but as I can see it, it fires per degree, and that is a lot... if you tilt the phone 180degrees thats 180 triggers.
Something like,
setTimeout(function() { your_func(); }, 50);
for a 50ms delay
You can also limit the triggers available from 360 to 36 or less by adding a counter of 10, 1 degree is for 1 count. So it triggers only after 10 degree movement.
$(function(){
var counter = 0;
Compass.watch(function (heading) {
if(counter <=10){
counter++;
}
else{
counter = 0;
$('.degrees').text(Math.floor(heading) + '°');
$('#rotate').css('-webkit-transform', 'rotate(' + (-heading) + 'deg)');
if (heading >= 10 && heading <= 30) {
sound.play("myFirstSound");
}
else if (heading >= 31 && heading <= 60) {
sound.play("mySecondSound");
} else { etc etc...
}
});
});
Add just a small layer of abstraction that will keep track of what's currently playing.
var nameOfSoundPlaying = null;
function play(soundName) {
if (nameOfSoundPlaying == soundName) {
return;
} else {
if (nameOfSoundPlaying != null) {
// stop currently playing sound (if still playing)
...
}
nameOfSoundPlaying = soundName;
sound.play(soundName);
}
}
Then it'll simplify your code :
$(function(){
Compass.watch(function (heading) {
$('.degrees').text(Math.floor(heading) + '°');
$('#rotate').css('-webkit-transform', 'rotate(' + (-heading) + 'deg)');
if (heading >= 10 && heading <= 30) {
play("myFirstSound");
}
else if (heading >= 31 && heading <= 60) {
play("mySecondSound");
} else { etc etc...
});
});

Javascript game - increment fires more than once

I am building simple "Spot the difference" game in jQuery/HTML. There are 5 rounds/stages, each with different pictures and user needs to go through all of them starting from round 1.
I am having this issue with increment firing twice when I am in 2nd round, and then triple times when I am in 3rd round and so on. This cause points to jump up double/triple/... instead of just jump up by 1.
The code is on baby level. I did not make any stuff to refactor it and improve.
I think I don't need to provide HTML for this, as simply looking at logic in JS file should be enough.
For those who prefer pastebin version is here (http://pastebin.com/ACqafZ5G). Full code:
(function(){
var round = 1;
var points = 0;
var pointsTotal = 0;
var pointsDisplay = $(".js-calc");
var pointsTotalDisplay = $(".js-calc-total");
var counterDisplay = $(".js-counter");
var entryPage = $(".entry-page");
var mainMenu = $(".main-menu");
var submitNow = $(".js-now");
var submitResultsFinalBtn = $(".js-submit-results-final");
// rounds-categories
var allRounds = $(".round");
var divRound1 = $(".round1"),
divRound2 = $(".round2"),
divRound3 = $(".round3"),
divRound4 = $(".round4"),
divRound5 = $(".round5");
var allPic = $(".js-pic");
var pic1 = $(".js-pic1"),
pic2 = $(".js-pic2"),
pic3 = $(".js-pic3"),
pic4 = $(".js-pic4"),
picFinish = $(".js-finish");
// on the beginning hide all and leave only entry page
mainMenu.hide();
allRounds.hide();
submitResultsFinalBtn.hide();
// countdown (SEE THE FUNCTION ON THE END)
var myCounter = new Countdown({
seconds: 60, // number of seconds to count down
onUpdateStatus: function(sec){
counterDisplay.html(sec); // display seconds in html
}, // callback for each second
onCounterEnd: function(){
console.log('TIME IS OVER!');
// THIS SHOULD NOT BE HERE, I WOULD PREFER TO MOVE IT SOMEWHERE TO GAME ITSELF
pointsTotalDisplay.html(pointsTotal);
round++; // update to next round
allRounds.hide(); // hide window
mainMenu.show(); // show back again main menu
} // final action
});
var initiateRound = $(".js-initiate");
initiateRound.on("click", function(){ // START GAME
console.log("ROUND " + round + " INITIATED");
points = 0; // reset the points for this round to 0 - not sure this is the way to do it...
console.log(points + " points for this round, " + pointsTotal + " in TOTAL"); // say how many points so far
entryPage.hide();
mainMenu.hide();
allPic.hide();
if( round === 1){
divRound1.show();
pic1.show();
}else if( round === 2){
divRound2.show();
pic2.show();
}else if( round === 3){
divRound3.show();
pic3.show();
}else if( round === 4){
divRound4.show();
pic4.show();
}else if( round === 5){
divRound5.show();
picFinish.show();
initiateRound.hide();
submitNow.hide();
submitResultsFinalBtn.show();
}
counterDisplay.html("60"); //display 60sec on the beginning
myCounter.start(); // and start play time (countdown)
// pointsDisplay.html(points); // display in HTML amount of points for particular round
// if user start collecting points, add them
var mapImage = $('.transparent AREA');
mapImage.each(function(index) {
// When clicked, reveal red circle with missing element
$(this).one("click", function(e) { // YOU CAN CLICK ONLY ONCE!! Using .one() to prevent multiple clicks and eventually scoring more points
e.stopPropagation();
console.log("FIRED");
var theDifference = '#'+$(this).attr('id')+'-diff';
$(theDifference).css('display', 'inline');
if ($(theDifference).data('clicked', true)){ // found circle
// points++;
points += 1;
pointsTotal++;
console.log(points + " points for this round, " + pointsTotal + " in TOTAL");
pointsDisplay.html(points); // display in html amount of points
}
if (points === 6){ // if all points collected (max 6) for this round
myCounter.stop(); // stop countdown
console.log("time stopped, you found all");
setTimeout(function(){ // give him 2sec delay to see last circle marked
allRounds.hide(); // hide window
mainMenu.show(); // show back again main menu
console.log("round " + round + " is finished");
round++; // update to next round
console.log("round " + round + " is activated");
pointsTotalDisplay.html(pointsTotal); // display in HTML total amount of pints
}, 2000);
};
});
});
});
})();
function Countdown(options) {
var timer,
instance = this,
seconds = options.seconds || 10,
updateStatus = options.onUpdateStatus || function () {},
counterEnd = options.onCounterEnd || function () {};
function decrementCounter() {
updateStatus(seconds);
if (seconds === 0) {
counterEnd();
instance.stop();
}
seconds--;
}
this.start = function () {
clearInterval(timer);
timer = 0;
seconds = options.seconds;
timer = setInterval(decrementCounter, 1000);
};
this.stop = function () {
clearInterval(timer);
};
}
Are you sure you're not stacking the $('.transparent AREA') from a round to another ?
This would explain why you score multiple times:
var mapImage = $('.transparent AREA');
mapImage.each(function(index) {
// ...
points++;
// ...
});
Solved!
mapImage.each should be outside of initiateRound

Categories

Resources