Including variables in a loop

This is the most ridiculous problem. I have been moving parenthesis and quotes and plus signs for HOURS and I still can’t get it right. Either I get an error like “invalid left-hand argument” or “unexpected character” or I get no errors (Chrome Debugger) and the loop doesn’t do anything.

I’m building a Web based image editor. On the Hue page, I need to create 13 canvases and load them with images. This loop works fine:

for (i = 1; i <= 13; i++)
{
c = document.getElementById(“canvas” + i.toString());
context = c.getContext(“2d”);
context.drawImage(image,0,0,c.width,c.height);
}

Later I need to make hue changes to all 13 images. The code I’m using is bulky and unprofessional (but it works):

document.getElementById(‘canvas1’).style.filter = “hue-rotate(” + (hue1 -= 90) + “deg) saturate(” + (sat1 -= 0) + “%)”;
document.getElementById(‘canvas2’).style.filter = “hue-rotate(” + (hue2 -= 90) + “deg) saturate(” + (sat2 -= 0) + “%)”;
document.getElementById(‘canvas3’).style.filter = “hue-rotate(” + (hue3 -= 90) + “deg) saturate(” + (sat3 -= 0) + “%)”;
document.getElementById(‘canvas4’).style.filter = “hue-rotate(” + (hue4 -= 90) + “deg) saturate(” + (sat4 -= 0) + “%)”;
document.getElementById(‘canvas5’).style.filter = “hue-rotate(” + (hue5 -= 90) + “deg) saturate(” + (sat5 -= 0) + “%)”;
document.getElementById(‘canvas6’).style.filter = “hue-rotate(” + (hue6 -= 90) + “deg) saturate(” + (sat6 -= 0) + “%)”;
document.getElementById(‘canvas7’).style.filter = “hue-rotate(” + (hue7 -= 90) + “deg) saturate(” + (sat7 -= 0) + “%)”;
document.getElementById(‘canvas8’).style.filter = “hue-rotate(” + (hue8 -= 90) + “deg) saturate(” + (sat8 -= 0) + “%)”;
document.getElementById(‘canvas9’).style.filter = “hue-rotate(” + (hue9 -= 90) + “deg) saturate(” + (sat9 -= 0) + “%)”;
document.getElementById(‘canvas10’).style.filter = “hue-rotate(” + (hue10 -= 90) + “deg) saturate(” + (sat10 -= 0) + “%)”;
document.getElementById(‘canvas11’).style.filter = “hue-rotate(” + (hue11 -= 90) + “deg) saturate(” + (sat11 -= 0) + “%)”;
document.getElementById(‘canvas12’).style.filter = “hue-rotate(” + (hue12 -= 90) + “deg) saturate(” + (sat12 -= 0) + “%)”;
document.getElementById(‘canvas13’).style.filter = “hue-rotate(” + (hue13 -= 90) + “deg) saturate(” + (sat13 -= 0) + “%)”;

I should be able to put this in a simple loop with the canvas number and hue and saturation changes. But I can’t get the loop to work:

for (i = 1; i <= 13; i++)
{
document.getElementById(“canvas” + i.toString + .“style.filter = “hue-rotate(hue” + i.toString() + " -= 90) deg) saturate(sat” + i.toString() + “) -= 0%”;
}

Simple enough, right?. canvas + i … hue + i (hue1, hue2, hue3 etc…)… sat + i …
But it doesn’t work.

PLEASE assist, I’ve been trying variations on this for HOURS.

Thank you

Hey,

You’re not using var (or let or const) meaning all your variables are global. That’d be the first thing I’d fix.

Other than that if you could post a minimal amount of code (including HTML) so that we can recreate the problem, I’m sure it shouldn’t be too hard to figure out.

1 Like

The simple way:

var hue = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
var sat = [0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0];
for (var i = 0; i < 13; i += 1) {
  document.getElementById('canvas' + (i + 1)).style.filter = 
    "hue-rotate(" + (hue[i] -= 90) + "deg) saturate(" + (sat[i] -= 0) + "%)"; 
}

The showing off way:

Array
  .from({length: 13})
  .map((v, i) => "hue-rotate(" + (hue[i] -= 90) + "deg) saturate(" + (sat[i] -= 0) + "%)")
  .map((filter, i) => document.getElementById("canvas" + (i + 1)).style.filter = filter);

Nice :slight_smile:

If you’re using ES6 methods though, you might as well go the whole hog and use template strings, which’ll make the code considerably easier to read.

Oh alright, if you insist :slight_smile:

Array
  .from({length: 13})
  .map((v, i) => `hue-rotate(${hue[i] -= 90}deg) saturate(${sat[i] -= 0}%)`)
  .map((filter, i) => document.querySelector(`#canvas${i + 1}`).style.filter = filter);
1 Like

Thank you so much Paul, that pointed me in the right direction. The code needed some minor changes (loading the variables into the array), since all zeros was creating greyscale images. :slight_smile:

			var hue = [90, 45, 20, 5, 135, 0, -180, 180, -135, -5, -20, -45, -90];
			var sat = [100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100, 100];
			for (var i = 0; i < 13; i += 1) 
			{
				if (i == 6) continue; 
				document.getElementById('canvas' + (i + 1)).style.filter = 
				"hue-rotate(" + (hue[i] -= 90) + "deg) saturate(" + (sat[i] -= 0) + "%)"; 
			}

Since canvas6 will be updated with the clicked thumbnails’ hue and sat settings, it cannot be included in the loop, thus the continue statement.

Only problem is, the above code will only work once. If I click the thumbnail again, nothing happens, In the debugger, the code fires with no errors. Why is it that I can only use this code once?

Thanks again.

If the arrays are initialised again when you run it another time, the values won’t have changed from the first time.

Paul, an educational question: why is it that this requires an array?

Pullo, here is the working JS and HTML code:

		function click13()
		{			
			// less hue more sat
			// Hue - 90 degrees	
			
			document.getElementById('canvas1').style.filter = "hue-rotate(" + (hue1 -= 90) + "deg) saturate(" + (sat1 -= 0) + "%)";  		
			document.getElementById('canvas2').style.filter = "hue-rotate(" + (hue2 -= 90) + "deg) saturate(" + (sat2 -= 0) + "%)";  		
			document.getElementById('canvas3').style.filter = "hue-rotate(" + (hue3 -= 90) + "deg) saturate(" + (sat3 -= 0) + "%)";  		
			document.getElementById('canvas4').style.filter = "hue-rotate(" + (hue4 -= 90) + "deg) saturate(" + (sat4 -= 0) + "%)";  		
			document.getElementById('canvas5').style.filter = "hue-rotate(" + (hue5 -= 90) + "deg) saturate(" + (sat5 -= 0) + "%)";  		
			document.getElementById('canvas6').style.filter = "hue-rotate(" + (hue6 -= 90) + "deg) saturate(" + (sat6 -= 0) + "%)";  		
			document.getElementById('canvas7').style.filter = "hue-rotate(" + (hue7 -= 90) + "deg) saturate(" + (sat7 -= 0) + "%)";  		
			document.getElementById('canvas8').style.filter = "hue-rotate(" + (hue8 -= 90) + "deg) saturate(" + (sat8 -= 0) + "%)";  		
			document.getElementById('canvas9').style.filter = "hue-rotate(" + (hue9 -= 90) + "deg) saturate(" + (sat9 -= 0) + "%)";	
			document.getElementById('canvas10').style.filter = "hue-rotate(" + (hue10 -= 90) + "deg) saturate(" + (sat10 -= 0) + "%)";  		
			document.getElementById('canvas11').style.filter = "hue-rotate(" + (hue11 -= 90) + "deg) saturate(" + (sat11 -= 0) + "%)";  		
			document.getElementById('canvas12').style.filter = "hue-rotate(" + (hue12 -= 90) + "deg) saturate(" + (sat12 -= 0) + "%)";  		
			document.getElementById('canvas13').style.filter = "hue-rotate(" + (hue13 -= 90) + "deg) saturate(" + (sat13 -= 0) + "%)";	
			onAnyClick();
			 
                     }



		<!-- Begin images table --> 
		<div id="iDisplay"></div>
		<!-- <canvas style="color:#FFFFFF;" id="canvas1" width="javascript:setCanvasWidth()" height="javascript:setCanvasHeight()">Your browser is too old to support this feature. <br>Please consider updating to a modern browser.</canvas> --> 		
		<table id="table0" style="margin-left:auto; margin-right:auto; border-color:#C0C0C0 #C0C0C0 #606060 #606060; ">
			<tr>
				<th id="tHeader1">Hue + 90 degrees</th>
				<th id="tHeader2">Hue + 45 degrees</th>
				<th id="tHeader3">Hue + 20 degrees</th>
				<th id="tHeader4">Hue + 5 degrees</th>
			</tr>
			<tr>
				<td id="tData1" onclick="click1()"><canvas id="canvas1" width="1" height="1"></canvas></td> 
				<td id="tData2" onclick="click2()"><canvas id="canvas2" width="1" height="1"></canvas></td> 
				<td id="tData3" onclick="click3()"><canvas id="canvas3" width="1" height="1"></canvas></td> 
				<td id="tData4" onclick="click4()"><canvas id="canvas4" width="1" height="1"></canvas></td> 
			</tr>
			<tr>
				<th id="tHeader5">Hue + 135 degrees</th>
				<th id="tHeader6" colspan="2">ORIGINAL IMAGE</th>
				<th id="tHeader7">Hue - 180 degrees</th>
			</tr>
			<tr>
				<td id="tData5" onclick="click5()"><canvas id="canvas5" width="1" height="1"></canvas></td>
				<td id="tData6" onclick="click6()" rowspan="3" colspan="2"><canvas id="canvas6" width="1" height="1"></canvas></td>
				<td id="tData7" onclick="click7()"><canvas id="canvas7" width="1" height="1"></canvas></td>	
			</tr>
			<tr>
				<th id="tHeader8">Hue + 180 degrees</th>	
				<th id="tHeader9">Hue - 135 degrees</th>
			</tr>
			<tr>
				<td id="tData8" onclick="click8()"><canvas id="canvas8" width="1" height="1"></canvas></td>
				<td id="tData9" onclick="click9()"><canvas id="canvas9" width="1" height="1"></canvas></td>		
			</tr>
			<tr>
				<th id="tHeader10">Hue - 5 degrees</th>
				<th id="tHeader11">Hue - 20 degrees</th>
				<th id="tHeader12">Hue - 45 degrees</th>
				<th id="tHeader13">Hue - 90 degrees</th>
			</tr>
			<tr>
				<td id="tData10" onclick="click10()"><canvas id="canvas10" width="1" height="1"></canvas></td> 
				<td id="tData11" onclick="click11()"><canvas id="canvas11" width="1" height="1"></canvas></td> 
				<td id="tData12" onclick="click12()"><canvas id="canvas12" width="1" height="1"></canvas></td> 
				<td id="tData13" onclick="**click13()**"><canvas id="canvas13" width="1" height="1"></canvas></td> 
			</tr>
		</table>

Thanks again

It doesn’t require an array, but it’s tidier than creating lots of global values.

I know this is politically incorrect programming, but I come from a background in BASIC languages, where global variables are common, so I really don’t have a problem with them.

I am curious, how would I write this critical sentence in a loop using variables, as I was trying to do in my original code? I very much want to know the way to do what I could not do.

Thank you

The proper way is to place the code in an IIFE (immediately invokes function expression).

I won’t be able to help with this until tomorrow, but I see that your code is subtracting 90 from the hue each time, when from the interface I presume that you want to subtract a different amount each time?

I can help further with this tomorrow.

Okay, thank you. After struggling with this for hours and not getting to bed until 7 am (I get a bit obsessive, I can’t sleep well with an unresolved programing issue) I very much look forward to seeing your solution.

In regard to the variables, the values would never change. The thumbnail click that invokes the function will add or subtract the same amount every time it is fired. This allows the user complete control over subtle to drastic hue changes with a simple click or clicks. The center image in the table shows the changes, and then passes the values to the original image when the user accepts the changes.

Hi Paul_Wilkins

I did not see a way to contact you privately. Can you assist further with this?

Thanks!

Yes indeed, I’ll get right on it.

The working JS and HTML code from post #8 that you supplied doesn’t work when I try it out.

Can you please supply the missing parts to make it work? I can then use that working example to make improvements from there.

I think I can summarize it as follows:

I want to take this mass repetition of code (which appears with minor variations (the hue rotation values - +5deg + 20deg etc…) in 13 functions and turn it into a loop.

function click13()
		{			
			// Hue - 90 degrees	
			
			document.getElementById('canvas1').style.filter = "hue-rotate(" + (hue1 -= 90) + "deg) saturate(" + (sat1 -= 0) + "%)";  		
			document.getElementById('canvas2').style.filter = "hue-rotate(" + (hue2 -= 90) + "deg) saturate(" + (sat2 -= 0) + "%)";  		
			document.getElementById('canvas3').style.filter = "hue-rotate(" + (hue3 -= 90) + "deg) saturate(" + (sat3 -= 0) + "%)";  		
			document.getElementById('canvas4').style.filter = "hue-rotate(" + (hue4 -= 90) + "deg) saturate(" + (sat4 -= 0) + "%)";  		
			document.getElementById('canvas5').style.filter = "hue-rotate(" + (hue5 -= 90) + "deg) saturate(" + (sat5 -= 0) + "%)";  		
			document.getElementById('canvas6').style.filter = "hue-rotate(" + (hue6 -= 90) + "deg) saturate(" + (sat6 -= 0) + "%)";  		
			document.getElementById('canvas7').style.filter = "hue-rotate(" + (hue7 -= 90) + "deg) saturate(" + (sat7 -= 0) + "%)";  		
			document.getElementById('canvas8').style.filter = "hue-rotate(" + (hue8 -= 90) + "deg) saturate(" + (sat8 -= 0) + "%)";  		
			document.getElementById('canvas9').style.filter = "hue-rotate(" + (hue9 -= 90) + "deg) saturate(" + (sat9 -= 0) + "%)";	
			document.getElementById('canvas10').style.filter = "hue-rotate(" + (hue10 -= 90) + "deg) saturate(" + (sat10 -= 0) + "%)";  		
			document.getElementById('canvas11').style.filter = "hue-rotate(" + (hue11 -= 90) + "deg) saturate(" + (sat11 -= 0) + "%)";  		
			document.getElementById('canvas12').style.filter = "hue-rotate(" + (hue12 -= 90) + "deg) saturate(" + (sat12 -= 0) + "%)";  		
			document.getElementById('canvas13').style.filter = "hue-rotate(" + (hue13 -= 90) + "deg) saturate(" + (sat13 -= 0) + "%)";	
			 
      }

I did this successfully with generating 13 canvases:

				for (i = 1; i <= 13; i++)   
				{	
				       	c = document.getElementById("canvas" + i.toString());
                                }

But I cannot figure out how to do it with the hue1 hue2 hue3 sat1 sat2 sat3 etc… variables.

What I have in mind is something like this, but it’s wrong. I have tried dozens of variations on the following but still cannot get it right:

for (i = 1; i <= 13: i++) 
{ 
	document.getElementById('canvas' + i.toString()).style.filter = "hue-rotate(" + (hue + i.toString() -= 90) + "deg) saturate(" + (sat + i.toString() -= 0) + "%)";	
}

So, in summary how do I fix that last loop?

Thank you very much for staying involved.

We’ve already gone over how to fix it. I want to make sure that any improvement that I make actually works with your current system.

That’s why I’m asking you for a link (possibly as jsfiddle code) to currently working code, even if it’s with loads of repetition. From that working by repetitive code, I can remove the repetition and more importantly, make sure that the improvements still continue to work with your code too.

2 Likes

The work I’m doing is covered by an NDA so I cannot publish my code. However, we have not already gone over how to fix it. You replied with an example using an array, but we never discussed the solution using a loop and variables. If you could just assist with that, it would be extremely helpful.

Thank you very much.

You don’t have to supply the full version, a simplified version will do perfectly well.

I could put together a simplified version, but then I risk making assumptions that result in it failing to work in your own code, and I do not want such assumptions to occur.

This topic was automatically closed 91 days after the last reply. New replies are no longer allowed.