Dynamically changing images in the DOM - javascript

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

Related

Javascript - Hide a tooltip after N seconds, but on my script

I'm trying to show a tooltip at the same time that my current script shows a div (gift) if a condition is met:
if(total > 999 && total < 2999) { $('#gift-1').show();
The same goes for #gift-2 :
if(total > 3000 && total < 4500) { $('#gift-2').show();
At that moment the corresponding tooltip should be visible:
#gift-1 = .tooltip-1
#gift-2 = .tooltip-2
And these should be shown only for 9 seconds, then disappear until the div ( #gift -1 or the div #gift-2 ) is shown again:
I tried something like this, but it has not worked for me:
if(total > 999 && total < 2999) { $('#gift-1').show();
$('.tooltip-1').fadeOut('slow');},9000);
I am learning JS (novice, level 0) and the truth is that I do not know
how I should approach this issue.
Any ideas...?
Thank in advance!
//-------------
HTML
<div class="tooltip-1"></div>
<div class="tooltip-2"></div>
<div id="gift-1"></div>
<div id="gift-2"></div>
CSS
.tooltip-1,.tooltip-2 {display:none}
Script
$(document).ready(function(){
function manageRegalo() {
var totalStorage = Number(localStorage.getItem("total"));
var total = Number($("#total").val().replace(".",""));
if(totalStorage != null && total === 0) {
total = totalStorage;
}
if(total > 999 && total < 2999) {
$('#gift-1').show();
}
else{
$('#gift-1').hide();
}
}
$(document).on('click', function (event) {
const target = event.target;
if (target.matches('.comp-clone') || target.matches('.bbp')) {
manageRegalo();
localStorage.setItem('total', Number($("#total").val().replace(".","")));
}
});
manageRegalo();
});
// -------------------------------------------------
$(document).ready(function(){
function manageRegaloDos() {
var totalStorage = Number(localStorage.getItem("total"));
var total = Number($("#total").val().replace(".",""));
if(totalStorage != null && total === 0) {
total = totalStorage;
}
if(total > 3000 && total < 4500) {
$('#gift-2').show();
}
else{
$('#gift-2').hide();
}
}
$(document).on('click', function (event) {
const target = event.target;
if (target.matches('.comp-clone') || target.matches('.bbp')) {
manageRegaloDos();
localStorage.setItem('total', Number($("#total").val().replace(".","")));
}
});
manageRegaloDos();
});
it is a bit difficult to exactly grasp all of your question. A fiddle (jsfiddle.net) is always helpful so maybe next time you can make one.
However, if I understand your question correctly the problem is not showing the tooltip but fading it out after 9 seconds, right?
I think you can change this code:
if(total > 999 && total < 2999) {
$('#gift-1').show();
$('.tooltip-1').fadeOut('slow');
},9000);
... to this code: (actually your code probably will produce a syntax error?):
if(total > 999 && total < 2999) {
$('#gift-1').show();
$('#tooltip-1').show(); // Maybe you did this already then you don't need this line.
window.setTimeout(function(){
$('.tooltip-1').fadeOut('slow');
},9000);
}
EDIT: To respect the additional info that a tooltip should only show once there are various ways to go. One would be to store the tooltips in eg. a window. variable. The other would be via CSS classes. I use CSS classes here (this is untested code):
if(total > 999 && total < 2999) {
$('#gift-1').show();
if (!$('#tooltip-1').hasClass('alreadyShown')) {
$('#tooltip-1').show().addClass('alreadyShown');
window.setTimeout(function(){
$('.tooltip-1').fadeOut('slow');
},9000);
}
}

classList and scroll event

I have some simple script to adding classes to my navbar relied on pageYOffset:
var navContainer = document.querySelector('.nav-container');
var firstTitle = document.querySelector('.first-title')
document.addEventListener('scroll',function(){
if(window.pageYOffset < 75){
navContainer.classList.remove('nav-action','yellow');
}else if(window.pageYOffset > 75){
navContainer.classList.add('nav-action')
}else if(window.pageYOffset<firstTitle.offsetTop){
navContainer.classList.remove('yellow');
}
else if(window.pageYOffset > firstTitle.offsetTop){
navContainer.classList.add('yellow');
};
});
my trouble is this that last condition is fulfilled when window.pageYOffset is bigger than firstTitle.offsetTop, writing this line between brackets in the console returns true, but nothing happens when I'm trying this all code.
Unless window.pageYOffset === 75, none of these lines will actually be executed. The previous conditions already catch all the cases.
I would suggest treating nav-action and yellow separately:
var navContainer = document.querySelector('.nav-container');
var firstTitle = document.querySelector('.first-title')
document.addEventListener('scroll', function() {
if (window.pageYOffset < 75) {
navContainer.classList.remove('nav-action');
} else {
navContainer.classList.add('nav-action')
}
if (window.pageYOffset < firstTitle.offsetTop) {
navContainer.classList.remove('yellow');
} else {
navContainer.classList.add('yellow');
}
});

Why isn't my function called after DOMContentLoaded?

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

Trying to debug a custom .sort in a JS array

A link to the Plunker.
I've been working on a button and list system in jQuery for awhile now. Recently I decided to make my code more reproducible. I want to make it so I just have to add classes or IDs, and I don't have to add any additional code. I'm very close to doing that for my entire site. So if you go to this site specifically you will see it in action.
If you click on any buttons, in any order, it will arrange chronologically.
The bugs come from closing them.
If you click at least three, close the middle one, then click a new button, the sort function falls apart and that closed middle one is now floating with the wrong class.
Below is my current jQuery. On my site, ignore the "All Years" button. I'll work on that after I figure out this bug.
//the variables needed for the floating buttons
var groupArray = $(".yearGroup");
var buttonArray = $(".buttonGroup");
var hideGroupArray = $(".hideGroup");
var closeBarArray = $(".closeBar");
var closeBar = $("#allCloseBar");
var allButtonArray = [];
sortElements = function(a,b)
{
if (a.text() < b.text())
{
return -1;
}
else if (a.text() > b.text())
{
return 1;
}
else
{
return 0;
}
}
$.each(buttonArray, function(i, item) {
$(this).click(function(){
console.log($(buttonArray[i]).text())
console.log($(closeBarArray[i]).text())
//for removing the tooltip when the button is clicked. Mostly for Firefox bug
$(".ui-tooltip-content").parents('div').remove();
$(hideGroupArray[i-1]).slideToggle(slideToggleDuration, function(){
htmlBody.animate({scrollTop: $(groupArray[i-1]).offset().top - 25}, {duration: timeDuration, easing: 'easeOutBack'});
$(buttonArray[i]).toggleClass("float", 1200);
if ($(groupArray[i-1]).height() > 0)
{
//This will stop any animations if the user scrolls.
htmlBody.bind("scroll mousedown DOMMouseScroll mousewheel keyup", function(e)
{
if ( e.which > 0 || e.type === "mousedown" || e.type === "mousewheel"){
htmlBody.stop().unbind('scroll mousedown DOMMouseScroll mousewheel keyup');
}
});
closeBar.addClass("floatCloseBar");
$(closeBarArray[i]).hide();
allButtonArray.splice(0, 0, $(buttonArray[i]));
var timer;
var delay = 1500;
$(buttonArray[i]).hover(function() {
//This will stop any animations if the user scrolls.
htmlBody.bind("scroll mousedown DOMMouseScroll mousewheel keyup", function(e)
{
if ( e.which > 0 || e.type === "mousedown" || e.type === "mousewheel"){
htmlBody.stop().unbind('scroll mousedown DOMMouseScroll mousewheel keyup');
}
});
var link = $(groupArray[i-1]);
var offset = link.offset();
var top2 = offset.top;
var left = offset.left;
var bottom = top2 + $(groupArray[i-1]).outerHeight();
//bottom = Math.abs(bottom - offset.top);
var right = $(window).width() - link.width();
right = Math.abs(offset.left - right);
var scrollDuration = 0;
if (inRange($(buttonArray[i]).offset().top, $(groupArray[i-1]).position().top, bottom))
{
//console.log("fast");
scrollDuration = 500;
//$(group).addClass("hoverYear");
}
else if ($(buttonArray[i]).offset().top <= $(groupArray[i-1]).offset().top && allButtonArray.length == 1)
{
//console.log("fast");
scrollDuration = 500;
//$(group).removeClass("hoverYear");
}
else if ($(buttonArray[i]).offset().top > 495 && $(buttonArray[i]).offset().top < 1700 && !inRange($(buttonArray[i]).offset().top, $(groupArray[i-1]).position().top, bottom))
{
scrollDuration = 1000;
//console.log("slow");
//$(group).removeClass("hoverYear");
}
else if ($(buttonArray[i]).offset().top > 1701 && $(buttonArray[i]).offset().top < 3000 && !inRange($(buttonArray[i]).offset().top, $(groupArray[i-1]).position().top, bottom))
{
scrollDuration = 1500;
//console.log("slower");
//$(group).removeClass("hoverYear");
}
else if ($(buttonArray[i]).offset().top > 3001 && $(buttonArray[i]).offset().top < 6000 && !inRange($(buttonArray[i]).offset().top, $(groupArray[i-1]).position().top, bottom))
{
scrollDuration = 2000;
//console.log("much slower");
//$(group).removeClass("hoverYear");
}
else if ($(buttonArray[i]).offset().top > 6001 && !inRange($(buttonArray[i]).offset().top, $(groupArray[i-1]).position().top, bottom))
{
scrollDuration = 2500;
console.log("the slowest");
//$(group).removeClass("hoverYear");
}
else
{
scrollDuration = 500;
}
//to prevent the various hover states to take control when the button isn't floating
if (!($(buttonArray[i])).hasClass("float"))
{
scrollDuration = 0;
console.log("doesnt have class")
}
// on mouse in, start a timeout
timer = setTimeout(function() {
//the delay for the hover scroll feature
htmlBody.animate({scrollTop: $(groupArray[i-1]).offset().top}, scrollDuration, 'easeInOutCubic');
}, delay);
}, function() {
// on mouse out, cancel the timer
clearTimeout(timer);
});
$.each(allButtonArray, function(j, val){
$(allButtonArray[j]).appendTo(closeBar);
console.log(allButtonArray.length);
arrowDown.show();
arrowUp.show();
arrowDown.prependTo(closeBar);
arrowUp.appendTo(closeBar);
//Changes the width of the buttons based upon how many are on the screen
if (allButtonArray.length > 7)
{
$("float").css('width', '7%');
$(val).css('width', '7%');
$(allButtonArray[0]).css('width','7%');
allButtonArray.sort(sortElements);
//console.log(val);
}
else if (allButtonArray.length <= 7)
{
$(val).css("width", '10%');
$("float").css("width", '10%');
allButtonArray.sort(sortElements);
//console.log(val);
}
});
}
if ($(groupArray[i-1]).height() == 0)
{
$(buttonArray[i]).css("width", '50%');
allButtonArray.splice(allButtonArray.indexOf($(buttonArray[i])), 1);
console.log(allButtonArray.length);
$(closeBarArray[i]).show();
$(buttonArray[i]).appendTo($(closeBarArray[i]));
arrowDown.show();
arrowUp.show();
arrowDown.prependTo(closeBar);
arrowUp.appendTo(closeBar);
}
if (group2001.height() == 0 && group2002.height() == 0 && group2003.height() == 0 && group2004.height() == 0 && group2005.height() == 0 && group2006.height() == 0 && group2007.height() == 0
&& group2008.height() == 0 && group2009.height() == 0 && group2010.height() == 0 && group2011.height() == 0 && group2012.height() == 0)
{
$(closeBarArray[i]).removeClass("floatCloseBar");
htmlBody.animate({scrollTop: revealAllButton.offset().top - 75}, 500);
arrowDown.hide();
arrowUp.hide();
//console.log($(document).height() + " the current height");
}
});
$(buttonArray[i]).toggleClass("openClose");
$(buttonArray[i]).toggleClass("openClose2");
});
});
function inRange(x, min, max){
return (x >= min && x <= max);
}
If you would like a reference to what worked previously, I could post that code. It is much more bulky and much less organized. I've tried many different things to eliminate the bug but I'm at a loss. My knowledge of JS scope is limited.
And thanks for any help, it is very much appreciated.

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

Categories