Totally stumped with a array-like issue

Hi guys,

So I’m stumped with a JS problem: I need to take a list of images, wrap each in a li (don’t ask, it’s just one of the those things), and place a set number into ul’s. The problem is the “set number”.

The idea is that the number of ul’s created will be based on the container width. So if we have a div that’s 200px, and I have 6 images, I have to divide those into rows of ul’s.

To illustrate:

container div width is 200px
images 1-2 = 186px
wrap images 1&2 in ul
images 3-5 = 199px
wrap images 3-5 in ul
image 6 = 40px
wrap image 6 in ul

I’ve tried doing for loops with if/else if in them, but because I’ve based them against the 200px (something like if total width < 200px, total width += width of this span, and push this into temp array; else if total width > 200px, push array into html, empty array, start over), the issue I have is that I never catch the last line of images, since they will always be under 200px, which means the “else if” no longer runs.

Any ideas guys? I’m totally stumped.

(Or if anyone has an alternative way of doing this without using arrays, it would be great - no CSS suggestions please. This needs to be strictly JS).

After the loop just check if there is anything in the buffer, and if there is just output to screen. You can be sure it’s <= 200px because if it weren’t the condition in your loop would’ve fired :slight_smile:

(pseudo code – i.e., won’t work as is, just to get the idea)


buffer = '';
wsum = 0;
for(i = 0; i < images.length; i++) {
   image = images[i];
   buffer += image.html;
   wsum + image.width;
   if (wsum >= 200) {
       output(buffer);
       buffer = '';
       wsum = 0;
   }
}
if (buffer) {
  output(buffer); // write the 'left overs'
}

HTH :slight_smile:

Brilliant! That worked like a charm.

…although I’m finding out very quickly that my problem is a lot more complex than I expected. :-T

Okay, so this is what it looks like so far:


function newGroups(){								
				var cont = $('.parentcontainer').width();
				var varWidth = cont;
				var narr = $('.source').html().split(' ');				
				console.log(narr); //just checking
				
				// Create the counters
				var x = 0; var z = 0;
				
				// Create the loop for slicing and grouping
				$('.source elements').each(function(i) {					
					var yCounter = $(this).index();
					var elWidth = $(this).width();
					
					if( elWidth < varWidth ){
						varwidth -= elWidth;
						z = yCounter;
						console.log("index: "+yCounter+" width: "+elWidth);
					} else if( elWidth > varWidth ) {					
						sarr = narr.slice(x,yCounter);
						sarr = sarr.join(' ');
						sarr = '<p>'+sarr+'</p>';
						$('div').append(sarr);

                                                // Set new X for next slice
						x = yCounter;
                                                
                                                // Reset for next go
						varw = cont;
					}
				})
				if (z > 0) {
					sarr = narr.slice(x);
					sarr = sarr.join(' ');
					sarr = '<p>'+sarr+'</p>';
					$('div').append(sarr);
				};
			};


Which is working fine except for one issue: when I set the new x (for the new slice), it skips the current index, so based on the console log, I get width’s for index 0, 1, 2, 4, 5… and I need to make sure 3 is in there.

Any advice? (Also, feel free to show a better way of doing this. I do feel this is very sloppy code, but I’m very very rusty with my JS now)

Ugh. Still ways off it seems. When I resize the window to something much smaller, it doesn’t properly measure what needs to be sliced.

Oh well, back to the board…

Here’s a thought … What happens when elWidth is the same as varWidth ? :wink:

Well, the idea was for that to never happen. Since the elWidth’s are expected to be completely random, they should never end up the same. :stuck_out_tongue:

::EDIT:: I’ve managed to make the missing indexes show up. Silly me, forgot to add a console.log when the else gets triggered. :stuck_out_tongue:

…and of course, the logic is flawed. Drat. Back to the board…

@ScallioXTX

Got it working. And it’s a lot simpler than I thought. Your buffer code was the catalyst, so I thought I’d share the finished bits with the console.log parts intact:


			function newGroups(){
				
				// Container and array source	- in this instance, it grabs <span> tags with text content
				var boxW = $('div').width();				
				var tArr = $('aside').html().split('|');
				console.log(tArr);
				console.log("container: "+boxW);
				
				// Create the counters
				var varW = 0; // Counter for the total width
				var x = 0; // Slice starts here
				var y = 0; // Iteration Count
				var l = tArr.length; // Array length
				var fArr = ''; // "Final" Array variable
				console.log("variable: "+varW);
				console.log("tArr length: "+l);
				
				// Create the loop for inserting
				$('aside span').each(function(i) {
					var z = $(this).index();					
					var elW = $(this).width();					
					varW += elW;
					if( varW > boxW ){
						
						// Check results
						lastW = (varW - elW);
						console.log("index: "+z+" went over width");
						console.log("total varw is: "+varW);
						console.log("varw less index "+z+" is: "+lastW);
						console.log("slice starts on index "+x+", ends on index "+z);
						
						// Do the slice
						sArr = tArr.slice(x,z);
						sArr = sArr.join(' ');
						fArr += '<p>'+sArr+'</p>';						
						
						// Check, just to be sure
						console.log(sArr);
						
						// Set the variables
						varW = 0; ++y; x = z;
						varW += elW; // Otherwise VarW will forget z's width in the next loop
					}
				})
				// Check to see if any are left
				if (y != l) {
					sArr = tArr.slice(x);
					sArr = sArr.join(' ');
					fArr += '<p>'+sArr+'</p>';
				};
				$('div').append(sArr);
			};

Without console log and comments:


			function newGroups(){								
				var boxW = $('div').width();				
				var tArr = $('aside').html().split('|');
				var varW = 0; var x = 0; var y = 0;
				var l = tArr.length;
				var fArr = '';
				$('aside span').each(function(i) {
					var z = $(this).index();					
					var elW = $(this).width();					
					varW += elW;
					if( varW > boxW ){		
		
						sArr = tArr.slice(x,z);
						sArr = sArr.join(' ');
						fArr += '<p>'+sArr+'</p>';						

						varW = 0; ++y; x = z;
						varW += elW;
					}
				})
				if (y != l) {
					sArr = tArr.slice(x);
					sArr = sArr.join(' ');
					fArr += '<p>'+sArr+'</p>';
				};
				$('div').append(fArr);
			};

Is there some way this can become more concise? Would love to shrink this even more. :slight_smile: