jQuery.fn.editable = function(target, options, callback) {

    /* prevent elem has no properties error */
    if (this.length == 0) { 
        return(this); 
    };
    
    var settings = {
        target   : target,
        name     : 'value',
        id       : 'id',
        type     : 'text',
        width    : 'auto',
        height   : 'auto',
        event    : 'click',
        onblur   : 'cancel',
        loadtype : 'GET'
    };
        
    if(options) {
        jQuery.extend(settings, options);
    };
    
    var callback = callback || function() { };
      
    jQuery(this).attr('title', settings.tooltip);
    jQuery(this)[settings.event](function(e) {
        /* save this to self because this changes when scope changes */
        var self = this;

        /* prevent throwing an exeption if edit field is clicked again */
        if (self.editing) {
            return;
        }
			
        /* figure out how wide and tall we are */
        var width = 
            ('auto' == settings.width)  ? jQuery(self).width()  : settings.width;
        var height = 
            ('auto' == settings.height) ? jQuery(self).height() : settings.height;

        self.editing    = true;
        self.revert     = jQuery(self).html();
        self.innerHTML  = '';

        /* create the form object */
        var f = document.createElement('form');
        
        /* apply css or style or both */
        if (settings.cssclass) {
            if ('inherit' == settings.cssclass) {
                jQuery(f).attr('class', jQuery(self).attr('class'));
            } else {
                jQuery(f).attr('class', settings.cssclass);
            }
        }
        
        if (settings.style) {
            if ('inherit' == settings.style) {
                jQuery(f).attr('style', jQuery(self).attr('style'));
                /* IE needs the second line or display wont be inherited */
                jQuery(f).css('display', jQuery(self).css('display'));                
            } else {
                jQuery(f).attr('style', settings.style);
            }
        }
        
        /*  main input element */
        var i;
        switch (settings.type) {
            case 'textarea':
                i = document.createElement('textarea');
                if (settings.rows) {
                    i.rows = settings.rows;
                } else {
                    jQuery(i).height(height);
                }
                if (settings.cols) {
                    i.cols = settings.cols;
                } else {
                    jQuery(i).width(width);
                }   
                break;
            case 'select':
                i = document.createElement('select');
                break;
            default:
                i = document.createElement('input');
                i.type  = settings.type;
                jQuery(i).width(width);
                jQuery(i).height(height);
                /* https://bugzilla.mozilla.org/show_bug.cgi?id=236791 */
                i.setAttribute('autocomplete','off');
        }

        /* maintain bc with 1.1.1 and earlier versions */        
        if (settings.getload) {
            settings.loadurl    = settings.getload;
            settings.loadtype = 'GET';
        } else if (settings.postload) {
            settings.loadurl    = settings.postload;
            settings.loadtype = 'POST';
        }

        /* set input content via POST, GET, given data or existing value */
        if (settings.loadurl) {
            var data = {};
            data[settings.id] = self.id;
            jQuery.ajax({
               type : settings.loadtype,
               url  : settings.loadurl,
               data : data,		
			   //the code below added by Logan
			   error : function(xml, msg, e)
			   			{
							alert(msg);	
						},
				//the code above added by Logan
               success: function(str) {
                  setInputContent(str);
									
               }
            });
        } else if (settings.data) {
            setInputContent(settings.data);
        } else { 
            setInputContent(self.revert);
        }

        i.name  = settings.name;
        f.appendChild(i);

        if (settings.submit) {
            var b = document.createElement('input');
            b.type = 'submit';
            b.value = settings.submit;
            f.appendChild(b);
        }

        if (settings.cancel) {
            var b = document.createElement('input');
            b.type = 'button';
            b.value = settings.cancel;
            jQuery(b).click(function() {
                reset();
            });
            f.appendChild(b);
        }

        /* add created form to self */
        self.appendChild(f);

        i.focus();
        
        /* highlight input contents when requested */
        if (settings.select) {
            i.select();
        }
         
        /* discard changes if pressing esc */
        jQuery(i).keydown(function(e) {
            if (e.keyCode == 27) {
                e.preventDefault();
                reset();
            }
        });

        /* discard, submit or nothing with changes when clicking outside */
        /* do nothing is usable when navigating with tab */
        var t;
        if ('cancel' == settings.onblur) {
            jQuery(i).blur(function(e) {
                t = setTimeout(reset, 500);
            });
        } else if ('submit' == settings.onblur) {
            jQuery(i).blur(function(e) {
                jQuery(f).submit();
            });
        } else {
            jQuery(i).blur(function(e) {
              /* TODO: maybe something here */
            });
        }

        jQuery(f).submit(function(e) {

            if (t) { 
                clearTimeout(t);
            }

            /* do no submit */
            e.preventDefault(); 

            /* check if given target is function */
            if (jQuery.isFunction(settings.target)) {
                var str = settings.target.apply(self, [jQuery(i).val(), settings]);
                self.innerHTML = str;
                self.editing = false;
                callback.apply(self, [self.innerHTML, settings]);
            } else {
                /* add edited content and id of edited element to POST */           
                var p = {};
                p[i.name] = jQuery(i).val();
                p[settings.id] = self.id;

                /* show the saving indicator */
                jQuery(self).html(settings.indicator);
                jQuery.post(settings.target, p, function(str) {
					// the code below updated by Logan //
				var errorPrefix = 'error:';
					var indexError = str.indexOf(errorPrefix);
					if( indexError > -1)
					{							
							reset();
							alert(str.substr(errorPrefix.length));
					}else
					{
						var fileNamePrefix = 'name:';
						var filePathPrefix = 'path:';
						var queryStrPrefix = 'querystr:';
						var fileNameIndex = str.indexOf(fileNamePrefix);
						var filePathIndex = str.indexOf(filePathPrefix);
						var queryStrIndex = str.indexOf(queryStrPrefix);
						
						if(fileNameIndex > -1 && filePathIndex > -1 && queryStrIndex > - 1)
						{
							var fileName = str.substring(fileNameIndex + fileNamePrefix.length, queryStrIndex);
							var filePath = str.substr(filePathPrefix.length, (fileNameIndex - fileNamePrefix.length));
							var queryStr = str.substr(queryStrIndex + queryStrPrefix.length);
							
							if(queryStr!= '')
							{
								queryStr = '&' + queryStr;
							}
								
							//alert(str.substr(fileNameIndex + fileNamePrefix.length));
							//change all references to the new file name or folder name
							var row = $(self).parent();
							var rowNum = $(row).attr('id').substr(3, $(row).attr('id').length - 3);
							//  fileUr, folderUrl
							var checkBox = $('#check' + rowNum);
							$(checkBox).val(fileName);
							var icon = $('#row'+rowNum + ' td a');
							//alert(checkBox.value);
							//var lastIndexOfSlash = $(checkBox).val().lastIndexOf('/');
							
							switch($('#itemType'+rowNum).val())
							{
								case "file":
									$('#fileName'+rowNum).val(fileName); //file name
									$(icon).attr('href', filePath); //icon url
									$('#filePath'+rowNum).val(filePath); //file path
									var fileUrl = $('#fileUrl'+rowNum);
									var fileUrlValue = $(fileUrl).val();
									var lastIndexOfSlash = fileUrlValue.lastIndexOf("/"); 									
									$(fileUrl).val(fileUrlValue.substring(0, fileUrlValue.lastIndexOf("/")) + "/" + fileName);
									break;
								case "folder":
									$('#folderName').val(fileName); //folder name
									var iconUrl = $('#row'+rowNum + ' td a').attr('href');
									$(icon).attr('href', (iconUrl.substring(0, iconUrl.lastIndexOf('?path=') + 6) + filePath + queryStr));
									//var lastIndexOfSlash = iconUrl.lastIndexOf("/");
									//$('#row'+rowNum + ' td a').attr('href', filePath) //icon url
									$('#folderPath'+rowNum).val(filePath); //folder path							
									break;
							}
							//alert(rowNum);
							//alert($(self).parent().attr('class'));
							self.innerHTML = fileName;	
							$(self).attr('id', filePath);
							self.editing = false;
							
							//alert($('#' + setting.id).parent().attr('title'));
							callback.apply(self, [self.innerHTML, settings]); 							
						}else
						{
							alert('Incorrect results');	
						}

					}
/*                    self.innerHTML = str;
                    self.editing = false;
                    callback.apply(self, [self.innerHTML, settings]);*/				
					// the code above updated by Logan //														 

                });
            }
                        
            return false;
        });

        function reset() {
            self.innerHTML = self.revert;
            self.editing   = false;
        };
        
        function setInputContent(str) {
        	
            if (jQuery.isFunction(str)) {
                var str = str.apply(self, [self.revert, settings]);
            }
            switch (settings.type) { 	 
                case 'select': 	 
                    if (String == str.constructor) { 	 
                        eval ("var json = " + str);
                        for (var key in json) {
                            if ('selected' == key) {
                                continue;
                            } 
                            o = document.createElement('option'); 	 
                            o.value = key;
                            var text = document.createTextNode(json[key]);
                            o.appendChild(text);
                            if (key == json['selected']) {
                                o.selected = true;
                            }
                            i.appendChild(o); 	 
                        }
                    } 	 
                    break; 	 
                default: 	
										
                    i.value = str; 
                    break; 	 
            } 	 
        }

    });

    return(this);
}
