# HG changeset patch
# User Sylvain Thénault <sylvain.thenault@logilab.fr>
# Date 1270655450 -7200
#      Wed Apr 07 17:50:50 2010 +0200
# Branch stable
# Node ID 2da4fe4c55265f096763040a3738ff7711a42113
# Parent  800f6067a053374b00cea06081c73a005fbd2c2a
fix #816385 by [re]loading only new/edited comment and properly edit the DOM using js. Also: cleanup javascript, try to put form where the comment will be located (not yet finished)

diff --git a/data/cubes.comment.js b/data/cubes.comment.js
--- a/data/cubes.comment.js
+++ b/data/cubes.comment.js
@@ -19,33 +19,50 @@
 }
 
 /* this function is called on inlined-comment editions
- * It calls the add_comment method on the jsoncontroller and reload
- * the comment's component
+ * 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) {
-    var buttonbar = jQuery('#comment' + eid + 'bbar').hide();
-    var divNode = jQuery('#comment' + eid + 'Slot');
+function processComment(eid, funcname, creation) {
+    var divId = 'comment' + eid + 'Slot'
+    var divNode = jQuery('#'+divId);
     var textarea = divNode.find('textarea')[0];
-    var comment = _getText(textarea);
     if (funcname) {
-        // store original value for edit cancel
-        textarea.setAttribute('cubicweb:origval', comment);
         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, comment, format);
-        d.addCallback(function () {
-            var rooteid = getNode('commentsectionComponent').getAttribute('cubicweb:rooteid');
-	    if (rooteid == eid){
-	        reloadComponent('commentsection', rql_for_eid(eid), 'contentnavigation');
-            } else {
-		reloadComponent('tree', rql_for_eid(eid), 'views', 'comment'+eid);
+        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');
         });
-    } else { // comment cancelled, close div holding the form
-        jQuery('#comment' + eid + 'Slot').remove();
+    } else {
+	// comment cancelled, close div holding the form
+        divNode.remove();
+	// on edition, show back the comment's content
+	if (!creation) {
+	    jQuery('#comment' + eid + 'Div div').show();
+	}
     }
 }
 
diff --git a/views.py b/views.py
--- a/views.py
+++ b/views.py
@@ -27,7 +27,7 @@
 from cubicweb.web.formwidgets import Button
 from cubicweb.web.views import primary, baseviews, xmlrss
 from cubicweb.web.component import EntityVComponent
-from cubicweb.web.views.basecontrollers import JSonController
+from cubicweb.web.views.basecontrollers import JSonController, jsonize
 
 
 uicfg.autoform_section.tag_subject_of(('*', 'comments', '*'), formtype='main', section='hidden')
@@ -114,6 +114,9 @@
         self._cw.add_css('cubes.comment.css')
         entity = self.cw_rset.get_entity(row, col)
         actions = self._cw.vreg['actions']
+        # DOM id of the whole comment's content
+        cdivid = 'comment%sDiv' % entity.eid
+        self.w(u'<div id="%s">' % cdivid)
         self.w(u'<div class="commentInfo">')
         self.w(self._cw.format_date(entity.creation_date))
         self.w(u' %s' % self._cw.format_time(entity.creation_date))
@@ -137,9 +140,11 @@
         editaction = actions.select_or_none('edit_comment', self._cw,
                                             rset=self.cw_rset, row=row)
         if editaction is not None:
-            url = self._cw.build_ajax_replace_url(
-                'comment%s' % entity.eid, rql_for_eid(entity.eid),
-                'editcomment')
+            # split(':', 1)[1] to remove javascript:
+            formjs = self._cw.build_ajax_replace_url(
+                cdivid, rql_for_eid(entity.eid),
+                'editcomment', 'append').split(':', 1)[1]
+            url = "javascript: jQuery('#%s div').hide(); %s" % (cdivid, formjs)
             self.w(u' | <span class="replyto"><a href="%s">%s</a></span>'
                    % (xml_escape(url), self._cw._(editaction.title)))
 
@@ -152,14 +157,12 @@
 
             self.w(u' | <span class="replyto"><a href="%s">%s</a></span>'
                    % (xml_escape(url), self._cw._(deleteaction.title)))
-
-        self.w(u'</div>\n')
-        text = entity.printable_value('content')
-        if not kwargs.get('full'):
-            maxsize = self._cw.property_value('navigation.short-line-size')
-            text = safe_cut(text, maxsize)
-        self.w(u'<div class="commentBody">%s</div>\n' % text)
+        self.w(u'</div>\n') # close comment's info div
+        self.w(u'<div class="commentBody">%s</div>\n'
+               % entity.printable_value('content'))
+        # holder for reply form
         self.w(u'<div id="comment%sHolder" class="replyComment"></div>' % entity.eid)
+        self.w(u'</div>\n') # close comment's content div
 
 
 class CommentThreadView(TreeViewMixIn, baseviews.ListView):
@@ -185,7 +188,7 @@
     __regid__ = 'editcomment'
     __select__ = implements('Comment')
 
-    jsfunc = "processComment(%s, '%s')"
+    jsfunc = "processComment(%s, '%s', false)"
     jsonmeth = 'edit_comment'
 
     def cell_call(self, row, col):
@@ -215,6 +218,7 @@
     __regid__ = 'inlinecommentform'
     __select__ = match_kwargs('commented') # explicit call when it makes sense
 
+    jsfunc = "processComment(%s, '%s', true)"
     jsonmeth = 'add_comment'
 
     def call(self, commented):
@@ -247,10 +251,17 @@
         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>')
+        self.w(u'</div>')
         addcomment = self._cw.vreg['actions'].select_or_none('reply_comment', req,
                                                         rset=self.cw_rset,
                                                         row=row, col=col)
         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), 'inlinecomment')
             self.w(u' (<a href="%s" onclick="javascript:toggleVisibility(\'addCommentLinks\');">%s</a>)' % (url, req._(addcomment.title)))
@@ -260,13 +271,6 @@
         if req.cnx.anonymous_connection:
             self.w(u'<div id="addCommentLinks" class="hidden">%s %s</div>' % \
                    (_login_register_link(req), req._(u'to comment')))
-        self.w(u'<div id="comment%sHolder"></div>' % eid)
-        if rset.rowcount:
-            self.w(u'<ul class="comment">')
-            for i in xrange(rset.rowcount):
-                self.wview('tree', rset, row=i, full=True)
-            self.w(u'</ul>')
-        self.w(u'</div>')
 
 
 # comment actions #############################################################
@@ -333,12 +337,14 @@
 # add some comments related methods to the Jsoncontroller #####################
 
 @monkeypatch(JSonController)
+@jsonize
 def js_add_comment(self, commented, text, format):
-    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')
+    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(JSonController)
+@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',