I'm practicing with event listeners and functions and am trying to build a very simple card game. My first 2 functions work to get values of card 1 and 2 once the respective buttons are clicked. I've built a third to combine the total, but having trouble pulling the generated values into a third function. My third function always returns zero. I get why, but haven't been able to find a solution to pull the values from the first 2 functions. Any help is appreciated, thanks.
var cardButton = document.getElementById('cardButton1');
var cardButton2 = document.getElementById('cardButton2');
var cardValue = document.getElementById('cardValue');
var cardValue2 = document.getElementById('cardValue2');
var cardTotalButton = document.getElementById('cardTotalButton');
var cardTotal = document.getElementById('displayTotal');
var card1Value = 0;
var card2Value = 0;
var totalCardsValue = 0;
var cardMin = 1;
var cardMax = 14;
function generateCard(){
var card1Value = randCard();
cardValue.innerHTML = 'card value is ' + card1Value;
return card1Value;
}
function generateCard2(){
var card2Value = randCard();
cardValue2.innerHTML = 'card value is ' + card2Value;
return card2Value;
}
function getPlayerTotal(){
var totalCardsValue = card1Value + card2Value;
//console.log(cardValue2 + 'test');
cardTotal.innerHTML = 'card total is ' + totalCardsValue;
}
cardButton.addEventListener('click',generateCard);
cardButton2.addEventListener('click',generateCard2);
cardTotalButton.addEventListener('click',getPlayerTotal);
function randCard(){
var genRandCard = Math.floor(Math.random()*cardMax)+1;
return genRandCard;
}
You are re-declaring your card1Value, card2Value, and totalCardsValue to a local scope. Remove the var in front of them. Doing it this way, you don't need to return any value from the generateCard() and generateCard() function because you're using the global variables.
function generateCard(){
card1Value = randCard(); //<-------Don't use var here
cardValue.innerHTML = 'card value is ' + card1Value;
return card1Value; //<-------This line is not really needed
}
function generateCard2(){
card2Value = randCard(); //<-------Don't use var here
cardValue2.innerHTML = 'card value is ' + card2Value;
return card2Value; //<-------This line is not really needed
}
function getPlayerTotal(){
totalCardsValue = card1Value + card2Value; //<-------Don't use var here
//console.log(cardValue2 + 'test');
cardTotal.innerHTML = 'card total is ' + totalCardsValue;
}
Related
I want to access variables ie. distance, vertex2Position, path which in two seperate function, inside main function called getResult. How can I achieve this without altering my code or altering my code in minimum way.
function getResult() {
document.getElementById("vertex1").onchange = function() {
var vertex1 = document.getElementById("vertex1").value;
var vertex1Position = graph.node.findIndex(e => e.id == vertex1) + 1;
document.getElementById("output").textContent = vertex1Position;
var distance = execute(vertex1Position); // How can I access distance in my result variable
};
var vertex2Position = 0;
console.log("whats here");
document.getElementById("vertex2").onchange = function() {
var vertex2 = document.getElementById("vertex2").value;
vertex2Position = graph.node.findIndex(e => e.name == vertex2)+ 1; // I also want to access vertex2Position in my result variable which is in outer function
document.getElementById("secondOutput").textContent = vertex2Position;
var path = getPath(vertex2Position); //How can I access path in var result
};
var result = distance.vertex2Position; // I want to store distance and vertex2Position in result variable
document.getElementById("searchResult").innerHTML = "test" + result + "" + path + "."; // I also want to access path
}
You should use something like this :
var container = (function(){
var distance;
var vertex2P;
return {
setDistance: function(distance){
this.distance = distance;
},
getDistance: function(){return this.distance;},
setVertex2P: function(vertex2P){
this.vertex2P = vertex2P;
},
getVertex2P: function(){return this.vertex2P;},
}}());
And then you can get and set the values in other functions like this
var result = function(){
container.setDistance(2);
container.setVertex2P(3);
console.log(container.getDistance() + container.getVertex2P());
}
result(); // 5
These are(maybe ) the best practices you can use in Javascript with this you avoid the global variables and added privacy to your variables, hope it helps you.
P.S you can short this with ECMASCRIPT 6
In javascript, you need understand about scopes. In your code, the
main scope is the getResult() function, so if you want to access
variables inside sub functions (functions inside the getResult()
function), you'll need declare the variables at beginning of this main
scope.
Example:
function getResult() {
var distance,
path,
vertex1,
vertex2,
vertex1Position,
vertex2Position = 0;
document.getElementById("vertex1").onchange = function() {
vertex1 = document.getElementById("vertex1").value;
vertex1Position = graph.node.findIndex(e => e.id == vertex1) + 1;
document.getElementById("output").textContent = vertex1Position;
distance = execute(vertex1Position);
}
document.getElementById("vertex2").onchange = function() {
vertex2 = document.getElementById("vertex2").value;
vertex2Position = graph.node.findIndex(e => e.name == vertex2)+ 1;
document.getElementById("secondOutput").textContent = vertex2Position;
path = getPath(vertex2Position); //How can I access path in var result
};
result = distance.vertex2Position;
document.getElementById("searchResult").innerHTML = "test" + result + "" + path + ".";
}
Note: You're using functions triggered by "onchange" event, so your variables will initiate as undefined, except for "vertex2Position"
Here is my JS function that sets the text to the variables. And how assign what Pokémon the player has.
function setStats() {
// Sets up stats based on Pokemon
if (computerPokemon === 'Pikachu') {
var computerAttack = 30;
var computerUlt = 60; // Does damage
var computerHealth = 50;
var computerSpeed = 20;
var computerAgility = 10;
}
if (playerPokemon === 'Ho-Oh') {
var playerAttack = 70;
var playerUlt = 10; // Buffs HP
var playerHealth = 80;
var playerSpeed = 35;
var playerAgility = 12;
}
document.getElementById("pHP").innerHTML = 'Health: ' + playerHealth;
document.getElementById("pSpeed").innerHTML = 'Speed: ' + playerSpeed;
document.getElementById("pAgility").innerHTML = 'Agility: ' + playerAgility;
}
function startGame() {
// Player Pokemon Selector
var playerPokemonArray = ["Ho-Oh","Venusaur","Weedle"];
var playerPokemonArrayRandom = Math.floor((Math.random() * playerPokemonArray.length));
var playerPokemon = playerPokemonArray[playerPokemonArrayRandom];
document.getElementById("playerPokemon").innerHTML = 'Your Pokemon is: ' + playerPokemon;
// Computer Pokemon Selector
var computerPokemonArray = ["Pikachu","Charmander","Diglett"];
var computerPokemonArrayRandom = Math.floor((Math.random() * computerPokemonArray.length));
var computerPokemon = computerPokemonArray[computerPokemonArrayRandom];
document.getElementById("computerPokemon").innerHTML = 'The Computer\'s Pokemon is: ' + computerPokemon;
When I run this code it sets the text of my stats paragraphs to undefined. Even though the variables are set depending on what Pokémon they were given.
I've tried changing my code around but nothing worked.
Your code is setting the stat variables from within the setStats() function, and you are trying to access them from startGame(). Javascript is a lexical scoped language. Since you are setting the variables from withink the function, only that function can access the variables. You can fix this by moving the variables into the global scope.
(Also, you are never calling the function setStats()
I am using CodeIgniter & jQuery and parsedown/markdown When I open my bootstrap modal, it allows me to create a new Reference-style link like on here.
I am trying to be able to find some how where it can find the next free number for my available in my textarea and when click save in model will set it.
I am fine [exmple-1][1] and [example-3][3]
[1]: http://www.example.com
[3]: http://www.example.com
And when I open my bootstrap modal and create a new hyperlink it will set and add the next available number
Here is the Codepen Example
Question: How can I when I create a new hyperlink in my bootstrap modal
and click save it can find the next available number set it. Because only 1 & 3 are set in example above next one should be 2 when click save in model
currently as you can see below I just use var counter = 1; and counter++; to be able to create numbers.
Script:
$('#myLink').on('shown.bs.modal', function() {
var text = getSelectedText();
$('#title').val(text.trim());
$('#url').val('http://');
});
function getSelectedText() {
var textarea = document.getElementById("message");
var len = textarea.value.length;
var start = textarea.selectionStart;
var end = textarea.selectionEnd;
var sel = textarea.value.substring(start, end);
return sel;
}
var counter = 1;
$('#save-link').on('click', function(e) {
var textarea = document.getElementById("message");
var len = textarea.value.length;
var start = textarea.selectionStart;
var end = textarea.selectionEnd;
var sel = textarea.value.substring(start, end);
var replace = '[' + $('input#title').val() + ']' + '[' + counter + ']';
var id = '\n [' + counter + ']: ' + $('input#url').val();
counter++;
if ($('#title').val().length > 0) {
textarea.value = textarea.value.substring(0,start) + replace +
textarea.value.substring(end,len) + ' \n' + id;
$('#myLink').modal('hide');
//$('#myLink form')[0].reset();
} else {
return false;
}
});
You can use a simple regex to find the used numbers in the textarea:
function findAvailableNumber(textarea){
//Find lines with links
var matches = textarea.value.match(/(^|\n)\s*\[\d+\]:/g);
//Find corresponding numbers
var usedNumbers = matches.map(function(match){
return parseInt(match.match(/\d+/)[0]); }
);
//Find first unused number
var number = 1;
while(true){
if(usedNumbers.indexOf(number) === -1){
//Found unused number
return number;
}
number++;
}
return number;
}
Add the function, remove the line var counter = 1; and replace counter++; with var counter = findAvailableNumber(textarea);
JSFiddle
As Barmar said: store your already generated numbers in an object or an array and check for the next non-existing number:
var existingNumbers = [1, 3];
function getNextNumber() {
var i = 1;
while (existingNumbers.indexOf(i) > - 1) {
i++;
}
existingNumbers.push(i);
return i;
}
Then get the next number with:
var number = getNextNumber();
I tried to make a function that returns an array, the output should be "My name is Sarah Adam" but actually it does not return anything
/*global s:true*/
var m = 'My name is ';
function updateMsg(h) {
"use strict";
var el = m + h;
s = ['Adam', 'Joseph'];
return s;
}
var n1 = document.getElementById("msg");
n1.textContent = updateMsg("Sarah")[0];
you are returning s (the array) - I think you want to return the concatenated message. As in:
Updated to include variable last names
var m = 'My name is ';
function updateMsg(h, index) {
"use strict";
var el = m + h;
// array of last names
var s = ['Adam', 'Joseph'];
return el + ' ' + s[index]; // return the concatenated string instead
}
var n1 = document.getElementById("msg");
n1.textContent = updateMsg("Sarah", 0); // invoke with param
// console log (confirmation)
console.log(updateMsg("Sarah", 0));
console.log(updateMsg("Meenah", 1));
<div id="msg">
hw
</div>
You could use currying to accomplish this. Just swap your brackets [0] for parentheses (0).
var m = 'My name is ';
function updateMsg(h) {
var s = ['Adam', 'Joseph'];
return function(index) { // return a function that concatenates when given index
return m + h + " " + s[index];
};
}
var messageMaker = updateMsg("Sarah");
console.log(messageMaker(0));
console.log(messageMaker(1));
I think you want to acces one element of the list of lastnames an pass the name. I have corrected your code and do something similar to what you want :
let m = 'My name is ',
s = ['Adam', 'Joseph'],
updateMsg = (h, i) => m + h + ' ' + s[i],
n1 = document.getElementById("msg");
n1.textContent = updateMsg("Sarah", 0);
<p id="msg"></p>
Details are in the source in the comments.
SNIPPET
/*
Global variable: intro
*/
var intro = 'My name is ';
/*
Paramenter: who
*/
function updateMsg(who) {
/*
Array of 2 Strings: guess
Named it guess because that's
what I ended up doing with it
*/
var guess = [' Shadey', ' Joseph'];
/*
Concated String: `hello`
Since `intro` is global it's always accessible
`who` is the parameter with value of "Slim"
`guess[0]` = 'Shadey'
*/
var hello = intro + who + guess[0];
/*
Output of `updateMsg()` function is `hello`
which is "My name is Slim Shadey"
*/
return hello;
}
/*
Reference the `output` element as `noLogic`
*/
var noLogic = document.getElementById("msg");
/*
Set `noLogic's` text to whatever `updateMsg()`
returns
`updateMsg()` parameter is "Slim"
*/
noLogic.textContent = updateMsg("Slim");
<output id="msg"></output>
I guess the intent is to return an array with el prepended to each of the names in s. So you need to loop through the array to create the new array.
var m = 'My name is ';
function updateMsg(h) {
"use strict";
var el = m + h;
var s = ['Adam', 'Joseph'];
return s.map(function(name) {
return el + ' ' + name;
});
}
var n1 = document.getElementById("msg");
n1.textContent = updateMsg("Sarah")[0];
<div id="msg">
</div>
In Google App Scripts (GAS), I want to be able to add and remove TextBox and TextArea elements to a FlexTable (that's being used as a form) and not worry about how many there are. I've named the text elements based on a counter to make this process easier.
So, is there a way to get the number of inputs (TextBox + TextArea) passed to e.parameter after the form is submitted?
Here's the relevant code from the FlexTable:
function doGet() {
var app = UiApp.createApplication();
var flex = app.createFlexTable().setId('myFlex');
var counter = 0;
var row_counter = 0;
...
var firstnameLabel = app.createLabel('Your FIRST Name');
var firstnameTextBox = app.createTextBox().setWidth(sm_width).setName('input' + counter).setText(data[counter]);
flex.setWidget(row_counter, 1, firstnameLabel);
flex.setWidget(row_counter, 2, firstnameTextBox);
row_counter++;
counter++;
var lastnameLabel = app.createLabel('Your LAST Name');
var lastnameTextBox = app.createTextBox().setWidth(sm_width).setName('input' + counter).setText(data[counter]);
flex.setWidget(row_counter, 1, lastnameLabel);
flex.setWidget(row_counter, 2, lastnameTextBox);
row_counter++;
counter++;
...
var submitButton = app.createButton('Submit Proposal');
flex.setWidget(row_counter, 2, submitButton);
var handler = app.createServerClickHandler('saveProposal');
handler.addCallbackElement(flex);
submitButton.addClickHandler(handler);
var scroll = app.createScrollPanel().setSize('100%', '100%');
scroll.add(flex);
app.add(scroll);
return app;
}
And here's the code for the ClickHandler (notice that I currently have 39 elements in my FlexTable):
function saveProposal(e){
var app = UiApp.getActiveApplication();
var userData = [];
var counter = 39;
for(var i = 0; i < counter; i++) {
var input_name = 'input' + i;
userData[i] = e.parameter[input_name];
}
So, is there a way to get the number of elements (in this case 39) without manually counting them and assigning this value to a variable?
I'm new at this stuff and I'd appreciate your help.
Cheers!
The simplest way is to add a hidden widget in your doGet() function that will hold the counter value like this :
var hidden = app.createHidden('counterValue',counter);// don't forget to add this widget as a callBackElement to your handler variable (handler.addCallBackElement(hidden))
then in the handler function simply use
var counter = Number(e.parameter.counterValue);// because the returned value is actually a string, as almost any other widget...
If you want to see this value while debugging you can replace it momentarily with a textBox...
You can search for arguments array based object.
function foo(x) {
console.log(arguments.length); // This will print 7.
}
foo(1,2,3,4,5,6,7) // Sending 7 parameters to function.
You could use a while loop.
var i = 0;
var userData = [];
while (e.parameter['input' + i] != undefined) {
userData[i] = e.parameter['input' + i];
i++;
};
OR:
var i = 0;
var userData = [];
var input_name = 'input0';
while (e.parameter[input_name] != undefined) {
userData[i] = e.parameter[input_name];
i++;
input_name = 'input' + i;
};