I am tasked with creating a dashboard interface in our ASP.NET MVC 3 web application. First I will list the features that are required for this project and then I will do my best to illustrate what I intend to create to accommodate all of these features.
The dashboard will contain widgets (or tiles) that will be draggable within the dashboard interface.
When dragging widgets, the surrounding widgets will re-order themselves appropriately.
Widgets are not re-sizable or collapsible but they will be removable. The user will add widgets back through a menu if they desire.
The widgets must accommodate variable width browser windows. Vertical space is pretty much unlimited.
The widgets' heights and widths will be in increments of 300 pixels, maxing out at 900 pixels. In other words, a widget could be: 300 x 300, 600 x 300, 300 x 900, 900 x 900, and so on.
Here are a couple illustrations of what I hope to build.
The dimensions aren't perfect but this shows a dashboard with 9 widgets on it. All widgets are snug and do their best to fill the width of the screen elegantly. However, the widgets do not have to form a perfect square or rectangle. Danglers are OK as pictured below.
Note how the widths and heights of the widgets are all in increments of 300 pixels, as noted in the requirements above. This should hopefully make it easier to do the math for re-ordering the tiles. Which brings me to my problem.
I have the concept understood but I am having trouble figuring out where to begin. I am not as proficient with math as I wish I was and I need some help getting pointed in the right direction.
How do I get from an array of widgets (of all shapes and sizes) that is sorted in no particular order, into a neatly laid out absolutely positioned grid of tiles that takes up space as elegantly as possible?
How do I get from this:
To this:
Or at least a similarly elegant layout. The tiles do not have to be in their exact places as pictured above. I just want them to play a perfect game of Tetris and fall into place without awkward gaps.
I need to take the width of the browser window into account and then somehow loop through the array of widgets and start adding them to some sort of virtual grid. I want it to look as elegant as I can make it.
Then, after solving how I order the widgets on the page after the initial page load I need to allow the user to move his/her widgets around and have the other widgets re-order themselves as neatly as possible to accommodate the moved widget's new position. I also need an elegant way to re-order widgets if the browser is re-sized.
I'm not expecting full-blown solutions or implementations. I just need a push in the right direction I think. Perhaps, a simple brain storm description of the logic for looping through the widgets and what things to calculate to arrive at the best configuration.
Float or tile a new itemUnder Objects in the Dashboard pane, click the layout option you want to use: Floating or Tiled. Drag the view or object onto the dashboard on the right.
After investigating jQuery Masonry, jQuery isotope, and even a custom block-filling algorithm, I stumbled upon another jQuery plugin known as jQuery Gridster that does exactly what I want. There are a few quirks with the plugin and it's not very polished, but with a few tweaks I was able to use it effectively.
Note: One of those quirks is the plugin's API. When you try to dynamically remove items from the grid using the remove option in the plugin API it throws a whole bunch of errors. It's some sort of race condition because it happens sporadically. The bug was probably missed because when you use the API to only remove one item at a time it works 99% of the time. If you remove more than one item in rapid succession (either by looping through and calling the API multiple times, or by passing the remove function a wrapped set with more than one element) then you'll get a bunch of console errors.
I had a need to remove all tiles from the grid and reload a new set of tiles. It was easier to just use jQuery to remove the element Gridster was invoked on and then call the plugin fresh from the beginning, passing it the new set of tiles.
You might try something like jQuery Masonry. It seems like it can at least solve some of the problems that you're looking to tackle. Also, for some inspiration and some code to look through, check out how StackExchange lists their QA sites: https://stackexchange.com/sites?view=grid
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With