From 64de4684e332e89790f424425fbd4db64e6697da Mon Sep 17 00:00:00 2001 From: d Date: Wed, 17 Feb 2016 15:46:48 -0500 Subject: [PATCH] Added obsoletion code for deprecated methods and options. Added jscs settings and ensured code passed. Ensured code passed jshint. --- .jscsrc | 14 + src/gridstack.js | 2087 +++++++++++++++++++++++++--------------------- 2 files changed, 1142 insertions(+), 959 deletions(-) create mode 100644 .jscsrc diff --git a/.jscsrc b/.jscsrc new file mode 100644 index 0000000..423b011 --- /dev/null +++ b/.jscsrc @@ -0,0 +1,14 @@ +{ + "preset": "google", + "validateIndentation": "\t", + "maximumLineLength": 120, + "jsDoc": { + "checkAnnotations": { + "preset": "jsdoc3", + "extra": { + "preserve": true + } + } + }, + "requireCamelCaseOrUpperCaseIdentifiers": true +} diff --git a/src/gridstack.js b/src/gridstack.js index 15e2a2a..ac1d889 100644 --- a/src/gridstack.js +++ b/src/gridstack.js @@ -6,1015 +6,1184 @@ * @preserve */ (function(factory) { - if (typeof define === 'function' && define.amd) { - define(['jquery', 'lodash', 'jquery-ui/core', 'jquery-ui/widget', 'jquery-ui/mouse', 'jquery-ui/draggable', - 'jquery-ui/resizable'], factory); - } - else if (typeof exports !== 'undefined') { - try { jQuery = require('jquery'); } catch(e) {} - try { _ = require('lodash'); } catch(e) {} - factory(jQuery, _); - } - else { - factory(jQuery, _); - } + if (typeof define === 'function' && define.amd) { + define(['jquery', 'lodash', 'jquery-ui/core', 'jquery-ui/widget', 'jquery-ui/mouse', 'jquery-ui/draggable', + 'jquery-ui/resizable'], factory); + } else if (typeof exports !== 'undefined') { + try { jQuery = require('jquery'); } catch (e) {} + try { _ = require('lodash'); } catch (e) {} + factory(jQuery, _); + } else { + factory(jQuery, _); + } })(function($, _) { - var scope = window; - - var Utils = { - is_intercepted: function(a, b) { - return !(a.x + a.width <= b.x || b.x + b.width <= a.x || a.y + a.height <= b.y || b.y + b.height <= a.y); - }, - - sort: function(nodes, dir, width) { - width = width || _.chain(nodes).map(function(node) { return node.x + node.width; }).max().value(); - dir = dir != -1 ? 1 : -1; - return _.sortBy(nodes, function(n) { return dir * (n.x + n.y * width); }); - }, - - create_stylesheet: function(id) { - var style = document.createElement('style'); - style.setAttribute('type', 'text/css'); - style.setAttribute('data-gs-id', id); - if (style.styleSheet) { - style.styleSheet.cssText = ''; - } - else { - style.appendChild(document.createTextNode('')); - } - document.getElementsByTagName('head')[0].appendChild(style); - return style.sheet; - }, - remove_stylesheet: function(id) { - $("STYLE[data-gs-id=" + id +"]").remove(); - }, - insert_css_rule: function(sheet, selector, rules, index) { - if (typeof sheet.insertRule === 'function') { - sheet.insertRule(selector + '{' + rules + '}', index); - } - else if (typeof sheet.addRule === 'function') { - sheet.addRule(selector, rules, index); - } - }, - - toBool: function(v) { - if (typeof v == 'boolean') - return v; - if (typeof v == 'string') { - v = v.toLowerCase(); - return !(v == '' || v == 'no' || v == 'false' || v == '0'); - } - return Boolean(v); - } - }; - - var id_seq = 0; - - var GridStackEngine = function(width, onchange, float_mode, height, items) { - this.width = width; - this['float'] = float_mode || false; - this.height = height || 0; - - this.nodes = items || []; - this.onchange = onchange || function() {}; - - this._update_counter = 0; - this._float = this['float']; - }; - - GridStackEngine.prototype.batch_update = function() { - this._update_counter = 1; - this.float = true; - }; - - GridStackEngine.prototype.commit = function() { - this._update_counter = 0; - if (this._update_counter == 0) { - this.float = this._float; - this._pack_nodes(); - this._notify(); - } - }; - - GridStackEngine.prototype._fix_collisions = function(node) { - this._sort_nodes(-1); - - var nn = node, has_locked = Boolean(_.find(this.nodes, function(n) { return n.locked })); - if (!this.float && !has_locked) { - nn = {x: 0, y: node.y, width: this.width, height: node.height}; - } - - while (true) { - var collision_node = _.find(this.nodes, _.bind(function(n) { - return n != node && Utils.is_intercepted(n, nn); - }, this)); - if (typeof collision_node == 'undefined') { - return; - } - this.move_node(collision_node, collision_node.x, node.y + node.height, - collision_node.width, collision_node.height, true); - } - }; - - GridStackEngine.prototype.is_area_empty = function(x, y, width, height) { - var nn = {x: x || 0, y: y || 0, width: width || 1, height: height || 1}; - var collision_node = _.find(this.nodes, _.bind(function(n) { - return Utils.is_intercepted(n, nn); - }, this)); - return collision_node == null; - }; - - GridStackEngine.prototype._sort_nodes = function(dir) { - this.nodes = Utils.sort(this.nodes, dir, this.width); - }; - - GridStackEngine.prototype._pack_nodes = function() { - this._sort_nodes(); - - if (this.float) { - _.each(this.nodes, _.bind(function(n, i) { - if (n._updating || typeof n._orig_y == 'undefined' || n.y == n._orig_y) - return; - - var new_y = n.y; - while (new_y >= n._orig_y) { - var collision_node = _.chain(this.nodes) - .find(function(bn) { - return n != bn && - Utils.is_intercepted({x: n.x, y: new_y, width: n.width, height: n.height}, bn); - }) - .value(); - - if (!collision_node) { - n._dirty = true; - n.y = new_y; - } - --new_y; - } - }, this)); - } - else { - _.each(this.nodes, _.bind(function(n, i) { - if (n.locked) - return; - while (n.y > 0) { - var new_y = n.y - 1; - var can_be_moved = i == 0; - - if (i > 0) { - var collision_node = _.chain(this.nodes) - .take(i) - .find(function(bn) { - return Utils.is_intercepted({x: n.x, y: new_y, width: n.width, height: n.height}, bn); - }) - .value(); - can_be_moved = typeof collision_node == 'undefined'; - } - - if (!can_be_moved) { - break; - } - n._dirty = n.y != new_y; - n.y = new_y; - } - }, this)); - } - }; - - GridStackEngine.prototype._prepare_node = function(node, resizing) { - node = _.defaults(node || {}, {width: 1, height: 1, x: 0, y: 0 }); - - node.x = parseInt('' + node.x); - node.y = parseInt('' + node.y); - node.width = parseInt('' + node.width); - node.height = parseInt('' + node.height); - node.auto_position = node.auto_position || false; - node.no_resize = node.no_resize || false; - node.no_move = node.no_move || false; - - if (node.width > this.width) { - node.width = this.width; - } - else if (node.width < 1) { - node.width = 1; - } - - if (node.height < 1) { - node.height = 1; - } - - if (node.x < 0) { - node.x = 0; - } - - if (node.x + node.width > this.width) { - if (resizing) { - node.width = this.width - node.x; - } - else { - node.x = this.width - node.width; - } - } - - if (node.y < 0) { - node.y = 0; - } - - return node; - }; - - GridStackEngine.prototype._notify = function() { - if (this._update_counter) { - return; - } - var deleted_nodes = Array.prototype.slice.call(arguments, 1).concat(this.get_dirty_nodes()); - deleted_nodes = deleted_nodes.concat(this.get_dirty_nodes()); - this.onchange(deleted_nodes); - }; - - GridStackEngine.prototype.clean_nodes = function() { - _.each(this.nodes, function(n) {n._dirty = false }); - }; - - GridStackEngine.prototype.get_dirty_nodes = function() { - return _.filter(this.nodes, function(n) { return n._dirty; }); - }; - - GridStackEngine.prototype.add_node = function(node) { - node = this._prepare_node(node); - - if (typeof node.max_width != 'undefined') node.width = Math.min(node.width, node.max_width); - if (typeof node.max_height != 'undefined') node.height = Math.min(node.height, node.max_height); - if (typeof node.min_width != 'undefined') node.width = Math.max(node.width, node.min_width); - if (typeof node.min_height != 'undefined') node.height = Math.max(node.height, node.min_height); - - node._id = ++id_seq; - node._dirty = true; - - if (node.auto_position) { - this._sort_nodes(); - - for (var i = 0;; ++i) { - var x = i % this.width, y = Math.floor(i / this.width); - if (x + node.width > this.width) { - continue; - } - if (!_.find(this.nodes, function(n) { - return Utils.is_intercepted({x: x, y: y, width: node.width, height: node.height}, n); - })) { - node.x = x; - node.y = y; - break; - } - } - } - - this.nodes.push(node); - - this._fix_collisions(node); - this._pack_nodes(); - this._notify(); - return node; - }; - - GridStackEngine.prototype.remove_node = function(node) { - node._id = null; - this.nodes = _.without(this.nodes, node); - this._pack_nodes(); - this._notify(node); - }; - - GridStackEngine.prototype.can_move_node = function(node, x, y, width, height) { - var has_locked = Boolean(_.find(this.nodes, function(n) { return n.locked })); - - if (!this.height && !has_locked) - return true; - - var cloned_node; - var clone = new GridStackEngine( - this.width, - null, - this.float, - 0, - _.map(this.nodes, function(n) { - if (n == node) { - cloned_node = $.extend({}, n); - return cloned_node; - } - return $.extend({}, n); - })); - - clone.move_node(cloned_node, x, y, width, height); - - var res = true; - - if (has_locked) - res &= !Boolean(_.find(clone.nodes, function(n) { - return n != cloned_node && Boolean(n.locked) && Boolean(n._dirty); - })); - if (this.height) - res &= clone.get_grid_height() <= this.height; - - return res; - }; - - GridStackEngine.prototype.can_be_placed_with_respect_to_height = function(node) { - if (!this.height) - return true; - - var clone = new GridStackEngine( - this.width, - null, - this.float, - 0, - _.map(this.nodes, function(n) { return $.extend({}, n) })); - clone.add_node(node); - return clone.get_grid_height() <= this.height; - }; - - GridStackEngine.prototype.move_node = function(node, x, y, width, height, no_pack) { - if (typeof x != 'number') x = node.x; - if (typeof y != 'number') y = node.y; - if (typeof width != 'number') width = node.width; - if (typeof height != 'number') height = node.height; - - if (typeof node.max_width != 'undefined') width = Math.min(width, node.max_width); - if (typeof node.max_height != 'undefined') height = Math.min(height, node.max_height); - if (typeof node.min_width != 'undefined') width = Math.max(width, node.min_width); - if (typeof node.min_height != 'undefined') height = Math.max(height, node.min_height); - - if (node.x == x && node.y == y && node.width == width && node.height == height) { - return node; - } - - var resizing = node.width != width; - node._dirty = true; - - node.x = x; - node.y = y; - node.width = width; - node.height = height; - - node = this._prepare_node(node, resizing); - - this._fix_collisions(node); - if (!no_pack) { - this._pack_nodes(); - this._notify(); - } - return node; - }; - - GridStackEngine.prototype.get_grid_height = function() { - return _.reduce(this.nodes, function(memo, n) { return Math.max(memo, n.y + n.height); }, 0); - }; - - GridStackEngine.prototype.begin_update = function(node) { - _.each(this.nodes, function(n) { - n._orig_y = n.y; - }); - node._updating = true; - }; - - GridStackEngine.prototype.end_update = function() { - _.each(this.nodes, function(n) { - n._orig_y = n.y; - }); - var n = _.find(this.nodes, function(n) { return n._updating; }); - if (n) { - n._updating = false; - } - }; - - var GridStack = function(el, opts) { - var self = this, one_column_mode; - - opts = opts || {}; - - this.container = $(el); - - opts.item_class = opts.item_class || 'grid-stack-item'; - var is_nested = this.container.closest('.' + opts.item_class).size() > 0; - - this.opts = _.defaults(opts || {}, { - width: parseInt(this.container.attr('data-gs-width')) || 12, - height: parseInt(this.container.attr('data-gs-height')) || 0, - item_class: 'grid-stack-item', - placeholder_class: 'grid-stack-placeholder', - placeholder_text: '', - handle: '.grid-stack-item-content', - handle_class: null, - cell_height: 60, - vertical_margin: 20, - auto: true, - min_width: 768, - float: false, - static_grid: false, - _class: 'grid-stack-instance-' + (Math.random() * 10000).toFixed(0), - animate: Boolean(this.container.attr('data-gs-animate')) || false, - always_show_resize_handle: opts.always_show_resize_handle || false, - resizable: _.defaults(opts.resizable || {}, { - autoHide: !(opts.always_show_resize_handle || false), - handles: 'se' - }), - draggable: _.defaults(opts.draggable || {}, { - handle: (opts.handle_class ? '.' + opts.handle_class : (opts.handle ? opts.handle : '')) || '.grid-stack-item-content', - scroll: false, - appendTo: 'body' - }) - }); - this.opts.is_nested = is_nested; - - this.container.addClass(this.opts._class); - - this._set_static_class(); - - if (is_nested) { - this.container.addClass('grid-stack-nested'); - } - - this._init_styles(); - - this.grid = new GridStackEngine(this.opts.width, function(nodes) { - var max_height = 0; - _.each(nodes, function(n) { - if (n._id == null) { - n.el.remove(); - } - else { - n.el - .attr('data-gs-x', n.x) - .attr('data-gs-y', n.y) - .attr('data-gs-width', n.width) - .attr('data-gs-height', n.height); - max_height = Math.max(max_height, n.y + n.height); - } - }); - self._update_styles(max_height + 10); - }, this.opts.float, this.opts.height); - - if (this.opts.auto) { - var elements = []; - var _this = this; - this.container.children('.' + this.opts.item_class + ':not(.' + this.opts.placeholder_class + ')').each(function(index, el) { - el = $(el); - elements.push({ - el: el, - i: parseInt(el.attr('data-gs-x')) + parseInt(el.attr('data-gs-y')) * _this.opts.width - }); - }); - _.chain(elements).sortBy(function(x) { return x.i; }).each(function(i) { - self._prepare_element(i.el); - }).value(); - } - - this.set_animation(this.opts.animate); - - this.placeholder = $( - '
' + - '
' + this.opts.placeholder_text + '
').hide(); - - this.container.height( - this.grid.get_grid_height() * (this.opts.cell_height + this.opts.vertical_margin) - - this.opts.vertical_margin); - - this.on_resize_handler = function() { - if (self._is_one_column_mode()) { - if (one_column_mode) - return; - - one_column_mode = true; - - self.grid._sort_nodes(); - _.each(self.grid.nodes, function(node) { - self.container.append(node.el); - - if (self.opts.static_grid) { - return; - } - if (!node.no_move) { - node.el.draggable('disable'); - } - if (!node.no_resize) { - node.el.resizable('disable'); - } - }); - } - else { - if (!one_column_mode) - return; - - one_column_mode = false; - - if (self.opts.static_grid) { - return; - } - - _.each(self.grid.nodes, function(node) { - if (!node.no_move) { - node.el.draggable('enable'); - } - if (!node.no_resize) { - node.el.resizable('enable'); - } - }); - } - }; - - $(window).resize(this.on_resize_handler); - this.on_resize_handler(); - }; - - GridStack.prototype._trigger_change_event = function(forceTrigger) { - var elements = this.grid.get_dirty_nodes(); - var hasChanges = false; - - var eventParams = []; - if (elements && elements.length) { - eventParams.push(elements); - hasChanges = true; - } - - if (hasChanges || forceTrigger === true) { - this.container.trigger('change', eventParams); - } - }; - - GridStack.prototype._init_styles = function() { - if (this._styles_id) { - $('[data-gs-id="' + this._styles_id + '"]').remove(); - } - this._styles_id = 'gridstack-style-' + (Math.random() * 100000).toFixed(); - this._styles = Utils.create_stylesheet(this._styles_id); - if (this._styles != null) - this._styles._max = 0; - }; - - GridStack.prototype._update_styles = function(max_height) { - if (this._styles == null) { - return; - } - - var prefix = '.' + this.opts._class + ' .' + this.opts.item_class; - - if (typeof max_height == 'undefined') { - max_height = this._styles._max; - this._init_styles(); - this._update_container_height(); - } - - if (this._styles._max == 0) { - Utils.insert_css_rule(this._styles, prefix, 'min-height: ' + (this.opts.cell_height) + 'px;', 0); - } - - if (max_height > this._styles._max) { - for (var i = this._styles._max; i < max_height; ++i) { - Utils.insert_css_rule(this._styles, - prefix + '[data-gs-height="' + (i + 1) + '"]', - 'height: ' + (this.opts.cell_height * (i + 1) + this.opts.vertical_margin * i) + 'px;', - i - ); - Utils.insert_css_rule(this._styles, - prefix + '[data-gs-min-height="' + (i + 1) + '"]', - 'min-height: ' + (this.opts.cell_height * (i + 1) + this.opts.vertical_margin * i) + 'px;', - i - ); - Utils.insert_css_rule(this._styles, - prefix + '[data-gs-max-height="' + (i + 1) + '"]', - 'max-height: ' + (this.opts.cell_height * (i + 1) + this.opts.vertical_margin * i) + 'px;', - i - ); - Utils.insert_css_rule(this._styles, - prefix + '[data-gs-y="' + i + '"]', - 'top: ' + (this.opts.cell_height * i + this.opts.vertical_margin * i) + 'px;', - i - ); - } - this._styles._max = max_height; - } - }; - - GridStack.prototype._update_container_height = function() { - if (this.grid._update_counter) { - return; - } - this.container.height( - this.grid.get_grid_height() * (this.opts.cell_height + this.opts.vertical_margin) - - this.opts.vertical_margin); - }; - - GridStack.prototype._is_one_column_mode = function() { - return (window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth) <= - this.opts.min_width; - }; - - GridStack.prototype._prepare_element = function(el) { - var self = this; - el = $(el); - - el.addClass(this.opts.item_class); - - var node = self.grid.add_node({ - x: el.attr('data-gs-x'), - y: el.attr('data-gs-y'), - width: el.attr('data-gs-width'), - height: el.attr('data-gs-height'), - max_width: el.attr('data-gs-max-width'), - min_width: el.attr('data-gs-min-width'), - max_height: el.attr('data-gs-max-height'), - min_height: el.attr('data-gs-min-height'), - auto_position: Utils.toBool(el.attr('data-gs-auto-position')), - no_resize: Utils.toBool(el.attr('data-gs-no-resize')), - no_move: Utils.toBool(el.attr('data-gs-no-move')), - locked: Utils.toBool(el.attr('data-gs-locked')), - el: el - }); - el.data('_gridstack_node', node); - - if (self.opts.static_grid) { - return; - } - - var cell_width, cell_height; - - var drag_or_resize = function(event, ui) { - var x = Math.round(ui.position.left / cell_width), - y = Math.floor((ui.position.top + cell_height / 2) / cell_height), - width, height; - if (event.type != "drag") { - width = Math.round(ui.size.width / cell_width); - height = Math.round(ui.size.height / cell_height); - } - - if (!self.grid.can_move_node(node, x, y, width, height)) { - return; - } - self.grid.move_node(node, x, y, width, height); - self._update_container_height(); - }; - - var on_start_moving = function(event, ui) { - self.container.append(self.placeholder); - var o = $(this); - self.grid.clean_nodes(); - self.grid.begin_update(node); - cell_width = o.outerWidth() / o.attr('data-gs-width'); - cell_height = self.opts.cell_height + self.opts.vertical_margin; - self.placeholder - .attr('data-gs-x', o.attr('data-gs-x')) - .attr('data-gs-y', o.attr('data-gs-y')) - .attr('data-gs-width', o.attr('data-gs-width')) - .attr('data-gs-height', o.attr('data-gs-height')) - .show(); - node.el = self.placeholder; - - el.resizable('option', 'minWidth', Math.round(cell_width * (node.min_width || 1))); - el.resizable('option', 'minHeight', self.opts.cell_height * (node.min_height || 1)); - - if (event.type == 'resizestart') { - o.find('.grid-stack-item').trigger('resizestart'); - } - }; - - var on_end_moving = function(event, ui) { - self.placeholder.detach(); - var o = $(this); - node.el = o; - self.placeholder.hide(); - o - .attr('data-gs-x', node.x) - .attr('data-gs-y', node.y) - .attr('data-gs-width', node.width) - .attr('data-gs-height', node.height) - .removeAttr('style'); - self._update_container_height(); - self._trigger_change_event(); - - self.grid.end_update(); - - var nested_grids = o.find('.grid-stack'); - if (nested_grids.length && event.type == 'resizestop') { - nested_grids.each(function(index, el) { - $(el).data('gridstack').on_resize_handler(); - }); - o.find('.grid-stack-item').trigger('resizestop'); - } - }; - - el - .draggable(_.extend(this.opts.draggable, { - containment: this.opts.is_nested ? this.container.parent() : null, - start: on_start_moving, - stop: on_end_moving, - drag: drag_or_resize - })) - .resizable(_.extend(this.opts.resizable, { - start: on_start_moving, - stop: on_end_moving, - resize: drag_or_resize - })); - - if (node.no_move || this._is_one_column_mode()) { - el.draggable('disable'); - } - - if (node.no_resize || this._is_one_column_mode()) { - el.resizable('disable'); - } - - el.attr('data-gs-locked', node.locked ? 'yes' : null); - }; - - GridStack.prototype.set_animation = function(enable) { - if (enable) { - this.container.addClass('grid-stack-animate'); - } - else { - this.container.removeClass('grid-stack-animate'); - } - }; - - GridStack.prototype.add_widget = function(el, x, y, width, height, auto_position) { - el = $(el); - if (typeof x != 'undefined') el.attr('data-gs-x', x); - if (typeof y != 'undefined') el.attr('data-gs-y', y); - if (typeof width != 'undefined') el.attr('data-gs-width', width); - if (typeof height != 'undefined') el.attr('data-gs-height', height); - if (typeof auto_position != 'undefined') el.attr('data-gs-auto-position', auto_position ? 'yes' : null); - this.container.append(el); - this._prepare_element(el); - this._update_container_height(); - this._trigger_change_event(true); - - return el; - }; - - GridStack.prototype.make_widget = function(el) { - el = $(el); - this._prepare_element(el); - this._update_container_height(); - this._trigger_change_event(true); - - return el; - }; - - GridStack.prototype.will_it_fit = function(x, y, width, height, auto_position) { - var node = {x: x, y: y, width: width, height: height, auto_position: auto_position}; - return this.grid.can_be_placed_with_respect_to_height(node); - }; - - GridStack.prototype.remove_widget = function(el, detach_node) { - detach_node = typeof detach_node === 'undefined' ? true : detach_node; - el = $(el); - var node = el.data('_gridstack_node'); - this.grid.remove_node(node); - el.removeData('_gridstack_node'); - this._update_container_height(); - if (detach_node) - el.remove(); - this._trigger_change_event(true); - }; - - GridStack.prototype.remove_all = function(detach_node) { - _.each(this.grid.nodes, _.bind(function(node) { - this.remove_widget(node.el, detach_node); - }, this)); - this.grid.nodes = []; - this._update_container_height(); - }; - - GridStack.prototype.destroy = function() { - $(window).off("resize", this.on_resize_handler); - this.disable(); - this.container.remove(); - Utils.remove_stylesheet(this._styles_id); - if (this.grid) - this.grid = null; - }; - - GridStack.prototype.resizable = function(el, val) { - var self = this; - el = $(el); - el.each(function(index, el) { - el = $(el); - var node = el.data('_gridstack_node'); - if (typeof node == 'undefined' || node == null) { - return; - } - - node.no_resize = !(val || false); - if (node.no_resize || self._is_one_column_mode()) { - el.resizable('disable'); - } - else { - el.resizable('enable'); - } - }); - return this; - }; - - GridStack.prototype.movable = function(el, val) { - var self = this; - el = $(el); - el.each(function(index, el) { - el = $(el); - var node = el.data('_gridstack_node'); - if (typeof node == 'undefined' || node == null) { - return; - } - - node.no_move = !(val || false); - if (node.no_move || self._is_one_column_mode()) { - el.draggable('disable'); - el.removeClass('ui-draggable-handle'); - } - else { - el.draggable('enable'); - el.addClass('ui-draggable-handle'); - } - }); - return this; - }; - - GridStack.prototype.disable = function() { - this.movable(this.container.children('.' + this.opts.item_class), false); - this.resizable(this.container.children('.' + this.opts.item_class), false); - this.container.trigger('disable'); - }; - - GridStack.prototype.enable = function() { - this.movable(this.container.children('.' + this.opts.item_class), true); - this.resizable(this.container.children('.' + this.opts.item_class), true); - this.container.trigger('enable'); - }; - - GridStack.prototype.locked = function(el, val) { - el = $(el); - el.each(function(index, el) { - el = $(el); - var node = el.data('_gridstack_node'); - if (typeof node == 'undefined' || node == null) { - return; - } - - node.locked = (val || false); - el.attr('data-gs-locked', node.locked ? 'yes' : null); - }); - return this; - }; - - GridStack.prototype.min_height = function (el, val) { + var scope = window; + + var obsolete = function(f, oldName, newName) { + var wrapper = function() { + console.warn('gridstack.js: Function `' + oldName + '` is deprecated as of v0.2.5 and has been replaced with `' + + newName + '`. It will be **completely** removed in v1.0.'); + return f.apply(this, arguments); + }; + wrapper.prototype = f.prototype; + + return wrapper; + }; + + var obsoleteOpts = function(oldName, newName) { + console.warn('gridstack.js: Option `' + oldName + '` is deprecated as of v0.2.5 and has been replaced with `' + + newName + '`. It will be **completely** removed in v1.0.'); + }; + + var Utils = { + isIntercepted: function(a, b) { + return !(a.x + a.width <= b.x || b.x + b.width <= a.x || a.y + a.height <= b.y || b.y + b.height <= a.y); + }, + + sort: function(nodes, dir, width) { + width = width || _.chain(nodes).map(function(node) { return node.x + node.width; }).max().value(); + dir = dir != -1 ? 1 : -1; + return _.sortBy(nodes, function(n) { return dir * (n.x + n.y * width); }); + }, + + createStylesheet: function(id) { + var style = document.createElement('style'); + style.setAttribute('type', 'text/css'); + style.setAttribute('data-gs-id', id); + if (style.styleSheet) { + style.styleSheet.cssText = ''; + } else { + style.appendChild(document.createTextNode('')); + } + document.getElementsByTagName('head')[0].appendChild(style); + return style.sheet; + }, + + removeStylesheet: function(id) { + $('STYLE[data-gs-id=' + id + ']').remove(); + }, + + insertCSSRule: function(sheet, selector, rules, index) { + if (typeof sheet.insertRule === 'function') { + sheet.insertRule(selector + '{' + rules + '}', index); + } else if (typeof sheet.addRule === 'function') { + sheet.addRule(selector, rules, index); + } + }, + + toBool: function(v) { + if (typeof v == 'boolean') { + return v; + } + if (typeof v == 'string') { + v = v.toLowerCase(); + return !(v === '' || v == 'no' || v == 'false' || v == '0'); + } + return Boolean(v); + }, + + _collisionNodeCheck: function(n) { + return n != this.node && Utils.isIntercepted(n, this.nn); + }, + + _didCollideFloat: function(bn) { + return this.n != bn && + Utils.isIntercepted({x: this.n.x, y: this.newY, width: this.n.width, height: this.n.height}, bn); + }, + + _didCollide: function(bn) { + return Utils.isIntercepted({x: this.n.x, y: this.newY, width: this.n.width, height: this.n.height}, bn); + }, + + _isAddNodeIntercepted: function(n) { + return Utils.isIntercepted({x: this.x, y: this.y, width: this.node.width, height: this.node.height}, n); + } + }; + + // jscs:disable requireCamelCaseOrUpperCaseIdentifiers + Utils.is_intercepted = obsolete(Utils.isIntercepted, 'is_intercepted', 'isIntercepted'); + + Utils.create_stylesheet = obsolete(Utils.createStylesheet, 'create_stylesheet', 'createStylesheet'); + + Utils.remove_stylesheet = obsolete(Utils.removeStylesheet, 'remove_stylesheet', 'removeStylesheet'); + + Utils.insert_css_rule = obsolete(Utils.insertCSSRule, 'insert_css_rule', 'insertCSSRule'); + // jscs:enable requireCamelCaseOrUpperCaseIdentifiers + + var idSeq = 0; + + var GridStackEngine = function(width, onchange, floatMode, height, items) { + this.width = width; + this.float = floatMode || false; + this.height = height || 0; + + this.nodes = items || []; + this.onchange = onchange || function() {}; + + this._updateCounter = 0; + this._float = this.float; + }; + + GridStackEngine.prototype.batchUpdate = function() { + this._updateCounter = 1; + this.float = true; + }; + + GridStackEngine.prototype.commit = function() { + this._updateCounter = 0; + if (this._updateCounter === 0) { + this.float = this._float; + this._packNodes(); + this._notify(); + } + }; + + GridStackEngine.prototype._fixCollisions = function(node) { + var self = this; + this._sortNodes(-1); + + var nn = node; + var hasLocked = Boolean(_.find(this.nodes, function(n) { return n.locked; })); + if (!this.float && !hasLocked) { + nn = {x: 0, y: node.y, width: this.width, height: node.height}; + } + while (true) { + var collisionNode = _.find(this.nodes, _.bind(Utils._collisionNodeCheck, {node: node, nn: nn})); + if (typeof collisionNode == 'undefined') { + return; + } + this.moveNode(collisionNode, collisionNode.x, node.y + node.height, + collisionNode.width, collisionNode.height, true); + } + }; + + GridStackEngine.prototype.isAreaEmpty = function(x, y, width, height) { + var nn = {x: x || 0, y: y || 0, width: width || 1, height: height || 1}; + var collisionNode = _.find(this.nodes, _.bind(function(n) { + return Utils.isIntercepted(n, nn); + }, this)); + return collisionNode === null; + }; + + GridStackEngine.prototype._sortNodes = function(dir) { + this.nodes = Utils.sort(this.nodes, dir, this.width); + }; + + GridStackEngine.prototype._packNodes = function() { + this._sortNodes(); + + if (this.float) { + _.each(this.nodes, _.bind(function(n, i) { + if (n._updating || typeof n._origY == 'undefined' || n.y == n._origY) { + return; + } + + var newY = n.y; + while (newY >= n._origY) { + var collisionNode = _.chain(this.nodes) + .find(_.bind(Utils._didCollide, {n: n, newY: newY})) + .value(); + + if (!collisionNode) { + n._dirty = true; + n.y = newY; + } + --newY; + } + }, this)); + } else { + _.each(this.nodes, _.bind(function(n, i) { + if (n.locked) { + return; + } + while (n.y > 0) { + var newY = n.y - 1; + var canBeMoved = i === 0; + + if (i > 0) { + var collisionNode = _.chain(this.nodes) + .take(i) + .find(_.bind(Utils._didCollide, {n: n, newY: newY})) + .value(); + canBeMoved = typeof collisionNode == 'undefined'; + } + + if (!canBeMoved) { + break; + } + n._dirty = n.y != newY; + n.y = newY; + } + }, this)); + } + }; + + GridStackEngine.prototype._prepareNode = function(node, resizing) { + node = _.defaults(node || {}, {width: 1, height: 1, x: 0, y: 0}); + + node.x = parseInt('' + node.x); + node.y = parseInt('' + node.y); + node.width = parseInt('' + node.width); + node.height = parseInt('' + node.height); + node.autoPosition = node.autoPosition || false; + node.noResize = node.noResize || false; + node.noMove = node.noMove || false; + + if (node.width > this.width) { + node.width = this.width; + } else if (node.width < 1) { + node.width = 1; + } + + if (node.height < 1) { + node.height = 1; + } + + if (node.x < 0) { + node.x = 0; + } + + if (node.x + node.width > this.width) { + if (resizing) { + node.width = this.width - node.x; + } else { + node.x = this.width - node.width; + } + } + + if (node.y < 0) { + node.y = 0; + } + + return node; + }; + + GridStackEngine.prototype._notify = function() { + if (this._updateCounter) { + return; + } + var deletedNodes = Array.prototype.slice.call(arguments, 1).concat(this.getDirtyNodes()); + deletedNodes = deletedNodes.concat(this.getDirtyNodes()); + this.onchange(deletedNodes); + }; + + GridStackEngine.prototype.cleanNodes = function() { + _.each(this.nodes, function(n) {n._dirty = false; }); + }; + + GridStackEngine.prototype.getDirtyNodes = function() { + return _.filter(this.nodes, function(n) { return n._dirty; }); + }; + + GridStackEngine.prototype.addNode = function(node) { + node = this._prepareNode(node); + + if (typeof node.maxWidth != 'undefined') { node.width = Math.min(node.width, node.maxWidth); } + if (typeof node.maxHeight != 'undefined') { node.height = Math.min(node.height, node.maxHeight); } + if (typeof node.minWidth != 'undefined') { node.width = Math.max(node.width, node.minWidth); } + if (typeof node.minHeight != 'undefined') { node.height = Math.max(node.height, node.minHeight); } + + node._id = ++idSeq; + node._dirty = true; + + if (node.autoPosition) { + this._sortNodes(); + + for (var i = 0;; ++i) { + var x = i % this.width; + var y = Math.floor(i / this.width); + if (x + node.width > this.width) { + continue; + } + if (!_.find(this.nodes, _.bind(Utils._isAddNodeIntercepted, {x: x, y: y, node: node}))) { + node.x = x; + node.y = y; + break; + } + } + } + + this.nodes.push(node); + + this._fixCollisions(node); + this._packNodes(); + this._notify(); + return node; + }; + + GridStackEngine.prototype.removeNode = function(node) { + node._id = null; + this.nodes = _.without(this.nodes, node); + this._packNodes(); + this._notify(node); + }; + + GridStackEngine.prototype.canMoveNode = function(node, x, y, width, height) { + var hasLocked = Boolean(_.find(this.nodes, function(n) { return n.locked; })); + + if (!this.height && !hasLocked) { + return true; + } + + var clonedNode; + var clone = new GridStackEngine( + this.width, + null, + this.float, + 0, + _.map(this.nodes, function(n) { + if (n == node) { + clonedNode = $.extend({}, n); + return clonedNode; + } + return $.extend({}, n); + })); + + clone.moveNode(clonedNode, x, y, width, height); + + var res = true; + + if (hasLocked) { + res &= !Boolean(_.find(clone.nodes, function(n) { + return n != clonedNode && Boolean(n.locked) && Boolean(n._dirty); + })); + } + if (this.height) { + res &= clone.getGridHeight() <= this.height; + } + + return res; + }; + + GridStackEngine.prototype.canBePlacedWithRespectToHeight = function(node) { + if (!this.height) { + return true; + } + + var clone = new GridStackEngine( + this.width, + null, + this.float, + 0, + _.map(this.nodes, function(n) { return $.extend({}, n); })); + clone.addNode(node); + return clone.getGridHeight() <= this.height; + }; + + GridStackEngine.prototype.moveNode = function(node, x, y, width, height, noPack) { + if (typeof x != 'number') { x = node.x; } + if (typeof y != 'number') { y = node.y; } + if (typeof width != 'number') { width = node.width; } + if (typeof height != 'number') { height = node.height; } + + if (typeof node.maxWidth != 'undefined') { width = Math.min(width, node.maxWidth); } + if (typeof node.maxHeight != 'undefined') { height = Math.min(height, node.maxHeight); } + if (typeof node.minWidth != 'undefined') { width = Math.max(width, node.minWidth); } + if (typeof node.minHeight != 'undefined') { height = Math.max(height, node.minHeight); } + + if (node.x == x && node.y == y && node.width == width && node.height == height) { + return node; + } + + var resizing = node.width != width; + node._dirty = true; + + node.x = x; + node.y = y; + node.width = width; + node.height = height; + + node = this._prepareNode(node, resizing); + + this._fixCollisions(node); + if (!noPack) { + this._packNodes(); + this._notify(); + } + return node; + }; + + GridStackEngine.prototype.getGridHeight = function() { + return _.reduce(this.nodes, function(memo, n) { return Math.max(memo, n.y + n.height); }, 0); + }; + + GridStackEngine.prototype.beginUpdate = function(node) { + _.each(this.nodes, function(n) { + n._origY = n.y; + }); + node._updating = true; + }; + + GridStackEngine.prototype.endUpdate = function() { + _.each(this.nodes, function(n) { + n._origY = n.y; + }); + var n = _.find(this.nodes, function(n) { return n._updating; }); + if (n) { + n._updating = false; + } + }; + + var GridStack = function(el, opts) { + var self = this; + var oneColumnMode; + + opts = opts || {}; + + this.container = $(el); + + // jscs:disable requireCamelCaseOrUpperCaseIdentifiers + if (typeof opts.handle_class !== 'undefined') { + opts.handleClass = opts.handle_class; + obsoleteOpts('handle_class', 'handleClass'); + } + if (typeof opts.item_class !== 'undefined') { + opts.itemClass = opts.item_class; + obsoleteOpts('item_class', 'itemClass'); + } + if (typeof opts.placeholder_class !== 'undefined') { + opts.placeholderClass = opts.placeholder_class; + obsoleteOpts('placeholder_class', 'placeholderClass'); + } + if (typeof opts.placeholder_text !== 'undefined') { + opts.placeholderText = opts.placeholder_text; + obsoleteOpts('placeholder_text', 'placeholderText'); + } + if (typeof opts.item_class !== 'undefined') { + opts.itemClass = opts.item_class; + obsoleteOpts('item_class', 'itemClass'); + } + if (typeof opts.cell_height !== 'undefined') { + opts.cellHeight = opts.cell_height; + obsoleteOpts('cell_height', 'cellHeight'); + } + if (typeof opts.vertical_margin !== 'undefined') { + opts.verticalMargin = opts.vertical_margin; + obsoleteOpts('vertical_margin', 'verticalMargin'); + } + if (typeof opts.min_width !== 'undefined') { + opts.minWidth = opts.min_width; + obsoleteOpts('min_width', 'minWidth'); + } + if (typeof opts.static_grid !== 'undefined') { + opts.staticGrid = opts.static_grid; + obsoleteOpts('static_grid', 'staticGrid'); + } + if (typeof opts.is_nested !== 'undefined') { + opts.isNested = opts.is_nested; + obsoleteOpts('is_nested', 'isNested'); + } + if (typeof opts.always_show_resize_handle !== 'undefined') { + opts.alwaysShowResizeHandle = opts.always_show_resize_handle; + obsoleteOpts('always_show_resize_handle', 'alwaysShowResizeHandle'); + } + // jscs:enable requireCamelCaseOrUpperCaseIdentifiers + + opts.itemClass = opts.itemClass || 'grid-stack-item'; + var isNested = this.container.closest('.' + opts.itemClass).size() > 0; + + this.opts = _.defaults(opts || {}, { + width: parseInt(this.container.attr('data-gs-width')) || 12, + height: parseInt(this.container.attr('data-gs-height')) || 0, + itemClass: 'grid-stack-item', + placeholderClass: 'grid-stack-placeholder', + placeholderText: '', + handle: '.grid-stack-item-content', + handleClass: null, + cellHeight: 60, + verticalMargin: 20, + auto: true, + minWidth: 768, + float: false, + staticGrid: false, + _class: 'grid-stack-instance-' + (Math.random() * 10000).toFixed(0), + animate: Boolean(this.container.attr('data-gs-animate')) || false, + alwaysShowResizeHandle: opts.alwaysShowResizeHandle || false, + resizable: _.defaults(opts.resizable || {}, { + autoHide: !(opts.alwaysShowResizeHandle || false), + handles: 'se' + }), + draggable: _.defaults(opts.draggable || {}, { + handle: (opts.handleClass ? '.' + opts.handleClass : (opts.handle ? opts.handle : '')) || + '.grid-stack-item-content', + scroll: false, + appendTo: 'body' + }) + }); + this.opts.isNested = isNested; + + this.container.addClass(this.opts._class); + + this._setStaticClass(); + + if (isNested) { + this.container.addClass('grid-stack-nested'); + } + + this._initStyles(); + + this.grid = new GridStackEngine(this.opts.width, function(nodes) { + var maxHeight = 0; + _.each(nodes, function(n) { + if (n._id === null) { + n.el.remove(); + } else { + n.el + .attr('data-gs-x', n.x) + .attr('data-gs-y', n.y) + .attr('data-gs-width', n.width) + .attr('data-gs-height', n.height); + maxHeight = Math.max(maxHeight, n.y + n.height); + } + }); + self._updateStyles(maxHeight + 10); + }, this.opts.float, this.opts.height); + + if (this.opts.auto) { + var elements = []; + var _this = this; + this.container.children('.' + this.opts.itemClass + ':not(.' + this.opts.placeholderClass + ')') + .each(function(index, el) { + el = $(el); + elements.push({ + el: el, + i: parseInt(el.attr('data-gs-x')) + parseInt(el.attr('data-gs-y')) * _this.opts.width + }); + }); + _.chain(elements).sortBy(function(x) { return x.i; }).each(function(i) { + self._prepareElement(i.el); + }).value(); + } + + this.setAnimation(this.opts.animate); + + this.placeholder = $( + '
' + + '
' + this.opts.placeholderText + '
').hide(); + + this.container.height( + this.grid.getGridHeight() * (this.opts.cellHeight + this.opts.verticalMargin) - + this.opts.verticalMargin); + + this.onResizeHandler = function() { + if (self._isOneColumnMode()) { + if (oneColumnMode) { + return; + } + + oneColumnMode = true; + + self.grid._sortNodes(); + _.each(self.grid.nodes, function(node) { + self.container.append(node.el); + + if (self.opts.staticGrid) { + return; + } + if (!node.noMove) { + node.el.draggable('disable'); + } + if (!node.noResize) { + node.el.resizable('disable'); + } + }); + } else { + if (!oneColumnMode) { + return; + } + + oneColumnMode = false; + + if (self.opts.staticGrid) { + return; + } + + _.each(self.grid.nodes, function(node) { + if (!node.noMove) { + node.el.draggable('enable'); + } + if (!node.noResize) { + node.el.resizable('enable'); + } + }); + } + }; + + $(window).resize(this.onResizeHandler); + this.onResizeHandler(); + }; + + GridStack.prototype._triggerChangeEvent = function(forceTrigger) { + var elements = this.grid.getDirtyNodes(); + var hasChanges = false; + + var eventParams = []; + if (elements && elements.length) { + eventParams.push(elements); + hasChanges = true; + } + + if (hasChanges || forceTrigger === true) { + this.container.trigger('change', eventParams); + } + }; + + GridStack.prototype._initStyles = function() { + if (this._stylesId) { + $('[data-gs-id="' + this._stylesId + '"]').remove(); + } + this._stylesId = 'gridstack-style-' + (Math.random() * 100000).toFixed(); + this._styles = Utils.createStylesheet(this._stylesId); + if (this._styles != null) { + this._styles._max = 0; + } + }; + + GridStack.prototype._updateStyles = function(maxHeight) { + if (this._styles === null) { + return; + } + + var prefix = '.' + this.opts._class + ' .' + this.opts.itemClass; + + if (typeof maxHeight == 'undefined') { + maxHeight = this._styles._max; + this._initStyles(); + this._updateContainerHeight(); + } + + if (this._styles._max === 0) { + Utils.insertCSSRule(this._styles, prefix, 'min-height: ' + (this.opts.cellHeight) + 'px;', 0); + } + + if (maxHeight > this._styles._max) { + for (var i = this._styles._max; i < maxHeight; ++i) { + Utils.insertCSSRule(this._styles, + prefix + '[data-gs-height="' + (i + 1) + '"]', + 'height: ' + (this.opts.cellHeight * (i + 1) + this.opts.verticalMargin * i) + 'px;', + i + ); + Utils.insertCSSRule(this._styles, + prefix + '[data-gs-min-height="' + (i + 1) + '"]', + 'min-height: ' + (this.opts.cellHeight * (i + 1) + this.opts.verticalMargin * i) + 'px;', + i + ); + Utils.insertCSSRule(this._styles, + prefix + '[data-gs-max-height="' + (i + 1) + '"]', + 'max-height: ' + (this.opts.cellHeight * (i + 1) + this.opts.verticalMargin * i) + 'px;', + i + ); + Utils.insertCSSRule(this._styles, + prefix + '[data-gs-y="' + i + '"]', + 'top: ' + (this.opts.cellHeight * i + this.opts.verticalMargin * i) + 'px;', + i + ); + } + this._styles._max = maxHeight; + } + }; + + GridStack.prototype._updateContainerHeight = function() { + if (this.grid._updateCounter) { + return; + } + this.container.height( + this.grid.getGridHeight() * (this.opts.cellHeight + this.opts.verticalMargin) - + this.opts.verticalMargin); + }; + + GridStack.prototype._isOneColumnMode = function() { + return (window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth) <= + this.opts.minWidth; + }; + + GridStack.prototype._prepareElement = function(el) { + var self = this; el = $(el); - el.each(function (index, el) { + + el.addClass(this.opts.itemClass); + var node = self.grid.addNode({ + x: el.attr('data-gs-x'), + y: el.attr('data-gs-y'), + width: el.attr('data-gs-width'), + height: el.attr('data-gs-height'), + maxWidth: el.attr('data-gs-max-width'), + minWidth: el.attr('data-gs-min-width'), + maxHeight: el.attr('data-gs-max-height'), + minHeight: el.attr('data-gs-min-height'), + autoPosition: Utils.toBool(el.attr('data-gs-auto-position')), + noResize: Utils.toBool(el.attr('data-gs-no-resize')), + noMove: Utils.toBool(el.attr('data-gs-no-move')), + locked: Utils.toBool(el.attr('data-gs-locked')), + el: el + }); + el.data('_gridstack_node', node); + + if (self.opts.staticGrid) { + return; + } + + var cellWidth; + var cellHeight; + + var dragOrResize = function(event, ui) { + var x = Math.round(ui.position.left / cellWidth); + var y = Math.floor((ui.position.top + cellHeight / 2) / cellHeight); + var width; + var height; + if (event.type != 'drag') { + width = Math.round(ui.size.width / cellWidth); + height = Math.round(ui.size.height / cellHeight); + } + + if (!self.grid.canMoveNode(node, x, y, width, height)) { + return; + } + self.grid.moveNode(node, x, y, width, height); + self._updateContainerHeight(); + }; + + var onStartMoving = function(event, ui) { + self.container.append(self.placeholder); + var o = $(this); + self.grid.cleanNodes(); + self.grid.beginUpdate(node); + cellWidth = o.outerWidth() / o.attr('data-gs-width'); + cellHeight = self.opts.cellHeight + self.opts.verticalMargin; + self.placeholder + .attr('data-gs-x', o.attr('data-gs-x')) + .attr('data-gs-y', o.attr('data-gs-y')) + .attr('data-gs-width', o.attr('data-gs-width')) + .attr('data-gs-height', o.attr('data-gs-height')) + .show(); + node.el = self.placeholder; + + el.resizable('option', 'minWidth', Math.round(cellWidth * (node.minWidth || 1))); + el.resizable('option', 'minHeight', self.opts.cellHeight * (node.minHeight || 1)); + + if (event.type == 'resizestart') { + o.find('.grid-stack-item').trigger('resizestart'); + } + }; + + var onEndMoving = function(event, ui) { + self.placeholder.detach(); + var o = $(this); + node.el = o; + self.placeholder.hide(); + o + .attr('data-gs-x', node.x) + .attr('data-gs-y', node.y) + .attr('data-gs-width', node.width) + .attr('data-gs-height', node.height) + .removeAttr('style'); + self._updateContainerHeight(); + self._triggerChangeEvent(); + + self.grid.endUpdate(); + + var nestedGrids = o.find('.grid-stack'); + if (nestedGrids.length && event.type == 'resizestop') { + nestedGrids.each(function(index, el) { + $(el).data('gridstack').onResizeHandler(); + }); + o.find('.grid-stack-item').trigger('resizestop'); + } + }; + + el + .draggable(_.extend(this.opts.draggable, { + containment: this.opts.isNested ? this.container.parent() : null, + start: onStartMoving, + stop: onEndMoving, + drag: dragOrResize + })) + .resizable(_.extend(this.opts.resizable, { + start: onStartMoving, + stop: onEndMoving, + resize: dragOrResize + })); + + if (node.noMove || this._isOneColumnMode()) { + el.draggable('disable'); + } + + if (node.noResize || this._isOneColumnMode()) { + el.resizable('disable'); + } + + el.attr('data-gs-locked', node.locked ? 'yes' : null); + }; + + GridStack.prototype.setAnimation = function(enable) { + if (enable) { + this.container.addClass('grid-stack-animate'); + } else { + this.container.removeClass('grid-stack-animate'); + } + }; + + GridStack.prototype.addWidget = function(el, x, y, width, height, autoPosition) { + el = $(el); + if (typeof x != 'undefined') { el.attr('data-gs-x', x); } + if (typeof y != 'undefined') { el.attr('data-gs-y', y); } + if (typeof width != 'undefined') { el.attr('data-gs-width', width); } + if (typeof height != 'undefined') { el.attr('data-gs-height', height); } + if (typeof autoPosition != 'undefined') { el.attr('data-gs-auto-position', autoPosition ? 'yes' : null); } + this.container.append(el); + this._prepareElement(el); + this._updateContainerHeight(); + this._triggerChangeEvent(true); + + return el; + }; + + GridStack.prototype.makeWidget = function(el) { + el = $(el); + this._prepareElement(el); + this._updateContainerHeight(); + this._triggerChangeEvent(true); + + return el; + }; + + GridStack.prototype.willItFit = function(x, y, width, height, autoPosition) { + var node = {x: x, y: y, width: width, height: height, autoPosition: autoPosition}; + return this.grid.canBePlacedWithRespectToHeight(node); + }; + + GridStack.prototype.removeWidget = function(el, detachNode) { + detachNode = typeof detachNode === 'undefined' ? true : detachNode; + el = $(el); + var node = el.data('_gridstack_node'); + this.grid.removeNode(node); + el.removeData('_gridstack_node'); + this._updateContainerHeight(); + if (detachNode) { + el.remove(); + } + this._triggerChangeEvent(true); + }; + + GridStack.prototype.removeAll = function(detachNode) { + _.each(this.grid.nodes, _.bind(function(node) { + this.removeWidget(node.el, detachNode); + }, this)); + this.grid.nodes = []; + this._updateContainerHeight(); + }; + + GridStack.prototype.destroy = function() { + $(window).off('resize', this.onResizeHandler); + this.disable(); + this.container.remove(); + Utils.removeStylesheet(this._stylesId); + if (this.grid) { + this.grid = null; + } + }; + + GridStack.prototype.resizable = function(el, val) { + var self = this; + el = $(el); + el.each(function(index, el) { el = $(el); var node = el.data('_gridstack_node'); - if (typeof node == 'undefined' || node == null) { + if (typeof node == 'undefined' || node === null) { return; } - if(!isNaN(val)){ - node.min_height = (val || false); + node.noResize = !(val || false); + if (node.noResize || self._isOneColumnMode()) { + el.resizable('disable'); + } else { + el.resizable('enable'); + } + }); + return this; + }; + + GridStack.prototype.movable = function(el, val) { + var self = this; + el = $(el); + el.each(function(index, el) { + el = $(el); + var node = el.data('_gridstack_node'); + if (typeof node == 'undefined' || node === null) { + return; + } + + node.noMove = !(val || false); + if (node.noMove || self._isOneColumnMode()) { + el.draggable('disable'); + el.removeClass('ui-draggable-handle'); + } else { + el.draggable('enable'); + el.addClass('ui-draggable-handle'); + } + }); + return this; + }; + + GridStack.prototype.disable = function() { + this.movable(this.container.children('.' + this.opts.itemClass), false); + this.resizable(this.container.children('.' + this.opts.itemClass), false); + this.container.trigger('disable'); + }; + + GridStack.prototype.enable = function() { + this.movable(this.container.children('.' + this.opts.itemClass), true); + this.resizable(this.container.children('.' + this.opts.itemClass), true); + this.container.trigger('enable'); + }; + + GridStack.prototype.locked = function(el, val) { + el = $(el); + el.each(function(index, el) { + el = $(el); + var node = el.data('_gridstack_node'); + if (typeof node == 'undefined' || node === null) { + return; + } + + node.locked = (val || false); + el.attr('data-gs-locked', node.locked ? 'yes' : null); + }); + return this; + }; + + GridStack.prototype.minHeight = function(el, val) { + el = $(el); + el.each(function(index, el) { + el = $(el); + var node = el.data('_gridstack_node'); + if (typeof node == 'undefined' || node === null) { + return; + } + + if (!isNaN(val)) { + node.minHeight = (val || false); el.attr('data-gs-min-height', val); } }); return this; }; - GridStack.prototype.min_width = function (el, val) { + GridStack.prototype.minWidth = function(el, val) { el = $(el); - el.each(function (index, el) { + el.each(function(index, el) { el = $(el); var node = el.data('_gridstack_node'); - if (typeof node == 'undefined' || node == null) { + if (typeof node == 'undefined' || node === null) { return; } - if(!isNaN(val)){ - node.min_width = (val || false); + if (!isNaN(val)) { + node.minWidth = (val || false); el.attr('data-gs-min-width', val); } }); return this; }; - GridStack.prototype._update_element = function(el, callback) { - el = $(el).first(); - var node = el.data('_gridstack_node'); - if (typeof node == 'undefined' || node == null) { - return; - } + GridStack.prototype._updateElement = function(el, callback) { + el = $(el).first(); + var node = el.data('_gridstack_node'); + if (typeof node == 'undefined' || node === null) { + return; + } - var self = this; + var self = this; - self.grid.clean_nodes(); - self.grid.begin_update(node); + self.grid.cleanNodes(); + self.grid.beginUpdate(node); - callback.call(this, el, node); + callback.call(this, el, node); - self._update_container_height(); - self._trigger_change_event(); + self._updateContainerHeight(); + self._triggerChangeEvent(); - self.grid.end_update(); - }; + self.grid.endUpdate(); + }; - GridStack.prototype.resize = function(el, width, height) { - this._update_element(el, function(el, node) { - width = (width != null && typeof width != 'undefined') ? width : node.width; - height = (height != null && typeof height != 'undefined') ? height : node.height; + GridStack.prototype.resize = function(el, width, height) { + this._updateElement(el, function(el, node) { + width = (width !== null && typeof width != 'undefined') ? width : node.width; + height = (height !== null && typeof height != 'undefined') ? height : node.height; - this.grid.move_node(node, node.x, node.y, width, height); - }); - }; + this.grid.moveNode(node, node.x, node.y, width, height); + }); + }; - GridStack.prototype.move = function(el, x, y) { - this._update_element(el, function(el, node) { - x = (x != null && typeof x != 'undefined') ? x : node.x; - y = (y != null && typeof y != 'undefined') ? y : node.y; + GridStack.prototype.move = function(el, x, y) { + this._updateElement(el, function(el, node) { + x = (x !== null && typeof x != 'undefined') ? x : node.x; + y = (y !== null && typeof y != 'undefined') ? y : node.y; - this.grid.move_node(node, x, y, node.width, node.height); - }); - }; + this.grid.moveNode(node, x, y, node.width, node.height); + }); + }; - GridStack.prototype.update = function(el, x, y, width, height) { - this._update_element(el, function(el, node) { - x = (x != null && typeof x != 'undefined') ? x : node.x; - y = (y != null && typeof y != 'undefined') ? y : node.y; - width = (width != null && typeof width != 'undefined') ? width : node.width; - height = (height != null && typeof height != 'undefined') ? height : node.height; + GridStack.prototype.update = function(el, x, y, width, height) { + this._updateElement(el, function(el, node) { + x = (x !== null && typeof x != 'undefined') ? x : node.x; + y = (y !== null && typeof y != 'undefined') ? y : node.y; + width = (width !== null && typeof width != 'undefined') ? width : node.width; + height = (height !== null && typeof height != 'undefined') ? height : node.height; - this.grid.move_node(node, x, y, width, height); - }); - }; + this.grid.moveNode(node, x, y, width, height); + }); + }; - GridStack.prototype.cell_height = function(val) { - if (typeof val == 'undefined') { - return this.opts.cell_height; - } - val = parseInt(val); - if (val == this.opts.cell_height) - return; - this.opts.cell_height = val || this.opts.cell_height; - this._update_styles(); - }; + GridStack.prototype.cellHeight = function(val) { + if (typeof val == 'undefined') { + return this.opts.cellHeight; + } + val = parseInt(val); + if (val == this.opts.cellHeight) { + return; + } + this.opts.cellHeight = val || this.opts.cellHeight; + this._updateStyles(); + }; - GridStack.prototype.cell_width = function() { - var o = this.container.children('.' + this.opts.item_class).first(); - return Math.ceil(o.outerWidth() / o.attr('data-gs-width')); - }; + GridStack.prototype.cellWidth = function() { + var o = this.container.children('.' + this.opts.itemClass).first(); + return Math.ceil(o.outerWidth() / o.attr('data-gs-width')); + }; - GridStack.prototype.get_cell_from_pixel = function(position) { - var containerPos = this.container.position(); - var relativeLeft = position.left - containerPos.left; - var relativeTop = position.top - containerPos.top; + GridStack.prototype.getCellFromPixel = function(position) { + var containerPos = this.container.position(); + var relativeLeft = position.left - containerPos.left; + var relativeTop = position.top - containerPos.top; - var column_width = Math.floor(this.container.width() / this.opts.width); - var row_height = this.opts.cell_height + this.opts.vertical_margin; + var columnWidth = Math.floor(this.container.width() / this.opts.width); + var rowHeight = this.opts.cellHeight + this.opts.verticalMargin; - return {x: Math.floor(relativeLeft / column_width), y: Math.floor(relativeTop / row_height)}; - }; + return {x: Math.floor(relativeLeft / columnWidth), y: Math.floor(relativeTop / rowHeight)}; + }; - GridStack.prototype.batch_update = function() { - this.grid.batch_update(); - }; + GridStack.prototype.batchUpdate = function() { + this.grid.batchUpdate(); + }; - GridStack.prototype.commit = function() { - this.grid.commit(); - this._update_container_height(); - }; + GridStack.prototype.commit = function() { + this.grid.commit(); + this._updateContainerHeight(); + }; - GridStack.prototype.is_area_empty = function(x, y, width, height) { - return this.grid.is_area_empty(x, y, width, height); - }; + GridStack.prototype.isAreaEmpty = function(x, y, width, height) { + return this.grid.isAreaEmpty(x, y, width, height); + }; - GridStack.prototype.set_static = function(static_value) { - this.opts.static_grid = (static_value === true); - this._set_static_class(); - }; + GridStack.prototype.setStatic = function(staticValue) { + this.opts.staticGrid = (staticValue === true); + this._setStaticClass(); + }; - GridStack.prototype._set_static_class = function() { - var static_class_name = 'grid-stack-static'; + GridStack.prototype._setStaticClass = function() { + var staticClassName = 'grid-stack-static'; - if (this.opts.static_grid === true) { - this.container.addClass(static_class_name); - } else { - this.container.removeClass(static_class_name); - } - }; + if (this.opts.staticGrid === true) { + this.container.addClass(staticClassName); + } else { + this.container.removeClass(staticClassName); + } + }; - scope.GridStackUI = GridStack; + // jscs:disable requireCamelCaseOrUpperCaseIdentifiers + GridStackEngine.prototype.batch_update = obsolete(GridStackEngine.prototype.batchUpdate); + GridStackEngine.prototype._fix_collisions = obsolete(GridStackEngine.prototype._fixCollisions, + '_fix_collisions', '_fixCollisions'); + GridStackEngine.prototype.is_area_empty = obsolete(GridStackEngine.prototype.isAreaEmpty, + 'is_area_empty', 'isAreaEmpty'); + GridStackEngine.prototype._sort_nodes = obsolete(GridStackEngine.prototype._sortNodes, + '_sort_nodes', '_sortNodes'); + GridStackEngine.prototype._pack_nodes = obsolete(GridStackEngine.prototype._packNodes, + '_pack_nodes', '_packNodes'); + GridStackEngine.prototype._prepare_node = obsolete(GridStackEngine.prototype._prepareNode, + '_prepare_node', '_prepareNode'); + GridStackEngine.prototype.clean_nodes = obsolete(GridStackEngine.prototype.cleanNodes, + 'clean_nodes', 'cleanNodes'); + GridStackEngine.prototype.get_dirty_nodes = obsolete(GridStackEngine.prototype.getDirtyNodes, + 'get_dirty_nodes', 'getDirtyNodes'); + GridStackEngine.prototype.add_node = obsolete(GridStackEngine.prototype.addNode, + 'add_node', 'addNode, '); + GridStackEngine.prototype.remove_node = obsolete(GridStackEngine.prototype.removeNode, + 'remove_node', 'removeNode'); + GridStackEngine.prototype.can_move_node = obsolete(GridStackEngine.prototype.canMoveNode, + 'can_move_node', 'canMoveNode'); + GridStackEngine.prototype.move_node = obsolete(GridStackEngine.prototype.moveNode, + 'move_node', 'moveNode'); + GridStackEngine.prototype.get_grid_height = obsolete(GridStackEngine.prototype.getGridHeight, + 'get_grid_height', 'getGridHeight'); + GridStackEngine.prototype.begin_update = obsolete(GridStackEngine.prototype.beginUpdate, + 'begin_update', 'beginUpdate'); + GridStackEngine.prototype.end_update = obsolete(GridStackEngine.prototype.endUpdate, + 'end_update', 'endUpdate'); + GridStackEngine.prototype.can_be_placed_with_respect_to_height = + obsolete(GridStackEngine.prototype.canBePlacedWithRespectToHeight, + 'can_be_placed_with_respect_to_height', 'canBePlacedWithRespectToHeight'); + GridStack.prototype._trigger_change_event = obsolete(GridStack.prototype._triggerChangeEvent, + '_trigger_change_event', '_triggerChangeEvent'); + GridStack.prototype._init_styles = obsolete(GridStack.prototype._initStyles, + '_init_styles', '_initStyles'); + GridStack.prototype._update_styles = obsolete(GridStack.prototype._updateStyles, + '_update_styles', '_updateStyles'); + GridStack.prototype._update_container_height = obsolete(GridStack.prototype._updateContainerHeight, + '_update_container_height', '_updateContainerHeight'); + GridStack.prototype._is_one_column_mode = obsolete(GridStack.prototype._isOneColumnMode, + '_is_one_column_mode',' _isOneColumnMode'); + GridStack.prototype._prepare_element = obsolete(GridStack.prototype._prepareElement, + '_prepare_element', '_prepareElement'); + GridStack.prototype.set_animation = obsolete(GridStack.prototype.setAnimation, + 'set_animation', 'setAnimation'); + GridStack.prototype.add_widget = obsolete(GridStack.prototype.addWidget, + 'add_widget', 'addWidget'); + GridStack.prototype.make_widget = obsolete(GridStack.prototype.makeWidget, + 'make_widget', 'makeWidget'); + GridStack.prototype.will_it_fit = obsolete(GridStack.prototype.willItFit, + 'will_it_fit', 'willItFit'); + GridStack.prototype.remove_widget = obsolete(GridStack.prototype.removeWidget, + 'remove_widget', 'removeWidget'); + GridStack.prototype.remove_all = obsolete(GridStack.prototype.removeAll, + 'remove_all', 'removeAll'); + GridStack.prototype.min_height = obsolete(GridStack.prototype.minHeight, + 'min_height', 'minHeight'); + GridStack.prototype.min_width = obsolete(GridStack.prototype.minWidth, + 'min_width', 'minWidth'); + GridStack.prototype._update_element = obsolete(GridStack.prototype._updateElement, + '_update_element', '_updateElement'); + GridStack.prototype.cell_height = obsolete(GridStack.prototype.cellHeight, + 'cell_height', 'cellHeight'); + GridStack.prototype.cell_width = obsolete(GridStack.prototype.cellWidth, + 'cell_width', 'cellWidth'); + GridStack.prototype.get_cell_from_pixel = obsolete(GridStack.prototype.getCellFromPixel, + 'get_cell_from_pixel', 'getCellFromPixel'); + GridStack.prototype.batch_update = obsolete(GridStack.prototype.batchUpdate, + 'batch_update', 'batchUpdate'); + GridStack.prototype.is_area_empty = obsolete(GridStack.prototype.isAreaEmpty, + 'is_area_empty', 'isAreaEmpty'); + GridStack.prototype.set_static = obsolete(GridStack.prototype.setStatic, + 'set_static', 'setStatic'); + GridStack.prototype._set_static_class = obsolete(GridStack.prototype._setStaticClass, + '_set_static_class', '_setStaticClass'); + // jscs:enable requireCamelCaseOrUpperCaseIdentifiers - scope.GridStackUI.Utils = Utils; + scope.GridStackUI = GridStack; - $.fn.gridstack = function(opts) { - return this.each(function() { - var o = $(this); - if (!o.data('gridstack')) { - o - .data('gridstack', new GridStack(this, opts)); - } - }); - }; + scope.GridStackUI.Utils = Utils; - return scope.GridStackUI; + $.fn.gridstack = function(opts) { + return this.each(function() { + var o = $(this); + if (!o.data('gridstack')) { + o + .data('gridstack', new GridStack(this, opts)); + } + }); + }; + + return scope.GridStackUI; });