|
15 | 15 | extra_rows: 0, |
16 | 16 | extra_cols: 0, |
17 | 17 | min_cols: 1, |
18 | | - max_cols: null, |
| 18 | + max_cols: Infinity, |
19 | 19 | min_rows: 15, |
20 | 20 | max_size_x: false, |
| 21 | + autogrow_cols: false, |
21 | 22 | autogenerate_stylesheet: true, |
22 | 23 | avoid_overlapped_widgets: true, |
23 | 24 | serialize_params: function($w, wgd) { |
|
137 | 138 | this.generate_grid_and_stylesheet(); |
138 | 139 | this.get_widgets_from_DOM(); |
139 | 140 | this.set_dom_grid_height(); |
| 141 | + this.set_dom_grid_width(); |
140 | 142 | this.$wrapper.addClass('ready'); |
141 | 143 | this.draggable(); |
142 | 144 | this.options.resize.enabled && this.resizable(); |
|
298 | 300 | * @param {HTMLElement} $widget The jQuery wrapped HTMLElement |
299 | 301 | * representing the widget. |
300 | 302 | * @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. |
304 | 303 | * By default <code>size_x</code> is limited to the space available from |
305 | 304 | * 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. |
306 | 306 | * @param {Function} [callback] Function executed when the widget is removed. |
307 | 307 | * @return {HTMLElement} Returns $widget. |
308 | 308 | */ |
309 | | - fn.resize_widget = function($widget, size_x, size_y, reposition, callback) { |
| 309 | + fn.resize_widget = function($widget, size_x, size_y, callback) { |
310 | 310 | 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; |
319 | 313 | var old_size_y = wgd.size_y; |
320 | 314 | var old_col = wgd.col; |
321 | 315 | var new_col = old_col; |
322 | 316 |
|
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); |
327 | 322 | } |
328 | 323 |
|
329 | 324 | if (size_y > old_size_y) { |
330 | 325 | this.add_faux_rows(Math.max(size_y - old_size_y, 0)); |
331 | 326 | } |
332 | 327 |
|
| 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 | + |
333 | 333 | var new_grid_data = { |
334 | 334 | col: new_col, |
335 | 335 | row: wgd.row, |
|
340 | 340 | this.mutate_widget_in_gridmap($widget, wgd, new_grid_data); |
341 | 341 |
|
342 | 342 | this.set_dom_grid_height(); |
| 343 | + this.set_dom_grid_width(); |
343 | 344 |
|
344 | 345 | if (callback) { |
345 | 346 | callback.call(this, new_grid_data.size_x, new_grid_data.size_y); |
|
776 | 777 | var self = this; |
777 | 778 | var draggable_options = $.extend(true, {}, this.options.draggable, { |
778 | 779 | offset_left: this.options.widget_margins[0], |
| 780 | + offset_top: this.options.widget_margins[1], |
779 | 781 | container_width: this.container_width, |
| 782 | + limit: true, |
780 | 783 | ignore_dragging: ['INPUT', 'TEXTAREA', 'SELECT', 'BUTTON', |
781 | 784 | '.' + this.options.resize.handle_class], |
782 | 785 | start: function(event, ui) { |
|
818 | 821 | offset_left: this.options.widget_margins[0], |
819 | 822 | container_width: this.container_width, |
820 | 823 | move_element: false, |
| 824 | + resize: true, |
| 825 | + limit: this.options.autogrow_cols ? false : true, |
821 | 826 | start: $.proxy(this.on_start_resize, this), |
822 | 827 | stop: $.proxy(function(event, ui) { |
823 | 828 | delay($.proxy(function() { |
|
860 | 865 | fn.on_start_drag = function(event, ui) { |
861 | 866 | this.$helper.add(this.$player).add(this.$wrapper).addClass('dragging'); |
862 | 867 |
|
| 868 | + this.highest_col = this.get_highest_occupied_cell().col; |
| 869 | + |
863 | 870 | this.$player.addClass('player'); |
864 | 871 | this.player_grid_data = this.$player.coords().grid; |
865 | 872 | this.placeholder_grid_data = $.extend({}, this.player_grid_data); |
866 | 873 |
|
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 | + } |
870 | 884 |
|
871 | 885 | var colliders = this.faux_grid; |
872 | 886 | var coords = this.$player.data('coords').coords; |
|
930 | 944 | this.on_stop_overlapping_row |
931 | 945 | ); |
932 | 946 |
|
| 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 | + |
933 | 960 | if (this.helper && this.$player) { |
934 | 961 | this.$player.css({ |
935 | 962 | 'left': ui.position.left, |
|
1001 | 1028 | this.cells_occupied_by_player = {}; |
1002 | 1029 |
|
1003 | 1030 | 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 | + } |
1004 | 1036 | }; |
1005 | 1037 |
|
1006 | 1038 |
|
|
1020 | 1052 | this.resize_initial_height = this.resize_coords.coords.height; |
1021 | 1053 | this.resize_initial_sizex = this.resize_coords.grid.size_x; |
1022 | 1054 | this.resize_initial_sizey = this.resize_coords.grid.size_y; |
| 1055 | + this.resize_initial_col = this.resize_coords.grid.col; |
1023 | 1056 | this.resize_last_sizex = this.resize_initial_sizex; |
1024 | 1057 | this.resize_last_sizey = this.resize_initial_sizey; |
| 1058 | + |
1025 | 1059 | 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); |
1027 | 1062 | this.resize_max_size_y = this.resize_wgd.max_size_y || |
1028 | 1063 | this.options.resize.max_size[1]; |
| 1064 | + this.resize_initial_last_col = this.get_highest_occupied_cell().col; |
1029 | 1065 |
|
1030 | 1066 | this.resize_dir = { |
1031 | 1067 | right: ui.$player.is('.' + this.resize_handle_class + '-x'), |
|
1080 | 1116 | }); |
1081 | 1117 | }, this), 300); |
1082 | 1118 |
|
| 1119 | + this.set_dom_grid_width(); |
| 1120 | + |
| 1121 | + if (this.options.autogrow_cols) { |
| 1122 | + this.drag_api.set_limits(this.container_width); |
| 1123 | + } |
| 1124 | + |
1083 | 1125 | if (this.options.resize.stop) { |
1084 | 1126 | this.options.resize.stop.call(this, event, ui, this.$resized_widget); |
1085 | 1127 | } |
|
1126 | 1168 | size_x = this.resize_initial_sizex; |
1127 | 1169 | } |
1128 | 1170 |
|
| 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 | + |
1129 | 1185 | var css_props = {}; |
1130 | 1186 | !this.resize_dir.bottom && (css_props.width = Math.min( |
1131 | 1187 | this.resize_initial_width + rel_x, max_width)); |
|
1137 | 1193 | if (size_x !== this.resize_last_sizex || |
1138 | 1194 | size_y !== this.resize_last_sizey) { |
1139 | 1195 |
|
1140 | | - this.resize_widget(this.$resized_widget, size_x, size_y, false); |
| 1196 | + this.resize_widget(this.$resized_widget, size_x, size_y); |
1141 | 1197 |
|
1142 | 1198 | this.$resize_preview_holder.css({ |
1143 | 1199 | 'width': '', |
|
2531 | 2587 | fn.get_highest_occupied_cell = function() { |
2532 | 2588 | var r; |
2533 | 2589 | var gm = this.gridmap; |
2534 | | - var rows = []; |
| 2590 | + var rl = gm[1].length; |
| 2591 | + var rows = [], cols = []; |
2535 | 2592 | var row_in_col = []; |
2536 | 2593 | 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--) { |
2538 | 2595 | if (this.is_widget(c, r)) { |
2539 | 2596 | rows.push(r); |
2540 | | - row_in_col[r] = c; |
| 2597 | + cols.push(c); |
2541 | 2598 | break; |
2542 | 2599 | } |
2543 | 2600 | } |
2544 | 2601 | } |
2545 | 2602 |
|
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) |
2551 | 2606 | }; |
2552 | | - |
2553 | | - return this.highest_occupied_cell; |
2554 | 2607 | }; |
2555 | 2608 |
|
2556 | 2609 |
|
|
2586 | 2639 | * @method set_dom_grid_height |
2587 | 2640 | * @return {Object} Returns the instance of the Gridster class. |
2588 | 2641 | */ |
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); |
2592 | 2670 | return this; |
2593 | 2671 | }; |
2594 | 2672 |
|
|
2790 | 2868 | fn.add_faux_cols = function(cols) { |
2791 | 2869 | var actual_cols = this.cols; |
2792 | 2870 | var max_cols = actual_cols + (cols || 1); |
| 2871 | + max_cols = Math.min(max_cols, this.options.max_cols); |
2793 | 2872 |
|
2794 | | - for (var c = actual_cols; c < max_cols; c++) { |
| 2873 | + for (var c = actual_cols + 1; c <= max_cols; c++) { |
2795 | 2874 | for (var r = this.rows; r >= 1; r--) { |
2796 | 2875 | this.add_faux_cell(r, c); |
2797 | 2876 | } |
|
2854 | 2933 | */ |
2855 | 2934 | fn.generate_grid_and_stylesheet = function() { |
2856 | 2935 | var aw = this.$wrapper.width(); |
2857 | | - var ah = this.$wrapper.height(); |
2858 | 2936 | var max_cols = this.options.max_cols; |
2859 | 2937 |
|
2860 | 2938 | var cols = Math.floor(aw / this.min_widget_width) + |
|
2869 | 2947 |
|
2870 | 2948 | var min_cols = Math.max.apply(Math, actual_cols); |
2871 | 2949 |
|
| 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 | + |
2872 | 2956 | // get all rows that could be occupied by the current widgets |
2873 | 2957 | var max_rows = this.options.extra_rows; |
2874 | 2958 | this.$widgets.each(function(i, w) { |
2875 | 2959 | max_rows += (+$(w).attr('data-sizey')); |
2876 | 2960 | }); |
2877 | 2961 |
|
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 | | - |
2884 | 2962 | this.rows = Math.max(max_rows, this.options.min_rows); |
2885 | 2963 |
|
2886 | 2964 | this.baseX = ($(window).width() - aw) / 2; |
2887 | 2965 | this.baseY = this.$wrapper.offset().top; |
2888 | 2966 |
|
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 | | - |
2894 | 2967 | if (this.options.autogenerate_stylesheet) { |
2895 | 2968 | this.generate_stylesheet(); |
2896 | 2969 | } |
|
0 commit comments