gridstack-rails 0.3.0

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