Creating Sortable Image Groups with PHP and jQuery

Days have gone where we used to group elements using multiple select boxes. Now the power of jQuery is playing a vital role in web application design and interactions. In this tutorial I am going to show you how to create a simple application to group images quickly using jQuery features.

Creating Sortable Image Groups with PHP and jQuery

Image galleries are so popular these days. Once you complete the tutorial, use this as the admin interface for creating and managing your image galleries.

So Let’s get started. Here is what we are going to develop today.

instantShift - Sortable Image Groups

You might be wondering how you are going to create groups with this after looking at our final output. Make a guess and use the demo to see how it actually works.

Live Demo       Download Files

Once you load the demo, click on the images you want and ticks will be shown for selected images. Then enter a name and click create button to group the selected elements. Next your group will appear on the right side box. Create as many groups as you want. Then click on each group to load the images inside the group. Just drag and drop to define the ordering of images.

If you are hosting the project files on your own server make sure to upload the sql file to your database server and create the database tables first. Then include the database name, database username and password in the db_connection.php file. Now you are ready to test the demo on your own server.

Now let’s get started.

Creating Initial Layout

We need to create 3 sections for group creation form, group items and group list. I have a given a sketch of our initial layout in the following screen.

instantShift - Creating Initial Layout of Sortable Image Groups

So let’s create the layout with necessary CSS styles. Code for creating Group Form, Group Items and Group List is shown below.

<html>
  <head>
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/1.7.2/jquery.min.js"></script>
  <script type="text/javascript" src="ui/jquery.ui.core.js"></script>
  <script type="text/javascript" src="ui/jquery.ui.widget.js"></script>
  <script type="text/javascript" src="ui/jquery.ui.mouse.js"></script>
  <script type="text/javascript" src="ui/jquery.ui.sortable.js"></script>
  <link href="demos.css" rel="stylesheet">
  </head>
  <body>
    <div id="group_container">
      <div id="group_panel">
      <div id="group_panel_header">Create Group</div>
      <table>
      <tbody><tr>
      <td>Group Name</td><td><input type="text" id="group_name"></td>
      </tr>
      <tr>
      <td></td><td><input type="button" onclick="group_elements()" value="Create" id="group_creation"></td>
      </tr>
      </tbody>
      </table>
      </div>
      <div class="ui-sortable" id="user_panel">
      </div>
      <div id="group_list">
        <div id="group_list_header">Group List</div>
        <div class='group_item act' id='all_gallery' >All</div>
      </div>
      <div style='float: left;margin: 10px 0;text-align: center;width: 315px;'>
      <input type='button' onclick='delete_group()' value='Delete Group' />
      </div>
      <div style='float: left;margin: 10px 0;text-align: center;width: 315px;'>
      <input type='button' onclick='delete_images()' value='Delete Images' />
      </div>
      <div style="clear:both"></div>
    </div>
  </body>
</html>

Above code contains basic HTML and it’s self-explanatory. You can see that I have included files from jQuery UI library. These files will be used for drag and drop that we will be discussing later.

Now we have the base structure set up. Let’s move to loading initial data from database.

Generating Group and Items Lists

We have to generate items to be grouped and the list of groups available in the initial page load. I have used 2 database tables for keeping groups and items. Sql script for database tables is included in project files. Simple php codes are used to generate the initial data as shown in the sections below.

Display Group List

<div id="group_list">
  <div id="group_list_header">Group List</div>
  <div class='group_item act' id='all_gallery' >All</div>
  <?php
    $result = mysql_query("select * from gallery_groups");
    while ($row = mysql_fetch_array($result)) {
      $count++;
      echo "<div class='group_item' id='" . $row['id'] . "' >" . $row['group_name'] . "</div>";
    }
  ?>  
</div>

In above code you can see that we have a predefined group called All to get all the available items whenever we want. Then the dynamically created lists of groups are retrieved from database table and added to the group list container.

Display Image List

As we did in the previous section we can directly load all the image names from gallery_items tables as shown below.

<div id="group_items_panel">
  <?php
  $result = mysql_query("select * from gallery_items");
  $count = 0;
  while ($row = mysql_fetch_array($result)) {
    $count++;
    echo "<div id='" . $row['img_name'] . "' class='item_box'><img src='img/" . $row['img_name'] . ".jpg' /></div>";
  }
  ?>
</div>

Next thing we have to do is select the images for creating groups.

Selecting Items to Group

When we click on an image from the list, it will be marked as selected using a image with tick. I am going to use simple jQuery code to mark the elements for grouping.

<script>
	$('.item_box').live("click", function() {
	if($(this).find('.tick_image').length == 0){
		$(this).append("<div class='tick_image'><img src='tick.png' /></div>");
	}else{
		$(this).find('.tick_image').remove();
	}
	});
</script>

Code Explanation

  • jQuery live function is used to assign the click event to the images. Since these elements are generated dynamically, we cannot assign the click event with default method. Every time an image is clicked this function will be called and tick is assigned to the image.
  • You can see that all the images contain a CSS class called item_box. So using this class we are adding the tick image, if it’s not selected and removes the image if it’s selected.
  • Important thing here is we have to place the tick at the bottom and on top of the image. So we have to position the tick image relative to the image. Following CSS code will show the necessary styling’s needed. You have to change the values according to the size of images you are using.
<style>
.tick_image{
	height: 48px;
	left: -5px;
	position: relative;
	top: -45px;
	width: 48px;
}
</style>

Creating Image Groups

We have created a method to select images for grouping. Let’s see how we can create group and save in database. We are going to need Ajax here. So get ready with your Ajax knowledge. Following is the function which will be called when the user clicks the Create button.

<script>
var group_elements = function(){
	if($('#group_name').val() == ''){
		alert("Group Name Cannot be Empty");
	}else if($('.tick_image').length == '0'){
		alert("No elements to group");
	}else{
		var selected_ids = '';
		$(".tick_image").each(function() {
		selected_ids += $(this).parent().attr("id")+"-";
	});
	var data = {
		action: 'save_gallery',
		image_list: selected_ids,
		gallery_name : $('#group_name').val()
	};
	$.ajax({
		type: "POST",
		url: "ajax.php",
		data:data,
		success: function(res) {
			if(res == 'invalid'){
				alert("Group Already Exists");
			}else{
				$('#group_list').append("<div class='group_item' id='"+res+"' >"+ $('#group_name').val() +"</div>");
				$('.tick_image').remove();
				$('#group_name').val('');
			}
		}
	});           
}	
};
</script>

Now I’ll explain the code in small sections.

if($('#group_name').val() == ''){
	alert("Group Name Cannot be Empty");
}else if($('.tick_image').length == '0'){
	alert("No elements to group");
}

We have to do the validation in creating groups. First we check whether group name is empty. Then we check whether images are selected for grouping using jQuery. If at least 1 image is not ticked, we cannot move further.

var selected_ids = '';
	$(".tick_image").each(function() { 
		selected_ids += $(this).parent().attr("id")+"-";
	});
	var data = {
		action: 'save_gallery',
		image_list: selected_ids,
		gallery_name : $('#group_name').val()
	};
	$.ajax({
		type: "POST",
		url: "ajax.php",
		data:data,
		success: function(res) {
		if(res == 'invalid'){
			alert("Group Already Exists");
		}else{
			$('#group_list').append("<div class='group_item' id='"+res+"' >"+ $('#group_name').val() +"</div>");
			$('.tick_image').remove();
			$('#group_name').val('');
		}
	}
});
  • Once all the validation is completed we get the ID list of the ticked images and concatenates into a single variable using – seperator.
  • Then we prepare the data for ajax request. We create a unique action to track from the ajax file and the other variables will selected image list and group name.
  • Then we send the ajax request to ajax.php file.
  • Once it’s successfully completed, we append the new group to the group list and removes all the ticks in images to start a new group.
  • If the group name is already created, we display the error message using the alert.

Now I’ll show you the server side code to handle the above request and save the data.

<?php
if (isset($_POST['action']) && $_POST['action'] == 'save_gallery') {
	$gallery_name = $_POST['gallery_name'];
	$image_list = substr($_POST['image_list'], 0, -1);
	$sql_select = "select * from gallery_groups where group_name = '$gallery_name'";
	$result = mysql_query($sql_select);
	if(mysql_num_rows($result) == 0){
		$sql = "insert into gallery_groups(group_name,group_images) values('$gallery_name','$image_list')";
		$result = mysql_query($sql);
		echo mysql_insert_id();
	}else{
		echo "invalid";
	}
}
?>

If the action is save_gallery, we directly save the list of images and group name into to the database if the group name is not available in the database.

Displaying Group Images

I have shown you how to group images and save to database. Now you will have a list of groups in the right panel. Each time you click on a group from the list, the items in the groups should be displayed. Let’s see how it works.

<script>
$('.group_item').live("click", function() {
	$('.group_item').removeClass("act");
	$(this).addClass("act");
	$('.tick_image').remove();
	var data = {
		action: 'load_gallery',
		gallery_id: $(this).attr("id")
	};
	$.ajax({
		type: "POST",
		url: "ajax.php",
		data:data,
		success: function(res) {
			var gallery_items = res;
			gallery_items = gallery_items.split("-");
			$("#group_items_panel").html('');
			for(x=0;x<gallery_items.length;x++){
					$("#group_items_panel").append("<div id='"+gallery_items[x]+ "' class='item_box'><img src='img/"+gallery_items[x]+".jpg' /></div>");
			}
			$('.tick_image').remove();
			$('#group_name').val('');
		}
	});
});
</script>

Since groups are created dynamically, attaching click events on group elements will not work. We have to use jQuery live event to attach events to dynamic elements.

Every time a group_item is clicked we change the active group to the clicked one by changing the act class.

Then we make the ajax request with ID of the group. Then server side ajax function will return the images of that particular group.

Next we split the list of image names and appends to the images panel.

Also we need to remove ticked items and group name.

Following is the server side code to handle loading group images.

<?php
if (isset($_POST['action']) && $_POST['action'] == 'load_gallery') {
  $gallery_id = $_POST['gallery_id'];
  if ($gallery_id != 'all_gallery') {
    $sql = "select * from gallery_groups where id='$gallery_id'";
    $result = mysql_query($sql);
    $gallery = mysql_fetch_object($result);
    echo $gallery->group_images;
  } else {
    $sql = "select * from gallery_items ";
    $result = mysql_query($sql );
    $images = '';
    while ($row = mysql_fetch_array($result)) {
    	$images .= $row['img_name'] . "-";
    }
    echo substr($images, 0, -1);
  }
}
?>

Deleting Groups

Now we need to add functionality to delete groups. When the delete button is clicked, active group will be deleted and images of ALL group will be displayed. Lets look at the source code.

<script>
var delete_group = function(){
	if($('.act').attr('id') != 'all_gallery'){
		var group_id =  $('.act').attr('id');  
		var data = {
			action: 'delete_gallery',
			group_id: group_id
		};
		$.ajax({
			type: "POST",
			url: "ajax.php",
			data:data,
			success: function(res) {
				if(res == 'success'){
					alert("Group Deleted Successfully");
					var data = {
						action: 'load_gallery',
						gallery_id: 'all_gallery'
					};
					$.ajax({
						type: "POST",
						url: "ajax.php",
						data:data,
						success: function(res) {
							var gallery_items = res;
							gallery_items = gallery_items.split("-");
							$("#group_items_panel").html('');
							for(x=0;x<gallery_items.length;x++){
								$("#group_items_panel").append("<div id='"+gallery_items[x]+ "' class='item_box'><img src='img/"+gallery_items[x]+".jpg' /></div>");
							}
							$('.tick_image').remove();
							$('#group_name').val('');
							$('.act').remove();
							$('#all_gallery').addClass('act');
						}
				});
			}
		}
	}); 
	}else{
		alert("All items cannot be delete");
	}
};
</script>
  • When delete button is clicked, we get the ID of the active group and make an ajax request to delete the group.
  • If the delete process is completed we display the success message using an alert box.
  • Then we create another ajax request to load the images of ALL group.
  • Finally we remove the active group from the list and assigns active class to ALL group.

Following is the server side code to handle delete groups.

<?php
if (isset($_POST['action']) && $_POST['action'] == 'delete_gallery') {
	$gallery_id = $_POST['group_id'];
	$sql = "delete from gallery_groups where id='$gallery_id'";
	$result = mysql_query($sql);
	if ($result) {
		echo "success";
	}
}
?>

Now we are almost done in creating and loading image groups to be used in image galleries. We need to be able to change the order of images in the gallery. Let’s work on that part.

Sorting Gallery Images

We can easily change the ordering of the images using sortable function provided by jQuery UI library. Once you assign sortable to images, you will be able to drag and drop images to change the positions. Let’s take a look at the code.

<script>
$("#group_items_panel").sortable({
	opacity: 0.6,
	cursor: 'move',
	update: function() {
		if($('.act').attr('id') != 'all_gallery'){
		}
	var selected_ids = '';
	$(".item_box").each(function() { 
		selected_ids += $(this).attr("id")+"-";
	});
	var data = {
		action: 'update_gallery',
		image_list: selected_ids,
		gallery_id : $('.act').attr('id')
	};
	$.ajax({
		type: "POST",
		url: "ajax.php",
		data:data,
		success: function(res) {
		}
	});
	}
});
</script>
  • I have assigned the sortable method to group_items_panel which holds all the images. Now you will be able to drag and drop all the images.
  • First we check if All images group is clicked. We don’t have to order elements in All image section.
  • Every time you drag and drop an image, this sortable method will be called.
  • When image position is changed using drag and drop, we send the image list back to the server to be updated on database.
  • Following code will show you how we update the group images in the database.
<?php
if (isset($_POST['action']) && $_POST['action'] == 'update_gallery') {
  $gallery_id = $_POST['gallery_id'];
  $image_list = substr($_POST['image_list'], 0, -1);
  $sql = "update gallery_groups set group_images='$image_list' where id='$gallery_id'";
  $result = mysql_query($sql);
}
?>

Deleting Group Images

Once the images are added to a group, we should be able to delete them as well. In this section I’ll show you how to complete the deleting process using the tick mechanism we used earlier.

<script>
var delete_images = function(){
	if($('.act').attr('id') != 'all_gallery'){
		if($(".tick_image").length == 0){
			alert("Please select images to remove");
		}else{
			var selected_ids = '';
			$(".tick_image").each(function() {
				$(this).parent().remove();
			});
			var selected_ids = '';
			$(".item_box").each(function() {
				selected_ids += $(this).attr("id")+"-";
			});
			var data = {
				action: 'update_gallery',
				image_list: selected_ids,
				gallery_id : $('.act').attr('id')
			};
			$.ajax({
			type: "POST",
			url: "ajax.php",
			data:data,
			success: function(res) {
			}
		});
	}
	}else{
		alert("All group images cannot be delete");
	}
};
</script>
  • When the delete images button is clicked, we check if the active group is ALL group. If so we provide an error message since we don’t want to delete all images section.
  • Then if at least one image is ticked for deletion, we remove the ticked images from the screen.
  • Next we get the remaining items in the group box and call the ajax request to update_gallery action, as we did in the sorting section.
  • Now the deleted images will not be available when you click the group again.

We have completed our goal of grouping images with ordering to create beautiful galleries. You can use this as an admin interface for creating image galleries. Just write simple code to receive the images for any given group and use it in you preferred image gallery plugin or slider.

Looking forward to your suggestions.

Like it? Share it.

8 Comments

  1. Instant Shift continues to amaze me. Be it planning career, design or development, you folks are the best!

    Many thx for this tutorial and everything that you post. Looking forward to more.

  2. I suggesting adding a shift click/ multiple selection feature using this: http://code.google.com/p/jquery-checkbox/source/browse/trunk/jquery.shiftclick.js?r=4

  3. Very interesting, easy and useful for everyone. Thanks for sharing.

  4. Hello Rakhitha, I Love this Script a lot ;o) Last 2 Days i combined it with the jquery multiple uploader and made it useful for me with user_id`s in the groups and items. Everything went fine!
    There is only one thing i`m not happy about it… the script displays 1 empty picture when it has a empty database…. ;o) But it`s still great to implement it for many ways!!
    Cheers man, great applause for sharing this ! Keep going with your delicious coding stuff and write other superscripts ;o)

    Get this script folks, the best you can find for now……

  5. Dear author! Unfortunately the code you showed us is vulnerable to SQL injection attack. It’s interesting topic, so I just wish you enjoying)))

Leave a Comment Yourself

Your email address will not be published. Required fields are marked *

You may use these HTML tags and attributes: <a href="" title=""> <abbr title=""> <acronym title=""> <b> <blockquote cite=""> <cite> <code> <del datetime=""> <em> <i> <q cite=""> <strike> <strong>