I want to change the innerHTML so for every circle thats the same it adds +1
if (document.getElementById("circle1").style.backgroundColor == document.getElementById("circle5").style.backgroundColor) {
document.getElementById("point2").innerHTML = +1
}
if (document.getElementById("circle2").style.backgroundColor == document.getElementById("circle6").style.backgroundColor) {
document.getElementById("point2").innerHTML = +1
}
I suggest you to use innerText then. First get the old value and cast to Number then add by 1 and replace the old value. Example:
if (document.getElementById("circle1").style.backgroundColor == document.getElementById("circle5").style.backgroundColor) {
let obj = document.getElementById("point2");
let oldValue = Number(obj.innerText);
obj.innerText = oldValue + 1;
}
if (document.getElementById("circle2").style.backgroundColor == document.getElementById("circle6").style.backgroundColor) {
let obj = document.getElementById("point2");
let oldValue = Number(obj.innerText);
obj.innerText = oldValue + 1;
}
See difference between innerText and innerHtml.
document.getElementById("point2").innerHTML doesn't give you a number, so you cannot add 1 to it. first you need to parse the content to a number (like with parseInt or Number), and then you can add 1.
// creating the reference variable (for smaller code)
var point2 = document.getElementById("point2").innerHTML
if (document.getElementById("circle1").style.backgroundColor ==
document.getElementById("circle5").style.backgroundColor) {
document.getElementById("point2").innerHTML = increment(point2)
}
if (document.getElementById("circle2").style.backgroundColor ==
document.getElementById("circle6").style.backgroundColor) {
document.getElementById("point2").innerHTML = increment(point2)
}
// function to increment the value of point2
function increment(html) {
return Number(document.getElementById("point2").innerHTML) + 1
}
#circle1 {
background-color: red;
}
#circle5 {
background-color: red;
}
#circle2 {
background-color: red;
}
#circle6 {
background-color: red;
}
<div id="circle1">C1</div>
<div id="circle5">C5</div>
<br />
<div id="circle2">C2</div>
<div id="circle6">C6</div>
<div id="point2">0</div>
Related
I have 9 boxes in my html.
There is a value, id called 'lifepoint'.
There is a mouse-click function: click once & decrease one life point. This code is completed.
function decrementlife() {
var element = document.getElementById('lifepoint');
var value = element.innerHTML;
--value;
console.log(value);
document.getElementById('lifepoint').innerHTML = value;
if(value <= 0) { alert("Game Over!")};
}
Also, there is a css style, called 'crackbox'.
.crackbox {
position: relative;
background: linear-gradient(0deg, black, rgb(120, 120, 120));
width: 12vh;
height: 12vh;
border-radius: 30%;
margin: 5px;
}
I want to change all box class from 'box' to 'crackbox' if life point is zero. Therefore, all box style can be 'crackbox'.
The below code is fail...
$(document).ready(function () {
$(".box").each(function() {
document.getElementById('lifepoint').innerHTML = value;
if(value <= 0) {
".box".toggleClass('crackbox')
};
})
});
Instead of using document ready, call another function from decrement life if the value turns 0. I am writing the code for your help.
function decrementlife() {
var element = document.getElementById('lifepoint');
var value = element.innerHTML;
--value;
console.log(value);
document.getElementById('lifepoint').innerHTML = value;
if(value <= 0) { changeClass(); alert("Game Over!")};
}
function changeClass(){
$('.box').addClass('crackbox').removeClass('box');
}
Hope, it helps!!
The simplest way would be to use querySelectorAll and loop through the elements:
for(let i = 0, list = document.querySelectorAll(".box"); i < list.length; i++)
{
list[i].classList.toggle('crackbox');
}
Or shorter ES6 version:
[...document.querySelectorAll(".box")].forEach(el => el.classList.toggle('crackbox'))
I am trying to create a typewriter effect animate so when I type into the input box, a new message is displayed and animates.
I tried having a global char variable to go through each element of the array, but when I would pass another other array of letters, after typing text into the input box, the h1 would not be overwritten.
This was my attempt at that
// wrap each letter in output in a span
function createInduvidualLetterSpans(letterArr) {
if (textEl.innerHTML) {
textEl.innerHTML = ''
}
for (const letter of letterArr) {
const letterEl = document.createElement('span')
letterEl.textContent = letter
textEl.appendChild(letterEl)
}
return textEl
}
// animate each letter
let char = 0
function displayChars() {
const span = textEl.querySelectorAll('span')[char]
span.classList.add('load')
char++
if (char == textArr.length) {
complete()
return
}
}
function complete() {
clearInterval(timer)
timer = null
}
createInduvidualLetterSpans(textArr)
let timer = setInterval(displayChars, 10)
My next attempt was to try iterators and closure. I've just been reading up on those ideas and imeditly thought this would be a perfect use case for them. However, I got the text to animate forward, but I am getting a
span is unidentified
error and I am not sure why.
//turn text into an array of letters
const textEl = document.querySelector('h1')
const textArr = textEl.textContent.split('')
const explore = 'Your lack of desire has lead you towards a life of bordeom and dread. [[GAME OVER]]'.split('')
const userInput = document.getElementById('user-input')
textEl.textContent = ''
// iterator fn
function iterator(arr) {
let count = 0
const inner = {
next: function () {
const el = arr[count]
count++
arr[count] == undefined ? done = true : done = false
return {
value: el,
done
}
},
createSpan: function (letterArr) {
textEl.textContent = ''
for (const letter of letterArr) {
const letterEl = document.createElement('span')
letterEl.textContent = letter
textEl.appendChild(letterEl)
}
},
animateEachLetter: function () {
const span = textEl.querySelectorAll('span')[count]
span.classList.add('load')
count++
arr[count] == undefined ? done = true : done = false
}
}
return inner
}
const it = iterator(explore);
it.createSpan(explore)
const exploreRoom = () => {
it.createSpan(explore)
}
exploreRoom()
setInterval(it.animateEachLetter, 10)
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html {
font-size: 62.5%;
}
body {
max-width: 100%;
}
span {
opacity: 0;
}
span.load {
opacity: 1;
}
<div class="grid">
<h1>You wake, confused and disoriented. Something just does not feel quite right. You reach over to the night stand, find a pair of glasses, put them on (even though you do not wear glasses and stand up. Do you explore the room or go back to bed?</h1>
<form id="user-input">
<input id="user-text" class="input" type="text" name="text" autofocus>
</form>
</div>
With
setInterval(it.animateEachLetter, 10)
and
animateEachLetter: function () {
const span = textEl.querySelectorAll('span')[count]
span.classList.add('load')
count++
arr[count] == undefined ? done = true : done = false
}
you're calling animateEachLetter and trying to find span, change its class, and increment the count regardless. It sounds like you just need to check whether such a span exists first - if it doesn't, clear the interval. The iterator protocol makes things much more confusing than they need to be for this, you might consider removing it completely.
Also, your animateEachLetter actually animates a single letter, not each letter. Consider having an animateEachLetter method which actually animates every letter, which calls a different method (one which runs in the interval) which animates one letter:
const textEl = document.querySelector('h1');
const textArr = textEl.textContent.split('');
const explore = 'Your lack of desire has lead you towards a life of bordeom and dread. [[GAME OVER]]'.split('');
const userInput = document.getElementById('user-input');
function makeAnimator(arr) {
let count = 0;
return {
createSpan: function(letterArr) {
textEl.textContent = '';
for (const letter of letterArr) {
const letterEl = document.createElement('span');
letterEl.textContent = letter;
textEl.appendChild(letterEl);
}
},
animateEachLetter(ms) {
this.interval = setInterval(() => this.animateOneLetter(), ms);
},
animateOneLetter() {
const span = textEl.querySelectorAll('span')[count];
if (!span) {
clearInterval(this.interval);
return;
}
span.classList.add('load')
count++
arr[count] == undefined ? done = true : done = false
}
};
}
const animator = makeAnimator(explore);
animator.createSpan(explore)
animator.animateEachLetter(20);
* {
margin: 0;
padding: 0;
box-sizing: border-box;
}
html {
font-size: 62.5%;
}
body {
max-width: 100%;
}
span {
opacity: 0;
}
span.load {
opacity: 1;
}
<div class="grid">
<h1>You wake, confused and disoriented. Something just does not feel quite right. You reach over to the night stand, find a pair of glasses, put them on (even though you do not wear glasses and stand up. Do you explore the room or go back to bed?</h1>
<form id="user-input">
<input id="user-text" class="input" type="text" name="text" autofocus>
</form>
</div>
Is it possible to change the color of val without changing the color of "Solution" and have them display in the same line (code shown below)?
result.innerText = "Solution:" + val.toFixed(2);
I know that you can add
result.style="color:red";
but that changes the color of the entire line including "solution:" when I run;
<div id="result" align ="center"></div>
EDIT: Changes I made by adding pseudo element and classes but nothing is displayed apart from "Solution"
val = sumsc/sumcr;
var result = document.querySelector('#result');
if(isNaN(sumsc/sumcr)){
val=0.00;
result.innerText = val.toFixed(2);
result.className = "white";
else if(val<3 & val>0.1){
result.innerText = val.toFixed(2);
result.className = "red";
}
else if(val>3 & val<3.5){
result.innerText = val.toFixed(2);
result.className = "pink";
}
else if(val>3.5){
result.innerText = val.toFixed(2);
result.className = "green";
}
#result{
text-align:center;
}
#result::before {
content: "Solution: ";
color: black;
}
.white {
color: white;
}
.red {
color: red;
}
.pink{
color: pink;
}
.green{
color: green;
}
Surrounding val with a span and adding styles to it should work:
result.innerHTML = 'Solution: <span class="red">' + val.toFixed(2) + '</span>';
.red {
color: red;
}
An alternate might be to put the span in the markup, <div id="result">Solution:<span class="solutionval"></span></div> then just change the text/value there.
let resutltTextSpan = document.getElementById('result')
.getElementsByClassName('solutionval')[0];
resutltTextSpan.innerText = val.toFixed(2);
Here I use a function so you can see simple changes over time with set of timeout functions that call it with a value.
More information on adding, removing, toggle etc. of classes : https://developer.mozilla.org/en-US/docs/Web/API/Element/classList
EDIT: added toggle of class as that might be most elegant given the comments.
function setVal(val = 0) {
let resutltTextSpan = document.getElementById('result')
.getElementsByClassName('solutionval')[0];
resutltTextSpan.innerText = val.toFixed(2);
// now we can do other things
if (val === 0) {
resutltTextSpan.classList.add("unset");
}
if (val > 0 && val < 9000) {
resutltTextSpan.classList.add("good");
}
resutltTextSpan.classList.toggle("bad",(val > 9000 && val <= 9300) );
if (val > 9900) {
resutltTextSpan.classList.add("ugly");
}
}
let val = 456;
setVal(); //use default 0 since we pass nothing
setTimeout(function() {
val = 9200.2455;
setVal(val);
}, 5000);
// change it after 10 seconds
setTimeout(function() {
val = 9934.56;
setVal(val);
}, 10000);
#retult {
text-align: center;
}
.solutionval.unset {
color: #0000ff;
}
.solutionval {
color: #ffffff;
}
.solutionval.good {
color: #00ff00;
}
.solutionval.bad {
font-weight: bold;
}
.solutionval.ugly {
color: #ff0000;
}
<div id="result">Solution:<span class="solutionval"></span></div>
You can do this by creating a ::before pseudo element of the word "solution" - this allows you to set the value of the number and have the text automatically placed as the first child of the div.
EDIT: I have addded a ternary equation to allow the changing of the color based on the value. Note that this has to be determined from the number not the .toFixed(2) value since that is now a string. This can be used as regular if / else statements if there are more than two options.
Also - it is better to apply styles via adding / removing classes than directly targetting the style attribute withing the JS.
var val = 13.789;
var result = document.querySelector('#result');
result.innerText = val.toFixed(2);
val > 10
? result.className = "red"
: result.className = "blue"
#result{
text-align:center;
}
#result::before {
content: "Solution ";
color: black;
}
.red {
color: red;
}
.blue {
color: blue;
}
<div id="result"><div>
I have a variable that I need to add 1 to each time an elements opacity is 1. I need to keep checking the opacity so I have wrapped it in a setInterval.
I am wondering if there is a way to only add 1 to the variable each time the opacity changes to 1 instead of keep adding 1 over and over again because of the interval. Here is my code
var number = 1;
var intervalsizer = setInterval(function() {
if ($(".cardButtons__discuss").css('opacity') == 1) {
number++;
console.log(number)
}
function fooo() {
if (number == 1) {
//do something
}
if (number == 2) {
}
if (number == 3) {
//do something
}
if (number == 4) {
//do something
}
}
}, 50);
Thanks in advance
Tracking an attribute can be done using a MutationObserver. This code tracks all attribute changes on the element and filters out changes to the style and class attributes specifically. When the attributes change it looks if the opacity value has changed.
This solution only works if the opacity is changed on the element itself, by setting a class or by setting a style.
const mydiv = document.getElementById('mydiv')
const observer = new MutationObserver(function(mutations) {
mutations.forEach(function(mutation) {
if(mutation.attributeName !== 'style' && mutation.attributeName !== 'class') return;
const target = $(mutation.target);
const oldVal = target.data("oldOpacity");
const newVal = getComputedStyle(target[0]).opacity;
if(oldVal != newVal) {
console.log(`opacity changed. Old: ${oldVal}, New: ${newVal}`)
target.data("oldOpacity", newVal)
}
});
});
const config = {
attributes: true
};
observer.observe(mydiv, config);
//code to change the opacity and another style attribute.
let i = 0;
setInterval(() => {
switch (i % 4) {
case 0:
mydiv.style.backgroundColor = "red"
break
case 1:
mydiv.style.opacity = "0.5"
break
case 2:
mydiv.classList.add('blue')
break
case 3:
mydiv.style.opacity = ""
mydiv.classList.remove('blue')
mydiv.style.backgroundColor = "blue"
break;
}
i++;
}, 1000)
.blue {
background-color: blue !important;
opacity: 1 !important;
}
#mydiv {
background-color: red;
width: 100px;
height: 100px;
}
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
<div id="mydiv"></div>
I would like to know how can I define a bigger variable for a set of variables that I have in javascript: showFootnotesPanel();, showReferencesPanel();, showImagesPanel();, showInformationPanel();.
Would it be something like this?
function showPanel() {
var x = [showFootnotesPanel();showReferencesPanel();showImagesPanel();showInformationPanel();]
}
Update:
I have this function that used to open a side panel on the right side and color the content:
var els = document.getElementsByClassName('change-color'),
target = document.getElementsByClassName('resources'),
changeColor = function(a) {
elements = document.getElementsByClassName("note");
for (var i = 0; i < elements.length; i++) {
console.log(elements[i])
elements[i].style.backgroundColor = "";
}
target = a.getAttribute('href');
element = document.querySelector('[data-id="' + target.substring(1, target.length) + '"]');
element.style.backgroundColor = a.getAttribute('data-color');
};
for (var i = els.length - 1; i >= 0; --i) {
els[i].onclick = function() {
showFootnotesPanel();
changeColor(this);
}
Now I have 4 side panels that need to respond to the same script, and I thought that by defining something like showPanel() is showFootnotesPanel() or showReferencesPanel() or showImagesPanel() or showInformationPanel() I might simplify things, so the last line of the script would be this instead just:
els[i].onclick = function(){showPanel();changeColor(this);}
Update 2:
Or is it possible to do this with the logical operator OR?
els[i].onclick = function(){showFootnotesPanel(); || showReferencesPanel(); || showImagesPanel(); || showInformationPanel();changeColor(this);}
Update 3:
This is the new script that I am using to hide and show the panels:
function showPanel(myPanel) {
var elem = document.getElementById(myPanel);
if (elem.classList) {
console.log("classList supported");
elem.classList.toggle("show");
} else {
var classes = elem.className;
if (classes.indexOf("show") >= 0) {
elem.className = classes.replace("show", "");
} else {
elem.className = classes + " show";
}
console.log(elem.className);
}
}
function hideOthers(one, two, three, four) {
if (one > "") {
var elem1 = document.getElementById(one);
var classes = elem1.className;
elem1.className = classes.replace("show", "");
}
if (two > "") {
var elem2 = document.getElementById(two);
var classes = elem2.className;
elem2.className = classes.replace("show", "");
}
if (three > "") {
var elem3 = document.getElementById(three);
var classes = elem3.className;
elem3.className = classes.replace("show", "");
}
if (four > "") {
var elem4 = document.getElementById(four);
var classes = elem4.className;
elem4.className = classes.replace("show", "");
}
return;
}
And this is the script that calls the panels and highlights the text on them:
var els = document.getElementsByClassName('change-color'),
target = document.getElementsByClassName('resources'),
changeColor = function(a) {
elements = document.getElementsByClassName("note");
for (var i = 0; i < elements.length; i++) {
console.log(elements[i])
elements[i].style.backgroundColor = "";
}
target = a.getAttribute('href');
element = document.querySelector('[data-id="' + target.substring(1, target.length) + '"]');
element.style.backgroundColor = a.getAttribute('data-color');
};
for (var i = els.length - 1; i >= 0; --i) {
els[i].onclick = function() {
hideOthers('footnotes-section', 'references-section', 'images-section', 'information-section');
showPanel('references-section');
changeColor(this);
}
}
Thank you!
Updated with a final solution.
In javascript you can declare variables by this way:
var text = ""; // String variable.
var number = 0; //Numeric variable.
var boolValue = true; //Boolean variable.
var arrayValue = []; // Array variable. This array can contain objects {}.
var obj = {}; // Object variable.
Check this version of your code.
// var text = ""; => String variable.
// var number = 0; => Numeric variable.
// var boolValue = true; => Boolean variable.
// var arrayValue = []; => Array variable. This array can contain objects {}.
// var obj = {}; => Object variable.
// This section of code is only to explain the first question.
(function() {
function showFootnotesPanel() {
return 10; // Random value.
}
function showReferencesPanel() {
return 30; // Random value.
}
function showImagesPanel() {
return 50; // Random value.
}
function showInformationPanel() {
return 90; // Random value.
}
function showPanel() {
return [
showFootnotesPanel(), // Index = 0
showReferencesPanel(), // Index = 1
showImagesPanel(), // Index = 2
showInformationPanel() // Index = 3
];
}
var bigVariable = showPanel(); // bigVariable is array of numeric values.
// Using logical operator to check status of variable about this demo code.
if (bigVariable[0] === 10 || bigVariable[1] === 30) {
console.log("Hey, with these values can show the FootnotesPanel and ReferencesPanel.");
} else {
console.log("With the current values can't show anything...");
}
console.log(bigVariable);
})();
// https://jsfiddle.net/dannyjhonston/t5e8g22b/
// This section of code attempts to answer the question of this post.
(function() {
// This function can be executed when the page is loaded.
function showPanel(panels) {
var panel, panelVisible = "";
var selPanels = document.getElementById("selPanels");
// In panels array...
for (var i = 0; i < panels.length; i++) {
// panels[0] = "ReferencesPanel";
panel = document.getElementById(panels[i]); // Get in the DOM tag context of the panel to set in the variable "panel".
panelVisible = panel.getAttribute("data-visible"); // HTML5 data attribute.
if (panelVisible == "true") {
panel.setAttribute("class", "show");
} else {
panel.setAttribute("class", "hide");
}
}
}
// This function is for set panel visibilty.
function setPanel(panelId, status) {
panel = document.getElementById(panelId);
panel.setAttribute("data-visible", status);
// Calling the showPanel function to check in the DOM.
showPanel(["ReferencesPanel", "InformationPanel", "ImagesPanel", "FootnotesPanel"]);
}
// Binding the change event to the select tag.
selPanels.addEventListener("change", function() {
// Executes setPanel function with panelId and true to update the data-visible attribute in the DOM.
setPanel(this.options[this.selectedIndex].value, "true");
});
// Executes showPanel function with array argument with panels Id. You need to specify every panel that want to handle.
showPanel(["ReferencesPanel", "InformationPanel", "ImagesPanel", "FootnotesPanel"]);
})();
#global {
border: solid 1px #6291AD;
}
.tools {
background-image: linear-gradient(#FFFFFF, #8999CE);
}
#global div[data-visible] {
height: 80px;
padding: 5px 0;
}
#global div p {
padding: 10px;
}
#ReferencesPanel {
background-image: linear-gradient(#FFFFFF, #FD9A9A);
float: left;
width: 20%;
}
#InformationPanel {
background-image: linear-gradient(#FFFFFF, #A1C7F1);
float: left;
width: 80%;
}
#ImagesPanel {
background-image: linear-gradient(#C6E9FB, #FFF);
width: 100%;
}
#FootnotesPanel {
background-image: linear-gradient(#C6E999, #FFF);
width: 100%;
}
.clear {
clear: both;
}
.show {
display: block;
}
.hide {
display: none;
}
<div id="global">
<div class="tools">Show Panel:
<br />
<!-- Demo -->
<select id="selPanels">
<option value="">[SELECT]</option>
<option value="ReferencesPanel">ReferencesPanel</option>
<option value="InformationPanel">InformationPanel</option>
<option value="ImagesPanel">ImagesPanel</option>
<option value="FootnotesPanel">FootnotesPanel</option>
</select>
</div>
<!-- You need to set data-visible attribute with true or false to show or hide a panel. -->
<div id="ReferencesPanel" data-visible="false">
<p>References Panel</p>
</div>
<div id="InformationPanel" data-visible="false">
<p>Information Panel</p>
</div>
<div class="clear"></div>
<div id="ImagesPanel" data-visible="false">
<p>Images Panel</p>
</div>
<div id="FootnotesPanel" data-visible="false">
<p>Foot notes Panel</p>
</div>
</div>
I dont understand your question exactly, but if you want to define a variable that contains other variables then you can use an object.
e.g:
var footNotesPanel = true;
var referencesPanel = true;
var imagesPanel = true;
var showPanels = {
footNotesPanel: footNotesPanel,
referencesPanel: referencesPanel,
imagesPanel: imagesPanel
}
/*
Option 2 - for showing/hiding side panels
1 ) create all your panels as they would appear, with all the data, but hide them with display:none;
2 ) call show panel function to show a panel.
*/
var showPanel(panel_id) {
var panel_element = $("#" + panel_id); /*panel that you want to show ( is hidden atm but somewhere on the page */
if (!panel_element.length) {
return false; //no panel with this id currently on page
} else {
//check the panel id and do some custom editing if needed, eg.
if (panel_id == "main_side_panel") {
//add some additional classes to body element etc
}
panel_element.show();
//Or Another option that you probably are looking for is below
if (panel_id == "footnotes_panel") {
showFootnotesPanel();
} else if (panel_id == "images_panel") {
showImagesPanel();
}
}
}
// And use it like this:
<div id="footnotes_panel" onclick="showPanel('footnotes_panel')"></div>
// Or simply get the element id from `event.target` and use `showPanel()` without arguments.