I'm wanting to make a game using javascript. And part of the game is that there is a 'shop' and the user can click on things in the shop and it effects the score.
var i;
var shop = new Array();
shop[0] = "Bins:" + " " + "5";
shop[1] = "Shops:" + " " + "60";
shop[2] = "Factories: " + " " + "190";
shop[3] = "Warehouses:" + " " + "600";
shop[4] = "Over sies:" + " " + "1,500";
for (i=0; i<shop.length; i++){
document.write(shop[i] + "<br>")
}
That's what the array(s) look like, so would it be possible for a user to click on the object in the 'shop' and for it to effect the overall score of the game?
This seems like a simple js/html thing. To get you rolling, here is what you can try.
// First, define the array in a bit more data-friendly way.
var i, itemEl, valueEl, liEl, qty, totalScore, shop = [];
shop.push({item: 'Bins', quantity: 5});
shop.push({item: 'Shops', quantity: 60});
shop.push({item: 'Factories', quantity: 60190);
shop.push({item: 'Warehouses', quantity: 600});
shop.push({item: 'Over sies', quantity: 1500});
// then, create a javascript handler for clicks. It will increase the total score
totalScore = 0;
function addToScore(val) {
totalScore += val;
alert('New score: ' + totalScore);
}
// finally, output this as HTML. Find an UL element and add each item row.
var itemsContainer = document.getElementById('items');
for (i = 0; i < shop.length; i++) {
// for each shop item, create a text node holding the label
// and a clickable span containing the number. When the user clicks on the number
// the totalScore increasing method will be called.
// you can add other html elements like this, like
// decreasing score, removing the item, whatever
itemEl = document.createTextNode(shop[i].item + ': ');
valueEl = document.createElement('span');
valueEl.setAttribute('onclick', 'addToScore(' + shop[i].quantity + ')');
liEl = document.createElement('li');
liEl.appendChild(itemEl);
liEl.appendChild(valueEl);
itemsContainer.appendChild(liEl);
}
Your HTML should only contain the itemsContainer, like an <ul> element.
<ul id='items'></ul>
This is just an example. There are a few things not done "properly" there, but the code will work. And as you start with this, you'll learn other stuff and then come back and ask how to improve your code.
Related
I am trying to figure out how I can clear the <p> elements that are generated from a for loop before the for loop starts.
Essentially. I have a webpage where someone searches something and a list of results are shown. However if I search for something else, the new results get appended instead of clearing the old results first.
Here is the code:
async function parseitglinkquery() {
var queriedresults = await getitglinkquery();
console.log(queriedresults);
const output = document.querySelector('span.ms-font-mitglue');
output.removeChild("createditginfo"); \\tried to clear the <pre> here and it failed
for (let i = 0; i < queriedresults.length; i++) {
let text = "Company: " + JSON.stringify(queriedresults[i]["data"]["attributes"].organization-name) + "<br>"+
"Name: " + JSON.stringify(queriedresults[i]["data"]["attributes"].name) + "<br>" +
"Username: " + JSON.stringify(queriedresults[i]["data"]["attributes"].username).replace("\\\\","\\") + "<br>" +
"Password: " + JSON.stringify(queriedresults[i]["data"]["attributes"].password);
let pre = document.createElement('p');
pre.setAttribute("id", "createditginfo")
pre.innerHTML = text;
pre.style.cssText += 'font-size:24px;font-weight:bold;';
output.appendChild(pre);
console.log(typeof pre)
}
}
I tried to create a try and catch block where it would try to clear the <p> using removeChild() but that didn't seem to work either.
async function parseitglinkquery() {
var queriedresults = await getitglinkquery();
console.log(queriedresults);
const output = document.querySelector('span.ms-font-mitglue');
try {
output.removeChild("createditginfo");
}
catch(err){
console.log(err)
}
for (let i = 0; i < queriedresults.length; i++) {
let text = "Company: " + JSON.stringify(queriedresults[i]["data"]["attributes"].organization-name) + "<br>"+
"Name: " + JSON.stringify(queriedresults[i]["data"]["attributes"].name) + "<br>" +
"Username: " + JSON.stringify(queriedresults[i]["data"]["attributes"].username).replace("\\\\","\\") + "<br>" +
"Password: " + JSON.stringify(queriedresults[i]["data"]["attributes"].password);
let pre = document.createElement('p');
pre.setAttribute("id", "createditginfo")
pre.innerHTML = text;
pre.style.cssText += 'font-size:24px;font-weight:bold;';
output.appendChild(pre);
console.log(typeof pre)
}
}
You only have to clear the output-node right before the loop using the innerHTML-property.
output.innerHTML = '';
https://developer.mozilla.org/en-US/docs/Web/API/Element/innerHTML
There are other ways too, if you want to remove only specific childs. You can make use of Node.childNodes together with a loop. With this, you have the opportunity to remove only specific children.
[...output.childNodes].forEach(childNode => {
output.removeChild(childNode)
});
// or specific
[...output.childNodes].forEach(childNode => {
// remove only <div>-nodes
if (childNode.nodeName == 'DIV') {
childNode.remove();
}
});
https://developer.mozilla.org/en-US/docs/Web/API/Node/childNodes
https://developer.mozilla.org/en-US/docs/Web/API/Node/removeChild
https://developer.mozilla.org/en-US/docs/Web/API/Element/remove
The answer above is correct, but I believe that the original code and the answer can be further improved:
for variables that do not change, use const instead of let - this helps explaining the intention.
there seems to be a bug - if you have an attribute called "organization-name", you cannot access it as a property (...["attributes"].organization-name), but you can use array access instead: ...["attributes"]["organization-name"]. Otherwise, the code end up effectively as ...["attributes"].organization - name
when you have long property paths that are repeated a lot (like queriedresults[i]["data"]["attributes"] in your case), consider assigning them to a local variable.
This makes the code more readable and is actually better for performance (because of less array lookups):
// old code
let text = "Company: " + JSON.stringify(queriedresults[i]["data"]["attributes"].organization-name) + "<br>"+
"Name: " + JSON.stringify(queriedresults[i]["data"]["attributes"].name) + "<br>";
// new code
const attrs = queriedresults[i]["data"]["attributes"];
let text = "Company: " + JSON.stringify(attrs['organization-name']) + "<br>"+
"Name: " + JSON.stringify(attrs.name) + "<br>";
you are creating several pre's in a loop, this is ok, however the element id must be different! Each id must be unique in the whole page:
// wrong
for (let i = 0; i < queriedresults.length; i++) {
...
pre.setAttribute("id", "createditginfo")
...
}
// right/better
for (let i = 0; i < queriedresults.length; i++) {
...
pre.setAttribute("id", "createditginfo" + i) // "i" for uniqueness
...
}
you can use innerText, in which case you do not need to encode the attributes, plus it simplifies the code:
const pre = document.createElement('p');
pre.innerText = [
"Company: " + attrs["organization-name"],
"Name: " + attrs.name,
"Username: " + attrs.username, // presumably you don't need to decode "/" anymore :)
"Password: " + attrs.password
].join("\n") // so we declared a bunch of lines as an array, then we join them with a newline character
Finally, regarding the original question, I see three main ways:
simply clearing the contents of the parent with output.innerHtml = ''
iterating over each child and removing it with output.removeChild(childPre)
you can keep references to the generated pre's (eg, store each element in an array) and remove the later with point 2, but this is less automatic but in some cases it might be more efficient if you have a tone of elements at that same level.
I want to reverse my line order while keeping the style of words and the order I created.
HTML:
<textarea id="mytext"">
Buy - 3 Potatoes $6.25
Sold - 3 Napkins $7.12
Buy - 5 Fries $11.62
Sold - 7 Potatoes $14.32
</textarea>
<div id = "myresult"></div>
As you can see I did the order of words and style the words I just need to reverse the lines now.
I'm working on notepad++ and still pretty new to Javascript.
Script:
var mytext = document.getElementById('mytext');
var result = document.getElementById('myresult');
var lines = mytext.value.split('<br>');
result.innerHTML = '';
for(let i = 0;i < lines.length;i++){
var line = lines[i];
var list = [];
list.unshift(line);
list.unshift("<br>");
var word = line.split(' ');
var n1 = line.match(/[0-9]+/g);
var n2 = line.match(/[0-9]+\.[0-9]+/g);
var check = line.match(/Buy/);
var check2 = line.match(/Sell/);
if(check) {
result.innerHTML += "<span style='color:green;'>" + word[0] + "</span>" + ' ' + word[2] + ' ' + word[3] + ' total:$' + (n1[0]*[n2]).toFixed(2) + "<br>";
}
else if(check2) {
result.innerHTML += "<span style='color:blue;'>" + word[0] + "</span>" + ' ' + word[2] + ' ' + word[3] + ' total: $' + (n1[0]*[n2]).toFixed(2) + "<br>";
}
else {
result.innerHTMl + " ";
}
}
As you can see I already style the colors and fix the order. I just need to reverse the line and display it in innerHTML.
My idea was to make a array[], and then for every line in the for loop try to unshift the line and br but everytime it give errors sometimes it gives me a bunch of commas, and one time it it displays no colors or give me a bunch of random words.
Result should look like what is after the snippet run. This is what I want innerHTMl after the code is run. The code has to display innerHTMl inside the div please.
<div id="result">
<span style='color:blue;'>Sold</span> 7 Potatoes total: $100.24<br>
<span style='color:green;'>Buy</span> 5 Fries total: $58.1<br>
<span style='color:blue;'>Sold</span> 3 Napkins total: $21.36<br>
<span style='color:green;'>Buy</span> 3 Potatoes total: $18.75<br>
</div>
In continuation of my comment above, you could use js reverse() before anything else on creating new elements.
E.g.
var lines = mytext.value.split("\n").reverse();
I am using the code below to call a php page that displays all the products and then parse them and display them on the string. This was working fine last week displaying all the results however now it has seem to have broken and only displays the last results from the database and after several days and painful hour staring at my screen i am starting to go mad and could do with some help.
function display(results) {
article = document.getElementById("homeArticle");
item = '';
for (var i = 0; i < results.length; i++){
var item = results[i];
var name = item.P_NAME;
var description = item.P_DESCRIPTION;
var price = item.P_PRICE;
// next I add to the string that we want to place on the page
item = '<section id="homePageSection"> <p>Name:' + name + '</p><p>Description:' + description + '</p><p>Price:' + price + '</p></section>';
};
article.innerHTML = item;
}
function getItems() {
var xhr = new XMLHttpRequest();
xhr.onload = function() {
var results = JSON.parse(this.responseText);
display(results.rows);
};
xhr.open("GET", "displayData.php");
xhr.send();
}
window.addEventListener("load", getItems);
if anyone could have any pointers that would help massively thank you!
You needed two variables. One that you use to build up the html string and one to hold each item from the results array.
Change your code to this:
function display(results) {
article = document.getElementById("homeArticle");
var html = '';
for (var i = 0; i < results.length; i++){
var item = results[i];
var name = item.P_NAME;
var description = item.P_DESCRIPTION;
var price = item.P_PRICE;
// next I add to the string that we want to place on the page
html += '<section id="homePageSection"> <p>Name:' + name + '</p><p>Description:' + description + '</p><p>Price:' + price + '</p></section>';
};
article.innerHTML = html;
}
That way you will append the html strings rather than overwrite the prior one.
Also consider making sure that each html element has a unique id, you could do this by appending i to the id e.g.
html += '<section id="homePageSection-'+i+'"> <p>Name:' + name + '</p><p>Description:' + description + '</p><p>Price:' + price + '</p></section>';
Concat the item string, and don't use duplicate IDs, but classes instead:
item += '<section class="homePageSection"> <p>Name:' + name + '</p><p>Description:' + description + '</p><p>Price:' + price + '</p></section>';
What you were doing is overwriting item on each iteration, which I why you only get the last one.
UPDATE
Forgot to provide the code for that last sentence I wrote. To avoid overwriting it, either use a different variable (as in the other answer), or simply assign the values directly without creating unnecessary variables, like this:
for (var i = 0; i < results.length; i++){
item += '<section class="homePageSection"> <p>Name:' +
results[i].P_NAME +
'</p><p>Description:' +
results[i].P_DESCRIPTION +
'</p><p>Price:' +
results[i].P_PRICE +
'</p></section>';
}
var family = {
dad: 'Father',
mom: 'Mother',
son: 'Boy',
daughter: 'Girl'
}
for ( var person in family ) {
console.log('<li>' + 'the ' + person + ' is a ' + family[person] + '</li>')
}
I want to know what the best way to insert this into the DOM instead of logging it to the console. I want to use just JavaScript
Depends on what is already in the HTML. If you're simply adding exactly what you have, it wouldn't be a bad idea to just use:
var all_family = "";
for (var person in family) {
all_family += "<li>the " + person + " is a " + family[person] + "</li>";
}
document.getElementById("main_ul").innerHTML = all_family;
where "main_ul" is:
<ul id="main_ul"></ul>
Another option is:
var ul = document.getElementById("main_ul");
for (var person in family) {
var li = document.createElement("li");
li.innerHTML = "the " + person + " is a " + family[person];
main_ul.appendChild(li);
}
Something you might look at to help decide which to use: "innerHTML += ..." vs "appendChild(txtNode)"
Native, cross-browser DOM methods are the safest.
var list = document.createElement('li');
for (var person in family)
list.appendChild(
document.createTextNode('the person is a ' + family[person]) );
document.body.appendChild( list );
I have a question with my JavaScript code (I am quite new at this...). I am making a test where I will calculate the score of the participants by using their answers. I have multiple variables where I store these answers. And also the calculation of the score is going ok. Then I have a table with the scores. That is like this:
<script type="text/javascript">
var row1col1var="Fruit";
var rowicol2var="% of how much I love them";
var applep=34; //result from score calcultaion
var row2col1var="Apple";
var bananasp=65; //result from score calcultaion
var row3col1var="Bananas";
document.write('<center><table width="50%" border="0">');
document.write('<tr align="center"><td>' + row1col1var + '<\/td><td>' + rowicol2var + '<\/td><\/tr>');
document.write('<tr align="center"><td>' + row2col1var + '<\/td><td' + applep + "%" + '<\/td><\/tr>');
document.write('<tr align="center"><td>' + row3col1var + '<\/td><td' + bananasp + "%" +'<\/td><\/tr>');
document.write('<\/table><\/center>'); </script>
Here I display the results per "fruit" in a table. What I cannot get to work is this:
I want to pick out the best score (in this case 65, for Bananas) and display: "You love Bananas the most." (ie link 65 to Bananas and display Bananas). I was trying to give the cells an id with the name Apples or Bananas and calling on the id to display it, but this did not work.
My problem breaks down in two pieces:
1. I cannot get math.max to work on variables.
2. I do not know how to link the highest score to its "name" (ie 65 belongs to Bananas).
I hope you can help me!!
You need to use more appropriate way for coding. For storing data, you can use object or array. I am using an array for this example.
Check this :
<html>
<head>
<script type="text/javascript">
function getScore(){
var scoreArr = [];
scoreArr.push(['apple', '35']);
scoreArr.push(['apple', '65']);
var maxPercentage = null;
var lovedFruit = '';
var finalScore = '<center><table width="50%" border="0"><tr align="center"><th>Fruits</th><th>% of how much I love them</th></tr>';
for (var i = 0; i < scoreArr.length; i++) {
finalScore += '<tr align="center"><td>' + scoreArr[i][0] + '</td><td>' + scoreArr[i][1] + "%" + '</td></tr>';
if (maxPercentage === null) {
lovedFruit = scoreArr[i][0];
maxPercentage = parseInt(scoreArr[i][1]);
} else {
if (maxPercentage < parseInt(scoreArr[i][1])) {
lovedFruit = scoreArr[i][0];
maxPercentage = parseInt(scoreArr[i][1]);
}
}
}
finalScore += '</table><br>Result is : ' + maxPercentage + ' belongs to ' + lovedFruit + '</center>';
// WITH JAVASCRIPT
var container = document.createElement('div');
container.innerHTML = finalScore;
document.body.insertBefore(container, null); //append div to end
// WITH JQUERY
// $('body').append(finalScore);
}
</script>
</head>
<body onLoad=getScore()>
</body>
</html>
It will store your data in array and then you can do whatever you want in more sophisticated way.