Using ng-repeat to provide multiple buttons - javascript

I'm trying to create a list of buttons with ng-repeat, each of which can be clicked to perform the same function, in this case, roll a die. How do I get it so that each button has it's own unique reference to the results? Currently when one button is clicked, the correct calculation is done, but the results are displayed next to every button, not just the button that was clicked.
Here is what I have so far (fiddle):
in html
...
<div ng-repeat="die in dice">
<button type="button" class="btn btn-default" ng-click="rollDice(1, die, 0, scope)">{{"d" + die}}</button>
<span>{{result}}</span>
</div>
...
in controller.js
angular.module('diceAngularApp')
.controller('DiceController', function ($scope) {
$scope.dice = [2,3,4,6,8,10,12,20,100];
$scope.result = 0;
$scope.rollDice = function(numRolls, numSides, bonus) {
var total = "";
var rolls = new Array( numRolls );
for (var i = 0; i < numRolls; i++ ) {
var roll = randomInt( 1, numSides );
rolls[i] = roll;
total += roll;
}
$scope.result = total;
}
function randomInt( intMin, intMax ) {
intMax = Math.round( intMax );
intMin = Math.round( intMin );
return intMin + Math.floor( intMax * (Math.random() % 1));
}
});

You can add a controller for each of the divs surrounding the button, then they get their own scope.
page.html
...
<div ng-repeat="die in dices" ng-controller="DieCtrl">
<button type="button" class="btn btn-default" ng-click="rollDice(1, die, 0, scope)">{{"d" + die}}</button>
<span>{{result}}</span>
</div>
...
controller.js
app.controller('DieCtrl', function ($scope) {
...
});

ng-repeat creates a new child scope for each iteration, but the $scope variable in your rollDice method is the parent scope. The easiest way would be to return the result from rollDice instead of setting a scope property directly and set that value in your ng-click (fiddle):
ng-click="result = rollDice(1, die, 0)"
Another way would be to access the child scope by passing the $event variable and use angular.element($event.target).scope(): (fiddle):
<div ng-repeat="die in dice">
<button type="button"
class="btn btn-default"
ng-click="rollDice(1, die, 0, $event)"> <!-- pass $event -->
{{"d" + die}}<br/>
</button>
<span>{{result}}</span>
</div>
Javascript:
$scope.rollDice = function(numRolls, numSides, bonus, $event) {
var total = "";
var rolls = new Array( numRolls );
for (var i = 0; i < numRolls; i++ ) {
var roll = randomInt( 1, numSides );
rolls[i] = roll;
total += roll;
}
// get scope for element sending event and use it
angular.element($event.target).scope().result = total;
}
Yet another way would be to have an object on your child scope to hold the results and pass that object to your click function. You can initialize the object with ng-init (fiddle)
<div ng-repeat="die in dice">
<button
ng-init="results = { result: 0 }"
type="button"
class="btn btn-default"
ng-click="rollDice(1, die, 0, results)">
{{"d" + die}}<br/>
</button>
<span>{{results.result}}</span>
</div>
Javascript:
$scope.rollDice = function(numRolls, numSides, bonus, results) {
var total = "";
var rolls = new Array( numRolls );
for (var i = 0; i < numRolls; i++ ) {
var roll = randomInt( 1, numSides );
rolls[i] = roll;
total += roll;
}
results.result = total;
}

Related

JS NaN after array[index]

I just started programming with js again and having some trouble.
This is the code i have problems with:
var actual = [10,50,20];
var sum = 0;
for(var i = actual.length; i > 0; i--){
sum = sum + actual[i];
}
What did i do wrong?
Start loop from actual.length-1, because every array starts from 0, so last element is actual.length-1 not actual.length.
I see Your calculator code is too complicated.
You do low level operation to add just "1" You multiply all things to 10 and add 1.
Be simple (;
var inputElement = document.getElementById("input");
var resultElement = document.getElementById("result");
var accept = [0,1,2,3,4,5,6,7,8,9,'-','+','calc'];
var input = [];
function op(value){
if(accept.indexOf(value) < 0) {
return;
}
if(value == 'calc') {
return calc();
}
input.push(value);
inputElement.innerHTML = input.join('');
}
function calc() {
resultElement.innerHTML = eval(input.join(''));
input = [];
}
<button onclick="op(1)">1</button>
<button onclick="op(2)">2</button>
<button onclick="op(3)">3</button>
<br/>
<button onclick="op(4)">4</button>
<button onclick="op(5)">5</button>
<button onclick="op(6)">6</button>
<br/>
<button onclick="op(7)">7</button>
<button onclick="op(8)">8</button>
<button onclick="op(9)">9</button>
<br/>
<button onclick="op(0)">0</button>
<button onclick="op('.')">.</button>
<button onclick="op('calc')">=</button>
<hr/>
<button onclick="op('+')">+</button>
<button onclick="op('-')">-</button>
<hr/>
INPUT:<div id="input"></div>
DISPLAY:<div id="result"></div>

How to reset a counter back to 0 with a button in javascript?

I have a counter in javascript right now and a button that adds 1 value to the counter, this is what I have so far:
var counter = 0;
var a = 0;
var add = function(valueToAdd){
a += valueToAdd;
document.getElementById('Value').innerHTML = a;
}
Value $<span id="Value">0</span>
<button width="500" height="500" id = add class="button button1" onclick="javascript:add(1)">Add Value</button>
I need a button to reset the counter back to 0 any help is appreciated.
Add a button, reset function and set values to "0" as shown in code below:
<button width="500" height="500" id ="reset" class="button button1"
onclick="javascript:reset()">Reset Value</button>
<script type="text/javascript">
var reset= function(){
a = 0;
document.getElementById('Value').innerHTML = a;
}
</script>
BTW you declared var count = 0 in your code (question) but not using that (apparently).
Some tips:
You correctly stored a variable to keep track of the counter, all you needed to do in a reset function was to change the value back to 0.
Keep your Javascript away from your HTML. Here's a good article
Your code should be properly formatted when posting on Stack Overflow.
Here's a cleaner solution:
HTML:
Value $<span id="Value">0</span>
<button id="add">Add Value</button>
<button id="reset">Reset</button>
Javascript:
var a = 0;
var add = function(valueToAdd) {
a += valueToAdd;
document.getElementById('Value').innerHTML = a;
}
var reset = function() {
a = 0;
document.getElementById('Value').innerHTML = 0;
}
var addButton = document.querySelector("#add");
var resetButton = document.querySelector("#reset");
addButton.addEventListener("click", function() {
add(1);
})
resetButton.addEventListener("click", function() {
reset();
})
JSFiddle: https://jsfiddle.net/sfh51odm/
Do not define a out of function as a general variable. Every time set the current value to a and continue. So you can get back to zero:
var counter = 0;
var add = function(valueToAdd){
var a = parseInt(document.getElementById('Value').innerHTML);
a += valueToAdd;
document.getElementById('Value').innerHTML = a;
}
function reset(){
document.getElementById('Value').innerHTML=0;
}
Value $<span id="Value">0</span>
<button width="500" height="500" id = add class="button button1" onclick="javascript:add(1)">Add Value</button>
<button width="500" height="500" id = add class="button button1" onclick="javascript:reset()">Reset</button>
var a = 0;
var displayValue = document.getElementById('Value');
var updateValue = function () {
displayValue.innerHTML = a;
};
var add = function (valueToAdd) {
a += valueToAdd;
updateValue();
};
var reset = function () {
a = 0;
updateValue();
};
Value $<span id="Value">0</span>
<button onclick="add(1)">Add 1</button>
<button onclick="reset()">Reset</button>
if you need to do a page refresh (like if you press F5 on the keyboard) this will work for you.
the "location.reload();" will work also.
change '.again' to a btn name you want.
document.querySelector('.again').addEventListener('click', function () { location.reload(); });

JavaScript function to generate dropdowns / remove dropdown menus

I am trying to add and remove dropdown <select>s to a form on a button click. This is the code I have currently. I could have sworn I had this working last night, but when I went to work some more on my project this morning, the dropdowns wouldn't add / remove correctly.
function DropDowns(){
this.counter = 0;
this.addDropdown = function (divname) {
var newDiv = document.createElement('div');
var html = '<select name="cookie' + this.counter + '">', i;
for (i = 0; i < cookies_drop.length; i++) {
html += "<option value='" + cookies_drop[i] + "'>" + cookies_drop[i] + "</option>"
}
html += '</select>';
newDiv.innerHTML = html;
document.getElementById(divname).appendChild(newDiv);
this.counter++;
}
this.remDropdown = function() {
$('#dropdowns-container').find('div:last').remove();
this.counter--;
}
}
var dropsTest = new DropDowns();
HTML:
<form action='' method=post id="dropdowns-container">
<button id="add_cookie" type="button" onclick="dropsTest.addDropdown('dropdowns-container');">add cookie</button>
<button id="rem_cookie" type="button" onclick="dropsTest.remDropdown();">remove cookie</button>
<input name="cookies" type=submit value="submit">
</form>
I can only figure out the main problem may be on the server side when you create the cookies_drop variable using json_encode.
Other problems may reside in:
A test on the parameter of addDropdown function is suggested to check if it's valid
In the function remDropdown the decrement of the counter variable must be done only if the element is actually removed
You mixed jQuery and javaScript
Instead of using directly the createElement, making the code more simple and readable, you used the innerHTML property.
So, my snippet is:
// I assume you used something like:
// var cookies_drop = JSON.parse( '<?php echo json_encode($data) ?>' );
var cookies_drop = [{text: "Text1", val: "Value1"},
{text: "Text2", val: "Value2"},
{text: "Text3", val: "Value3"}];
function DropDowns() {
this.counter = 0;
this.addDropdown = function (divname) {
var divEle = document.querySelectorAll('form[id=' + divname + ']');
if (divEle.length != 1) {
return; // error
}
var newDiv = document.createElement('div');
var newSelect = document.createElement('select');
newSelect.name = 'cookie' + this.counter;
newDiv.appendChild(newSelect);
for (var i = 0; i < cookies_drop.length; i++) {
var newOption = document.createElement('option');
newOption.value = cookies_drop[i].val;
newOption.text = cookies_drop[i].text;
newSelect.appendChild(newOption);
}
divEle[0].appendChild(newDiv);
this.counter++;
}
this.remDropdown = function () {
var lastDiv = document.querySelectorAll('#dropdowns-container div:last-child');
if (lastDiv.length == 1) {
lastDiv[0].parentNode.removeChild(lastDiv[0]);
this.counter--;
}
}
}
var dropsTest = new DropDowns();
<form action="" method="post" id="dropdowns-container">
<button id="add_cookie" type="button" onclick="dropsTest.addDropdown('dropdowns-container');">add cookie</button>
<button id="rem_cookie" type="button" onclick="dropsTest.remDropdown();">remove cookie</button>
<input name="cookies" type=submit value="submit">
</form>

Why does my value keep returning as "NaN"?

Here is the link to the jsbin.
I was almost finished with my project (I thought I was) and then I tested it out. It is supposed to add buttons with the chosen title of the task and the number of points it awards. Every time the button is clicked the points would be added on to the "Points" section and every 500 points my "Level" would increase.
Upon finishing it, it worked. Then I went to clear the localStorage since that's what I used to save the information, but I wanted to start over. When I did that, the 'Points' section, or 'results' value, keeps returning as "NaN". The code is exactly the same as it was when it worked. Can someone please tell me how to fix this problem, thank you in advance.
Here is the code. (Used bootstrap for CSS)
HTML
<center>
<br>
<h2> Add task </h2>
<div class='well' style='width:500px' id="addc">
<div id="addc">
<input class='form-control' style='width:450px' id="btnName" type="text" placeholder="New Task" /><br>
<input class='form-control' style='width:450px' id="btnPoints" type="text" placeholder="Points" /><br>
<button id="addBtn">Add</button>
</div> </div>
<div class='well' style='width:230px' id="container">
</div>
<hr style="width:400px;">
<h3>Points </h3>
<div id="result">0</div>
</div>
<hr style="width:400px;">
<div style="width:400px;">
<h3>Level
<p id='lvl'>0</p>
</div>
<hr style="width:400px;">
</center>
JavaScript
var res = document.getElementById('result');
res.innerText = localStorage.getItem('myResult');
var level = document.getElementById('lvl');
level.textContent = localStorage.getItem('myLevel');
var btns = document.querySelectorAll('.btn');
for(var i = 0; i < btns.length; i++) {
btns[i].addEventListener('click', function() {
addToResult(this.getAttribute('data-points'));
this.parentNode.removeChild(this.nextElementSibling);
this.parentNode.removeChild(this);
});
}
var addBtn = document.getElementById('addBtn');
addBtn.className = "btn btn-default";
addBtn.addEventListener('click', function() {
var container = document.getElementById('container');
var btnName = document.getElementById('btnName').value;
var btnPoints = parseInt(document.getElementById('btnPoints').value);
if(!btnName)
btnName = "Button ?";
if(!btnPoints)
btnPoints = 50;
var newBtn = document.createElement('button');
var newPnt = document.createElement('span');
newBtn.className = 'btn btn-danger';
newBtn.innerText = btnName;
newBtn.setAttribute('data-points', btnPoints);
newBtn.addEventListener('click', function() {
addToResult(this.getAttribute('data-points'));
this.parentNode.removeChild(this.nextElementSibling);
this.parentNode.removeChild(this);
});
newPnt.className = 'label';
newPnt.innerText = "+" + btnPoints;
container.appendChild(newBtn);
container.appendChild(newPnt);
});
function addToResult(pts) {
var result = document.getElementById('result');
result.innerText = parseInt(result.innerText) + parseInt(pts);
var lvl = 0;
var a = 100;
while (result.innerText > 5*a) {
lvl+=1;
a+=100;
}
document.getElementById('lvl').innerText = lvl;
var res = document.getElementById('result');
localStorage.setItem("myResult", res.innerText);
var level = document.getElementById('lvl');
localStorage.setItem("myLevel", level.textContent);
}
You were parsing result.innerText as a number, but its value, initially, was actually either NaN or nothing, both which end up being NaN. One fix is to just check if it parsed to a number, and if it didn't, fall back to 0.
I just basically changed that and removed some getElementByIds that, in my opinion, were redundant, check the addToResult function:
http://jsfiddle.net/owc26a0p/1/
function addToResult(pts) {
// NaN is falsy, so you can just use || to make a fallback to 0
var result = parseInt(resDiv.innerText, 10) || 0,
lvl = 0,
a = 100;
result = result + parseInt(pts, 10) || 0;
while (result > 5 * a) {
lvl += 1;
a += 100;
}
resDiv.innerText = result;
levelDiv.innerText = lvl;
localStorage.setItem("myResult", result);
localStorage.setItem("myLevel", levelDiv.textContent);
}
I ended up using jsFiddle since I couldn't always get jsBin to save my changes. Good luck.

Using an array to toggle different images

First, I cannot get morscreens[i] to produce the image from the array that I want. When I have it as is, it literally makes a [<] button, says literally "morscreens[i]" then the [>] button. when I surround the morscreens[i] with quotes (exiting then re-entering quoted text), I get the error morshots() is not defined.
Second, if I want the buttons to cycle through, should I use subroutines morPrev() and morNext() to do so? My worry is getting the value I want to be returned out of scope and placed in the appropriate locations. I worry that simply using i++ and i-- will not be enough for it to work properly, even with the 2 if statements.
var mordorscreens = new Array();
mordorscreens[0] = '<img src=\"http://i.imgur.com/83HCt.png\" alt=\"scrns1\">';
mordorscreens[1] = '<img src=\"http://i.imgur.com/5mWIy.png\" alt=\"scrns1\">';
mordorscreens[2] = '<img src=\"http://i.imgur.com/pPafl.png\" alt=\"scrns1\">';
function morshots()
{
var i = 0;
var mordor = document.getElementById("ss1");
mordor.innerHTML = '<button onClick="morPrev();"> < </button> mordorscreens[i] <button onClick="morNext();"> > </button> ';
if (i<0) {i=2};
if (i>2) {i=0};
}
This line
'<button onClick="morPrev();"> < </button>
mordorscreens[i] <button onClick="morNext();"> > </button> ';
is supposed to look like
'<button onClick="morPrev();"> < </button>'
+ mordorscreens[i] + '<button onClick="morNext();"> > </button>';
I think its a bad idea to expose the variable i to iterate over the images.
Better to assign the event handlers in Javascript instead HTML..
Try this code
HTML
<div id="ss1">
<button id="previous"> < </button>
<span id="imageSpan"></span>
<button id="next"> > </button>
</div>
Javascript
var mordorscreens = [];
mordorscreens[0] = '<img src="http://i.imgur.com/83HCt.png" alt="scrns1">';
mordorscreens[1] = '<img src="http://i.imgur.com/5mWIy.png" alt="scrns1">';
mordorscreens[2] = '<img src="http://i.imgur.com/pPafl.png" alt="scrns1">';
function morshots() {
var i = 0;
var elem = document.getElementById('imageSpan');
elem.innerHTML = mordorscreens[i];
// Data Attribute that holds the initial
// image number
elem.setAttribute('data-number', i);
}
// Call The function
morshots();
// Assign Event handlers
var buttons = document.getElementsByTagName('button');
for (var j = 0; j < buttons.length; j++) {
// Add Click events to the button
buttons[j].addEventListener('click', clickHandler);
}
function clickHandler() {
var elem = document.getElementById('imageSpan');
// Store the current Image Number in a HTML5 data-attribute
var currImage = parseInt(elem.getAttribute('data-number'), 10);
if (this.id === 'previous') {
currImage--;
currImage = currImage < 0 ? 2 : currImage;
}
else if (this.id === 'next') {
currImage++;
currImage = currImage > 2 ? 0 : currImage;
}
// Set the current Image Number
elem.setAttribute('data-number', currImage);
elem.innerHTML = mordorscreens[currImage];
}
Check JSBin Demo
This is a string with no variables in it:
mordor.innerHTML = '<button onClick="morPrev();"> < </button> mordorscreens[i] <button onClick="morNext();"> > </button> ';
You need to break out your value:
mordor.innerHTML = '<button onClick="morPrev();"> < </button>' + mordorscreens[i] + '<button onClick="morNext();"> > </button> ';

Categories