Tuesday, 12 January 2016

Gridster.js: saving the state and dynamic loading of the elements

Gridster is a jQuery plugin that allows building intuitive draggable layouts from elements spanning multiple columns. You can even save the state of the elements and dynamically load the elements from the grid. Dynamic loading is on par with sliced bread, or possibly better.
          You all must be familiar with the new windows 8 theme. Here I am going to implement the Windows 8 theme (Although the functionalities would not be the same, the UI may look similar). If I would have got the same functionalities running, I would have been working at Microsoft now. :P
          Nevertheless, you will be able to use this theme as a web application. You might want to integrate this cool feature in your website.Trust me! Its a lot easier. This is where gridster comes into the picture. There are no articles as such which will provide you with the insights of Gridster.js. Since there are too many unsolved issues related to this topic, I thought of sharing my experience and this blog is intended to do so.

To know about the issues related with this plugin, you can go through the following link:
https://github.com/ducksboard/gridster.js/issues?page=1&state=open

Windows 8 Theme

Enough of Theory! Huh!!! Bored??? You must not be :P
Lets jump directly into the implementation part

Getting Started

index.html

<script type="text/javascript" src="assets/jquery.js"></script>
<script type="text/javascript" src="assets/jquery.gridster.js" charster="utf-8"></script>


HTML structure

<div class="gridster">
<ul id="hello">

<li id="li1" data-row="1" data-col="1" data-sizex="1" data-sizey="1"></li>
<li id="li2" data-row="2" data-col="1" data-sizex="1" data-sizey="1"></li>
<li id="li3" data-row="3" data-col="1" data-sizex="1" data-sizey="1"></li>
<li id="li4" data-row="4" data-col="1" data-sizex="2" data-sizey="1"></li>
<li id="li5" data-row="1" data-col="2" data-sizex="1" data-sizey="1"></li>
<li id="li6" data-row="2" data-col="2" data-sizex="1" data-sizey="1"></li>
<li id="li7" data-row="3" data-col="2" data-sizex="1" data-sizey="1"></li>

<li id="li8" data-row="1" data-col="3" data-sizex="2" data-sizey="1"></li>
<li id="li9" data-row="2" data-col="3" data-sizex="2" data-sizey="1"></li>
<li id="li10" data-row="3" data-col="3" data-sizex="2" data-sizey="1"></li>
<li id="li11" data-row="4" data-col="3" data-sizex="2" data-sizey="1"></li>


<li id="li12" data-row="1" data-col="5" data-sizex="2" data-sizey="1"></li>
<li id="li13" data-row="2" data-col="5" data-sizex="2" data-sizey="1"></li>
<li id="li14" data-row="3" data-col="5" data-sizex="2" data-sizey="1"></li>
<li id="li15" data-row="4" data-col="5" data-sizex="1" data-sizey="1"></li>
<li id="li16" data-row="4" data-col="6" data-sizex="1" data-sizey="1"></li>

<li id="li17" data-row="1" data-col="8" data-sizex="2" data-sizey="1"></li>
<li id="li18" data-row="2" data-col="8" data-sizex="2" data-sizey="1"></li>
<li id="li19" data-row="3" data-col="8" data-sizex="2" data-sizey="1"></li>
<li id="li20" data-row="4" data-col="8" data-sizex="1" data-sizey="1"></li>
<li id="li21" data-row="4" data-col="9" data-sizex="1" data-sizey="1"></li>

</ul>
</div>


Grid Elements

gridster.js

$(document).load(function () {
var grid_canvas = $(".gridster > ul").gridster( 
{ widget_margins: [3, 3],        
widget_base_dimensions: [110, 110],
       
widget_selector: "> ul"
         Define which elements are the widgets. Can be a CSS Selector string or a jQuery collection of HTML Elements.

widget_margins: [3, 3]
         Horizontal and vertical margins respectively for widgets.

widget_base_dimensions: [110, 110]
         Base widget dimensions in pixels. The first index is the width, the second is the height.


serialize_params: function($w, wgd)
{
return {
id: $($w).attr('id'),
col: wgd.col,
row: wgd.row,
size_x: wgd.size_x,
size_y: wgd.size_y,
};
},

 
 A function used to return serialized data for each each widget, used when calling the serialize method. Two    arguments are passed - $w is the jQuery wrapped HTMLElement which is used to get the id, wgd represents the grid coordinates object with keys col, row, size_x and size_y.
           
draggable: 
{
stop: function(event, ui) {
var positions = JSON.stringify(this.serialize());
localStorage.setItem('positions', positions);
$.post(
"process.php",
{"positions": positions},
function(data)
{
if(data==200)
console.log("Data successfully sent to the server");
else
console.log("Error: Data cannot be sent to the server")
}
);}
}
    }).data('gridster');

.serialize( ) creates an array of objects representing the current position of all widgets in the grid.
 Returns an Array of Objects (ready to be encoded as a JSON string) with the data specified by the serialize_params option


JSON.stringify() converts a primitive value, object or array to a JSON-formatted string that can later be parsed with JSON.parse().


localStorage.setItem('positions', positions) :
With HTML5, web pages can store data locally within the user's browser.


Note: Earlier, this was done with cookies. However, Web Storage is more secure and faster. The data is not included with every server request, but used ONLY when asked for. It is also possible to store large amounts of data, without affecting the website's performance. The data is stored in key/value pairs, and a web page can only access data stored by itself.


You can also send the serialize json array to the server using the jQuery POST method. A 'data' status of 200 implies success


draggable.stop : A callback for when dragging stops.

You can also implement other draggable options based on your requirements:
draggable.start : A callback for when dragging starts.
draggable.drag : A callback for when the mouse is moved during the dragging.



Include this gradient.js file into your index.html through the following lines :

<script type="text/javascript" src="gridster.js"></script>



Now to get the positions of the elements (remember we had stored it in the local storage),
we need to parse the items one by one by using the following lines of code:


var localData = JSON.parse(localStorage.getItem('positions'));

if(localData!=null)
{
$.each(localData, function(i,value){

    var id_name;

id_name="#";
id_name = id_name + value.id;

$(id_name).attr({"data-col":value.col, "data-row":value.row, "data-sizex":value.size_x, "data-sizey":value.size_y});

             });
}
else{
console.log('No data stored in the local storage. Continue with the default values');
}



If the local storage contains the positions, parameters for the li tag are fetched and the elements are loaded accordingly else the default grid is loaded.
You can also clear the localStorage using localStorage.clear() function.


Also instead of fetching the positions from the localStorage, if you need to fetch it from the server you can using the following code:

$.getJSON("url_here", function(data)  
{ 
if(data!=null)  
{  
$.each(data, function(i,value){       
                  var id_name;id_name="#";  
                  id_name = id_name + value.id;  
                  $(id_name).attr({"data-col":value.col, "data-row":value.row, "data-sizex":value.size_x, "data-sizey":value.size_y}); });
  }

                             else{
                                        console.log('No data returned by the server. Continue with the default positions');
                                   }
                    }  

Note: Use of local storage is not preferred for business use since a user can use the application from different machines in which case the positions cannot be retrieved. The reason behind this is it is stored in a machine's local storage and hence can only be accessed by that particular machine.

Default grid elements


Dynamic loading of grid elements

You can view the demo at:

Hope this information was useful. If you have any doubts or getting any errors just leave a comment and I will try my best to help you out.

Source: gridster.net