Why isn't my function called after DOMContentLoaded? - javascript

Ive created this jFiddle to demonstrate:
https://jsfiddle.net/t5Lgwvzg/5/
I have a function that changes the colours of a few svg polygons I've made. When I run this locally with Chrome/Firefox, the colours load as expected. But when I run it with Internet Explorer/JSFiddle the polygons remain white they're original colour. My question is why isn't this working? I've spent hours trying to figure it out . . .
Here's my function:
function statColor() {
var random;
document.getElementById("print").innerHTML = "Enter";
for (var i = 0; i < counties.length; i++) {
random = (Math.random() * 100);
elem = document.getElementById(counties[i]);
if (random >= 0 && random <= 25) {
elem.style.fill = "green";
} else if (random > 25 && random <= 50) {
elem.style.fill = "yellow";
} else if (random > 50 && random <= 75) {
elem.style.fill = "orange";
} else if (random > 75 && random <= 100) {
elem.style.fill = "red";
}
}
document.getElementById("polyNorthernIreland").style.fill = "grey";
}
And this is where it should be called:
document.addEventListener("DOMContentLoaded", statColor, false);
Should have also mentioned I'm using IE11

Use attachEvent() , addEventListener() doesn't work on IE less than 9.0

Related

How can I get setInterval() to increase by 1 instead of 12?

My game has two players that get random numbers, and the person who has the bigger number gets 1 "win". My while loop is for the "auto-roll" button, and instead of clicking "roll dice" each time, auto-roll will do it for you until one player has wins == game limit # (bestof.value). No matter where I put my setInterval it increases by a bunch at a time. If bestof.value = 10 then each interval displays at least 10 wins for one player at a time.
checkBox.checked = input checkmark that enables auto-roll feature. So this setInterval will only be active while the auto-roll loop is active.
Anyways, what am I doing wrong?
button.addEventListener("click", myFunction);
function myFunction() {
let random = Math.floor((Math.random() * 6) + 1);
let random2 = Math.floor((Math.random() * 6) + 1);
screenID.innerHTML = random;
screenIDD.innerHTML = random2;
if (random > random2){
winNumber.innerHTML = ++a;
} else if(random2 > random){
winNumba1.innerHTML = ++b;
} else {
console.log("Draw");
}
if (a > b){
winNumber.style.color = 'white';
winNumba1.style.color = 'black';
} else if(b > a){
winNumba1.style.color = 'white';
winNumber.style.color = 'black';
} else {
winNumber.style.color = 'black';
winNumba1.style.color = 'black';
}
if (checkBox.checked){
setInterval(myFunction, 2000)
while(a < bestof.value && b < bestof.value){
myFunction();
}};
if (winNumba1.innerHTML == bestof.value){
winAlert.style.display = "flex";
console.log('winNumba1 wins!');
} else if (winNumber.innterHTML == bestof.value){
winAlert.style.display = "flex";
console.log('winNumber wins!');
} else {}
};
I wrote a simplified js only version of your game here since I don't have html at hand, but I am sure you can adjust it to your environment.
Main difference: I check if someone won and use return to stop the function
If no one won and autoplay is activated I autoplay after 500ms again.
let playerA = 0
let playerB = 0
let autoPlay = true
let bestOf = 3
function myFunction() {
let random = Math.floor((Math.random() * 6) + 1);
let random2 = Math.floor((Math.random() * 6) + 1);
console.log("New Round " + random + " vs " + random2)
if (random > random2) {
playerA++
} else if (random2 > random) {
playerB++
} else {
console.log("Draw");
}
if (playerA > playerB) {
console.log("a is winning")
} else if (playerB > playerA) {
console.log("b is winning")
} else {
console.log("There has been a draw")
}
if (playerA == bestOf) {
console.log('A won');
return
} else if (playerB == bestOf) {
console.log('B won');
return
}
if (autoPlay) {
setTimeout(myFunction, 500)
};
};
myFunction()

Why does my setInterval seem to run one last time after an alert message?

I am writing a simple n-back game, and at the end of a session I have an alert message popping up to tell the user their n-back level is being increased if they score 75% or better. For some reason though, after the user clicks OK or hits enter, the setInterval function seems to be running through one more time. On the grid I have created, one more square lights up, even though the session is supposed to be over. I will post the relevant game code below:
$('#start').click(function()
{
let counter = 0;
message_switch = true;
$('#start').blur();
$('#score-output').text(0);
$('#percentage').text('%');
var intervalID = setInterval(function()
{
counter++;
show_card(get_cardID(cardIDs));
if (counter === 30)
{
window.clearInterval(intervalID);
message_switch = false;
var score = Math.round((playerMatches.length / matches.length) * 100);
score = score - (error_count * 3);
update_score(score);
if (score < 50)
{
if (n_back < 2)
{
n_back = 1;
} else {
n_back = n_back - 1;
}
} else if (score < 75 && score >= 50)
{
n_back = n_back;
} else if (score >= 75) {
n_back = n_back + 1;
};
$('#nback').text(n_back);
reset_game_values();
if (score >= 75) //here there is some issue
{
window.alert("Congratulations, you will move up to " + n_back + " back.");
score = 0;
return;
} else {
score = 0;
}
}
}, 3500);
})
I know this is a lot of code and there is also a lot of code I haven't provided, mainly just in an attempt to be brief. Does anyone see anything obvious that I am not seeing? If you feel you need to see more of the program I can provide it. Thanks.

Dynamically changing images in the DOM

I'm trying to add a health meter representation to a game I'm working on and stuck on a DOM manipulation problem. The idea is that there is an image that deteriorates in various stages as the player loses health. Here is an example of what I have so far.
var healthDisplay = document.getElementById('healthDisplay');
if (heroHealth > 75) {
healthDisplay.src = 'image1.png';
} else if (heroHealth < 75 || heroHealth > 30){
healthDisplay.src = 'image2.png';
} else {
healthDisplay.src = 'image3.png';
};
That's just the basics of it. My question is about the next step. What do I add to make it so the script is constantly checking to see if these parameters are true or false? Would it be best to put it in a while loop, or add an event listener?
You'd want to put it in a setinterval.
//this is assuming that heroHealth, and healthDisplay
//are available to this function already
//either through closure or they are global
//variables etc.
function checkHealth () {
if (heroHealth > 75) {
healthDisplay.src = 'image1.png';
} else if (heroHealth < 75 && heroHealth > 30){
healthDisplay.src = 'image2.png';
} else {
healthDisplay.src = 'image3.png';
};
}
setInterval(checkHealth, 100);
The setInterval calls a function repeatedly at certain intervals. This example is set to 100 milliseconds. This way as the hero's health goes up and down, the image src will change as the function fires.
Depending on how your game is set up and how the health is stored, you could wire up the function to an on change event:
<input type="textbox" id="heroHealthCheckBox"
onchange="checkHeroHealth(this.value)"/>
function checkHeroHealth(health) {
var heroHealth = parseInt(health);
if (heroHealth > 75) {
healthDisplay.src = 'image1.png';
} else if (heroHealth < 75 && heroHealth > 30){
healthDisplay.src = 'image2.png';
} else {
healthDisplay.src = 'image3.png';
}
}
I also changed the second conditional from
heroHealth < 75 || heroHealth > 30
to this
heroHealth < 75 && heroHealth > 30

Change DIV Background Color, Depending on Its Width

I'm wanting to use jQuery to dynamically modify the background color of a <div>, based on its CSS property, width value.
The usage is for some form of color-coded meter, which indicates how well (or poorly) a device performs in a specific category (there are 5), and then there is one 'overall' category, which produces the overall score, based on a little math (add all 5 together and divide the answer by 5).
I have tried two methods, one based on the little jQuery knowledge I have, and the other adapted from an answer on SO. Both are included in the JSFiddle I have provided, with the latter commented out.
Here are the colors and the ranges of the widths for each:
0-24% = red - #a41818
25-49% = orange - #87581c
50-74% = yellow - #997815
75-90% = yellowgreen - #7ba01c
91-100% = green - #3a8d24
Thanks!
I'd suggest:
$('.rating-bar').css('background-color', function(){
var percentage = parseInt($(this).data('size'), 10);
if (percentage > 0 && percentage < 25){
return '#a41818'
}
else if (percentage > 24 && percentage < 50) {
return '#87581c';
}
else if (percentage > 49 && percentage < 75) {
return '#997815';
}
else if (percentage > 74 && percentage < 90) {
return '#7ba01c';
}
else if (percentage > 89 && percentage <= 100) {
return '#3a8d24';
}
});
JS Fiddle demo.
There were a few semantic problems ($(e) used instead of $(this), ($(document).ready nested strangely), and the logic you've used requires the ratio of each bar's width to the parent bar, not the width itself.
Try this: http://jsfiddle.net/VFSUN/1/
$(document).ready(function () {
var bar = $('.rating-bar');
bar.css("background-color", "#7ba01c");
var parentWidth = parseInt($('.rating-bar-bg').css("width"));
$('.rating-bar').each(function () {
var e = $(this).css("width");
e = parseInt(e);
ratio = e / parentWidth * 100;
if (ratio <= 24) {
$(this).css("background-color", "#a41818");
} else if (ratio >= 25 && e < 50) {
$(this).css("background-color", "#87581c");
} else if (ratio >= 50 && e < 75) {
$(this).css("background-color", "#997815");
} else if (e >= 75 && e < 91) {
$(this).css("background-color", "#7ba01c");
} else if (ratio >= 91) {
$(this).css("background-color", "#3a8d24");
}
});
});
I suggest you are starting at wrong point by checking width, when in fact you need to be setting width based on the data-size attribute. This size can then be used to set bckground color
$(document).ready(function() {
$('.rating-bar').each(function(){
var $bar=$(this), size=$bar.data('size');
$bar.width(size+'%').css("background-color", getBackground( size))
});
});
function getBackground( e){
var color= "#a41818";/* < 24*/
if (e >= 25 && e < 50) {
color= "#87581c";
} else if (e >= 50 && e < 75) {
color= "#997815";
} else if (e >= 75 && e < 91) {
color= "#7ba01c";
} else if (e >= 91) {
color= "#3a8d24";
}
return color
}
DEMO

Javascript - Repeated if-statements don't work

My code works (doesn't fail), but it doesn't do the right thing.
I call the "generate" function every time i want to generate a new "chunk", passing a new number into the function each time its called. It generates the chunk fine, but it doesn't generate what I want it to generate.
I want it to generate either a space, a jump, a slide, or a gap, if the previous generation was a space. But if the previous generation wasn't a space, generate a space.
It doesn't do that. It sometimes generates 2 gaps, 2 jumps, or 2 slides after each other and i have no idea why... ???
Here is my code:
var ptg = 'space'; // what was previously generated to top
var wtgt; // what is currently being generated to top
var chunktogenerateto = 0;
function generate(a){
chunktogenerateto = a;
var rand1 = Math.floor(Math.random()*100) + 1;
if(ptg == 'space' && rand1 <= 25){
wtgt = 'space';
}
else if(ptg == 'space' && rand1 <= 50 && rand1 > 25){
wtgt = 'jump';
}
else if(ptg == 'space' && rand1 <= 75 && rand1 > 50){
wtgt = 'slide';
}
else if(ptg == 'space' && rand1 > 75){
wtgt = 'gap';
}
else{
wtgt = 'space';
}
ptg = wtgt;
topGen(wtgt);
}
function topGen(g){
document.getElementById('t' + chunktogenerateto).setAttribute('src','images/terrain/t' + g + '.png');
}
I hope it's not a typo... HELP!
Where the calls to "generate" are coming from:
var chunkpos = new Array();
chunkpos[0] = -100;
chunkpos[1] = 0;
chunkpos[2] = 100;
chunkpos[3] = 200;
chunkpos[4] = 300;
chunkpos[5] = 400;
chunkpos[6] = 500;
chunkpos[7] = 600;
chunkpos[8] = 700;
chunkpos[9] = 800;
chunkpos[10] = 900;
chunkpos[11] = 1000;
var temppos = new Array();
var time1;
var millis1;
var time2;
var millis2;
var millis3;
var firstreset = true;
var pos;
var poschange;
function moveLevel(){
if(firstreset == true){
resetTime();
}
var time2 = new Date();
var millis2 = time2.getTime();
var millis3 = millis2 - millis1;
poschange = Math.floor(millis3 / 5);
for(i = 0; i < chunkpos.length; i++){
temppos[i] = chunkpos[i] - poschange;
if(temppos[i] <= -150){
generate(i);
temppos[i] += 1200;
}
pos = temppos[i];
document.getElementById('chunk' + i).setAttribute('style','left: ' + pos + 'px;');
}
}
function resetTime(){
time1 = new Date();
millis1 = time1.getTime();
if(firstreset != true){
for(i = 0; i < chunkpos.length; i++){
chunkpos[i] = temppos[i];
}
}
firstreset = false;
setTimeout('resetTime()',1000);
}
Where the calls to "moveLevel" are coming from:
window.onload = function(){
if(test = 'runnable')
{
gameLoop();
}
else
{
document.getElementById('gm').innerHTML = (gm + 'Failed to run game.');
}
}
function gameLoop(){
if(currentscreen == 'playing'){
moveLevel();
}
setTimeout('gameLoop()',0);
}
Here is a download link to a zip file containing all of the code:
ParkourFreak.zip
The code i'm having trouble with is under scripts/generation.js.
The main game page (where the generation is visible is index.html.
Rather than each if statement starting with "if(ptg == 'space' ... etc" - do this first in one simple "if not space return space".
After that you can start on your random - that should work for you.
Roughly a quarter of the time you previously had a space, it will create another, because of this code:
if(ptg == 'space' && rand1 <= 25){
wtgt = 'space';
}
Note that it's creating a space when a space was previously created.
Side note:
There's no need for the && rand1 > 25 on this line:
else if(ptg == 'space' && rand1 <= 50 && rand1 > 25){
Since you previously had if(ptg == 'space' && rand1 <= 25){, it's impossible as of that line for rand1 to be <= 25 when ptg == 'space'.
(And similarly the && rand2 > 50 on the following condition.)
Are you sure you're incrementing chunktogenerateto?
It appears to stay at 0 with the current code, is that in a segment you haven't shown?
Edit: oh, it's the argument of the function. Try logging that variable, maybe that's the problem?
// elsewhere
var wtgts = ['space','jump','slide','gap'];
// in the function
if(ptg !== 'space') {
wtgt = 'space';
} else {
var randidx = Math.floor(Math.random()*4);
wtgt = wtgts[randidx];
}
Or even in the function:
var newidx = (ptg == 'space') ? Math.floor(Math.random()*4) : 0;
wtgt = wtgts[newidx];
The weights were equal, so just pick a random index from 0 to 3 and use that to pick an action from an array.
Separate the logic for ptg being space so that you only test for it once
Consider denoting the actions as numbers instead of strings, as the assignment, comparison etc will be faster and more robust.
I thought the problem lied with the generation, when in fact all I had to do to solve it was to change this:
if(temppos[i] <= -100){
generate(i);
temppos[i] += 1200;
}
to this:
if(temppos[i] <= -100){
generate(i);
chunkpos[i] += 1200;
temppos[i] += 1200;
}

Categories