I want to change the coilor of a button on mouse click from white to red then from red back to white if click again. I tried like this:
<script language="JavaScript">
<!--
function changecolor(Id){
var series = "0";
var a = window.getComputedStyle(document.getElementById(Id)).backgroundColor;
var b = 2
if (a == "#FF4F4F") {
b = 1
}
if (b == 1) {
document.getElementById(Id).style.backgroundColor = "#FFFFFF";
}
if (b == 2) {
document.getElementById(Id).style.backgroundColor = "#FF4F4F";
}
}
//-->
</script>
It won't work. This will make the button go red in mozilla, chrome but it won't click back to white. IE says "error in page". The button HTML code is:
<input type = "button" Id = "01" value="01" onClick="changecolor('01')">
Something missing from my CSS styles. It looks like the first read (of the colour) is a null value but it does makes the button go red -in the two browsers- the way this function of mine is constructed. Then it looks like the if condition is not working properly, to see the red and make it white.
The computed style of a background colour is of the format rgb(###, ###, ###) (or variations thereof, such as different whitespace or rgba) Therefore comparing with #xxxxxx will not work.
Since you're assigning to style.backgroundColor, you can simply read back:
var elem = document.getElementById(Id);
if( elem.style.backgroundColor == "#FF4F4F") {
elem.style.backgroundColor = "#FFFFFF";
}
else {
elem.style.backgroundColor = "#FF4F4F";
}
Feel free to switch the cases around as needed (based on how it should change the first time), but this will work because the browser will keep whatever you assigned to it.
However, in general, you should have a more reliable toggle:
var elem = document.getElementById(Id);
if( elem._toggle) {
elem.style.backgroundColor = "#FFFFFF";
}
else {
elem.style.backgroundColor = "#FF4F4F";
}
elem._toggle = !elem._toggle;
This will toggle reliably.
Related
I have a web app that outputs the results of a function as a double. The function compares two text documents and returns the percentage indicating the percentage of similarity between the two documents. When the user clicks a Compare button, the function runs and takes the user from the compare.jsp page to the results.jsp page, and displays a loading-bar that is filled in like so:
<div id="levenshtein-distance"
class="ldBar label-center levenshtein-distance"
data-preset="fan"
data-value="${result.percentage}"
data-stroke="">
</div>
This works fine, the fan bar gets the correct percentage. However, I am also trying to color the fan bar using the data-stroke value based on this percentage. I have a simple javascript function to do this, but can't figure out how to pass the value. I've tried running the function in the body tag of the results.jsp page using "onload", but this doesn't work. Here is my JavaScript function:
function barSetLD(percent) {
var red = "red";
var green = "green";
var orange = "orange";
var elem = document.getElementById("levenshtein-distance");
if (percent <= 40.00) {
elem.setAttribute("data-stroke", green);
} else if (percent > 40.00 && percent <= 70.00) {
elem.setAttribute("data-stroke", orange);
} else {
elem.setAttribute("data-stroke", red);
}
}
I've done quite a bit of searching and can't seem to find an example that helped me solve this. Any help is very much appreciated.
////Update:
Trinh, that worked to change the color, thanks! My problem now is that I do, in fact, have multiple 'levenshtein-distance' ids and I am looping through them. So currently everything is being set to the same color. I should have mentioned this initially, sorry. I am comparing multiple pairs of files and outputting the loading-bar for each pair. If you have some idea about how to resolve the looping issue, that would be great, but thanks for the original solution either way! I updated my javascript function as follows:
function barSetLD(percent) {
var red = "red";
var green = "green";
var orange = "orange";
var elem = document.querySelectorAll("[id^=levenshtein-distance]");
for (var i in elem) {
if (percent <= 40.00) {
elem[i].setAttribute("data-stroke", green);
} else if (percent > 40.00 && percent <= 70.00) {
elem[i].setAttribute("data-stroke", orange);
} else {
elem[i].setAttribute("data-stroke", red);
}
}
}
And the full bit of code with the html loop is, and I am now calling the barSetLD(percent) at the very bottom of the page as you suggested:
<c:forEach items="${studentResults}" var="result" varStatus="loop">
<div id="levenshtein-distance"
class="ldBar label-center levenshtein-distance"
data-preset="fan"
data-value="${result.percentage}">
</div>
</c:forEach>
<script type="text/javascript">
barSetLD("${result.percentage}");
</script>
Put your code at the very bottom of the page where all DOM has been loaded. Or at least make sure <div id="levenshtein-distance"/> exist and fully loaded before calling this document.getElementById("levenshtein-distance");. Also double check if you have multiple levenshtein-distance id...
I'm still new to javascript, so expect to see a lot of bad programming practices...
function addButton(name, state) {
numButtons += 1;
if (name === '') {
var i = 0;
while(buttonStates.hasOwnProperty("button" + i) === true) i++;
name = "button" + i;
}
document.getElementById("buttonTable").innerHTML +=
"<tr>\
<td>\
<p id=\"buttonName" + numButtons + "\" class=\"buttonName\">" + name + "</p>\
</td><td>\
<button id=\"" + name + "\" onclick=\"setButton(this, 'toggle')\" class=\"button\">OFF</button>\
</td>\
</tr>";
//===IMPORTANT AREA 1==========================================================//
//setTimeout(function(){setButton(document.getElementById(name), state)}, 0); //works
setButton(document.getElementById(name), state); //doesn't work, no change
//=============================================================================//
}
function setButton(elem, state) {
//this is where the button's colors are set to light colors
//notice how I am using elem.style.backgroundColor
if(String(state) === 'toggle') state = !buttonStates[elem.id];
if (String(state) === 'true') {
buttonStates[elem.id] = true;
elem.style.backgroundColor = "rgb(112,192,112)";
elem.textContent = 'ON';
} else {
buttonStates[elem.id] = false;
elem.style.backgroundColor = "rgb(255,128,128)";
elem.textContent = 'OFF';
}
var xhttp = new XMLHttpRequest();
xhttp.onreadystatechange = function () {
if (this.readyState === 4 && this.status === 200) {
document.getElementById("demo").innerHTML = this.responseText;
//===IMPORTANT AREA 2==========================================================//
if (buttonStates[elem.id] === true) {
elem.style.backgroundColor = 'green'; //doesn't work, no change. Notice how I am, again, using elem.style.backgroundColor
//document.getElementById(elem.id).style.backgroundColor = 'green'; //works
} else {
elem.style.backgroundColor = 'red';
}
//=============================================================================//
} else {
document.getElementById("demo").innerHTML = "readyState: " + this.readyState + "<br>status: " + this.status;
}
};
xhttp.open("POST", "/buttonToggle", true);
xhttp.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
xhttp.send(elem.id + "=" + buttonStates[elem.id]);
}
So basically I add an HTML button in addButton(), which calls setButton() and passes the new element to that function. In setButton(), it first sets the element's color to light-green or light-red, indicating that the server has not yet updated the state of the button. This part works fine, the button's color DOES change. HOWEVER, in the callback function for the server request, the button refuses to change color in the exact same method as used before. I have found ways around it (either by using setTimeout() with a time of 0ms, or by using the passed element to again get the element from document), but I want to know WHY this happens. It seems to only be a problem in the callback function. I have verified that the callback function does execute and that the code for changing the color is executed.
As a side note, if I have multiple buttons, the last button works fine and all those before it do not work, their color is still light-green or light-red.
Notice buttons 0-5 are all a light color, yet button6 is solid, WHY?!?
Different elements on the HTML doc should have different unique ids. Your all buttons have the same id so only last one is working.
Make your ids unique by using 'button' + i like you are using name.
Okay, I don´t get the current error and why your code doesn´t work. Maybe we need to see the whole code?
But you are definitely searching for the keyword "event loop".
When your code works when you are running it in a timeout, your code needs to be running async.
See more details here: https://developer.mozilla.org/en-US/docs/Web/JavaScript/EventLoop
If you post the whole code, I will take a look again, but maybe this already helps.
And if this are your first steps in programming, you are doing it great!
Here we have a simple practice javascript game , it has a list of valid HTML colors, it picks a random color when the page is loaded , it asks you for guesses and gives you hints based on your input, when you enter the correct color , it changes the background color to the color of the answer.
when you enter the winning answer , you get an alert to tell you that you've won, for some reason the background color only changes after i press ok when the alert appears on the screen, even though the statement that changes the bg color precedes the alert.
My questions are:
(1) why is the BG color changing after i close the alert popup ?
(2)whats the correct way to make the BG color change before the alert appears on the screen?
function do_game() {
var colors = ["aqua", "beige", "deeppink" , "coral", "honeydew", "lime", "gainsboro","rebeccapurple","peru","tan"].sort();
var answer = colors[Math.floor((Math.random() * colors.length))];
var finished = 0;
var numberOfGuesses = 0;
var myBody=document.getElementsByTagName("body")[0];
console.log(answer);
while(!finished){
var input = prompt('I am thinking of one of these colors \n\n' + colors + '\n\n what color am i thinking of? ' );
if(input === null)
finished = 1;
else{
numberOfGuesses++;
checkGuess(input);
if(input === answer){
myBody.style.background=answer;
finished = 1;
alert('You are right! \n you took ' + numberOfGuesses + ' Guesses!');
}
}
}
function checkGuess(input){
if(colors.indexOf(input) === -1){
//does not recognize input
alert('I don’t recognize that color!');
}else if(input > answer){
//alphabetically higher
alert('Your input is alphabetically higher than mine!');
}else if(input < answer){
//alphabatially lower
alert('Your input is alphabetically lower than mine!');
}
}
}
The browser won't repaint the screen until the function which has updated the DOM has finished running.
alert is blocking, so prevents that function from continuing to run until you click OK.
Put the alert in another function and use setTimeout to call it in a non-blocking way.
document.body.style.background = "blue";
setTimeout(function() {
alert("Hello");
});
So I am trying to make something where whenever I click on the text it change's color.
Javascript:
function changecolor(){
var tc = document.getElementById("header").style.color.value;
if (tc = "#000000") { tc = "#0009FF"}
else if (tc == "#0009FF") { tc = "#FF0000"}
else if (tc == "#FF0000") { tc = "#15FF00"}
else if (tc == "#15FF00") { tc = "#FFA600"}
else {tc = "#000000"};
document.getElementById("header").style.color.value = tc;
}
html:
<div onclick="changecolor()"><h1 id="header" style="color:#000000;"> Nick's Basic Physic's Calculator </h1></div>
It is not working and I have not been able to figure out why. When I click on the text nothing happens.
Change
document.getElementById("header").style.color.value = tc;
to
document.getElementById("header").style.color = tc;
Working example:
http://jsfiddle.net/xEyLf/
your problem is in var tc = document.getElementById("header").style.color.value;
you have to change to tc = document.getElementById("header").style.color;in order to get the color into variable.
I have another solution... here's a jsfiddle: http://jsfiddle.net/9zfJA/
Keep in mind I'm using these jQuery methods (as well as the jQuery library itself), by simply switching between CSS classes:
hasClass(): to check if the class is present
addClass(): to add the correct class based on the condition above
removeClass(): remove all classes, I've basically built a "reset" function
I think there are errors in the way it functions and how you want it, but I've built it on the same logic you have in your question.
I have a problem. I wish to flash (or blink) text from yellow to grey, but I would like the yellow text to remain displayed longer than the grey text.
The code that I have works for an equal duration for each color.
function flashtext(ele,col) {
var tmpColCheck = document.getElementById( ele ).style.color;
if (tmpColCheck === 'grey') {
document.getElementById( ele ).style.color = col;
} else {
document.getElementById( ele ).style.color = 'grey';
}
}
setInterval(function() {
flashtext('flashingtext','yellow');
}, 700 ); //set an interval timer up to repeat the function
Any ideas?
Something like this, you mean?
function flashtext(id, col) {
var grey = true,
el = document.getElementById(id);
(function f() {
grey = !grey;
el.style.color = grey ? 'grey' : col;
setTimeout(f, grey ? 500 : 1000);
})();
};
demo at http://jsfiddle.net/alnitak/8LYG2/
This code uses the local variable grey to store the current state, rather than attempt to read it from the element. This is both very efficient, and eliminates the risk that the browser might have converted the .style.color property into another format.
The inner closure is then responsible for toggling the state, changing the element's style, and then recursively queueing itself again with the appropriate timeout.
You can use setTimeout:
function flashtext(ele,col) {
var tmpColCheck = document.getElementById( ele ).style.color,
time;
if (tmpColCheck === 'grey') {
document.getElementById( ele ).style.color = col;
time=1400;
} else {
document.getElementById( ele ).style.color = 'grey';
time=700;
}
setTimeout(function(){flashtext('flashingtext','yellow')},time);
}
flashtext('flashingtext','yellow');
DEMO: http://jsfiddle.net/EfpEP/
Edit:
But it can be improved a bit:
function flashtext(ele,col) {
var style = document.getElementById(ele).style;
(function main(){
var cond=style.color === 'grey';
style.color=cond?col:'grey';
setTimeout(main,cond?1400:700);
})();
}
flashtext('flashingtext','yellow');
DEMO: http://jsfiddle.net/EfpEP/3/
Alnitak had the great idea of storing the color because the browser can change it to another syntax. But his code is calling document.getElementById each time. Then, taking his idea, I think the best way is:
function flashtext(ele,col) {
var style = document.getElementById(ele).style,
cond=style.color === 'grey';
(function main(){
cond=!cond;
style.color=cond?col:'grey';
setTimeout(main,cond?1400:700);
})();
}
flashtext('flashingtext','yellow');
DEMO: http://jsfiddle.net/EfpEP/4/
Edit 2:
But if you are going to use something like
flashtext('flashingtext','yellow');
flashtext('flashingtext2','blue');
...
you will end up freezing the browser.
Instead, you should use
function FlashText(){
var arr=[],
cond=false,
started=false;
this.add=function(el,col){
if(typeof el==='string'){el=document.getElementById(el);}
arr.push([el.style,col]);
}
this.start=function(){
if(started){return;}
started=true;
main();
}
function main(){
cond=!cond;
for(var i=0,l=arr.length;i<l;i++){
arr[i][0].color=cond?arr[i][1]:'grey';
}
setTimeout(main,cond?1400:700);
};
}
var flash=new FlashText();
flash.add('flashingtext','yellow');
flash.add('flashingtext2','blue');
flash.start();
You can also call passing an element by reference: flash.add(document.getElementById('flashingtext'),'yellow') (maybe you have a variable which contains an element which has no id).
But try not to add more elements after flash.start(). If you do that, the element will be black (or default color) until main is called (maybe 1.4 seconds).
DEMO: http://jsfiddle.net/EfpEP/6/