Skip to content
New issue

Have a question about this project? Sign up for a free GitHub account to open an issue and contact its maintainers and the community.

By clicking “Sign up for GitHub”, you agree to our terms of service and privacy statement. We’ll occasionally send you account related emails.

Already on GitHub? Sign in to your account

Allow widget dimensions to be resized. #77

Closed
wants to merge 1 commit into from

Conversation

joannecheng
Copy link

After defining the gridster, you can update the widget_base_dimensions and/or widget_margins using resize_widget_dimensions.

Example:

$('.gridster ul').gridster({
    widget_margins: [10, 10],
    widget_base_dimensions: [140, 140]
 });
var gridster = $('.gridster ul').gridster().data('gridster');
gridster.resize_widget_dimensions({widget_base_dimensions: [100,  100]});

We needed the ability to resize the dimensions and margins on window resize for a work project, so I modified jquery.gridster.with-extras.js and added a function to do so.

I have an example of it in action here: http://jc-2.github.com/gridster-test/

@timatron
Copy link

FYI this isn't working for me when I start with a fullscreen window on 1600+ screen and then get smaller. It cuts off a part of the grid. This is on chrome.

-tim

@dovys
Copy link

dovys commented Nov 13, 2012

Same here with 1680x resolution and chrome.

@keichinger
Copy link

I'm encountering the same propblem with 1680x1050. I also do have some huge problems moving some objects in a specific column.

@joannecheng
Copy link
Author

The above demo was just supposed to demonstrate the resizing capability. You are more than welcome to play around with the resize event handlers to get things to size correctly.

That is all.

@surjikal
Copy link

There's a problem with this. If you add a background color to the placeholder, you'll see (after resizing) that while the widget looks bigger, gridster still uses its original size. I've fixed the placeholder issue by doing this inside the resize_widget_dimensions call:

this.$widgets.each($.proxy(function(i, widget) {
    this.resize_widget($(widget), 1, 1);
}, this));

Now the placeholder is the correct size, but the collisions are still done using the original size. So basically, dragging stuff around doesn't work properly. I've tried to debug this but I can't figure it out.

EDIT

I think I got it. Here's the updated resize_widget_dimensions function:

fn.resize_widget_dimensions = function(options) {

    if (options.widget_margins) {
      this.options.widget_margins = options.widget_margins;
    }

    if (options.widget_base_dimensions) {
      this.options.widget_base_dimensions = options.widget_base_dimensions;
    }

    this.min_widget_width  = (this.options.widget_margins[0] * 2)
        + this.options.widget_base_dimensions[0];
    this.min_widget_height = (this.options.widget_margins[1] * 2)
        + this.options.widget_base_dimensions[1];

    this.$widgets.each($.proxy(function(i, widget) {
        var $widget = $(widget);
        var data = $widget.data();
        this.resize_widget($widget, data.sizex, data.sizey);
    }, this));

    this.generate_grid_and_stylesheet();
    this.get_widgets_from_DOM();
    this.set_dom_grid_height();

    return false;
};

@brantje
Copy link

brantje commented Jan 26, 2013

Something like: http://jqueryui.com/resizable/ would be awsome to use with this

@brainTrain
Copy link

brantje, if you bind the stop call back in resizable to a function that passes the widget object on, you can manually resize there.

you should check out this thread if that's what you wanna do:

#69

@brainTrain
Copy link

hey @surjikal, thanks for the awesome solution for resizing these backdrops! I ran into some issues with the resize method. Essentially $widget.data() returns an older version of these widget coordinates than gridster.serialize() does. Took me some fiddling and an extra set of eyes to finally figure this out. Anyway, I updated your code to use the .serialize() coordinates rather than the .data() coordinates and figured I'd paste it in here just in case anyone else runs into the same issue.

fn.resize_widget_dimensions = function(options) {

    if (options.widget_margins) {
      this.options.widget_margins = options.widget_margins;
    }

    if (options.widget_base_dimensions) {
      this.options.widget_base_dimensions = options.widget_base_dimensions;
    }

    this.min_widget_width  = (this.options.widget_margins[0] * 2)
        + this.options.widget_base_dimensions[0];
    this.min_widget_height = (this.options.widget_margins[1] * 2)
        + this.options.widget_base_dimensions[1];

    var serializedGrid = this.serialize(); 
    this.$widgets.each($.proxy(function(i, widget) {
        var $widget = $(widget);
        var data = serializedGrid[i];
        this.resize_widget($widget, data.sizex, data.sizey);
    }, this));

    this.generate_grid_and_stylesheet();
    this.get_widgets_from_DOM();
    this.set_dom_grid_height();

    return false;
};

@smajl
Copy link

smajl commented Feb 20, 2013

@brainTrain Thank you for that piece of code. I am trying to use that in my project but there is still a one big problem. You can maximize/demaximize window exactly twice with desired effect (widgets resizing), but then it stops working (stylesheet doesn't update). The manual window resizing by dragging sides and corners still works like expected.

Do you have any idea how to fix that?

@brainTrain
Copy link

Hmm no, my app will continue to resize as much as I like, are you using any other plugins on the widgets? We used Jquery ui's resizable widget and I have to update its grid to match the new gridster size otherwise the whole thing goes a bit haywire. So I dunno, my suggestion would be to look at other js you're applying to your widgets or page and see if there is ever a conflict with dimensions. Other than that I would say your issue is one I haven't encountered yet

@smajl
Copy link

smajl commented Feb 20, 2013

@brainTrain I need to clarify. I am actually going for an automatic fluid layout. So on window.resize I recalculate new dimensions and margins and pass them as options into your enhanced version of gridster.resize_widget_dimensions. It works fine when dragging edges of window by hand, but not with maximize/demaximize window button.

I think I figured out where the problem might be. Seems like gridster.resize_widget_dimensions should not be called more then once? Because I just noticed it injects new stylesheet into the head every time - and it seems like it is causing conflicts.

Example of my project: http://jsfiddle.net/nxmRr/1/
You can see, that stylesheets are breeding like 🐇s while resizing window, which is not good. :-D

Could gridster.resize_widget_dimensions update existing style or do remove/new instead?

@brainTrain
Copy link

ah I see! I haven't tested that interaction yet, I'll have to look into it once I get in the office. You should checkout underscorejs if you haven't already, they give some nice utility functions that you won't have to build yourself.. one that we've used for this is debounce, which will use set timeouts to determine whether or not it should start the resize... It might not solve your issue, but it should help things a bit, check out the function here:

http://underscorejs.org/#debounce

if you want to implement it with your gridster resize function you'll want to make it a named function then call it within the $(window).resize() function like this:

        // trigger a sub-panel reflow when we resize
        var debounced_resizer_fn = _.debounce( function() {
           gridster.resize_widget_dimensions(x, y);
          }, 250);  
        $(window).resize( debounced_resizer_fn );

this will only call the window resize_widget_dimensions() function if the user hasn't resized the the window in 250ms, not sure if that's the magic number, haven't played around with it yet, but that should help.

@smajl
Copy link

smajl commented Feb 20, 2013

I guess that's very similar to what I have already in my code:

...
$(window).resize(function() {
  window.clearTimeout(resizeTimer);
  resizeTimer = window.setTimeout(function() {
    resizeWidgetDimensions();
   }, RESIZE_TIME); // 500ms
});
...

So firing the resize callback too often is not the problem here as I am already controlling that.

UPDATE: The problem is that gridster.resize_widget_dimensions injects brand new stylesheet into head every time it is called (which is not good behavior - you can be flooded with styles in no time). And second problem is, that it works only 1-2 times when it is triggered by window resize triggered by maximize/demaximize button (really strange). This all can be seen in my fiddle example in previous post.

You will be very kind, if you can look at that later. :)

@brainTrain
Copy link

Yeah I see what you're saying... one possible hack would be to dig into the gridster code and add some unique attribute to these stylesheets so you can clean them up as you resize, which may be all that needs to be done here. I've got other stuff I need to try and finish today, but later tonight I'll probably take a look and see if that option fixes it, other than that I'm kind of at a loss, I'll have to start combing stack overflow or tracing gridster's code to try and find a solution.

Another thing to note that a coworker discovered is that this line:
this.set_dom_grid_height();

was causing our widgets to stack (one would fall behind the other and stay there). Once we got rid of it, they started behaving in a more sane way.

@brainTrain
Copy link

Ok, so I added a way to cleanup these style sheets... in gridster's source I added this line to the function add_style_tag()

2373 tag.setAttribute('generated-from', 'gridster');

and clean up at the top of this extras resize_widget_dimensions function like so:

$('head [generated-from="gridster"]:not(:last)').remove();

What I noticed is that if you click to expand or shrink your window, the window resize function is called but gridster does not add a new stylesheet. If you can figure out why it's not doing that, I think you'll have your fix. Also please note that using my generated-from attribute seems to do the trick most of the time, but it does get into a state where there will be 2 css style blocks generated so it's not perfect.

Ball's in your court now dude :p

@smajl
Copy link

smajl commented Feb 21, 2013

I found out, that the problem was in generate_stylesheet (line 2276) method:

        // don't duplicate stylesheets for the same configuration
        var serialized_opts = $.param(opts);
        if ($.inArray(serialized_opts, Gridster.generated_stylesheets) >= 0) {
            return false; // comment this out, and updating dimensions will work as expected
        }

It's strange, but after 1-2 resizing with buttons this condition kicks in and breaks the style generating method so CSS don't update. I think it is safe to disable this check since we introduced your little hack for removing stylesheet duplicates and recalculating stylesheet for "the same configuration" isn't such an issue (it's not such a frequent task). :)

@brainTrain
Copy link

interesting. I'd be careful with this one though, since I don't know what else in gridster changes the style sheet, my little cleanup only works when you call the resizing all widgets function. That's awesome though, when I get a chance I'll see if I can find any negative repercussions from commenting that line out.

@jim-at-miramontes
Copy link

Just a thought: It would be nice to have the same ability for adjusting widget_margins after the initial configuration. I'm using gridster to display a column of items that are moved in and out of "draggable" mode, and I'd like to be able to break them out a bit vertically when in draggable mode, to emphasize that they're manipulable things.

@fredpe
Copy link

fredpe commented Apr 9, 2013

Thanks @brainTrain for your code, great work! Just one situation where it gets into trouble: When you set your own serialize_params function when initializing gridster it looks like gridster does not hand over the "wgd" parameter ( see http://gridster.net/#serialize_params_opt ) correctly when calling this.serialize() in your code. It's simply undefined in that case and therefor my serialize_params function fails resulting in error on console.

When thinking about this I think it would be best to avoid calling the this.serialize() method at all as this method also triggers the serialize_params function (once again: the mentioned error only happens if you set a custom serialize_params function when initializing gridster). So I looked at your code and tried to find a solution for this. Here is your code once again:

    var serializedGrid = this.serialize(); 
    this.$widgets.each($.proxy(function(i, widget) {
        var $widget = $(widget);
        var data = serializedGrid[i];
        this.resize_widget($widget, data.sizex, data.sizey);
    }, this));

Looking at this the serializedGrid variable is only used to hand over data.sizex and data.sizey. Looking further at the implementation of resize_widget(...) one can see that the second and third parameters are optional. If not set, gridster will get these values itsself. So I patched your code shown above as follows:

    this.$widgets.each($.proxy(function(i, widget) {
        var $widget = $(widget);
        this.resize_widget($widget);
    }, this));

Now this.serialize() will not be called anymore, thus no error in my case.

Just thought I share this in case someone else runs into this problem when setting a custom "serialize_params" function on gridster initialization. Glad to here your feedback on this :-)

@Thomasforweb
Copy link

@brainTrain and @fredpe , Hats Off to both of you!..

really helped me out to resize grids while window resizing.

@hustcer
Copy link

hustcer commented May 16, 2013

@surjikal @brainTrain @fredpe Thank you all !

@praveenaj
Copy link

@smajl I used your jsfiddle code and tried placing three large widgets spanning full width, in the top most row. But when I resized the browser window, the right most widgets jumps into the row below (http://jsfiddle.net/nxmRr/30/). Any idea why this happens? I noticed this doesn't occur when there's another row above this (http://jsfiddle.net/nxmRr/29/)

@brio50
Copy link

brio50 commented Jun 3, 2013

I had the same issue, I was using the gridster.js provided by
gridster.netand not the github .js, look at the external resources on
his jsfiddle and
you'll see that the gridster-with-extra.js from github is used!

On Monday, June 3, 2013, Praveena Sarathchandra wrote:

@smajl https://github.com/smajl I used your jsfiddle code and tried
placing three large widgets spanning full width, in the top most row. But
when I resized the browser window, the right most widgets jumps into the
row below (http://jsfiddle.net/nxmRr/30/). Any idea why this happens? I
noticed this doesn't occur when there's another row above this (
http://jsfiddle.net/nxmRr/29/)


Reply to this email directly or view it on GitHubhttps://github.com//pull/77#issuecomment-18826798
.

559-906-5052 | brio50@gmail.com

@praveenaj
Copy link

I'm using gridster-with-extra and still having the issue. :(

On Mon, Jun 3, 2013 at 8:19 PM, brio50 notifications@github.com wrote:

I had the same issue, I was using the gridster.js provided by
gridster.netand not the github .js, look at the external resources on
his jsfiddle and
you'll see that the gridster-with-extra.js from github is used!

On Monday, June 3, 2013, Praveena Sarathchandra wrote:

@smajl https://github.com/smajl I used your jsfiddle code and tried
placing three large widgets spanning full width, in the top most row.
But
when I resized the browser window, the right most widgets jumps into the
row below (http://jsfiddle.net/nxmRr/30/). Any idea why this happens? I
noticed this doesn't occur when there's another row above this (
http://jsfiddle.net/nxmRr/29/)


Reply to this email directly or view it on GitHub<
https://github.com/ducksboard/gridster.js/pull/77#issuecomment-18826798>
.

559-906-5052 | brio50@gmail.com


Reply to this email directly or view it on GitHubhttps://github.com//pull/77#issuecomment-18846274
.

@OClement
Copy link

OClement commented Jul 8, 2013

Guys,
I am implementing Gridster as an Angular Directive (basically a "standalone component" for use with AngularJs) and adding these changes discussed here; You can see the project here: https://github.com/OClement/Dashboard-PoC

I am having an issue that seems to be related to resize_widget_dimensions
Say I set the options to something like 12 columns, depending on the width of the browser, it won't let me drag a widget to the last 1 to 3 columns (sometimes 1, sometimes 2, etc)

I am not sure what is causing this; If anyone care to take a look, that would be great;

To run the project, clone or fork it and run grunt server from main folder

Thanks


Update

Line 2556 of jquery.gridster.js (in dist folder) calculate this.container_width properly;
However, in fn.on_dragstart = function(e) {, which is exec'd when you start dragging, at line 604, it "reset" the container_width like so: var container_width = this.options.container_width || this.$container.width();

Turns out that (for me at least), this.options.container_width is always set to 1240, no matter what.

Any ideas on that?

Thanks again - Hoping someone will read that at least

@chrisapl
Copy link

Hi Oclement,

Change:
''' var container_width = this.options.container_width || this.$container.width(); '''

to:

''' var container_width = this.$container.width(); '''

This improves the situation for me. I have my gridster container set to 80% width and I can now resize the browser window and the gridster area will resize accordingly. If I make it bigger I can drag widgets into the extra space created.

For my my mind the only thing left is to reposition all of the widgets after resize as at the moment if I make the browser window smaller and widgets that are now outside the grid area are not moved. Once I got to drag them again the are moved to within the grid area.

Looking into that part now.

Cheers
chris

@OwlyCode
Copy link

OwlyCode commented Sep 3, 2013

Hi there. I use gridster with extra and came across the problem of resizing the grid. I came up using an external override of gridster instead of directly modifying the vendor library : https://gist.github.com/OwlyCode/6421823

Just include this file in your page and start using it :

var gridster = $(".gridster ul").gridster().data('gridster');

// [...]

$(window).resize(function() {
            $('head [generated-from="gridster"]:not(:last)').remove();
            var widgetLength = $(window).width() / 12; // 12 columns.
            gridster.resize_widget_dimensions({widget_base_dimensions: [widgetLength, 25]});
});

It works for me, even with the maximize/demaximize window button.

@epetre
Copy link

epetre commented Sep 22, 2013

@OwlyCode I was going to look into your code but it's not there anymore.

@epetre
Copy link

epetre commented Sep 22, 2013

Is @joannecheng 's solution going to be included? Cause it looks like a nice solution...

@OwlyCode
Copy link

OwlyCode commented Oct 2, 2013

@epetre Hi ! Sorry I updated the link so you can now see it. I recently renamed my account and it broke some links.

@byrichardpowell
Copy link

@surjikal @brainTrain @fredpe I am implementing gridster within an area of the page that resizes and I just wanted to thank you for all your efforts with this. Your code has saved me countless hours.

Thank you all.

@byrichardpowell
Copy link

I had a small problem with this. Steps to reproduce the problem:

  1. Add 3 rows worth of widgets
  2. Drag widgets from row 1 to row 2
  3. Resize the window
  4. Row 3 incorrectly moves to row 2.

I believe the problem is related to #147

I think I've solved it by simplifying the resize_widget_dimensions method:

fn.resize_widget_dimensions = function(options) { 
    if (options.widget_margins) {
        this.options.widget_margins = options.widget_margins;
    }

    if (options.widget_base_dimensions) {
        this.options.widget_base_dimensions = options.widget_base_dimensions;
    }

    this.min_widget_width  = (this.options.widget_margins[0] * 2)
        + this.options.widget_base_dimensions[0];
    this.min_widget_height = (this.options.widget_margins[1] * 2)
        + this.options.widget_base_dimensions[1];

    var serializedGrid = this.serialize(); 

    this.$widgets.each($.proxy(function(i, widget) {

        var $widget = $(widget);
        var data = serializedGrid[i];

        this.resize_widget($widget, data.sizex, data.sizey);

    }, this));

    // Causes problems with widgets loosing their order
    // this.generate_grid_and_stylesheet();
    // this.set_dom_grid_height();
    // this.get_widgets_from_DOM()
    this.generate_stylesheet()

    $('head [generated-from="gridster"]:not(:last)').remove();

    return false;
};

Basically I commented out the following function calls:

    this.generate_grid_and_stylesheet();
    this.set_dom_grid_height();
    this.get_widgets_from_DOM()

and replaced them with:

this.generate_stylesheet() 

In my case all I need to do is generate the new stylesheet. I don't care about the rest. Your requirements may be different

@mastastealth
Copy link

I was trying to use @OwlyCode's external script, but apparently the dimensions are off just on the first load (it's just a 2 column layout, some rows are 50/50, others are full width, and almost every row just loads the wrong widths). Are any of these solutions meant to work on 0.5.0?

Edit: It looks like the sizex styles aren't generating when enabling the plugin.

@JacquiManzi
Copy link

I have it working in 5.0 using brainTrain's last posted solutions. Though, I did need to slightly modify the gridster source code with smalj's suggestion:

// don't duplicate stylesheets for the same configuration
var serialized_opts = $.param(opts);
if ($.inArray(serialized_opts, Gridster.generated_stylesheets) >= 0) {
return false; // comment this out, and updating dimensions will work as expected
}

I did need to comment out that return false because it prevented any new stylesheets from being generated using the newly calculated dimensions. I also manually clear out the generated stylesheets on every resize: this.gridster.generated_stylesheets = []. I do this since commenting out the return false now allows for a lot of stylesheets to be created.

@mastastealth
Copy link

Apparently I needed to define the max_size_x first, that's what the sizex uses in it's for loop, so I guess it makes sense.

@otisg
Copy link

otisg commented Mar 11, 2014

This seems like a great addition. Any chance of it being merged?

@otisg
Copy link

otisg commented Mar 24, 2014

@SMJ93 Dashing or Gridster?

@gcphost
Copy link

gcphost commented Apr 19, 2014

Based on @OwlyCode's example I was able to get this working for me.

Here is my example with bootstrap panels and some extra features
https://github.com/gcphost/gridster-responsive

@DrieStone
Copy link

I noticed that the responsive.js file doesn't change the limits for dragging widgets. I had to add:

available_width = $('.gridster').width();
gridster.drag_api.set_limits(available_width);

to allow me to drag widgets around the entire area correctly.

@dmbuchta
Copy link

@DrieStone I've been messing with this for quite sometime, your fix was exactly what I needed!

@ghmulti
Copy link

ghmulti commented Dec 12, 2014

@smajl
"It's strange, but after 1-2 resizing with buttons this condition kicks in and breaks the style generating method so CSS don't update." - this makes sense if your new window bounds are exact same to previous (click maximize/minimize in browser couple times, it will not work after fullscreen->minimize->maximize), but if you resize window manually - everything will work.
Anyway, it would be probably even better if fn.add_style_tag returns added tag. Then you can remove it after next resize from Gridster.generated_stylesheets manually and detach from page. This should
prevent "if ($.inArray(serialized_opts, Gridster.generated_stylesheets) >= 0)"

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Projects
None yet
Development

Successfully merging this pull request may close these issues.

None yet