');
$('.grille', $ctx).css({
'width': '100%',
'height': '100%',
'position': 'relative'
});
}
// create all empty cells
for (var l = 0; l < this.settings.lines; l++) {
_cells[l] = new Array();
for (var c = 0; c < this.settings.columns; c++) {
_cells[l][c] = new Cell(this, c, l);
};
};
function _setPrevCell(){
// _grid.prev_cell = false;
switch(_grid.settings.positioning_mode){
case 'lefttop': // add items from top left to bootm rif-ght
_grid.prev_cell = _cells[0][0];
break;
case 'center': // add items from center of grid to both side randomly
_grid.prev_cell = _cells[Math.floor(_grid.settings.lines*.5)][Math.floor(_grid.settings.columns*.5)];
break;
case 'borders': // add items from center of grid to both side randomly
var side = Math.floor(Math.random()*4);
$.log('side = '+side);
switch(side){
case 0 :
_grid.prev_cell = _cells[0][Math.floor(_grid.settings.columns*Math.random())];
break;
case 1 :
_grid.prev_cell = _cells[_grid.settings.lines-1][Math.floor(_grid.settings.columns*Math.random())];
break;
case 2 :
_grid.prev_cell = _cells[Math.floor(_grid.settings.lines*Math.random())][0];
break;
case 3 :
_grid.prev_cell = _cells[Math.floor(_grid.settings.lines*Math.random())][_grid.settings.columns-1];
break;
}
break;
case 'random': // add items randomly
default:
_grid.prev_cell = _cells[Math.floor(_grid.settings.lines*Math.random())][Math.floor(_grid.settings.columns*Math.random())];
break;
}
}
_setPrevCell();
/**
* placeTargets()
*/
function _placeTargets(){
// parse targets
var $targets = _grid.settings.children != '' ? $(_grid.settings.children+':not(.grid-placed)', $ctx) : $ctx.children(':not(.grid-placed)');
$targets.each(function() {
var $this = $(this),
// get the width and height ( ! on cell unit ! how much cells it takes ? ) of item to be positioned
this_cells_w = Math.ceil($this.width() / (_grid.settings.cell_w + _grid.settings.gouttiere)),
this_cells_h = Math.ceil($this.height() / (_grid.settings.cell_h + _grid.settings.gouttiere)),
// get free cells function of width and height of item
free_cells = getFreeCells(this_cells_w, this_cells_h);
if(free_cells.length > 0){
// positioning mode, to change this mode uncomment/comment lines after description
switch(_grid.settings.positioning_mode){
case 'lefttop': // add items from top left to bootm rif-ght
var cell_num = 0,
cell = free_cells[cell_num];
break;
default: // add items from center of grid to both side randomly
// var cell_num = Math.floor((free_cells.length-1)*0.5 + (-2+Math.random()*4));
// cell_num = cell_num > free_cells.length-1 ? free_cells.length-1 : ( cell_num < 0 ? 0 : cell_num );
// var cell = free_cells[cell_num];
var cell_num = Math.round(Math.random() * (free_cells.length - 1)),
cell = free_cells[cell_num];
break;
}
_grid.prev_cell = cell;
var line_limit_loop = cell.row() + (this_cells_h),
column_limit_loop = cell.column() + (this_cells_w);
for (var l = cell.row(); l < line_limit_loop; l++) {
for (var c = cell.column(); c < column_limit_loop; c++) {
var temp_cell = _cells[l][c];
temp_cell.setFull();
};
};
// get tp and left coordinates
// should be directly recorded in the cell object
var top = cell.row() * (_grid.settings.cell_h + _grid.settings.gouttiere),
left = cell.column() * (_grid.settings.cell_w + _grid.settings.gouttiere),
groove = _grid.settings.groove;
// set groove ;)
top = !groove ? top: top + Math.round(Math.random() * groove - groove / 2);
left = !groove ? left: left + Math.round(Math.random() * groove - groove / 2);
// apply ccs position
top += _grid.settings.cell_padding.t;
left += _grid.settings.cell_padding.l;
var event = jQuery.Event("grid_positioned");
event.top = top;
event.left = left;
$this.css({
'top': top,
'left': left
}).addClass('grid-positioned').trigger(event);
}else{
$.log('GRID no free cells left');
// if no free cells exist
$this.css({
'border': '2px solid red',
'opacity': 0.2
}).trigger('grid_removed');//.remove();
}
$this.addClass('grid-placed').trigger('grid_placed');
}); // end children each
}
/**
* getFreeCells()
*
* @ width in cells
* @ height in cells
*
* return array of cell objects
*
*/
function getFreeCells(this_cells_w, this_cells_h){
var free_cells = new Array(),
padding = _grid.settings.padding,
max_dist = _grid.settings.max_distance,
min_dist = _grid.settings.min_distance,
prev_cell = _grid.prev_cell;
// $.log()
for (var l = 0; l < _grid.settings.lines; l++) {
for (var c = 0; c < _grid.settings.columns; c++) {
var cell = _cells[l][c];
/*
TODO about the max_dist keep in mind that all element will not always be 1 cell elemnts !!
*/
// here is a big stuff of conditionning
// we check a lot of things
// 1 - basicly if the cell is free
// 2 - if the cell is under the padding limits
// 3 - if she has enought space arround her
// 4 - if we got a prev cell
// 4.1 - if we got a max_dist != 0
// 4.1.1 - if the cell is under the max limits
// 4.2 - if we got a min_dist != 0
// 4.2.1 - if the cell is behind the min limits
if (cell.isFree() // if cell is free
&& (cell.row() > padding.t && cell.row() < _grid.settings.lines - padding.b
&& cell.column() > padding.l && cell.column() < _grid.settings.columns - padding.r
)
&& (
(cell.getAround().right + 1) >= this_cells_w // if enought free space on the right
&& (cell.getAround().bottom + 1) >= this_cells_h // if enought free space on the bottom
)
&& ( !_grid.prev_cell // else if _grid.prev_cell undefined it's true
|| ( // check max_dist AND min_dist
(!max_dist // if max_distance is 0 return (stop condition) true
|| ( cell.row() < prev_cell.row()+max_dist && cell.row() > prev_cell.row()-max_dist
&& cell.column() < prev_cell.column()+max_dist && cell.column() > prev_cell.column()-max_dist )// if we got max_distance and prev_cell we check the distance
)
&&
(!min_dist // if min_distance is 0 return (stop condition) true
|| ( (cell.row() > prev_cell.row()+min_dist || cell.row() < prev_cell.row()-min_dist)
|| (cell.column() > prev_cell.column()+min_dist || cell.column() < prev_cell.column()-min_dist) )// if we got min_distance and prev_cell we check the distance
)
)
)
) { // true of first big stuff if
var good = true;
for (var i = 1; i < this_cells_w; i++) { // for each free cells needed on right
var temp_cell = _cells[l][c + i];
if ((temp_cell.getAround().bottom + 1) < this_cells_h) { // if enought free space on bottom
good = false;
break;
}
};
if (good) free_cells.push(cell);
}
};
};
return free_cells;
}
/**
* Cell()
*/
function Cell(g, c, r) {
var _grid = g,
_column = c,
_row = r,
_free = true,
_free_cell_right = _grid.settings.columns - 1 - c,
_free_cell_bottom = _grid.settings.lines - 1 - l;
if (_grid.settings.grille) {
var _table = '
';
_table += ' | | |
';
// _table += ' | '+_free+' | '+_free_cell_right+' |
';
_table += ' | | ' + _free_cell_right + ' |
';
_table += ' | ' + _free_cell_bottom + ' | |
';
_table += '
';
_grid.ctx.find('.grille').append('
' + _table + '
');
var _dom = $('.cell-' + l + '-' + c, _grid.ctx.find('.grille'));
_dom.css({
'position': 'absolute',
'top': _row * (_grid.settings.cell_h + _grid.settings.gouttiere) + _grid.settings.cell_padding.t,
'left': _column * (_grid.settings.cell_w + _grid.settings.gouttiere) + _grid.settings.cell_padding.l,
'width': _grid.settings.cell_w,
'height': _grid.settings.cell_h,
'backgroundColor': '#00FF00',
'opacity': 0.6
});
// $('td', _dom).css({
// 'fontSize': '8px'
// });
}
this.isFree = function() { return _free; };
this.getPos = function() { return { c: _column, l: _row }; };
this.column = function() { return _column; };
this.row = function() { return _row; };
this.getAround = function() { return { right: _free_cell_right, bottom: _free_cell_bottom }; };
this.setFull = function() {
_free = false;
_free_cell_bottom = -1;
_free_cell_right = -1;
if (_grid.settings.grille) {
_dom.css({
'backgroundColor': '#0000FF'
});
$('.fb', _dom).html(_free_cell_bottom);
$('.fr', _dom).html(_free_cell_right);
}
_propageFreeCells();
};
this.setFreeCellsRight = function(right) {
if (_free) {
// $.log('_setFreeCellRigth | _free_cell_right = ' + _free_cell_right + ' | new right = ' + right);
_free_cell_right = right;
if (_grid.settings.grille) $('.fr', _dom).html(_free_cell_right);
_propageFreeCellsLeft();
}
};
this.setFreeCellsBottom = function(bottom) {
if (_free) {
// $.log('_setFreeCellsBottom | _free_cell_bottom = ' + _free_cell_bottom + ' | new right = ' + bottom);
_free_cell_bottom = bottom;
if (_grid.settings.grille) $('.fb', _dom).html(_free_cell_bottom);
_propageFreeCellsTop();
}
};
function _propageFreeCells() {
// $.log('_propageFreeCells');
_propageFreeCellsLeft();
_propageFreeCellsTop();
};
function _propageFreeCellsLeft() {
// $.log('_propageFreeCellsLeft | _column = '+_column);
if (_column > 0) {
var left_cel = _cells[_row][_column - 1];
left_cel.setFreeCellsRight(_free_cell_right + 1);
}
};
function _propageFreeCellsTop() {
// $.log('_propageFreeCellsTop | _row = '+_row);
if (_row > 0) {
var top_cel = _cells[_row - 1][_column];
top_cel.setFreeCellsBottom(_free_cell_bottom + 1);
}
};
if (typeof Cell.initialized == "undefined") {
Cell.prototype.infos = function() {
$.log('cell | column = ' + this.column() + ', line = ' + this.row() + ', free = ' + this.isFree() + ', free cell right = ' + this.getAround().right + ', free cell bottom = ' + this.getAround().bottom);
};
Cell.initialized = true;
}
}; // cell()
if (typeof Node.initialized == "undefined") {
Grid.prototype.refresh = function() {
_placeTargets();
};
Grid.prototype.resetPrevCell = function() {
_setPrevCell();
// this.prev_cell = false;
};
Node.initialized = true;
}
};
(function($) {
$.fn.grid = function(settings) {
return this.each(function(index) {
$(this).data('grid', new Grid(this, settings));
});
}
})(jQuery);