I'm learning JS and I'm trying to create a web game with javascript. The goal is simple: a flag is displayed at random, and the player must guess the name of the country associated with the flag.
The flag is randomly selected and displayed correctly, but I have a problem with the user interaction. I'd like to display "bad answer" in a <p> and if it's correct, display "good answer" (in a <p>), regenerate a flag and start again, indefinitely. The problem is that I can get the user's answer but i can't compare it to real answer and then display true or false.
I would like to know if someone could explain to me what is wrong and correct me please. Here is my code :
function getRandomInt(max) {
return Math.floor(Math.random() * max);
}
function getVal() {
const inputValue = document.querySelector('input').value;
console.log(inputValue);
}
function getData() {
var json = 'https://cdn.jsdelivr.net/npm/country-flag-emoji-json#2.0.0/dist/index.json'
fetch(json)
.then(data => data.json())
.then(data => {
const randomInt = getRandomInt(data.length);
console.log(data[randomInt]);
var image = document.getElementById("flag");
image.src = data[randomInt].image;
});
if (inputValue != data[randomInt].name.toLowerCase()) {
document.getElementsByClassName('result').class.add("result-false");
document.getElementsByClassName('result').innerHTML = 'Mauvaise Réponse';
} else if (inputValue == data[randomInt].name.toLowerCase()) {
document.getElementsByClassName('result').class.add("result-true");
document.getElementsByClassName('result').innerHTML = 'Bonne Réponse';
}
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Guess The Flag - </title>
<link rel="stylesheet" href="style.css">
<!-- <script type="text/js" src="app.js"></script> -->
</head>
<body>
<h1>GuessTheFlag</h1>
<div class="flagCanva">
<img id="flag" src="https://cdn.jsdelivr.net/npm/country-flag-emoji-json#2.0.0/dist/images/KH.svg" alt="">
</div>
<input type="text" name="flagName">
<button type="submit" onclick="getVal()">Je valide</button>
<p class="result"></p><br>
<button onclick="getData()">Next</button>
</body>
</html>
The reason is because the scope of inputValue is inside the function getVal only.
So in function getData it doesn't know inputValue.
The scope is the perimeter where the variable is known, it could be globally, local to a function, or at other level. It depends where and how you declare the variable.
It's an important thing to understand in most of the computer langage.
Here's a refactored working version with some comments to help clear things out:
function getRandomInt(max) {
return Math.floor(Math.random() * max);
}
let flag = "Cambodia"; // <= We need a global variable so that it can be set and accessed inside getVal() and getData()
function getVal() {
const inputValue = document.querySelector('input').value;
//>> Move the flag vs input comparison inside the input event handler:
if ( inputValue.toLowerCase() !== flag.toLowerCase()) { // <= Lowercasing both input and flag name to avoid case sensitive comparison failures
// Use `classList` instead of `class` to have access to the add() method
// Use `querySelector` to pick a single element instead of getElementsByClassName which returns a list of elements:
document.querySelector('.result').classList.add("result-false");
document.querySelector('.result').innerHTML = 'Mauvaise Réponse';
// No need for an else if here:
} else {
document.querySelector('.result').classList.add("result-true");
document.querySelector('.result').innerHTML = 'Bonne Réponse';
}
}
// TIP: Ideally the next function should be split into 2 functions:
// 1) fetchData(), runs once to grab the JSON
// 2) getRandomFlag(), runs on 'Next' click to get a random flag
// without re-fetching the JSON.
function getData() {
var json = 'https://cdn.jsdelivr.net/npm/country-flag-emoji-json#2.0.0/dist/index.json'
fetch(json)
.then(data=>data.json())
.then(data=> {
const randomInt = getRandomInt(data.length);
console.log(data[randomInt]);
var image = document.getElementById("flag");
image.src = data[randomInt].image;
flag = data[randomInt].name; // <= Set the value for the newly fetched flag name
});
}
Working demo:
function getRandomInt(max) {
return Math.floor(Math.random() * max);
}
let flag = "Cambodia"; // <= We need a global variable so that it can be set and accessed inside getVal() and getData()
function getVal() {
const inputValue = document.querySelector('input').value;
//>> Move the flag vs input comparison inside the input event handler:
if(inputValue.toLowerCase() != flag.toLowerCase()) {
// Use `classList` instead of `class` to have access to the add() method
// Use `querySelector` to pick a single element instead of getElementsByClassName which returns a list of elements:
document.querySelector('.result').classList.add("result-false");
document.querySelector('.result').innerHTML = 'Mauvaise Réponse';
} else {
document.querySelector('.result').classList.add("result-true");
document.querySelector('.result').innerHTML = 'Bonne Réponse';
}
}
function getData() {
var json = 'https://cdn.jsdelivr.net/npm/country-flag-emoji-json#2.0.0/dist/index.json'
fetch(json)
.then(data=>data.json())
.then(data=> {
const randomInt = getRandomInt(data.length);
console.log(data[randomInt]);
var image = document.getElementById("flag");
image.src = data[randomInt].image;
flag = data[randomInt].name;
});
}
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>Guess The Flag - </title>
<link rel="stylesheet" href="style.css">
<!-- <script type="text/js" src="app.js"></script> -->
</head>
<body>
<h1>GuessTheFlag</h1>
<div class="flagCanva">
<img width="100" id="flag" src="https://cdn.jsdelivr.net/npm/country-flag-emoji-json#2.0.0/dist/images/KH.svg" alt="">
</div>
<input type="text" name="flagName">
<button type="submit" onclick="getVal()">Je valide</button>
<p class="result"></p><br>
<button onclick="getData()">Next</button>
</body>
</html>
There's a lot of refactoring that we can do (e.g. caching the selected elements, cache the json response to avoid re-fetching the data, removing global variables, etc.) to improve the code, but this is just a good start for a functional code.
Related
I am trying to use javascript to extract data from the URL parameter 'utm_source' and add it to a field on a form so that it is stored in my contact database for tracking purposes.
I had previously accomplished this on another site, but when trying to reuse the code it is not working for me.
The page is here (with the included URL parameter to be extracted):
https://members.travisraab.com/country-guitar-clinic-optin-1-1?utm_source=youtube&utm_medium=description
The desired result if for the 'traffic_source' field on my form to be populated with the value from the 'utm_source' URL parameter, in this case 'youtube'.
Here is the code I am using:
<script type="text/javascript">
function addSource() {
var fieldToChange = document.getElementsByName("form_submission[custom_4]");
var source = trafficSource();
fieldToChange.value = source;
}
var trafficSource = function() {
var query = window.location.search.substring(1);
var vars = query.split("&");
for (var i=0;i<vars.length;i++) {
var pair = vars[i].split("=");
if(pair[0] == "utm_source"){
return pair[1];
} else if (pair[0] == "gclid") {
return 'google';
}
}
return 'unknown';
}
document.onload = addSource();
</script>
fieldToChange is a NodeList so if you want to change the value property you need to specify the index number
So this should fix your code
fieldToChange[0].value = source;
You can take all the query params using new URLSearchParams(window.location.search) and get the particular query param using searchParams.get('utm_source') and then, store the value of utm_source in form field using document.getElementById("utmsource").value = param;.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=\, initial-scale=1.0">
<title>Document</title>
</head>
<body>
<input type="text" id="utmsource" />
<script>
let searchParams = new URLSearchParams(window.location.search)
let param = searchParams.get('utm_source')
document.getElementById("utmsource").value = param;
</script>
</body>
</html>
I'm trying to make a list of buttons and their names into an array in javascript?
I heave searched the internet for help but not found anything so far. The div with the name "apps" is where I'm trying to grab from and the array inside of the if statement in the javascript code is what I'm to to replace with the array.
HTML code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta http-equiv="X-UA-Compatible" content="IE=edge">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<link rel="stylesheet" type="text/css" href="clicker.css">
<script src="http://code.jquery.com/jquery-1.9.1.js"></script>
<title>Vairoon's clicker</title>
</head>
<body>
<button onclick="smnPlayer()">Get new player</button>
<p>Players per click: <span id="PPC">1</span></p>
<p>Players: <span id="players">0</span></p>
<p>New players per second: <span id="PPS">0</span></p>
<div class="upgrade">
<p>Upgrade your clicker game: <span id="upgCost">400</span></p>
<button id="upgrade">Upgrade clicker</button>
</div>
<div id="apps" name="apps"> <!-- The div I'm trying to grab from-->
<button>Obj1</button>
<button>Obj2</button>
</div>
<script ="clicker.js"></script>
</body>
</html>
Javascript code:
var players=0;
var PPS=0;
var PPC=1;
var upgradeCost=400;
var apps = ["New buildings","More upgrades","Adverts","More minigames"]
var basecosts = [0,20,100,1500,15000]
function getEl(elID) {
return document.getElementById(elID);
}
function smnPlayer() {
players+=PPC;
document.getElementById("players").innerHTML=players;
}
getEl("upgrade").onclick = function upgrade() {
if (players>=upgradeCost) {
players-=upgradeCost;
upgradeCost=upgradeCost*3;
PPC=Math.ceil(PPC*2);
PPS=PPS*2;
getEl("players").innerHTML=players;
getEl("upgCost").innerHTML=upgradeCost;
getEl("PPC").innerHTML=PPC;
getEl("PPS").innerHTML=PPS;
}
}
setInterval(() => {
if (players>=upgradeCost) {
getEl("upgrade").style.display="block";
} else {
getEl("upgrade").style.display="none";
}
for (let index = document.querySelectorAll('#apps').length; index < basecosts.length+1; index++) {
if (players>=basecosts[index]) {
if (array.includes(apps[index])){}else{ //the "array" is what to replace with the array
var button = document.createElement("BUTTON");
button.innerHTML = apps[index];
document.getElementById("apps").appendChild(button);
}
}
}
},10)
If you still don't understand what I'm trying to do, here's another explanation:
I want the code to go from
<div>
<button>Obj1</button>
<button>Obj2</button>
</div>
to
["Obj1","Obj2"]
Oh and a question if you can answer too, how do I add break line between the items I'm creating just with js?
For your simplified example:
myArray = Array.from(document.querySelectorAll("div button")).map(
function(b) {
return b.innerText;
}
);
console.log(myArray);
//add a line break:
document.querySelector("div").insertBefore(document.createElement("br"),document.querySelectorAll("div button")[1]);
<div>
<button>Obj1</button>
<button>Obj2</button>
</div>
please am trying to integrate sending any trc20 token using tronlink by clicking a button on my website. I was able to send TRX using the JavaScript code below but I want to be able to send trc-20 like USDT, any help will be highly appreciated. Thanks
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div>
<input type="text" name="numb" id="numb">
<button onclick="sendtron()">Can you get tronweb from tronlink?</button>
</div>
<script>
function sendtron(){
var obj = setInterval(async ()=>{
if (window.tronWeb && window.tronWeb.defaultAddress.base58) {
clearInterval(obj)
var tronweb = window.tronWeb
var amount = document.querySelector('#numb').value;
var tokens = amount * 1000000
var tx = await tronweb.trx.sendTransaction("TWs2Z7dLMcPnXi9pnWqCUPzAnqUv6T54dy", tokens)
var signedTx = await tronweb.trx.sign(tx)
var broastTx = await tronweb.trx.sendRawTransaction(signedTx)
console.log(broastTx);
}
});
}
</script>
</body>
</html>
TRC20 are actually smart contracts. tronscan USDT link To transfer TRC20 from your address to another address, you will be calling TRC20's transfer function, below is a snippet of Tron USDT's code.
function transfer(address _to, uint256 _value) public returns (bool) {
require(_to != address(0));
require(_value <= balances[msg.sender]);
// SafeMath.sub will throw if there is not enough balance.
balances[msg.sender] = balances[msg.sender].sub(_value);
balances[_to] = balances[_to].add(_value);
Transfer(msg.sender, _to, _value);
return true;
}
TronWeb TRC20 Contract Interaction documentation. You can use tronWeb's triggerSmartContract function to create a raw transaction, sign and broadcast.
create raw transaction
var senderAddress = tronweb.defaultAddress.base58;
var receiverAddress = "TV3nb5HYFe2xBEmyb3ETe93UGkjAhWyzrs";
var amount = 100;
var parameter = [{type:'address',value:receiverAddress},{type:'uint256',value:amount}]
var options = {
feeLimit:100000000
}
const transactionObject = await tronWeb.transactionBuilder.triggerSmartContract(
tronweb.address.toHex(contractAddress),
"transfer(address,uint256)",
options,
parameter,
tronweb.address.toHex(senderAddress)
);
Note: address are all in base58 format, we need to convert it to hex format using tronweb.address.toHex(address) at transactionObject. The parameter variable is where we set the receiver address and amount.
Sign
var signedTransaction = await tronWeb.trx.sign(transactionObject.transaction);
Broadcast
var broadcastTransaction = await tronWeb.trx.sendRawTransaction(signedTransaction);
console.log(broadcastTransaction);
I'm trying to display contents of an API but for some reason I'm getting an error in the console that says Uncaught (in promise) TypeError: Cannot read property 'appendChild' of null which sort doesn't make sense to me because I've set to innerHTML = <p>${this.items[i]}</p>.
What am I doing wrong and how can I fix this? If you need more information, please let me know.
Here's my html
<!doctype html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport"
content="width=device-width, user-scalable=no, initial-scale=1.0, maximum-scale=1.0, minimum-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div class="baseball">
<h1>test</h1>
</div>
<script type="application/javascript" src="index.js"></script>
<script type="text/javascript">
window.addEventListener("load", function() {
console.log("document is loaded");
var baseballStats = new BaseballStats();
baseballStats.init("https://statsapi.mlb.com/api/v1/people/660670/stats?stats=byDateRange&season=2018&group=hitting&startDate=&endDate=&leagueListId=mlb_milb", true);
});
</script>
</body>
</html>
Here's my javascript
class BaseballStats {
constructor() {
this.totalItems = 0;
this.list = document.querySelector("baseball");
}
init(url, bool) {
this.bool = bool;
var that = this;
console.log(url);
fetch(url)
.then(resp => resp.json())
.then(data => {
console.log(data.stats);
that.data = data;
if (this.bool) {
that.items = that.data.stats;
this.totalItems = that.items.length;
console.log("about to loop");
for (var i = 0; i < this.totalItems; i++) {
var listNode = document.createElement("LI");
listNode.innerHTML = `<p>${this.items[i]}</p>`;
console.log("did it reach here");
this.list.appendChild(listNode);
}
}
});
}
}
Try to console.log the list variable. You will see it's null. You're treating this variable as an object, but the content of the variable is null.
Your problem is the BaseballStats' list member is null. This is because you're misusing document.querySelector - it selects in the same way as CSS, so to select an element with a class you need to use the . selector - https://www.w3schools.com/cssref/css_selectors.asp.
You are selecting for 'baseball' however, which means it is trying to find an element with the tag name <baseball>. Change this to '.baseball' and it will work
I have just started learning Javascript, and I attempted to write code for hit counter for a webpage using Javascript. I know that we have to use cookies to get the correct number and use PHP to modify data stored in servers. But could you please debug this for me ? I'm getting the output as "The number of visitors is: NaN"
This is my code:
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div>
<p>The number of visitors is : <span id="cntr">0</span></p>
</div>
<script>
function counter_fn() {
var counter = document.getElementById("cntr");
var count = 0;
count = counter.value;
count = count + 1;
counter.innerHTML = count;
}
window.onload = counter_fn;
</script>
</body>
</html>
You are trying to get the valuefrom a span element, which is wrong.
Your counter.value is undefined so it will give you the wrong answer.
You can get the 0 from the span by using document.getElementById("cntr").innerHTML. But the value returned is in string. So you need to do parseInt to convert it into integer and only then your addition will give you the correct value.
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0">
<meta http-equiv="X-UA-Compatible" content="ie=edge">
<title>Document</title>
</head>
<body>
<div>
<p>The number of visitors is : <span id="cntr">0</span></p>
</div>
<script>
function counter_fn() {
var counter = document.getElementById("cntr");
var count = 0;
count = parseInt(counter.innerHTML);
count = count + 1;
counter.innerHTML = count;
}
window.onload = counter_fn;
</script>
</body>
</html>
You need to use parseInt
<script>
function counter_fn(){
var counter = document.getElementById("cntr");
var count = 0;
count = parseInt(counter.value);
count = count+1;
counter.innerHTML = parseInt(count);
}
window.onload = counter_fn;
</script>
UPDATE
As #Anurag Singh Bisht commented, you cannot get value from a span element . So to get value from <span> you need to use $('span').text();
<html>
<body>
<div id="cntr">
The number of visitors is :
<span>0</span>
</div>
<script>
function counter_fn(){
var counter = $('#cntr span').text(); // geting value from span
var count = 0;
count = parseInt(counter.value);
count = count+1;
counter.innerHTML = parseInt(count);
}
window.onload = counter_fn;
</script>
</body>
</html>
You need to parse the string to an integer and you need to get the innerHTML.
<script>
function counter_fn(){
var counterElement = document.getElementById("cntr")
var counterNumber = parseInt(counterElement.innerHTML)
counterNumber = counterNumber + 1
counterElement.innerHTML = counterNumber
}
window.onload = counter_fn;
</script>
The correct way to do it would be storing this value somewhere else, like localStorage and reading it from there. You are not supposed to read your own HTML to update the value. HTML elements are supposed to be results, not your input.
var counterNumber = 1
if (localStorage.getItem("count")) {
counterNumber = parseInt(localStorage.getItem("count")) + 1
}
else {
localStorage.setItem("count", counterNumber)
}