I NEED TO CREATE A DICE OBJECT, so how can I include a dice object into this code?
I am creating a very simple dice roll in javascript. I have to have a dice object with an attribute named value, a roll method, and a printDie method which shows the two die numbers on the page. When I try this code I get "undefined." Any help is appreciated, thank you!
<!doctype html>
<html>
<head>
<meta charset="UTF-8">
<title>Untitled Document</title>
<script>
// dice object attribute named value, method printDie, method roll
function dice(value){
this.value = value;
this.roll = function(roll){
}
this.printDie = function(printDie){
}
}
function roll(){
var die = Math.floor(Math.random()*6)+1;
return die;
}
function printDie(){
this.roll();
var die1 = document.getElementById('die1');
var die2 = document.getElementById('die2');
die1.innerHTML = die1.value;
die2.innerHTML = die2.value;
}
</script>
</head>
<body>
<button onClick="printDie()">Roll Dice</button>
<h1 id="die1"></h1> <h1 id="die2"></h1>
</body>
</html>
There are several problems with your code, the first of which is the use of the this keyword, which will only work if you are making an instance of dice. Also, you are not capturing the result of the roll method.
Look at the comments below for more issues:
// dice object attribute named value, method printDie, method roll
function dice(value){
// The only way the use of the word this will help you here
// is if the function is called as a constructor (var d = new dice())
// Because that's not the case, this refers to the global window
// object, which does not have a value property
this.value = value;
// Here, you are adding a roll property to the global window object
// and assigning a function to it
this.roll = function(roll){
}
// Here, you are creating a printDie property on the global window object
this.printDie = function(printDie){
}
}
// if this function is a function of the dice, it should be added to the
// dice.prototype as in: dice.prototype.roll = function () { var die = . . . }
function roll(){
var die = Math.floor(Math.random()*6)+1;
return die;
}
function printDie(){
// You are calling roll(), which returns a value, but you are not
// capturing that value? Also, no need for this.roll(), use just roll()
this.roll();
var die1 = document.getElementById('die1');
var die2 = document.getElementById('die2');
die1.innerHTML = die1.value;
die2.innerHTML = die2.value;
}
Also, as an FYI, you really should avoid inline HTML event handlers (onclick="") as they create spaghetti code and cause the code you supplied as a value for onclick to be wrapped in a global function, which causes problems if/when the keyword this is used within the callback code. Instead, wire event handlers using the DOM Event Model standard (via JavaScript)
element.addEventListener("eventName", callbackFunction);
Here is working code
I now invoke the object and chain it in the die.roll().printDie()
I also changed the type of button to button to stop submission in some browsers. All the methods are now local to the object you need to create and the click is moved out of the button.
function Dice() {
this.die = [];
this.roll = function(roll) {
this.die = [Math.floor(Math.random() * 6) + 1, Math.floor(Math.random() * 6) + 1]
return this; // for chaining
}
this.printDie = function() {
document.getElementById('die1').innerHTML = this.die[0];
document.getElementById('die2').innerHTML = this.die[1];
}
return this;
}
window.onload=function() {
document.getElementById("rollBut").onclick=function() {
var die = new Dice()
die.roll().printDie();
}
}
<button type="button" id="rollBut">Roll Dice</button>
<h1 id="die1"></h1>
<h1 id="die2"></h1>
Related
I have been working all day trying to pass the value of "returnData.salary" inside the "readData" function to
the object inside the "calculateTax" function which is suppose to take the salary value and calculate state and federal taxes. I am stumped, I can't find anything on the internet which provides a good example for me to work with. The examples are either way to simple or super complex. Any help would be appreciated.
I apologize in advance if I did not submit this question in the correct format. This is my first time asking for help on stackoverflow.
function readForm() {
var returnData = {};
returnData.name = $("#name").val();
returnData.lastName = $("#lastName").val();
returnData.age = $("#age").val();
returnData.gender = $("[name=gender]:checked").val();
returnData.salary = $("#salary").val();
returnData.isManager = $("#isManager").val();
returnData.myTextArea = $("#myTextArea").val();
$("#name2").text(returnData.name);
$("#lastName2").text(returnData.lastName);
$("#age2").text(returnData.age);
$("#gender2").text(returnData.gender);
$("#salary2").text(returnData.salary);
$("#myTextArea2").text(returnData.myTextArea);
if ($(isManager).is(':checked')) {
$("#isManager2").text("Yes");
}
else {
$("#isManager2").text("No");
}
//$("#employeeForm")[0].reset();
} //end of readForm function
function calculateTax() {
console.log("Button Works");
var calculateTax = {
state: function(num) {
num *= 0.09;
return num;
}
, federal: function(num) {
if (num > 10000) {
num *= 0.2;
return num;
}
else {
num * 0.1;
return num;
}
}
, exempt: true
};
}
//Invoke readForm function when the submit button is clicked.
$(document).ready(function () {
$("#btnSubmit").on("click", readForm);
$("#btnCalculate").on("click", calculateTax);
})
</script>
Well, simply put; you can't. Not like this anyway. Or, at least not pass the value to the function directly.
You are using global functions right now, which are not inside a class. If it was inside a class, you could instantiate the class and save it to this (which would be the class' instance). However, I'm assuming classes are a bit over complicated in this case. What you could do, is set variables globally so all functions can use them, like this;
//declare the global variable so it exists for every function
var returnData = {};
function readForm() {
//We do NOT redeclare the "var" again. It's global now.
returnData = {}; //Reset the global variable when this function is called
returnData.name = $("#name").val();
returnData.lastName = $("#lastName").val();
returnData.age = $("#age").val();
returnData.gender = $("[name=gender]:checked").val();
returnData.salary = $("#salary").val();
returnData.isManager = $("#isManager").val();
returnData.myTextArea = $("#myTextArea").val();
//Rest of your function
}
function calculateTax(){
console.log(returnData) //works here
}
Note that you do overwrite global variables, so it's best to reset them on every function call. You might get old data stuck in there, otherwise.
I have 3 "dice" objects created from this custom constructor:
function Dice() {
this.value = 0;
this.keep = false;
this.roll = function() {
this.value = Math.floor(Math.random()*6)+1;
};
}
Then, inside function rollOnce(), I have 3 HTML buttons inside a document.getElementById("paragraph1").innerHTML command that will display each dice's value as follows:
function rollOnce() {
(...)
document.getElementById("paragraph1").innerHTML =
'<button id="diceOne" class="unkept" onclick="keepDice(this.id)">'+dice1.value+'</button> ' +
'<button id="diceTwo" class="unkept" onclick="keepDice(this.id)">'+dice2.value+'</button> ' +
'<button id="diceThree" class="unkept" onclick="keepDice(this.id)">'+dice3.value+'</button> ';
}
Now, function keepDice(diceId) will set attribute class="kept" for each dice/button that has been clicked.
The next thing I want to do is to know which dice variable (dice1, dice2, dice3) has been clicked (in order to keep their value by doing diceN.keep = true;. Because after that there will be another round of the game in which only those dice which are "unkept" will get another diceN.roll() call. But my knowledge is still very limited and I only know how to access (HTML only) elements by using document.getElementsBy(...) (this is the HTML DOM, right? I'm currently learning this at W3Schools).
I have not yet learned about jQuery, AngularJS and all the other cool webdev stuff. So if it is possible to answer using only Javascript it would be much appreciated (even if other libs would make it easier! It's a bonus if there are alternative solutions and I would be happy to learn too!). Is this possible at all?
Thanks in advance,
Maybe something like class="kept-'+dice1.keet+'" onclick="keepDice(1)"
then
function keepDice(index){
dices[index].keep = true;
turns--;
if (turns > 0) {
rollOnce()
}
}
Try this:
function keepDice(id) {
var whichDice;
switch(id) {
case 'diceOne':
whichDice = dice1;
break;
case 'diceTwo':
whichDice = dice2;
break;
case 'diceThree':
whichDice = dice3;
break;
}
whichDice.keep = true;
}
If you stored your dice in an associative array like this:
dice['diceOne'] = new Dice();
dice['diceTwo'] = new Dice();
dice['diceThree'] = new Dice();
you would create the buttons almost the same way
<button id="diceOne" class="unkept" onclick="keepDice(this.id)">dice["diceOne"].value</button>
you could then write your dice function like this
function keepDice(id)
{
dice[id].keep = true;
document.GetElementById(id).setAttribute("class","kept");
//...
}
I came back to this again and realised there's a better way. It's quite a different approach than what you've got so far, but let me explain...
I know your question title is "How to get Javascript object from HTML element" but my answer better serves the question "How to get HTML element from Javascript object" and also better solves the problem you're facing.
First, I set the stage by creating a container element #paragraph1 and a "Roll Once" button which runs the rollOnce() function
<p id="paragraph1"></p>
<button onclick="rollOnce()">Roll Once</button>
Then I create the Dice() Object which takes a parameter - this parameter is the id of the element we wish to use as a container. We must wait for the HTML to load before we can find that container because until then, it simply doesn't exist yet. That's why I have bound a function to the document.onreadystatechange event.
So when the HTML has loaded and the document is ready, I initialise the Object, storing it in a var and the Object has all the required functions built-in for managing it's button.
function Dice(container) {
this.button = document.createElement("button");
this.button.innerHTML = 0;
document.getElementById(container).appendChild(this.button);
this.button.addEventListener('click', function() {
this.className = 'kept';
});
this.roll = function() {
if(this.button.className != 'kept') {
this.button.innerHTML = Math.floor(Math.random()*6)+1;
}
}
}
var dice1;
var dice2;
var dice3;
document.onreadystatechange = function () {
if(document.readyState == "complete") {
dice1 = new Dice("paragraph1");
dice2 = new Dice("paragraph1");
dice3 = new Dice("paragraph1");
rollOnce();
}
}
function rollOnce() {
dice1.roll();
dice2.roll();
dice3.roll();
}
Fully working demonstration is here: http://codepen.io/anon/pen/groEmg
Edit: If you want to get the values of the dice later, you can access the Objects' properties like so: dice1.button.innerHTML
You need to keep track of what has been kept and what has not been kept. It would be useful to hold all the dice functionality inside the dice class. every time you run rollOnce() you must also represent the kept/unkept state in the className.
Here's an example including what I gather is your current initialisation - define var dice then define rollOnce() then run rollOnce()
function Dice() {
this.value = 0;
this.kept = false;
this.roll = function() {
if(!this.kept) this.value = Math.floor(Math.random()*6)+1;
};
this.keep = function(id) {
this.kept = true;
document.getElementById(id).className = 'kept';
}
}
var dice1 = new Dice();
var dice2 = new Dice();
var dice3 = new Dice();
function rollOnce() {
dice1.roll();
dice2.roll();
dice3.roll();
document.getElementById("paragraph1").innerHTML =
'<button id="diceOne" class="'+(dice1.kept?'kept':'keep')+'" onclick="dice1.keep(\'diceOne\')">'+dice1.value+'</button> ' +
'<button id="diceTwo" class="'+(dice2.kept?'kept':'keep')+'" onclick="dice2.keep(\'diceTwo\')">'+dice2.value+'</button> ' +
'<button id="diceThree" class="'+(dice3.kept?'kept':'keep')+'" onclick="dice3.keep(\'diceThree\')">'+dice3.value+'</button> ';
}
rollOnce();
I've made it pass an ID to Dice.keep(id) just to have a live update of the DOM element which represents this Object variable.
Some clarification on the classnames since you're a beginner: I used ternary logic operators to quickly perform an IF THEN ELSE
So the part that says dice1.kept?'kept':'keep'
Actually means IF dice1.kept THEN 'kept' ELSE 'keep'
You can put a blank '' instead of 'keep' if you like since I don't think it's being used (but you might use it for CSS). Of course, there is plenty of room for improvement all over this code, but I wanted to keep it as similar to your sample code as possible. In fact, the first thing I would do is probably change the onclick to this: onclick="dice1.keep(this)" and then change your object like:
this.keep = function(button) {
this.kept = true;
button.className = 'kept';
}
http://codepen.io/anon/pen/MyrxyX
Edit: here's a slightly modified version where the Dice() object is agnostic to the DOM but still provides all the relevant data: http://codepen.io/anon/pen/MyrxbB
I am making a simple hmtl/js game. I'd like to have all the data of the Game in DataofGame. It is like tennis, it is simpler than tennis: there is only set and match. changeinSet is called on click.
But I think i have a problem with private variable so it doesn't work.
Uncaught TypeError: Cannot read property 'WordsoftheGame' of undefined
//Added
document.getElementById('playboutton').addEventListener('click', newGame);
function newGame() {
var DataofGame = new newGameData();
}
// New game
function newGameData() {
this.pointTeam1 = 0;
this.pointTeam2 = 0;
this.WordsoftheGame = ShuffleListe();
this.ASet = new aSet();
}
//How the set is manage ********************
function aSet() {
var oneWord = DataofGame.ListeMot;
// display the word and delete it from the list
document.getElementById('jouer').innerHTML = oneWord[0];
DataofGame.WordsoftheGame.shift();
this.turn = true;
this.score = 0;
}
function changeinSet() {
DataofGame.ASet.score += 1;
//This is the other team's turn:
DataofGame.ASet.turn = !DataofGame.ASet.turn;
};
//shuffle liste
ListOfWords = ['Artiste', 'Appeler', 'Cheval', 'Choisir', 'Ciel', 'Croire', 'Dormir'];
function ShuffleListe() {
data = shuffle(ListOfWords);
return data;
}
function newGameData(){
this.pointTeam1=0;
this.pointTeam2=0;
this.WordsoftheGame= ShuffleListe();
this.ASet=new aSet();
}
//How the set is manage ********************
function aSet(){
var oneWord=DataofGame.ListeMot;
// display the word and delete it from the list
document.getElementById('jouer').innerHTML=oneWord[0];
DataofGame.WordsoftheGame.shift(); // << DataofGame not assigned yet
this.turn=true;
this.score=0;
}
Here when you're accessing DataofGame, it's not yet assigned because you're inside the constructor when calling aSet().
What you want to achieve is not completely clear, but if it's adding an ASet method to your object, you could write something like this:
function newGameData(){
this.pointTeam1=0;
this.pointTeam2=0;
this.WordsoftheGame= ShuffleListe();
this.ASet = function() {
// your code
};
}
NB your coding style for names is a bit messy, you should use uppercases consistently. The usage is to start constructor names with uppercases, the rest in lower cases.
You can let the function return an object with the data or just set the object.
function newGameData(){
return {
pointTeam1 : 0,
pointTeam2 : 0,
WordsoftheGame : ShuffleListe(),
ASet : new aSet()
}
}
But I would recommend to search for how to work with objects in javascript. Maybe this helps:
https://developer.mozilla.org/en-US/docs/Web/JavaScript/Introduction_to_Object-Oriented_JavaScript
I'm not very experienced with JavaScript (This is my first real thing I've made with it), so my syntax is probably horrendous. I'm trying to get 5 variables to update whenever the input box is changed, however for some reason, they just won't update! I've Googled for solutions but nothing seems to work
document.getElementById("name").addEventListener("keyup", updateName);
document.getElementById("id").addEventListener("keyup", updateID);
document.getElementById("quantity").addEventListener("keyup", updateNumber);
document.getElementById("buybase").addEventListener("keyup", updateBuy);
document.getElementById("sellbase").addEventListener("keyup", updateSell);
Here's a JSFiddle
http://jsfiddle.net/q1w6v12u/
Here's the live site
http://ts-mc.net/pricing/chest.html
You have declared all those variables as local variables(since you have used var inside the method), which exists only inside the methods in which they are declared, declare them as global variables.
So now you have a global variable and a local one which exists only inside the method, so any changes you have done to the variable inside the method will not get reflected in the variable which is in the global scope.
function updateName() {
ITEMNAME = document.getElementById("name").value;
}
Why are you declaring variables twice:
var ITEMNAME = "NULL";//first
function updateName() {
var ITEMNAME = document.getElementById("name").value;
^^^==========>second
}
Just do this:
var ITEMNAME = "NULL";
function updateName() {
ITEMNAME = document.getElementById("name").value;
}
To solve your immediate issue with variables not updating you could change your JS to this:
...
function updateName() {
ITEMNAME = document.getElementById("name").value;
}
function updateID() {
ITEMID = document.getElementById("id").value;
}
function updateNumber() {
NUMBER = document.getElementById("quantity").value;
}
function updateBuy() {
BUYCOST = document.getElementById("buybase").value;
}
function updateSell() {
SELLCOST = document.getElementById("sellbase").value;
}
function Replace() {
BUYCOST = BUYCOST * 4 * NUMBER;
SELLCOST = SELLCOST / 4 * NUMBER;
var DONE = BASE.replace(/ITEMNAME/igm, ITEMNAME);
var DONE = DONE.replace(/ITEMID/igm, ITEMID);
var DONE = DONE.replace(/NUMBER/igm, NUMBER);
var DONE = DONE.replace(/BUYCOST/igm, BUYCOST);
var DONE = DONE.replace(/SELLCOST/igm, SELLCOST);
document.getElementById("output").innerHTML = DONE;
}
The cause of the problem is due to you redefining your variables within function scope instead of using the ones already existing in the parent.
There are some issues with your HTML also, with not terminating your elements properly for example <input ... />
I just started using javascript and I'm missing something important in my knowledge. I was hoping you could help me fill in the gap.
So the script I'm trying to run is suppose to count the characters in a text field, and update a paragraph to tell the user how many characters they have typed. I have an object called charCounter. sourceId is the id of the text area to count characters in. statusId is the id of the paragraph to update everytime a key is pressed.
function charCounter(sourceId, statusId) {
this.sourceId = sourceId;
this.statusId = statusId;
this.count = 0;
}
There is one method called updateAll. It updates the count of characters and updates the paragraph.
charCounter.prototype.updateAll = function() {
//get the character count;
//change the paragraph;
}
I have a start function that is called when the window loads.
function start() {
//This is the problem
document.getElementbyId('mytextfield').onkeydown = myCounter.updateAll;
document.getElementbyId('mytextfield').onkeyup = myCounter.updateAll;
}
myCounter = new charCounter("mytextfield","charcount");
window.onload = start;
The above code is the problem. Why in the world can't I call the myCounter.updateAll method when the event is fired? This is really confusing to me. I understand that if you call a method likeThis() you'll get a value from the function. If you call it likeThis you are getting a pointer to a function. I'm pointing my event to a function. I've also tried calling the function straight up and it works just fine, but it will not work when the event is fired.
What am I missing?
Thanks for all the answers. Here's three different implementations.
Implementation 1
function CharCounter(sourceId, statusId) {
this.sourceId = sourceId;
this.statusId = statusId;
this.count = 0;
};
CharCounter.prototype.updateAll = function() {
this.count = document.getElementById(this.sourceId).value.length;
document.getElementById(this.statusId).innerHTML = "There are "+this.count+" charactors";
};
function start() {
myCharCounter.updateAll();
document.getElementById('mytextfield').onkeyup = function() { myCharCounter.updateAll(); };
document.getElementById('mytextfield').onkeydown = function() { myCharCounter.updateAll(); };
};
myCharCounter = new CharCounter('mytextfield','charcount');
window.onload = start;
Implementation 2
function CharCounter(sourceId, statusId) {
this.sourceId = sourceId;
this.statusId = statusId;
this.count = 0;
};
CharCounter.prototype.updateAll = function() {
this.count = document.getElementById(this.sourceId).value.length;
document.getElementById(this.statusId).innerHTML = "There are "+ this.count+" charactors";
};
CharCounter.prototype.start = function() {
var instance = this;
instance.updateAll();
document.getElementById(this.sourceId).onkeyup = function() {
instance.updateAll();
};
document.getElementById(this.sourceId).onkeydown = function() {
instance.updateAll();
};
};
window.onload = function() {
var myCounter = new CharCounter("mytextfield","charcount");
myCounter.start();
};
Implementation 3
function CharCounter(sourceId, statusId) {
this.sourceId = sourceId;
this.statusId = statusId;
this.count = 0;
};
CharCounter.prototype.updateAll = function() {
this.count = document.getElementById(this.sourceId).value.length;
document.getElementById(this.statusId).innerHTML = "There are "+this.count+" charactors";
};
function bind(funcToCall, desiredThisValue) {
return function() { funcToCall.apply(desiredThisValue); };
};
function start() {
myCharCounter.updateAll();
document.getElementById('mytextfield').onkeyup = bind(myCharCounter.updateAll, myCharCounter);
document.getElementById('mytextfield').onkeydown = bind(myCharCounter.updateAll, myCharCounter);
};
myCharCounter = new CharCounter('mytextfield','charcount');
window.onload = start;
I think you are having problems accessing your instance members on the updateAll function, since you are using it as an event handler, the context (the this keyword) is the DOM element that triggered the event, not your CharCounter object instance.
You could do something like this:
function CharCounter(sourceId, statusId) {
this.sourceId = sourceId;
this.statusId = statusId;
this.count = 0;
}
CharCounter.prototype.updateAll = function() {
var text = document.getElementById(this.sourceId).value;
document.getElementById(this.statusId).innerHTML = text.length;
};
CharCounter.prototype.start = function() {
// event binding
var instance = this; // store the current context
document.getElementById(this.sourceId).onkeyup = function () {
instance.updateAll(); // use 'instance' because in event handlers
// the 'this' keyword refers to the DOM element.
};
}
window.onload = function () {
var myCharCounter = new CharCounter('textarea1', 'status');
myCharCounter.start();
};
Check the above example running here.
The expression "myCounter.updateAll" merely returns a reference to the function object bound to "updateAll". There's nothing special about that reference - specifically, nothing "remembers" that the reference came from a property of your "myCounter" object.
You can write a function that takes a function as an argument and returns a new function that's built specifically to run your function with a specific object as the "this" pointer. Lots of libraries have a routine like this; see for example the "functional.js" library and its "bind" function. Here's a real simple version:
function bind(funcToCall, desiredThisValue) {
return function() { funcToCall.apply(desiredThisValue); };
}
Now you can write:
document.getElementById('myTextField').onkeydown = bind(myCounter.updateAll, myCounter);
You can:
function start() {
//This is the problem
document.getElementbyId('mytextfield').onkeydown = function() { myCounter.updateAll(); };
document.getElementbyId('mytextfield').onkeyup = function() { myCounter.updateAll(); };
}
In ASP.Net Ajax you can use
Function.createDelegate(myObject, myFunction);
I want to do something like this but simpler.
The idea is to have the user click on bolded text and have a text field appear where they can change all the values of a role-playing character. Then when the value is changed, have the text field disappear again replaced by the updated bolded text value.
I can do this already using an annoying text box alert. But I would rather have something similar to this below to replace all that.
I have searched for months and CMS is the closest to answering my question in the simplest way with a full html example. Nobody else on the net could.
So my question is, how do I do this?
I have multiple objects(characters) and need this.elementId to make this work.
I've modified this example but it breaks if I try to add to it.
html>
head>
title>Sandbox
/head>
body>
input id="textarea1" size=10 type=text>
script>
function CharCounter(sourceId, statusId)
{this.sourceId=sourceId;
this.statusId=statusId;
this.count=0;
}
CharCounter.prototype.updateAll=function()
{text=document.getElementById(this.sourceId).value
document.getElementById(this.statusId).innerHTML=text
}
CharCounter.prototype.start=function()
{instance=this
document.getElementById(this.sourceId).onkeyup=function ()
{instance.updateAll()}
}
window.onload=function ()
{myCharCounter=new CharCounter('textarea1', 'status')
myCharCounter.start()
}
/script>
/body>
/html>