gridstack-js-rails 0.2.3

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,21 @@
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
+ .idea
21
+ .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,132 @@
1
+ # gridstack-js-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-js-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-js-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
+ # To add a specific version:
41
+ gem 'gridstack-js-rails', github: 'randoum/gridstack-js-rails', tag: 'v0.2.3'
42
+
43
+ # OR to use the latest development version:
44
+ gem 'gridstack-js-rails', github: 'randoum/gridstack-js-rails'
45
+ ```
46
+
47
+ And then execute:
48
+
49
+ ```bash
50
+ bundle
51
+ ```
52
+
53
+ And restart your server
54
+
55
+ # Dependencies
56
+
57
+ ### Default
58
+
59
+ By default gridstack-js-rails will include the following javascripts libraries:
60
+
61
+ - lodash
62
+ - jquery-ui: core, widget, mouse, draggable, and resizable modules
63
+ - gridstack.js
64
+
65
+ Along with the following stylesheets files:
66
+
67
+ - jquery-ui: core, draggable, and resizable modules
68
+ - gridstack.js
69
+
70
+ To integrate gridstack.js and its default dependencies, add to your javascript manifest file:
71
+
72
+ ```
73
+ //= require gridstack-js-rails
74
+ ```
75
+
76
+ And add to your stylesheet manifest file:
77
+
78
+ ```
79
+ /*
80
+ *= require gridstack-js-rails
81
+ */
82
+ ```
83
+
84
+ ### With underscore.js
85
+
86
+ To integrate the default library but to use underscore.js in place of lodash, add to your javascript manifest file:
87
+
88
+ ```
89
+ //= require gridstack-js-rails-underscore
90
+ ```
91
+
92
+ And add to your stylesheet manifest file:
93
+
94
+ ```
95
+ /*
96
+ *= require gridstack-js-rails
97
+ */
98
+ ```
99
+
100
+ ### Without dependencies
101
+
102
+ If you want to integrate the dependencies manually, and need only the gridstack.js library, add to your javascript manifest file:
103
+
104
+ ```
105
+ //= require gridstack/gridstack
106
+ ```
107
+
108
+ And add to your stylesheet manifest file:
109
+
110
+ ```
111
+ /*
112
+ *= require gridstack/gridstack
113
+ */
114
+ ```
115
+
116
+ ### Gridstack extra css styles
117
+
118
+ You can also add the gridstack-extra css styles by adding to your stylesheet manifest file:
119
+
120
+ ```
121
+ /*
122
+ *= require gridstack/gridstack-extra
123
+ */
124
+ ```
125
+
126
+ # Contributing
127
+
128
+ 1. Fork it
129
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
130
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
131
+ 4. Push to the branch (`git push origin my-new-feature`)
132
+ 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-js-rails/rails/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'gridstack-js-rails'
8
+ spec.version = GridstackJs::Rails::VERSION
9
+ spec.authors = ['randoum']
10
+ spec.email = ['randoum@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/randoum/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-js-rails/rails'
2
+
3
+ module GridstackJs
4
+ require 'lodash/rails/engine'
5
+ require 'underscore-rails'
6
+ end
@@ -0,0 +1,2 @@
1
+ require 'gridstack-js-rails/rails/engine' if ::Rails.version >= '3.1'
2
+ require 'gridstack-js-rails/rails/version'
@@ -0,0 +1,6 @@
1
+ module GridstackJs
2
+ module Rails
3
+ class Engine < ::Rails::Engine
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,5 @@
1
+ module GridstackJs
2
+ module Rails
3
+ VERSION = '0.2.3'
4
+ end
5
+ end
@@ -0,0 +1,7 @@
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
@@ -0,0 +1,7 @@
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
@@ -0,0 +1,874 @@
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) {
7
+ 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 {
11
+ factory(jQuery, _);
12
+ }
13
+ })(function ($, _) {
14
+
15
+ var scope = window;
16
+
17
+ var Utils = {
18
+ is_intercepted: function (a, b) {
19
+ 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
+ },
21
+
22
+ sort: function (nodes, dir, width) {
23
+ width = width || _.chain(nodes).map(function (node) { return node.x + node.width; }).max().value();
24
+ dir = dir != -1 ? 1 : -1;
25
+ return _.sortBy(nodes, function (n) { return dir * (n.x + n.y * width); });
26
+ },
27
+
28
+ create_stylesheet: function (id) {
29
+ var style = document.createElement("style");
30
+ style.setAttribute("type", "text/css");
31
+ style.setAttribute("data-gs-id", id);
32
+ if (style.styleSheet) {
33
+ style.styleSheet.cssText = "";
34
+ }
35
+ else {
36
+ style.appendChild(document.createTextNode(""));
37
+ }
38
+ document.getElementsByTagName('head')[0].appendChild(style);
39
+ return style.sheet;
40
+ },
41
+
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') {
47
+ sheet.addRule(selector, rules, index);
48
+ }
49
+ },
50
+
51
+ toBool: function (v) {
52
+ if (typeof v == 'boolean')
53
+ return v;
54
+ if (typeof v == 'string') {
55
+ v = v.toLowerCase();
56
+ return !(v == '' || v == 'no' || v == 'false' || v == '0');
57
+ }
58
+ return Boolean(v);
59
+ }
60
+ };
61
+
62
+ var id_seq = 0;
63
+
64
+ var GridStackEngine = function (width, onchange, float, height, items) {
65
+ this.width = width;
66
+ this.float = float || false;
67
+ this.height = height || 0;
68
+
69
+ this.nodes = items || [];
70
+ this.onchange = onchange || function () {};
71
+
72
+ this._update_counter = 0;
73
+ this._float = this.float;
74
+ };
75
+
76
+ GridStackEngine.prototype.batch_update = function () {
77
+ this._update_counter = 1;
78
+ this.float = true;
79
+ };
80
+
81
+ GridStackEngine.prototype.commit = function () {
82
+ this._update_counter = 0;
83
+ if (this._update_counter == 0) {
84
+ this.float = this._float;
85
+ this._pack_nodes();
86
+ this._notify();
87
+ }
88
+ };
89
+
90
+ GridStackEngine.prototype._fix_collisions = function (node) {
91
+ this._sort_nodes(-1);
92
+
93
+ var nn = node, has_locked = Boolean(_.find(this.nodes, function (n) { return n.locked }));
94
+ if (!this.float && !has_locked) {
95
+ nn = {x: 0, y: node.y, width: this.width, height: node.height};
96
+ }
97
+
98
+ 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') {
103
+ return;
104
+ }
105
+ this.move_node(collision_node, collision_node.x, node.y + node.height,
106
+ collision_node.width, collision_node.height, true);
107
+ }
108
+ };
109
+
110
+ GridStackEngine.prototype.is_area_empty = function (x, y, width, height) {
111
+ 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;
116
+ };
117
+
118
+ GridStackEngine.prototype._sort_nodes = function (dir) {
119
+ this.nodes = Utils.sort(this.nodes, dir, this.width);
120
+ };
121
+
122
+ GridStackEngine.prototype._pack_nodes = function () {
123
+ this._sort_nodes();
124
+
125
+ if (this.float) {
126
+ _.each(this.nodes, function (n, i) {
127
+ if (n._updating || typeof n._orig_y == 'undefined' || n.y == n._orig_y)
128
+ return;
129
+
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
+ })
136
+ .value();
137
+
138
+ if (!collision_node) {
139
+ n._dirty = true;
140
+ n.y = new_y;
141
+ }
142
+ --new_y;
143
+ }
144
+ }, this);
145
+ }
146
+ else {
147
+ _.each(this.nodes, function (n, i) {
148
+ if (n.locked)
149
+ return;
150
+ while (n.y > 0) {
151
+ var new_y = n.y - 1;
152
+ var can_be_moved = i == 0;
153
+
154
+ if (i > 0) {
155
+ var collision_node = _.chain(this.nodes)
156
+ .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
+ })
160
+ .value();
161
+ can_be_moved = typeof collision_node == 'undefined';
162
+ }
163
+
164
+ if (!can_be_moved) {
165
+ break;
166
+ }
167
+ n._dirty = n.y != new_y;
168
+ n.y = new_y;
169
+ }
170
+ }, this);
171
+ }
172
+ };
173
+
174
+ GridStackEngine.prototype._prepare_node = function (node, resizing) {
175
+ node = _.defaults(node || {}, {width: 1, height: 1, x: 0, y: 0 });
176
+
177
+ node.x = parseInt('' + node.x);
178
+ node.y = parseInt('' + node.y);
179
+ node.width = parseInt('' + node.width);
180
+ 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;
184
+
185
+ if (node.width > this.width) {
186
+ node.width = this.width;
187
+ }
188
+ else if (node.width < 1) {
189
+ node.width = 1;
190
+ }
191
+
192
+ if (node.height < 1) {
193
+ node.height = 1;
194
+ }
195
+
196
+ if (node.x < 0) {
197
+ node.x = 0;
198
+ }
199
+
200
+ if (node.x + node.width > this.width) {
201
+ if (resizing) {
202
+ node.width = this.width - node.x;
203
+ }
204
+ else {
205
+ node.x = this.width - node.width;
206
+ }
207
+ }
208
+
209
+ if (node.y < 0) {
210
+ node.y = 0;
211
+ }
212
+
213
+ return node;
214
+ };
215
+
216
+ GridStackEngine.prototype._notify = function () {
217
+ if (this._update_counter) {
218
+ return;
219
+ }
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);
223
+ };
224
+
225
+ GridStackEngine.prototype.clean_nodes = function () {
226
+ _.each(this.nodes, function (n) {n._dirty = false });
227
+ };
228
+
229
+ GridStackEngine.prototype.get_dirty_nodes = function () {
230
+ return _.filter(this.nodes, function (n) { return n._dirty; });
231
+ };
232
+
233
+ GridStackEngine.prototype.add_node = function(node) {
234
+ node = this._prepare_node(node);
235
+
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);
240
+
241
+ node._id = ++id_seq;
242
+ node._dirty = true;
243
+
244
+ if (node.auto_position) {
245
+ this._sort_nodes();
246
+
247
+ for (var i = 0; ; ++i) {
248
+ var x = i % this.width, y = Math.floor(i / this.width);
249
+ if (x + node.width > this.width) {
250
+ continue;
251
+ }
252
+ if (!_.find(this.nodes, function (n) {
253
+ return Utils.is_intercepted({x: x, y: y, width: node.width, height: node.height}, n);
254
+ })) {
255
+ node.x = x;
256
+ node.y = y;
257
+ break;
258
+ }
259
+ }
260
+ }
261
+
262
+ this.nodes.push(node);
263
+
264
+ this._fix_collisions(node);
265
+ this._pack_nodes();
266
+ this._notify();
267
+ return node;
268
+ };
269
+
270
+ GridStackEngine.prototype.remove_node = function (node) {
271
+ node._id = null;
272
+ this.nodes = _.without(this.nodes, node);
273
+ this._pack_nodes();
274
+ this._notify(node);
275
+ };
276
+
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 }));
279
+
280
+ if (!this.height && !has_locked)
281
+ return true;
282
+
283
+ var cloned_node;
284
+ var clone = new GridStackEngine(
285
+ this.width,
286
+ null,
287
+ this.float,
288
+ 0,
289
+ _.map(this.nodes, function (n) { if (n == node) { cloned_node = $.extend({}, n); return cloned_node; } return $.extend({}, n) }));
290
+
291
+ clone.move_node(cloned_node, x, y, width, height);
292
+
293
+ var res = true;
294
+
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;
299
+
300
+ return res;
301
+ };
302
+
303
+ GridStackEngine.prototype.can_be_placed_with_respect_to_height = function (node) {
304
+ if (!this.height)
305
+ return true;
306
+
307
+ var clone = new GridStackEngine(
308
+ this.width,
309
+ null,
310
+ this.float,
311
+ 0,
312
+ _.map(this.nodes, function (n) { return $.extend({}, n) }));
313
+ clone.add_node(node);
314
+ return clone.get_grid_height() <= this.height;
315
+ };
316
+
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;
322
+
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);
327
+
328
+ if (node.x == x && node.y == y && node.width == width && node.height == height) {
329
+ return node;
330
+ }
331
+
332
+ var resizing = node.width != width;
333
+ node._dirty = true;
334
+
335
+ node.x = x;
336
+ node.y = y;
337
+ node.width = width;
338
+ node.height = height;
339
+
340
+ node = this._prepare_node(node, resizing);
341
+
342
+ this._fix_collisions(node);
343
+ if (!no_pack) {
344
+ this._pack_nodes();
345
+ this._notify();
346
+ }
347
+ return node;
348
+ };
349
+
350
+ GridStackEngine.prototype.get_grid_height = function () {
351
+ return _.reduce(this.nodes, function (memo, n) { return Math.max(memo, n.y + n.height); }, 0);
352
+ };
353
+
354
+ GridStackEngine.prototype.begin_update = function (node) {
355
+ _.each(this.nodes, function (n) {
356
+ n._orig_y = n.y;
357
+ });
358
+ node._updating = true;
359
+ };
360
+
361
+ GridStackEngine.prototype.end_update = function () {
362
+ _.each(this.nodes, function (n) {
363
+ n._orig_y = n.y;
364
+ });
365
+ var n = _.find(this.nodes, function (n) { return n._updating; });
366
+ if (n) {
367
+ n._updating = false;
368
+ }
369
+ };
370
+
371
+ var GridStack = function (el, opts) {
372
+ var self = this, one_column_mode;
373
+
374
+ this.container = $(el);
375
+
376
+ opts.item_class = opts.item_class || 'grid-stack-item';
377
+ var is_nested = this.container.closest('.' + opts.item_class).size() > 0;
378
+
379
+ this.opts = _.defaults(opts || {}, {
380
+ width: parseInt(this.container.attr('data-gs-width')) || 12,
381
+ height: parseInt(this.container.attr('data-gs-height')) || 0,
382
+ item_class: 'grid-stack-item',
383
+ placeholder_class: 'grid-stack-placeholder',
384
+ handle: '.grid-stack-item-content',
385
+ cell_height: 60,
386
+ vertical_margin: 20,
387
+ auto: true,
388
+ min_width: 768,
389
+ float: false,
390
+ _class: 'grid-stack-' + (Math.random() * 10000).toFixed(0),
391
+ animate: Boolean(this.container.attr('data-gs-animate')) || false,
392
+ always_show_resize_handle: opts.always_show_resize_handle || false,
393
+ resizable: _.defaults(opts.resizable || {}, {
394
+ autoHide: !(opts.always_show_resize_handle || false),
395
+ handles: 'se'
396
+ }),
397
+ draggable: _.defaults(opts.draggable || {}, {
398
+ handle: '.grid-stack-item-content',
399
+ scroll: false,
400
+ appendTo: 'body'
401
+ })
402
+ });
403
+ this.opts.is_nested = is_nested;
404
+
405
+ this.container.addClass(this.opts._class);
406
+ if (is_nested) {
407
+ this.container.addClass('grid-stack-nested');
408
+ }
409
+
410
+ this._init_styles();
411
+
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 {
419
+ n.el
420
+ .attr('data-gs-x', n.x)
421
+ .attr('data-gs-y', n.y)
422
+ .attr('data-gs-width', n.width)
423
+ .attr('data-gs-height', n.height);
424
+ max_height = Math.max(max_height, n.y + n.height);
425
+ }
426
+ });
427
+ self._update_styles(max_height + 10);
428
+ }, this.opts.float, this.opts.height);
429
+
430
+ if (this.opts.auto) {
431
+ var elements = [];
432
+ 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
438
+ });
439
+ });
440
+ _.chain(elements).sortBy(function (x) { return x.i; }).each(function (i) {
441
+ self._prepare_element(i.el);
442
+ }).value();
443
+ }
444
+
445
+ this.set_animation(this.opts.animate);
446
+
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);
449
+
450
+ var on_resize_handler = function () {
451
+ if (self._is_one_column_mode()) {
452
+ if (one_column_mode)
453
+ return;
454
+
455
+ one_column_mode = true;
456
+
457
+ self.grid._sort_nodes();
458
+ _.each(self.grid.nodes, function (node) {
459
+ self.container.append(node.el);
460
+
461
+ if (!node.no_move) {
462
+ node.el.draggable('disable');
463
+ }
464
+ if (!node.no_resize) {
465
+ node.el.resizable('disable');
466
+ }
467
+ });
468
+ }
469
+ else {
470
+ if (!one_column_mode)
471
+ return;
472
+
473
+ one_column_mode = false;
474
+
475
+ _.each(self.grid.nodes, function (node) {
476
+ if (!node.no_move) {
477
+ node.el.draggable('enable');
478
+ }
479
+ if (!node.no_resize) {
480
+ node.el.resizable('enable');
481
+ }
482
+ });
483
+ }
484
+ };
485
+
486
+ $(window).resize(on_resize_handler);
487
+ on_resize_handler();
488
+ };
489
+
490
+ GridStack.prototype._init_styles = function () {
491
+ if (this._styles_id) {
492
+ $('[data-gs-id="' + this._styles_id + '"]').remove();
493
+ }
494
+ this._styles_id = 'gridstack-style-' + (Math.random() * 100000).toFixed();
495
+ this._styles = Utils.create_stylesheet(this._styles_id);
496
+ if (this._styles != null)
497
+ this._styles._max = 0;
498
+ };
499
+
500
+ GridStack.prototype._update_styles = function (max_height) {
501
+ if (this._styles == null) {
502
+ return;
503
+ }
504
+
505
+ var prefix = '.' + this.opts._class + ' .' + this.opts.item_class;
506
+
507
+ if (typeof max_height == 'undefined') {
508
+ max_height = this._styles._max;
509
+ this._init_styles();
510
+ this._update_container_height();
511
+ }
512
+
513
+ if (this._styles._max == 0) {
514
+ Utils.insert_css_rule(this._styles, prefix, 'min-height: ' + (this.opts.cell_height) + 'px;', 0);
515
+ }
516
+
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,
520
+ prefix + '[data-gs-height="' + (i + 1) + '"]',
521
+ 'height: ' + (this.opts.cell_height * (i + 1) + this.opts.vertical_margin * i) + 'px;',
522
+ i
523
+ );
524
+ Utils.insert_css_rule(this._styles,
525
+ prefix + '[data-gs-min-height="' + (i + 1) + '"]',
526
+ 'min-height: ' + (this.opts.cell_height * (i + 1) + this.opts.vertical_margin * i) + 'px;',
527
+ i
528
+ );
529
+ Utils.insert_css_rule(this._styles,
530
+ prefix + '[data-gs-max-height="' + (i + 1) + '"]',
531
+ 'max-height: ' + (this.opts.cell_height * (i + 1) + this.opts.vertical_margin * i) + 'px;',
532
+ i
533
+ );
534
+ Utils.insert_css_rule(this._styles,
535
+ prefix + '[data-gs-y="' + i + '"]',
536
+ 'top: ' + (this.opts.cell_height * i + this.opts.vertical_margin * i) + 'px;',
537
+ i
538
+ );
539
+ }
540
+ this._styles._max = max_height;
541
+ }
542
+ };
543
+
544
+ GridStack.prototype._update_container_height = function () {
545
+ if (this.grid._update_counter) {
546
+ return;
547
+ }
548
+ this.container.height(this.grid.get_grid_height() * (this.opts.cell_height + this.opts.vertical_margin) - this.opts.vertical_margin);
549
+ };
550
+
551
+ GridStack.prototype._is_one_column_mode = function () {
552
+ return (window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth) <= this.opts.min_width;
553
+ };
554
+
555
+ GridStack.prototype._prepare_element = function (el) {
556
+ var self = this;
557
+ el = $(el);
558
+
559
+ el.addClass(this.opts.item_class);
560
+
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);
577
+
578
+ var cell_width, cell_height;
579
+
580
+ var on_start_moving = function (event, ui) {
581
+ self.container.append(self.placeholder);
582
+ 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;
587
+ self.placeholder
588
+ .attr('data-gs-x', o.attr('data-gs-x'))
589
+ .attr('data-gs-y', o.attr('data-gs-y'))
590
+ .attr('data-gs-width', o.attr('data-gs-width'))
591
+ .attr('data-gs-height', o.attr('data-gs-height'))
592
+ .show();
593
+ node.el = self.placeholder;
594
+
595
+ el.resizable('option', 'minWidth', cell_width * (node.min_width || 1));
596
+ el.resizable('option', 'minHeight', self.opts.cell_height * (node.min_height || 1));
597
+ };
598
+
599
+ var on_end_moving = function (event, ui) {
600
+ self.placeholder.detach();
601
+ var o = $(this);
602
+ node.el = o;
603
+ 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
+
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;
641
+ }
642
+ self.grid.move_node(node, x, y, width, height);
643
+ self._update_container_height();
644
+ }
645
+ }));
646
+
647
+ if (node.no_move || this._is_one_column_mode()) {
648
+ el.draggable('disable');
649
+ }
650
+
651
+ if (node.no_resize || this._is_one_column_mode()) {
652
+ el.resizable('disable');
653
+ }
654
+
655
+ el.attr('data-gs-locked', node.locked ? 'yes' : null);
656
+ };
657
+
658
+ GridStack.prototype.set_animation = function (enable) {
659
+ if (enable) {
660
+ this.container.addClass('grid-stack-animate');
661
+ }
662
+ else {
663
+ this.container.removeClass('grid-stack-animate');
664
+ }
665
+ };
666
+
667
+ GridStack.prototype.add_widget = function (el, x, y, width, height, auto_position) {
668
+ 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);
674
+ this.container.append(el);
675
+ this._prepare_element(el);
676
+ this._update_container_height();
677
+
678
+ return el;
679
+ };
680
+
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);
684
+ };
685
+
686
+ GridStack.prototype.remove_widget = function (el, detach_node) {
687
+ detach_node = typeof detach_node === 'undefined' ? true : detach_node;
688
+ el = $(el);
689
+ var node = el.data('_gridstack_node');
690
+ this.grid.remove_node(node);
691
+ el.removeData('_gridstack_node');
692
+ this._update_container_height();
693
+ if (detach_node)
694
+ el.remove();
695
+ };
696
+
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);
701
+ this.grid.nodes = [];
702
+ this._update_container_height();
703
+ };
704
+
705
+ GridStack.prototype.resizable = function (el, val) {
706
+ el = $(el);
707
+ el.each(function (index, el) {
708
+ el = $(el);
709
+ var node = el.data('_gridstack_node');
710
+ if (typeof node == 'undefined' || node == null) {
711
+ return;
712
+ }
713
+
714
+ node.no_resize = !(val || false);
715
+ if (node.no_resize) {
716
+ el.resizable('disable');
717
+ }
718
+ else {
719
+ el.resizable('enable');
720
+ }
721
+ });
722
+ return this;
723
+ };
724
+
725
+ GridStack.prototype.movable = function (el, val) {
726
+ el = $(el);
727
+ el.each(function (index, el) {
728
+ el = $(el);
729
+ var node = el.data('_gridstack_node');
730
+ if (typeof node == 'undefined' || node == null) {
731
+ return;
732
+ }
733
+
734
+ node.no_move = !(val || false);
735
+ if (node.no_move) {
736
+ el.draggable('disable');
737
+ }
738
+ else {
739
+ el.draggable('enable');
740
+ }
741
+ });
742
+ return this;
743
+ };
744
+
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);
748
+ };
749
+
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);
753
+ };
754
+
755
+ GridStack.prototype.locked = function (el, val) {
756
+ el = $(el);
757
+ el.each(function (index, el) {
758
+ el = $(el);
759
+ var node = el.data('_gridstack_node');
760
+ if (typeof node == 'undefined' || node == null) {
761
+ return;
762
+ }
763
+
764
+ node.locked = (val || false);
765
+ el.attr('data-gs-locked', node.locked ? 'yes' : null);
766
+ });
767
+ return this;
768
+ };
769
+
770
+ GridStack.prototype._update_element = function (el, callback) {
771
+ el = $(el).first();
772
+ var node = el.data('_gridstack_node');
773
+ if (typeof node == 'undefined' || node == null) {
774
+ return;
775
+ }
776
+
777
+ var self = this;
778
+
779
+ self.grid.clean_nodes();
780
+ self.grid.begin_update(node);
781
+
782
+ callback.call(this, el, node);
783
+
784
+ self._update_container_height();
785
+ var elements = self.grid.get_dirty_nodes();
786
+ if (elements && elements.length)
787
+ self.container.trigger('change', [elements]);
788
+
789
+ self.grid.end_update();
790
+ };
791
+
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;
796
+
797
+ this.grid.move_node(node, node.x, node.y, width, height);
798
+ });
799
+ };
800
+
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;
805
+
806
+ this.grid.move_node(node, x, y, node.width, node.height);
807
+ });
808
+ };
809
+
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;
816
+
817
+ this.grid.move_node(node, x, y, width, height);
818
+ });
819
+ };
820
+
821
+ GridStack.prototype.cell_height = function (val) {
822
+ if (typeof val == 'undefined') {
823
+ return this.opts.cell_height;
824
+ }
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
+ };
831
+
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'));
835
+ };
836
+
837
+ GridStack.prototype.get_cell_from_pixel = function(position) {
838
+ var containerPos = this.container.position();
839
+ var relativeLeft = position.left - containerPos.left;
840
+ var relativeTop = position.top - containerPos.top;
841
+
842
+ var column_width = Math.floor(this.container.width() / this.opts.width);
843
+ var row_height = this.opts.cell_height + this.opts.vertical_margin;
844
+
845
+ return {x: Math.floor(relativeLeft / column_width), y: Math.floor(relativeTop / row_height)};
846
+ };
847
+
848
+ GridStack.prototype.batch_update = function () {
849
+ this.grid.batch_update();
850
+ };
851
+
852
+ GridStack.prototype.commit = function () {
853
+ this.grid.commit();
854
+ this._update_container_height()
855
+ };
856
+
857
+ GridStack.prototype.is_area_empty = function (x, y, width, height) {
858
+ return this.grid.is_area_empty(x, y, width, height);
859
+ };
860
+
861
+ scope.GridStackUI = GridStack;
862
+
863
+ scope.GridStackUI.Utils = Utils;
864
+
865
+ $.fn.gridstack = function (opts) {
866
+ return this.each(function () {
867
+ if (!$(this).data('gridstack')) {
868
+ $(this).data('gridstack', new GridStack(this, opts));
869
+ }
870
+ });
871
+ };
872
+
873
+ return scope.GridStackUI;
874
+ });