gridstack-js-rails 0.2.3 → 0.2.5

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: c5110fe2da295f1267cf2d9b861ccdf6c8ad9e9e
4
+ data.tar.gz: 6aa95c14dabfe90b660ca1706cd74ed4db2ba610
5
+ SHA512:
6
+ metadata.gz: bbbbb1960a014b6d535a1edb4eafa37de1b73e6a2851dd57894a758e05bfed2a169a7ca30a52dddc8b0089dcb829627e94b121372164caadf2b06e051b245e7e
7
+ data.tar.gz: 6e6edf99392d024f95f6d7063132e258ea01f9d2037f5e74d808415e9f509927f56e3cf4ea49c77e3264ba39e7407105201b24b5b21aa64623f4a96e9d0f775e
data/.gitignore CHANGED
@@ -17,5 +17,4 @@ spec/reports
17
17
  test/tmp
18
18
  test/version_tmp
19
19
  tmp
20
- .idea
21
20
  .ruby-version
@@ -1,5 +1,5 @@
1
1
  module GridstackJs
2
2
  module Rails
3
- VERSION = '0.2.3'
3
+ VERSION = '0.2.5'
4
4
  end
5
5
  end
@@ -1,191 +1,255 @@
1
- // gridstack.js 0.2.3-dev
2
- // http://troolee.github.io/gridstack.js/
3
- // (c) 2014-2015 Pavel Reznikov
4
- // gridstack.js may be freely distributed under the MIT license.
5
-
6
- (function (factory) {
1
+ /**
2
+ * gridstack.js 0.2.5
3
+ * http://troolee.github.io/gridstack.js/
4
+ * (c) 2014-2016 Pavel Reznikov
5
+ * gridstack.js may be freely distributed under the MIT license.
6
+ * @preserve
7
+ */
8
+ (function(factory) {
7
9
  if (typeof define === 'function' && define.amd) {
8
- define(['jquery', 'lodash', 'jquery-ui/core', 'jquery-ui/widget', 'jquery-ui/mouse', 'jquery-ui/draggable', 'jquery-ui/resizable'], factory);
9
- }
10
- else {
10
+ define(['jquery', 'lodash', 'jquery-ui/core', 'jquery-ui/widget', 'jquery-ui/mouse', 'jquery-ui/draggable',
11
+ 'jquery-ui/resizable'], factory);
12
+ } else if (typeof exports !== 'undefined') {
13
+ try { jQuery = require('jquery'); } catch (e) {}
14
+ try { _ = require('lodash'); } catch (e) {}
15
+ factory(jQuery, _);
16
+ } else {
11
17
  factory(jQuery, _);
12
18
  }
13
- })(function ($, _) {
19
+ })(function($, _) {
14
20
 
15
21
  var scope = window;
16
22
 
23
+ var obsolete = function(f, oldName, newName) {
24
+ var wrapper = function() {
25
+ console.warn('gridstack.js: Function `' + oldName + '` is deprecated as of v0.2.5 and has been replaced ' +
26
+ 'with `' + newName + '`. It will be **completely** removed in v1.0.');
27
+ return f.apply(this, arguments);
28
+ };
29
+ wrapper.prototype = f.prototype;
30
+
31
+ return wrapper;
32
+ };
33
+
34
+ var obsoleteOpts = function(oldName, newName) {
35
+ console.warn('gridstack.js: Option `' + oldName + '` is deprecated as of v0.2.5 and has been replaced with `' +
36
+ newName + '`. It will be **completely** removed in v1.0.');
37
+ };
38
+
17
39
  var Utils = {
18
- is_intercepted: function (a, b) {
40
+ isIntercepted: function(a, b) {
19
41
  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);
20
42
  },
21
43
 
22
- sort: function (nodes, dir, width) {
23
- width = width || _.chain(nodes).map(function (node) { return node.x + node.width; }).max().value();
44
+ sort: function(nodes, dir, width) {
45
+ width = width || _.chain(nodes).map(function(node) { return node.x + node.width; }).max().value();
24
46
  dir = dir != -1 ? 1 : -1;
25
- return _.sortBy(nodes, function (n) { return dir * (n.x + n.y * width); });
47
+ return _.sortBy(nodes, function(n) { return dir * (n.x + n.y * width); });
26
48
  },
27
49
 
28
- create_stylesheet: function (id) {
29
- var style = document.createElement("style");
30
- style.setAttribute("type", "text/css");
31
- style.setAttribute("data-gs-id", id);
50
+ createStylesheet: function(id) {
51
+ var style = document.createElement('style');
52
+ style.setAttribute('type', 'text/css');
53
+ style.setAttribute('data-gs-style-id', id);
32
54
  if (style.styleSheet) {
33
- style.styleSheet.cssText = "";
34
- }
35
- else {
36
- style.appendChild(document.createTextNode(""));
55
+ style.styleSheet.cssText = '';
56
+ } else {
57
+ style.appendChild(document.createTextNode(''));
37
58
  }
38
59
  document.getElementsByTagName('head')[0].appendChild(style);
39
60
  return style.sheet;
40
61
  },
41
62
 
42
- insert_css_rule: function (sheet, selector, rules, index) {
43
- if(typeof sheet.insertRule === 'function') {
44
- sheet.insertRule(selector + "{" + rules + "}", index);
45
- }
46
- else if(typeof sheet.addRule === 'function') {
63
+ removeStylesheet: function(id) {
64
+ $('STYLE[data-gs-style-id=' + id + ']').remove();
65
+ },
66
+
67
+ insertCSSRule: function(sheet, selector, rules, index) {
68
+ if (typeof sheet.insertRule === 'function') {
69
+ sheet.insertRule(selector + '{' + rules + '}', index);
70
+ } else if (typeof sheet.addRule === 'function') {
47
71
  sheet.addRule(selector, rules, index);
48
72
  }
49
73
  },
50
74
 
51
- toBool: function (v) {
52
- if (typeof v == 'boolean')
75
+ toBool: function(v) {
76
+ if (typeof v == 'boolean') {
53
77
  return v;
78
+ }
54
79
  if (typeof v == 'string') {
55
80
  v = v.toLowerCase();
56
- return !(v == '' || v == 'no' || v == 'false' || v == '0');
81
+ return !(v === '' || v == 'no' || v == 'false' || v == '0');
57
82
  }
58
83
  return Boolean(v);
84
+ },
85
+
86
+ _collisionNodeCheck: function(n) {
87
+ return n != this.node && Utils.isIntercepted(n, this.nn);
88
+ },
89
+
90
+ _didCollide: function(bn) {
91
+ return Utils.isIntercepted({x: this.n.x, y: this.newY, width: this.n.width, height: this.n.height}, bn);
92
+ },
93
+
94
+ _isAddNodeIntercepted: function(n) {
95
+ return Utils.isIntercepted({x: this.x, y: this.y, width: this.node.width, height: this.node.height}, n);
96
+ },
97
+
98
+ parseHeight: function(val) {
99
+ var height = val;
100
+ var heightUnit = 'px';
101
+ if (height && _.isString(height)) {
102
+ var match = height.match(/^(-[0-9]+\.[0-9]+|[0-9]*\.[0-9]+|-[0-9]+|[0-9]+)(px|em|rem|vh|vw)?$/);
103
+ if (!match) {
104
+ throw new Error('Invalid height');
105
+ }
106
+ heightUnit = match[2] || 'px';
107
+ height = parseFloat(match[1]);
108
+ }
109
+ return {height: height, unit: heightUnit};
59
110
  }
60
111
  };
61
112
 
62
- var id_seq = 0;
113
+ // jscs:disable requireCamelCaseOrUpperCaseIdentifiers
114
+ Utils.is_intercepted = obsolete(Utils.isIntercepted, 'is_intercepted', 'isIntercepted');
115
+
116
+ Utils.create_stylesheet = obsolete(Utils.createStylesheet, 'create_stylesheet', 'createStylesheet');
117
+
118
+ Utils.remove_stylesheet = obsolete(Utils.removeStylesheet, 'remove_stylesheet', 'removeStylesheet');
119
+
120
+ Utils.insert_css_rule = obsolete(Utils.insertCSSRule, 'insert_css_rule', 'insertCSSRule');
121
+ // jscs:enable requireCamelCaseOrUpperCaseIdentifiers
63
122
 
64
- var GridStackEngine = function (width, onchange, float, height, items) {
123
+ var idSeq = 0;
124
+
125
+ var GridStackEngine = function(width, onchange, floatMode, height, items) {
65
126
  this.width = width;
66
- this.float = float || false;
127
+ this.float = floatMode || false;
67
128
  this.height = height || 0;
68
129
 
69
130
  this.nodes = items || [];
70
- this.onchange = onchange || function () {};
131
+ this.onchange = onchange || function() {};
71
132
 
72
- this._update_counter = 0;
133
+ this._updateCounter = 0;
73
134
  this._float = this.float;
135
+
136
+ this._addedNodes = [];
137
+ this._removedNodes = [];
74
138
  };
75
139
 
76
- GridStackEngine.prototype.batch_update = function () {
77
- this._update_counter = 1;
140
+ GridStackEngine.prototype.batchUpdate = function() {
141
+ this._updateCounter = 1;
78
142
  this.float = true;
79
143
  };
80
144
 
81
- GridStackEngine.prototype.commit = function () {
82
- this._update_counter = 0;
83
- if (this._update_counter == 0) {
145
+ GridStackEngine.prototype.commit = function() {
146
+ if (this._updateCounter !== 0) {
147
+ this._updateCounter = 0;
84
148
  this.float = this._float;
85
- this._pack_nodes();
149
+ this._packNodes();
86
150
  this._notify();
87
151
  }
88
152
  };
89
153
 
90
- GridStackEngine.prototype._fix_collisions = function (node) {
91
- this._sort_nodes(-1);
154
+ // For Meteor support: https://github.com/troolee/gridstack.js/pull/272
155
+ GridStackEngine.prototype.getNodeDataByDOMEl = function(el) {
156
+ return _.find(this.nodes, function(n) { return el.get(0) === n.el.get(0); });
157
+ };
158
+
159
+ GridStackEngine.prototype._fixCollisions = function(node) {
160
+ var self = this;
161
+ this._sortNodes(-1);
92
162
 
93
- var nn = node, has_locked = Boolean(_.find(this.nodes, function (n) { return n.locked }));
94
- if (!this.float && !has_locked) {
163
+ var nn = node;
164
+ var hasLocked = Boolean(_.find(this.nodes, function(n) { return n.locked; }));
165
+ if (!this.float && !hasLocked) {
95
166
  nn = {x: 0, y: node.y, width: this.width, height: node.height};
96
167
  }
97
-
98
168
  while (true) {
99
- var collision_node = _.find(this.nodes, function (n) {
100
- return n != node && Utils.is_intercepted(n, nn);
101
- }, this);
102
- if (typeof collision_node == 'undefined') {
169
+ var collisionNode = _.find(this.nodes, _.bind(Utils._collisionNodeCheck, {node: node, nn: nn}));
170
+ if (typeof collisionNode == 'undefined') {
103
171
  return;
104
172
  }
105
- this.move_node(collision_node, collision_node.x, node.y + node.height,
106
- collision_node.width, collision_node.height, true);
173
+ this.moveNode(collisionNode, collisionNode.x, node.y + node.height,
174
+ collisionNode.width, collisionNode.height, true);
107
175
  }
108
176
  };
109
177
 
110
- GridStackEngine.prototype.is_area_empty = function (x, y, width, height) {
178
+ GridStackEngine.prototype.isAreaEmpty = function(x, y, width, height) {
111
179
  var nn = {x: x || 0, y: y || 0, width: width || 1, height: height || 1};
112
- var collision_node = _.find(this.nodes, function (n) {
113
- return Utils.is_intercepted(n, nn);
114
- }, this);
115
- return collision_node == null;
180
+ var collisionNode = _.find(this.nodes, _.bind(function(n) {
181
+ return Utils.isIntercepted(n, nn);
182
+ }, this));
183
+ return collisionNode === null || typeof collisionNode === 'undefined';
116
184
  };
117
185
 
118
- GridStackEngine.prototype._sort_nodes = function (dir) {
186
+ GridStackEngine.prototype._sortNodes = function(dir) {
119
187
  this.nodes = Utils.sort(this.nodes, dir, this.width);
120
188
  };
121
189
 
122
- GridStackEngine.prototype._pack_nodes = function () {
123
- this._sort_nodes();
190
+ GridStackEngine.prototype._packNodes = function() {
191
+ this._sortNodes();
124
192
 
125
193
  if (this.float) {
126
- _.each(this.nodes, function (n, i) {
127
- if (n._updating || typeof n._orig_y == 'undefined' || n.y == n._orig_y)
194
+ _.each(this.nodes, _.bind(function(n, i) {
195
+ if (n._updating || typeof n._origY == 'undefined' || n.y == n._origY) {
128
196
  return;
197
+ }
129
198
 
130
- var new_y = n.y;
131
- while (new_y >= n._orig_y) {
132
- var collision_node = _.chain(this.nodes)
133
- .find(function (bn) {
134
- return n != bn && Utils.is_intercepted({x: n.x, y: new_y, width: n.width, height: n.height}, bn);
135
- })
199
+ var newY = n.y;
200
+ while (newY >= n._origY) {
201
+ var collisionNode = _.chain(this.nodes)
202
+ .find(_.bind(Utils._didCollide, {n: n, newY: newY}))
136
203
  .value();
137
204
 
138
- if (!collision_node) {
205
+ if (!collisionNode) {
139
206
  n._dirty = true;
140
- n.y = new_y;
207
+ n.y = newY;
141
208
  }
142
- --new_y;
209
+ --newY;
143
210
  }
144
- }, this);
145
- }
146
- else {
147
- _.each(this.nodes, function (n, i) {
148
- if (n.locked)
211
+ }, this));
212
+ } else {
213
+ _.each(this.nodes, _.bind(function(n, i) {
214
+ if (n.locked) {
149
215
  return;
216
+ }
150
217
  while (n.y > 0) {
151
- var new_y = n.y - 1;
152
- var can_be_moved = i == 0;
218
+ var newY = n.y - 1;
219
+ var canBeMoved = i === 0;
153
220
 
154
221
  if (i > 0) {
155
- var collision_node = _.chain(this.nodes)
222
+ var collisionNode = _.chain(this.nodes)
156
223
  .take(i)
157
- .find(function (bn) {
158
- return Utils.is_intercepted({x: n.x, y: new_y, width: n.width, height: n.height}, bn);
159
- })
224
+ .find(_.bind(Utils._didCollide, {n: n, newY: newY}))
160
225
  .value();
161
- can_be_moved = typeof collision_node == 'undefined';
226
+ canBeMoved = typeof collisionNode == 'undefined';
162
227
  }
163
228
 
164
- if (!can_be_moved) {
229
+ if (!canBeMoved) {
165
230
  break;
166
231
  }
167
- n._dirty = n.y != new_y;
168
- n.y = new_y;
232
+ n._dirty = n.y != newY;
233
+ n.y = newY;
169
234
  }
170
- }, this);
235
+ }, this));
171
236
  }
172
237
  };
173
238
 
174
- GridStackEngine.prototype._prepare_node = function (node, resizing) {
175
- node = _.defaults(node || {}, {width: 1, height: 1, x: 0, y: 0 });
239
+ GridStackEngine.prototype._prepareNode = function(node, resizing) {
240
+ node = _.defaults(node || {}, {width: 1, height: 1, x: 0, y: 0});
176
241
 
177
242
  node.x = parseInt('' + node.x);
178
243
  node.y = parseInt('' + node.y);
179
244
  node.width = parseInt('' + node.width);
180
245
  node.height = parseInt('' + node.height);
181
- node.auto_position = node.auto_position || false;
182
- node.no_resize = node.no_resize || false;
183
- node.no_move = node.no_move || false;
246
+ node.autoPosition = node.autoPosition || false;
247
+ node.noResize = node.noResize || false;
248
+ node.noMove = node.noMove || false;
184
249
 
185
250
  if (node.width > this.width) {
186
251
  node.width = this.width;
187
- }
188
- else if (node.width < 1) {
252
+ } else if (node.width < 1) {
189
253
  node.width = 1;
190
254
  }
191
255
 
@@ -200,8 +264,7 @@
200
264
  if (node.x + node.width > this.width) {
201
265
  if (resizing) {
202
266
  node.width = this.width - node.x;
203
- }
204
- else {
267
+ } else {
205
268
  node.x = this.width - node.width;
206
269
  }
207
270
  }
@@ -213,45 +276,47 @@
213
276
  return node;
214
277
  };
215
278
 
216
- GridStackEngine.prototype._notify = function () {
217
- if (this._update_counter) {
279
+ GridStackEngine.prototype._notify = function() {
280
+ if (this._updateCounter) {
218
281
  return;
219
282
  }
220
- var deleted_nodes = Array.prototype.slice.call(arguments, 1).concat(this.get_dirty_nodes());
221
- deleted_nodes = deleted_nodes.concat(this.get_dirty_nodes());
222
- this.onchange(deleted_nodes);
283
+ var deletedNodes = Array.prototype.slice.call(arguments, 0);
284
+ deletedNodes = deletedNodes.concat(this.getDirtyNodes());
285
+ this.onchange(deletedNodes);
223
286
  };
224
287
 
225
- GridStackEngine.prototype.clean_nodes = function () {
226
- _.each(this.nodes, function (n) {n._dirty = false });
288
+ GridStackEngine.prototype.cleanNodes = function() {
289
+ if (this._updateCounter) {
290
+ return;
291
+ }
292
+ _.each(this.nodes, function(n) {n._dirty = false; });
227
293
  };
228
294
 
229
- GridStackEngine.prototype.get_dirty_nodes = function () {
230
- return _.filter(this.nodes, function (n) { return n._dirty; });
295
+ GridStackEngine.prototype.getDirtyNodes = function() {
296
+ return _.filter(this.nodes, function(n) { return n._dirty; });
231
297
  };
232
298
 
233
- GridStackEngine.prototype.add_node = function(node) {
234
- node = this._prepare_node(node);
299
+ GridStackEngine.prototype.addNode = function(node, triggerAddEvent) {
300
+ node = this._prepareNode(node);
235
301
 
236
- if (typeof node.max_width != 'undefined') node.width = Math.min(node.width, node.max_width);
237
- if (typeof node.max_height != 'undefined') node.height = Math.min(node.height, node.max_height);
238
- if (typeof node.min_width != 'undefined') node.width = Math.max(node.width, node.min_width);
239
- if (typeof node.min_height != 'undefined') node.height = Math.max(node.height, node.min_height);
302
+ if (typeof node.maxWidth != 'undefined') { node.width = Math.min(node.width, node.maxWidth); }
303
+ if (typeof node.maxHeight != 'undefined') { node.height = Math.min(node.height, node.maxHeight); }
304
+ if (typeof node.minWidth != 'undefined') { node.width = Math.max(node.width, node.minWidth); }
305
+ if (typeof node.minHeight != 'undefined') { node.height = Math.max(node.height, node.minHeight); }
240
306
 
241
- node._id = ++id_seq;
307
+ node._id = ++idSeq;
242
308
  node._dirty = true;
243
309
 
244
- if (node.auto_position) {
245
- this._sort_nodes();
310
+ if (node.autoPosition) {
311
+ this._sortNodes();
246
312
 
247
- for (var i = 0; ; ++i) {
248
- var x = i % this.width, y = Math.floor(i / this.width);
313
+ for (var i = 0;; ++i) {
314
+ var x = i % this.width;
315
+ var y = Math.floor(i / this.width);
249
316
  if (x + node.width > this.width) {
250
317
  continue;
251
318
  }
252
- if (!_.find(this.nodes, function (n) {
253
- return Utils.is_intercepted({x: x, y: y, width: node.width, height: node.height}, n);
254
- })) {
319
+ if (!_.find(this.nodes, _.bind(Utils._isAddNodeIntercepted, {x: x, y: y, node: node}))) {
255
320
  node.x = x;
256
321
  node.y = y;
257
322
  break;
@@ -260,70 +325,93 @@
260
325
  }
261
326
 
262
327
  this.nodes.push(node);
328
+ if (typeof triggerAddEvent != 'undefined' && triggerAddEvent) {
329
+ this._addedNodes.push(_.clone(node));
330
+ }
263
331
 
264
- this._fix_collisions(node);
265
- this._pack_nodes();
332
+ this._fixCollisions(node);
333
+ this._packNodes();
266
334
  this._notify();
267
335
  return node;
268
336
  };
269
337
 
270
- GridStackEngine.prototype.remove_node = function (node) {
338
+ GridStackEngine.prototype.removeNode = function(node, detachNode) {
339
+ detachNode = typeof detachNode === 'undefined' ? true : detachNode;
340
+ this._removedNodes.push(_.clone(node));
271
341
  node._id = null;
272
342
  this.nodes = _.without(this.nodes, node);
273
- this._pack_nodes();
274
- this._notify(node);
343
+ this._packNodes();
344
+ if (detachNode) {
345
+ this._notify(node);
346
+ }
275
347
  };
276
348
 
277
- GridStackEngine.prototype.can_move_node = function (node, x, y, width, height) {
278
- var has_locked = Boolean(_.find(this.nodes, function (n) { return n.locked }));
349
+ GridStackEngine.prototype.canMoveNode = function(node, x, y, width, height) {
350
+ var hasLocked = Boolean(_.find(this.nodes, function(n) { return n.locked; }));
279
351
 
280
- if (!this.height && !has_locked)
352
+ if (!this.height && !hasLocked) {
281
353
  return true;
354
+ }
282
355
 
283
- var cloned_node;
356
+ var clonedNode;
284
357
  var clone = new GridStackEngine(
285
358
  this.width,
286
359
  null,
287
360
  this.float,
288
361
  0,
289
- _.map(this.nodes, function (n) { if (n == node) { cloned_node = $.extend({}, n); return cloned_node; } return $.extend({}, n) }));
362
+ _.map(this.nodes, function(n) {
363
+ if (n == node) {
364
+ clonedNode = $.extend({}, n);
365
+ return clonedNode;
366
+ }
367
+ return $.extend({}, n);
368
+ }));
369
+
370
+ if (typeof clonedNode === 'undefined') {
371
+ return true;
372
+ }
290
373
 
291
- clone.move_node(cloned_node, x, y, width, height);
374
+ clone.moveNode(clonedNode, x, y, width, height);
292
375
 
293
376
  var res = true;
294
377
 
295
- if (has_locked)
296
- res &= !Boolean(_.find(clone.nodes, function (n) { return n != cloned_node && Boolean(n.locked) && Boolean(n._dirty); }));
297
- if (this.height)
298
- res &= clone.get_grid_height() <= this.height;
378
+ if (hasLocked) {
379
+ res &= !Boolean(_.find(clone.nodes, function(n) {
380
+ return n != clonedNode && Boolean(n.locked) && Boolean(n._dirty);
381
+ }));
382
+ }
383
+ if (this.height) {
384
+ res &= clone.getGridHeight() <= this.height;
385
+ }
299
386
 
300
387
  return res;
301
388
  };
302
389
 
303
- GridStackEngine.prototype.can_be_placed_with_respect_to_height = function (node) {
304
- if (!this.height)
390
+ GridStackEngine.prototype.canBePlacedWithRespectToHeight = function(node) {
391
+ if (!this.height) {
305
392
  return true;
393
+ }
306
394
 
307
395
  var clone = new GridStackEngine(
308
396
  this.width,
309
397
  null,
310
398
  this.float,
311
399
  0,
312
- _.map(this.nodes, function (n) { return $.extend({}, n) }));
313
- clone.add_node(node);
314
- return clone.get_grid_height() <= this.height;
400
+ _.map(this.nodes, function(n) { return $.extend({}, n); }));
401
+ clone.addNode(node);
402
+ return clone.getGridHeight() <= this.height;
315
403
  };
316
404
 
317
- GridStackEngine.prototype.move_node = function (node, x, y, width, height, no_pack) {
318
- if (typeof x != 'number') x = node.x;
319
- if (typeof y != 'number') y = node.y;
320
- if (typeof width != 'number') width = node.width;
321
- if (typeof height != 'number') height = node.height;
405
+ GridStackEngine.prototype.moveNode = function(node, x, y, width, height, noPack) {
406
+ if (typeof x != 'number') { x = node.x; }
407
+ if (typeof y != 'number') { y = node.y; }
408
+ if (typeof width != 'number') { width = node.width; }
409
+ if (typeof height != 'number') { height = node.height; }
322
410
 
323
- if (typeof node.max_width != 'undefined') width = Math.min(width, node.max_width);
324
- if (typeof node.max_height != 'undefined') height = Math.min(height, node.max_height);
325
- if (typeof node.min_width != 'undefined') width = Math.max(width, node.min_width);
326
- if (typeof node.min_height != 'undefined') height = Math.max(height, node.min_height);
411
+ if (typeof node.maxWidth != 'undefined') { width = Math.min(width, node.maxWidth); }
412
+ if (typeof node.maxHeight != 'undefined') { height = Math.min(height, node.maxHeight); }
413
+ if (typeof node.minWidth != 'undefined') { width = Math.max(width, node.minWidth); }
414
+ if (typeof node.minHeight != 'undefined') { height = Math.max(height, node.minHeight); }
327
415
 
328
416
  if (node.x == x && node.y == y && node.width == width && node.height == height) {
329
417
  return node;
@@ -337,253 +425,615 @@
337
425
  node.width = width;
338
426
  node.height = height;
339
427
 
340
- node = this._prepare_node(node, resizing);
428
+ node = this._prepareNode(node, resizing);
341
429
 
342
- this._fix_collisions(node);
343
- if (!no_pack) {
344
- this._pack_nodes();
430
+ this._fixCollisions(node);
431
+ if (!noPack) {
432
+ this._packNodes();
345
433
  this._notify();
346
434
  }
347
435
  return node;
348
436
  };
349
437
 
350
- GridStackEngine.prototype.get_grid_height = function () {
351
- return _.reduce(this.nodes, function (memo, n) { return Math.max(memo, n.y + n.height); }, 0);
438
+ GridStackEngine.prototype.getGridHeight = function() {
439
+ return _.reduce(this.nodes, function(memo, n) { return Math.max(memo, n.y + n.height); }, 0);
352
440
  };
353
441
 
354
- GridStackEngine.prototype.begin_update = function (node) {
355
- _.each(this.nodes, function (n) {
356
- n._orig_y = n.y;
442
+ GridStackEngine.prototype.beginUpdate = function(node) {
443
+ _.each(this.nodes, function(n) {
444
+ n._origY = n.y;
357
445
  });
358
446
  node._updating = true;
359
447
  };
360
448
 
361
- GridStackEngine.prototype.end_update = function () {
362
- _.each(this.nodes, function (n) {
363
- n._orig_y = n.y;
449
+ GridStackEngine.prototype.endUpdate = function() {
450
+ _.each(this.nodes, function(n) {
451
+ n._origY = n.y;
364
452
  });
365
- var n = _.find(this.nodes, function (n) { return n._updating; });
453
+ var n = _.find(this.nodes, function(n) { return n._updating; });
366
454
  if (n) {
367
455
  n._updating = false;
368
456
  }
369
457
  };
370
458
 
371
- var GridStack = function (el, opts) {
372
- var self = this, one_column_mode;
459
+ var GridStack = function(el, opts) {
460
+ var self = this;
461
+ var oneColumnMode, isAutoCellHeight;
462
+
463
+ opts = opts || {};
373
464
 
374
465
  this.container = $(el);
375
466
 
376
- opts.item_class = opts.item_class || 'grid-stack-item';
377
- var is_nested = this.container.closest('.' + opts.item_class).size() > 0;
467
+ // jscs:disable requireCamelCaseOrUpperCaseIdentifiers
468
+ if (typeof opts.handle_class !== 'undefined') {
469
+ opts.handleClass = opts.handle_class;
470
+ obsoleteOpts('handle_class', 'handleClass');
471
+ }
472
+ if (typeof opts.item_class !== 'undefined') {
473
+ opts.itemClass = opts.item_class;
474
+ obsoleteOpts('item_class', 'itemClass');
475
+ }
476
+ if (typeof opts.placeholder_class !== 'undefined') {
477
+ opts.placeholderClass = opts.placeholder_class;
478
+ obsoleteOpts('placeholder_class', 'placeholderClass');
479
+ }
480
+ if (typeof opts.placeholder_text !== 'undefined') {
481
+ opts.placeholderText = opts.placeholder_text;
482
+ obsoleteOpts('placeholder_text', 'placeholderText');
483
+ }
484
+ if (typeof opts.cell_height !== 'undefined') {
485
+ opts.cellHeight = opts.cell_height;
486
+ obsoleteOpts('cell_height', 'cellHeight');
487
+ }
488
+ if (typeof opts.vertical_margin !== 'undefined') {
489
+ opts.verticalMargin = opts.vertical_margin;
490
+ obsoleteOpts('vertical_margin', 'verticalMargin');
491
+ }
492
+ if (typeof opts.min_width !== 'undefined') {
493
+ opts.minWidth = opts.min_width;
494
+ obsoleteOpts('min_width', 'minWidth');
495
+ }
496
+ if (typeof opts.static_grid !== 'undefined') {
497
+ opts.staticGrid = opts.static_grid;
498
+ obsoleteOpts('static_grid', 'staticGrid');
499
+ }
500
+ if (typeof opts.is_nested !== 'undefined') {
501
+ opts.isNested = opts.is_nested;
502
+ obsoleteOpts('is_nested', 'isNested');
503
+ }
504
+ if (typeof opts.always_show_resize_handle !== 'undefined') {
505
+ opts.alwaysShowResizeHandle = opts.always_show_resize_handle;
506
+ obsoleteOpts('always_show_resize_handle', 'alwaysShowResizeHandle');
507
+ }
508
+ // jscs:enable requireCamelCaseOrUpperCaseIdentifiers
509
+
510
+ opts.itemClass = opts.itemClass || 'grid-stack-item';
511
+ var isNested = this.container.closest('.' + opts.itemClass).size() > 0;
378
512
 
379
513
  this.opts = _.defaults(opts || {}, {
380
514
  width: parseInt(this.container.attr('data-gs-width')) || 12,
381
515
  height: parseInt(this.container.attr('data-gs-height')) || 0,
382
- item_class: 'grid-stack-item',
383
- placeholder_class: 'grid-stack-placeholder',
516
+ itemClass: 'grid-stack-item',
517
+ placeholderClass: 'grid-stack-placeholder',
518
+ placeholderText: '',
384
519
  handle: '.grid-stack-item-content',
385
- cell_height: 60,
386
- vertical_margin: 20,
520
+ handleClass: null,
521
+ cellHeight: 60,
522
+ verticalMargin: 20,
387
523
  auto: true,
388
- min_width: 768,
524
+ minWidth: 768,
389
525
  float: false,
390
- _class: 'grid-stack-' + (Math.random() * 10000).toFixed(0),
526
+ staticGrid: false,
527
+ _class: 'grid-stack-instance-' + (Math.random() * 10000).toFixed(0),
391
528
  animate: Boolean(this.container.attr('data-gs-animate')) || false,
392
- always_show_resize_handle: opts.always_show_resize_handle || false,
529
+ alwaysShowResizeHandle: opts.alwaysShowResizeHandle || false,
393
530
  resizable: _.defaults(opts.resizable || {}, {
394
- autoHide: !(opts.always_show_resize_handle || false),
531
+ autoHide: !(opts.alwaysShowResizeHandle || false),
395
532
  handles: 'se'
396
533
  }),
397
534
  draggable: _.defaults(opts.draggable || {}, {
398
- handle: '.grid-stack-item-content',
535
+ handle: (opts.handleClass ? '.' + opts.handleClass : (opts.handle ? opts.handle : '')) ||
536
+ '.grid-stack-item-content',
399
537
  scroll: false,
400
538
  appendTo: 'body'
401
- })
539
+ }),
540
+ disableDrag: opts.disableDrag || false,
541
+ disableResize: opts.disableResize || false,
542
+ rtl: 'auto',
543
+ removable: false,
544
+ removeTimeout: 2000,
545
+ verticalMarginUnit: 'px',
546
+ cellHeightUnit: 'px'
402
547
  });
403
- this.opts.is_nested = is_nested;
548
+
549
+ if (this.opts.rtl === 'auto') {
550
+ this.opts.rtl = this.container.css('direction') === 'rtl';
551
+ }
552
+
553
+ if (this.opts.rtl) {
554
+ this.container.addClass('grid-stack-rtl');
555
+ }
556
+
557
+ this.opts.isNested = isNested;
558
+
559
+ isAutoCellHeight = this.opts.cellHeight === 'auto';
560
+ if (isAutoCellHeight) {
561
+ self.cellHeight(self.cellWidth(), true);
562
+ } else {
563
+ this.cellHeight(this.opts.cellHeight, true);
564
+ }
565
+ this.verticalMargin(this.opts.verticalMargin, true);
404
566
 
405
567
  this.container.addClass(this.opts._class);
406
- if (is_nested) {
568
+
569
+ this._setStaticClass();
570
+
571
+ if (isNested) {
407
572
  this.container.addClass('grid-stack-nested');
408
573
  }
409
574
 
410
- this._init_styles();
575
+ this._initStyles();
411
576
 
412
- this.grid = new GridStackEngine(this.opts.width, function (nodes) {
413
- var max_height = 0;
414
- _.each(nodes, function (n) {
415
- if (n._id == null) {
416
- n.el.remove();
417
- }
418
- else {
577
+ this.grid = new GridStackEngine(this.opts.width, function(nodes) {
578
+ var maxHeight = 0;
579
+ _.each(nodes, function(n) {
580
+ if (n._id === null) {
581
+ if (n.el) {
582
+ n.el.remove();
583
+ }
584
+ } else {
419
585
  n.el
420
586
  .attr('data-gs-x', n.x)
421
587
  .attr('data-gs-y', n.y)
422
588
  .attr('data-gs-width', n.width)
423
589
  .attr('data-gs-height', n.height);
424
- max_height = Math.max(max_height, n.y + n.height);
590
+ maxHeight = Math.max(maxHeight, n.y + n.height);
425
591
  }
426
592
  });
427
- self._update_styles(max_height + 10);
593
+ self._updateStyles(maxHeight + 10);
428
594
  }, this.opts.float, this.opts.height);
429
595
 
430
596
  if (this.opts.auto) {
431
597
  var elements = [];
432
598
  var _this = this;
433
- this.container.children('.' + this.opts.item_class).each(function (index, el) {
434
- el = $(el);
435
- elements.push({
436
- el: el,
437
- i: parseInt(el.attr('data-gs-x')) + parseInt(el.attr('data-gs-y')) * _this.opts.width // Use opts.width as weight for Y
599
+ this.container.children('.' + this.opts.itemClass + ':not(.' + this.opts.placeholderClass + ')')
600
+ .each(function(index, el) {
601
+ el = $(el);
602
+ elements.push({
603
+ el: el,
604
+ i: parseInt(el.attr('data-gs-x')) + parseInt(el.attr('data-gs-y')) * _this.opts.width
605
+ });
438
606
  });
439
- });
440
- _.chain(elements).sortBy(function (x) { return x.i; }).each(function (i) {
441
- self._prepare_element(i.el);
607
+ _.chain(elements).sortBy(function(x) { return x.i; }).each(function(i) {
608
+ self._prepareElement(i.el);
442
609
  }).value();
443
610
  }
444
611
 
445
- this.set_animation(this.opts.animate);
612
+ this.setAnimation(this.opts.animate);
613
+
614
+ this.placeholder = $(
615
+ '<div class="' + this.opts.placeholderClass + ' ' + this.opts.itemClass + '">' +
616
+ '<div class="placeholder-content">' + this.opts.placeholderText + '</div></div>').hide();
446
617
 
447
- this.placeholder = $('<div class="' + this.opts.placeholder_class + ' ' + this.opts.item_class + '"><div class="placeholder-content" /></div>').hide();
448
- this.container.height((this.grid.get_grid_height()) * (this.opts.cell_height + this.opts.vertical_margin) - this.opts.vertical_margin);
618
+ this._updateContainerHeight();
449
619
 
450
- var on_resize_handler = function () {
451
- if (self._is_one_column_mode()) {
452
- if (one_column_mode)
620
+ this._updateHeightsOnResize = _.throttle(function() {
621
+ self.cellHeight(self.cellWidth(), false);
622
+ }, 100);
623
+
624
+ this.onResizeHandler = function() {
625
+ if (isAutoCellHeight) {
626
+ self._updateHeightsOnResize();
627
+ }
628
+
629
+ if (self._isOneColumnMode()) {
630
+ if (oneColumnMode) {
453
631
  return;
632
+ }
454
633
 
455
- one_column_mode = true;
634
+ oneColumnMode = true;
456
635
 
457
- self.grid._sort_nodes();
458
- _.each(self.grid.nodes, function (node) {
636
+ self.grid._sortNodes();
637
+ _.each(self.grid.nodes, function(node) {
459
638
  self.container.append(node.el);
460
639
 
461
- if (!node.no_move) {
640
+ if (self.opts.staticGrid) {
641
+ return;
642
+ }
643
+ if (node.noMove || self.opts.disableDrag) {
462
644
  node.el.draggable('disable');
463
645
  }
464
- if (!node.no_resize) {
646
+ if (node.noResize || self.opts.disableResize) {
465
647
  node.el.resizable('disable');
466
648
  }
467
649
  });
468
- }
469
- else {
470
- if (!one_column_mode)
650
+ } else {
651
+ if (!oneColumnMode) {
471
652
  return;
653
+ }
472
654
 
473
- one_column_mode = false;
655
+ oneColumnMode = false;
474
656
 
475
- _.each(self.grid.nodes, function (node) {
476
- if (!node.no_move) {
657
+ if (self.opts.staticGrid) {
658
+ return;
659
+ }
660
+
661
+ _.each(self.grid.nodes, function(node) {
662
+ if (!node.noMove && !self.opts.disableDrag) {
477
663
  node.el.draggable('enable');
478
664
  }
479
- if (!node.no_resize) {
665
+ if (!node.noResize && !self.opts.disableResize) {
480
666
  node.el.resizable('enable');
481
667
  }
482
668
  });
483
669
  }
484
670
  };
485
671
 
486
- $(window).resize(on_resize_handler);
487
- on_resize_handler();
672
+ $(window).resize(this.onResizeHandler);
673
+ this.onResizeHandler();
674
+
675
+ if (typeof self.opts.removable === 'string') {
676
+ var trashZone = $(self.opts.removable);
677
+ if (!trashZone.data('droppable')) {
678
+ trashZone.droppable({
679
+ accept: '.' + self.opts.itemClass
680
+ });
681
+ }
682
+ trashZone
683
+ .on('dropover', function(event, ui) {
684
+ var el = $(ui.draggable);
685
+ var node = el.data('_gridstack_node');
686
+ if (node._grid !== self) {
687
+ return;
688
+ }
689
+ self._setupRemovingTimeout(el);
690
+ })
691
+ .on('dropout', function(event, ui) {
692
+ var el = $(ui.draggable);
693
+ var node = el.data('_gridstack_node');
694
+ if (node._grid !== self) {
695
+ return;
696
+ }
697
+ self._clearRemovingTimeout(el);
698
+ });
699
+ }
700
+
701
+ if (self.opts.acceptWidgets) {
702
+ var draggingElement = null;
703
+
704
+ var onDrag = function(event, ui) {
705
+ var el = draggingElement;
706
+ var node = el.data('_gridstack_node');
707
+ var pos = self.getCellFromPixel(ui.offset, true);
708
+ var x = Math.max(0, pos.x);
709
+ var y = Math.max(0, pos.y);
710
+ if (!node._added) {
711
+ node._added = true;
712
+
713
+ node.el = el;
714
+ node.x = x;
715
+ node.y = y;
716
+ self.grid.cleanNodes();
717
+ self.grid.beginUpdate(node);
718
+ self.grid.addNode(node);
719
+
720
+ self.container.append(self.placeholder);
721
+ self.placeholder
722
+ .attr('data-gs-x', node.x)
723
+ .attr('data-gs-y', node.y)
724
+ .attr('data-gs-width', node.width)
725
+ .attr('data-gs-height', node.height)
726
+ .show();
727
+ node.el = self.placeholder;
728
+ node._beforeDragX = node.x;
729
+ node._beforeDragY = node.y;
730
+
731
+ self._updateContainerHeight();
732
+ } else {
733
+ if (!self.grid.canMoveNode(node, x, y)) {
734
+ return;
735
+ }
736
+ self.grid.moveNode(node, x, y);
737
+ self._updateContainerHeight();
738
+ }
739
+ };
740
+
741
+ $(self.container).droppable({
742
+ accept: function(el) {
743
+ el = $(el);
744
+ var node = el.data('_gridstack_node');
745
+ if (node && node._grid === self) {
746
+ return false;
747
+ }
748
+ return el.is(self.opts.acceptWidgets === true ? '.grid-stack-item' : self.opts.acceptWidgets);
749
+ },
750
+ over: function(event, ui) {
751
+ var offset = self.container.offset();
752
+ var el = $(ui.draggable);
753
+ var cellWidth = self.cellWidth();
754
+ var cellHeight = self.cellHeight();
755
+ var origNode = el.data('_gridstack_node');
756
+
757
+ var width = origNode ? origNode.width : (Math.ceil(el.outerWidth() / cellWidth));
758
+ var height = origNode ? origNode.height : (Math.ceil(el.outerHeight() / cellHeight));
759
+
760
+ draggingElement = el;
761
+
762
+ var node = self.grid._prepareNode({width: width, height: height, _added: false, _temporary: true});
763
+ el.data('_gridstack_node', node);
764
+ el.data('_gridstack_node_orig', origNode);
765
+
766
+ el.on('drag', onDrag);
767
+ },
768
+ out: function(event, ui) {
769
+ var el = $(ui.draggable);
770
+ el.unbind('drag', onDrag);
771
+ var node = el.data('_gridstack_node');
772
+ node.el = null;
773
+ self.grid.removeNode(node);
774
+ self.placeholder.detach();
775
+ self._updateContainerHeight();
776
+ el.data('_gridstack_node', el.data('_gridstack_node_orig'));
777
+ },
778
+ drop: function(event, ui) {
779
+ self.placeholder.detach();
780
+
781
+ var node = $(ui.draggable).data('_gridstack_node');
782
+ node._grid = self;
783
+ var el = $(ui.draggable).clone(false);
784
+ el.data('_gridstack_node', node);
785
+ $(ui.draggable).remove();
786
+ node.el = el;
787
+ self.placeholder.hide();
788
+ el
789
+ .attr('data-gs-x', node.x)
790
+ .attr('data-gs-y', node.y)
791
+ .attr('data-gs-width', node.width)
792
+ .attr('data-gs-height', node.height)
793
+ .addClass(self.opts.itemClass)
794
+ .removeAttr('style')
795
+ .enableSelection()
796
+ .removeData('draggable')
797
+ .removeClass('ui-draggable ui-draggable-dragging ui-draggable-disabled')
798
+ .unbind('drag', onDrag);
799
+ self.container.append(el);
800
+ self._prepareElementByNode(el, node);
801
+ self._updateContainerHeight();
802
+ self._triggerChangeEvent();
803
+
804
+ self.grid.endUpdate();
805
+ }
806
+ });
807
+ }
488
808
  };
489
809
 
490
- GridStack.prototype._init_styles = function () {
491
- if (this._styles_id) {
492
- $('[data-gs-id="' + this._styles_id + '"]').remove();
810
+ GridStack.prototype._triggerChangeEvent = function(forceTrigger) {
811
+ var elements = this.grid.getDirtyNodes();
812
+ var hasChanges = false;
813
+
814
+ var eventParams = [];
815
+ if (elements && elements.length) {
816
+ eventParams.push(elements);
817
+ hasChanges = true;
818
+ }
819
+
820
+ if (hasChanges || forceTrigger === true) {
821
+ this.container.trigger('change', eventParams);
493
822
  }
494
- this._styles_id = 'gridstack-style-' + (Math.random() * 100000).toFixed();
495
- this._styles = Utils.create_stylesheet(this._styles_id);
496
- if (this._styles != null)
823
+ };
824
+
825
+ GridStack.prototype._triggerAddEvent = function() {
826
+ if (this.grid._addedNodes && this.grid._addedNodes.length > 0) {
827
+ this.container.trigger('added', [_.map(this.grid._addedNodes, _.clone)]);
828
+ this.grid._addedNodes = [];
829
+ }
830
+ };
831
+
832
+ GridStack.prototype._triggerRemoveEvent = function() {
833
+ if (this.grid._removedNodes && this.grid._removedNodes.length > 0) {
834
+ this.container.trigger('removed', [_.map(this.grid._removedNodes, _.clone)]);
835
+ this.grid._removedNodes = [];
836
+ }
837
+ };
838
+
839
+ GridStack.prototype._initStyles = function() {
840
+ if (this._stylesId) {
841
+ Utils.removeStylesheet(this._stylesId);
842
+ }
843
+ this._stylesId = 'gridstack-style-' + (Math.random() * 100000).toFixed();
844
+ this._styles = Utils.createStylesheet(this._stylesId);
845
+ if (this._styles !== null) {
497
846
  this._styles._max = 0;
847
+ }
498
848
  };
499
849
 
500
- GridStack.prototype._update_styles = function (max_height) {
501
- if (this._styles == null) {
850
+ GridStack.prototype._updateStyles = function(maxHeight) {
851
+ if (this._styles === null || typeof this._styles === 'undefined') {
502
852
  return;
503
853
  }
504
854
 
505
- var prefix = '.' + this.opts._class + ' .' + this.opts.item_class;
855
+ var prefix = '.' + this.opts._class + ' .' + this.opts.itemClass;
856
+ var self = this;
857
+ var getHeight;
506
858
 
507
- if (typeof max_height == 'undefined') {
508
- max_height = this._styles._max;
509
- this._init_styles();
510
- this._update_container_height();
859
+ if (typeof maxHeight == 'undefined') {
860
+ maxHeight = this._styles._max;
861
+ this._initStyles();
862
+ this._updateContainerHeight();
863
+ }
864
+ if (!this.opts.cellHeight) { // The rest will be handled by CSS
865
+ return ;
866
+ }
867
+ if (this._styles._max !== 0 && maxHeight <= this._styles._max) {
868
+ return ;
511
869
  }
512
870
 
513
- if (this._styles._max == 0) {
514
- Utils.insert_css_rule(this._styles, prefix, 'min-height: ' + (this.opts.cell_height) + 'px;', 0);
871
+ if (!this.opts.verticalMargin || this.opts.cellHeightUnit === this.opts.verticalMarginUnit) {
872
+ getHeight = function(nbRows, nbMargins) {
873
+ return (self.opts.cellHeight * nbRows + self.opts.verticalMargin * nbMargins) +
874
+ self.opts.cellHeightUnit;
875
+ };
876
+ } else {
877
+ getHeight = function(nbRows, nbMargins) {
878
+ if (!nbRows || !nbMargins) {
879
+ return (self.opts.cellHeight * nbRows + self.opts.verticalMargin * nbMargins) +
880
+ self.opts.cellHeightUnit;
881
+ }
882
+ return 'calc(' + ((self.opts.cellHeight * nbRows) + self.opts.cellHeightUnit) + ' + ' +
883
+ ((self.opts.verticalMargin * nbMargins) + self.opts.verticalMarginUnit) + ')';
884
+ };
515
885
  }
516
886
 
517
- if (max_height > this._styles._max) {
518
- for (var i = this._styles._max; i < max_height; ++i) {
519
- Utils.insert_css_rule(this._styles,
887
+ if (this._styles._max === 0) {
888
+ Utils.insertCSSRule(this._styles, prefix, 'min-height: ' + getHeight(1, 0) + ';', 0);
889
+ }
890
+
891
+ if (maxHeight > this._styles._max) {
892
+ for (var i = this._styles._max; i < maxHeight; ++i) {
893
+ Utils.insertCSSRule(this._styles,
520
894
  prefix + '[data-gs-height="' + (i + 1) + '"]',
521
- 'height: ' + (this.opts.cell_height * (i + 1) + this.opts.vertical_margin * i) + 'px;',
895
+ 'height: ' + getHeight(i + 1, i) + ';',
522
896
  i
523
897
  );
524
- Utils.insert_css_rule(this._styles,
898
+ Utils.insertCSSRule(this._styles,
525
899
  prefix + '[data-gs-min-height="' + (i + 1) + '"]',
526
- 'min-height: ' + (this.opts.cell_height * (i + 1) + this.opts.vertical_margin * i) + 'px;',
900
+ 'min-height: ' + getHeight(i + 1, i) + ';',
527
901
  i
528
902
  );
529
- Utils.insert_css_rule(this._styles,
903
+ Utils.insertCSSRule(this._styles,
530
904
  prefix + '[data-gs-max-height="' + (i + 1) + '"]',
531
- 'max-height: ' + (this.opts.cell_height * (i + 1) + this.opts.vertical_margin * i) + 'px;',
905
+ 'max-height: ' + getHeight(i + 1, i) + ';',
532
906
  i
533
907
  );
534
- Utils.insert_css_rule(this._styles,
908
+ Utils.insertCSSRule(this._styles,
535
909
  prefix + '[data-gs-y="' + i + '"]',
536
- 'top: ' + (this.opts.cell_height * i + this.opts.vertical_margin * i) + 'px;',
910
+ 'top: ' + getHeight(i, i) + ';',
537
911
  i
538
912
  );
539
913
  }
540
- this._styles._max = max_height;
914
+ this._styles._max = maxHeight;
541
915
  }
542
916
  };
543
917
 
544
- GridStack.prototype._update_container_height = function () {
545
- if (this.grid._update_counter) {
918
+ GridStack.prototype._updateContainerHeight = function() {
919
+ if (this.grid._updateCounter) {
546
920
  return;
547
921
  }
548
- this.container.height(this.grid.get_grid_height() * (this.opts.cell_height + this.opts.vertical_margin) - this.opts.vertical_margin);
922
+ var height = this.grid.getGridHeight();
923
+ this.container.attr('data-gs-current-height', height);
924
+ if (!this.opts.cellHeight) {
925
+ return ;
926
+ }
927
+ if (!this.opts.verticalMargin) {
928
+ this.container.css('height', (height * (this.opts.cellHeight)) + this.opts.cellHeightUnit);
929
+ } else if (this.opts.cellHeightUnit === this.opts.verticalMarginUnit) {
930
+ this.container.css('height', (height * (this.opts.cellHeight + this.opts.verticalMargin) -
931
+ this.opts.verticalMargin) + this.opts.cellHeightUnit);
932
+ } else {
933
+ this.container.css('height', 'calc(' + ((height * (this.opts.cellHeight)) + this.opts.cellHeightUnit) +
934
+ ' + ' + ((height * (this.opts.verticalMargin - 1)) + this.opts.verticalMarginUnit) + ')');
935
+ }
549
936
  };
550
937
 
551
- GridStack.prototype._is_one_column_mode = function () {
552
- return (window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth) <= this.opts.min_width;
938
+ GridStack.prototype._isOneColumnMode = function() {
939
+ return (window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth) <=
940
+ this.opts.minWidth;
553
941
  };
554
942
 
555
- GridStack.prototype._prepare_element = function (el) {
943
+ GridStack.prototype._setupRemovingTimeout = function(el) {
556
944
  var self = this;
557
- el = $(el);
945
+ var node = $(el).data('_gridstack_node');
558
946
 
559
- el.addClass(this.opts.item_class);
947
+ if (node._removeTimeout || !self.opts.removable) {
948
+ return;
949
+ }
950
+ node._removeTimeout = setTimeout(function() {
951
+ el.addClass('grid-stack-item-removing');
952
+ node._isAboutToRemove = true;
953
+ }, self.opts.removeTimeout);
954
+ };
560
955
 
561
- var node = self.grid.add_node({
562
- x: el.attr('data-gs-x'),
563
- y: el.attr('data-gs-y'),
564
- width: el.attr('data-gs-width'),
565
- height: el.attr('data-gs-height'),
566
- max_width: el.attr('data-gs-max-width'),
567
- min_width: el.attr('data-gs-min-width'),
568
- max_height: el.attr('data-gs-max-height'),
569
- min_height: el.attr('data-gs-min-height'),
570
- auto_position: Utils.toBool(el.attr('data-gs-auto-position')),
571
- no_resize: Utils.toBool(el.attr('data-gs-no-resize')),
572
- no_move: Utils.toBool(el.attr('data-gs-no-move')),
573
- locked: Utils.toBool(el.attr('data-gs-locked')),
574
- el: el
575
- });
576
- el.data('_gridstack_node', node);
956
+ GridStack.prototype._clearRemovingTimeout = function(el) {
957
+ var node = $(el).data('_gridstack_node');
958
+
959
+ if (!node._removeTimeout) {
960
+ return;
961
+ }
962
+ clearTimeout(node._removeTimeout);
963
+ node._removeTimeout = null;
964
+ el.removeClass('grid-stack-item-removing');
965
+ node._isAboutToRemove = false;
966
+ };
967
+
968
+ GridStack.prototype._prepareElementByNode = function(el, node) {
969
+ var self = this;
577
970
 
578
- var cell_width, cell_height;
971
+ var cellWidth;
972
+ var cellHeight;
579
973
 
580
- var on_start_moving = function (event, ui) {
974
+ var dragOrResize = function(event, ui) {
975
+ var x = Math.round(ui.position.left / cellWidth);
976
+ var y = Math.floor((ui.position.top + cellHeight / 2) / cellHeight);
977
+ var width;
978
+ var height;
979
+
980
+ if (event.type != 'drag') {
981
+ width = Math.round(ui.size.width / cellWidth);
982
+ height = Math.round(ui.size.height / cellHeight);
983
+ }
984
+
985
+ if (event.type == 'drag') {
986
+ if (x < 0 || x >= self.grid.width || y < 0) {
987
+ if (self.opts.removable === true) {
988
+ self._setupRemovingTimeout(el);
989
+ }
990
+
991
+ x = node._beforeDragX;
992
+ y = node._beforeDragY;
993
+
994
+ self.placeholder.detach();
995
+ self.placeholder.hide();
996
+ self.grid.removeNode(node);
997
+ self._updateContainerHeight();
998
+
999
+ node._temporaryRemoved = true;
1000
+ } else {
1001
+ self._clearRemovingTimeout(el);
1002
+
1003
+ if (node._temporaryRemoved) {
1004
+ self.grid.addNode(node);
1005
+ self.placeholder
1006
+ .attr('data-gs-x', x)
1007
+ .attr('data-gs-y', y)
1008
+ .attr('data-gs-width', width)
1009
+ .attr('data-gs-height', height)
1010
+ .show();
1011
+ self.container.append(self.placeholder);
1012
+ node.el = self.placeholder;
1013
+ node._temporaryRemoved = false;
1014
+ }
1015
+ }
1016
+ } else if (event.type == 'resize') {
1017
+ if (x < 0) {
1018
+ return;
1019
+ }
1020
+ }
1021
+
1022
+ if (!self.grid.canMoveNode(node, x, y, width, height)) {
1023
+ return;
1024
+ }
1025
+ self.grid.moveNode(node, x, y, width, height);
1026
+ self._updateContainerHeight();
1027
+ };
1028
+
1029
+ var onStartMoving = function(event, ui) {
581
1030
  self.container.append(self.placeholder);
582
1031
  var o = $(this);
583
- self.grid.clean_nodes();
584
- self.grid.begin_update(node);
585
- cell_width = Math.ceil(o.outerWidth() / o.attr('data-gs-width'));
586
- cell_height = self.opts.cell_height + self.opts.vertical_margin;
1032
+ self.grid.cleanNodes();
1033
+ self.grid.beginUpdate(node);
1034
+ cellWidth = Math.ceil(o.outerWidth() / o.attr('data-gs-width'));
1035
+ var strictCellHeight = Math.ceil(o.outerHeight() / o.attr('data-gs-height'));
1036
+ cellHeight = self.container.height() / parseInt(self.container.attr('data-gs-current-height'));
587
1037
  self.placeholder
588
1038
  .attr('data-gs-x', o.attr('data-gs-x'))
589
1039
  .attr('data-gs-y', o.attr('data-gs-y'))
@@ -591,173 +1041,280 @@
591
1041
  .attr('data-gs-height', o.attr('data-gs-height'))
592
1042
  .show();
593
1043
  node.el = self.placeholder;
1044
+ node._beforeDragX = node.x;
1045
+ node._beforeDragY = node.y;
1046
+
1047
+ el.resizable('option', 'minWidth', cellWidth * (node.minWidth || 1));
1048
+ el.resizable('option', 'minHeight', strictCellHeight * (node.minHeight || 1));
594
1049
 
595
- el.resizable('option', 'minWidth', cell_width * (node.min_width || 1));
596
- el.resizable('option', 'minHeight', self.opts.cell_height * (node.min_height || 1));
1050
+ if (event.type == 'resizestart') {
1051
+ o.find('.grid-stack-item').trigger('resizestart');
1052
+ }
597
1053
  };
598
1054
 
599
- var on_end_moving = function (event, ui) {
600
- self.placeholder.detach();
1055
+ var onEndMoving = function(event, ui) {
601
1056
  var o = $(this);
1057
+ if (!o.data('_gridstack_node')) {
1058
+ return;
1059
+ }
1060
+
1061
+ var forceNotify = false;
1062
+ self.placeholder.detach();
602
1063
  node.el = o;
603
1064
  self.placeholder.hide();
604
- o
605
- .attr('data-gs-x', node.x)
606
- .attr('data-gs-y', node.y)
607
- .attr('data-gs-width', node.width)
608
- .attr('data-gs-height', node.height)
609
- .removeAttr('style');
610
- self._update_container_height();
611
- var elements = self.grid.get_dirty_nodes();
612
- if (elements && elements.length)
613
- self.container.trigger('change', [elements]);
614
-
615
- self.grid.end_update();
616
- };
617
1065
 
618
- el.draggable(_.extend(this.opts.draggable, {
619
- start: on_start_moving,
620
- stop: on_end_moving,
621
- drag: function (event, ui) {
622
- var x = Math.round(ui.position.left / cell_width),
623
- y = Math.floor((ui.position.top + cell_height/2) / cell_height);
624
- if (!self.grid.can_move_node(node, x, y, node.width, node.height)) {
625
- return;
626
- }
627
- self.grid.move_node(node, x, y);
628
- self._update_container_height();
629
- },
630
- containment: this.opts.is_nested ? this.container.parent() : null
631
- })).resizable(_.extend(this.opts.resizable, {
632
- start: on_start_moving,
633
- stop: on_end_moving,
634
- resize: function (event, ui) {
635
- var x = Math.round(ui.position.left / cell_width),
636
- y = Math.floor((ui.position.top + cell_height/2) / cell_height),
637
- width = Math.round(ui.size.width / cell_width),
638
- height = Math.round(ui.size.height / cell_height);
639
- if (!self.grid.can_move_node(node, x, y, width, height)) {
640
- return;
1066
+ if (node._isAboutToRemove) {
1067
+ forceNotify = true;
1068
+ el.removeData('_gridstack_node');
1069
+ el.remove();
1070
+ } else {
1071
+ self._clearRemovingTimeout(el);
1072
+ if (!node._temporaryRemoved) {
1073
+ o
1074
+ .attr('data-gs-x', node.x)
1075
+ .attr('data-gs-y', node.y)
1076
+ .attr('data-gs-width', node.width)
1077
+ .attr('data-gs-height', node.height)
1078
+ .removeAttr('style');
1079
+ } else {
1080
+ o
1081
+ .attr('data-gs-x', node._beforeDragX)
1082
+ .attr('data-gs-y', node._beforeDragY)
1083
+ .attr('data-gs-width', node.width)
1084
+ .attr('data-gs-height', node.height)
1085
+ .removeAttr('style');
1086
+ node.x = node._beforeDragX;
1087
+ node.y = node._beforeDragY;
1088
+ self.grid.addNode(node);
641
1089
  }
642
- self.grid.move_node(node, x, y, width, height);
643
- self._update_container_height();
644
1090
  }
645
- }));
1091
+ self._updateContainerHeight();
1092
+ self._triggerChangeEvent(forceNotify);
1093
+
1094
+ self.grid.endUpdate();
1095
+
1096
+ var nestedGrids = o.find('.grid-stack');
1097
+ if (nestedGrids.length && event.type == 'resizestop') {
1098
+ nestedGrids.each(function(index, el) {
1099
+ $(el).data('gridstack').onResizeHandler();
1100
+ });
1101
+ o.find('.grid-stack-item').trigger('resizestop');
1102
+ }
1103
+ };
646
1104
 
647
- if (node.no_move || this._is_one_column_mode()) {
1105
+ el
1106
+ .draggable(_.extend(this.opts.draggable, {
1107
+ containment: this.opts.isNested ? this.container.parent() : null,
1108
+ start: onStartMoving,
1109
+ stop: onEndMoving,
1110
+ drag: dragOrResize
1111
+ }))
1112
+ .resizable(_.extend(this.opts.resizable, {
1113
+ start: onStartMoving,
1114
+ stop: onEndMoving,
1115
+ resize: dragOrResize
1116
+ }));
1117
+
1118
+ if (node.noMove || this._isOneColumnMode() || this.opts.staticGrid || this.opts.disableDrag) {
648
1119
  el.draggable('disable');
649
1120
  }
650
1121
 
651
- if (node.no_resize || this._is_one_column_mode()) {
1122
+ if (node.noResize || this._isOneColumnMode() || this.opts.staticGrid || this.opts.disableResize) {
652
1123
  el.resizable('disable');
653
1124
  }
654
1125
 
655
1126
  el.attr('data-gs-locked', node.locked ? 'yes' : null);
656
1127
  };
657
1128
 
658
- GridStack.prototype.set_animation = function (enable) {
1129
+ GridStack.prototype._prepareElement = function(el, triggerAddEvent) {
1130
+ triggerAddEvent = typeof triggerAddEvent != 'undefined' ? triggerAddEvent : false;
1131
+ var self = this;
1132
+ el = $(el);
1133
+
1134
+ el.addClass(this.opts.itemClass);
1135
+ var node = self.grid.addNode({
1136
+ x: el.attr('data-gs-x'),
1137
+ y: el.attr('data-gs-y'),
1138
+ width: el.attr('data-gs-width'),
1139
+ height: el.attr('data-gs-height'),
1140
+ maxWidth: el.attr('data-gs-max-width'),
1141
+ minWidth: el.attr('data-gs-min-width'),
1142
+ maxHeight: el.attr('data-gs-max-height'),
1143
+ minHeight: el.attr('data-gs-min-height'),
1144
+ autoPosition: Utils.toBool(el.attr('data-gs-auto-position')),
1145
+ noResize: Utils.toBool(el.attr('data-gs-no-resize')),
1146
+ noMove: Utils.toBool(el.attr('data-gs-no-move')),
1147
+ locked: Utils.toBool(el.attr('data-gs-locked')),
1148
+ el: el,
1149
+ id: el.attr('data-gs-id'),
1150
+ _grid: self
1151
+ }, triggerAddEvent);
1152
+ el.data('_gridstack_node', node);
1153
+
1154
+ this._prepareElementByNode(el, node);
1155
+ };
1156
+
1157
+ GridStack.prototype.setAnimation = function(enable) {
659
1158
  if (enable) {
660
1159
  this.container.addClass('grid-stack-animate');
661
- }
662
- else {
1160
+ } else {
663
1161
  this.container.removeClass('grid-stack-animate');
664
1162
  }
665
1163
  };
666
1164
 
667
- GridStack.prototype.add_widget = function (el, x, y, width, height, auto_position) {
1165
+ GridStack.prototype.addWidget = function(el, x, y, width, height, autoPosition, minWidth, maxWidth,
1166
+ minHeight, maxHeight, id) {
668
1167
  el = $(el);
669
- if (typeof x != 'undefined') el.attr('data-gs-x', x);
670
- if (typeof y != 'undefined') el.attr('data-gs-y', y);
671
- if (typeof width != 'undefined') el.attr('data-gs-width', width);
672
- if (typeof height != 'undefined') el.attr('data-gs-height', height);
673
- if (typeof auto_position != 'undefined') el.attr('data-gs-auto-position', auto_position ? 'yes' : null);
1168
+ if (typeof x != 'undefined') { el.attr('data-gs-x', x); }
1169
+ if (typeof y != 'undefined') { el.attr('data-gs-y', y); }
1170
+ if (typeof width != 'undefined') { el.attr('data-gs-width', width); }
1171
+ if (typeof height != 'undefined') { el.attr('data-gs-height', height); }
1172
+ if (typeof autoPosition != 'undefined') { el.attr('data-gs-auto-position', autoPosition ? 'yes' : null); }
1173
+ if (typeof minWidth != 'undefined') { el.attr('data-gs-min-width', minWidth); }
1174
+ if (typeof maxWidth != 'undefined') { el.attr('data-gs-max-width', maxWidth); }
1175
+ if (typeof minHeight != 'undefined') { el.attr('data-gs-min-height', minHeight); }
1176
+ if (typeof maxHeight != 'undefined') { el.attr('data-gs-max-height', maxHeight); }
1177
+ if (typeof id != 'undefined') { el.attr('data-gs-id', id); }
674
1178
  this.container.append(el);
675
- this._prepare_element(el);
676
- this._update_container_height();
1179
+ this._prepareElement(el, true);
1180
+ this._triggerAddEvent();
1181
+ this._updateContainerHeight();
1182
+ this._triggerChangeEvent(true);
1183
+
1184
+ return el;
1185
+ };
1186
+
1187
+ GridStack.prototype.makeWidget = function(el) {
1188
+ el = $(el);
1189
+ this._prepareElement(el, true);
1190
+ this._triggerAddEvent();
1191
+ this._updateContainerHeight();
1192
+ this._triggerChangeEvent(true);
677
1193
 
678
1194
  return el;
679
1195
  };
680
1196
 
681
- GridStack.prototype.will_it_fit = function (x, y, width, height, auto_position) {
682
- var node = {x: x, y: y, width: width, height: height, auto_position: auto_position};
683
- return this.grid.can_be_placed_with_respect_to_height(node);
1197
+ GridStack.prototype.willItFit = function(x, y, width, height, autoPosition) {
1198
+ var node = {x: x, y: y, width: width, height: height, autoPosition: autoPosition};
1199
+ return this.grid.canBePlacedWithRespectToHeight(node);
684
1200
  };
685
1201
 
686
- GridStack.prototype.remove_widget = function (el, detach_node) {
687
- detach_node = typeof detach_node === 'undefined' ? true : detach_node;
1202
+ GridStack.prototype.removeWidget = function(el, detachNode) {
1203
+ detachNode = typeof detachNode === 'undefined' ? true : detachNode;
688
1204
  el = $(el);
689
1205
  var node = el.data('_gridstack_node');
690
- this.grid.remove_node(node);
1206
+
1207
+ // For Meteor support: https://github.com/troolee/gridstack.js/pull/272
1208
+ if (!node) {
1209
+ node = this.grid.getNodeDataByDOMEl(el);
1210
+ }
1211
+
1212
+ this.grid.removeNode(node, detachNode);
691
1213
  el.removeData('_gridstack_node');
692
- this._update_container_height();
693
- if (detach_node)
1214
+ this._updateContainerHeight();
1215
+ if (detachNode) {
694
1216
  el.remove();
1217
+ }
1218
+ this._triggerChangeEvent(true);
1219
+ this._triggerRemoveEvent();
695
1220
  };
696
1221
 
697
- GridStack.prototype.remove_all = function (detach_node) {
698
- _.each(this.grid.nodes, function (node) {
699
- this.remove_widget(node.el, detach_node);
700
- }, this);
1222
+ GridStack.prototype.removeAll = function(detachNode) {
1223
+ _.each(this.grid.nodes, _.bind(function(node) {
1224
+ this.removeWidget(node.el, detachNode);
1225
+ }, this));
701
1226
  this.grid.nodes = [];
702
- this._update_container_height();
1227
+ this._updateContainerHeight();
703
1228
  };
704
1229
 
705
- GridStack.prototype.resizable = function (el, val) {
1230
+ GridStack.prototype.destroy = function(detachGrid) {
1231
+ $(window).off('resize', this.onResizeHandler);
1232
+ this.disable();
1233
+ if (typeof detachGrid != 'undefined' && !detachGrid) {
1234
+ this.removeAll(false);
1235
+ } else {
1236
+ this.container.remove();
1237
+ }
1238
+ Utils.removeStylesheet(this._stylesId);
1239
+ if (this.grid) {
1240
+ this.grid = null;
1241
+ }
1242
+ };
1243
+
1244
+ GridStack.prototype.resizable = function(el, val) {
1245
+ var self = this;
706
1246
  el = $(el);
707
- el.each(function (index, el) {
1247
+ el.each(function(index, el) {
708
1248
  el = $(el);
709
1249
  var node = el.data('_gridstack_node');
710
- if (typeof node == 'undefined' || node == null) {
1250
+ if (typeof node == 'undefined' || node === null) {
711
1251
  return;
712
1252
  }
713
1253
 
714
- node.no_resize = !(val || false);
715
- if (node.no_resize) {
1254
+ node.noResize = !(val || false);
1255
+ if (node.noResize || self._isOneColumnMode()) {
716
1256
  el.resizable('disable');
717
- }
718
- else {
1257
+ } else {
719
1258
  el.resizable('enable');
720
1259
  }
721
1260
  });
722
1261
  return this;
723
1262
  };
724
1263
 
725
- GridStack.prototype.movable = function (el, val) {
1264
+ GridStack.prototype.movable = function(el, val) {
1265
+ var self = this;
726
1266
  el = $(el);
727
- el.each(function (index, el) {
1267
+ el.each(function(index, el) {
728
1268
  el = $(el);
729
1269
  var node = el.data('_gridstack_node');
730
- if (typeof node == 'undefined' || node == null) {
1270
+ if (typeof node == 'undefined' || node === null) {
731
1271
  return;
732
1272
  }
733
1273
 
734
- node.no_move = !(val || false);
735
- if (node.no_move) {
1274
+ node.noMove = !(val || false);
1275
+ if (node.noMove || self._isOneColumnMode()) {
736
1276
  el.draggable('disable');
737
- }
738
- else {
1277
+ el.removeClass('ui-draggable-handle');
1278
+ } else {
739
1279
  el.draggable('enable');
1280
+ el.addClass('ui-draggable-handle');
740
1281
  }
741
1282
  });
742
1283
  return this;
743
1284
  };
744
1285
 
745
- GridStack.prototype.disable = function () {
746
- this.movable(this.container.children('.' + this.opts.item_class), false);
747
- this.resizable(this.container.children('.' + this.opts.item_class), false);
1286
+ GridStack.prototype.enableMove = function(doEnable, includeNewWidgets) {
1287
+ this.movable(this.container.children('.' + this.opts.itemClass), doEnable);
1288
+ if (includeNewWidgets) {
1289
+ this.opts.disableDrag = !doEnable;
1290
+ }
748
1291
  };
749
1292
 
750
- GridStack.prototype.enable = function () {
751
- this.movable(this.container.children('.' + this.opts.item_class), true);
752
- this.resizable(this.container.children('.' + this.opts.item_class), true);
1293
+ GridStack.prototype.enableResize = function(doEnable, includeNewWidgets) {
1294
+ this.resizable(this.container.children('.' + this.opts.itemClass), doEnable);
1295
+ if (includeNewWidgets) {
1296
+ this.opts.disableResize = !doEnable;
1297
+ }
753
1298
  };
754
1299
 
755
- GridStack.prototype.locked = function (el, val) {
1300
+ GridStack.prototype.disable = function() {
1301
+ this.movable(this.container.children('.' + this.opts.itemClass), false);
1302
+ this.resizable(this.container.children('.' + this.opts.itemClass), false);
1303
+ this.container.trigger('disable');
1304
+ };
1305
+
1306
+ GridStack.prototype.enable = function() {
1307
+ this.movable(this.container.children('.' + this.opts.itemClass), true);
1308
+ this.resizable(this.container.children('.' + this.opts.itemClass), true);
1309
+ this.container.trigger('enable');
1310
+ };
1311
+
1312
+ GridStack.prototype.locked = function(el, val) {
756
1313
  el = $(el);
757
- el.each(function (index, el) {
1314
+ el.each(function(index, el) {
758
1315
  el = $(el);
759
1316
  var node = el.data('_gridstack_node');
760
- if (typeof node == 'undefined' || node == null) {
1317
+ if (typeof node == 'undefined' || node === null) {
761
1318
  return;
762
1319
  }
763
1320
 
@@ -767,105 +1324,322 @@
767
1324
  return this;
768
1325
  };
769
1326
 
770
- GridStack.prototype._update_element = function (el, callback) {
1327
+ GridStack.prototype.maxHeight = function(el, val) {
1328
+ el = $(el);
1329
+ el.each(function(index, el) {
1330
+ el = $(el);
1331
+ var node = el.data('_gridstack_node');
1332
+ if (typeof node === 'undefined' || node === null) {
1333
+ return;
1334
+ }
1335
+
1336
+ if (!isNaN(val)) {
1337
+ node.maxHeight = (val || false);
1338
+ el.attr('data-gs-max-height', val);
1339
+ }
1340
+ });
1341
+ return this;
1342
+ };
1343
+
1344
+ GridStack.prototype.minHeight = function(el, val) {
1345
+ el = $(el);
1346
+ el.each(function(index, el) {
1347
+ el = $(el);
1348
+ var node = el.data('_gridstack_node');
1349
+ if (typeof node === 'undefined' || node === null) {
1350
+ return;
1351
+ }
1352
+
1353
+ if (!isNaN(val)) {
1354
+ node.minHeight = (val || false);
1355
+ el.attr('data-gs-min-height', val);
1356
+ }
1357
+ });
1358
+ return this;
1359
+ };
1360
+
1361
+ GridStack.prototype.maxWidth = function(el, val) {
1362
+ el = $(el);
1363
+ el.each(function(index, el) {
1364
+ el = $(el);
1365
+ var node = el.data('_gridstack_node');
1366
+ if (typeof node === 'undefined' || node === null) {
1367
+ return;
1368
+ }
1369
+
1370
+ if (!isNaN(val)) {
1371
+ node.maxWidth = (val || false);
1372
+ el.attr('data-gs-max-width', val);
1373
+ }
1374
+ });
1375
+ return this;
1376
+ };
1377
+
1378
+ GridStack.prototype.minWidth = function(el, val) {
1379
+ el = $(el);
1380
+ el.each(function(index, el) {
1381
+ el = $(el);
1382
+ var node = el.data('_gridstack_node');
1383
+ if (typeof node === 'undefined' || node === null) {
1384
+ return;
1385
+ }
1386
+
1387
+ if (!isNaN(val)) {
1388
+ node.minWidth = (val || false);
1389
+ el.attr('data-gs-min-width', val);
1390
+ }
1391
+ });
1392
+ return this;
1393
+ };
1394
+
1395
+ GridStack.prototype._updateElement = function(el, callback) {
771
1396
  el = $(el).first();
772
1397
  var node = el.data('_gridstack_node');
773
- if (typeof node == 'undefined' || node == null) {
1398
+ if (typeof node == 'undefined' || node === null) {
774
1399
  return;
775
1400
  }
776
1401
 
777
1402
  var self = this;
778
1403
 
779
- self.grid.clean_nodes();
780
- self.grid.begin_update(node);
1404
+ self.grid.cleanNodes();
1405
+ self.grid.beginUpdate(node);
781
1406
 
782
1407
  callback.call(this, el, node);
783
1408
 
784
- self._update_container_height();
785
- var elements = self.grid.get_dirty_nodes();
786
- if (elements && elements.length)
787
- self.container.trigger('change', [elements]);
1409
+ self._updateContainerHeight();
1410
+ self._triggerChangeEvent();
788
1411
 
789
- self.grid.end_update();
1412
+ self.grid.endUpdate();
790
1413
  };
791
1414
 
792
- GridStack.prototype.resize = function (el, width, height) {
793
- this._update_element(el, function (el, node) {
794
- width = (width != null && typeof width != 'undefined') ? width : node.width;
795
- height = (height != null && typeof height != 'undefined') ? height : node.height;
1415
+ GridStack.prototype.resize = function(el, width, height) {
1416
+ this._updateElement(el, function(el, node) {
1417
+ width = (width !== null && typeof width != 'undefined') ? width : node.width;
1418
+ height = (height !== null && typeof height != 'undefined') ? height : node.height;
796
1419
 
797
- this.grid.move_node(node, node.x, node.y, width, height);
1420
+ this.grid.moveNode(node, node.x, node.y, width, height);
798
1421
  });
799
1422
  };
800
1423
 
801
- GridStack.prototype.move = function (el, x, y) {
802
- this._update_element(el, function (el, node) {
803
- x = (x != null && typeof x != 'undefined') ? x : node.x;
804
- y = (y != null && typeof y != 'undefined') ? y : node.y;
1424
+ GridStack.prototype.move = function(el, x, y) {
1425
+ this._updateElement(el, function(el, node) {
1426
+ x = (x !== null && typeof x != 'undefined') ? x : node.x;
1427
+ y = (y !== null && typeof y != 'undefined') ? y : node.y;
805
1428
 
806
- this.grid.move_node(node, x, y, node.width, node.height);
1429
+ this.grid.moveNode(node, x, y, node.width, node.height);
807
1430
  });
808
1431
  };
809
1432
 
810
- GridStack.prototype.update = function (el, x, y, width, height) {
811
- this._update_element(el, function (el, node) {
812
- x = (x != null && typeof x != 'undefined') ? x : node.x;
813
- y = (y != null && typeof y != 'undefined') ? y : node.y;
814
- width = (width != null && typeof width != 'undefined') ? width : node.width;
815
- height = (height != null && typeof height != 'undefined') ? height : node.height;
1433
+ GridStack.prototype.update = function(el, x, y, width, height) {
1434
+ this._updateElement(el, function(el, node) {
1435
+ x = (x !== null && typeof x != 'undefined') ? x : node.x;
1436
+ y = (y !== null && typeof y != 'undefined') ? y : node.y;
1437
+ width = (width !== null && typeof width != 'undefined') ? width : node.width;
1438
+ height = (height !== null && typeof height != 'undefined') ? height : node.height;
816
1439
 
817
- this.grid.move_node(node, x, y, width, height);
1440
+ this.grid.moveNode(node, x, y, width, height);
818
1441
  });
819
1442
  };
820
1443
 
821
- GridStack.prototype.cell_height = function (val) {
1444
+ GridStack.prototype.verticalMargin = function(val, noUpdate) {
822
1445
  if (typeof val == 'undefined') {
823
- return this.opts.cell_height;
1446
+ return this.opts.verticalMargin;
1447
+ }
1448
+
1449
+ var heightData = Utils.parseHeight(val);
1450
+
1451
+ if (this.opts.verticalMarginUnit === heightData.unit && this.opts.height === heightData.height) {
1452
+ return ;
1453
+ }
1454
+ this.opts.verticalMarginUnit = heightData.unit;
1455
+ this.opts.verticalMargin = heightData.height;
1456
+
1457
+ if (!noUpdate) {
1458
+ this._updateStyles();
824
1459
  }
825
- val = parseInt(val);
826
- if (val == this.opts.cell_height)
827
- return;
828
- this.opts.cell_height = val || this.opts.cell_height;
829
- this._update_styles();
830
1460
  };
831
1461
 
832
- GridStack.prototype.cell_width = function () {
833
- var o = this.container.children('.' + this.opts.item_class).first();
834
- return Math.ceil(o.outerWidth() / o.attr('data-gs-width'));
1462
+ GridStack.prototype.cellHeight = function(val, noUpdate) {
1463
+ if (typeof val == 'undefined') {
1464
+ if (this.opts.cellHeight) {
1465
+ return this.opts.cellHeight;
1466
+ }
1467
+ var o = this.container.children('.' + this.opts.itemClass).first();
1468
+ return Math.ceil(o.outerHeight() / o.attr('data-gs-height'));
1469
+ }
1470
+ var heightData = Utils.parseHeight(val);
1471
+
1472
+ if (this.opts.cellHeightUnit === heightData.heightUnit && this.opts.height === heightData.height) {
1473
+ return ;
1474
+ }
1475
+ this.opts.cellHeightUnit = heightData.unit;
1476
+ this.opts.cellHeight = heightData.height;
1477
+
1478
+ if (!noUpdate) {
1479
+ this._updateStyles();
1480
+ }
1481
+
835
1482
  };
836
1483
 
837
- GridStack.prototype.get_cell_from_pixel = function(position) {
838
- var containerPos = this.container.position();
1484
+ GridStack.prototype.cellWidth = function() {
1485
+ var o = this.container.children('.' + this.opts.itemClass).first();
1486
+ return Math.ceil(o.outerWidth() / parseInt(o.attr('data-gs-width'), 10));
1487
+ };
1488
+
1489
+ GridStack.prototype.getCellFromPixel = function(position, useOffset) {
1490
+ var containerPos = (typeof useOffset != 'undefined' && useOffset) ?
1491
+ this.container.offset() : this.container.position();
839
1492
  var relativeLeft = position.left - containerPos.left;
840
1493
  var relativeTop = position.top - containerPos.top;
841
1494
 
842
- var column_width = Math.floor(this.container.width() / this.opts.width);
843
- var row_height = this.opts.cell_height + this.opts.vertical_margin;
1495
+ var columnWidth = Math.floor(this.container.width() / this.opts.width);
1496
+ var rowHeight = Math.floor(this.container.height() / parseInt(this.container.attr('data-gs-current-height')));
844
1497
 
845
- return {x: Math.floor(relativeLeft / column_width), y: Math.floor(relativeTop / row_height)};
1498
+ return {x: Math.floor(relativeLeft / columnWidth), y: Math.floor(relativeTop / rowHeight)};
846
1499
  };
847
1500
 
848
- GridStack.prototype.batch_update = function () {
849
- this.grid.batch_update();
1501
+ GridStack.prototype.batchUpdate = function() {
1502
+ this.grid.batchUpdate();
850
1503
  };
851
1504
 
852
- GridStack.prototype.commit = function () {
1505
+ GridStack.prototype.commit = function() {
853
1506
  this.grid.commit();
854
- this._update_container_height()
1507
+ this._updateContainerHeight();
855
1508
  };
856
1509
 
857
- GridStack.prototype.is_area_empty = function (x, y, width, height) {
858
- return this.grid.is_area_empty(x, y, width, height);
1510
+ GridStack.prototype.isAreaEmpty = function(x, y, width, height) {
1511
+ return this.grid.isAreaEmpty(x, y, width, height);
859
1512
  };
860
1513
 
1514
+ GridStack.prototype.setStatic = function(staticValue) {
1515
+ this.opts.staticGrid = (staticValue === true);
1516
+ this.enableMove(!staticValue);
1517
+ this.enableResize(!staticValue);
1518
+ this._setStaticClass();
1519
+ };
1520
+
1521
+ GridStack.prototype._setStaticClass = function() {
1522
+ var staticClassName = 'grid-stack-static';
1523
+
1524
+ if (this.opts.staticGrid === true) {
1525
+ this.container.addClass(staticClassName);
1526
+ } else {
1527
+ this.container.removeClass(staticClassName);
1528
+ }
1529
+ };
1530
+
1531
+ GridStack.prototype._updateNodeWidths = function(oldWidth, newWidth) {
1532
+ this.grid._sortNodes();
1533
+ this.grid.batchUpdate();
1534
+ var node = {};
1535
+ for (var i = 0; i < this.grid.nodes.length; i++) {
1536
+ node = this.grid.nodes[i];
1537
+ this.update(node.el, Math.round(node.x * newWidth / oldWidth), undefined,
1538
+ Math.round(node.width * newWidth / oldWidth), undefined);
1539
+ }
1540
+ this.grid.commit();
1541
+ };
1542
+
1543
+ GridStack.prototype.setGridWidth = function(gridWidth,doNotPropagate) {
1544
+ this.container.removeClass('grid-stack-' + this.opts.width);
1545
+ if (doNotPropagate !== true) {
1546
+ this._updateNodeWidths(this.opts.width, gridWidth);
1547
+ }
1548
+ this.opts.width = gridWidth;
1549
+ this.grid.width = gridWidth;
1550
+ this.container.addClass('grid-stack-' + gridWidth);
1551
+ };
1552
+
1553
+ // jscs:disable requireCamelCaseOrUpperCaseIdentifiers
1554
+ GridStackEngine.prototype.batch_update = obsolete(GridStackEngine.prototype.batchUpdate);
1555
+ GridStackEngine.prototype._fix_collisions = obsolete(GridStackEngine.prototype._fixCollisions,
1556
+ '_fix_collisions', '_fixCollisions');
1557
+ GridStackEngine.prototype.is_area_empty = obsolete(GridStackEngine.prototype.isAreaEmpty,
1558
+ 'is_area_empty', 'isAreaEmpty');
1559
+ GridStackEngine.prototype._sort_nodes = obsolete(GridStackEngine.prototype._sortNodes,
1560
+ '_sort_nodes', '_sortNodes');
1561
+ GridStackEngine.prototype._pack_nodes = obsolete(GridStackEngine.prototype._packNodes,
1562
+ '_pack_nodes', '_packNodes');
1563
+ GridStackEngine.prototype._prepare_node = obsolete(GridStackEngine.prototype._prepareNode,
1564
+ '_prepare_node', '_prepareNode');
1565
+ GridStackEngine.prototype.clean_nodes = obsolete(GridStackEngine.prototype.cleanNodes,
1566
+ 'clean_nodes', 'cleanNodes');
1567
+ GridStackEngine.prototype.get_dirty_nodes = obsolete(GridStackEngine.prototype.getDirtyNodes,
1568
+ 'get_dirty_nodes', 'getDirtyNodes');
1569
+ GridStackEngine.prototype.add_node = obsolete(GridStackEngine.prototype.addNode,
1570
+ 'add_node', 'addNode, ');
1571
+ GridStackEngine.prototype.remove_node = obsolete(GridStackEngine.prototype.removeNode,
1572
+ 'remove_node', 'removeNode');
1573
+ GridStackEngine.prototype.can_move_node = obsolete(GridStackEngine.prototype.canMoveNode,
1574
+ 'can_move_node', 'canMoveNode');
1575
+ GridStackEngine.prototype.move_node = obsolete(GridStackEngine.prototype.moveNode,
1576
+ 'move_node', 'moveNode');
1577
+ GridStackEngine.prototype.get_grid_height = obsolete(GridStackEngine.prototype.getGridHeight,
1578
+ 'get_grid_height', 'getGridHeight');
1579
+ GridStackEngine.prototype.begin_update = obsolete(GridStackEngine.prototype.beginUpdate,
1580
+ 'begin_update', 'beginUpdate');
1581
+ GridStackEngine.prototype.end_update = obsolete(GridStackEngine.prototype.endUpdate,
1582
+ 'end_update', 'endUpdate');
1583
+ GridStackEngine.prototype.can_be_placed_with_respect_to_height =
1584
+ obsolete(GridStackEngine.prototype.canBePlacedWithRespectToHeight,
1585
+ 'can_be_placed_with_respect_to_height', 'canBePlacedWithRespectToHeight');
1586
+ GridStack.prototype._trigger_change_event = obsolete(GridStack.prototype._triggerChangeEvent,
1587
+ '_trigger_change_event', '_triggerChangeEvent');
1588
+ GridStack.prototype._init_styles = obsolete(GridStack.prototype._initStyles,
1589
+ '_init_styles', '_initStyles');
1590
+ GridStack.prototype._update_styles = obsolete(GridStack.prototype._updateStyles,
1591
+ '_update_styles', '_updateStyles');
1592
+ GridStack.prototype._update_container_height = obsolete(GridStack.prototype._updateContainerHeight,
1593
+ '_update_container_height', '_updateContainerHeight');
1594
+ GridStack.prototype._is_one_column_mode = obsolete(GridStack.prototype._isOneColumnMode,
1595
+ '_is_one_column_mode','_isOneColumnMode');
1596
+ GridStack.prototype._prepare_element = obsolete(GridStack.prototype._prepareElement,
1597
+ '_prepare_element', '_prepareElement');
1598
+ GridStack.prototype.set_animation = obsolete(GridStack.prototype.setAnimation,
1599
+ 'set_animation', 'setAnimation');
1600
+ GridStack.prototype.add_widget = obsolete(GridStack.prototype.addWidget,
1601
+ 'add_widget', 'addWidget');
1602
+ GridStack.prototype.make_widget = obsolete(GridStack.prototype.makeWidget,
1603
+ 'make_widget', 'makeWidget');
1604
+ GridStack.prototype.will_it_fit = obsolete(GridStack.prototype.willItFit,
1605
+ 'will_it_fit', 'willItFit');
1606
+ GridStack.prototype.remove_widget = obsolete(GridStack.prototype.removeWidget,
1607
+ 'remove_widget', 'removeWidget');
1608
+ GridStack.prototype.remove_all = obsolete(GridStack.prototype.removeAll,
1609
+ 'remove_all', 'removeAll');
1610
+ GridStack.prototype.min_height = obsolete(GridStack.prototype.minHeight,
1611
+ 'min_height', 'minHeight');
1612
+ GridStack.prototype.min_width = obsolete(GridStack.prototype.minWidth,
1613
+ 'min_width', 'minWidth');
1614
+ GridStack.prototype._update_element = obsolete(GridStack.prototype._updateElement,
1615
+ '_update_element', '_updateElement');
1616
+ GridStack.prototype.cell_height = obsolete(GridStack.prototype.cellHeight,
1617
+ 'cell_height', 'cellHeight');
1618
+ GridStack.prototype.cell_width = obsolete(GridStack.prototype.cellWidth,
1619
+ 'cell_width', 'cellWidth');
1620
+ GridStack.prototype.get_cell_from_pixel = obsolete(GridStack.prototype.getCellFromPixel,
1621
+ 'get_cell_from_pixel', 'getCellFromPixel');
1622
+ GridStack.prototype.batch_update = obsolete(GridStack.prototype.batchUpdate,
1623
+ 'batch_update', 'batchUpdate');
1624
+ GridStack.prototype.is_area_empty = obsolete(GridStack.prototype.isAreaEmpty,
1625
+ 'is_area_empty', 'isAreaEmpty');
1626
+ GridStack.prototype.set_static = obsolete(GridStack.prototype.setStatic,
1627
+ 'set_static', 'setStatic');
1628
+ GridStack.prototype._set_static_class = obsolete(GridStack.prototype._setStaticClass,
1629
+ '_set_static_class', '_setStaticClass');
1630
+ // jscs:enable requireCamelCaseOrUpperCaseIdentifiers
1631
+
861
1632
  scope.GridStackUI = GridStack;
862
1633
 
863
1634
  scope.GridStackUI.Utils = Utils;
1635
+ scope.GridStackUI.Engine = GridStackEngine;
864
1636
 
865
- $.fn.gridstack = function (opts) {
866
- return this.each(function () {
867
- if (!$(this).data('gridstack')) {
868
- $(this).data('gridstack', new GridStack(this, opts));
1637
+ $.fn.gridstack = function(opts) {
1638
+ return this.each(function() {
1639
+ var o = $(this);
1640
+ if (!o.data('gridstack')) {
1641
+ o
1642
+ .data('gridstack', new GridStack(this, opts));
869
1643
  }
870
1644
  });
871
1645
  };