简体   繁体   中英

How to get Javascript object from HTML element

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");
    //...
}

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 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

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM