java script whack a mole, dynamically removing mole - javascript

I am not sure how to remove a mole at a random timed interval, any thoughts? the instructions are..One of the few tasks which remains is to make the randomly appearing moles, disappear at random! Each randomly added mole should also disappear after a separately random time.
function timeDecrease(){
$("#timer").show();
$("#timer").html(time + " seconds left")
time -= 1;
if (time >0)
{
t = setTimeout("timeDecrease()",1000);
}
else time = 0;
};
function randomMole(min,max){
return Math.floor(Math.random() * (max - min + 1)) + min;
};
function addMole(){
yPos = getY();
xPos = getX();
$("#gamespace").append('<img class= "Image" img src="img/mole.png"
style ="top:'+yPos+'px; bottom:
'+xPos+'px;left:'+xPos+'px;right:'+yPos+'px;"/>');
moreMoles = setTimeout(addMole,randomMole(0,2000));

In your addMole function, store a reference to the new mole and set a timer to remove it.
let newMole = $(`<img
class="Image"
src="img/mole.png"
style="top: ${yPos}px; left: ${xPos}px;"
>`);
$("#gamespace").append(newMole);
setTimeout(newMole.remove.bind(newMole), randomMole(1000, 2000));
moreMoles = setTimeout(addMole,randomMole(0,2000));
We use template literals because they hurt less than concatenating strings. newMole.remove() would remove the new mole from the DOM, but calling it as a setTimeout callback won't work. It would be called by window, so the this keyword would be set to window, but jQuery expects this to be set to the element you're removing. newMole.remove.bind(newMole) gives us a version of newMole.remove with this explicitly set to newMole.

Related

JQuery: Hiding dynamically added images via generated ID

I am trying to make a program in JavaScript that functions similar to a "Whack-a-Mole" game. I have everything figured out except for one thing. I would like to have each "mole" disappear after a brief time if it is not clicked on. The function that generates the moles is shown below. I am not entirely sure how to go about hiding the moles, but I would like to do so by selecting them by a uniquely generated ID, as shown in the code. There is a global variable "count" that is used to generate each ID.
function addMole(){
var yPos = numOne();
var xPos = numTwo();
if (timeLeft > 0){
$("#gamespace").append('<img id="i'+count+'" src="img/mole.gif" style="top:'+yPos+'px;left:'+xPos+'px;" />');
count++;
setTimeout("addMole()", Math.floor(Math.random()*2000));
};
};
I have tried using this function, but it doesn't seem to do anything and I'm not sure how or where to call it or if I'm even using the right selector.
function noMole(){
$("#i"+count).delay(2000).hide();
};
I'd probably go with something like the following:
function addMole() {
var yPos = numOne();
var xPos = numTwo();
if (timeLeft > 0) {
//make a new mole and have a reference to it
var newMole = $('<img src="img/mole.gif" style="top:' + yPos + 'px;left:' + xPos + 'px;" />');
//put the mole in the game
$("#gamespace").append(newMole);
//add another mole in a random amount of time
setTimeout(addMole, Math.floor(Math.random() * 2000));
//remove the created mole after 5 seconds
setTimeout(function(){ newMole.remove(); }, 5000);
};
};
You don't need a lookup. You just need the reference.

Javascript: Countdown by animation.width()

I am currently trying to make a visual countdown for my user for when the animation is finished. My current attempt looks somewhat like this:
function setClassAndFire(){
timer = setInterval(function () {
t--;
$(this).attr('class', 'timerAnimation');
countdownTimer();
if (t === 0) {
clearInterval(timer);
timer = undefined;
funcForCall();
}
}, 1000);
}
function countdownTimer(){
var timerCurrentWidth = $('.timerAnimation').width(),
timerMaxWidth = $("#awardQueueText").width(),
pxPerSecond = timerMaxWidth / 60,
currentCountdown = timerCurrentWidth / pxPerSecond;
currentCountdown = Math.round(currentCountdown);
document.getElementById("timer").innerHTML = "<span style='white-space : nowrap;'>Animation ends in:</br></span>"+
"<span style='white-space : nowrap;'>" + currentCountdown + " sec.</span>";
}
Important to know is that the animation only displays the time until we may be able to send an API call. So the animation will be re-engaged if we have something in queue.
So as you can see my current attempt works, but is some-what cluncky:
The countdown sometimes fails to subtract a second and "fixes"
that with a 2 seconds subtract in the next attempt.
This is probably caused by the Math.round() for currentCountdown, but is there a work around for that? I mean I have the max possible width of the animation object and can seperate it from the current width.
Is there a way to bring it to work? We need to relate the timer to the animation to achive desired behavior. So when the animation count hits 25, I want that the displayed number is 25 as well!
You got this problem because you got the number from the width andh the width can't have decimals (or better, they can be but they are gonna be truncated sometimes).
So my suggestion is to use a differente variable for the number you will show and the width of the DOM element.
It seems to me that the variable t is what I am talking about, so just try to use it.
function setClassAndFire(){
timer = setInterval(function () {
t--; //What is t?
$(this).attr('class', 'timerAnimation');
countdownTimer(t);
if (t === 0) {
clearInterval(timer);
timer = undefined;
funcForCall();
}
}, 1000);
}
function countdownTimer(t){
document.getElementById("timer").innerHTML = "<span style='white-space : nowrap;'>Animation ends in:</br></span>"+
"<span style='white-space : nowrap;'>" + t+ " sec.</span>";
}

javascript variable in foreach loop

I try to have a parallax effect for my sections the speed of the parallax are given in the html with data-Lon1 like this
I get back the data-Lon1 and use it in my parallax function for having diferent speed for the sections
(function(){
var parallax = document.querySelectorAll(".parallax"),
window.onscroll = function(){
[].slice.call(parallax).forEach(function(el,i){
speed = parseFloat($(el).attr('data-lon1'));
var windowYOffset = window.pageYOffset,
elBackgrounPos = "0 " + (windowYOffset * speed) + "px";
el.style.backgroundPosition = elBackgrounPos;
});
};
})();
The sections aren't getting the speed value but if I given a speed value by default it works. How could I get each data-Lon1 section value and have three different speed ?
This is always going to return the same value:
parseFloat($('.parallax').attr('data-lon1'))
Because you're selecting all matching .parallax elements and trying to get one value from all of them, which is likely always going to default to the first in the set.
You probably want to get the value for the specific element being used in that iteration of the loop:
parseFloat($(el).attr('data-lon1'))

jQuery fade in box with unique content

I am making an info screen, and for that, it needs to show reviews from their customers pulled from Trustpilot.
I got the reviews and everything formatted in HTML showing the 20 latest, but I want to present it very sweet. I am not a JavaScript guru, but I thought i would do it using jQuery and its fadein function.
What is want, is have 20 unique divs fading in with X milliseconds difference popping randomly up. By unique I mean, that each div must have unique content. And by randomly popping up, I mean that if box 1 spawns first, then the next should be 5, then 14 etc, and then another cycle the next time around.
Just like what I made here;
$(function() {
var box = $('.box');
var delay = 100;
for (i = 0; i < 30; i++) {
setTimeout(function() {
var new_box = box.clone();
$('.container').append(new_box);
new_box.fadeIn();
}, delay);
delay += 500; // Delay the next box by an extra 500ms
}
});
http://jsfiddle.net/CCawh/5/
Is this even possible, and how would this be done?
I am very new to JavaScript, so please bear with me if I ask to much
Thanks in advance.
EDIT:
The HTML i want to spawn will all be wrapped in divs, so it would go like this;
<div id="one">content</div>
<div id="two">content</div>
<div id="three">content</div>
<div id="four">content</div>
etc.
Made up a nice function for you. I believe this may be what you are looking for
Here's a rundown of how it works :
Populate an array with numbers randomly generated 1-10 in this case.
Run through that array with a set interval, and when everything has
been added stop the interval
pretty straightforward from there. Set the visibility etc. You should be able to change up the function to dynamically add HTML elements and what-not, but just giving you something to start with.
var usedNum = [];
var i, j, y;
i = 0;
for(y = 0; y < 10; y++){
var x = Math.floor((Math.random() * 10) + 1);
if(!isUsed(x)) usedNum.push(x);
else y--;
}
var showInterval = setInterval ( function(){
if(i == 10){
clearInterval(showInterval);
}
$(".container div[data-line='" + usedNum[i] + "']").css({opacity: 0.0, visibility: "visible"}).animate({opacity: 1.0});
i++;
}, 500);
function isUsed(num) {
var used = false;
for(j = 0; j < usedNum.length; j++){
if(usedNum[j] == num){
used = true;
}
}
return used;
}
Demo fiddle : http://jsfiddle.net/xS39F/3/
Edit:
You can also mess around with the speed of the animation. In this demo (http://jsfiddle.net/adjit/XYU34/1/) I set the speed to 1000 so the next element starts fading in before the last element was done fading in. Makes it look a little smoother.
Instead of using a for loop and setTimeout, would setInterval work better for what you need? Some HTML might help better understand what you're trying to achieve.
$(function() {
var box = $('.box');
var delay = 100;
var interval = setInterval(function() {
var new_box = box.clone();
$('.container').append(new_box);
new_box.fadeIn();
}, delay);
delay += 500; // Delay the next box by an extra 500ms
}, delay);
});

Javascript delete div Element

I am implementing a Stopwatch in JavaScript.
I want to delete additional div elements when pushing a clear button. I added function cc();, but function cc() doesn't work. What's wrong with my code?
Javascript:
a = 0;
myButton = 0;
function myWatch(flug) {
if(myButton == 0) {
Start = new Date();
myButton = 1;
document.myForm.myFormButton.value = "Stop!";
myInterval = setInterval("myWatch(1)", 1);
} else {
if(flug == 0) {
myButton = 0;
document.myForm.myFormButton.value = "Start";
clearInterval(myInterval);
}
Stop = new Date();
T = Stop.getTime() - Start.getTime();
H = Math.floor(T / (60 * 60 * 1000));
T = T - (H * 60 * 60 * 1000);
M = Math.floor(T / (60 * 1000));
T = T - (M * 60 * 1000);
S = Math.floor(T / 1000);
Ms = T % 1000;
document.myForm.myClick.value = H + ":" + M + ":" + S + ":" + Ms;
}
}
b = 0;
function stop() {
b++;
stopa();
}
function stopa() {
var element = document.createElement('div');
element.id = pos;
var objBody = document.getElementsByTagName("body")
.item(0);
objBody.appendChild(element);
rap = "";
rap = "rap" + b + "=" + H + ":" + M + ":" + S + ":" + Ms;
element.innerHTML = rap;
}
function cc() {
document.body.removeChild(element);
}
HTML:
<form name="myForm" action="#">
<input type="text" size="20" name="myClick">
<input type="button" value="Start" name="myFormButton" onclick="myWatch(0)" />
<input type="button" value="Rap" name="Rap" onclick="stop()">
<input type="button" value="clear" name="clear" onclick="cc()">
</form>
<h3>
<div id="pos">
</div>
</h3>
Try to pass the context explicitly as parameter on the cc() function.
js
function cc(el) {
el.parentNode.removeChild(el);
}
html
<input type="button" value="clear" name="clear" onclick="cc(this)">
Open up your Console. It's found in most major browsers and will help you loads with JS development.
For example, if you look at your code exactly as is, you get an error:
Uncaught ReferenceError: element is not defined
As several have said, it's a variable scope issue. There's a few easy fixes, the easiest being simply making element have a larger scope - that is, define it outside of your functions first.
var element = null;
and then in stopa, don't use var because it'll make a new, local variable instead of using the global one.
element = document.createElement('div');
The next problem you'll notice is that element in cc still doesn't refer to the correct element - this is because in the following line, pos is not defined.
element.id = pos;
Again, take a look at the Console (now more specifically at the HTML section than the JS, but it's in the same developer options). You'll notice the created element's ID is [object HTMLDivElement] - not "pos". I'd recommend not even worrying about giving them ids, you have a div with id pos already in your HTML, simply append your results to that instead of the body.
objBody = document.getElementById("pos");
Then when you clear, clear all children from pos (you'll also want to clear the text box I'm sure, so here ya go)
while (objBody.hasChildNodes()) {
objBody.removeChild(objBody.lastChild);
}
document.myForm.myClick.value = "";
Notice now we no longer need element to be global, because it's only referenced in one function - it can be local to that function. However, objBody is now referenced in stopa and cc, so we'll make it global as we did with element and simply ensure all future references to it don't include var.
var element = null;
Add some error checking (clearing before you click Start causes errors, for example) and you're good to go!
http://jsfiddle.net/daCrosby/MMywX/1/
The function cc has no idea what 'element' is. The easiest way to fix this is to use jquery. When you delete the div, do something like
$('#pos').remove()
This finds the div with id 'pos' and removes it. You may need to pass the id of the div to cc if it's not just 'pos'.
Modern browsers supports remove() method on the element. You don't need to use external libraries as jQuery or long code. It's simple as :
var x = document.getElementById("myElement");
x.remove();
Working exemple here -> https://jsfiddle.net/tmj3p7t5/

Categories