diff --git a/src/containers/editable-container.js b/src/containers/editable-container.js
index c75cf01..8cc64c2 100644
--- a/src/containers/editable-container.js
+++ b/src/containers/editable-container.js
@@ -107,8 +107,30 @@ Applied as jQuery method.
         Hides container with form
         @method hide()
         **/         
-        hide: function() {
+        hide: function() {  
+            if(!this.tip() || !this.tip().is(':visible')) {
+                return;
+            }
             this.call('hide');
+            /**        
+            Fired when container was hidden. It occurs on both save or cancel.
+
+            @event hidden 
+            @param {Object} event event object
+            **/             
+            this.$element.triggerHandler('hidden');   
+        },
+        
+        /**
+        Toggles container visibility (show / hide)
+        @method toggle()
+        **/          
+        toggle: function() {
+            if(this.tip && this.tip().is(':visible')) {
+                this.hide();
+            } else {
+                this.show();
+            } 
         },
 
         /*
@@ -119,12 +141,12 @@ Applied as jQuery method.
             //tbd in child class
         },
 
-        cancel: function() {
+        cancel: function() {     
             if(this.options.autohide) {
                 this.hide();
             }
             /**        
-            Fired when form was cancelled
+            Fired when form was cancelled by user
             
             @event cancel 
             @param {Object} event event object
diff --git a/src/containers/editable-inline.js b/src/containers/editable-inline.js
index fe0f17e..92c5455 100644
--- a/src/containers/editable-inline.js
+++ b/src/containers/editable-inline.js
@@ -41,12 +41,18 @@
         }, 
         
         hide: function () {
+            if(!this.tip() || !this.tip().is(':visible')) {
+                return;
+            }            
             this.$form.hide(this.options.anim, $.proxy(function() {
                 this.$element.show();
                 //return focus on element
                 if (this.options.enablefocus) {
                     this.$element.focus();
-                }                
+                }  
+                
+                //trigger event
+                this.$element.triggerHandler('hidden');              
             }, this)); 
         },
         
diff --git a/src/containers/editable-tooltip.js b/src/containers/editable-tooltip.js
index 5f1463a..dcfa261 100644
--- a/src/containers/editable-tooltip.js
+++ b/src/containers/editable-tooltip.js
@@ -63,7 +63,11 @@
         },  
         
         hide: function() {
-            this.call('close');      
+            if(!this.tip() || !this.tip().is(':visible')) {
+                return;
+            }            
+            this.call('close'); 
+            this.$element.triggerHandler('hidden');     
         },
         
         setPosition: function() {
diff --git a/src/editable-form/editable-form.js b/src/editable-form/editable-form.js
index 8334286..8a975b0 100644
--- a/src/editable-form/editable-form.js
+++ b/src/editable-form/editable-form.js
@@ -167,6 +167,14 @@ Editableform is linked with one of input types, e.g. 'text' or 'select'.
             //sending data to server
             $.when(this.save(newValueStr))
             .done($.proxy(function(response) {
+                var error;
+                //call success callback. if it returns string --> show error
+                if(error = this.options.success.call(this, response, newValue)) {
+                    this.error(error);
+                    this.showForm();
+                    return;
+                }                
+                
                //clear error message
                this.error(false);   
                this.value = newValue;
@@ -367,7 +375,20 @@ Editableform is linked with one of input types, e.g. 'text' or 'select'.
             }
         }
         **/         
-        validate: null
+        validate: null,
+        /**
+        Success callback. Called when value successfully sent on server and response status = 200.
+        Can be used to process json response. If this function returns string - means error occured and string is shown as error message.
+        
+        @property success 
+        @type function
+        @default null
+        @example
+        success: function(response, newValue) {
+            if(!response.success) return response.msg;
+        }
+        **/          
+        success: function(response, newValue) {}         
     };   
 
     /*
diff --git a/src/element/editable-element.js b/src/element/editable-element.js
index 365e08c..ed282fd 100644
--- a/src/element/editable-element.js
+++ b/src/element/editable-element.js
@@ -220,7 +220,7 @@ Makes editable any HTML element on the page. Applied as jQuery method.
             if(!this.container) {
                 var containerOptions = $.extend({}, this.options, {
                     value: this.value,
-                    autohide: false
+                    autohide: false //element itsef will show/hide container
                 });
                 this.$element.editableContainer(containerOptions);
                 this.$element.on({
@@ -243,22 +243,22 @@ Makes editable any HTML element on the page. Applied as jQuery method.
         Hides container with form
         @method hide()
         **/       
-        hide: function () {
-            if(this.container && this.container.tip().is(':visible')) {
+        hide: function () {   
+            if(this.container) {  
                 this.container.hide();
-                
-                //return focus on element
-                if (this.options.enablefocus && this.options.toggle === 'click') {
-                    this.$element.focus();
-                }                
             }
+                
+            //return focus on element
+            if (this.options.enablefocus && this.options.toggle === 'click') {
+                this.$element.focus();
+            }                
         },
         
         /**
         Toggles container visibility (show / hide)
         @method toggle()
         **/  
-        toggle: function () {
+        toggle: function() {
             if(this.container && this.container.tip().is(':visible')) {
                 this.hide();
             } else {
@@ -270,16 +270,6 @@ Makes editable any HTML element on the page. Applied as jQuery method.
         * called when form was submitted
         */          
         save: function(e, params) {
-             var error, form;
-             
-             //if sent to server, call success callback. if it return string --> show error
-             if((params.response !== undefined) && (error = this.options.success.call(this, params.response, params.newValue))) {
-                 form = this.container.tip().find('form').parent().data('editableform');
-                 form.error(error);
-                 form.showForm();
-                 return;
-             }
-           
             //if url is not user's function and value was not sent to server and value changed --> mark element with unsaved css. 
             if(typeof this.options.url !== 'function' && params.response === undefined && this.input.value2str(this.value) !== this.input.value2str(params.newValue)) { 
                 this.$element.addClass('editable-unsaved');
@@ -539,20 +529,7 @@ Makes editable any HTML element on the page. Applied as jQuery method.
         @type mixed
         @default element's text
         **/
-        value: null,
-        /**
-        Success callback. Called when value successfully sent on server and response status = 200.
-        Can be used to process json response. If this function returns string - means error occured and string is shown as error message.
-        
-        @property success 
-        @type function
-        @default null
-        @example
-        success: function(response, newValue) {
-            if(!response.success) return response.msg;
-        }
-        **/          
-        success: function(response, newValue) {} 
+        value: null
     };
     
 }(window.jQuery));
\ No newline at end of file
diff --git a/test/unit/api.js b/test/unit/api.js
index 10a7019..dfb24fb 100644
--- a/test/unit/api.js
+++ b/test/unit/api.js
@@ -179,8 +179,8 @@ $(function () {
      });  
               
      
-     asyncTest("events: shown / cancel", function () {
-        expect(2);
+     asyncTest("events: shown / cancel / hidden", function () {
+        expect(3);
         var val = '1',
             e = $('<a href="#" data-pk="1" data-type="select" data-url="post.php" data-name="text" data-value="'+val+'"></a>').appendTo(fx);
         
@@ -192,7 +192,12 @@ $(function () {
         e.on('cancel', function(event) {
              var editable = $(this).data('editable');
              ok(true, 'cancel triggered'); 
-        });        
+        });     
+        
+        e.on('hidden', function(event) {
+             var editable = $(this).data('editable');
+             ok(true, 'hidden triggered'); 
+        });            
         
         e.editable({
             source: 'groups.php',
@@ -209,7 +214,38 @@ $(function () {
              }, timeout);
         }, timeout);                                        
         
-     });     
+     });    
+     
+     asyncTest("event: save / hidden", function () {
+        expect(2);
+        var val = '1',
+            e = $('<a href="#" data-pk="1" data-type="select" data-url="post.php" data-name="text" data-value="'+val+'"></a>').appendTo(fx);
+        
+        e.on('save', function(event, params) {
+            var editable = $(this).data('editable');
+            equal(params.newValue, 2, 'save triggered, value correct');
+        });
+        
+        e.on('hidden', function(event) {
+             var editable = $(this).data('editable');
+             ok(true, 'hidden triggered'); 
+        });         
+        
+        e.editable({
+            source: 'groups.php',
+        });
+        
+        e.click();
+        var p = tip(e);
+        p.find('select').val(2);
+        p.find('form').submit(); 
+        
+        setTimeout(function() {
+             p.find('button[type=button]').click(); 
+             e.remove();    
+             start();  
+        }, timeout);                                        
+     });       
   
    
      test("show/hide/toggle methods", function () {
@@ -375,7 +411,7 @@ $(function () {
      }); 
      
      
-     test("setValue", function () {
+     test("setValue method", function () {
         var e = $('<a href="#" data-name="name" data-type="select" data-url="post.php"></a>').appendTo('#qunit-fixture').editable({
             value: 1,
             source: groups
diff --git a/test/unit/common.js b/test/unit/common.js
index fbbd10b..c6fd49e 100644
--- a/test/unit/common.js
+++ b/test/unit/common.js
@@ -107,7 +107,7 @@
         ok(!p2.is(':visible'), 'popover2 closed');
       });
       
-     test("click outside popoover should hide it", function () {
+     test("click outside container should hide it", function () {
         var e = $('<a href="#" data-pk="1" data-url="post.php" data-name="text1">abc</a>').appendTo('#qunit-fixture').editable(),
             e1 = $('<div>').appendTo('body');
         
diff --git a/test/unit/text.js b/test/unit/text.js
index 9081923..df70bda 100644
--- a/test/unit/text.js
+++ b/test/unit/text.js
@@ -186,13 +186,14 @@ $(function () {
         }, timeout);                     
       });       
       
-     asyncTest("should show error if success callback return string", function () {
-        var e = $('<a href="#" data-pk="1" data-url="post.php" data-name="text1">abc</a>').appendTo(fx).editable({
-             success: function(data) {
+     asyncTest("should show error if success callback returns string", function () {
+        var newText = 'cd<e>;"',
+            e = $('<a href="#" data-pk="1" data-url="post.php" data-name="text1">abc</a>').appendTo(fx).editable({
+             success: function(response, newValue) {
+                 equal(newValue, newText, 'value in success passed correctly');
                  return 'error';
              } 
-          }),  
-          newText = 'cd<e>;"'
+          });  
 
         e.click()
         var p = tip(e);
@@ -211,7 +212,7 @@ $(function () {
            start();  
         }, timeout);             
         
-      })   
+      });   
    
       asyncTest("should submit all required params", function () {
         var e = $('<a href="#" data-pk="1" data-url="post-resp.php">abc</a>').appendTo(fx).editable({