Skip to content

Commit 37c4e94

Browse files
committed
feat(gridster): increase grid width when dragging or resizing
1 parent d4482ec commit 37c4e94

File tree

2 files changed

+126
-53
lines changed

2 files changed

+126
-53
lines changed

src/jquery.gridster.css

+5-5
Original file line numberDiff line numberDiff line change
@@ -4,11 +4,11 @@
44

55
.gridster > * {
66
margin: 0 auto;
7-
-webkit-transition: height .4s;
8-
-moz-transition: height .4s;
9-
-o-transition: height .4s;
10-
-ms-transition: height .4s;
11-
transition: height .4s;
7+
-webkit-transition: height .4s, width .4s;
8+
-moz-transition: height .4s, width .4s;
9+
-o-transition: height .4s, width .4s;
10+
-ms-transition: height .4s, width .4s;
11+
transition: height .4s, width .4s;
1212
}
1313

1414
.gridster .gs-w {

src/jquery.gridster.js

+121-48
Original file line numberDiff line numberDiff line change
@@ -15,9 +15,10 @@
1515
extra_rows: 0,
1616
extra_cols: 0,
1717
min_cols: 1,
18-
max_cols: null,
18+
max_cols: Infinity,
1919
min_rows: 15,
2020
max_size_x: false,
21+
autogrow_cols: false,
2122
autogenerate_stylesheet: true,
2223
avoid_overlapped_widgets: true,
2324
serialize_params: function($w, wgd) {
@@ -137,6 +138,7 @@
137138
this.generate_grid_and_stylesheet();
138139
this.get_widgets_from_DOM();
139140
this.set_dom_grid_height();
141+
this.set_dom_grid_width();
140142
this.$wrapper.addClass('ready');
141143
this.draggable();
142144
this.options.resize.enabled && this.resizable();
@@ -298,38 +300,36 @@
298300
* @param {HTMLElement} $widget The jQuery wrapped HTMLElement
299301
* representing the widget.
300302
* @param {Number} size_x The number of columns that will occupy the widget.
301-
* @param {Number} size_y The number of rows that will occupy the widget.
302-
* @param {Boolean} [reposition] Set to false to not move the widget to
303-
* the left if there is insufficient space on the right.
304303
* By default <code>size_x</code> is limited to the space available from
305304
* the column where the widget begins, until the last column to the right.
305+
* @param {Number} size_y The number of rows that will occupy the widget.
306306
* @param {Function} [callback] Function executed when the widget is removed.
307307
* @return {HTMLElement} Returns $widget.
308308
*/
309-
fn.resize_widget = function($widget, size_x, size_y, reposition, callback) {
309+
fn.resize_widget = function($widget, size_x, size_y, callback) {
310310
var wgd = $widget.coords().grid;
311-
reposition !== false && (reposition = true);
312-
size_x || (size_x = wgd.size_x);
313-
size_y || (size_y = wgd.size_y);
314-
315-
if (size_x > this.cols) {
316-
size_x = this.cols;
317-
}
318-
311+
var col = wgd.col;
312+
var max_cols = this.options.max_cols;
319313
var old_size_y = wgd.size_y;
320314
var old_col = wgd.col;
321315
var new_col = old_col;
322316

323-
if (reposition && old_col + size_x - 1 > this.cols) {
324-
var diff = old_col + (size_x - 1) - this.cols;
325-
var c = old_col - diff;
326-
new_col = Math.max(1, c);
317+
size_x || (size_x = wgd.size_x);
318+
size_y || (size_y = wgd.size_y);
319+
320+
if (max_cols !== Infinity) {
321+
size_x = Math.min(size_x, max_cols - col + 1);
327322
}
328323

329324
if (size_y > old_size_y) {
330325
this.add_faux_rows(Math.max(size_y - old_size_y, 0));
331326
}
332327

328+
var player_rcol = (col + size_x - 1);
329+
if (player_rcol > this.cols) {
330+
this.add_faux_cols(player_rcol - this.cols);
331+
}
332+
333333
var new_grid_data = {
334334
col: new_col,
335335
row: wgd.row,
@@ -340,6 +340,7 @@
340340
this.mutate_widget_in_gridmap($widget, wgd, new_grid_data);
341341

342342
this.set_dom_grid_height();
343+
this.set_dom_grid_width();
343344

344345
if (callback) {
345346
callback.call(this, new_grid_data.size_x, new_grid_data.size_y);
@@ -776,7 +777,9 @@
776777
var self = this;
777778
var draggable_options = $.extend(true, {}, this.options.draggable, {
778779
offset_left: this.options.widget_margins[0],
780+
offset_top: this.options.widget_margins[1],
779781
container_width: this.container_width,
782+
limit: true,
780783
ignore_dragging: ['INPUT', 'TEXTAREA', 'SELECT', 'BUTTON',
781784
'.' + this.options.resize.handle_class],
782785
start: function(event, ui) {
@@ -818,6 +821,8 @@
818821
offset_left: this.options.widget_margins[0],
819822
container_width: this.container_width,
820823
move_element: false,
824+
resize: true,
825+
limit: this.options.autogrow_cols ? false : true,
821826
start: $.proxy(this.on_start_resize, this),
822827
stop: $.proxy(function(event, ui) {
823828
delay($.proxy(function() {
@@ -860,13 +865,22 @@
860865
fn.on_start_drag = function(event, ui) {
861866
this.$helper.add(this.$player).add(this.$wrapper).addClass('dragging');
862867

868+
this.highest_col = this.get_highest_occupied_cell().col;
869+
863870
this.$player.addClass('player');
864871
this.player_grid_data = this.$player.coords().grid;
865872
this.placeholder_grid_data = $.extend({}, this.player_grid_data);
866873

867-
//set new grid height along the dragging period
868-
this.$el.css('height', this.$el.height() +
869-
(this.player_grid_data.size_y * this.min_widget_height));
874+
this.set_dom_grid_height(this.$el.height() +
875+
(this.player_grid_data.size_y * this.min_widget_height));
876+
877+
this.set_dom_grid_width(this.highest_col + 1);
878+
879+
// auto grow cols
880+
var cols_diff = this.cols - this.highest_col;
881+
if (cols_diff < this.player_grid_data.size_x) {
882+
this.add_faux_cols(this.player_grid_data.size_x - cols_diff);
883+
}
870884

871885
var colliders = this.faux_grid;
872886
var coords = this.$player.data('coords').coords;
@@ -930,6 +944,19 @@
930944
this.on_stop_overlapping_row
931945
);
932946

947+
//auto grow cols
948+
if (this.options.autogrow_cols) {
949+
var prcol = this.placeholder_grid_data.col +
950+
this.placeholder_grid_data.size_x - 1;
951+
if (prcol === this.highest_col) {
952+
if (prcol < this.cols) {
953+
this.set_dom_grid_width(prcol + 1);
954+
}
955+
this.highest_col = prcol + 1;
956+
this.drag_api.set_limits(this.container_width);
957+
}
958+
}
959+
933960
if (this.helper && this.$player) {
934961
this.$player.css({
935962
'left': ui.position.left,
@@ -1001,6 +1028,11 @@
10011028
this.cells_occupied_by_player = {};
10021029

10031030
this.set_dom_grid_height();
1031+
this.set_dom_grid_width();
1032+
1033+
if (this.options.autogrow_cols) {
1034+
this.drag_api.set_limits(this.container_width);
1035+
}
10041036
};
10051037

10061038

@@ -1020,12 +1052,16 @@
10201052
this.resize_initial_height = this.resize_coords.coords.height;
10211053
this.resize_initial_sizex = this.resize_coords.grid.size_x;
10221054
this.resize_initial_sizey = this.resize_coords.grid.size_y;
1055+
this.resize_initial_col = this.resize_coords.grid.col;
10231056
this.resize_last_sizex = this.resize_initial_sizex;
10241057
this.resize_last_sizey = this.resize_initial_sizey;
1058+
10251059
this.resize_max_size_x = Math.min(this.resize_wgd.max_size_x ||
1026-
this.options.resize.max_size[0], this.cols - this.resize_wgd.col + 1);
1060+
this.options.resize.max_size[0],
1061+
this.options.max_cols - this.resize_initial_col + 1);
10271062
this.resize_max_size_y = this.resize_wgd.max_size_y ||
10281063
this.options.resize.max_size[1];
1064+
this.resize_initial_last_col = this.get_highest_occupied_cell().col;
10291065

10301066
this.resize_dir = {
10311067
right: ui.$player.is('.' + this.resize_handle_class + '-x'),
@@ -1080,6 +1116,12 @@
10801116
});
10811117
}, this), 300);
10821118

1119+
this.set_dom_grid_width();
1120+
1121+
if (this.options.autogrow_cols) {
1122+
this.drag_api.set_limits(this.container_width);
1123+
}
1124+
10831125
if (this.options.resize.stop) {
10841126
this.options.resize.stop.call(this, event, ui, this.$resized_widget);
10851127
}
@@ -1126,6 +1168,20 @@
11261168
size_x = this.resize_initial_sizex;
11271169
}
11281170

1171+
1172+
if (this.options.autogrow_cols) {
1173+
// auto grow cols
1174+
var last_widget_col = this.resize_initial_col + size_x - 1;
1175+
if (this.options.autogrow_cols && this.resize_initial_last_col <= last_widget_col) {
1176+
this.set_dom_grid_width(last_widget_col + 1);
1177+
1178+
if (this.cols < last_widget_col) {
1179+
this.add_faux_cols(last_widget_col - this.cols);
1180+
}
1181+
}
1182+
}
1183+
1184+
11291185
var css_props = {};
11301186
!this.resize_dir.bottom && (css_props.width = Math.min(
11311187
this.resize_initial_width + rel_x, max_width));
@@ -1137,7 +1193,7 @@
11371193
if (size_x !== this.resize_last_sizex ||
11381194
size_y !== this.resize_last_sizey) {
11391195

1140-
this.resize_widget(this.$resized_widget, size_x, size_y, false);
1196+
this.resize_widget(this.$resized_widget, size_x, size_y);
11411197

11421198
this.$resize_preview_holder.css({
11431199
'width': '',
@@ -2531,26 +2587,23 @@
25312587
fn.get_highest_occupied_cell = function() {
25322588
var r;
25332589
var gm = this.gridmap;
2534-
var rows = [];
2590+
var rl = gm[1].length;
2591+
var rows = [], cols = [];
25352592
var row_in_col = [];
25362593
for (var c = gm.length - 1; c >= 1; c--) {
2537-
for (r = gm[c].length - 1; r >= 1; r--) {
2594+
for (r = rl - 1; r >= 1; r--) {
25382595
if (this.is_widget(c, r)) {
25392596
rows.push(r);
2540-
row_in_col[r] = c;
2597+
cols.push(c);
25412598
break;
25422599
}
25432600
}
25442601
}
25452602

2546-
var highest_row = Math.max.apply(Math, rows);
2547-
2548-
this.highest_occupied_cell = {
2549-
col: row_in_col[highest_row],
2550-
row: highest_row
2603+
return {
2604+
col: Math.max.apply(Math, cols),
2605+
row: Math.max.apply(Math, rows)
25512606
};
2552-
2553-
return this.highest_occupied_cell;
25542607
};
25552608

25562609

@@ -2586,9 +2639,34 @@
25862639
* @method set_dom_grid_height
25872640
* @return {Object} Returns the instance of the Gridster class.
25882641
*/
2589-
fn.set_dom_grid_height = function() {
2590-
var r = this.get_highest_occupied_cell().row;
2591-
this.$el.css('height', r * this.min_widget_height);
2642+
fn.set_dom_grid_height = function(height) {
2643+
if (typeof height === 'undefined') {
2644+
var r = this.get_highest_occupied_cell().row;
2645+
height = r * this.min_widget_height;
2646+
}
2647+
2648+
this.container_height = height;
2649+
this.$el.css('height', this.container_height);
2650+
return this;
2651+
};
2652+
2653+
/**
2654+
* Set the current width of the parent grid.
2655+
*
2656+
* @method set_dom_grid_width
2657+
* @return {Object} Returns the instance of the Gridster class.
2658+
*/
2659+
fn.set_dom_grid_width = function(cols) {
2660+
var width;
2661+
2662+
if (typeof cols === 'undefined') {
2663+
cols = this.get_highest_occupied_cell().col;
2664+
}
2665+
2666+
cols = Math.min(this.options.max_cols,
2667+
Math.max(cols, this.options.min_cols));
2668+
this.container_width = cols * this.min_widget_width;
2669+
this.$el.css('width', this.container_width);
25922670
return this;
25932671
};
25942672

@@ -2790,8 +2868,9 @@
27902868
fn.add_faux_cols = function(cols) {
27912869
var actual_cols = this.cols;
27922870
var max_cols = actual_cols + (cols || 1);
2871+
max_cols = Math.min(max_cols, this.options.max_cols);
27932872

2794-
for (var c = actual_cols; c < max_cols; c++) {
2873+
for (var c = actual_cols + 1; c <= max_cols; c++) {
27952874
for (var r = this.rows; r >= 1; r--) {
27962875
this.add_faux_cell(r, c);
27972876
}
@@ -2854,7 +2933,6 @@
28542933
*/
28552934
fn.generate_grid_and_stylesheet = function() {
28562935
var aw = this.$wrapper.width();
2857-
var ah = this.$wrapper.height();
28582936
var max_cols = this.options.max_cols;
28592937

28602938
var cols = Math.floor(aw / this.min_widget_width) +
@@ -2869,28 +2947,23 @@
28692947

28702948
var min_cols = Math.max.apply(Math, actual_cols);
28712949

2950+
this.cols = Math.max(min_cols, cols, this.options.min_cols);
2951+
2952+
if (max_cols !== Infinity && max_cols >= min_cols && max_cols < this.cols) {
2953+
this.cols = max_cols;
2954+
}
2955+
28722956
// get all rows that could be occupied by the current widgets
28732957
var max_rows = this.options.extra_rows;
28742958
this.$widgets.each(function(i, w) {
28752959
max_rows += (+$(w).attr('data-sizey'));
28762960
});
28772961

2878-
this.cols = Math.max(min_cols, cols, this.options.min_cols);
2879-
2880-
if (max_cols && max_cols >= min_cols && max_cols < this.cols) {
2881-
this.cols = max_cols;
2882-
}
2883-
28842962
this.rows = Math.max(max_rows, this.options.min_rows);
28852963

28862964
this.baseX = ($(window).width() - aw) / 2;
28872965
this.baseY = this.$wrapper.offset().top;
28882966

2889-
// left and right gutters not included
2890-
this.container_width = (this.cols *
2891-
this.options.widget_base_dimensions[0]) + ((this.cols - 1) * 2 *
2892-
this.options.widget_margins[0]);
2893-
28942967
if (this.options.autogenerate_stylesheet) {
28952968
this.generate_stylesheet();
28962969
}

0 commit comments

Comments
 (0)