Files
librenms-librenms/docs/files/src_jquery.gridster.js.html

2073 lines
68 KiB
HTML
Raw Normal View History

2012-07-18 18:31:44 +02:00
<!DOCTYPE html>
<html lang="en">
<head>
<meta charset="utf-8">
<title>src&#x2F;jquery.gridster.js</title>
<link rel="stylesheet" href="http:&#x2F;&#x2F;yui.yahooapis.com&#x2F;3.5.1&#x2F;build&#x2F;cssgrids&#x2F;cssgrids-min.css">
<link rel="stylesheet" href="..&#x2F;assets/vendor/prettify/prettify-min.css">
<link rel="stylesheet" href="..&#x2F;assets/css/main.css" id="site_styles">
<link rel="shortcut icon" type="image/png" href="..&#x2F;assets/favicon.png">
<script src="http:&#x2F;&#x2F;yui.yahooapis.com&#x2F;combo?3.5.1&#x2F;build&#x2F;yui&#x2F;yui-min.js"></script>
</head>
<body class="yui3-skin-sam">
<div id="doc">
<div id="hd" class="yui3-g header">
<div class="yui3-u-3-4">
<!-- <h1><img src="..&#x2F;assets/css/logo.png" title=""></h1> -->
<h1><img src="http://ducksboard.com/wp-content/themes/blog-theme-ducksboard/images/ducksboard.png" title=""></h1>
</div>
<div class="yui3-u-1-4 version">
<em>API Docs for: </em>
</div>
</div>
<div id="bd" class="yui3-g">
<div class="yui3-u-1-4">
<div id="docs-sidebar" class="sidebar apidocs">
<div id="api-list">
<h2 class="off-left">APIs</h2>
<div id="api-tabview" class="tabview">
<ul class="tabs">
<li><a href="#api-classes">Classes</a></li>
<li><a href="#api-modules">Modules</a></li>
</ul>
<div id="api-tabview-filter">
<input type="search" id="api-filter" placeholder="Type to filter APIs">
</div>
<div id="api-tabview-panel">
<ul id="api-classes" class="apis classes">
<li><a href="..&#x2F;classes/Collision.html">Collision</a></li>
<li><a href="..&#x2F;classes/Coords.html">Coords</a></li>
<li><a href="..&#x2F;classes/Gridster.html">Gridster</a></li>
</ul>
<ul id="api-modules" class="apis modules">
</ul>
</div>
</div>
</div>
</div>
</div>
<div class="yui3-u-3-4">
<div id="api-options">
Show:
<label for="api-show-inherited">
<input type="checkbox" id="api-show-inherited" checked>
Inherited
</label>
<label for="api-show-protected">
<input type="checkbox" id="api-show-protected">
Protected
</label>
<label for="api-show-private">
<input type="checkbox" id="api-show-private">
Private
</label>
<label for="api-show-deprecated">
<input type="checkbox" id="api-show-deprecated">
Deprecated
</label>
</div>
<div class="apidocs">
<div id="docs-main">
<div class="content">
<h1 class="file-heading">File: src&#x2F;jquery.gridster.js</h1>
<div class="file">
<pre class="code prettyprint linenums">
&#x2F;*
* jquery.gridster
* https:&#x2F;&#x2F;github.com&#x2F;ducksboard&#x2F;gridster.js
*
* Copyright (c) 2012 ducksboard
* Licensed under the MIT, GPL licenses.
*&#x2F;
;(function($, window, document, undefined) {
var defaults = {
widget_selector: &#x27;&gt; li&#x27;,
widget_margins: [10, 10],
widget_base_dimensions: [400, 225],
extra_rows: 0,
extra_cols: 0,
min_cols: 1,
min_rows: 10,
autogenerate_stylesheet: true,
serialize_params: function($w, wgd) {
return {
col: wgd.col,
row: wgd.row
};
},
collision: {
on_overlap: function(coords) {}
},
draggable: {
}
};
&#x2F;* Debounce and throttle functions taken from underscore.js *&#x2F;
var debounce = function(func, wait, immediate) {
var timeout;
return function() {
var context = this, args = arguments;
var later = function() {
timeout = null;
if (!immediate) func.apply(context, args);
};
if (immediate &amp;&amp; !timeout) func.apply(context, args);
clearTimeout(timeout);
timeout = setTimeout(later, wait);
};
};
var throttle = function(func, wait) {
var context, args, timeout, throttling, more, result;
var whenDone = debounce(function(){ more = throttling = false; }, wait, true);
return function() {
context = this; args = arguments;
var later = function() {
timeout = null;
if (more) func.apply(context, args);
whenDone();
};
if (!timeout) timeout = setTimeout(later, wait);
if (throttling) {
more = true;
} else {
result = func.apply(context, args);
}
whenDone();
throttling = true;
return result;
};
};
&#x2F;**
* @class Gridster
* @uses Coords
* @uses Collision
* @param {HTMLElement} el The HTMLelement that contains all the widgets.
* @param {Object} [options] An Object with all options you want to
* overwrite:
* @param {HTMLElement|String} [options.widget_selector] Define who will be the
* draggable widgets. Can be a CSS Selector String or a collection of
* HTMLElements
* @param {Array} [options.widget_margins] Margin between widgets. The first
* index for the horizontal margin (left, right) and the second
* for the vertical margin (top, bottom).
* @param {Array} [options.widget_base_dimensions] Base widget dimensions in
* pixels. The first index for the width and the second for the
* height.
* @param {Number} [options.extra_cols] Add more columns in addition to
* those that have been calculated.
* @param {Number} [options.extra_rows] Add more rows in addition to
* those that have been calculated.
* @param {Number} [options.min_cols] The minimum required columns.
* @param {Number} [options.min_rows] The minimum required rows.
* @param {Boolean} [options.autogenerate_stylesheet] If true, all the
* CSS required to position all widgets in their respective columns
* and rows will be generated automatically and injected to the
* &#x60;&lt;head&gt;&#x60; of the document. You can set this to false, and write
* your own CSS targeting rows and cols via data-attributes like so:
* &#x60;[data-col=&quot;1&quot;] { left: 10px; }&#x60;
* @param {Function} [options.serialize_params] Return the data you want
* for each widget in the serialization. Two arguments are passed:
* &#x60;$w&#x60;: the jQuery wrapped HTMLElement, and &#x60;wgd&#x60;: the grid
* coords object (&#x60;col&#x60;, &#x60;row&#x60;, &#x60;size_x&#x60;, &#x60;size_y&#x60;).
* @param {Object} [options.collision] An Object with all options for
* Collision class you want to overwrite. See Collision docs for
* more info.
* @param {Object} [options.draggable] An Object with all options for
* jQuery UI Draggable you want to overwrite. See
* http:&#x2F;&#x2F;jqueryui.com&#x2F;demos&#x2F;draggable&#x2F; for more info.
*
* @constructor
*&#x2F;
function Gridster(el, options) {
this.options = $.extend(true, defaults, options);
this.$el = $(el);
this.$wrapper = this.$el.parent();
this.$widgets = this.$el.find(this.options.widget_selector).addClass(&#x27;gs_w&#x27;);
this.widgets = [];
this.$changed = $([]);
this.wrapper_width = this.$wrapper.width();
this.min_widget_width = (this.options.widget_margins[0] * 2) +
this.options.widget_base_dimensions[0];
this.min_widget_height = (this.options.widget_margins[1] * 2) +
this.options.widget_base_dimensions[1];
this.init();
}
var fn = Gridster.prototype;
fn.init = function() {
this.generate_grid_and_stylesheet();
this.get_widgets_from_DOM();
this.set_dom_grid_height();
this.$wrapper.addClass(&#x27;ready&#x27;);
this.draggable();
};
&#x2F;**
* Add a new widget to the grid.
*
* @method add_widget
* @param {String} html The string representing the HTML of the widget.
* @param {Number} size_x The nº of rows the widget occupies horizontally.
* @param {Number} size_y The nº of columns the widget occupies vertically.
* @return {HTMLElement} Returns the jQuery wrapped HTMLElement representing
* the widget that was just created.
*&#x2F;
fn.add_widget = function(html, size_x, size_y) {
var $w = $(html).attr({
&#x27;data-col&#x27;: this.highest_occupied_cell.col,
&#x27;data-row&#x27;: this.highest_occupied_cell.row + 1,
&#x27;data-sizex&#x27; : size_x || 1,
&#x27;data-sizey&#x27; : size_y || 1
}).addClass(&#x27;gs_w&#x27;).appendTo(this.$el).hide();
this.$widgets = this.$widgets.add($w);
this.register_widget($w);
this.$widgets.draggable(&#x27;destroy&#x27;);
this.draggable();
this.set_dom_grid_height();
$w.fadeIn();
};
&#x2F;**
* Remove a widget from the grid.
*
* @method remove_widget
* @param {HTMLElement} el The jQuery wrapped HTMLElement you want to remove.
* @return {Class} Returns the instance of the Gridster Class.
*&#x2F;
fn.remove_widget = function(el) {
var $el = el instanceof jQuery ? el : $(el);
var wgd = $el.coords().grid;
this.$widgets = this.$widgets.not($el);
var $nexts = this.widgets_below($el);
this.remove_from_gridmap(wgd);
$el.fadeOut($.proxy(function(){
$el.remove();
$nexts.each($.proxy(function(i, widget){
this.move_widget_up( $(widget), wgd.size_y );
}, this));
}, this));
};
&#x2F;**
* Returns a serialized array of the widgets in the grid.
*
* @method serialize
* @param {HTMLElement} [$widgets] The collection of jQuery wrapped
* HTMLElements you want to serialize. If no argument is passed all widgets
* will be serialized.
* @return {Array} Returns an Array of Objects with the data specified in
* the serialize_params option.
*&#x2F;
fn.serialize = function($widgets) {
$widgets || ($widgets = this.$widgets);
var result = [];
$widgets.each($.proxy(function(i, widget){
result.push( this.options.serialize_params(
$(widget),$(widget).coords().grid ) );
}, this));
return result;
};
&#x2F;**
* Returns a serialized array of the widgets that have changed their position.
*
* @method serialize_changed
* @return {Array} Returns an Array of Objects with the data specified in
* the serialize_params option.
*&#x2F;
fn.serialize_changed = function() {
return this.serialize(this.$changed);
};
&#x2F;**
* Creates the grid coords object representing the widget a add it to the mapped array of positions
*
* @method serialize_changed
* @return {Array} Returns the instance of the Gridster class.
*&#x2F;
fn.register_widget = function($el) {
var widget_grid_data = {
&#x27;col&#x27;: parseInt($el.attr(&#x27;data-col&#x27;), 10),
&#x27;row&#x27;: parseInt($el.attr(&#x27;data-row&#x27;), 10),
&#x27;size_x&#x27;: parseInt($el.attr(&#x27;data-sizex&#x27;), 10),
&#x27;size_y&#x27;: parseInt($el.attr(&#x27;data-sizey&#x27;), 10),
&#x27;el&#x27;: $el
};
&#x2F;&#x2F; attach Coord object to player data-coord attribute
$el.data(&#x27;coords&#x27;, $el.coords());
&#x2F;&#x2F; Extend Coord object with grid position info
$el.data(&#x27;coords&#x27;).grid = widget_grid_data;
this.add_to_gridmap(widget_grid_data, $el);
this.widgets.push($el);
return this;
};
&#x2F;**
* Update in the mapped array of positions the value of cells represented by
* the grid coords object passed in the &#x60;grid_data&#x60; param.
*
* @param {Object} grid_data The grid coords object representing the cells
* to update in the mapped array.
* @param {HTMLElement|Boolean} value Pass &#x60;false&#x60; or the jQuery wrapped
* HTMLElement, depends if you want to delete an existing position or add
* a new one.
* @method update_widget_position
* @return {Class} Returns the instance of the Gridster Class.
*&#x2F;
fn.update_widget_position = function(grid_data, value) {
this.for_each_cell_occupied(grid_data, function(col, row) {
if (!this.gridmap[col]) { return this; }
this.gridmap[col][row] = value;
});
return this;
};
&#x2F;**
* Remove a widget from the mapped array of positions.
*
* @method remove_from_gridmap
* @param {Object} grid_data The grid coords object representing the cells
* to update in the mapped array.
* @return {Class} Returns the instance of the Gridster Class.
*&#x2F;
fn.remove_from_gridmap = function(grid_data){
return this.update_widget_position(grid_data, false);
};
&#x2F;**
* Add a widget to the mapped array of positions.
*
* @method add_to_gridmap
* @param {Object} grid_data The grid coords object representing the cells
* to update in the mapped array.
* @param {HTMLElement|Boolean} value The value to set in the specified
* position .
* @return {Class} Returns the instance of the Gridster Class.
*&#x2F;
fn.add_to_gridmap = function(grid_data, value){
this.update_widget_position(grid_data, value || grid_data.el);
if (grid_data.el) {
var $widgets = this.widgets_below(grid_data.el);
$widgets.each($.proxy(function(i, widget){
this.move_widget_up( $(widget));
}, this));
}
};
&#x2F;**
* Make widgets draggable. It Wraps the jQuery UI Draggable Plugin.
*
* @method draggable
* @return {Class} Returns the instance of the Gridster Class.
*&#x2F;
fn.draggable = function() {
var self = this;
var draggable_options = $.extend(true, {}, this.options.draggable, {
&#x2F;&#x2F; containment : this.$wrapper,
start: function(event, ui) {
self.$player = $(this);
self.on_start_drag.call(self, event, ui);
},
stop: function(event, ui) {
self.on_stop_drag.call(self, ui);
},
drag: throttle(function(event, ui) {
self.on_drag.call(self, event, ui);
}, 100, true)
});
this.$widgets.draggable(draggable_options);
return this;
};
&#x2F;**
* This function is executed when the player begins to be dragged.
*
* @method on_start_drag
* @param {Event} The original browser event
* @param {Object} A prepared ui object.
* See http:&#x2F;&#x2F;jqueryui.com&#x2F;demos&#x2F;draggable&#x2F; for more info.
*&#x2F;
fn.on_start_drag = function(event, ui) {
this.$player.addClass(&#x27;player&#x27;);
this.$wrapper.addClass(&#x27;dragging&#x27;);
this.player_grid_data = this.$player.coords().grid;
this.placeholder_grid_data = $.extend({}, this.player_grid_data);
&#x2F;&#x2F;set new grid height along the dragging period
this.$el.css(&#x27;height&#x27;, this.$el.height() +
(this.player_grid_data.size_y * this.min_widget_height));
var colliders = this.faux_grid;
var coords = this.$player.data(&#x27;coords&#x27;).coords;
this.cells_occupied_by_player = this.get_cells_occupied(this.player_grid_data);
this.cells_occupied_by_placeholder = this.get_cells_occupied(this.placeholder_grid_data);
this.last_cols = [];
this.last_rows = [];
&#x2F;&#x2F; see jquery.collision.js
this.drag_api = this.$player.collision(colliders, this.options.collision);
this.$preview_holder = $(&#x27;&lt;li &#x2F;&gt;&#x27;, {
&#x27;class&#x27;: &#x27;preview-holder&#x27;,
&#x27;data-row&#x27;: this.$player.attr(&#x27;data-row&#x27;),
&#x27;data-col&#x27;: this.$player.attr(&#x27;data-col&#x27;),
css: {
width: coords.width,
height: coords.height
}
}).appendTo(this.$el);
if (this.options.draggable.start) {
this.options.draggable.start.call(this, event, ui);
}
};
&#x2F;**
* This function is executed when the player is being dragged.
*
* @method on_drag
* @param {Event} The original browser event
* @param {Object} A prepared ui object.
* See http:&#x2F;&#x2F;jqueryui.com&#x2F;demos&#x2F;draggable&#x2F; for more info.
*&#x2F;
fn.on_drag = function(event, ui) {
this.colliders_data = this.drag_api.get_closest_colliders();
this.on_overlapped_column_change(
this.on_start_overlapping_column,
this.on_stop_overlapping_column
);
this.on_overlapped_row_change(
this.on_start_overlapping_row,
this.on_stop_overlapping_row
);
if (this.options.draggable.drag) {
this.options.draggable.drag.call(this, event, ui);
}
};
&#x2F;**
* This function is executed when the player stops being dragged.
*
* @method on_stop_drag
* @param {Event} The original browser event
* @param {Object} A prepared ui object.
* See http:&#x2F;&#x2F;jqueryui.com&#x2F;demos&#x2F;draggable&#x2F; for more info.
*&#x2F;
fn.on_stop_drag = function(event, ui) {
this.colliders_data = this.drag_api.get_closest_colliders();
this.on_overlapped_column_change(
this.on_start_overlapping_column,
this.on_stop_overlapping_column
);
this.on_overlapped_row_change(
this.on_start_overlapping_row,
this.on_stop_overlapping_row
);
this.$player.attr({
&#x27;data-col&#x27;: this.placeholder_grid_data.col,
&#x27;data-row&#x27;: this.placeholder_grid_data.row
}).css({
&#x27;left&#x27;: &#x27;&#x27;,
&#x27;top&#x27;: &#x27;&#x27;
}).removeClass(&#x27;player&#x27;);
this.$changed = this.$changed.add(this.$player);
this.cells_occupied_by_player = this.get_cells_occupied(
this.placeholder_grid_data);
this.set_cells_player_occupies(
this.placeholder_grid_data.col, this.placeholder_grid_data.row);
this.$player.coords().grid.row = this.placeholder_grid_data.row;
this.$player.coords().grid.col = this.placeholder_grid_data.col;
this.$player = null;
this.$preview_holder.remove();
this.set_dom_grid_height();
if (this.options.draggable.stop) {
this.options.draggable.stop.call(this, event, ui);
}
};
&#x2F;**
* Executes the callbacks passed as arguments when a column begins to be
* overlapped or stops being overlapped.
*
* @param {Function} start_callback Function executed when a new column
* begins to be overlapped. The column is passed as first argument.
* @param {Function} stop_callback Function executed when a column stops
* being overlapped. The column is passed as first argument.
* @method on_overlapped_column_change
* @return {Class} Returns the instance of the Gridster Class.
*&#x2F;
fn.on_overlapped_column_change = function(start_callback, stop_callback) {
if (!this.colliders_data.length) {
return;
}
var cols = this.get_targeted_columns(
this.colliders_data[0].el.data.col);
var last_n_cols = this.last_cols.length;
var n_cols = cols.length;
var i;
for (i = 0; i &lt; n_cols; i++) {
if ($.inArray(cols[i], this.last_cols) === -1) {
(start_callback || $.noop).call(this, cols[i]);
}
}
for (i = 0; i&lt; last_n_cols; i++) {
if ($.inArray(this.last_cols[i], cols) === -1) {
(stop_callback || $.noop).call(this, this.last_cols[i]);
}
}
this.last_cols = cols;
return this;
};
&#x2F;**
* Executes the callbacks passed as arguments when a row starts to be
* overlapped or stops being overlapped.
*
* @param {Function} start_callback Function executed when a new row begins
* to be overlapped. The row is passed as first argument.
* @param {Function} stop_callback Function executed when a row stops being
* overlapped. The row is passed as first argument.
* @method on_overlapped_row_change
* @return {Class} Returns the instance of the Gridster Class.
*&#x2F;
fn.on_overlapped_row_change = function(start_callback, end_callback) {
if (!this.colliders_data.length) {
return;
}
var rows = this.get_targeted_rows(this.colliders_data[0].el.data.row);
var last_n_rows = this.last_rows.length;
var n_rows = rows.length;
var i;
for (i = 0; i &lt; n_rows; i++) {
if ($.inArray(rows[i], this.last_rows) === -1) {
(start_callback || $.noop).call(this, rows[i]);
}
}
for (i = 0; i &lt; last_n_rows; i++) {
if ($.inArray(this.last_rows[i], rows) === -1) {
(end_callback || $.noop).call(this, this.last_rows[i]);
}
}
this.last_rows = rows;
};
&#x2F;**
* Sets the current position of the player
*
* @param {Function} start_callback Function executed when a new row begins
* to be overlapped. The row is passed as first argument.
* @param {Function} stop_callback Function executed when a row stops being
* overlapped. The row is passed as first argument.
* @method set_player
* @return {Class} Returns the instance of the Gridster Class.
*&#x2F;
fn.set_player = function(col, row) {
this.empty_cells_player_occupies();
var self = this;
var cell = self.colliders_data[0].el.data;
var to_col = cell.col;
var to_row = row || cell.row;
this.player_grid_data = {
col: to_col,
row: to_row,
size_y : this.player_grid_data.size_y,
size_x : this.player_grid_data.size_x
};
this.cells_occupied_by_player = this.get_cells_occupied(
this.player_grid_data);
var $overlapped_widgets = this.get_widgets_overlapped(
this.player_grid_data);
var constraints = this.widgets_constraints($overlapped_widgets);
this.manage_movements(constraints.can_go_up, to_col, to_row);
this.manage_movements(constraints.can_not_go_up, to_col, to_row);
&#x2F;* if there is not widgets overlapping in the new player position,
* update the new placeholder position. *&#x2F;
if (!$overlapped_widgets.length) {
var pp = this.can_go_player_up(this.player_grid_data);
if (pp !== false) {
to_row = pp;
}
this.set_placeholder(to_col, to_row);
}
return {
col: to_col,
row: to_row
};
};
&#x2F;**
* See which of the widgets in the $widgets param collection can go to
* a upper row and which not.
*
* @method widgets_contraints
* @param {HTMLElements} $widgets A jQuery wrapped collection of
* HTMLElements.
* @return {Array} Returns a literal Object with two keys: &#x60;can_go_up&#x60; &amp;
* &#x60;can_not_go_up&#x60;. Each contains a set of HTMLElements.
*&#x2F;
fn.widgets_constraints = function($widgets) {
var $widgets_can_go_up = $([]);
var $widgets_can_not_go_up;
var wgd_can_go_up = [];
var wgd_can_not_go_up = [];
$widgets.each($.proxy(function(i, w){
var $w = $(w);
var wgd = $w.coords().grid;
if (this.can_go_widget_up(wgd)) {
$widgets_can_go_up = $widgets_can_go_up.add($w);
wgd_can_go_up.push(wgd);
}else{
wgd_can_not_go_up.push(wgd);
}
}, this));
$widgets_can_not_go_up = $widgets.not($widgets_can_go_up);
return {
can_go_up: this.sort_by_row_asc(wgd_can_go_up),
can_not_go_up: this.sort_by_row_desc(wgd_can_not_go_up)
};
};
&#x2F;**
* Sorts an Array of grid coords objects (representing the grid coords of each widget) in ascending way.
*
* @method sort_by_row_asc
* @param {Array} widgets Array of grid coords objects
* @return {Array} Returns the array sorted.
*&#x2F;
fn.sort_by_row_asc = function(widgets) {
widgets = widgets.sort(function(a, b){
if (a.row &gt; b.row) {
return 1;
}
return -1;
});
return widgets;
};
&#x2F;**
* Sorts an Array of grid coords objects (representing the grid coords of each widget) in descending way.
*
* @method sort_by_row_desc
* @param {Array} widgets Array of grid coords objects
* @return {Array} Returns the array sorted.
*&#x2F;
fn.sort_by_row_desc = function(widgets) {
widgets = widgets.sort(function(a, b){
if (a.row + a.size_y &lt; b.row + b.size_y){
return 1;
}
return -1;
});
return widgets;
};
&#x2F;**
* Sorts an Array of grid coords objects (representing the grid coords of each widget) in descending way.
*
* @method manage_movements
* @param {HTMLElements} $widgets A jQuery collection of HTMLElements
* representing the widgets you want to move.
* @param {Number} to_col The column to which we want to move the widgets.
* @param {Number} to_row The row to which we want to move the widgets.
* @return {Class} Returns the instance of the Gridster Class.
*&#x2F;
fn.manage_movements = function($widgets, to_col, to_row) {
$.each($widgets, $.proxy(function(i, w){
var wgd = w;
var $w = wgd.el;
var can_go_widget_up = this.can_go_widget_up(wgd);
if (can_go_widget_up) {
&#x2F;&#x2F;target CAN go up
&#x2F;&#x2F;so move widget up
this.move_widget_to($w, can_go_widget_up);
this.set_placeholder(to_col, can_go_widget_up + wgd.size_y);
} else {
&#x2F;&#x2F;target can&#x27;t go up
var can_go_player_up = this.can_go_player_up(
this.player_grid_data);
if (!can_go_player_up) {
&#x2F;&#x2F; target can&#x27;t go up
&#x2F;&#x2F; player cant&#x27;t go up
&#x2F;&#x2F; so we need to move widget down to a position that dont
&#x2F;&#x2F; overlaps player
var y = (to_row + this.player_grid_data.size_y) - wgd.row;
this.move_widget_down($w, y);
this.set_placeholder(to_col, to_row);
}
}
}, this));
return this;
};
&#x2F;**
* Determines if there is a widget in the row and col given. Or if the
* HTMLElement passed as first argument is the player.
*
* @method is_player
* @param {Number|HTMLElement} col_or_el A jQuery wrapped collection of
* HTMLElements.
* @param {Number} [row] The column to which we want to move the widgets.
* @return {Boolean} Returns true or false.
*&#x2F;
fn.is_player = function(col_or_el, row) {
if (row &amp;&amp; !this.gridmap[col_or_el]) { return false; }
var $w = row ? this.gridmap[col_or_el][row] : col_or_el;
return $w &amp;&amp; $w.is(this.$player);
};
&#x2F;**
* Determines if the widget that is being dragged is currently over the row
* and col given.
*
* @method is_player_in
* @param {Number} col The column to check.
* @param {Number} row The row to check.
* @return {Boolean} Returns true or false.
*&#x2F;
fn.is_player_in = function(col, row) {
var c = this.cells_occupied_by_player;
return $.inArray(col, c.cols) &gt;= 0 &amp;&amp; $.inArray(row, c.rows) &gt;= 0;
};
&#x2F;**
* Determines if the placeholder is currently over the row and col given.
*
* @method is_placeholder_in
* @param {Number} col The column to check.
* @param {Number} row The row to check.
* @return {Boolean} Returns true or false.
*&#x2F;
fn.is_placeholder_in = function(col, row) {
var c = this.cells_occupied_by_placeholder || [];
return this.is_placeholder_in_col(col) &amp;&amp; $.inArray(row, c.rows) &gt;= 0;
};
fn.is_placeholder_in_col = function(col, row) {
return $.inArray(col, this.cells_occupied_by_placeholder.cols) &gt;= 0;
};
&#x2F;**
* Determines if the placeholder is currently over the row and col given.
*
* @method is_placeholder_in
* @param {Number} col The column to check.
* @param {Number} row The row to check.
* @return {Boolean} Returns true or false.
*&#x2F;
fn.is_placeholder_in = function(col, row) {
var c = this.cells_occupied_by_placeholder || [];
return $.inArray(col, c.cols) &gt;= 0 &amp;&amp; $.inArray(row, c.rows) &gt;= 0;
};
&#x2F;**
* Determines if the cell represented by col and row params is empty.
*
* @method is_empty
* @param {Number} col The column to check.
* @param {Number} row The row to check.
* @return {Boolean} Returns true or false.
*&#x2F;
fn.is_empty = function(col, row) {
if (typeof this.gridmap[col] !== &#x27;undefined&#x27; &amp;&amp;
typeof this.gridmap[col][row] !== &#x27;undefined&#x27; &amp;&amp;
this.gridmap[col][row] === false
) {
return true;
}
return false;
};
&#x2F;**
* Determines if the cell represented by col and row params is occupied.
*
* @method is_occupied
* @param {Number} col The column to check.
* @param {Number} row The row to check.
* @return {Boolean} Returns true or false.
*&#x2F;
fn.is_occupied = function(col, row) {
if (!this.gridmap[col]) {
return false;
}
if (this.gridmap[col][row]) {
return true;
}
return false;
};
&#x2F;**
* Determines if there is a widget in the cell represented by col&#x2F;row params.
*
* @method is_widget
* @param {Number} col The column to check.
* @param {Number} row The row to check.
* @return {Boolean|HTMLElement} Returns false if there is no widget,
* else returns the jQuery HTMLElement
*&#x2F;
fn.is_widget = function(col, row) {
var cell = this.gridmap[col];
if (!cell) {
return false;
}
cell = cell[row];
if (cell) {
return cell;
}
return false;
};
&#x2F;**
* Determines if there is a widget in the cell represented by col&#x2F;row
* params and if this is under the widget that is being dragged.
*
* @method is_widget_under_player
* @param {Number} col The column to check.
* @param {Number} row The row to check.
* @return {Boolean} Returns true or false.
*&#x2F;
fn.is_widget_under_player = function(col, row) {
if (this.is_widget(col, row)) {
return this.is_player_in(col, row);
}
return false;
};
&#x2F;**
* Get widgets overlapping with the player.
*
* @method get_widgets_under_player
* @return {HTMLElement} Returns a jQuery collection of HTMLElements
*&#x2F;
fn.get_widgets_under_player = function() {
var cells = this.cells_occupied_by_player;
var $widgets = $([]);
$.each(cells.cols, $.proxy(function(i, col){
$.each(cells.rows, $.proxy(function(i, row){
if(this.is_widget(col, row)){
$widgets = $widgets.add(this.gridmap[col][row]);
}
}, this));
}, this));
return $widgets;
};
&#x2F;**
* Put placeholder at the row and column specified.
*
* @method set_placeholder
* @param {Number} col The column to which we want to move the
* placeholder.
* @param {Number} row The row to which we want to move the
* placeholder.
* @return {Class} Returns the instance of the Gridster Class.
*&#x2F;
fn.set_placeholder = function(col, row) {
var phgd = $.extend({}, this.placeholder_grid_data);
var $nexts = this.widgets_below({
col: phgd.col,
row: phgd.row,
size_y: phgd.size_y,
size_x: phgd.size_x
});
var moved_down = this.placeholder_grid_data.row &lt; row;
var changed_column = this.placeholder_grid_data.col !== col;
this.placeholder_grid_data.col = col;
this.placeholder_grid_data.row = row;
this.cells_occupied_by_placeholder = this.get_cells_occupied(
this.placeholder_grid_data);
this.$preview_holder.attr({
&#x27;data-row&#x27; : row,
&#x27;data-col&#x27; : col
});
if (moved_down || changed_column) {
$nexts.each($.proxy(function(i, widget){
this.move_widget_up( $(widget) , this.placeholder_grid_data.col - col + phgd.size_y );
}, this));
}
};
&#x2F;**
* Determines whether the player can move to a position above.
*
* @method can_go_player_up
* @param {Object} widget_grid_data The actual grid coords object of the
* player.
* @return {Number|Boolean} If the player can be moved to an upper row
* returns the row number, else returns false.
*&#x2F;
fn.can_go_player_up = function(widget_grid_data) {
var p_bottom_row = widget_grid_data.row + widget_grid_data.size_y - 1;
var result = true;
var upper_rows = [];
var min_row = 10000;
var $widgets_under_player = this.get_widgets_under_player();
&#x2F;* generate an array with columns as index and array with upper rows
* empty as value *&#x2F;
this.for_each_column_occupied(widget_grid_data, function(tcol){
var grid_col = this.gridmap[tcol];
var r = p_bottom_row + 1;
upper_rows[tcol] = [];
while (--r &gt; 0){
if (this.is_empty(tcol, r) || this.is_player(tcol, r) ||
this.is_widget(tcol, r) &amp;&amp; grid_col[r].is($widgets_under_player)
) {
upper_rows[tcol].push(r);
min_row = r &lt; min_row ? r : min_row;
}else{
break;
}
}
if (upper_rows[tcol].length === 0) {
result = false;
return true; &#x2F;&#x2F;break
}
upper_rows[tcol].sort();
});
if (!result) { return false; }
return this.get_valid_rows(widget_grid_data, upper_rows, min_row);
};
&#x2F;**
* Determines whether a widget can move to a position above.
*
* @method can_go_widget_up
* @param {Object} widget_grid_data The actual grid coords object of the
* widget we want to check.
* @return {Number|Boolean} If the widget can be moved to an upper row
* returns the row number, else returns false.
*&#x2F;
fn.can_go_widget_up = function(widget_grid_data) {
var p_bottom_row = widget_grid_data.row + widget_grid_data.size_y - 1;
var result = true;
var upper_rows = [];
var min_row = 10000;
&#x2F;* generate an array with columns as index and array with upper rows
* empty as value *&#x2F;
this.for_each_column_occupied(widget_grid_data, function(tcol){
var grid_col = this.gridmap[tcol];
upper_rows[tcol] = [];
var r = p_bottom_row + 1;
while (--r &gt; 0) {
if (this.is_occupied(tcol, r) &amp;&amp; !this.is_player(tcol, r)) {
break;
}
if (!this.is_player(tcol, r) &amp;&amp;!this.is_placeholder_in(tcol, r)) {
upper_rows[tcol].push(r);
}
if (r &lt; min_row ) {
min_row = r;
}
}
if (upper_rows[tcol].length === 0) {
result = false;
return true; &#x2F;&#x2F;break
}
upper_rows[tcol].sort();
});
if (!result) { return false; }
return this.get_valid_rows(widget_grid_data, upper_rows, min_row);
};
&#x2F;**
* Search a valid row for the widget represented by &#x60;widget_grid_data&#x27; in
* the &#x60;upper_rows&#x60; array. Iteration starts from row specified in &#x60;min_row&#x60;.
*
* @method get_valid_rows
* @param {Object} widget_grid_data The actual grid coords object of the
* player.
* @param {Array} upper_rows An array with columns as index and arrays
* of valid rows as values.
* @param {Number} min_row The upper row from which the iteration will start.
* @return {Number|Boolean} Returns the upper row valid from the &#x60;upper_rows&#x60;
* for the widget in question.
*&#x2F;
fn.get_valid_rows = function(widget_grid_data, upper_rows, min_row){
var p_top_row = widget_grid_data.row;
var p_bottom_row = widget_grid_data.row + widget_grid_data.size_y - 1;
var size_y = widget_grid_data.size_y;
var r = min_row - 1;
var valid_rows = [];
while (++r &lt;= p_bottom_row ) {
var common = true;
$.each(upper_rows, function(col, rows){
if (rows &amp;&amp; $.inArray(r, rows) === -1) {
common = false;
}
});
if (common === true) {
valid_rows.push(r);
if (valid_rows.length === size_y) {
break;
}
}
}
var new_row = false;
if (size_y === 1) {
if (valid_rows[0] !== p_top_row) {
new_row = valid_rows[0] || false;
}
}else{
if (valid_rows[0] !== p_top_row) {
new_row = this.get_consecutive_numbers_index(
valid_rows, size_y);
}
}
return new_row;
};
fn.get_consecutive_numbers_index = function(arr, size_y) {
var max = arr.length;
var result = [];
var first = true;
var prev = -1; &#x2F;&#x2F; or null?
for (var i=0; i &lt; max; i++) {
if (first || arr[i] === prev + 1) {
result.push(i);
if (result.length === size_y) {
break;
}
first = false;
}else{
result = [];
first = true;
}
prev = arr[i];
}
return result.length &gt;= size_y ? arr[result[0]] : false;
};
&#x2F;**
* Get widgets overlapping with the player.
*
* @method get_widgets_overlapped
* @return {HTMLElements} Returns a jQuery collection of HTMLElements.
*&#x2F;
fn.get_widgets_overlapped = function() {
var $w;
var $widgets = $([]);
var used = [];
var rows_from_bottom = this.cells_occupied_by_player.rows.slice(0);
rows_from_bottom.reverse();
$.each(this.cells_occupied_by_player.cols, $.proxy(function(i, col){
$.each(rows_from_bottom, $.proxy(function(i, row){
&#x2F;&#x2F; if there is a widget in the player position
if (!this.gridmap[col]) { return true; } &#x2F;&#x2F;next iteration
var $w = this.gridmap[col][row];
if (this.is_occupied(col, row) &amp;&amp; !this.is_player($w) &amp;&amp;
$.inArray($w, used) === -1
) {
$widgets = $widgets.add($w);
used.push($w);
}
}, this));
}, this));
return $widgets;
};
&#x2F;**
* This callback is executed when the player begins to collide with a column.
*
* @method on_start_overlapping_column
* @param {Number} col The collided column.
* @return {HTMLElements} Returns a jQuery collection of HTMLElements.
*&#x2F;
fn.on_start_overlapping_column = function(col) {
this.set_player(col, false);
};
&#x2F;**
* A callback executed when the player begins to collide with a row.
*
* @method on_start_overlapping_row
* @param {Number} col The collided row.
* @return {HTMLElements} Returns a jQuery collection of HTMLElements.
*&#x2F;
fn.on_start_overlapping_row = function(row) {
this.set_player(false, row);
};
&#x2F;**
* A callback executed when the the player ends to collide with a column.
*
* @method on_stop_overlapping_column
* @param {Number} col The collided row.
* @return {HTMLElements} Returns a jQuery collection of HTMLElements.
*&#x2F;
fn.on_stop_overlapping_column = function(col) {
this.set_player();
var self = this;
this.for_each_widget_below(col, this.cells_occupied_by_player.rows[0],
function(tcol, trow) {
self.move_widget_up(this, self.player_grid_data.size_y);
});
};
&#x2F;**
* This callback is executed when the player ends to collide with a row.
*
* @method on_stop_overlapping_row
* @param {Number} row The collided row.
* @return {HTMLElements} Returns a jQuery collection of HTMLElements.
*&#x2F;
fn.on_stop_overlapping_row = function(row) {
this.set_player();
var self = this;
var cols = this.cells_occupied_by_player.cols;
for (var c = 0, cl = cols.length; c &lt; cl; c++) {
this.for_each_widget_below(cols[c], row, function(tcol, trow) {
self.move_widget_up(this, self.player_grid_data.size_y);
});
}
};
&#x2F;**
* Move a widget to a specific row. The cell or cells must be empty.
* If the widget has widgets below, all of these widgets will be moved also
* if they can.
*
* @method move_widget_to
* @param {HTMLElement} $widget The jQuery wrapped HTMLElement of the widget is going to be moved.
* @return {Class} Returns the instance of the Gridster Class.
*&#x2F;
fn.move_widget_to = function($widget, row) {
var self = this;
var widget_grid_data = $widget.coords().grid;
var diff = row - widget_grid_data.row;
var $next_widgets = this.widgets_below($widget);
var can_move_to_new_cell = this.can_move_to(
widget_grid_data, widget_grid_data.col, row, $widget);
if (can_move_to_new_cell === false) {
return false;
}
this.remove_from_gridmap(widget_grid_data);
widget_grid_data.row = row;
this.add_to_gridmap(widget_grid_data);
$widget.attr(&#x27;data-row&#x27;, row);
this.$changed = this.$changed.add($widget);
$next_widgets.each(function(i, widget){
var $w = $(widget);
var wgd = $w.coords().grid;
var can_go_up = self.can_go_widget_up(wgd);
if (can_go_up &amp;&amp; can_go_up !== wgd.row){
self.move_widget_to($w, can_go_up);
}
});
return this;
};
&#x2F;**
* Move up the specified widget and all below it.
*
* @method move_widget_up
* @param {HTMLElement} $widget The widget you want to move.
* @param {Number} [y_units] The number of cells that the widget has to move.
* @return {Class} Returns the instance of the Gridster Class.
*&#x2F;
fn.move_widget_up = function($widget, y_units) {
var el_grid_data = $widget.coords().grid;
var actual_row = el_grid_data.row;
var moved = [];
var can_go_up = true;
y_units || (y_units = 1);
if (!this.can_go_up($widget)) { return false; } &#x2F;&#x2F;break;
this.for_each_column_occupied(el_grid_data, function(col){
&#x2F;&#x2F; can_go_up
if ($.inArray($widget, moved) === -1) {
var widget_grid_data = $widget.coords().grid;
var next_row = actual_row - y_units;
next_row = this.can_go_up_to_row(widget_grid_data, col, next_row);
if (!next_row) {
return true;
}
var $next_widgets = this.widgets_below($widget);
this.remove_from_gridmap(widget_grid_data);
widget_grid_data.row = next_row;
this.add_to_gridmap(widget_grid_data);
$widget.attr(&#x27;data-row&#x27;, widget_grid_data.row);
this.$changed = this.$changed.add($widget);
moved.push($widget);
$next_widgets.each($.proxy(function(i, widget){
this.move_widget_up($(widget), y_units);
}, this));
}
});
};
&#x2F;**
* Move down the specified widget and all below it.
*
* @method move_widget_down
* @param {HTMLElement} $widget The jQuery object representing the widget you want to move.
* @param {Number} The number of cells that the widget has to move.
* @return {Class} Returns the instance of the Gridster Class.
*&#x2F;
fn.move_widget_down = function($widget, y_units) {
var el_grid_data = $widget.coords().grid;
var actual_row = el_grid_data.row;
var moved = [];
var y_diff = y_units;
if (!$widget) { return false; }
if ($.inArray($widget, moved) === -1) {
var widget_grid_data = $widget.coords().grid;
var next_row = actual_row + y_units;
var $next_widgets = this.widgets_below($widget);
this.remove_from_gridmap(widget_grid_data);
$next_widgets.each($.proxy(function(i, widget){
var $w = $(widget);
var wd = $w.coords().grid;
var tmp_y = this.displacement_diff(
wd, widget_grid_data, y_diff);
if (tmp_y &gt; 0) {
this.move_widget_down($w, tmp_y);
}
}, this));
widget_grid_data.row = next_row;
this.update_widget_position(widget_grid_data, $widget);
$widget.attr(&#x27;data-row&#x27;, widget_grid_data.row);
this.$changed = this.$changed.add($widget);
moved.push($widget);
}
};
&#x2F;**
* Check if the widget can move to the specified row, else returns the
* upper row possible.
*
* @method can_go_up_to_row
* @param {Number} widget_grid_data The current grid coords object of the
* widget.
* @param {Number} col The target column.
* @param {Number} row The target row.
* @return {Boolean|Number} Returns the row number if the widget can move
* to the target position, else returns false.
*&#x2F;
fn.can_go_up_to_row = function(widget_grid_data, col, row) {
var ga = this.gridmap;
var result = true;
var urc = []; &#x2F;&#x2F; upper_rows_in_columns
var actual_row = widget_grid_data.row;
var r;
&#x2F;&#x2F;generate an array with columns as index and array with upper rows empty in the column
this.for_each_column_occupied(widget_grid_data, function(tcol){
var grid_col = ga[tcol];
urc[tcol] = [];
r = actual_row;
while (r--){
if (this.is_empty(tcol, r) &amp;&amp;
!this.is_placeholder_in(tcol, r)
) {
urc[tcol].push(r);
}else{
break;
}
}
if (!urc[tcol].length) {
result = false;
return true;
}
});
if (!result) { return false; }
&#x2F;&#x2F;get common rows starting from upper position in all the columns widget occupies
r = row;
for (r = 1; r &lt; actual_row; r++) {
var common = true;
for (var uc = 0, ucl = urc.length; uc &lt; ucl; uc++) {
if (urc[uc] &amp;&amp; $.inArray(r, urc[uc]) === -1) {
common = false;
}
}
if (common === true) {
result = r;
break;
}
}
return result;
};
fn.displacement_diff = function(widget_grid_data, parent_bgd, y_units) {
var actual_row = widget_grid_data.row;
var diffs = [];
var parent_max_y = parent_bgd.row + parent_bgd.size_y;
this.for_each_column_occupied(widget_grid_data, function(col){
var temp_y_units = 0;
for (var r = parent_max_y; r &lt; actual_row; r++) {
if (this.is_empty(col, r)) {
temp_y_units = temp_y_units + 1;
}
}
diffs.push(temp_y_units);
});
var max_diff = Math.max.apply(null, diffs);
y_units = (y_units - max_diff);
return y_units &gt; 0 ? y_units : 0;
};
&#x2F;**
* Get widgets below a widget.
*
* @method widgets_below
* @param {HTMLElement} $el The jQuery wrapped HTMLElement.
* @return {HTMLElements} A jQuery collection of HTMLElements.
*&#x2F;
fn.widgets_below = function($el) {
var el_grid_data = $.isPlainObject($el) ? $el : $el.coords().grid;
var self = this;
var ga = this.gridmap;
var next_row = el_grid_data.row + el_grid_data.size_y - 1;
var $nexts = $([]);
this.for_each_column_occupied(el_grid_data, function(col){
self.for_each_widget_below(col, next_row,
function(tcol, trow){
if (!self.is_player(this) &amp;&amp;
$.inArray(this, $nexts) === -1) {
$nexts = $nexts.add(this);
return true; &#x2F;&#x2F; break
}
});
});
return this.sort_by_row_asc($nexts);
};
&#x2F;**
* Update the array of mapped positions with the new player position.
*
* @method set_cells_player_occupies
* @param {Number} col The new player col.
* @param {Number} col The new player row.
* @return {Class} Returns the instance of the Gridster Class.
*&#x2F;
fn.set_cells_player_occupies = function(col, row) {
this.remove_from_gridmap(this.placeholder_grid_data);
this.placeholder_grid_data.col = col;
this.placeholder_grid_data.row = row;
this.add_to_gridmap(this.placeholder_grid_data, this.$player);
return this;
};
&#x2F;**
* Remove from the array of mapped positions the reference to the player.
*
* @method empty_cells_player_occupies
* @return {Class} Returns the instance of the Gridster Class.
*&#x2F;
fn.empty_cells_player_occupies = function() {
this.remove_from_gridmap(this.placeholder_grid_data);
return this;
};
fn.can_go_up = function($el) {
var el_grid_data = $el.coords().grid;
var initial_row = el_grid_data.row;
var prev_row = initial_row - 1;
var ga = this.gridmap;
var upper_rows_by_column = [];
var result = true;
if (initial_row === 1) { return false; }
this.for_each_column_occupied(el_grid_data, function(col){
if (this.is_occupied(col, prev_row) ||
this.is_player(col, prev_row) ||
this.is_placeholder_in(col, prev_row)
) {
result = false;
return true; &#x2F;&#x2F;break
}
});
return result;
};
&#x2F;**
* Check if it&#x27;s possible to move a widget to a specific col&#x2F;row. It takes
* into account the dimensions (&#x60;size_y&#x60; and &#x60;size_x&#x60; attrs. of the grid coords
* object) the widget occupies.
*
* @method can_move_to
* @param {Object} widget_grid_data The grid coords object that represents
* the widget.
* @param {Object} The col target col.
* @param {Object} The row target row.
* @return {Boolean} Returns true if all cells are empty, else return false.
*&#x2F;
fn.can_move_to = function(widget_grid_data, col, row) {
var ga = this.gridmap;
var $w = widget_grid_data.el;
var future_wd = {
size_y: widget_grid_data.size_y,
size_x: widget_grid_data.size_x,
col: col,
row: row
};
var cells_occupied_by_w = this.get_cells_occupied(widget_grid_data);
var result = true;
this.for_each_cell_occupied(future_wd, function(tcol, trow){
var $tw = this.is_widget(tcol, trow);
if ($tw &amp;&amp; !$tw.is($w)) {
result = false;
}
});
return result;
};
&#x2F;**
* Given the leftmost column returns all columns that are overlapping with the player.
*
* @method get_targeted_columns
* @param {Number} [from_col] The leftmost column.
* @return {Array} Returns an array with column numbers.
*&#x2F;
fn.get_targeted_columns = function(from_col) {
var max = (from_col || this.player_grid_data.col) +
(this.player_grid_data.size_x - 1);
var cols = [];
for (var col = from_col; col &lt;= max; col++) {
cols.push(col);
}
return cols;
};
&#x2F;**
* Given the upper row returns all rows that are overlapping with the player.
*
* @method get_targeted_rows
* @param {Number} [from_row] The upper row.
* @return {Array} Returns an array with row numbers.
*&#x2F;
fn.get_targeted_rows = function(from_row) {
var max = (from_row || this.player_grid_data.row) +
(this.player_grid_data.size_y - 1);
var rows = [];
for (var row = from_row; row &lt;= max; row++) {
rows.push(row);
}
return rows;
};
&#x2F;**
* Get all columns and rows that a widget occupies.
*
* @method get_cells_occupied
* @param {Object} el_grid_data The grid coords object of the widget.
* @return {Object} Returns an object like &#x60;{ cols: [], rows: []}&#x60;.
*&#x2F;
fn.get_cells_occupied = function(el_grid_data) {
var cells = { cols: [], rows: []};
var i;
if (arguments[1] instanceof jQuery) {
el_grid_data = arguments[1].coords().grid;
}
for (i = 0; i &lt; el_grid_data.size_x; i++) {
var col = el_grid_data.col + i;
cells.cols.push(col);
}
for (i = 0; i &lt; el_grid_data.size_y; i++) {
var row = el_grid_data.row + i;
cells.rows.push(row);
}
return cells;
};
&#x2F;**
* Iterate over the cells occupied by a widget executing a function for
* each one.
*
* @method for_each_column_occupied
* @param {Object} el_grid_data The grid coords object that represents the
* widget.
* @param {Function} callback The function to execute on each column
* iteration. Column and row are passed as arguments.
* @return {Class} Returns the instance of the Gridster Class.
*&#x2F;
fn.for_each_cell_occupied = function(grid_data, callback) {
this.for_each_column_occupied(grid_data, function(col){
this.for_each_row_occupied(grid_data, function(row){
callback.call(this, col, row);
});
});
return this;
};
&#x2F;**
* Iterate over the columns occupied by a widget executing a function for
* each one.
*
* @method for_each_column_occupied
* @param {Object} el_grid_data The grid coords object that represents
* the widget.
* @param {Function} callback The function to execute on each column
* iteration. The column number is passed as first argument.
* @return {Class} Returns the instance of the Gridster Class.
*&#x2F;
fn.for_each_column_occupied = function(el_grid_data, callback) {
for (var i = 0; i &lt; el_grid_data.size_x; i++) {
var col = el_grid_data.col + i;
callback.call(this, col, el_grid_data);
}
};
&#x2F;**
* Iterate over the rows occupied by a widget executing a function for
* each one.
*
* @method for_each_row_occupied
* @param {Object} el_grid_data The grid coords object that represents
* the widget.
* @param {Function} callback The function to execute on each column iteration. The row number is passed as first argument.
* @return {Class} Returns the instance of the Gridster Class.
*&#x2F;
fn.for_each_row_occupied = function(el_grid_data, callback) {
for (var i = 0; i &lt; el_grid_data.size_y; i++) {
var row = el_grid_data.row + i;
callback.call(this, row, el_grid_data);
}
};
fn._traversing_widgets = function(type, direction, col, row, callback) {
var ga = this.gridmap;
if (!ga[col]) { return; }
var cr, max;
var action = type + &#x27;&#x2F;&#x27; + direction;
if (arguments[2] instanceof jQuery) {
var el_grid_data = arguments[2].coords().grid;
col = el_grid_data.col;
row = el_grid_data.row;
callback = arguments[3];
}
var matched = [];
var trow = row;
var methods = {
&#x27;for_each&#x2F;above&#x27;: function() {
while (trow--) {
if (trow &gt; 0 &amp;&amp; this.is_widget(col, trow) &amp;&amp;
$.inArray(ga[col][trow], matched) === -1
) {
cr = callback.call(ga[col][trow], col, trow);
matched.push(ga[col][trow]);
if (cr) { break; }
}
}
},
&#x27;for_each&#x2F;below&#x27;: function() {
for (trow = row + 1, max = ga[col].length; trow &lt; max; trow++) {
if (this.is_widget(col, trow) &amp;&amp;
$.inArray(ga[col][trow], matched) === -1
) {
cr = callback.call(ga[col][trow], col, trow);
matched.push(ga[col][trow]);
if (cr) { break; }
}
}
}
};
if (methods[action]) {
methods[action].call(this);
}
};
&#x2F;**
* Iterate over each widget above the column and row specified.
*
* @method for_each_widget_above
* @param {Number} col The column to start iterating.
* @param {Number} row The row to start iterating.
* @param {Function} callback The function to execute on each widget
* iteration. The value of &#x60;this&#x60; inside the function is the jQuery wrapped HTMLElement.
* @return {Class} Returns the instance of the Gridster Class.
*&#x2F;
fn.for_each_widget_above = function(col, row, callback) {
this._traversing_widgets(&#x27;for_each&#x27;, &#x27;above&#x27;, col, row, callback);
return this;
};
&#x2F;**
* Iterate over each widget below the column and row specified.
*
* @method for_each_widget_below
* @param {Number} col The column to start iterating.
* @param {Number} row The row to start iterating.
* @param {Function} callback The function to execute on each widget
* iteration. The value of &#x60;this&#x60; inside the function is the jQuery wrapped HTMLElement.
* @return {Class} Returns the instance of the Gridster Class.
*&#x2F;
fn.for_each_widget_below = function(col, row, callback) {
this._traversing_widgets(&#x27;for_each&#x27;, &#x27;below&#x27;, col, row, callback);
return this;
};
&#x2F;**
* Returns the highest occupied cell in the grid.
*
* @method get_highest_occupied_cell
* @return {Object} Returns an object with &#x60;col&#x60; and &#x60;row&#x60; numbers.
*&#x2F;
fn.get_highest_occupied_cell = function() {
var r;
var gm = this.gridmap;
var rows = [];
var row_in_col = [];
for (var c = gm.length - 1; c &gt;= 1; c--) {
for (r = gm[c].length - 1; r &gt;= 1; r--) {
if (this.is_widget(c, r)) {
rows.push(r);
row_in_col[r] = c;
break;
}
}
}
var highest_row = Math.max.apply(null, rows);
this.highest_occupied_cell = {
col: row_in_col[highest_row],
row: highest_row
};
return this.highest_occupied_cell;
};
&#x2F;**
* Set the current height of the parent grid.
*
* @method set_dom_grid_height
* @return {Object} Returns the instance of the Gridster class.
*&#x2F;
fn.set_dom_grid_height = function() {
var r = this.get_highest_occupied_cell().row;
this.$el.css(&#x27;height&#x27;, r * this.min_widget_height);
return this;
};
&#x2F;**
* It generates the neccessary styles to position the widgets.
*
* @method generate_stylesheet
* @param {Number} rows Number of columns.
* @param {Number} cols Number of rows.
* @return {Object} Returns the instance of the Gridster class.
*&#x2F;
fn.generate_stylesheet = function(rows, cols) {
var styles = &#x27;&#x27;;
var extra_cells = 10;
var max_size_y = 6;
var max_size_x = 6;
var i;
var rules;
&#x2F;* generate CSS styles for cols *&#x2F;
for (i = cols + extra_cells; i &gt;= 0; i--) {
styles += &#x27;[data-col=&quot;&#x27;+ (i + 1) +&#x27;&quot;] { left: &#x27; +
(i * this.min_widget_width) +
&#x27;px;} &#x27;;
}
&#x2F;* generate CSS styles for rows *&#x2F;
for (i = rows + extra_cells; i &gt;= 0; i--) {
styles += &#x27;[data-row=&quot;&#x27; + (i + 1) + &#x27;&quot;] { top: &#x27; +
(i * this.min_widget_height) + &#x27;px;} &#x27;;
}
for (var y = 1; y &lt; max_size_y; y++) {
styles += &#x27;[data-sizey=&quot;&#x27; + (y) + &#x27;&quot;] { height: &#x27; +
(y * this.options.widget_base_dimensions[1] + (y-1)*(this.options.widget_margins[1]*2)) + &#x27;px;}&#x27;;
}
for (var x = 1; x &lt; max_size_x; x++) {
styles += &#x27;[data-sizex=&quot;&#x27; + (x) + &#x27;&quot;] { width: &#x27; +
(x * this.options.widget_base_dimensions[0] + (x-1)*(this.options.widget_margins[0]*2)) + &#x27;px;}&#x27;;
}
return this.add_style_tag(styles);
};
&#x2F;**
* Injects the given CSS as string to the head of the document.
*
* @method generate_stylesheet
* @param {String} css The styles to apply.
* @return {Object} Returns the instance of the Gridster class.
*&#x2F;
fn.add_style_tag = function(css){
var d = document;
var tag = d.createElement(&#x27;style&#x27;);
d.getElementsByTagName(&#x27;head&#x27;)[0].appendChild(tag);
tag.setAttribute(&#x27;type&#x27;, &#x27;text&#x2F;css&#x27;);
if (tag.styleSheet) {
tag.styleSheet.cssText = css;
}else{
tag.appendChild(document.createTextNode(css));
}
return this;
};
&#x2F;**
* Generates a faux grid to collide with it when a widget is dragged and
* detect row or column that we want to go.
*
* @method generate_faux_grid
* @param {Number} rows Number of columns.
* @param {Number} cols Number of rows.
* @return {Object} Returns the instance of the Gridster class.
*&#x2F;
fn.generate_faux_grid = function(rows, cols) {
this.faux_grid = [];
this.gridmap = [];
var col;
var row;
for (col = cols; col &gt; 0; col--) {
this.gridmap[col] = [];
for (row = rows; row &gt; 0; row--) {
var coords = $({
left: this.baseX + ((col - 1) * this.min_widget_width),
top: this.baseY + (row -1) * this.min_widget_height,
width: this.min_widget_width,
height: this.min_widget_height,
col: col,
row: row,
original_col: col,
original_row: row
}).coords();
this.gridmap[col][row] = false;
this.faux_grid.push(coords);
}
}
return this;
};
&#x2F;**
* Get all widgets in the DOM and register them.
*
* @method get_widgets_from_DOM
* @return {Object} Returns the instance of the Gridster class.
*&#x2F;
fn.get_widgets_from_DOM = function() {
this.$widgets.each($.proxy(function(i, widget){
this.register_widget($(widget));
}, this));
return this;
};
&#x2F;**
* Calculate columns and rows to be set based on the configuration
* parameters, grid dimensions, etc ...
*
* @method generate_grid_and_stylesheet
* @return {Object} Returns the instance of the Gridster class.
*&#x2F;
fn.generate_grid_and_stylesheet = function() {
var grid_width;
var aw = this.$wrapper.width();
var ah = this.$wrapper.height();
var cols = Math.floor(aw&#x2F;this.min_widget_width) +
this.options.extra_cols;
var rows = Math.floor(ah&#x2F;this.min_widget_height) +
this.options.extra_rows;
var actual_cols = this.$widgets.map(function() {
return $(this).attr(&#x27;data-col&#x27;);
});
var actual_rows = this.$widgets.map(function() {
return $(this).attr(&#x27;data-row&#x27;);
});
var min_cols = Math.max.apply(null, actual_cols);
var min_rows = Math.max.apply(null, actual_rows);
cols = Math.max(min_cols, cols, this.options.min_cols);
rows = Math.max(min_rows, rows, this.options.min_rows);
grid_width = cols * (this.options.widget_base_dimensions[0] +
(this.options.widget_margins[0] * 2));
&#x2F;&#x2F;this.support_grid_width = cols * this.min_widget_width;
this.support_grid_width = this.wrapper_width;
this.support_grid_height = rows * this.min_widget_height;
this.baseX = ($(window).width() - this.support_grid_width) &#x2F; 2;
this.baseY = this.$wrapper.offset().top;
&#x2F;&#x2F;this.baseX = 0;
if(this.options.autogenerate_stylesheet) {
this.generate_stylesheet(rows, cols);
}
&#x2F;* more faux rows that needed are created so that there are cells
* where drag beyond the limits *&#x2F;
return this.generate_faux_grid(rows, cols);
};
&#x2F;&#x2F;jQuery adapter
$.fn.gridster = function(options) {
return this.each(function() {
if (!$(this).data(&#x27;gridster&#x27;)) {
$(this).data(&#x27;gridster&#x27;, new Gridster( this, options ));
}
});
};
}(jQuery, window, document));
</pre>
</div>
</div>
</div>
</div>
</div>
</div>
</div>
<script src="..&#x2F;assets/vendor/prettify/prettify-min.js"></script>
<script>prettyPrint();</script>
<script src="..&#x2F;assets/js/yui-prettify.js"></script>
<script src="..&#x2F;assets/../api.js"></script>
<script src="..&#x2F;assets/js/api-filter.js"></script>
<script src="..&#x2F;assets/js/api-list.js"></script>
<script src="..&#x2F;assets/js/api-search.js"></script>
<script src="..&#x2F;assets/js/apidocs.js"></script>
</body>
</html>