diff --git a/CHANGELOG.txt b/CHANGELOG.txt
index c1a6fcb..3dc6bcc 100644
--- a/CHANGELOG.txt
+++ b/CHANGELOG.txt
@@ -3,10 +3,13 @@ X-editable changelog
 
 
 Version 1.2.0 wip
-----------------------------   
+----------------------------  
+[enh] 'checklist' submit value as array, not comma separated string (vitalets)  
+[enh] 'checklist' was refactored: options 'viewseparator', 'limit', 'limitText' are supressed by 'display' callback (vitalets)  
+[enh] new option: 'display' callback. Makes far more flexible rendering value into element's text. (vitalets)  
 [bug] fix typos (atrophic) 
 [enh] all callbacks scope changed to element (vitalets) 
-[enh] new option 'cancelnochange' to cancel or submit value when it was not changed in form (vitalets) 
+[enh] new option: 'cancelnochange' to cancel or submit value when it was not changed in form (vitalets) 
 [enh] composite pk can be defined as JSON in data-pk attribute (vitalets) 
 [enh #30] new option 'sourceCache' true|false to disable cache for select (vitalets) 
 [bug #34] inputclass span* broken with fluid bootstrap layout. Classes changed to 'input-*'. (vitalets) 
diff --git a/src/containers/editable-container.js b/src/containers/editable-container.js
index d20aed9..55fab88 100644
--- a/src/containers/editable-container.js
+++ b/src/containers/editable-container.js
@@ -75,6 +75,7 @@ Applied as jQuery method.
         },
 
         initForm: function() {
+            this.formOptions.scope = this.$element[0]; //set scope of form callbacks to element
             this.$form = $('<div>')
             .editableform(this.formOptions)
             .on({
@@ -263,7 +264,7 @@ Applied as jQuery method.
         closeOthers: function(element) {
             $('.editable-open').each(function(i, el){
                 //do nothing with passed element
-                if(el === element) {
+                if(el === element || $(el).find(element).length) {
                     return;
                 }
 
diff --git a/src/editable-form/editable-form-utils.js b/src/editable-form/editable-form-utils.js
index 29981fe..aa22f64 100644
--- a/src/editable-form/editable-form-utils.js
+++ b/src/editable-form/editable-form-utils.js
@@ -117,6 +117,13 @@
                 return k;
             }
 
-        }   
+        },
+        
+       /**
+        method to escape html.
+       **/
+       escape: function(str) {
+           return $('<div>').text(str).html();
+       }           
     };      
 }(window.jQuery));
\ No newline at end of file
diff --git a/src/editable-form/editable-form.js b/src/editable-form/editable-form.js
index da8e452..f7f7dcc 100644
--- a/src/editable-form/editable-form.js
+++ b/src/editable-form/editable-form.js
@@ -168,8 +168,7 @@ Editableform is linked with one of input types, e.g. 'text', 'select' etc.
             e.preventDefault();
             
             var error,
-                newValue = this.input.input2value(), //get new value from input
-                newValueStr;
+                newValue = this.input.input2value(); //get new value from input
 
             //validation
             if (error = this.validate(newValue)) {
@@ -178,19 +177,16 @@ Editableform is linked with one of input types, e.g. 'text', 'select' etc.
                 return;
             } 
             
-            //value as string
-            newValueStr = this.input.value2str(newValue);
-
             //if value not changed --> cancel
             /*jslint eqeq: true*/
-            if (this.options.cancelnochange && newValueStr == this.input.value2str(this.value)) {
+            if (this.options.cancelnochange && this.input.value2str(newValue) == this.input.value2str(this.value)) {
             /*jslint eqeq: false*/                
                 this.cancel();
                 return;
             } 
 
             //sending data to server
-            $.when(this.save(newValueStr))
+            $.when(this.save(newValue))
             .done($.proxy(function(response) {
                 //run success callback
                 var res = typeof this.options.success === 'function' ? this.options.success.call(this.options.scope, response, newValue) : null;
@@ -238,13 +234,16 @@ Editableform is linked with one of input types, e.g. 'text', 'select' etc.
             }, this));
         },
 
-        save: function(value) {
+        save: function(newValue) {
+            //convert value for submitting to server
+            var submitValue = this.input.value2submit(newValue);
+            
             //try parse composite pk defined as json string in data-pk 
             this.options.pk = $.fn.editableutils.tryParseJson(this.options.pk, true); 
             
             var pk = (typeof this.options.pk === 'function') ? this.options.pk.call(this.options.scope) : this.options.pk,
             send = !!(typeof this.options.url === 'function' || (this.options.url && ((this.options.send === 'always') || (this.options.send === 'auto' && pk)))),
-            params, ajaxOptions;
+            params;
 
             if (send) { //send to server
                 this.showLoading();
@@ -252,7 +251,7 @@ Editableform is linked with one of input types, e.g. 'text', 'select' etc.
                 //standard params
                 params = {
                     name: this.options.name || '',
-                    value: value,
+                    value: submitValue,
                     pk: pk 
                 };
 
@@ -267,15 +266,14 @@ Editableform is linked with one of input types, e.g. 'text', 'select' etc.
 
                 if(typeof this.options.url === 'function') { //user's function
                     return this.options.url.call(this.options.scope, params);
-                } else {  //send ajax to server and return deferred object
-                    ajaxOptions = $.extend({
+                } else {  
+                    //send ajax to server and return deferred object
+                    return $.ajax($.extend({
                         url     : this.options.url,
                         data    : params,
                         type    : 'post',
                         dataType: 'json'
-                    }, this.options.ajaxOptions);
-
-                    return $.ajax(ajaxOptions);
+                    }, this.options.ajaxOptions));
                 }
             }
         }, 
@@ -455,6 +453,7 @@ Editableform is linked with one of input types, e.g. 'text', 'select' etc.
         @property ajaxOptions 
         @type object
         @default null
+        @since 1.1.1        
         **/        
         ajaxOptions: null,
         /**
diff --git a/src/element/editable-element.js b/src/element/editable-element.js
index 2df7d75..3beb7d2 100644
--- a/src/element/editable-element.js
+++ b/src/element/editable-element.js
@@ -47,13 +47,20 @@ Makes editable any HTML element on the page. Applied as jQuery method.
                 this.value = this.input.html2value($.trim(this.$element.html()));
                 isValueByText = true;
             } else {
+                /*
+                  value can be string when received from 'data-value' attribute
+                  for complext objects value can be set as json string in data-value attribute, 
+                  e.g. data-value="{city: 'Moscow', street: 'Lenina'}"
+                */
+                this.options.value = $.fn.editableutils.tryParseJson(this.options.value, true); 
                 if(typeof this.options.value === 'string') {
-                   this.options.value = $.trim(this.options.value);
+                    this.value = this.input.str2value(this.options.value);
+                } else {
+                    this.value = this.options.value;
                 }
-                this.value = this.input.str2value(this.options.value);
             }
             
-            //add 'editable' class
+            //add 'editable' class to every editable element
             this.$element.addClass('editable');
             
             //attach handler activating editable. In disabled mode it just prevent default action (useful for links)
@@ -64,6 +71,13 @@ Makes editable any HTML element on the page. Applied as jQuery method.
                     //stop propagation not required anymore because in document click handler it checks event target
                     //e.stopPropagation();
                     
+                    //mark event with special flag: it will not be processed in document click handler
+                    /*
+                    if(e.type === 'click' && e.target !== e.currentTarget) {
+                        $(e.target).data('editable-element', e.currentTarget);
+                    }
+                    */
+                    
                     if(this.options.toggle === 'mouseenter') {
                         //for hover only show container
                         this.show(); 
@@ -81,7 +95,7 @@ Makes editable any HTML element on the page. Applied as jQuery method.
             //if value was generated by text or value is empty, no sense to run autotext
             doAutotext = !isValueByText && this.value !== null && this.value !== undefined;
             doAutotext &= (this.options.autotext === 'always') || (this.options.autotext === 'auto' && !this.$element.text().length);
-            $.when(doAutotext ? this.input.value2html(this.value, this.$element) : true).then($.proxy(function() {
+            $.when(doAutotext ? this.render() : true).then($.proxy(function() {
                 if(this.options.disabled) {
                     this.disable();
                 } else {
@@ -104,6 +118,25 @@ Makes editable any HTML element on the page. Applied as jQuery method.
                 this.isInit = false;    
             }, this));
         },
+
+        /*
+        Renders value into element's text.
+        Can call custom display method from options.
+        Can return deferred object.
+        @method render()
+        */          
+        render: function() {
+           //if it is input with source, we pass callback in third param to be called when source is loaded
+           if(this.input.options.hasOwnProperty('source')) {
+               return this.input.value2html(this.value, this.$element[0], this.options.display); 
+           //if display method defined --> use it    
+           } else if(typeof this.options.display === 'function') {
+               return this.options.display.call(this.$element[0], this.value);
+           //else use input's original value2html() method    
+           } else {
+               return this.input.value2html(this.value, this.$element[0]); 
+           }
+        },
         
         /**
         Enables editable
@@ -222,8 +255,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, //element will take care to show/hide container. Otherwise hide() will be called twice
-                    scope: this.$element[0] //set scope to element
+                    autohide: false //element will take care to show/hide container. Otherwise hide() will be called twice
                 });
                 this.$element.editableContainer(containerOptions);
                 this.$element.on({
@@ -326,7 +358,7 @@ Makes editable any HTML element on the page. Applied as jQuery method.
             if(this.container) {
                 this.container.option('value', this.value);
             }
-            $.when(this.input.value2html(this.value, this.$element))
+            $.when(this.render())
             .then($.proxy(function() {
                 this.handleEmpty();
                 this.$element.triggerHandler('render', this);                        
@@ -401,7 +433,7 @@ Makes editable any HTML element on the page. Applied as jQuery method.
                 this.each(function () {
                     var $this = $(this), data = $this.data(datakey);
                     if (data && data.value !== undefined && data.value !== null) {
-                        result[data.options.name] = data.input.value2str(data.value);
+                        result[data.options.name] = data.input.value2submit(data.value);
                     }
                 });
             return result;
@@ -544,7 +576,23 @@ Makes editable any HTML element on the page. Applied as jQuery method.
         @type mixed
         @default element's text
         **/
-        value: null
+        value: null,
+        /**
+        Callback to perform custom displaying of value in element's text.
+        If not defined, default input's value2html() will be called.
+        Runs under element's scope.
+        Second parameter __sourceData__ is passed for inputs with source (select, checklist).
+        
+        @property display 
+        @type function
+        @default null
+        @since 1.2.0
+        @example
+        display: function(value, sourceData) {
+            $(this).html('<b>'+value+'</b>');
+        }
+        **/          
+        display: null
     };
     
 }(window.jQuery));
\ No newline at end of file
diff --git a/src/inputs/abstract.js b/src/inputs/abstract.js
index 02eb07e..40fcb0c 100644
--- a/src/inputs/abstract.js
+++ b/src/inputs/abstract.js
@@ -49,8 +49,7 @@ To create your own input you should inherit from this class.
         @param {DOMElement} element
        **/       
        value2html: function(value, element) {
-           var html = this.escape(value);
-           $(element).html(html);
+           $(element).text(value);
        },
         
        /**
@@ -65,7 +64,7 @@ To create your own input you should inherit from this class.
        },
         
        /**
-        Converts value to string (for submitting to server)
+        Converts value to string (for comparering)
         
         @method value2str(value) 
         @param {mixed} value
@@ -86,6 +85,17 @@ To create your own input you should inherit from this class.
            return str;
        }, 
        
+       /**
+        Converts value for submitting to server
+        
+        @method value2submit(value) 
+        @param {mixed} value
+        @returns {mixed}
+       **/       
+       value2submit: function(value) {
+           return value;
+       },         
+       
        /**
         Sets value of input.
         
@@ -121,7 +131,7 @@ To create your own input you should inherit from this class.
         
         @method clear() 
        **/        
-       clear:  function() {
+       clear: function() {
            this.$input.val(null);
        },
        
diff --git a/src/inputs/checklist.js b/src/inputs/checklist.js
index d36d603..243b008 100644
--- a/src/inputs/checklist.js
+++ b/src/inputs/checklist.js
@@ -49,10 +49,8 @@ $(function(){
         },
        
        value2str: function(value) {
-           return $.isArray(value) ? value.join($.trim(this.options.separator)) : '';
-           //it is also possible to sent as array
-           //return value;
-       },        
+           return $.isArray(value) ? value.sort().join($.trim(this.options.separator)) : '';
+       },  
        
        //parse separated string
         str2value: function(str) {
@@ -95,19 +93,16 @@ $(function(){
           
        //collect text of checked boxes
         value2htmlFinal: function(value, element) {
-           var selected = [], item, i, html = '';
-           if($.isArray(value) && value.length <= this.options.limit) {    
-               for(i=0; i<value.length; i++){
-                   item = this.itemByVal(value[i]);
-                   if(item) {
-                       selected.push($('<div>').text(item.text).html());
-                   }
-               }
-               html = selected.join(this.options.viewseparator);
-           } else {  
-               html = this.options.limitText.replace('{checked}', $.isArray(value) ? value.length : 0).replace('{count}', this.sourceData.length); 
+           var html = [],
+               checked = $.grep(this.sourceData, function(o){
+                   return $.grep(value, function(v){return v == o.value;}).length;
+               });
+           if(checked.length) {
+               $.each(checked, function(i, v) { html.push($.fn.editableutils.escape(v.text)); });
+               $(element).html(html.join('<br>'));
+           } else {
+               $(element).empty(); 
            }
-           $(element).html(html);
         },
         
        activate: function() {
@@ -138,39 +133,13 @@ $(function(){
         inputclass: 'editable-checklist',        
         
         /**
-        Separator of values in string when sending to server
+        Separator of values when reading from 'data-value' string
 
         @property separator 
         @type string
         @default ', '
         **/         
-        separator: ',',
-        /**
-        Separator of text when display as element content.
-
-        @property viewseparator 
-        @type string
-        @default '<br>'
-        **/         
-        viewseparator: '<br>',
-        /**
-        Maximum number of items shown as element content. 
-        If checked more items - <code>limitText</code> will be shown.
-
-        @property limit 
-        @type integer
-        @default 4
-        **/         
-        limit: 4,
-        /**
-        Text shown when count of checked items is greater than <code>limit</code> parameter.
-        You can use <code>{checked}</code> and <code>{count}</code> placeholders.
-
-        @property limitText 
-        @type string
-        @default 'Selected {checked} of {count}'
-        **/         
-        limitText: 'Selected {checked} of {count}'        
+        separator: ','
     });
 
     $.fn.editabletypes.checklist = Checklist;      
diff --git a/src/inputs/date/date.js b/src/inputs/date/date.js
index 3cc974a..1de781f 100644
--- a/src/inputs/date/date.js
+++ b/src/inputs/date/date.js
@@ -79,7 +79,11 @@ $(function(){
        
        str2value: function(str) {
            return str ? this.dpg.parseDate(str, this.parsedFormat, this.options.datepicker.language) : null;
-       },             
+       }, 
+       
+       value2submit: function(value) {
+           return this.value2str(value);
+       },                    
 
        value2input: function(value) {
            this.$input.datepicker('update', value);
diff --git a/src/inputs/dateui/dateui.js b/src/inputs/dateui/dateui.js
index 356cc41..baa8afc 100644
--- a/src/inputs/dateui/dateui.js
+++ b/src/inputs/dateui/dateui.js
@@ -97,7 +97,11 @@ $(function(){
            } catch(e) {}
            
            return d;
-       },             
+       }, 
+       
+       value2submit: function(value) {
+           return this.value2str(value);
+       },                     
 
        value2input: function(value) {
            this.$input.datepicker('setDate', value);
diff --git a/src/inputs/list.js b/src/inputs/list.js
index 2fe54fb..9570cb8 100644
--- a/src/inputs/list.js
+++ b/src/inputs/list.js
@@ -34,10 +34,15 @@ List - abstract class for inputs that have source option loaded from js array or
             return null; //can't set value by text
         },
         
-        value2html: function (value, element) {
+        value2html: function (value, element, display) {
             var deferred = $.Deferred();
             this.onSourceReady(function () {
-                this.value2htmlFinal(value, element);
+                if(typeof display === 'function') {
+                    //custom display method
+                    display.call(element, value, this.sourceData); 
+                } else {
+                    this.value2htmlFinal(value, element);
+                }
                 deferred.resolve();
             }, function () {
                 List.superclass.value2html(this.options.sourceError, element);
diff --git a/test/unit/checklist.js b/test/unit/checklist.js
index 294d2a5..f94604a 100644
--- a/test/unit/checklist.js
+++ b/test/unit/checklist.js
@@ -4,21 +4,28 @@ $(function () {
         setup: function(){
             sfx = $('#qunit-fixture'),
             fx = $('#async-fixture');               
-            $.support.transition = false;
         }
     });  
    
     asyncTest("should load options, set correct value and save new value", function () {
-         var sep = '-',
+         var sep = '<br>',
              newValue,
-             e = $('<a href="#" data-type="checklist" data-url="post.php"></a>').appendTo(fx).editable({
+             e = $('<a href="#" data-type="checklist" data-url="post-checklist.php"></a>').appendTo(fx).editable({
              pk: 1,
              source: groupsArr,
-             value: [2, 3],
-             viewseparator: sep
+             value: [2, 3]
         });
            
-        equal(e.text(), groups[2]+sep+groups[3], 'autotext ok');
+        equal(e.html(), groups[2]+sep+groups[3], 'autotext ok');
+        
+          $.mockjax({
+              url: 'post-checklist.php',
+              response: function(settings) {
+                 ok($.isArray(settings.data.value), 'value submitted as array');
+                 equal(settings.data.value.sort().join(''), [newValue, 3].join(''), 'submitted array correct');
+              }
+          });         
+        
         
         e.click();
         var p = tip(e);
@@ -28,8 +35,8 @@ $(function () {
         equal(p.find('input[type="checkbox"]:checked').eq(1).val(), 3, '2nd checked');
 
         //set new value
-        p.find('input[type="checkbox"]:checked').eq(0).click(); 
-        p.find('input[type="checkbox"]').first().click();
+        p.find('input[type="checkbox"]:checked').eq(0).click();  //uncheck 2
+        p.find('input[type="checkbox"]').first().click(); //check first 
         newValue = p.find('input[type="checkbox"]').first().val();
         
         //submit
@@ -39,7 +46,7 @@ $(function () {
                ok(!p.is(':visible'), 'popup closed');
                
                equal(e.data('editable').value.join(''), [newValue, 3].join(''), 'new value ok')
-               equal(e.text(), groups[newValue]+sep+groups[3], 'new text ok');
+               equal(e.html(), groups[newValue]+'<br>'+groups[3], 'new text ok');
               
                // open container again to see what checked
                e.click()
@@ -54,40 +61,5 @@ $(function () {
                start();  
          }, timeout);                              
     });                  
-   
-     asyncTest("limit option", function () {
-         var e = $('<a href="#" data-type="checklist" data-value="2,3" data-url="post.php"></a>').appendTo(fx).editable({
-             pk: 1,
-             source: groupsArr,
-             limit: 1,
-             limitText: '{checked} of {count}'
-        });
-           
-        equal(e.text(), '2 of '+groupsArr.length, 'autotext ok');
-        
-        e.click();
-        var p = tip(e);
-
-        equal(p.find('input[type="checkbox"]:checked').length, 2, 'checked count ok');
-        equal(p.find('input[type="checkbox"]:checked').eq(0).val(), 2, '1st checked');
-        equal(p.find('input[type="checkbox"]:checked').eq(1).val(), 3, '2nd checked');
-
-        //set new value
-        p.find('input[type="checkbox"]').first().click();
-        newValue = p.find('input[type="checkbox"]').first().val();
-        
-        //submit
-        p.find('form').submit(); 
-         
-         setTimeout(function() {
-               ok(!p.is(':visible'), 'popup closed');
-               
-               equal(e.text(), '3 of '+groupsArr.length, 'autotext ok');
-               
-               e.remove();    
-               start();  
-         }, timeout);                              
-    });   
-   
      
 });
\ No newline at end of file
diff --git a/test/unit/select.js b/test/unit/select.js
index ea90852..1da2835 100644
--- a/test/unit/select.js
+++ b/test/unit/select.js
@@ -523,6 +523,34 @@ $(function () {
                e.remove();    
                start();  
          }, timeout);   
-     });    
+     });   
+     
+     asyncTest("'display' callback", function () {
+         var e = $('<a href="#" data-type="select" data-value="2" data-url="post.php"></a>').appendTo(fx).editable({
+             pk: 1,
+             source: groups,
+             display: function(value, sourceData) {
+                var els = $.grep(sourceData, function(o) {return o.value == value;});  
+                $(this).text('qq' + els[0].text);
+             }
+        }),
+        selected = 3;
+
+        equal(e.text(), 'qq'+groups[2], 'autotext display ok'); 
+        
+        e.click();
+        var p = tip(e);
+
+        p.find('select').val(selected);
+        p.find('form').submit();
+         
+         setTimeout(function() {
+               ok(!p.is(':visible'), 'popover closed');
+               equal(e.data('editable').value, selected, 'new value saved')
+               equal(e.text(), 'qq'+groups[selected], 'text shown correctly') 
+               e.remove();    
+               start();  
+         }, timeout);   
+     });        
      
 });
\ No newline at end of file
diff --git a/test/unit/text.js b/test/unit/text.js
index e9ad7d0..ad500ff 100644
--- a/test/unit/text.js
+++ b/test/unit/text.js
@@ -454,6 +454,31 @@ $(function () {
             delete $.fn.editable.defaults.name;
             var e = $('<a href="#" id="cde">abc</a>').appendTo('#qunit-fixture').editable();
             equal(e.data('editable').options.name, 'cde', 'name is taken from id');
-      });      
+      });   
+      
+     asyncTest("'display' callback", function () {
+        var newText = 'cd<e>;"',
+            e = $('<a href="#" data-pk="1" data-url="post.php" data-name="text1">abc</a>').appendTo(fx).editable({
+             display: function(value) {
+                 ok(this === e[0], 'scope is ok');
+                 $(this).text('qq'+value);
+             } 
+          });  
+
+        e.click()
+        var p = tip(e);
+
+        ok(p.find('input[type=text]').length, 'input exists')
+        p.find('input').val(newText);
+        p.find('form').submit(); 
+        
+        setTimeout(function() {
+           ok(!p.is(':visible'), 'popover was removed');
+           equal(e.text(), 'qq'+newText, 'custom display ok');
+           e.remove();    
+           start();  
+        }, timeout);             
+        
+      });           
          
 });    
\ No newline at end of file
diff --git a/test/unit/textarea.js b/test/unit/textarea.js
index 6a76813..a24b225 100644
--- a/test/unit/textarea.js
+++ b/test/unit/textarea.js
@@ -34,8 +34,8 @@ $(function () {
         var e = $('<a href="#" data-pk="1" data-url="post.php">'+v1+'</a>').appendTo(fx).editable({
              type: 'textarea',
              send: 'ifpk',
-             success: function(data) {
-                 return false;
+             success: function(response, newvalue) {
+                 equal(newvalue, v2, 'value in success ok');         
              } 
           });