Edit in JSFiddle

////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////
// JQUERY "lasso" Extension  to capture points
//
//
$.fn.extend({
  lasso: function () {
     this.mousedown(function (e) {
        // left mouse down switches on "capturing mode"
        if (e.which === 1 && !$(this).is(".lassoRunning")) {
          $(this).addClass("lassoRunning");
          $(this).data("lassoPoints", []);
          $(this).trigger("lassoBegin");
          $(this).css("cursor","crosshair");
          return false;
        }  
      });
      this.mouseup(function (e) {
        // left mouse up ends "capturing mode" + triggers "Done" event
        if (e.which === 1 && $(this).is(".lassoRunning")) {
          $(this).removeClass("lassoRunning");
          $(this).trigger("lassoDone", [$(this).data("lassoPoints")]);
          $(this).css("cursor","default");
            
        }
      });
      this.mousemove(function (e) {
        // mouse move captures co-ordinates + triggers "Point" event
        if ($(this).is(".lassoRunning")) {
           //$(this).css("cursor","crosshair");
          //var offsetX, offsetY;
          /////////////////////////////////////////////
          // Below if-block-code is to make e.offsetX, e.offsetY work in Firefox
          //
          
          // Below if-block-code is from - http://bugs.jquery.com/ticket/8523
          //	-- this is working partially
          /*
          if(typeof e.offsetX === "undefined" || typeof e.offsetY === "undefined") {
          	var targetOffset = $(e.target).offset();
           	offsetX = e.pageX - targetOffset.left;
           	offsetY = e.pageY - targetOffset.top;
          }
          */
          var offsetX = (e.offsetX || e.pageX - $(e.target).offset().left);
          var offsetY = (e.offsetY || e.pageY - $(e.target).offset().top);
          /*
          // Below if-code-block is from - http://www.codewrecks.com/blog/index.php/2009/01/02/firefox-and-missing-offsetx-value-from-event-object/
          // -- this is not working at all
          if (typeof e.offsetX === "undefined") {
              //e.offsetX = (e.pageX - $(element).offset().left);
              //e.offsetY = (e.pageY - $(element).offset().top);
              e.offsetX = e.layerX - $(e.target).position().left;
              e.offsetY = e.layerY - $(e.target).position().top;
          }
          */
          ///////////////////////////////////
            
          //var point = [e.offsetX, e.offsetY];
          var point = [offsetX, offsetY];
          //var point = [e.pageX, e.pageY];
          $(this).data("lassoPoints").push(point);
          $(this).trigger("new_lassoPoint_detected", [point]);
            
            return false;
        }
      });
      return this;
      
  }
});
////////////////////////////////////////////////////////////////////////////
////////////////////////////////////////////////////////////////////////////




var Tool_Enabled = false;
var tmp_array = [];  // will hold 'element' objects created as user is drawing something
var main_array = []; // will hold all the FULL 'element' objects created using Raphael
var circle_element;
var rectangle_element;
var final_rectangle, final_circle;
var stroke_opacity = 0.1;
var fill_opacity = 0.1;

//////////////////////////////////////////////////////////////////////////
//                         GET FROM SERVER
// 2 things need to come from the server:
// 1. Mode (whether "user" or "admin")
// 2. JSON data
//////////////////////////////////////////////////////////////////////////
var Mode = "admin"; 

var ShapesJSONData = { 
        list: [
                {
                  id:1,
                  shape: 'path',
                  shape_properties: { d: 'M253,325L45,56L675,300'} ,
                  name: 'Item AAAAAAA',
                  price: '$100',
                  description: 'Item A is a great product with great features'
                },
                {
                  id:2,
                  shape: 'circle',
                  shape_properties: { cx:75, cy: 25, r: 20},
                  name: 'Item BBBBBB',
                  price: '$200',
                  description: 'Item B is even better than A'
                },
                {
                  id:3,
                  shape: 'rectangle',
                  shape_properties: {x1:10, y1: 10, width: 50, height: 50},
                  name: 'Item CCCCCC',
                  price: '$300',
                  description: 'Item C is also a great product with great features'
                }
            ]
};
////////////////////////////////////////////////////////////////////////////



////////////////////////////////////////////////
// Depending on Mode (whether Admin or User), show the drawn shapes or hide them
if (Mode.toLowerCase() === "user") {
    stroke_opacity = 0.1;    // These 2 values will be 0 or 0.01 finally
    fill_opacity = 0.1;
}
else {
    stroke_opacity = 0.3;
    fill_opacity = 0.3;
}
///////////////////////////////////////////////    

var shape_selected = 'polygon';
//var shape_selected = 'circle';
//var shape_selected = 'rectangle';

function SelectShape() {
	shape_selected = $('input:radio[name=shape11]:checked').val();
    log("shape_selected = " + shape_selected);
    //$('#SelectShapeDiv').dialog("close");
    EnableDrawing();
}

function EnableDrawing() {
    if ($('input:radio[name=shape11]:checked').length === 0) {
        alert("Please select a Shape");
        return;
    }
    if (!Tool_Enabled) {
        try {
            if ($("#SaveDialog").dialog( "isOpen" ) === true) {
                alert("SAVE dialog seems to be open.. Please close it before drawing again");
            return;
            }
        }
        catch (err) {
            Tool_Enabled = true;
        }
        Tool_Enabled = true;
    }
    $('#btnEnableDrawing').attr("disabled","disabled");
}

$(document).ready(function() {
    
    if ($('html > body').attr("id") === undefined) {
        $('html > body').attr("id","body_id"); 
    }
    paper = Raphael($('html > body').attr("id"));
    
    // Fix svg's height & width bug - svg height & width not spanning the document
    $('svg').height($(document).height());
	$('svg').width($(document).width());
    
    
    
    // If some shapes are there in JSON string, show them (irrespective of whether it is Admin or User)
    try {
        if (ShapesJSONData.list.length != 0) {
            CreateShapesFromArray(ShapesJSONData,paper);
            //return;
        }
    }
    catch(err) 
    {
    }
    
    
    // Show/Enable Drawing Tool only in Admin mode 
    if (Mode.toLowerCase() === "admin") {
        var PrevPoint = [-1,-1];
        
        $('#SelectShapeDiv').dialog({ position: { my: "right top", at: "right top", of: window } });
        
        $('body').lasso()
        .on("lassoBegin", function(e, lassoPoints) {
            if (!Tool_Enabled) return;
            
            //$('body').css("cursor","crosshair");
            PrevPoint[0] = -1; 
            PrevPoint[1] = -1;
            
            switch(shape_selected) {
               case 'polygon':
                    log("Lasso Begins.. Here are the points");
                    break;
               case 'circle' :
                   log("Circle Begins..");
                   break;
               case 'rectangle' :
                   break;
               default:
                   break;
                  
           }  		
        })
        .bind("new_lassoPoint_detected", function (e, lassoPoint) {
            if (!Tool_Enabled) return;
            
            if (PrevPoint[0] == -1 && PrevPoint[1] == -1) {
                PrevPoint[0] = lassoPoint[0]; 
                PrevPoint[1] = lassoPoint[1];     
                
                return;
            } 
            
            switch(shape_selected) {
                case 'polygon':
                                    
                      var path = 'M' + PrevPoint[0] + ',' + PrevPoint[1] + 'L' + lassoPoint[0] + ',' + lassoPoint[1];
                      // Add line from PrevPoint to new point to the path, so that the user sees  the path as he/she is drawing it. These will be cleared in 'lassoDone' event, and the entire array of lassoPoints is drawn again as 1 path element
                      var path_element = paper.path(path);
                      //var path_element = Raphael.path2curve(path);
                      // path_element.attr('fill', '#FFD');
                      if (path_element !== undefined) {
                          //path_element.attr('stroke-opacity',0.2);
                          path_element.attr('stroke-opacity',stroke_opacity);
                          PrevPoint[0] = lassoPoint[0]; 
                          PrevPoint[1] = lassoPoint[1];
                          
                          tmp_array.push(path_element);
                        
                        //Raphael.pathBBox(path_element);
                        
                        log(lassoPoint[0] + "," + lassoPoint[1]);
                    }
                    
                    break;
                case 'circle':
                   
                    // calculate radius using starting point
                    var x1 = PrevPoint[0]; var y1 = PrevPoint[1];
                    var x2 = lassoPoint[0]; var y2 = lassoPoint[1];
                    //var radius = Math.sqrt((x2-x1)*(x2-x1) + (y2 - y1)*(y2-y1));
                    var centerX = x1 + (x2-x1)/2;
                    var centerY = y1 + (y2-y1)/2;
                    var radius = Math.sqrt((x2-centerX)*(x2-centerX) + (y2 - centerY)*(y2-centerY));
                    //log ('circle parameters = ' + x1 + ',' + y1 + ',' + radius); 
                    
                    // clear prev drawn circle 
                    if (circle_element !== undefined) circle_element.remove();
                    // draw new circle
                    //circle_element = paper.circle(x1, y1, radius);
                    circle_element = paper.circle(centerX, centerY, radius);
                    break;
                case 'rectangle':
                     // calculate width & height using starting point
                    var x1 = PrevPoint[0]; var y1 = PrevPoint[1];
                    var x2 = lassoPoint[0]; var y2 = lassoPoint[1];
                    var width = Math.abs(x2-x1);
                    var height = Math.abs(y2-y1);
                                         
                    //log ('rectangle parameters = ' + x1 + ',' + y1 + ',' + radius); 
                    
                    // clear prev drawn rectangle 
                    if (rectangle_element !== undefined) rectangle_element.remove();
                    // draw new rectangle
                    rectangle_element = paper.rect(x1, y1, width, height);
                    break;
                default:
                    break;
            }
           
        })
        .on("lassoDone", function (e, lassoPoints) {
            //$('body').css("cursor","default");
            if (!Tool_Enabled) return;
           
            log("Lasso Done");
            
            // Disable the Lasso Tool. We'll enable it only when user clicks a button in Save Dialog
            Tool_Enabled = false; 
            
            if ($('#btnEnableDrawing').attr("disabled") != undefined) 
                $('#btnEnableDrawing').removeAttr("disabled");
            
            //$('input:radio[name=shape11]:checked').removeAttr("checked");
            
            switch(shape_selected) {
                case 'polygon':
                    // From 'paper' - Remove all path elements created in "new_lassoPoint_detected" event
                    $(tmp_array).each(function() { 
                        this.remove(); 
                    });
                    // From tmp_array - Remove all 
                    tmp_array.splice(0,tmp_array.length);                  
                    
                    // $('svg:last path').remove(); 
                    if ( lassoPoints.length == 0 ) return;
                    var start_lassoPoint = lassoPoints[0]; 
                    var path = 'M' + start_lassoPoint[0] + ',' + start_lassoPoint[1];
                    for (var i=1;i < lassoPoints.length; i++) {
                        var lassoPoint = lassoPoints[i];
                        path += 'L' + lassoPoint[0] + ',' + lassoPoint[1];
                    }
                    path = path + 'Z';// Z - to close the path
                    SelectedArea = paper.path(path);	// create a path element 
                    if (SelectedArea != undefined) {
                        AddColorAndHandlersTo(SelectedArea);
                        $('#SaveDialog').data("element", SelectedArea).dialog({close: ResetSaveDialog});
                    }
                    break;
                case 'circle':
                    if (circle_element != undefined) {
                        final_circle = circle_element.clone();
                        circle_element.remove();
                        AddColorAndHandlersTo(final_circle);
                        $('#SaveDialog').data("element", final_circle).dialog({close: ResetSaveDialog});
                    }
                    break;
                case 'rectangle':
                    if (rectangle_element != undefined) {
                        final_rectangle = rectangle_element.clone();
                        rectangle_element.remove();
                        AddColorAndHandlersTo(final_rectangle);
                        $('#SaveDialog').data("element", final_rectangle).dialog({close: ResetSaveDialog});
                    }
                    break;
                default:
                    break;
            }
        })
        /*
        .bind("contextmenu", function(e) {
            $('#SelectShapeDiv').dialog();
            return false;
         });
         */
    }
});

function AddColorAndHandlersTo(ele) {
    if (ele === undefined || ele === null) return;
    
    ele.attr('fill','#000');
    //ele.attr('fill-opacity',0.1);
    //ele.attr('stroke-opacity',0.1);
    ele.attr('fill-opacity',fill_opacity);
    ele.attr('stroke-opacity',stroke_opacity);
    
    
        ele.dblclick(EditElement);
        main_array.push(ele);		// add it to main_array
    
    //$('#SaveDialog').data("element", ele).dialog({close: ResetSaveDialog});
    
    //ele.hover(hover_in, hover_out);
}


function hover_in () { 
    try {
    if ($("#SaveDialog").dialog( "isOpen" ) === true)
        return;
    }
    catch(err)
    {
    }
    //document.getElementById('SomeText').style.display = 'block';
    var Name = this.data("Name");
    var Price = this.data("Price");
    var Description = this.data("Description");
    
    $('#txtName_Display').val(Name);
    $('#txtPrice_Display').val(Price);
    $('#txtDescription_Display').val(Description);
    $('#DisplayDialog').dialog( {
        show: 'fade'//,
    	//hide: 'fade'
    });
    
}

function hover_out () { 
    //document.getElementById('SomeText').style.display = 'none';
    if ($("#DisplayDialog").dialog( "isOpen" ) === true)
    	$('#DisplayDialog').dialog("close");
}

function Remove() {
 	//Remove shape
    var element = $('#SaveDialog').data("element") ;
    
    // If element exists on server-side, i.e in database, send Ajax call to remove it
    if (element.data("id") != undefined)
        AjaxMethod("/Remove_URL", element.data("id"));
    
    // Remove element from Javascript array on client-side
    //delete element;
    for (var i = 0; i<main_array.length; i++) {
        if (element === main_array[i])
            break;
    }
    main_array.splice(i,1);
    
    // Ask Raphael to remove the element from webpage
    element.remove();  
    
    Cancel();
       
}

function Cancel() {
    ResetSaveDialog();
    
  	//Close the dialog
    if ($("#SaveDialog").dialog("isOpen") === true)
  		 $("#SaveDialog").dialog("close");
    
    //ShowShapesSelectorDialog();
}

function ShowShapesSelectorDialog() {
    $('#SelectShapeDiv').dialog();
}

function ResetSaveDialog() {
    var ele = $('#SaveDialog').data("element");
    ele.hover(hover_in, hover_out);
    
    $('#txtDescription').val("");
    $('#txtName').val("");
    $('#txtPrice').val("");
    
    // Enable the Lasso Tool
    //Tool_Enabled = true;
}



function Save() {
 // STEP 1 - Add values to .data property of shape element 
 // STEP 2 - Add values & Path string to ARRAY 
 // STEP 3 - Close the dialog
    var element = $('#SaveDialog').data("element") ;
    
    var dom_element = element.node ;
    var type_of_element = $(dom_element).prop('tagName').toLowerCase();
    
    switch(type_of_element) {
        case 'path':
            path = $(dom_element).attr("d");
            log(path);
            break;
        case 'circle':
            radius = $(dom_element).attr("r");
            cx = $(dom_element).attr("cx");
            cy = $(dom_element).attr("cy");
            break;
    }
    
    //var path = $('#SaveDialog').data("path") ;
    
    //element.data("path", path);
    element.data("Name", $('#txtName').val());
    element.data("Price", $('#txtPrice').val());
    element.data("Description", $('#txtDescription').val());
    $('#SaveDialog').dialog("close");
    
    // Clear fields in Save Dialog
    $('#txtName').val("");
    $('#txtPrice').val("");
    $('#txtDescription').val("");
    
    //Tool_Enabled = true;
    
    //ShowShapesSelectorDialog();
}

function EditElement() {
   if (Mode.toLowerCase() === "user") {   // GET FROM SERVER 
       return;
   }
    
   try {
       if ($("#DisplayDialog").dialog( "isOpen" ) === true)
             $("#DisplayDialog").dialog( "close" );
       
       if ($("#SaveDialog").dialog( "isOpen" ) === true)
             $("#SaveDialog").dialog( "close" );
    }
    catch(err)
    {
    }
    
	var element = this;
	if (element.data("Name")) $('#txtName').val(element.data("Name"));     
    if (element.data("Price")) $('#txtPrice').val(element.data("Price"));
    if (element.data("Description")) $('#txtDescription').val(element.data("Description"));
    
    $("#SaveDialog").data("element", element).dialog();
}

function CreateShapesFromArray(arr, paper) {
    for (var i = 0; i < arr.list.length; i++ ) {
      var element = arr.list[i];
      
      switch(element.shape) {
        case 'path':
          //console.log(element.shape_properties.d);
          var path = paper.path(element.shape_properties.d);
          path.data("Name", element.name);
          path.data("Price", element.price);
          path.data("Description", element.description);
          AddColorAndHandlersTo(path);
          path.hover(hover_in, hover_out);
          path.data("Id", element.id);
          break;
        case 'circle':
          var radius = element.shape_properties.r; 
          var cx =  element.shape_properties.cx;         
          var cy =  element.shape_properties.cy;
          var circle = paper.circle(cx, cy, radius);
          
          circle.attr({fill: "blue"});
          circle.data("Name", element.name);
          circle.data("Price", element.price);
          circle.data("Description", element.description);
          AddColorAndHandlersTo(circle);
          circle.hover(hover_in, hover_out);
          circle.data("Id", element.id);
          break;
        case 'rectangle':
          //console.log(element.shape_properties.y2);
          var x1 = element.shape_properties.x1;var y1 = element.shape_properties.y1;
          var width = element.shape_properties.width;var height = element.shape_properties.height;
          var rect = paper.rect(x1,y1,width,height);
          rect.attr({fill: "green"});
          rect.data("Name", element.name);
          rect.data("Price", element.price);
          rect.data("Description", element.description);
          AddColorAndHandlersTo(rect);
          rect.hover(hover_in, hover_out);
          rect.data("Id", element.id);
          break;
      }
    }
}

function SaveAllChanges() {
    //alert("Code to save all changes goes here");
    var Update_URL = "";
    var Insert_URL = ""; 
    
    $(main_array).each(function() {
        var ele = this;
        var dom_element = ele.node ;
        var type_of_element = $(dom_element).prop('tagName').toLowerCase();
        var d = ""; // will be filled for PATH element
        var cx ="", cy = "", r = ""; // will be filled for CIRCLE element
        var x = "", y = "", width="", height = ""; // will be filled for RECTANGLE element
        
        var AjaxCallURL, id;
        if (ele.data("Id") != undefined) { // Presence of "id" indicates whether element is a new element or not
            AjaxCallURL = Update_URL;
            id = ele.data("Id");
        }
        else {
            AjaxCallURL = Insert_URL;
            id = -1;
        }
        switch(type_of_element) {
            case "path":
                d = $(dom_element).attr('d').toString();
                AjaxMethod(AjaxCallURL,"shape",type_of_element,"id", id, "name",ele.data("Name"),"description", ele.data("Description"), "price", ele.data("Price"), "d", d);
                break;
            case "circle":
                cx = $(dom_element).attr('cx').toString();
                cy = $(dom_element).attr('cy').toString();
                r = $(dom_element).attr('r').toString();
                AjaxMethod(AjaxCallURL,"shape",type_of_element,"id", id, "name",ele.data("Name"),"description", ele.data("Description"), "price", ele.data("Price"), "cx", cx, "cy", "r", r);
                break;
            case 'rect':
                x = $(dom_element).attr('x').toString();
                y = $(dom_element).attr('y').toString();
                width = $(dom_element).attr('width').toString();
                height = $(dom_element).attr('height').toString();
                AjaxMethod(AjaxCallURL,"shape",type_of_element,"id", id, "name",ele.data("Name"),"description", ele.data("Description"), "price", ele.data("Price"), "x", x, "y", y, "width", width, "height", height);
                break;
        }     
    });
}

function AjaxMethod() {
    // Ajax call to server - Send values to server
    // 1st value - Update URL or Insert URL
    // 2nd value - shape (whether "path", "rect", "circle")
    // 3rd value - id (this is probably a column value of a row in the database)
    // Rest of the values depend on the shape :
    //    For Circle: cx, cy, r
    //    For Path: d
    //    For Rectangle: x,y,width,height
}


<html>
<body>
    <div id="SelectShapeDiv" style="display:none; width:200px">
        Select Shape:<br>
        <input type="radio" name="shape11" id="polygon_shape" value="polygon" onclick="SelectShape();" />Free Hand<br>
        <input type="radio" name="shape11" id="circle_shape"  value="circle" onclick="SelectShape();" />Circle<br>
        <input type="radio" name="shape11" id="rectangle_shape"  value="rectangle" onclick="SelectShape();" />Rectangle
         <br>
             <input type = "button" value = "Enable Drawing" id="btnEnableDrawing" onclick="EnableDrawing();" />
             <input type = "button" value = "Save All Changes" id="btnSaveAllChanges" onclick="SaveAllChanges();" />
    </div>
         
	<div id="SaveDialog" style="display:none;width:340px">
        <table>
            <tr><td> Name </td><td><input type="text" id="txtName"></td></tr>
            <tr><td> Description </td><td><input type="text" id="txtDescription"></td></tr>
            <tr><td> Price </td><td><input type="text" id="txtPrice"></td></tr>
        </table>
        <input type="button" value="Cancel" onclick="Cancel()">
        <input type="button" value="Save Details" onclick="Save()">  
        <input type="button" value="Remove Shape" onclick="Remove()">               
    </div>
	<div id="DisplayDialog" style="display:none;">
        <table>
            <tr><td> Name </td><td><input type="text" id="txtName_Display" readonly></td></tr>
            <tr><td> Description </td><td><input type="text" id="txtDescription_Display"></td></tr>
            <tr><td> Price </td><td><input type="text" id="txtPrice_Display"></td></tr>
        </table>           
	</div>
    
<script type="text/javascript">
    function log(s) {
    	//$('#log').append(s + "<br>"); 
    }    
</script>
</body>
</html>
     
             


/*-------------------------------
---------------------------------
------------NEEDED--------------- 
*/
svg { 
    position: absolute !important; 
}

html { 
    position:relative;
}
/* 
Above is From - 
1) http://stackoverflow.com/questions/3910676/body-tag-as-root-level-containing-block 
which refers to 
http://www.quirksmode.org/css/position.html


---------------------------------
---------------------------------
*/

/* 
----------NOT NEEDED------------- 
Below is just for this example -
*/
body {
    
     background: url('http://blog.cognac-expert.com/wp-content/uploads/2010/12/top10-cognac-2011.jpg') no-repeat;
    
}


External resources loaded into this fiddle: