fu: Close-up of Fu, bringing a scoop of water to her mouth (Default)
fu ([personal profile] fu) wrote in [site community profile] changelog2011-09-29 05:13 pm

[dw-free] Expand all comments on page

[commit: http://hg.dwscoalition.org/dw-free/rev/eec83fe603d3]

http://bugs.dwscoalition.org/show_bug.cgi?id=31

New link: "Expand all comments on page".

Patch by [personal profile] allen.

Files modified:
  • bin/upgrading/en.dat
  • bin/upgrading/s2layers/core2.s2
  • cgi-bin/LJ/S2/EntryPage.pm
  • cgi-bin/LJ/Talk.pm
  • cgi-bin/LJ/User.pm
  • htdocs/js/jquery.threadexpander.js
  • htdocs/js/thread_expander.js
  • htdocs/talkread.bml
--------------------------------------------------------------------------------
diff -r 6c913dabed65 -r eec83fe603d3 bin/upgrading/en.dat
--- a/bin/upgrading/en.dat	Fri Sep 30 00:53:33 2011 +0800
+++ b/bin/upgrading/en.dat	Fri Sep 30 01:13:39 2011 +0800
@@ -3903,6 +3903,8 @@
 
 talk.error.suspendedentryreply=This entry has been suspended. You can't reply to it. <a [[aopts]]>Visit the journal</a>.
 
+talk.expandalllink=Expand All
+
 talk.expandlink=Expand
 
 talk.frozen=Replies frozen
diff -r 6c913dabed65 -r eec83fe603d3 bin/upgrading/s2layers/core2.s2
--- a/bin/upgrading/s2layers/core2.s2	Fri Sep 30 00:53:33 2011 +0800
+++ b/bin/upgrading/s2layers/core2.s2	Fri Sep 30 01:13:39 2011 +0800
@@ -487,7 +487,9 @@
 {
   var string view_mode "The current view mode (threaded, flat, top-only).";
   var string url "The url for this entry page, complete with style argument if present.";
+  var int current_page "The currently displayed page";
   var bool filter "True if the current view is filtered.";
+  var bool show_expand_all "True if we should show the expand_all option.";
 
   function print () "Prints the nav bar, including the comment_pages bar";
 }
@@ -5968,13 +5970,15 @@
 function CommentNav::print
 {
     var string sep = $.url->contains( "?" ) ? "&" : "?";
+    var string page_arg = $.current_page > 1 ? "&page=$.current_page" : "";
 
     print "<div class='comment-pages'>";
 
     var string{} links = {
         "flat"      => """<a href="$.url${sep}view=flat#comments">Flat</a>""",
         "threaded"  => """<a href="$.url#comments">Threaded</a>""",
-        "top-only"  => """<a href="$.url${sep}view=top-only#comments">Top-Level Comments Only</a>"""
+        "top-only"  => """<a href="$.url${sep}view=top-only#comments">Top-Level Comments Only</a>""",
+        "expand_all"  => """<a href="$.url${sep}expand_all=1${page_arg}#comments" onClick="Expander.make(this,'$.url${sep}expand_all=1${page_arg}#comments',-1,false,false);return false;">Expand All</a>"""
     };
 
     if ( $.view_mode == "threaded" ) {
@@ -5985,6 +5989,9 @@
         print "$links{"threaded"} | $links{"flat"}";
     }
 
+    if ( $.show_expand_all ) {
+        print "<span id='expand_all'> | $links{"expand_all"}</span>";
+    }
     print "</div>";
 }
 
diff -r 6c913dabed65 -r eec83fe603d3 cgi-bin/LJ/S2/EntryPage.pm
--- a/cgi-bin/LJ/S2/EntryPage.pm	Fri Sep 30 00:53:33 2011 +0800
+++ b/cgi-bin/LJ/S2/EntryPage.pm	Fri Sep 30 01:13:39 2011 +0800
@@ -101,6 +101,8 @@
     my $top_only_mode  = ($view_arg =~ /\btop-only\b/);
     my $view_num = ($view_arg =~ /(\d+)/) ? $1 : undef;
 
+    my $expand_all = ( $u->thread_expand_all( $remote ) && $get->{'expand_all'} );
+
     my %userpic;
     my %user;
     my $copts = {
@@ -114,7 +116,7 @@
         # user object is cached from call just made in EntryPage_entry
         'up' => LJ::load_user($s2entry->{'poster'}->{'user'}),
         'viewall' => $viewall,
-        'expand_all' => $opts->{expand_all},
+        'expand_all' => $expand_all,
         'filter' => $get->{comments},
     };
 
@@ -377,6 +379,8 @@
                     u      => $poster,
                     parent => $cmt->parent ? $cmt->parent->dtalkid : undef,
                     full   => ($i->{full}),
+                    deleted   => $cmt->is_deleted,
+                    screened   => $cmt->is_screened,
                 };
                 $self->($self, $i->{'replies'}) if $has_threads;
             }
@@ -415,11 +419,13 @@
         $copts->{'out_itemfirst'} = $copts->{'out_itemlast'} = undef;
     }
 
+    my $show_expand_all = $u->thread_expand_all( $remote ) && $copts->{out_has_collapsed} && ! $top_only_mode;
     # creates the comment nav bar
     $p->{'comment_nav'} = CommentNav({
         'view_mode' => $flat_mode ? "flat" : $top_only_mode ? "top-only" : "threaded",
         'url' => $entry->url( style_args => LJ::viewing_style_opts( %$get ) ),
         'current_page' => $copts->{'out_page'},
+        'show_expand_all' => $show_expand_all,
     });
 
     $p->{'comment_pages'} = ItemRange({
diff -r 6c913dabed65 -r eec83fe603d3 cgi-bin/LJ/Talk.pm
--- a/cgi-bin/LJ/Talk.pm	Fri Sep 30 00:53:33 2011 +0800
+++ b/cgi-bin/LJ/Talk.pm	Fri Sep 30 01:13:39 2011 +0800
@@ -916,6 +916,7 @@
 #   out_itemlast:  last comment number on page (1-based, not db numbers)
 #   out_pagesize:  size of each page
 #   out_items:  number of total top level items
+#   out_has_collpased:  set by us; 0 if no collapsed messages, 1 if there are
 #
 #   userpicref -- hashref to load userpics into, or undef to
 #                 not load them.
@@ -1169,6 +1170,9 @@
 
     my (@subjects_to_load, @subjects_ignored);
 
+    # track if there are any collapsed messages being displayed
+    my $has_collapsed = 0;
+
     while (@check_for_children) {
         my $cfc = shift @check_for_children;
 
@@ -1179,6 +1183,7 @@
                 ## expand only the first child, then clear the flag
                 delete $expand_children{$cfc};
             } else {
+                $has_collapsed = 1;
                 if ( $opts->{'top-only'} ) {
                     $posts->{$child}->{'hidden_child'} = 1;
                 }
@@ -1198,6 +1203,7 @@
     $opts->{'out_itemlast'} = $itemlast;
     $opts->{'out_pagesize'} = $page_size;
     $opts->{'out_items'} = $top_replies;
+    $opts->{'out_has_collapsed'} = $has_collapsed;
 
     # load text of posts
     my ($posts_loaded, $subjects_loaded);
diff -r 6c913dabed65 -r eec83fe603d3 cgi-bin/LJ/User.pm
--- a/cgi-bin/LJ/User.pm	Fri Sep 30 00:53:33 2011 +0800
+++ b/cgi-bin/LJ/User.pm	Fri Sep 30 01:13:39 2011 +0800
@@ -3066,6 +3066,16 @@
     return 0;
 }
 
+# should allow expand-all for this user/journal
+sub thread_expand_all {
+    my ( $u, $remote ) = @_;
+
+    return 1 if $remote && $remote->get_cap( 'thread_expand_all' )
+        || $u->get_cap( 'thread_expand_all' );
+
+    return 0;
+}
+
 #get/set Sticky Entry parent ID for settings menu
 sub sticky_entry {
     my ( $u, $input ) = @_;
diff -r 6c913dabed65 -r eec83fe603d3 htdocs/js/jquery.threadexpander.js
--- a/htdocs/js/jquery.threadexpander.js	Fri Sep 30 00:53:33 2011 +0800
+++ b/htdocs/js/jquery.threadexpander.js	Fri Sep 30 01:13:39 2011 +0800
@@ -23,8 +23,23 @@
     if (includeSelf) {
       returnValue.push(talkid);
     }
-    for (var i = 0; i < LJ[talkid].rc.length; i++) {
-      returnValue = returnValue.concat(getReplies(LJ, LJ[talkid].rc[i], true));
+    if (LJ[talkid] && LJ[talkid].rc) {
+      for (var i = 0; i < LJ[talkid].rc.length; i++) {
+        returnValue = returnValue.concat(getReplies(LJ, LJ[talkid].rc[i], true));
+      }
+    }
+    return returnValue;
+  }
+
+  /**
+   * Returns all of the unexpanded comments on this page.
+   */
+  function getUnexpandedComments(LJ) {
+    var returnValue = [];
+    for (var talkid in LJ) {
+      if (LJ[talkid].hasOwnProperty("full") && ! LJ[talkid].full && ! LJ[talkid].deleted && ! LJ[talkid].screened) {
+        returnValue.push(talkid);
+      }
     }
     return returnValue;
   }
@@ -55,14 +70,31 @@
           datatype: "html",
           timeout: 30000,
           success: function(data) {
-          element.doJqExpand(LJ, data, talkid, isS1, unhide);
-        },
+            var updateCount = element.doJqExpand(LJ, data, talkid, isS1, unhide);
+            // if we didn't update any comments, something must have gone wrong
+            if (updateCount == 0) {
+              showExpanderError($.threadexpander.config.text.error_nomatches);
+            } else if (unhide) {
+              element.unhideComments(LJ, talkid, isS1);
+            }
+
+            // remove the expand_all option if all comments are expanded
+            var expand_all_span = $('#expand_all');
+            if (expand_all_span.length > 0) {
+              if (getUnexpandedComments(LJ).length == 0) {
+                expand_all_span.fadeOut('fast');
+              } else if (talkid < 0) {
+                img.remove();
+                element.removeClass("disabled").fadeTo("fast", 1.0);
+              }
+            }
+          },
           error: function(jqXHR, textStatus, errorThrown) {
-          img.remove();
-          element.removeClass("disabled");
-          element.fadeTo("fast", 1.0);
-          showExpanderError($.threadexpander.config.text.error);
-        }
+            img.remove();
+            element.removeClass("disabled");
+            element.fadeTo("fast", 1.0);
+            showExpanderError($.threadexpander.config.text.error);
+          }
       } );
   };
 
@@ -70,39 +102,61 @@
   $.fn.doJqExpand = function(LJ, data, talkid, isS1, unhide) {
     var updateCount = 0;
     // check for matching expansions on the page
-    var replies = getReplies(LJ, talkid, true);
-    for (var cmtIdCnt = 0; cmtIdCnt < replies.length; cmtIdCnt++) {
-      var cmtId = replies[cmtIdCnt];
-      // if we're a valid comment, and either the comment is not expanded
-      // or it's the original comment, then it's valid to expand it.
-      if (/^\d*$/.test(cmtId) && (talkid == cmtId || (! LJ[cmtId].full))) {
-        var cmtElement = $("#cmt" + cmtId);
-        if (cmtElement) {
-          var newComment = $("#cmt" + cmtId, data);
-          if (newComment && newComment.attr('id') == 'cmt' + cmtId) {
-            if (isS1) {
-              var oldWidth = getS1SpacerObject(cmtElement).width();
-              getS1SpacerObject(newComment).width(oldWidth);
+    var replies;
+    if (talkid > 0) {
+      replies = getReplies(LJ, talkid, true);
+    } else {
+      replies = getUnexpandedComments(LJ);
+    }
+
+    if (replies.length > 0) {
+      // get all comments and map them by id.  this seems to be more efficient
+      // in jquery (at least for the results of an ajax request).
+      var newComments = $(".comment", data);
+      var newCommentMap = {};
+      newComments.each(function() {
+          newCommentMap[$(this).attr("id")] = $(this);
+        });
+
+      var cmtIdPrefix = isS1 ? "cmt" : "comment-cmt";
+      for (var cmtIdCnt = 0; cmtIdCnt < replies.length; cmtIdCnt++) {
+        var cmtId = replies[cmtIdCnt];
+        // if we're a valid comment, and either the comment is not expanded
+        // or it's the original comment, then it's valid to expand it.
+        if (/^\d*$/.test(cmtId) && (talkid == cmtId || (! LJ[cmtId].full))) {
+          var cmtElement = $('#' + cmtIdPrefix + cmtId);
+          if (cmtElement.length > 0) {
+            var newComment = newCommentMap[cmtIdPrefix + cmtId];
+            if (newComment) {
+              if (isS1) {
+                var oldWidth = getS1SpacerObject(cmtElement).width();
+                getS1SpacerObject(newComment).width(oldWidth);
+              }
+              cmtElement.html($(newComment).html())
+                .trigger( "updatedcontent.comment" );
+              $(".cmt_show_hide_default", cmtElement).show();
+
+              // don't mark partial comments as full; make sure that the
+              // loaded comments are full.
+              if (isS1) {
+                if ($('table.talk-comment', newComment).length > 0) {
+                  LJ[cmtId].full = true;
+                }
+              } else {
+                if (newComment.parent().hasClass("full")) {
+                  LJ[cmtId].full = true;
+                  setFull(cmtElement, true);
+                }
+              }
+              updateCount++;
             }
-            cmtElement.html($(newComment).html())
-                .trigger( "updatedcontent.comment" );
-            $(".cmt_show_hide_default", cmtElement).show();
-            LJ[cmtId].full = true;
-            if (! isS1) {
-              setFull(cmtElement, true);
-            }
-            updateCount++;
           }
         }
       }
     }
 
-    // if we didn't update any comments, something must have gone wrong
-    if (updateCount == 0) {
-      showExpanderError($.threadexpander.config.text.error_nomatches);
-    } else if (unhide) {
-      this.unhideComments(LJ, talkid, isS1);
-    }
+    return updateCount;
+
   }
 
   // returns the comment elements for the given talkids.
diff -r 6c913dabed65 -r eec83fe603d3 htdocs/js/thread_expander.js
--- a/htdocs/js/thread_expander.js	Fri Sep 30 00:53:33 2011 +0800
+++ b/htdocs/js/thread_expander.js	Fri Sep 30 01:13:39 2011 +0800
@@ -3,7 +3,7 @@
     this.__caller__;    // <a> HTML element from where Expander was called
     this.url;           // full url of thread to be expanded
     this.id;            // id of the thread
-    this.onclick;   
+    this.onclick;
     this.stored_caller;
     this.iframe;        // iframe, where the thread will be loaded
     this.is_S1;         // bool flag, true == journal is in S1, false == in S2
@@ -22,7 +22,7 @@
 }
 
 Expander.prototype.getCanvas = function(id,context){
-    return context.document.getElementById('cmt'+id); 
+    return context.document.getElementById('cmt'+id);
 }
 
 Expander.prototype.parseLJ_cmtinfo = function(context,callback){
@@ -33,15 +33,15 @@
         if(/^\d*$/.test(j) && (node = this.getCanvas(j,context))){
             map[j] = {info:LJ[j],canvas:node};
             if(typeof callback == 'function'){
-                callback(j,map[j]);     
+                callback(j,map[j]);
             }
         }
     }
-    return map; 
+    return map;
 }
 
 Expander.prototype.loadingStateOn = function(){
-    this.stored_caller = this.__caller__.cloneNode(true); 
+    this.stored_caller = this.__caller__.cloneNode(true);
     this.__caller__.setAttribute('already_clicked','already_clicked');
     this.onclick = this.__caller__.onclick;
     this.__caller__.onclick = function(){return false;}
@@ -49,11 +49,28 @@
 }
 
 Expander.prototype.loadingStateOff = function(){
-    if(this.__caller__){
-        // actually, the <a> element is removed from main window by
-        // copying comment from ifame, so this code is not executed (?)
-        this.__caller__.removeAttribute('already_clicked','already_clicked');
-        if(this.__caller__.parentNode) this.__caller__.parentNode.replaceChild(this.stored_caller,this.__caller__);
+    var expand_all = document.getElementById("expand_all");
+    if (expand_all != null) {
+      // if all comments have been expanded, remove the expand_all entry
+      var LJ = window.LJ_cmtinfo;
+      var removeExpandAll = true;
+      for (var talkid in LJ) {
+        if (LJ[talkid].hasOwnProperty("full") && ! LJ[talkid].full && ! LJ[talkid].deleted && ! LJ[talkid].screened) {
+          removeExpandAll = false;
+        }
+      }
+      if (removeExpandAll) {
+        expand_all.parentNode.removeChild(expand_all);
+      }
+    }
+
+    if (this.__caller__) {
+      // only used on error, or when expand all fails to expand all.
+      // in most cases, the <a> element is removed from main window by
+      // copying comment from iframe, or above by the removeExpandAll
+      // logic, so this code is not executed.
+      this.__caller__.removeAttribute('already_clicked','already_clicked');
+      if (this.__caller__.parentNode) this.__caller__.parentNode.replaceChild(this.stored_caller,this.__caller__);
     }
     var obj = this;
     // When frame is removed immediately, IE raises an error sometimes
@@ -61,7 +78,7 @@
 }
 
 Expander.prototype.killFrame = function(){
-    document.body.removeChild(this.iframe); 
+    document.body.removeChild(this.iframe);
 }
 
 Expander.prototype.isFullComment = function(comment){
@@ -92,30 +109,30 @@
   //yet, this works until we have not changed the spacers url = 'dot.gif');
   var img, imgs, found;
   imgs = canvas.getElementsByTagName('img');
-  if(!imgs)return false;    
+  if(!imgs)return false;
   for(var j=0;j<imgs.length;j++){
     img=imgs[j];
     if(/dot\.gif$/.test(img.src)){
         found = true;
-        break;  
+        break;
     }
   }
-  if(found&&img.width)return Number(img.width);   
-  else return false;     
+  if(found&&img.width)return Number(img.width);
+  else return false;
 }
 
 Expander.prototype.setS1width = function(canvas,w){
   var img, imgs, found;
   imgs = canvas.getElementsByTagName('img');
-  if(!imgs)return false;    
+  if(!imgs)return false;
   for(var j=0;j<imgs.length;j++){
     img=imgs[j];
     if(/dot\.gif$/.test(img.src)){
         found = true;
-        break;  
+        break;
     }
   }
-  if(found)img.setAttribute('width',w);         
+  if(found)img.setAttribute('width',w);
 }
 
 Expander.prototype.onLoadHandler = function(iframe){
@@ -131,12 +148,12 @@
                                         comments_intersection[id] = comments_page[id];
                                         // copy comment from iframe to main window if
                                         // 1) the comment is collapsed in main window and is full in iframe
-                                        // 2) or this is the root comment of this thread (it may be full in 
+                                        // 2) or this is the root comment of this thread (it may be full in
                                         //     main window too, it's copied so that to remove "expand" link from it)
                                         if((!obj.isFullComment(comments_page[id]) && obj.isFullComment(new_comment)) || (id===obj.id)){
                                             var w;
                                             if(obj.is_S1){
-                                                w =obj.getS1width(comments_page[id].canvas);        
+                                                w =obj.getS1width(comments_page[id].canvas);
                                             }
                                             comments_page[id].canvas.innerHTML = new_comment.canvas.innerHTML;
                                             if(obj.is_S1 && w!==null){
@@ -148,7 +165,7 @@
                                         }
                                     }//if(id in comments_page){
                                 });
-       this.killDuplicate(comments_intersection);   
+       this.killDuplicate(comments_intersection);
        this.loadingStateOff();
        if ( typeof ContextualPopup.setup() != "undefined" )
            ContextualPopup.setup();
@@ -158,7 +175,7 @@
 
 //just for debugging
 Expander.prototype.toString = function(){
-  return '__'+this.id+'__'; 
+  return '__'+this.id+'__';
 }
 
 
@@ -167,7 +184,7 @@
         return false;
     }
     this.loadingStateOn();
-    
+
     var iframe;
     if(/*@cc_on !@*/0){
         // branch for IE
diff -r 6c913dabed65 -r eec83fe603d3 htdocs/talkread.bml
--- a/htdocs/talkread.bml	Fri Sep 30 00:53:33 2011 +0800
+++ b/htdocs/talkread.bml	Fri Sep 30 01:13:39 2011 +0800
@@ -64,6 +64,7 @@
                thread          talk.threadlink
                threadroot      talk.threadrootlink
                expand          talk.expandlink
+               expandall       talk.expandalllink
                replythis       talk.replytothis
                screened        talk.screened
                frozen          talk.frozen
@@ -243,13 +244,13 @@
     BML::ebml(\$event);
 
     # make the title
-{
-       my $subject = $item->{'subject'} || $event;
-       # yes, the 3 param to text_trim is chars, and length returns bytes, but
-       # it works, as bytes >= chars:
-       $subject = LJ::CleanHTML::clean_and_trim_subject(\$subject, length($item->{'subject'}) || 40);
-       $$title = "$u->{'user'}: $subject";
-}
+    {
+        my $subject = $item->{'subject'} || $event;
+        # yes, the 3 param to text_trim is chars, and length returns bytes, but
+        # it works, as bytes >= chars:
+        $subject = LJ::CleanHTML::clean_and_trim_subject(\$subject, length($item->{'subject'}) || 40);
+        $$title = "$u->{'user'}: $subject";
+    }
 
     $ret .= "<p>";
     $ret .= "<table summary='' id='poster'><tr>";
@@ -349,6 +350,8 @@
     my $top_only = ($view_arg =~ /\btop-only\b/);
     my $view_num = ($view_arg =~ /(\d+)/) ? $1 : undef;
 
+    my $expand_all = ( $u->thread_expand_all( $remote ) && $GET{'expand_all'} );
+
     my %user;
     my $opts = {
         'flat' => $flat_mode,
@@ -361,6 +364,7 @@
         'up' => $up,
         'viewall' => $viewall,
         'filter' => $GET{comments},
+        'expand_all' => $expand_all,
     };
 
     my @comments = LJ::Talk::load_comments($u, $remote, "L", $itemid, $opts);
@@ -369,6 +373,8 @@
     my $page  = $opts->{out_page};
     my $pages = $opts->{out_pages};
 
+    my $has_collapsed = $opts->{out_has_collapsed};
+
     # this overrides the default self_link to add the #comments anchor
     my $self_link = sub { BML::self_link( { page => $_[0] } ) . "#comments" };
     my $nav = LJ::paging_bar( $page, $pages, { self_link => $self_link } );
@@ -393,7 +399,7 @@
 
         my $tid = $post->{'talkid'};
         my $dtid = $tid * 256 + $init->{'anum'};
-        my $LJci = $LJ_cmtinfo{$dtid} = { rc => [], u => '', full => $post->{_loaded} };
+        my $LJci = $LJ_cmtinfo{$dtid} = { rc => [], u => '', full => $post->{_loaded}, deleted => ( $post->{state} eq "D" ), screened => ( $post->{state} eq "S" ) };
 
         my $datepost = LJ::S2::sitescheme_secs_to_iso( $post->{datepost_unix}, tz => 1 );
 
@@ -423,7 +429,7 @@
 
         my $hidestyle = $post->{'hidden_child'} ? " style=\"display: none;\"" : "";
         if ($post->{'state'} eq "D") {
-            $ret .= "<div id='$htmlid'><p><a name='$htmlid'></a><table summary='' class='delcomment'$hidestyle><tr>";
+            $ret .= "<div class='comment' id='$htmlid'><p><a name='$htmlid'></a><table summary='' class='delcomment'$hidestyle><tr>";
             $ret .= "<td class='spacer'><img src='$LJ::IMGPREFIX/dot.gif' alt='' height='1' width='" . ($opts->{'depth'} * 25) . "'></td>";
             $ret .= "<td>$ML{'.deletedpost'}</td>";
             if ($post->{'hide_children'} && $post->{'children'} && @{$post->{'children'}}) {
@@ -507,7 +513,7 @@
                     $editreason = "($editreason)" if $editreason;
                 }
 
-                $ret .= "<div id='$htmlid'><table summary='' width='100%' class='talk-comment'><tbody><tr>";
+                $ret .= "<div class='comment' id='$htmlid'><table summary='' width='100%' class='talk-comment'><tbody><tr>";
                 $ret .= "<td rowspan='2' class='spacer'><img src='$LJ::IMGPREFIX/dot.gif' alt='' height='1' width='" . ($opts->{'depth'} * 25) . "'></td>";
                 $ret .= "<td id='cmtbar$dtid' class='cmtbar $level $additional_classes' width='100%'>";
 
@@ -671,9 +677,9 @@
                                 $ret .= BML::ml( 'talk.unhide', { num => $post->{'showable_children'} } );
                                 $ret .= qq[</a>)</span>];
                             }
+                        } else {
+                            $ret .= qq[(<a href='$url' onClick="Expander.make(this,'$url','$dtid',true);return false;">$T{'expand'}</a>)];
                         }
-                    } else {
-                        $ret .= qq[(<a href='$url' onClick="Expander.make(this,'$url','$dtid',true);return false;">$T{'expand'}</a>)];
                     }
                     if ( $show_thread_expander ) {
                         if ( LJ::BetaFeatures->user_in_beta( $remote => "journaljquery" ) ) {
@@ -698,7 +704,7 @@
                 # link to message
 
                 my $url = LJ::Talk::talkargs( $talkurl, "thread=$dtid", $style_args ) . LJ::Talk::comment_anchor( $dtid );
-                $ret .= "<div id='$htmlid'$hidestyle><table summary=''><tbody><tr>";
+                $ret .= "<div class='comment' id='$htmlid'$hidestyle><table summary=''><tbody><tr>";
                 $ret .= "<td class='spacer'><img src='$LJ::IMGPREFIX/dot.gif' alt='' height='1' width='" . ($opts->{'depth'} * 25) . "'></td>";
                 $ret .= "<td  class='cmtpartial'>";
                 if ($post->{'state'} eq 'F') {
@@ -778,6 +784,11 @@
         } elsif ( $view_mode eq "top-only" ) {
             $ret .= "(<a href = '" . BML::self_link( { view => ''  } ) . "#comments'>" . BML::ml('.commentnav.threaded') . "</a>) (<a href = '" . BML::self_link( { view => 'flat'  } ) . "#comments'>" . BML::ml('.commentnav.flat') . "</a>)";
         }
+
+        if ( $u->thread_expand_all( $remote ) && $has_collapsed && $view_mode ne "top-only" ) {
+            my $expand_all_url = $page > 1 ? BML::self_link( { expand_all => '1', page => $page } ) . "#comments" : BML::self_link( { expand_all => '1' } ) . "#comments";
+            $ret .= "<span id='expand_all'> (<a href=\"$expand_all_url\" onClick=\"Expander.make(this,'$expand_all_url',-1,true,false);return false;\">" . $T{expandall} . "</a>)</span>";
+        }
         $ret .= "</b></p>";
 
         $ret .= "<div align='center'>" . LJ::make_qr_target('top') . "</div>" if $remote;
--------------------------------------------------------------------------------
turlough: Gerard Way, Spin photoshoot, 1 October 2010 ((mcr) my eyes are shining bright)

[personal profile] turlough 2011-09-29 09:17 pm (UTC)(link)
:-D
ninetydegrees: Art: self-portrait (Default)

[personal profile] ninetydegrees 2011-10-08 10:27 am (UTC)(link)
Is the reason why this doesn't work on Hacks is because we don't have the thread_expand_all cap in the config file?

Edit: yep, seems that's why. Should that be included then?
Edited 2011-10-08 10:34 (UTC)
ninetydegrees: Text: I came to dance (dance)

[personal profile] ninetydegrees 2011-10-08 01:03 pm (UTC)(link)
Thank *you*