ptwickler
ptwickler

Reputation: 21

Using jQuery to Generate a Grid of DIVs, but Get Wierd Behavior if it Isn't 10 x 10

I'm using jQuery to generate a grid of divs that I will then style to become the board of a game. It works fine when I set the grid to 10 x 10, but when I increase the number of squares, even by one, the second column from the left either doesn't display at all (although the html is fine), or it extends from the bottom of the grid down instead of up.

I've tried messing with the stylesheet and pretty much every variable in the code to no avail. Any help would be appreciated.

$(document).ready(function() {
  var row_count = 11;

  var base = document.getElementById('base');

  var square = '<div class="square"></div>';

  var col_count = 11; // Sets the number of columns

  while (col_count >= 0) { //Outer loops controls the columns.
    row_count = 11; // sets the number of rows

    while (row_count >= 0) {
      $('<div class="square" id = "in_col' + '_' + col_count + '_' + row_count + '"></div>', {
        "class": "square"
      }).appendTo('#base');

      row_count--;
    }

    col_count--;
  }

  // These two values, for posx and posy are the positioning 
  // coordinates for the squares of the grid
  var posx = 10;
  var posy = 10;

  var col = 0; // Initiates the column counter for the below while loop

  while (col <= 11) { // must match var col_count above
    $.each($('div[id^="in_col_' + col + '"]'), function() {

      $(this).css('top', posy);
      $(this).css('left', posx);

      posy += 41;

    });

    posy = 10;
    posx += 41;

    col++;
  }
});
.square {
  border: 1px solid black;
  height: 40px;
  width: 40px;
  position: absolute;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id='base'>

</div>

Fiddle of example

Upvotes: 2

Views: 111

Answers (7)

ptwickler
ptwickler

Reputation: 21

IrkenInvader, thanks, I went with your solution, much cleaner than what I had originally and obviates the need for the bit of code (the regex in the jQuery selector) that was causing the problem.

$(document).ready(function(){

var col_count = 11;// Sets the number of columns
var row_count = 11; //sets the number of rows
var base = $('#base');

for(var i = 0; i < col_count; i++) {
    for (var j = 0; j < row_count; j++) {

        var square = '<div class="square" id = "in_col' + '_' + j + '_' + i +'"></div>';
        var tile = $(square);
        if (j === 0) tile.addClass('newRow');
        base.append(tile);
    }

}

});

Upvotes: 0

Raheel Khan
Raheel Khan

Reputation: 111

insted for running while loop backward run it forward, it will fix your problem

var row_count = 0;
var col_count = 0; // Sets the number of columns

while (col_count <= 10){ //Outer loops controls the columns.
   row_count = 0; // sets the number of rows

    while (row_count <= 10) { // Inner loop controls the cells in each column.
        $('<div class="square" id = "in_col' + '_' + col_count + '_' + row_count +'"></div>', {"class":"square"}).appendTo('#base');

        row_count++;
    }

    col_count++;
}

Upvotes: 0

IrkenInvader
IrkenInvader

Reputation: 4050

I refactored the code a bit, using for loops instead so we don't have to keep track of iteration variables. I also used float: left; on the tiles and clear: both; whenever we want to wrap down to a new line.

Javascript

$(document).ready(function() {
    var col_count = 11; //Sets the number of columns
    var row_count = 11; //sets the number of rows
    var base = $('#base');
    var square = '<div class="square"></div>';

    for(var i = 0; i < col_count; i++){
      for(var j = 0; j < row_count; j++){
        var tile = $(square);
        if(j === 0) tile.addClass('newRow');
        base.append(tile);
      }
    }
});

CSS

.square {
    border: 1px solid black;
    height: 40px;
    width: 40px;
    float: left;
    margin-top: -1px;
    margin-left: -1px;
}

.newRow {
    clear: both;
}

fiddle: https://jsfiddle.net/e0g6y9th/

Upvotes: 2

ahmet2106
ahmet2106

Reputation: 5007

Yours is more a mathematical problem. My version is much easier to understand, here is a fiddle.

go row by row and column by column in each row. so var i is each row and var j is each column in the row (starting every time by 1 and count up till reach var col_count.

$(document).ready(function() {
  var row_count = 11;
  var col_count = 11;
  var size = 41;

  var base = document.getElementById('base');

  for (var i=1; i<=row_count; i++) {
        for (var j=1; j<=col_count; j++) {
        $('<div class="square" id = "in_col' + '_' + j + '_' + i + '"></div>')
            .addClass('square')
          .css({
            'left': j*size,
            'top': i*size
          })
          .appendTo('#base');
      }
  }
});

to select each elements in column 1 use div[id^="in_col_1_"]. I would recommend you to work with data attributes by changing the code to:

$(document).ready(function() {
  var row_count = 11;
  var col_count = 11;
  var size = 41;

  var base = document.getElementById('base');

  for (var i=1; i<=row_count; i++) {
        for (var j=1; j<=col_count; j++) {
        $('<div class="square" id = "in_col' + '_' + j + '_' + i + '"></div>')
            .addClass('square')
            .attr('data-col', j)
            .attr('data-row', i)
            .css({
                'left': j*size,
                'top': i*size
            })
            .appendTo('#base');
      }
  }
});

so you can easily select elements in row 1 by div[data-row="1"] and column 1 by div[data-col="1"]. Have a look at this fiddle.

Upvotes: 0

Eric
Eric

Reputation: 10658

Here's my take

fiddle

  $(document).ready(function() {
  var row_count = 11;
  var col_count = 11;
  var x = 0;
  var y = 0;
  var offX = 41;
  var offY = 41;
  for(var i = 0; i < col_count; i++){
    $('#base').append('<div id="col_'+i+'" class="col" style="left:'+x+'px"><div>');
    x += offX;
    y = 0;
    for(var j = 0; j < row_count; j++){
        $('#col_'+i).append('<div class="square" id="row_'+j+'" style="top:'+y+'px"></div>');
      y += offY;
    }  
  }
 });
.col{
  position: absolute;
}
.square {
  border: 1px solid black;
  height: 40px;
  width: 40px;
  position: absolute;
}

Upvotes: 0

Dave
Dave

Reputation: 4412

The selector in your $.each loop is matching columns multiple times. A simple solution will be to zero-pad the numbers in your ids:

function pad(num, size) {
    var s = num+"";
    while (s.length < size) s = "0" + s;
    return s;
}

Then change

$('<div class="square" id = "in_col' + '_' + col_count + '_' + row_count + '"></div>', {
        "class": "square"
      }).appendTo('#base');

To

  $('<div class="square" id = "in_col' + '_' + pad(col_count,3) + '_' + pad(row_count,3) + '"></div>', {
    "class": "square"
  }).appendTo('#base');

And

$.each($('div[id^="in_col_' + col + '"]'), function() {

to

$.each($('div[id^="in_col_' + pad(col,3) + '"]'), function() {

Here's a working fiddle: https://jsfiddle.net/xc9gyv8p/4/

Upvotes: 0

Alexandru Chichinete
Alexandru Chichinete

Reputation: 1183

Problem is in $.each($('div[id^="in_col_' + col + '"]'), function() { col_10 is called 2 times. Change it to $.each($('div[id^="in_col_' + col + '_"]'), function() {, a more restrictive regex

$(document).ready(function() {
  var row_count = 11;

  var base = document.getElementById('base');

  var square = '<div class="square"></div>';

  var col_count = 11; // Sets the number of columns

  while (col_count >= 0) { //Outer loops controls the columns.
    row_count = 11; // sets the number of rows

    while (row_count >= 0) {
      $('<div class="square" id = "in_col' + '_' + col_count + '_' + row_count + '"></div>', {
        "class": "square"
      }).appendTo('#base');

      row_count--;
    }

    col_count--;
  }

  // These two values, for posx and posy are the positioning 
  // coordinates for the squares of the grid
  var posx = 10;
  var posy = 10;

  var col = 0; // Initiates the column counter for the below while loop

  while (col <= 11) { // must match var col_count above
    $.each($('div[id^="in_col_' + col + '_"]'), function() {

      $(this).css('top', posy);
      $(this).css('left', posx);

      posy += 41;

    });

    posy = 10;
    posx += 41;

    col++;
  }
});
.square {
  border: 1px solid black;
  height: 40px;
  width: 40px;
  position: absolute;
}
<script src="https://ajax.googleapis.com/ajax/libs/jquery/2.1.1/jquery.min.js"></script>
<div id='base'>

</div>

Upvotes: 1

Related Questions