diff --git a/__pkginfo__.py b/__pkginfo__.py
index d32c5dffe4b182fd15f3f267aeb67383f15b1514_X19wa2dpbmZvX18ucHk=..c6e6d5adc287a3996fa5fd47e5bc88ba29c6257d_X19wa2dpbmZvX18ucHk= 100644
--- a/__pkginfo__.py
+++ b/__pkginfo__.py
@@ -23,7 +23,7 @@
            'Programming Language :: JavaScript',
 ]
 
-__depends__ = {'cubicweb': '>= 3.6.0'}
+__depends__ = {'cubicweb': '>= 3.9.0'}
 
 # package ###
 
diff --git a/data/cubes.comment.js b/data/cubes.comment.js
index d32c5dffe4b182fd15f3f267aeb67383f15b1514_ZGF0YS9jdWJlcy5jb21tZW50Lmpz..c6e6d5adc287a3996fa5fd47e5bc88ba29c6257d_ZGF0YS9jdWJlcy5jb21tZW50Lmpz 100644
--- a/data/cubes.comment.js
+++ b/data/cubes.comment.js
@@ -4,21 +4,7 @@
  *  :contact: http://www.logilab.fr/ -- mailto:contact@logilab.fr
  */
 
-CubicWeb.require('python.js');
-CubicWeb.require('htmlhelpers.js');
-CubicWeb.require('ajax.js');
-
-function _getText(textarea) {
-    if (typeof(FCKeditor) != 'undefined') {
-        var fck = FCKeditorAPI.GetInstance(textarea.id);
-        if (fck) {
-            return fck.GetHTML();
-        }
-    }
-    return textarea.value;
-}
-
 /* this function is called on inlined-comment editions
  * It calls the [add|eid]_comment method on the jsoncontroller and [re]load
  * only the view for the added or edited comment
  */
@@ -21,8 +7,8 @@
 /* this function is called on inlined-comment editions
  * It calls the [add|eid]_comment method on the jsoncontroller and [re]load
  * only the view for the added or edited comment
  */
-function processComment(eid, funcname, creation) {
+function processComment(eid, cancel, creation) {
     var divId = 'comment' + eid + 'Slot'
     var divNode = jQuery('#'+divId);
     var textarea = divNode.find('textarea')[0];
@@ -26,36 +12,32 @@
     var divId = 'comment' + eid + 'Slot'
     var divNode = jQuery('#'+divId);
     var textarea = divNode.find('textarea')[0];
-    if (funcname) {
-        var format = 'text/html'; // no select widget if fckeditor is used
-        var select = divNode.find('select')[0];
-        if (select) {
-            format = firstSelected(select);
-        }
-        d = asyncRemoteExec(funcname, eid, _getText(textarea), format);
-        d.addCallback(function (neweid) {
-	    if (creation) {
-		var commentNode = jQuery('#comment'+ eid);
-		var ul = null;
-		if (!commentNode.length) {
-		    // we are adding a comment to the top level entity
-		    commentNode = jQuery('#commentsectionComponent');
-		    klass = 'comment';
-		} else {
-		    klass = 'section';
-		}
-		ul = commentNode.find('> ul:first');
-		if (!ul.length) {
-		    ul = jQuery(UL({'class': klass}));
-		    commentNode.append(ul);
-		}
-		ul.append(LI({'id': 'comment'+ neweid, 'class': 'comment'},
-			     DIV({'id': 'comment'+ neweid + 'Div'})));
-		divNode.remove();
-		eid = neweid;
-	    }
-	    replacePageChunk('comment' + eid + 'Div', rql_for_eid(eid), 'treeitem');
-        });
+    if (!cancel) {
+	validateForm('commentForm' + eid, null,
+		     function(result, formid, cbargs) {
+			 var neweid = result[2].eid;
+			 if (creation) {
+			     var commentNode = $('#comment'+ eid);
+			     var ul = null;
+			     if (!commentNode.length) {
+				 // we are adding a comment to the top level entity
+				 commentNode = $('#commentsectionComponent');
+				 klass = 'comment';
+			     } else {
+				 klass = 'section';
+			     }
+			     ul = commentNode.find('> ul:first');
+			     if (!ul.length) {
+				 ul = jQuery(UL({'class': klass}));
+				 commentNode.append(ul);
+			     }
+			     ul.append(LI({'id': 'comment'+ neweid, 'class': 'comment'},
+					  DIV({'id': 'comment'+ neweid + 'Div'})));
+			     divNode.remove();
+			 }
+			 var form = ajaxFuncArgs('render', null, 'views', 'treeitem', neweid);
+			 $('#comment' + neweid + 'Div').loadxhtml('json', form, null, null, true);
+		     });
     } else {
 	// comment cancelled, close div holding the form
         divNode.remove();
@@ -71,6 +53,3 @@
     $('html, body').animate({scrollTop:0}, 'fast');
     return false;
 }
-
-CubicWeb.provide('comment.js');
-
diff --git a/debian/control b/debian/control
index d32c5dffe4b182fd15f3f267aeb67383f15b1514_ZGViaWFuL2NvbnRyb2w=..c6e6d5adc287a3996fa5fd47e5bc88ba29c6257d_ZGViaWFuL2NvbnRyb2w= 100644
--- a/debian/control
+++ b/debian/control
@@ -10,7 +10,7 @@
 
 Package: cubicweb-comment
 Architecture: all
-Depends: cubicweb-common (>= 3.6.0)
+Depends: cubicweb-common (>= 3.9.0)
 Description: comment component for the CubicWeb framework
  This CubicWeb component provides threadable comments.
  .
diff --git a/test/unittest_comment.py b/test/unittest_comment.py
index d32c5dffe4b182fd15f3f267aeb67383f15b1514_dGVzdC91bml0dGVzdF9jb21tZW50LnB5..c6e6d5adc287a3996fa5fd47e5bc88ba29c6257d_dGVzdC91bml0dGVzdF9jb21tZW50LnB5 100644
--- a/test/unittest_comment.py
+++ b/test/unittest_comment.py
@@ -139,26 +139,6 @@
 
 ''')
 
-class CommentJsonControllerExtensionsTC(CubicWebTC):
-
-    def setup_database(self):
-        self.john = self.create_user(u'John')
-
-    def test_add_and_edit_comment(self):
-        # add comment
-        self.remote_call('add_comment', self.john.eid, u'yo', u'text/plain')
-        comment = self.entity('Any C,CT,F WHERE C content CT, C content_format F, '
-                              'C comments P, P eid %s' % self.john.eid)
-        self.assertEquals(comment.content, u'yo')
-        self.assertEquals(comment.content_format, u'text/plain')
-        # edit comment
-        self.remote_call('edit_comment', comment.eid, u'yipee', u'text/plain')
-        comment2 = self.entity('Any C,CT,F WHERE C content CT, C content_format F, '
-                               'C comments P, P eid %s' % self.john.eid)
-        self.assertEquals(comment.eid, comment2.eid)
-        self.assertEquals(comment2.content, u'yipee')
-        self.assertEquals(comment2.content_format, u'text/plain')
-
 
 if __name__ == '__main__':
     from logilab.common.testlib import unittest_main
diff --git a/views.py b/views.py
index d32c5dffe4b182fd15f3f267aeb67383f15b1514_dmlld3MucHk=..c6e6d5adc287a3996fa5fd47e5bc88ba29c6257d_dmlld3MucHk= 100644
--- a/views.py
+++ b/views.py
@@ -15,7 +15,9 @@
 from cubicweb.web import dumps
 
 from cubicweb.selectors import (implements, has_permission, authenticated_user,
-                                score_entity, relation_possible, one_line_rset)
+                                score_entity, relation_possible, one_line_rset,
+                                match_kwargs, match_form_params,
+                                partial_relation_possible, traced_selection)
 from cubicweb.view import EntityView
 from cubicweb.uilib import rql_for_eid, cut, safe_cut
 from cubicweb.mixins import TreeViewMixIn
@@ -193,7 +195,7 @@
 
 # comment forms ################################################################
 
-class InlineEditCommentForm(form.FormViewMixIn, EntityView):
+class InlineEditCommentFormView(form.FormViewMixIn, EntityView):
     __regid__ = 'editcommentform'
     __select__ = implements('Comment')
 
@@ -197,6 +199,5 @@
     __regid__ = 'editcommentform'
     __select__ = implements('Comment')
 
-    jsfunc = "processComment(%s, '%s', false)"
-    jsonmeth = 'edit_comment'
+    jsfunc = "processComment(%s, %s, false)"
 
@@ -202,6 +203,6 @@
 
-    def cell_call(self, row, col):
-        self.comment_form(self.cw_rset.get_entity(row, col))
+    def entity_call(self, entity):
+        self.comment_form(entity)
 
     def propose_to_login(self):
         self.w(u'<div class="warning">%s ' % self._cw._('You are not authenticated.'))
@@ -212,7 +213,7 @@
         self.w(u'</div>')
 
     def comment_form(self, commented, newcomment=None):
-        self._cw.add_js('cubes.comment.js')
+        self._cw.add_js(('cubicweb.edition.js', 'cubes.comment.js'))
         if newcomment is None:
             newcomment = commented
         if self._cw.cnx.anonymous_connection:
@@ -220,6 +221,5 @@
         # hack to avoid tabindex conflicts caused by Ajax requests
         self._cw.next_tabindex = count(20).next
         jseid = dumps(commented.eid)
-        cancel_action = self.jsfunc % (jseid, '')
-        buttons = [fw.Button(onclick=self.jsfunc % (jseid, self.jsonmeth)),
+        buttons = [fw.Button(onclick=self.jsfunc % (jseid, 'false')),
                    fw.Button(stdmsgs.BUTTON_CANCEL,
@@ -225,6 +225,24 @@
                    fw.Button(stdmsgs.BUTTON_CANCEL,
-                             onclick=cancel_action)]
-        form = self._cw.vreg['forms'].select('edition', self._cw,
-                                             entity=newcomment,
-                                             form_buttons=buttons)
+                             onclick=self.jsfunc % (jseid, 'true'))]
+        fvreg = self._cw.vreg['forms']
+        if newcomment is not None and not commented.has_eid():
+            form = fvreg.select('composite', self._cw, form_buttons=buttons,
+                                domid='commentForm%s' % commented.eid,
+                                form_renderer_id='default')
+            form.add_subform(fvreg.select('edition', self._cw, entity=commented,
+                                          mainform=False))
+            cform = fvreg.select('edition', self._cw, entity=newcomment,
+                                          mainform=False)
+            form.add_subform(cform)
+        else:
+            form = fvreg.select('edition', self._cw, entity=newcomment,
+                                domid='commentForm%s' % commented.eid,
+                                form_buttons=buttons)
+            cform = form
+        if newcomment is not None:
+            cform.append_field(cform.field_by_name('comments', 'subject',
+                                                eschema=newcomment.e_schema))
+            formvalues = {'comments': commented.eid}
+        else:
+            formvalues = {}
         self.w(u'<div id="comment%sSlot">%s</div>' % (
@@ -230,6 +248,7 @@
         self.w(u'<div id="comment%sSlot">%s</div>' % (
-            commented.eid, form.render(main_form_title=u'',
+            commented.eid, form.render(formvalues={'comments': commented.eid},
+                                       main_form_title=u'',
                                        display_label=False,
                                        display_relations_form=False)))
 
 
@@ -232,6 +251,6 @@
                                        display_label=False,
                                        display_relations_form=False)))
 
 
-class InlineAddCommentForm(InlineEditCommentForm):
+class InlineAddCommentFormView(InlineEditCommentFormView):
     __regid__ = 'addcommentform'
@@ -237,3 +256,6 @@
     __regid__ = 'addcommentform'
-    __select__ = relation_possible('comments', 'object', 'Comment', 'add')
+    __select__ = (relation_possible('comments', 'object', 'Comment', 'add')
+                  | match_form_params('etype'))
+
+    jsfunc = "processComment(%s, %s, true)"
 
@@ -239,4 +261,9 @@
 
-    jsfunc = "processComment(%s, '%s', true)"
-    jsonmeth = 'add_comment'
+    def call(self, **kwargs):
+        if self.cw_rset is None:
+            entity = self._cw.vreg['etypes'].etype_class(self._cw.form['etype'])(self._cw)
+            entity.eid = self._cw.varmaker.next()
+            self.entity_call(entity)
+        else:
+            super(InlineAddCommentFormView, self).call(**kwargs)
 
@@ -242,6 +269,5 @@
 
-    def cell_call(self, row, col):
-        commented = self.cw_rset.get_entity(row, col)
+    def entity_call(self, commented):
         newcomment = self._cw.vreg['etypes'].etype_class('Comment')(self._cw)
         newcomment.eid = self._cw.varmaker.next()
         self.comment_form(commented, newcomment)
@@ -254,8 +280,8 @@
     related to an object
     """
     __regid__ = 'commentsection'
-    __select__ = (component.EntityVComponent.__select__
+    __select__ = ((component.EntityVComponent.__select__ | match_kwargs('entity'))
                   & relation_possible('comments', 'object', 'Comment'))
 
     context = 'navcontentbottom'
 
@@ -258,7 +284,7 @@
                   & relation_possible('comments', 'object', 'Comment'))
 
     context = 'navcontentbottom'
 
-    def cell_call(self, row, col, view=None):
+    def entity_call(self, entity, view=None):
         req = self._cw
         req.add_js( ('cubicweb.ajax.js', 'cubes.comment.js') )
@@ -263,5 +289,5 @@
         req = self._cw
         req.add_js( ('cubicweb.ajax.js', 'cubes.comment.js') )
-        eid = self.cw_rset[row][col]
+        eid = entity.eid
         self.w(u'<div id="%s" class="%s" cubicweb:rooteid="%s">' % (
             self.div_id(), self.div_class(), eid))
@@ -266,14 +292,14 @@
         self.w(u'<div id="%s" class="%s" cubicweb:rooteid="%s">' % (
             self.div_id(), self.div_class(), eid))
-        rql = u'Any C,CD,CC,CCF,U,UL,US,UF ORDERBY CD WHERE C is Comment, '\
-              'C comments X, C creation_date CD, C content CC, C content_format CCF, ' \
-              'C created_by U?, U login UL, U firstname UF, U surname US, X eid %(x)s'
-        rset = req.execute(rql, {'x': eid}, 'x')
-        if rset.rowcount:
-            self.w(u'<h4>%s</h4>' % (req._('Comment_plural')))
-        if rset.rowcount:
-            self.w(u'<ul class="comment">')
-            for i in xrange(rset.rowcount):
-                self.wview('tree', rset, row=i)
-            self.w(u'</ul>')
+        if entity.has_eid():
+            rql = u'Any C,CD,CC,CCF,U,UL,US,UF ORDERBY CD WHERE C is Comment, '\
+                  'C comments X, C creation_date CD, C content CC, C content_format CCF, ' \
+                  'C created_by U?, U login UL, U firstname UF, U surname US, X eid %(x)s'
+            rset = req.execute(rql, {'x': eid})
+            if rset.rowcount:
+                self.w(u'<h4>%s</h4>' % (req._('Comment_plural')))
+                self.w(u'<ul class="comment">')
+                for i in xrange(rset.rowcount):
+                    self.wview('tree', rset, row=i)
+                self.w(u'</ul>')
         self.w(u'</div>')
@@ -279,6 +305,6 @@
         self.w(u'</div>')
-        addcomment = self._cw.vreg['actions'].select_or_none('reply_comment', req,
-                                                        rset=self.cw_rset,
-                                                        row=row, col=col)
+        addcomment = self._cw.vreg['actions'].select_or_none(
+            'reply_comment', req, entity=entity,
+            rset=entity.cw_rset, row=entity.cw_row, col=entity.cw_col)
         if addcomment is not None:
             self.w(u'<div id="comment%sHolder"></div>' % eid)
@@ -283,5 +309,10 @@
         if addcomment is not None:
             self.w(u'<div id="comment%sHolder"></div>' % eid)
-            url = req.build_ajax_replace_url(
-                'comment%sHolder' % eid, rql_for_eid(eid), 'addcommentform')
+            params = self.cw_extra_kwargs
+            if entity.has_eid():
+                params['eid'] = eid
+            else:
+                params['etype'] = entity.__regid__
+            url = req.ajax_replace_url(
+                'comment%sHolder' % eid, vid='addcommentform', **params)
             self.w(u' (<a href="%s">%s</a>)' % (url, req._(addcomment.title)))
@@ -287,7 +318,4 @@
             self.w(u' (<a href="%s">%s</a>)' % (url, req._(addcomment.title)))
-            # XXX still necessary?
-            #if req.use_fckeditor() and req.property_value('ui.default-text-format') == 'text/html':
-            #    req.fckeditor_config()
 
 
 class UserLatestCommentsSection(component.EntityVComponent):
@@ -341,7 +369,9 @@
 class AddCommentAction(LinkToEntityAction):
     """add comment is like reply for everything but Comment"""
     __regid__ = 'reply_comment'
-    __select__ = LinkToEntityAction.__select__ & ~implements('Comment')
+    __select__ = ((LinkToEntityAction.__select__
+                   | (match_kwargs('entity') & partial_relation_possible(action='add', strict=True)))
+                   & ~implements('Comment'))
 
     rtype = 'comments'
     role = 'object'
@@ -374,20 +404,3 @@
 
     def url(self):
         return self._cw.build_url(rql=self.cw_rset.printable_rql(), vid='deleteconf')
-
-
-# JSONController extensions through monkey-patching ############################
-
-@monkeypatch(basecontrollers.JSonController)
-@basecontrollers.jsonize
-def js_add_comment(self, commented, text, format):
-    return self._cw.execute('INSERT Comment C: C comments X, C content %(text)s, '
-                            'C content_format %(format)s  WHERE X eid %(x)s',
-                            {'format' : format, 'text' : text, 'x' : commented}, 'x')[0][0]
-
-@monkeypatch(basecontrollers.JSonController)
-@basecontrollers.jsonize
-def js_edit_comment(self, comment, text, format):
-    self._cw.execute('SET C content %(text)s, C content_format %(format)s '
-                     'WHERE C eid %(x)s',
-                     {'format' : format, 'text' : text, 'x' : comment}, 'x')