Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Use jquery to dynamically number table columns diagonally

Hi there fellow coders,

I'm looking to find a way to fill a pre-built dynamic blank table with numbering (and colouring if possible) like so:

5x5 grid
As you can see the numbering is ascending order diagonally. I know there's probably some way to calculate the number based on the tables td index but can't quite figure out how to do that for every column diagonally. Any help would be appreciated.

Update: Ok back from my Holidays. Thanks to all you clever people for your replies. As I'm sure you've all had to experience the pain in the neck clients can be, I've been told the spec has changed(again). This being the case I've had to put the grid/matrix into a database and output using a pivot table. Every square has to be customizable color-wise.

Nothing is going to waste though I have learnt quite a few nifty new javascript/jquery tricks from your responses I didn't know about before, so thanks, and I'll be sure to pay it forward :)

Here's what I came up with in the end.

custom grid

like image 763
JT... Avatar asked Jun 23 '12 10:06

JT...


3 Answers

Given you said "colouring if possible" I'll provide an example solution that doesn't do colours quite the way you want (it does it in a way that I found easier to code and more attractive to look at) but which does handle all the numbering correctly for varying table sizes.

The function below assumes the table already exists; in this demo I've included code that generates a table to whatever size you specify and then calls the function below to do the numbering and colours.

function numberDiagonally(tableId) {
    var rows = document.getElementById(tableId).rows,
        numRows = rows.length,
        numCols = rows[0].cells.length,
        sq = numRows + numCols - 1,
        d, x, y,
        i = 1,
        dc,
        c = -1,
        colors = ["green","yellow","orange","red"];

    diagonalLoop:
    for (d = 0; d < sq; d++) {
        dc = "diagonal" + d;
        for (y = d, x = 0; y >= 0; y--, x++) {
            if (x === numCols)
                continue diagonalLoop;
            if (y < numRows)
                $(rows[y].cells[x]).html(i++).addClass(dc);
        }
    }
    for (d = 0; d < sq; d++)
        $(".diagonal" + d).css("background-color", colors[c=(c+1)%colors.length]);
}

Demo: http://jsfiddle.net/7NZt3/2

The general idea I came up with was to imagine a square twice as big as whichever of the x and y dimensions is bigger and then use a loop to create diagonals from the left edge of that bounding square going up and to the right - i.e., in the order you want the numbers. EDIT: Why twice as big as longer side? Because that's the first thing that came into my head when I started coding it and it worked (note that the variable i that holds the numbers that get displayed is not incremented for the imaginary cells). Now that I've had time to think, I realise that my sq variable can be set precisely to one less than the number of rows plus the columns - a number that ends up rather smaller for non-square tables. Code above and fiddle updated accordingly.

Note that the background colours could be set directly in the first loop, but instead I opted to assign classes and set the loops for each class later. Seemed like a good idea at the time because it meant individual diagonals could be easily selected in jQuery with a single class selector.

Explaining exactly how the rest works is left as an exercise for the reader...

UPDATE - this version does the colouring more like you asked for: http://jsfiddle.net/7NZt3/1/ (in my opinion not as pretty, but each to his own).

like image 51
nnnnnn Avatar answered Oct 12 '22 09:10

nnnnnn


This fiddle populates an existing table with numbers and colors. It is not limited to being a 5x5 table. I didn't understand the logic of 15 being orange rather than yellow, so I simply grouped the diagonal cells into color regions.


// we're assuming the table exists
var $table = $('table'),
    // cache the rows for quicker access
    $rows = $table.find('tr'),
    // determine number of rows
    _rows = $rows.length,
    // determine number of cells per row
    _cols = $rows.first().children().length,
    // determine total number of cells
    max = _rows * _cols,
    // current diagonal offset (for coloring)
    d = 1,
    // current row
    r = 0,
    // current cell
    c = 0;

for (var i=1; i <= max; i++) {
    // identify and fill the cell we're targeting
    $rows.eq(r).children().eq(c)
        .addClass('d' + d)
        .text(i);

    if (i < max/2) {
        // in the first half we make a "line-break" by 
        // moving one row down and resetting to first cell
        if (!r) {
            r = c + 1;
            c = 0;
            d++;
            continue;
        }
    } else {
        // in the second half our "line-break" changes to
        // moving to the last row and one cell to the right
        if (c + 1 == _cols) {
            c = 1 + r;
            r = _rows -1;
            d++;
            continue;
        }
    }

    r--;
    c++;
}
like image 41
rodneyrehm Avatar answered Oct 12 '22 07:10

rodneyrehm


Here's a jsFiddle that does what you asked for - http://jsfiddle.net/jaspermogg/MzNr8/8/

I took the liberty of making it a little bit user-customisable; it's interesting to see how long it takes the browser to render a 1000x1000 table using this method :-D

Assuming that each cell has an id of [column]x[row], here are teh codez for how to fill in the numbers of a square table of side length sidelength.

//populate the cells with numbers according to the spec
function nums(){

    var xpos = 0
    var ypos = 0     
    var cellval = 1

        for(i=0;i<2*sidelength;i++){

            if(i >= sidelength){

                ypos = sidelength - 1
                xpos = 1 + i - sidelength
                $('td#' + xpos + 'x' + ypos).text(cellval)
                cellval = cellval + 1        

                while(xpos + 1 < sidelength){
                    ypos = ypos-1
                    xpos = xpos+1
                    $('td#' + xpos + 'x' + ypos).text(cellval)
                    cellval = cellval + 1
                }

            } else {

                ypos = i
                xpos = 0        
                $('td#' + xpos + 'x' + ypos).text(cellval)
                cellval = cellval + 1

                while(!(ypos-1 < 0)){
                    ypos = ypos-1
                    xpos = xpos+1
                    $('td#' + xpos + 'x' + ypos).text(cellval)
                    cellval = cellval + 1
                }        

            }

        }

}

And here they are for how to colour the bugger.

// color the cells according to the spec
function cols(){
        if(+$('td#0x0').text() === 99){
        return false
        } else {
            $('td').each(function(index, element){
                if(+$(this).text() > 22)
                {
                    $(this).attr("bgcolor", "red")
                } 
                if(+$(this).text() <= 22)
                {
                    $(this).attr("bgcolor", "orange")
                }
                if(+$(this).text() <= 14)
                {
                    $(this).attr("bgcolor", "yellow")
                }
                if(+$(this).text() <= 6)
                {
                    $(this).attr("bgcolor", "green")
                }
            })
        }
}

Enjoy, eh? :-)

like image 36
Jasper Mogg Avatar answered Oct 12 '22 07:10

Jasper Mogg