Created
October 17, 2013 22:58
-
-
Save floz/7033797 to your computer and use it in GitHub Desktop.
JS - Grid.js
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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