Tagging Pictures! Complete Example Explained with jQuery and PHP

9:14 AM Mahder Alemayehu 1 Comments

Recently I have been getting many questions from my readers and former students asking me to develop and show how a picture tagging works using jQuery and php. I have been using this functionality in one of my projects. Hence I decided to grab the codes and develop a quick app showing exactly how to tag a picture using jquery and php.

In this post, I will try to show how we can use jQuery and php to store tag values from a picture in to a database and show the tagged values to the page when the user hovers the mouse pointer to the picture that was tagged.

For this case, I have use the following:

1. php
2. mysql
3. jquery (you can grab the latest version from http://jquery.com/download/)
4. netbeans IDE (you can use any compatible text editor)

I will try to provide different screen captures to show how the whole project is structured and developed.

Project Structure:

As you can see from the above picture, I have categorized the different files under the appropriate folders.

In this project we have two classes and the class files are stored under a folder named "Classes".

classes folder:
A. DBConnection.php: This class is used to establish a database connection and handles also writing and reading data to and from the table.

B. NameTag.php: This class encapsulate the attributes that we are interested in saving to the database. This class is used to create instance of the NameTag class and then we can save data to the database table or read data from the table. This class in turn will communicate with DBConnection.php class to get its instances saved to the database or to get all name tag records saved for a particular image.

css folder:
This folder is dedicated to containing any css related files. In our case the 'tag_style.css' which is an external css file is defined under this folder.

db_script folder:
This folder is dedicated to store any .SQL file which you may have used in creating database, table and stored-procedures or other database related activities.

images folder:
This folder should contain any image that the web app/site is using. In our case, I have grabbed a random picture from the internet for tagging purpose.

js folder:
If you have any external .js (javascript) files you need to store them in a folder dedicated to hold all javascript files under such a folder. In this example, our jQuery library is saved under this folder.

The .php filers (index.php and savetag.php) are stored under the root folder. so if you type www.tagphoto.com then you will be redirected to www.tagphoto.com/index.php. You can modify this project structure as you wish. But you should always remember to organize your files under a self descriptive folders so when you come back later to maintain the application you don't waste a lot of time where each file is under.

Now let us step by step see how the name tagging could be developed.

STEP 1: Database And Table Creation:
The following picture shows the script I have used in creating the database and the table:


N.B: I have made the person_name and image id columns to be unique for every record in table tbl_name_tag. The reason for this is, to avoid any identical name tagging in the same picture. For example if you develop this application and try to give the same name for more than one person in the example image, it will not be saved. If you want to have name duplicates in the same image, just simply ignore the line # 11.

STEP 2: Create the DBConnection File Under 'classes' folder:

The content of this file is given as follows:

<?php
/**
 * Description of DBConnection
 *
 * @author Mahder
 */
class DBConnection {
    private static $DATABASE_NAME = 'db_photo_tagging';
    /**
     * This method is used to establish a connection to the database
     * @return db connection
     */
    public static function connect()
    {      
        $server = "localhost";      
        $username = "root";
        $password="root";
        $connection = mysql_pconnect($server, $username, $password);
        return $connection;
    }

    /**
     * This method is used to write data to the database (do action)
     * A wrapper method around the build in mysql_query() function.
     * @param type $query : SQL values passed from the caller methods
     * @return type: $result,
     */
    public static function writeToDatabase($query)
    {
        $dbConnection = DBConnection::connect();              
        mysql_select_db(DBConnection::$DATABASE_NAME);      
        $result = mysql_query($query);            
        return $result;
    }

    /**
     *
     * @param type $query - Basically SQL SELECT statements from the caller
     * methods. This method in turn will call the writeToDatabase method. I
     * know the name does not make sense but basically we are using mysql_query...
     * @return type
     */
    public static function readFromDatabase($query)
    {        
        $result = DBConnection::writeToDatabase($query);      
        return $result;
    }
 
}//end class
?>

I have tried to add comments under each method. The only modification you need to do if you want to use this DBConnection class is, to just change the $username and $password values under the connect() method.

STEP 3: Create the Entity Class NameTag.php


This is the representation of the underlying database table tbl_name_tag. Using this class we can save or read what ever values are stored in this table. The content of this file is given below:

<?php

/*
 * To change this template, choose Tools | Templates
 * and open the template in the editor.
 */

/**
 * Description of NameTag
 *
 * @author Mahder
 */
require_once 'DBConnection.php';
class NameTag {
    private $id;
    private $personName;
    private $imageId;
    private $posTop;
    private $posLeft;
 
    function __construct($personName,$imageId, $posTop, $posLeft) {
        $this->personName = $personName;
        $this->imageId = $imageId;
        $this->posTop = $posTop;
        $this->posLeft = $posLeft;
    }
 
    public function getId() {
        return $this->id;
    }

    public function setId($id) {
        $this->id = $id;
    }

    public function getPersonName() {
        return $this->personName;
    }

    public function setPersonName($personName) {
        $this->personName = $personName;
    }

    public function getPosTop() {
        return $this->posTop;
    }

    public function setPosTop($posTop) {
        $this->posTop = $posTop;
    }

    public function getPosLeft() {
        return $this->posLeft;
    }

    public function setPosLeft($posLeft) {
        $this->posLeft = $posLeft;
    }
 
    public function getImageId() {
        return $this->imageId;
    }

    public function setImageId($imageId) {
        $this->imageId = $imageId;
    }

 
    public function saveNameTag(){
        try{
            $query = "insert into tbl_name_tag values(0,'$this->personName',
                    '$this->imageId',$this->posTop,$this->posLeft)";          
            DBConnection::writeToDatabase($query);
        }catch(Exception $e){
            $e->__toString();
        }
    }
 
    public static function getAllNameTagsForImage($imageId){
        $nameTags = null;
        try{
            $query = "select * from tbl_name_tag where image_id = '$imageId'";
            $result = DBConnection::readFromDatabase($query);
            if($result != null){              
                $nameTags = $result;
            }
        }catch(Exception $e){
            $e->__toString();
        }    
        return $nameTags;
    }

}//end class

?>

STEP 4: Add the Appropriate Files Under Their Respective Folders.

As described under the project structure section, you are supposed to put the different files the project uses in the folder created for holding them. Please download the latest jquery library from the internet. You can use any picture you can get from the internet that can be used for tagging. e.g group of people, animals, objects etc.

The following picture shows the content of the CSS file I have used for this project.




STEP 5: Create the index.php and savetag.php Files

The two files are important and I will try to show the contents of each file here with.

<!--import the jQuery lib from the js folder-->
<script type="text/javascript" src="js/jquery-1.10.2.min.js"></script>
<!--link the document with the css file (external css)-->
<link href="css/tag_style.css" rel="stylesheet" type="text/css"/>
<html>
    <head>
        <meta http-equiv="Content-Type" content="text/html; charset=UTF-8">
        <title></title>
    </head>
    <body>
        <?php
            require_once 'classes/NameTag.php';
            //you can have more than one image in a page, so bring all the tagas
            //for a particular image only.
            $nameTags = NameTag::getAllNameTagsForImage('imgtag');
            
            while($nameTagsRow = mysql_fetch_object($nameTags)){
                $personName = $nameTagsRow->person_name;
                $posTop = $nameTagsRow->pos_top;
                $posLeft = $nameTagsRow->pos_left;
                ?>
                    <!--Position the div according to the value in the database-->
                    <div id='taggedPic' style="top:<?php echo $posTop;?>;left:<?php echo $posLeft;?>">
                        <?php
                            echo $personName;
                        ?>
                    </div>
                <?php
            }//end while...loop
                
        ?>
        <img src='images/tagpicture.png' border='0'name='imgtag' id='imgtag'/>
        <!--the hidden text field is used to hold the clicked pic id value-->
        <input type="hidden" name="hiddenimageid" id="hiddenimageid"/>
        <div>
            <input type='text' name='txtname' id='txtname'/>
        </div>
    </body>
</html>

<script type="text/javascript">
    $(document).ready(function(){
        
        $('#imgtag').click(function(e){
            //get the x and y coordinates of the click on the image
            var posTop = e.clientY;
            var posLeft = e.clientX;
            //get the id value of the clicked image
            var imageId = $(this).attr('id');
            //store the imageId in the hidden text field component
            $('#hiddenimageid').val(imageId);
            //adjust the location (css attribute) of text field via jquery
            $('#txtname').css('top',posTop-10).css('left',posLeft-20);
            //after adjusting show and put the cursor inside the text field
            $('#txtname').show().focus();
        });//end imgtag click
        
        $('#txtname').keyup(function(e){
            //check if the pressed and release key is 'Enter' key
            if(e.keyCode === 13){
                //get the values of txtname content, top left point x and y coordinate
                var personName = $(this).val();
                var posTop = $(this).position().top;
                var posLeft = $(this).position().left;
                //contains the hidden image id of the image you are tagging
                var imageId = $('#hiddenimageid').val();
                var dataString = "personName="+personName+"&posTop="+
                    posTop+"&posLeft="+posLeft+"&imageId="+imageId;
                //when enter key is released save data to database...
                $.ajax({
                    type:'POST',
                    data:dataString,
                    url:'savetag.php',        
                    success:function(data) {
                      //after saving refresh the page  
                      location.reload();
                    }
                });            
                
            }//end if
        });//end keyup function
        
    });//end document.ready
</script>

The content of savetag.php is shown below in the figure:


As you can see from the picture, this file gets the values sent from the jQuery.ajax call and stores them in a variable. ($personName,$posTop,$posLeft and $imageId).

Then using these variables, it creates an object from NameTag class and calls the saveNameTag() method to save the values to the database.

If you combine the above files in the order described in this post, you should be able to see the following out put window.

1. When you run the project, you will see the index page showing the sample picture


2. Try clicking on one person:
As you can see I have clicked on the first person (left extreme) and the text box is showing ready to take the name of the person. Try typing name value and press the enter key. You should get the next picture when you hover the mouse on the exact location you have tagged the person.

3. Types a Name on the Picture and After saving Moved mouse pointer to tag location:


This is how you can simple use jQuery and PHP to create your own tagging app. Feel free to customize the code in whatever way you would like to use. You might also want to modify this code if

1. You have more than one taggable image in a single page or
2. If the user uploads the picture and wants to tag the uploaded picture.

The basic is very similar and I am sure if you have made it this far, you can do your own imagination and creativity to this code.

I hope this will be of importance to some one out there. If you have any question or comment about this post, plz add your comments below or use my email mahderalem@gmail.com

Thanks,
Mahder

1 comments: