Setting id attribute in javascript prevents function from running properly - javascript

I am trying to make a memory game and I want to give each image an ID so that the program can keep track of which images are the same. My function was working properly and generating the grid of random images but when I try to give the images their respective ID, random images just come out missing. Does anyone have an idea why this is happening?
function placeImages(arr){
let place = 0;
let num = 0;
let box = 1;
for(let i = 0; i < 10; i++){
num = arr[place];
const pic = document.createElement('img');
pic.id = `${num}`; //THIS IS THE PROBLEM
// pic.setAttribute('id', `${num}`); //number pics
pic.classList.toggle('pic');
pic.setAttribute('src', `./images/${num}.png`);
document.getElementById(`${box}`).appendChild(pic); //goes box by box and add image
box++;
place++;
}
console.log(arr);
}
The array is a random array of 10 numbers 1-5 only repeating once like {1, 3 , 2, 5, 5, 3, 2, 1, 4, 4}
The first image is with "pic.id = ${num};" commented out and the second one it is not commented out. I just started learning so sorry if the code is hard to understand.
result without id
result with id

So what I think this comes down to is that the ID attribute should be completely unique to each HTML element on a page. However, your code has multiple IDs that are the same. In the image you posted that was not displaying images it was where it was trying to give you one element with the ID of ${box} on line12. You expect this to be your div to place an image but instead, it probably got an image element that you created in a previous iteration of the loop. That is my guess and I hope that helps.
Take away: Keep IDs unique to every HTML Element!
What I recommend doing is something like this:
pic.id = `pic-${num}-${i}`;
Which will do something like this:
<img src="4.png" id="pic-4-2">
This way every ID will be unique because images will be prefixed with "pic" and postfixed with the iteration number. Then later in your code, you can splice out the middle number to match them to another image.

Related

Choose random image for every image Javascript

//Setting up the Array
var arrayImg =['http://www.whattofix.com/images/PoliticalAnimal.jpg','http://www.fubiz.net/wp-content/uploads/2013/03/Fashion-Zoo-Animals26.jpeg','http://cdn.trendhunterstatic.com/thumbs/suit-animal-art-berkley-illustrations.jpeg','http://img1.etsystatic.com/016/1/7647665/il_340x270.411173311_ojy5.jpg'];
// creating the randomizing
var random = arrayImg[Math.floor(Math.random()*arrayImg.length)];
// image source looks for the attribute, by using the variable arraying
$('img').attr('src',random);
Above is my code. I currently have javascript set up this way. The current code has the piece where images are randomly replaced from an image from the array. I want to have the code state that switch every image with a new random image, not every image with the same time. I like how it is random every time, but I also want to random for each picture.
Set up a loop to go over each image, pick a random one, and then assign to that one:
var arrayImg =['http://www.whattofix.com/images/PoliticalAnimal.jpg','http://www.fubiz.net/wp-content/uploads/2013/03/Fashion-Zoo-Animals26.jpeg','http://cdn.trendhunterstatic.com/thumbs/suit-animal-art-berkley-illustrations.jpeg','http://img1.etsystatic.com/016/1/7647665/il_340x270.411173311_ojy5.jpg'];
$("img").each(function() {
var random = arrayImg[Math.floor(Math.random()*arrayImg.length)];
$(this).attr('src',random);
});
You can use a callback function with the attr method to calculate the value for each element:
$('img').attr('src', function(){
return arrayImg[Math.floor(Math.random()*arrayImg.length)];
});

How to use splice method to solve my problem correctly?

I am displaying rotating images.
var pics= [
"images/img1.jpg",
"images/img2.jpg",
"images/img3.jpg",
];
And would want it to stop onClick.
function StopRotate(interval, imgIndex) {
clearInterval(interval);
var permanentImage = picture[imgIndex].src;
picture[imgIndex].src = permanentImage;
pics.splice(pics.indexOf(picture[imgIndex].src), 1);
}
Here's how I rotate the images (this block has three occurrences for three image containers):
interval0 = setInterval(function () {
if(pics.length != 1) {
picture[0].src = pics[count];
count++;
if (count == pics.length) count = 0;
}
else picture[0].src = pics[0];
}, 10);
But the image occurs yet again to other frames even if the path has been already removed from the array. I tried this using 12 images. Some times when I run it, the src turns out to be undefined.
Also if I click the images unordered, the images from other frames becomes blank. In this sample, I have three images, if I clicked on the third container, the first container becomes blank, how does that affect other frames when the interval functions are separate. There's no problem however when clicking it in order. Note I have changed the sequence where I put the if condition inside setInterval.
The .src property will return a fully qualified pathname which will never be found in your array of partial path names when you try to look for it with .indexOf().
You can use .getAttribute("src") to get what is actually in the HTML and that should then match what you have in your array.
Example: http://jsfiddle.net/jfriend00/3H8XF/

Replace Images by their alt-text using javascript

I found out so far how to replace element by another element on a html-page. But my function is working in a strange way. First it replaces first and third image. If i invoke it again, it replaces only the second image. Pressing button again makes finally the last fourth image replace. Somebody any ideas about that? Here's the source: http://pastie.org/5502630
And here you can see how it works: http://clubnights.square7.ch/webtech/a2.html
With each pass through the for loop, you remove the first image from the images[] array. This changes both the array contents and the array length set as the conditional in your loop.
For example, your first loop through removes images[0], ausdruck_1.gif -- but now images.length equals 3, not 4, and the contents of the array are now:
images[0]=ausdruck_2.gif
images[1]=ausdruck_3.gif
images[2]=ausdurck_4.gif
Your second pass through the loop removes images[1] -- now ausdruck_3.gif -- and further changes the length of the images array to 2, so the next increment of i to 2 causes the loop to exit.
I created a jsfiddle showing a possible solution of changing your for statement to:
for(i = images.length-1; i >=0; i--)
and looping through the images in reverse order.
You're modifying the list of images as you're iterating through it. So when you try to access the images array it's not what you think it is! Below is a possible workaround..
function Convert()
{
images = window.document.getElementsByTagName('img');
var num_images = images.length;
for (var i = 0; i < num_images; i++)
{
var image = images[0];
textReplacement = document.createTextNode(image.getAttribute('alt'));
image.parentNode.replaceChild(textReplacement, image);
}
}

Should/How would I use .slice() to swap an image scr on a button press? (for next/previous button use in a gallery)

I am stumped and could really use some help with this gallery I've been working on. I used Ivan's '4 lines of jquery gallery' tutorial to get me where I am at currently. Here's his demo which shows exactly how it all works http://workshop.rs/demo/gallery-in-4-lines/
I've hit the point where I would like to include a previous and back button.
As the images are named '1-large.jpg','2-large.jpg','3-large.jpg'... etc I tried using the .slice() to take the first digit then add 1 or minus 1 to it, resulting in the next/previous pic but that didn't work well at all as my javascript skills are lacking and I don't even know if it's the best way to approach it.
My question is - Is using .slice() the way to go or is there a more simpler code I can use on my buttons?
Any help would be much appreciated.
If you just want the first character of a string:
var name = "1-large.jpg";
var i = name[0];
// i is now '1'
but this won't work for i > 9, so using split would be better:
var i = name.split('-')[0];
// i is now '1'
var i = "1023-large.jpg".split('-')[0];
// i is now '1023'
and to convert string to int:
var num = parseInt("23", 10);
// num is now the number 23, not a string

How to reference an array in a function argument

I have a series of arrays that contain words I want to use as text in various HTML divs (there are about 35 of these, I included only a few for brevity).
var bodyplan = ['Anguilliform', 'Compressiform', 'Depressiform', 'Filiform', 'Fusiform', 'Globiform', 'Sagittiform', 'Taeniform'];
var mouthposition = ["Inferior", "Jawless", "Subterminal", "Superior", "Terminal"];
var barbels = ['1', '2', '4 or more'];
var caudalshape = ['Continuous', 'Emarginate', 'Forked', 'Lunate', 'Rounded', 'Truncate'];
I have a switch function that is supposed to change the text based on user selections:
switch(n){
case 1:
changelabels(bodyplan, 8);
break;
case 2:
changelabels(mouthposition, 5);
break;
case 3:
changelabels(barbels, 3);
break;
case 4:
changelabels(caudalshape, 6);
break;
case 5:
changelabels(dorsalspines, 8);
break;
default:
alert("handquestsel error")}};
Finally, I have the function which I would like to make the changes (except it doesn't):
function changelabels(opt1,opt2){
var i = opt2;
var im = opt2 - 1;
var c = 1;
var index = 0;
while (i>=c){
var oldlbl = document.getElementById("rb" + c + "lbl");
var newlbla = opt1.slice(im,i);
var newlblb = opt1.toString();
oldlbl.innerHTML = newlblb;
c = c + 1
index = index + 1
}};
I know the code for my function is just plain wrong at this point, but I have altered it so many times that I'm not sure what's going on anymore. At one point I did have the function able to change the text, but it did so incorrectly (it parsed the name of the array, not extracted a value from the array as I wished). Please help. I know I am overlooking some fundamental concepts here, but am not sure which ones. I've lost count of the hours I've spent trying to figure this out. It's seems like it should be so simple, yet in all my chaotic attempts to make it work, I have yet to stumble on an answer.
EDIT: I want my switch statement to call the function and pass to the function, the appropriate array from which to pull the labels from. The purpose of the app is to help a user learn to identify fish. When the user makes selections on the page, a series of pictures will be shown for various character states with an accompanying label describing the state. For example, when the user selects Mouth Position a series of divs will show the different mouth positions that fish have and have a label below the picture to tell the user what that certain character state is called. I can get the pictures to change just fine, but I am having a hell of a time with the labels.
Why not just something along the lines of:
document.getElementById("bodyplan_label").innerHTML = bodyplan[bodyplan_index];
You seem trying to put everything in really abstract data structures, I see no reason to. Just keep it simple.
Also bodyplan has only 8 elements, so bodyplan[8] will give you an out of bounds exception because arrays start at 0 as is common in all modern programming languages.
If I'm reading your requirement and code correctly, in your switch statement you are passing both a reference to the appropriate array and that array's expected length - you don't need the second parameter because all JavaScript arrays have a .length property.
You don't want to use .slice() to get the individual values out of the array, because that returns a new array copied out of the original - just use arrayVariable[index] to get the individual item at index.
So, putting that together try something like this (with your existing array definitions):
switch(n){
case 1:
changelabels(bodyplan);
break;
case 2:
changelabels(mouthposition);
// etc.
}
function changelabels(data) {
var i,
lbl;
for (i = 0; i < data.length; i++) {
lbl = document.getElementById("rb" + (i+1) + "lbl");
lbl.innerHTML = data[i];
}
}
Notice how much simpler that is than your code? I'm assuming here the elements you are updating have an id in the format "rb1lbl", "rb2lbl", etc, with numbering starting at 1: I'm getting those ids using (i+1) because JavaScript array indexes start at zero. Note also that you don't even need the lbl variable: you could just say document.getElementById("rb" + (i+1) + "lbl").innerHTML = data[i] - however I've left it in so that we have something to expand on below...
Within your function you seem to be changing the labels on a set of elements (radio button labels?), one per value in the array, but you stop when you run out of array items which means any leftover elements will still hold the values from the previous selection (e.g., if the previous selection was "bodyplan" with 8 options and you change to "mouthposition" with only 5 - you probably should hide the 3 leftover elements that would otherwise continue to display the last few "bodyplan" items. One way to do that is instead of setting your loop up based on the array length you could loop over the elements, and if the current element has an index beyond the end of the array hide it, something like this:
function changelabels(data) {
var i,
lbl,
elementCount = 20; // or whatever your element count is
for (i = 0; i < elementCount; i++) {
lbl = document.getElementById("rb" + (i+1) + "lbl");
if (i < data.length) {
lbl.innerHTML = data[i];
lbl.style.display = "";
} else {
lbl.innerHTML = "";
lbl.style.display = "none";
}
}
}
If these elements are labels for radio buttons (just a guess based on the ids) then you'd also want to hide or show the corresponding radio buttons, but I hope you can figure out how to add a couple of lines to the above to do that.
(As mentioned above, be careful about having element ids count up from 1 when the array indexes start at 0.)
If the above doesn't work please post (at least some of) the relevant HTML - obviously I've just had to guess at what it might be like.
SOLUTION: Changed the scope of the array variables to local by moving them into the function where they are used, instead of having them as global variables at the top of the page. I don't understand as I was following every rule of variable declaration. But for some unknown reason, global variables in javascript are abhorrent.
Solution Edit: Found an error in declaring my global variables. This may have been the source of my problem of why I could not access them. But it is a non-issue at this point since I corrected my code.
I don't understand what your trying to achieve exactly with your code. But to pass a variable (in this case an array) by reference you just have to add "&" before the variable.
function the_name(&$var_by_ref, $var_by_value) {
// Here if you modify $var_by_ref this will change the variable passed to the function.
}
More: http://php.net/manual/en/language.references.pass.php
Hope that helps.

Categories