Can't change inner HTML - javascript

function order(){
var i = 1;
while(i != 0){
if(sessionStorage.getItem("taska"+i)!=null){
var p1 = sessionStorage.getItem("taska"+i);
var p2 = sessionStorage.getItem("price"+i);
var a = document.createElement('td');
a.innerHTML = sessionStorage.getItem("id"+i);
var b = document.createElement('td');
var b1 = document.createElement('img');
b1.src = '/obrazky/taska_'+p1+'.png';
b.appendChild(b1);
var c = document.createElement('td');
c.innerHTML = p1;
var d = document.createElement('td');
d.innerHTML = ''+p2+' Kč';
var e = document.createElement('td');
var e1 = document.createElement('input');
e1.type = 'number';
e1.setAttribute("id", i);
e1.onclick = totalPrice(this);
e.appendChild(e1);
var f = document.createElement('td');
f.setAttribute("id", "total"+i);
f.innerHTML = ''+p2+' Kč';
document.getElementById('tr'+i).appendChild(a);
document.getElementById('tr'+i).appendChild(b);
document.getElementById('tr'+i).appendChild(c);
document.getElementById('tr'+i).appendChild(d);
document.getElementById('tr'+i).appendChild(e);
document.getElementById('tr'+i).appendChild(f);
i++;
}else{
i=0;
}
}
}
function totalPrice(nofitems){
var x = nofitems.id;
var y = nofitems.value*Number(sessionStorage.getItem("price"+x));
document.getElementById('total'+x).innerHTML = y+' Kč';
}
I've created function order to insert some html elements. I want to change the element var f when qty of the item is increased. I'm using the totalPrice function to do this, but whenever it's calledm, the console pops up:
Uncaught TypeError: Cannot set property 'innerHTML' of null
I think, that it isn't able to find the created element by id.
Thanks for your help.

Well first, I see something is not right in this line of code:
e1.onclick = totalPrice(this);
this will not attach totalPrice function to the onclick event of the e1 element. Also, the keyword this in the current context refers to the window object, so there is no meaning to send it as a parameter to the totalPrice function It should be like this instead:
e1.onclick = totalPrice;
You should also adjust your totalPrice function to get the totalnumber of items and calculate the price accordingly
Edit: the function shall look like this
function totalPrice(){
var x = this.id;
var y = this.value*Number(sessionStorage.getItem("price"+x));
document.getElementById('total'+x).innerHTML = y+' Kč';
}

try creating a text node and adding it to element f
http://www.w3schools.com/jsref/met_document_createtextnode.asp
if that isn't sufficient then try swapping out this line:
f.setAttribute("id", "total"+i);
for this line:
f.id = "total"+i;
references:
setting the id attribute of an input element dynamically in IE: alternative for setAttribute method
http://www.w3schools.com/jsref/prop_html_id.asp

Related

Reading values from input fields created in an array with document.createElement()

I'm trying to build a table that the user can hit "new line" to create a new row of the table. I do this by foo.push(document.createElement("INPUT"));
function newLine() {
sArr.push(document.createElement("INPUT"));
sArr[sArr.length-1].setAttribute("type", "text");
document.body.appendChild(sArr[sArr.length-1]);
gArr.push(document.createElement("INPUT"));
gArr[gArr.length-1].setAttribute("type", "text");
document.body.appendChild(gArr[gArr.length-1]);
tArr.push(document.createElement("INPUT"));
tArr[tArr.length-1].setAttribute("type", "text");
document.body.appendChild(tArr[tArr.length-1]);
//alert(sArr.length+", "+gArr.length+", "+tArr.length);
var x = document.createElement("br");
document.body.appendChild(x);
}
function calc(){
var temp = 0;
var total = 0;
for(i = 0; i<sArr.length; i++){
total = total + calc2(i);
}
var o = document.getElementById("output");
o.value = total;
}
function calc2(i){
alert(i);
var s = document.getElementById(sArr[i]);
var g = document.getElementById(gArr[i]);
var t = document.getElementById(tArr[i]);
var VO2walkmin = 3.28;
var VO2rest = 3.05;
var C1 = 0.32;
var C2 = 0.19;
var C3 = 2.66;
var Cdecline = 0.73;
var s2 = s.value;
var g2 = g.value;
var t2 = t.value;
var negGrade = g.value;
if(g2 < 0){g2 = 0};
VO2move = ((C1 * g2)+VO2walkmin)+((1+(C2*g2))*(C3*(s2^2)));
VO2inc = VO2rest+(t2*VO2move);
VO2dec = VO2rest+(Cdecline*(t2*VO2move))
//var o = document.getElementById("output");
return VO2inc;
}
When run, I get the error:
Uncaught TypeError: Cannot read property 'value' of null
from line 66. Specifically, this line:
var s2 = s.value;
I'm struggling to find my mistake here... and all help is appreciated.
You create a new element, but it has no ID. And so you can't fetch it by ID. The result of document.getElementById(sArr[i]) will be null.
Check this answer to see how ID can be assigned to a newly created element:
Create element with ID
There's no need to use document.getElementById. sArr[i] is the input element itself, not its ID, so you can just read its value directly.
var s = sArr[i];
var g = gArr[i];
var t = tArr[i];

Why can't I get my images to appear in table cells/nodes.. maybe I can get some closure?

I want to add a new image in each cell of the new table and give it the same source as the old table, and then make it clickable. Firstly, I did this:
function showData() {
if (localStorage.getItem(name) !== null) {
var showme = localStorage.getItem(name);
alert("I got the table");
var newTable = document.createElement('table');
newTable.innerHTML = showme;
newTable.id = "newTable";
newNumRows = newTable.getElementsByTagName('tr').length;
newNumCells = newTable.getElementsByTagName('td').length;
newNumCols = newNumCells / newNumRows;
alert(newNumRows);
alert(newNumCells);
alert(newNumCols);
var newImages = newTable.getElementsByTagName('img');
for (var i = 0; i < newImages.length; i += 1) {
var picSource = newImages[i]['src'];
console.log(picSource);
}
function addNewImage(newNumCols) {
var newImg = new Image();
newImg.src = picSource;
col.appendChild(newImg);
newImg.onclick = function() {
alert("WOW");
};
}
for (r = 0; r < newNumRows; r++) {
row = newTable.insertRow(-1);
for (c = 0; c < newNumCols; c++) {
col = row.insertCell(-1);
addNewImage(newNumCols);
}
}
var showIt = document.getElementById('holdTable');
showIt.appendChild(newTable);
}
}
This works to a certain extent, but, unfortunately, only the last image was displaying. So, I did a bit of looking around and I think it has to do with closure (apologies for any duplication), but it's a concept I am really struggling to understand. So then I tried this:
function showData() {
if (localStorage.getItem(name) !== null) {
hideTaskForm();
var showme = localStorage.getItem(name);
var oldTable = document.createElement('table');
oldTable.innerHTML = showme;
newTable = document.createElement('table');
newTable.id = "newTable";
var i, r, c, j;
newNumRows = oldTable.getElementsByTagName('tr').length;
newNumCells = oldTable.getElementsByTagName('td').length;
newNumCols = newNumCells / newNumRows;
var newTableCells = newTable.getElementsByTagName('td');
var getImages = oldTable.getElementsByTagName('img');
for (r = 0; r < newNumRows; r++) {
row = newTable.insertRow(-1);
for (c = 0; c < newNumCols; c++) {
makeNodes = row.insertCell(-1);
}
}
for (var j = 0; j < newTableCells.length; j++) {
var theNodeImage = document.createElement("img");
newTableCells[j].appendChild(theNodeImage);
alert(newTableCells[j].innerHTML); //This gives me img tags
}
for (i = 0; i < getImages.length; i += 1) {
var oldSource = getImages[i]['src']; //gets the src of the images from the saved table
console.log(oldSource);
//alert(oldSource);//successfully alerts the image paths
var newPic = new Image(); //creates a new image
(function(newPic, oldSource) {
newPic.src = oldSource;
alert(newPic.src); //gives the same image paths
newTable.getElementsByTagName('img').src = newPic.src; //This doesn't work - table is blank???
})(newPic, oldSource);
}
var showIt = document.getElementById('holdTable');
showIt.appendChild(newTable);
}
}
Now, this doesn't throw any errors. However, nor does it fill the table. It does give me the source and I think I have created the new image objects to attach to the img tags in the newTableCells, but the table is showing up blank. I don't know where I am going wrong. All help really welcome.
Note: Even as a hobbyist, even I know there are probably tons of more efficient ways to do this, but I purposely did it this way to try and help me understand the logic of each step I was taking.
In your code you have:
var newImages = newTable.getElementsByTagName('img');
for (var i = 0; i < newImages.length; i += 1) {
var picSource = newImages[i]['src'];
console.log(picSource);
}
At the end of this, picSource has the value of the last image's src attribute. Then there is:
function addNewImage(newNumCols) {
var newImg = new Image();
newImg.src = picSource;
col.appendChild(newImg);
newImg.onclick = function() {
alert("WOW");
};
}
A value is passed to newNumCols but not used in the function. The value of picSource comes from the outer execution context and is not changed, so it's still the last image src from the previous for loop.
for (r = 0; r < newNumRows; r++) {
row = newTable.insertRow(-1);
for (c = 0; c < newNumCols; c++) {
col = row.insertCell(-1);
addNewImage(newNumCols);
}
}
This loop just keeps calling addNewImage with a single parameter that isn't used in the function, so you get the same image over and over.
For the record, the addNewImage function does have a closure to picSource, but it also has a closure to all the variables of the outer execution contexts. This isn't the issue, though it perhaps masks the fact that you aren't setting a value for picSource on each call, so you get the left over value from the previous section of code.
You haven't provided any indication of the content of showme, so it's impossible to determine if this approach will work at all.
Note
Where you have:
var showme = localStorage.getItem(name);
alert("I got the table");
var newTable = document.createElement('table');
newTable.innerHTML = showme;
newTable.id = "newTable";
IE does not support setting the innerHTML property of table elements, though you can create an entire table as the innerHTML of some other element and set the innerHTML of a cell (tr, th). If you want to use this approach, consider:
var div = document.createElement('div');
div.innerHTML = '<table id="newTable">' + showme + '<\/table>';
var newTable = div.firstChild;

How to refer to a dynamically created div with JS

So I am creating div's onclick and giving them incrementally greater Id's. I want to then change the CSS properties of each div but I can't seem to select it with document.getElementById.
Obviously I'm missing something incredibly simple here, any advice or reading would be appreciated.
JS Fiddle
Some relevant Javascript:
function createDiv(){
i++;
var newDiv = document.createElement("div");
newDiv.id = "newDiv"+i;
var e = document.getElementById("newDiv1");
e.innerHTML = "hello";
e.className = "newDivs";
var x = 50*i;
e.style.left = x+"px";
e.style.top = 200+"px";
//but nothing appears
}
you have not attached your div to the DOM tree, you should first attach it then try to grab its reference:
function createDiv(){
i++;
var newDiv = document.createElement("div");
newDiv.id = "newDiv"+i;
document.body.appendChild(newDiv); // <--- Append it here
var e = document.getElementById("newDiv1");
e.innerHTML = "hello";
e.className = "newDivs";
var x = 50*i;
e.style.left = x+"px";
e.style.top = 200+"px";
//but nothing appears
}
You need to append the div into the dom see fiddle
http://jsfiddle.net/coqkg5oz/5/
function addDiv() {
var objTo = document.getElementById('container')
var divtest = document.createElement("div");
divtest.innerHTML = "new div"
objTo.appendChild(divtest)
}
You haven't added the element to the page, that's why it doesn't show up.
You don't need to use getElementById to get a reference to the element, as you already have a reference to the element.
Example:
function createDiv(){
i++;
var e = document.createElement("div");
e.id = "newDiv"+i;
document.body.appendChild(e);
e.innerHTML = "hello";
e.className = "newDivs";
var x = 50*i;
e.style.left = 100+"px";
e.style.top = 200+"px";
}
Demo: http://jsfiddle.net/Guffa/coqkg5oz/8/

assign parameter value of an object javascript

I have been looking at this code for a long time trying to figure this out, but I am having no luck. This issue is that I want to assign a value to the parameter boxId. When I click on a box in the webpage an alert will come up displaying that id. I have tried many things, but nothing seems to work. I'm a beginner, so I feel at this point there just must be something that I don't know how to do.
constructor function:
function Box (boxId, name, color, number, coordinates) {
this.boxId = boxId;
this.name = name;
this.color = color;
this.number = number;
this.coordinates = coordinates;
}
global variables:
var boxes = [];
var counter = 0;
var boxId = 0;
init function:
window.onload = init;
function init() {
var generateButton = document.getElementById("generateButton");
generateButton.onclick = getBoxValues;
var clearButton = document.getElementById("clearButton");
clearButton.onclick = clear;
}
function to get values and create new boxes:
function getBoxValues() {
var nameInput = document.getElementById("name");
var name = nameInput.value;
var numbersArray = dataForm.elements.amount;
for (var i = 0; i < numbersArray.length; i++) {
if (numbersArray[i].checked) {
number = numbersArray[i].value;
}
}
var colorSelect = document.getElementById("color");
var colorOption = colorSelect.options[colorSelect.selectedIndex];
var color = colorOption.value;
if (name == null || name == "") {
alert("Please enter a name for your box");
return;
}
else {
var newbox = new Box(boxId, name, color, number, "coordinates");
boxes.push(newbox);
counter++;
var boxId = counter;
}
addBox(newbox);
var data = document.getElementById("dataForm");
data.reset();
}
function that adds boxes to the page:
function addBox(newbox) {
for (var i = 0; i < newbox.number; i++) {
var scene = document.getElementById("scene");
var div = document.createElement("div");
div.className += " " + "box";
div.innerHTML += newbox.name;
div.style.backgroundColor = newbox.color;
var x = Math.floor(Math.random() * (scene.offsetWidth-101));
var y = Math.floor(Math.random() * (scene.offsetHeight-101));
div.style.left = x + "px";
div.style.top = y + "px";
scene.appendChild(div);
div.onclick = display;
}
}
function to display alert when box is clicked:
function display(e) {
var a = e.target;
alert(a.counter);
}
function to clear boxes:
function clear() {
var elems = document.getElementsByClassName("box");
for ( k = elems.length - 1; k >= 0; k--) {
var parent = elems[k].parentNode;
parent.removeChild(elems[k]);
}
}
All of the other functions work just fine. I keep running into the id showing up as "undefined" when I click it, or the counter displaying "0" in the console log, for everything I've tried.
You can do it like this.
First, in addBox() embed boxId as an tag's attribute like this:
div.setAttribute('data-boxId', newbox.boxId);
Then in display() you can retrieve it back:
alert(e.target.getAttribute('data-boxId'));
Please tell if you do not prefer this approach and I will post an alternative (closure things).
Edit: Add jsfiddle example http://jsfiddle.net/runtarm/8FJpU/
One more try. Perhaps if you change:
var boxId = counter;
to
boxId = counter;
It will then use the boxId from the outer scope instead of the one defined in the function getBoxValues()

how to use an event object to dispaly information about a DOM element

I want to be able to click on a box (the boxes are created through code, and receive values from a form) in the webpage and display information about the box. I am working on a display() function that uses an event object and an alert to display information about the box. So far, I've had multiple odd failures in my attempt to do this, which leads me to believe that I'm not accessing object attributes correctly. I'm a beginner, so this could be really obvious, but thanks for the help.
constructor function:
function Box (counter, name, color, number, coordinates) {
this.counter = counter;
this.name = name;
this.color = color;
this.number = number;
this.coordinates = coordinates;
}
Global variables:
var boxes = [];
var counter = 0;
Init function:
function init() {
var generateButton = document.getElementById("generateButton");
generateButton.onclick = getBoxValues;
var clearButton = document.getElementById("clearButton");
clearButton.onclick = clear;
}
Function that gets values from the form:
function getBoxValues() {
var nameInput = document.getElementById("name");
var name = nameInput.value;
var numbersArray = dataForm.elements.amount;
for (var i = 0; i < numbersArray.length; i++) {
if (numbersArray[i].checked) {
number = numbersArray[i].value;
}
}
var colorSelect = document.getElementById("color");
var colorOption = colorSelect.options[colorSelect.selectedIndex];
var color = colorOption.value;
if (name == null || name == "") {
alert("Please enter a name for your box");
return;
} else {
var newbox = new Box(counter, name, color, number, "coordinates");
boxes.push(newbox);
counter++;
/*for(m = 0; m < boxes.length; m++) {
counter.newbox = boxes[m];
}*/
}
addBox(newbox);
var data = document.getElementById("dataForm");
data.reset();
}
function that assigns attributes to the boxes:
function addBox(newbox) {
for (var i = 0; i < newbox.number; i++) {
var scene = document.getElementById("scene");
var div = document.createElement("div");
div.className += " " + "box";
div.innerHTML += newbox.name;
div.style.backgroundColor = newbox.color;
var x = Math.floor(Math.random() * (scene.offsetWidth-101));
var y = Math.floor(Math.random() * (scene.offsetHeight-101));
div.style.left = x + "px";
div.style.top = y + "px";
scene.appendChild(div);
div.onclick = display;
//console.log(newbox);
//shows all of the property values of newbox in the console
//console.log(div); shows that it is an object in the console
//console.log(div.hasAttribute(number)); says false
}
}
display function:
function display(e) {
// alert(e.target); says its an html object
//alert(e.target.className); works - says "box"
//alert(e.target.hasAttribute(name)); says false
}
I've included some of the things i've found in comments.
The event object only gives you the name not a reference to the element. So... a couple of things.
First if you want to be browser agnostic you want something like (e.srcElement is for IE):
var x = e.target||e.srcElement;
Then get a reference to the element and do what you want:
var refToElement = document.getElementById(x.id);

Categories

Resources