SitePoint Sponsor

User Tag List

Results 1 to 9 of 9
  1. #1
    Designer
    Join Date
    Jun 2006
    Location
    Manila
    Posts
    590
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)

    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).
    Last edited by XLCowBoy; May 28, 2012 at 11:21. Reason: additional info

  2. #2
    Utopia, Inc. silver trophy
    ScallioXTX's Avatar
    Join Date
    Aug 2008
    Location
    The Netherlands
    Posts
    8,895
    Mentioned
    138 Post(s)
    Tagged
    2 Thread(s)
    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

    (pseudo code -- i.e., won't work as is, just to get the idea)
    Code:
    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
    Rémon - Hosting Advisor

    Minimal Bookmarks Tree
    My Google Chrome extension: browsing bookmarks made easy

  3. #3
    Designer
    Join Date
    Jun 2006
    Location
    Manila
    Posts
    590
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    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

  4. #4
    Designer
    Join Date
    Jun 2006
    Location
    Manila
    Posts
    590
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    Okay, so this is what it looks like so far:

    Code:
    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)

  5. #5
    Designer
    Join Date
    Jun 2006
    Location
    Manila
    Posts
    590
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    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...

  6. #6
    Utopia, Inc. silver trophy
    ScallioXTX's Avatar
    Join Date
    Aug 2008
    Location
    The Netherlands
    Posts
    8,895
    Mentioned
    138 Post(s)
    Tagged
    2 Thread(s)
    Here's a thought ... What happens when elWidth is the same as varWidth ?
    Rémon - Hosting Advisor

    Minimal Bookmarks Tree
    My Google Chrome extension: browsing bookmarks made easy

  7. #7
    Designer
    Join Date
    Jun 2006
    Location
    Manila
    Posts
    590
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    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. :P

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

  8. #8
    Designer
    Join Date
    Jun 2006
    Location
    Manila
    Posts
    590
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    ...and of course, the logic is flawed. Drat. Back to the board...

  9. #9
    Designer
    Join Date
    Jun 2006
    Location
    Manila
    Posts
    590
    Mentioned
    0 Post(s)
    Tagged
    0 Thread(s)
    @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:

    Code:
    			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:

    Code:
    			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.


Bookmarks

Posting Permissions

  • You may not post new threads
  • You may not post replies
  • You may not post attachments
  • You may not edit your posts
  •