jQuery Sortable connectWith – how to save all changes to the database

I’ve been working on the interesting project for a friend of mine. It is system which simply allows users to upload a tutorial of their sculpture creation (greenstuffworld.com). I wanted to make the creation of the tutorial as simple as possible. The idea was to allow to add steps dynamically and sort them and also move images uploaded by the user between steps.  I decided to use http://jqueryui.com/sortable/.

Looking at the example:

Each
step is an entity and has many image entities. 

jQuery Sortable connectWith - how to save all changes to the database

The idea is to allow change the order of the steps and more important move images between steps.

However, using jQuery Sortable I found a little inconvenience.  When moving an image from Step 1 to Step 2 the update event is  called twice, for new listing in Step1 and another call for Step2 (SO Question)

This is a big problem when your section and items in it represent database persisted entities, you really want to post all changes to the server and persist it in the database.

To find my way around it I had to write up a little of a code so all changes could be posted in one call to the server.

</pre>
<div class="container">
<div class="step" id="step_1">
<h2 class="title">Step 1</h2>
<div class="image" id="image_10">Image 10</div>
<div class="image" id="image_11">Image 11</div>
<div class="image" id="image_12">Image 12</div>
</div>
<div class="step" id="step_2">
<h2 class="title">Step 2</h2>
<div class="image" id="image_21">Image 21</div>
<div class="image" id="image_22">Image 22</div>
<div class="image" id="image_23">Image 23</div>
</div>
<div class="step" id="step_3">
<h2 class="title">Step 3</h2>
<div class="image" id="image_31">Image 31</div>
<div class="image" id="image_32">Image 32</div>
<div class="image" id="image_33">Image 33</div>
</div>
</div>
<div id="result"></div>
<pre>

Than Javascript goes like this:

   $(function(){

	/* Sort steps */
	$('.container').sortable({
		axis: "y",
		update: function (event, ui) {
			var data = $(this).sortable('toArray');
			$("#result").html("JSON:
"+JSON.stringify(data)+"
");
 }
 });

 /* Here we will store all data */
 var myArguments = {};

 function assembleData(object,arguments)
 {
 var data = $(object).sortable('toArray'); // Get array data
 var step_id = $(object).attr("id"); // Get step_id and we will use it as property name
 var arrayLength = data.length; // no need to explain

 /* Create step_id property if it does not exist */
 if(!arguments.hasOwnProperty(step_id))
 {
 arguments[step_id] = new Array();
 }

 /* Loop through all items */
 for (var i = 0; i < arrayLength; i++)
 {
 var image_id = data[i];
 /* push all image_id onto property step_id (which is an array) */
 arguments[step_id].push(image_id);
 }
 return arguments;
 }

 /* Sort images */
 $('.step').sortable({
 connectWith: '.step',
 items : ':not(.title)',
 /* That's fired first */
 start : function( event, ui ) {
 myArguments = {}; /* Reset the array*/
 },
 /* That's fired second */
 remove : function( event, ui ) {
 /* Get array of items in the list where we removed the item */
 myArguments = assembleData(this,myArguments);
 },
 /* That's fired thrird */
 receive : function( event, ui ) {
 /* Get array of items where we added a new item */
 myArguments = assembleData(this,myArguments);
 },
 update: function(e,ui) {
 if (this === ui.item.parent()[0]) {
 /* In case the change occures in the same container */
 if (ui.sender == null) {
 myArguments = assembleData(this,myArguments);
 }
 }
 },
 /* That's fired last */
 stop : function( event, ui ) {
 /* Send JSON to the server */
 $("#result").html("Send JSON to the server:
"+JSON.stringify(myArguments)+"
");
 },
 });
});

If you move the image 10 from Step 1 to Step 2 the following json string will be send to the server

{"step_1":["image_11","image_12"],"step_2":["image_10","image_21","image_22","image_23"]}

The final result can be tested here: http://jsfiddle.net/r2d3/p3J8z/

You may also like...