Skip to content

Instantly share code, notes, and snippets.

@floz
Created October 17, 2013 22:58
Show Gist options
  • Save floz/7033797 to your computer and use it in GitHub Desktop.
Save floz/7033797 to your computer and use it in GitHub Desktop.
JS - Grid.js
Grid = ( function Grid() {
var _itemSize = 156,
_$content = null, _w = 0, _h = 0, _spacing,
_cellWidthPercent = 0.0, _totalWidth = 0, _cellWidth = 0, _spacingPercent = 0.5;
function Grid( $content, w, h, spacing ) {
_$content = $content;
_w = w;
_h = h;
_spacing = spacing;
_$content.width( "100%" );
_totalWidth = $( window ).width();
this._countLines = 0;
this._countCols = 0;
this._lines = [];
this._linesCapacities = []; // TODO: to improve perf of searching free space
this.createGrid();
}
Grid.prototype.constructor = Grid;
Grid.prototype.createGrid = function createGrid() {
this._countLines = _h >> 0;
this._countCols = _w >> 0;
_cellWidthPercent = ( 100 - ( this._countCols - 1 ) * _spacing ) / this._countCols;
_cellWidth = ( _totalWidth - ( this._countCols - 1 ) * _spacing ) / this._countCols;
//console.log( _totalWidth, _spacingPercent, _cellWidth );
var cols = [], i = j = 0;
for( ; i < this._countLines; i++ ) {
for( j = 0; j < this._countCols; j++ ) cols[ j ] = 0;
this._lines[ i ] = cols;
this._linesCapacities[ i ] = [];
cols = [];
}
var bigs = [], smalls = [],
$entries = _$content.find( ".entry" );
$entries.each( function() {
var $this = $( this );
if( $this.hasClass( "entry-w-1" ) && $this.hasClass( "entry-h-1" ) ){
smalls.push( $this );
} else {
bigs.push( $this );
}
});
this.placeBigs( bigs );
var lastY = this.placeSmalls( smalls );
_$content.height( ( lastY + 1 ) * _cellWidth + _spacing * lastY + 20 );
}
Grid.prototype.placeBigs = function placeBigs( bigs ) {
var coordsY = [ 1, 3, 6, 6, 3, 0 ], coordsX = [ 0, 2, 3, 4, 1, 0 ],
idxCoordsY = 0, idxCoordsX = 0;
var $big = null,
py = 0, stepY = 2, px = 0, stepX = 3, w = 0, h =0, idxCol = 0, coords = null,
wVal = 0,
i = 0, n = bigs.length;
for( ; i < n; i++ ) {
$big = bigs[ i ];
w = $big.data( "w" );
h = $big.data( "h" );
wVal = ( w * _cellWidth + ( w - 1 ) * _spacing ) + "px"
$big.width( wVal );
$big.height( ( h * _cellWidth + ( h - 1 ) * _spacing ) + "px" );
coords = this.findCoordsBig( coordsY[ idxCoordsY ], coordsX[ idxCoordsX ], stepY, w, h, [] );
idxCoordsY++;
if( idxCoordsY > 5 ) idxCoordsY = 0;
idxCoordsX = idxCoordsY;
if( coords == null ) {
$big.remove();
continue;
}
$big.css( {
top: ( coords.y * _cellWidth + _spacing * coords.y ) + "px",
left: ( coords.x * _cellWidth + _spacing * coords.x ) + "px"
});
}
}
Grid.prototype.findCoordsBig = function findCoordsBig( py, px, stepY, w, h, linesChecked ) {
if( linesChecked.length == this._countLines )
return null;
var idxLine = py + Math.random() * stepY >> 0;
idxLine = Math.max( 0, Math.min( idxLine, this._countLines -1 ) );
if( $.inArray( idxLine, linesChecked ) > -1 ) {
py = this.getNewLineIdx( py );
return this.findCoordsBig( py, px, stepY, w, h, linesChecked );
}
// has enough v space
var coords = this.getAvailableCoords( idxLine, px, w, h );
if( coords == -1 ) {
py = this.getNewLineIdx( py );
linesChecked.push( idxLine );
return this.findCoordsBig( py, px, stepY, w, h, linesChecked );
}
this.fillSpace( coords, w, h );
return coords;
}
Grid.prototype.getNewLineIdx = function getNewLineIdx( py ) {
py++;
if( py > this._countLines - 1 ) py = 0;
return py;
}
// we could add an orientation => fromLeft/fromRight
Grid.prototype.getAvailableCoords = function getAvailableCoords( idx, px, w, h, restart ) {
restart = restart == null ? true : restart;
// we are searching for the first available square
var isOK = true,
line = this._lines[ idx ],
i = px, j = 0, m = 0;
for( ; i < this._countCols; i++ ) {
if( line[ i ] == 1 ) // already occupied
continue;
if( i + w > this._countCols ) // if it's going outside of the zone
continue;
isOK = true;
for( j = i, m = i + w; j < m; j++ ) { // we are looking for i to i + w > origin to origin + width of the bloc
if( line[ j ] == 0 ) // it's OK
continue;
// if col already occupied, speed up, move the head
i = j;
isOK = false;
break;
}
if( !isOK )
continue;
if( !this.hasEnoughSpace( idx, i, w, h ) ) // check if the width and height fit
continue;
return { x: i, y: idx };
}
if( restart ) {
return this.getAvailableCoords( idx, 0, w, h, false );
}
return -1;
}
Grid.prototype.hasEnoughSpace = function hasEnoughSpace( idxLine, idxCol, w, h ) {
if( idxLine + h > this._countLines - 1 )
return false;
var line = null,
i = idxLine, n = idxLine + h,
j = idxCol, m = idxCol + w;
for( ; i < n; i++ ) {
line = this._lines[ i ];
for( j = idxCol; j < m; j++ ) {
if( line[ j ] == 1 )
return false;
}
}
return true;
}
Grid.prototype.fillSpace = function fillSpace( coords, w, h ) {
var line = this._lines[ coords.y ],
i = coords.y, j = 0, n = coords.y + h, m = coords.x + w;
for( ; i < n; i ++ ) {
line = this._lines[ i ];
for( j = coords.x; j < m; j++ ) {
line[ j ] = 1;
}
}
}
Grid.prototype.logMap = function logMap() {
for( var i = 0, n = this._lines.length; i < n; i++ ) {
var s = "";
for( var j = 0, m = this._lines[ i ].length; j < m; j++ ) {
s += this._lines[ i ][ j ];
}
}
}
Grid.prototype.placeSmalls = function placeSmalls( smalls ) {
var $small = null, coords = null,
x = 0, y = 0, wVal = 0,
idxSmall = 0, maxSmalls = smalls.length;
var navs = [];
idxSmall = maxSmalls;
console.log( smalls.length );
while( --idxSmall > -1 ) {
if( $( smalls[ idxSmall ] ).hasClass( "entry-nav" ) )
navs.push( smalls.splice( idxSmall, 1 )[ 0 ] );
}
if( navs.length >= 4 ) smalls.splice( 0, 0, $( navs[ 3 ] ) );
smalls.splice( 3, 0, $( navs[ 2 ] ) );
smalls.splice( 4, 0, $( navs[ 0 ] ) );
smalls.splice( 7, 0, $( navs[ 1 ] ) );
maxSmalls = smalls.length;
for( idxSmall = 0; idxSmall < maxSmalls; idxSmall++ ) {
$small = smalls[ idxSmall ];
coords = this.findCoordsSmall( x, y );
if( coords == null ) {
this.removeSmalls( smalls, idxSmall );
return y;
}
wVal = _cellWidth + "px";
$small.css( {
width: wVal,
height: wVal,
top: ( coords.y * _cellWidth + _spacing * coords.y ) + "px",
left: ( coords.x * _cellWidth + _spacing * coords.x ) + "px"
});
x = coords.x;
y = coords.y;
}
return y;
}
Grid.prototype.findCoordsSmall = function findCoordsSmall( x, y ) {
var line = null;
for( ; y < this._countLines; y++ ) {
line = this._lines[ y ];
for( ; x < this._countCols; x++ ) {
if( line[ x ] == 0 ) {
line[ x ] = 1
return { x: x, y: y }
}
}
x = 0;
}
return null;
}
Grid.prototype.removeSmalls = function removeSmalls( smalls, idxSmall ) {
var maxSmalls = smalls.length;
for( ; idxSmall < maxSmalls; idxSmall++ ) {
smalls[ idxSmall ].remove();
}
}
return Grid;
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment