function columnLayout(numItems, minItemWidth, range) {
    // Calculate maximum allowed columns:
    var cols = Math.floor(range / minItemWidth);
    var rows = Infinity;
    var widow;

    // Fewer items than allowed columns:
    if (numItems < cols) {
      
      cols = numItems;

    } else {

      // Calculate ideal column count:
      // Use hill-climbing to find fewest columns with fewest rows and fullest final row.
      for (var i = cols; i > 0; i--) {
        // Calculate row count and widow items for this column config:
        var r = Math.ceil(numItems / i);
        var w = numItems % i;

        // Stop searching if we've exceeded minimum row count:
        // (we're count down, so we know we have surpassed minimum rows now)
        if (r > rows) break;

        // Record new minimum row counts,
        // and reset widow counter for each new row threshold reached:
        if (r !== rows) {
          rows = r;
          widow = -Infinity;
        }

        // Keep column count if there are no widows,
        // or if widow count is higher than previous best:
        // (we want exactly zero widows, or else as many hanging items as possible)
        if (w === 0 || w >= widow) {
          widow = w;
          cols = i;
        }
      }
    }

    // Return functions for calculating X and Y positions:
    return {
      rowHeight: 20,
      rowPad: 5,

      x: function(i) {
        return Math.floor(range / cols) * (i % cols);
      },

      y: function(i) {
        return Math.floor(i / cols) * (this.rowHeight + this.rowPad);
      },

      h: function() {
        return this.y(numItems-1) + this.rowHeight;
      }
    };
  }
// - Maximum possible items in last row.
Maximum possible items in last row.
Maximum possible items in last row .
function columnLayout(numItems, minItemWidth, range) {
    var cols = Math.floor(range / minItemWidth);
    var rows = Infinity;
    var widow;
    if (numItems < cols) {
      cols = numItems;
    } else {
      for (var i = cols; i > 0; i--) {
        var r = Math.ceil(numItems / i);
        var w = numItems % i;
        if (r > rows) break;
        if (r !== rows) {
          rows = r;
          widow = -Infinity;
        }
        if (w === 0 || w >= widow) {
          widow = w;
          cols = i;
        }
      }
    }
    return {
      rowHeight: 20,
      rowPad: 5,
      x: function(i) {
        return Math.floor(range / cols) * (i % cols);
      },
      y: function(i) {
        return Math.floor(i / cols) * (this.rowHeight + this.rowPad);
      },
      h: function() {
        return this.y(numItems-1) + this.rowHeight;
      }
    };
  }
function columnLayout ( numItems , minItemWidth , range ) { var cols = Math . floor ( range / minItemWidth ) ; var rows = Infinity ; var widow ; if ( numItems < cols ) { cols = numItems ; } else { for ( var i = cols ; i > 0 ; i -- ) { var r = Math . ceil ( numItems / i ) ; var w = numItems % i ; if ( r > rows ) break ; if ( r !== rows ) { rows = r ; widow = - Infinity ; } if ( w === 0 || w >= widow ) { widow = w ; cols = i ; } } } return { rowHeight : 20 , rowPad : 5 , x : function ( i ) { return Math . floor ( range / cols ) * ( i % cols ) ; } , y : function ( i ) { return Math . floor ( i / cols ) * ( this . rowHeight + this . rowPad ) ; } , h : function ( ) { return this . y ( numItems - 1 ) + this . rowHeight ; } } ; }
Maximum possible items in last row.
Maximum possible items in last row .
// Calculate maximum allowed columns: // Fewer items than allowed columns: // Calculate ideal column count: // Use hill-climbing to find fewest columns with fewest rows and fullest final row. // Calculate row count and widow items for this column config: // Stop searching if we've exceeded minimum row count: // (we're count down, so we know we have surpassed minimum rows now) // Record new minimum row counts, // and reset widow counter for each new row threshold reached: // Keep column count if there are no widows, // or if widow count is higher than previous best: // (we want exactly zero widows, or else as many hanging items as possible) // Return functions for calculating X and Y positions: