javascript generate repeated images in meteor - javascript

Can anyone help I am trying to have an image that repeats according to how many portions there are. I am getting Uncaught TypeError: Cannot set property 'src' of undefined.
I am using meteor and react
genPrtnImg: function () {
var pNum = FoodItemsC.find(this.props.foodItem.portionNo);
for (i = 0; i < pNum; i++)
var img = document.createElement('img');
img.src = "http://downloadicons.net/sites/default/files/carrot-icon-14142.png";
return img;
},
the function is called in the render below:
render() {
return (
<tbody>
<tr>
<td rowSpan="3"><img className="itemSmlPic" src="http://bed56888308e93972c04-0dfc23b7b97881dee012a129d9518bae.r34.cf1.rackcdn.com/sites/default/files/veggie-heart.jpg"></img></td>
<td><h1>{this.props.foodItem.foodName}</h1></td>
<td rowSpan="3"><img className="itemSmlPic" src="http://thesocialmediamonthly.com/wp-content/uploads/2015/08/photo.png"></img></td>
</tr>
<tr>
<td>{this.props.foodItem.foodDesc}</td>
</tr>
<tr>
<td>{this.genPrtnImg()}</td>
</tr>
</tbody>
);
}
Thanks!

You are not enclosing your entire for loop inside curly brackets so your for loop is actually only iterating over this line var img = document.createElement('img');. Because of this and the fact that your var is declared inside the for loop i.e. doesn't exist outwith that one line of code when you hit the next line and do img.src = you get your error because img doesn't actually exist here. Fix is to wrap in brackets
for (i = 0; i < pNum; i++) {
var img = document.createElement('img');
img.src = "http://downloadicons.net/sites/default/files/carrot-icon-14142.png";
}
B) This still wont work because when you return img you are also returning outside the scope of the for loop hence the img does not exist. You could move it inside the for loop but this would mean it would only ever execute the loop once and as soon as it hits the return line it will return a singular img value
EDIT:
A fix for this would possibly be to push these values to an array and return that (wrapped in an element so react doesn't have a wipe out):
genPrtnImg: function () {
var pNum = FoodItemsC.find(this.props.foodItem.portionNo);
var i=0;
var x = [];
for (i = 0; i < pNum; i++){
x.push(<img src='http://downloadicons.net/sites/default/files/carrot-icon-14142.png' />);
}
return <div>{x}</div>;
}

Related

Why this javascript does not work?

I am having some trouble with this code, I tested it online but it doesn't seem to work. This is all of my coding:
My HTML:
<img src="kruisje.jpg" id="image1">
And the script that SHOULD make it a slideshow but doesn't:
var img = document.getElementById("image1").src;
function changeimage(){
wait(10)
for(var i = 0; i < images.length; i++){
return img
}
}
var images = ["","","","","",""]
And I know the links in the array aren't filled in but I have the links for it ready. They are just pictures so you can fill in any url you want if you are testing it.
Can somebody say me what i am doing wrong on this code?
Depending on when you run it, document.getElementById("image1") may return an element or null. If it returns null the script will error when you try to access the src property and abort.
You never call the changeimage function
There is no wait function in JavaScript and you don't appear to have defined one.
You return img, so you exit the function on the first time you go around the loop
If you wanted to assign a new URL to img then you would just be assigning the URL to the variable. img will be a variable containing a string. It won't reference the src property.
If you want to do this, you need to completely change your approach.
// Get a reference to the element (make sure you run this *after* the image has been added to the DOM)
var img = document.getElementById("image1");
// Track where you are in the array
var imagesIndex = 0;
var images = ["","","","","",""]
function changeImage(){
// Assign the new URL to the src property of the image
img.src = images[imagesIndex];
// Increment the index here
imageIndex++;
// Check if it has gone off the end and reset it if it has
if (imageIndex >= images.length) {
imageIndex = 0;
}
}
// Call the function on your time period
setInterval(changeImage, 10000);
var img = document.getElementById("image1").src;
function changeimage(){
wait(10) // ERROR FUNCTION
setTimeout(function(){alert("Hello")},3000);
for(var i = 0; i < images.length; i++){
return img
}
}
var images = ["","","","","",""]
you need use setTimeout(function(){alert("Hello")},3000);

Javascript constructor copies array as empty when it should contain items

My code:
function BayesNet(vars) {
this.variables = {};
this.numVars = Object.keys(this.variables).length;
for (v in vars) {
this.variables[v] = new BayesNode(vars[v]);
this.variables[v].CPTorder = this.generateDomainRows(this.variables[v].parents);
this.variables[v].fullCPT = {}
for (var i = 0; i < this.variables[v].CPTorder.length; i++) {
this.variables[v].fullCPT[this.variables[v].CPTorder[i]] = this.variables[v].CPT[i];
}
this.variables[v].blocks = false;
}
}
function BayesNode(obj) {
this.parents = obj.parents;
this.children = obj.children;
if (typeof obj.domain == 'undefined')
this.domain = ['T','F'];
else
this.domain = obj.domain;
this.observation = obj.observation;
this.CPT = obj.CPT;
this.sampleDistribution = [];
for (var i = 0; i < this.CPT.length; i++) {
var s = [];
if(this.CPT[i].length == this.domain.length - 1)
this.CPT[i].push(1 - sumArray(this.CPT[i]));
s.push(this.CPT[i][0]);
for (var j = 1; j < this.domain.length - 1; j++) {
s.push(this.CPT[i][j]+s[j-1]);
}
s.push(1.0);
this.sampleDistribution.push(s);
}
//TODO: Check if CPT is valid
}
My problem is that BayesNode.parent is copied incorrectly.
BayesNode.parent should be an array containing items, and when I run the debugger through the constructor, this.parents is the correct value . However, once I go back to the BayesNet constructor, parents is an empty array. What could be causing this? All other variables in the object behave as expected.
Javascript executes function calls asynchronously. This is the root cause of your issue. You should use callbacks to execute code that is dependent on results of function calls.
Let me explain this using your code:
this.variables[v] = new BayesNode(vars[v]);
this.variables[v].CPTorder = this.generateDomainRows(this.variables[v].parents);
When you call the constructor, JS does NOT wait for the function to finish executing before moving onto the next line of code. When JS comes across "this.variables[v].parents", it is empty, because, the function call in the previous line is still executing asynchronously.
Javascript code design requires a different approach as compared to most other languages.
I don't see any issues in your code, its strange why its becoming empty. but to solve the problem there is a way. change the code as follow.
after this line
this.variables[v] = new BayesNode(vars[v]);
Add the follow
this.variables[v].parents = vars[v].parents;
I see you are not modifying the parents in the constructor, it will work for time being before you find out whats happening. you might have done this already :)

Javascript: How do I get the height of unloaded images in a loop?

I am loading a json file and parsing it into an array in Javascript. One of the elements is the path to an image. I am not ready to load the images yet but I need to get the image's height. I know how to do that with code like the following (found on other stackoverflow pages)
function getimageheight(img) {
var tmpImg = new Image();
tmpImg.onload = function() {
var ht = this.height;
return ht+0;
}
tmpImg.src = img;
}
If I try to call this function in a loop, it returns undefined because the onload for the images is running slower than the loop. My actual code is this:
var j = 0;
$.each(cat.placemarks, function(index, mark) {
markers[cat.name][j] = [];
markers[cat.name][j].name = mark.name;
markers[cat.name][j].title = mark.title;
markers[cat.name][j].markerURL = mark.markerURL;
markers[cat.name][j].imageURL = mark.imageURL;
markers[cat.name][j].imageHEIGHT = getimageheight(projpath+mark.imageURL);
j++;
});
If I call the function once, it works. But calling it in a loop does not. How can I fix this?
If you store reference to data object in Img object used to load it, you can set the value of its properties after the loading is done. Hope that makes sense... Your data will not be ready to use before loading is complete tho. Heres the code
var total=cat.placemarks.length;//if an array, otherwise use another each cycle to get object count
var loaded=0;
$each(cat.placemarks, function(index, mark) {
markers[cat.name][j] = [];
var tmpImg = new Image();
tmpImg.refToObjWithNameOfYourChoice=markers[cat.name][j];
tmpImg.onload = function() {
this.refToObjWithNameOfYourChoice.imageHEIGHT=this.heigh;
loaded++;
if(loaded==total){
//markers data is ready to use - add function callback herer or sumthin'
}
}
tmpImg.src=projpath+mark.imageURL;
markers[cat.name][j].name = mark.name;
markers[cat.name][j].title = mark.title;
markers[cat.name][j].markerURL = mark.markerURL;
markers[cat.name][j].imageURL = mark.imageURL;
j++;
});
markers[cat.name][j].imageHEIGHT is undefined because getImageHeight() isn't returning anything. And naturally, the image load will occur much more slowly than your each() loop, so it won't do you any good to have getImageHeight() return something. You'll have to set up your load() callback to determine which image has been loaded and update the height of the corresponding markers element.

For loop inside function (newbie)

I would like to have some variables that my for loop uses inside a function scope (not global).
I tried to wrap the for loop inside a function like this but it results in console error:
function() {
var data = livingroomTableData;
for(var i = data[0]; i < data[1]; i++) {
var elemvalue = data[2] + format(i) + ".png";
livingroomTableArray[i] = elemvalue;
}
}
I would like the data variable to have the values of livingroomTableData only inside this for loop (not globally). In other loops I will input a different variable into the data variable.
Oh yes, and as you can probably tell, I'm a total newbie. :S
There is only function scope in javascript, block scope does not exist, so you can't let the variable only inside the for loop. What you could do is to create a function scope.
Code example:
(function(livingroomTableData) {
var data = livingroomTableData;
//... the rest code
})(livingroomTableData);
The big problem is this line:
for(var i = data[0]; i < data[1]; i++) {
That means, starting with i as the first element of the array, do the code in the loop, incrementing i by one at the end of each run until i is not less than the second element of data.
I'd rewrite it to show you a working version, but its not clear what you actually want to do.
function() {
for(var i = 0; i < livingroomTableData.length; i++) {
var data = livingroomTableData[i];
//your code here...
}
}

Loading and removing images with DOM, Javascript

I'm new to DOM and I'm having trouble removing multiple images that I loaded
this loads 7 images (1.jpg, 2.jpg, etc..)
function loadImages() {
for (var i = 1; i < 8; i++ ) {
var img = document.createElement("img");
img.src = "images/"+i+".jpg";
var idName = "img"+i+"";
document.getElementById(idName).appendChild(img);
}
}
this should remove all of them, but doesn't.. I think it breaks at the removeChild line.
function removeImages() {
for (var i = 1; i < 8; i++ ) {
var idName = "img"+i+"";
var d = document.getElementById(idName);
d.removeChild(document.getElementById(img));
}
}
I think I'm doing something fundamentally wrong, because I don't fully understand how this works...
In the removeImages function the variable img is not initialized. And even if it was you don't set the id for any of the images in the loadImages function. You could modify your code like this:
function loadImages() {
for (var i = 1; i < 8; i++ ) {
var img = document.createElement("img");
img.src = "images/"+i+".jpg";
img.id = i;
var idName = "img"+i+"";
document.getElementById(idName).appendChild(img);
}
}
function removeImages() {
for (var i = 1; i < 8; i++ ) {
var d = document.getElementById(i);
d.parentNode.removeChild(d);
}
}
Your code example implies that you're trying to remove a child element of the image and not the image itself. Also, you're using the wrong variable to reference the image. Maybe it works when you replace this line:
d.removeChild(document.getElementById(img));
With this:
d.parent.removeChild(document.getElementById(idName));
Also, if you're not that familiar with the DOM tree, you might want to take a look at jQuery, which is more browser-independent than regular DOM instructions.
If you are doing DOM manipulation, I would recommend that you use jQuery (or at least try it out).
It will make your life more pleasant, you will be a happier person and it will prevent you from committing harakiri.

Categories