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> ';
Related
I'm creating a choose your own adventure game that uses a health bar and changing texts.
My health bar is able to change with my current code but the text does not. Is there something I am missing? What can I do?
The two buttons are identified with "btn q1" and it reads "Question1", and "btn q2" and it reads "Question2". I would like to change "Question1" to "Question1A", etc.
Here is my html for the buttons:
<div class="click">
<span class="btn q1" id="btn q1" onclick="remove(); change();">
Question1
</span>
<span class="btn q2" id="btn q2" onclick="remove(); change();">
Question2
</span>
</div>;
And my javascript:
var _Health = 100;
function remove() {
let addHealth = document.getElementById("health");
_Health += 20;
if (addHealth) {
addHealth.style.width = _Health + "%";
addHealth.innerHTML = _Health + "ep";
}
}
function remove() {
let damage = document.getElementById("health");
_Health -= 10;
if (damage) {
damage.style.width = _Health + "%";
damage.innerHTML = _Health + "ep";
}
}
function change() {
var elem = document.getElementById("btn q1");
if ((elem.value = "Question1")) elem.value = "Question1A";
else elem.value = "Question1B";
}
function change() {
var elem = document.getElementById("btn q2");
if (elem.value == "Question2") elem.value = "Question2A";
else elem.value = "Question2B";
}
You can’t create functions with same name. You should create remove1() and remove2() for example, and call them into the button. But it is not the right way: you need to generalise the functions. Consider the example of Manuel in the comment: it is enough to pass the parameter with the name of the button, and execute all the stuffs with the name passed.
<span class="btn_q1" id="btn_q1" onclick= "remove(10); change(“btn_q1”, “Question1A”);">Question1</span>
<span class="btn_q2" id="btn_q2" onclick= "remove(20); change(“btn_q2”,”Question1B”);">Question2</span>
</div>
And In the js:
function change(btn,value)
{
var elem = document.getElementById(btn);
elem.value = value;
}
function remove(n) {
let addHealth = document.getElementById('health')
_Health += n;
if (addHealth) {
addHealth.style.width = _Health + '%';
addHealth.innerHTML = _Health + 'ep';
}
}
Last thing: don’t use namespaces in the ids. Use underscore instead of space (same in classes)
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>
I'm working on parsing JSON data and converting it to html form.
I'm using the javascript push function, which I thought would push the data into the array I've designated it to in the order I push it. However, whenever I push a new div element, it is automatically closed after being pushed making the html come out in a different order I want. Is there a way I can prevent this?
JavaScript:
$(function(){
var container = $('.panel-body');
var jsonObj = $.parseJSON('{"fields":[{"label":"Nafn form / Form name","field_type":"sFormName","required":false,"field_options":{"size":"small"},"cid":"c2"},{"label":"Spurning 1 ","field_type":"QuestionText","required":false,"field_options":{"size":"small"},"cid":"c5"},{"label":"Spurning 2","field_type":"QuestionCheckbox","required":false,"field_options":{"options":[{"label":"","checked":false},{"label":"","checked":false}]},"cid":"c9"},{"label":"Spunring 4","field_type":"QuestionRadio","required":false,"field_options":{"options":[{"label":"Val","checked":false},{"label":"VAl ","checked":false},{"label":"Val","checked":false}],"include_other_option":false},"cid":"c13"},{"label":"Spurning með multi","field_type":"QuestionMultiBegin","required":false,"field_options":{"options":[{"label":"","checked":false},{"label":"","checked":false}]},"cid":"c17"},{"label":"Spurning","field_type":"QuestionDropdown","required":false,"field_options":{"options":[{"label":"Val","checked":false},{"label":"Val","checked":false},{"label":"Val","checked":false}],"include_blank_option":false},"cid":"c21"},{"label":"Skráning","field_type":"Registration","required":false,"field_options":{"options":[{"label":"Notendanafn / Username"},{"label":"Lykilorð / Password"}],"include_blank_option":false},"cid":"c25"}]}');
var body = [];
var headerData = jsonObj.fields;
console.log(headerData);
for (var i = 0; i < headerData.length; i++) {
if(jsonObj.fields[i].field_type == "sFormName") {
body.unshift("<div class='panel panel-default panel-element'><div class='panel-heading'>" + jsonObj.fields[i].label)
} else {
body.push("<div class='panel panel-default panel-element'><div class='panel-heading'>" + jsonObj.fields[i].label);
}
if (jsonObj.fields[i].field_type == "QuestionText") {
body.push("<div class='panel-body'><textarea class='large-text form-control'></textarea></div>");
} else if (jsonObj.fields[i].field_type == "QuestionParagraph") {
body.push(jsonObj.fields[i].field_options.description);
} else if (jsonObj.fields[i].field_type == "QuestionDropdown") {
var data = jsonObj.fields[i].field_options.options;
body.push("<div class='panel-body'><div class='dropdown'><button class='btn btn-default dropdown-toggle' type='button' data-toggle='dropdown' id='dropdownMenu1' aria-haspopup='true' aria-expanded='true'>" + jsonObj.fields[i].field_options.options[0].label + "<span class='caret'></span></button>");
body.push("<ul class='dropdown-menu' aria-labelledby=dropdownMenu1'>");
for(var j = 0; j < data.length; j++) {
body.push("<li><a href='#'>" + jsonObj.fields[i].field_options.options[j].label + "</a></li>");
}
body.push("</ul></div></div>");
} else if (jsonObj.fields[i].field_type == "QuestionRadio") {
var data = jsonObj.fields[i].field_options.options;
body.push("<div class='panel-body'>");
for(var j = 0; j < data.length; j++) {
body.push("<div class='radio'><div class='controls'><input type='radio' name='radio'></input>" + jsonObj.fields[i].field_options.options[j].label);
}
body.push("</div></div></div></div>");
} else if (jsonObj.fields[i].field_type == "Registration") {
body.push("<div class='panel-body'>");
body.push("<div class='form-group'><form class='reg-form' role='form'><div class='form-group'><label for='email'>" + jsonObj.fields[i].field_options.options[0].label + "</label>");
body.push("<input type'email' class='form-control' id='email'></div>");
body.push("<div class='form-group'><form class='reg-form' role='form'><div class='form-group'><label for='pwd'>" + jsonObj.fields[i].field_options.options[1].label + "</label>");
body.push("<input type'password' class='form-control' id='pwd'></div>");
body.push("<div class='checkbox'><label><input type='checkbox'> Muna mig / Remember me</label></div></form></div>");
}
$(container).html(body);
}});
As you can see, I wrote the code assuming that I would have to push an ending div to each element that I'd opened, however that seems to be ignored.
The problem here is that you're trying to pass the body array to the html method, however you should instead concatenate all strings inside of it, the pass it.
Like so:
var htmlMarkup = body.reduce(function(){
return prev + current;
}, '');
or use 'join' as suggested by Hacketo, since it's less verbose:
var htmlMarkup = body.join('');
$(container).html(htmlMarkup);
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.
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;
}