|
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