[dw-free] Option to view top level comments only
[commit: http://hg.dwscoalition.org/dw-free/rev/2259a0756378]
http://bugs.dwscoalition.org/show_bug.cgi?id=3298
Allow users to view only top-level comments (along with a link to expand the
thread / view the thread). Also adds a link to view=flat. Also, also adds
the ability to collapse expanded comments.
Patch by
allen.
Files modified:
http://bugs.dwscoalition.org/show_bug.cgi?id=3298
Allow users to view only top-level comments (along with a link to expand the
thread / view the thread). Also adds a link to view=flat. Also, also adds
the ability to collapse expanded comments.
Patch by
Files modified:
- bin/upgrading/en.dat
- bin/upgrading/s2layers/core2.s2
- cgi-bin/LJ/S2.pm
- cgi-bin/LJ/S2/EntryPage.pm
- cgi-bin/LJ/S2Theme.pm
- cgi-bin/LJ/Talk.pm
- htdocs/js/jquery.threadexpander.js
- htdocs/talkread.bml
- htdocs/talkread.bml.text
--------------------------------------------------------------------------------
diff -r fecd2b3c1a0b -r 2259a0756378 bin/upgrading/en.dat
--- a/bin/upgrading/en.dat Fri Sep 09 14:51:13 2011 +0800
+++ b/bin/upgrading/en.dat Fri Sep 09 16:57:23 2011 +0800
@@ -3774,6 +3774,8 @@
talk.frozen=Replies frozen
+talk.hide=Hide [[num]] [[?num|comment|comments]]
+
talk.parentlink=Parent
talk.readsimilar=Read similar journal entries:
@@ -3792,6 +3794,8 @@
talk.threadrootlink=Thread from start
+talk.unhide=Show [[num]] [[?num|comment|comments]]
+
time.ago.day=[[num]] [[?num|day|days]] ago
time.ago.hour=[[num]] [[?num|hour|hours]] ago
diff -r fecd2b3c1a0b -r 2259a0756378 bin/upgrading/s2layers/core2.s2
--- a/bin/upgrading/s2layers/core2.s2 Fri Sep 09 14:51:13 2011 +0800
+++ b/bin/upgrading/s2layers/core2.s2 Fri Sep 09 16:57:23 2011 +0800
@@ -341,6 +341,9 @@
var string[] link_keyseq "An array of keys which you should pass to [method[EntryLite.get_link(string key)]] to produce an entry 'toolbar'. Does not contain nav_next and nav_prev for entries; you should retrieve those separately and put them somewhere appropriate for your layout.";
+ var readonly bool hidden_child "Indicates if the child is hidden by default.";
+ var readonly bool hide_children "Indicates we are hiding the children of this comment";
+
function print_wrapper_start() "Start the wrapper for this entry or comment; includes anchor and classes";
function print_wrapper_end() "End the wrapper for this entry or comment.";
function print_metatypes() "Print the metatype icons for this entry (security, age restriction) or comment (subject icon)";
@@ -448,6 +451,11 @@
function builtin print_expand_link () : string "Prints a link to expand a collapsed comment. Uses the value of the 'text_comment_expand' property as the text.";
function builtin print_expand_link (string{} opts) : string "Prints a link to expand a collapsed comment. Can pass options 'text', 'title', 'class', and 'img_url' (and other 'img_*' options).";
+
+ function builtin print_hide_link () : string "Prints a link to hide a comment thread. Uses the value of the 'text_comment_hide' property as the text.";
+ function builtin print_hide_link (string{} opts) : string "Prints a link to hide a comment. Can pass options 'text', 'title', 'class', and 'img_url' (and other 'img_*' options).";
+ function builtin print_unhide_link () : string "Prints a link to unhide a comment thread. Uses the value of the 'text_comment_unhide' property as the text.";
+ function builtin print_unhide_link (string{} opts) : string "Prints a link to hide a comment. Can pass options 'text', 'title', 'class', and 'img_url' (and other 'img_*' options).";
function print_time (string datefmt, string timefmt, bool edittime) "Same as EntryLite::print_time, except can pass in if we want the edit time or not.";
function time_display (string datefmt, string timefmt, bool edittime) : string "Same as EntryLite::time_display, except can pass in if we want the edit time or not.";
function print_edittime () "Print the time that this comment was edited, with most useful information for user. Empty string if the comment hasn't been edited.";
@@ -474,6 +482,16 @@
function print() "Prints the icon";
}
+class CommentNav
+"Represents the comment navigation bar."
+{
+ 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 bool filter "True if the current view is filtered.";
+
+ function print () "Prints the nav bar, including the comment_pages bar";
+}
+
### Userinfo
@@ -858,6 +876,8 @@
{
var Entry entry "Journal entry being viewed";
var ItemRange comment_pages "Represents what comment page is being displayed.";
+ var CommentNav comment_nav "The comment navigation bar";
+
var Comment[] comments "Comments to journal entry, or at least some of them.";
var bool viewing_thread "True if viewing a specific sub-thread of the comments. Style may which to hide the journal entry at this point, since the focus is the comments.";
@@ -2481,6 +2501,16 @@
example = "Expand";
maxlength = "50";
}
+property string text_comment_hide {
+ des = "Text to hide a comment thread";
+ example = "Hide 1 comment // Hide # comments";
+ maxlength = "50";
+}
+property string text_comment_unhide {
+ des = "Text to unhide a comment thread";
+ example = "Show 1 comment // Show # comments";
+ maxlength = "50";
+}
set text_comment_reply = "Reply";
set text_comment_frozen = "Frozen";
set text_comment_parent = "Parent";
@@ -2488,6 +2518,8 @@
set text_comment_thread = "Thread";
set text_comment_threadroot = "Thread from start";
set text_comment_expand = "Expand";
+set text_comment_hide = "Hide 1 comment // Hide # comments";
+set text_comment_unhide = "Show 1 comment // Show # comments";
##===============================
## Text - icons
@@ -4993,6 +5025,23 @@
$this->print_expand_link();
"""</li>\n""";
}
+ var Link hide_link = $this->get_link("hide_comments");
+ if (defined $hide_link) {
+ var string show_hide = "";
+ if (not $this.hide_children) {
+ $show_hide = " cmt_show_hide_default";
+ }
+ """<li class="link cmt_hide$show_hide" style="display:none;" id="cmt${this.talkid}_hide">""";
+ $this->print_hide_link();
+ """</li>\n""";
+ }
+ var Link unhide_link = $this->get_link("unhide_comments");
+ if (defined $unhide_link) {
+ var string show_hide = "";
+ """<li class="link cmt_unhide$show_hide" style="display: none;" id="cmt${this.talkid}_unhide">""";
+ $this->print_unhide_link();
+ """</li>\n""";
+ }
"""</ul>""";
}
@@ -5731,6 +5780,7 @@
"""<div class='comments-message'>$*text_comments_disabled_maintainer</div>""";
}
if ($.comment_pages.total_subitems > 0) {
+ $.comment_nav->print();
$this->print_multiform_start();
}
$this->print_comments($.comments);
@@ -5753,7 +5803,11 @@
var string parity = $c.depth % 2 ? "odd" : "even";
var int indent = ($c.depth - 1) * 25;
"<div class='comment-thread comment-depth-$parity comment-depth-$c.depth'>\n";
- "<div id='$c.dom_id' style='margin-left: ${indent}px; margin-top: 5px'>\n";
+ "<div id='$c.dom_id' style='margin-left: ${indent}px; margin-top: 5px;";
+ if ($c.hidden_child) {
+ " display: none;";
+ }
+ "'>\n";
if ($c.full) {
$this->print_comment($c);
} else {
@@ -5828,9 +5882,39 @@
function EntryPage::print_comment_partial (Comment c) {
$c->print_wrapper_start();
- if ($c.deleted) { print $*text_deleted; }
- elseif ($c.fromsuspended) { print $*text_fromsuspended; }
- elseif ($c.screened_noshow) { print $*text_screened; }
+ if ($c.deleted) {
+ print $*text_deleted;
+ if ($c.hide_children) {
+ var Link expand_link = $c->get_link("expand_comments");
+ if (defined $expand_link) {
+ print " (";
+ $c->print_expand_link();
+ print ")";
+ }
+ }
+ }
+ elseif ($c.fromsuspended) {
+ print $*text_fromsuspended;
+ if ($c.hide_children) {
+ var Link expand_link = $c->get_link("expand_comments");
+ if (defined $expand_link) {
+ print " (";
+ $c->print_expand_link();
+ print ")";
+ }
+ }
+ }
+ elseif ($c.screened_noshow) {
+ print $*text_screened;
+ if ($c.hide_children) {
+ var Link expand_link = $c->get_link("expand_comments");
+ if (defined $expand_link) {
+ print " (";
+ $c->print_expand_link();
+ print ")";
+ }
+ }
+ }
else {
var string poster = defined $c.poster ? $c.poster->as_string() : "<i>$*text_poster_anonymous</i>";
$c->print_subject();
@@ -5878,6 +5962,29 @@
"</div>";
}
+function CommentNav::print
+{
+ var string sep = $.url->contains( "?" ) ? "&" : "?";
+
+ 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>"""
+ };
+
+ if ( $.view_mode == "threaded" ) {
+ print "$links{"flat"} | $links{"top-only"}";
+ } elseif ( $.view_mode == "flat" ) {
+ print "$links{"threaded"} | $links{"top-only"}";
+ } elseif ( $.view_mode == "top-only" ) {
+ print "$links{"threaded"} | $links{"flat"}";
+ }
+
+ print "</div>";
+}
+
function EntryPage::print_body
{
var Entry e = $.entry;
diff -r fecd2b3c1a0b -r 2259a0756378 cgi-bin/LJ/S2.pm
--- a/cgi-bin/LJ/S2.pm Fri Sep 09 14:51:13 2011 +0800
+++ b/cgi-bin/LJ/S2.pm Fri Sep 09 16:57:23 2011 +0800
@@ -2421,6 +2421,14 @@
return $h;
}
+sub CommentNav
+{
+ my $h = shift;
+ $h->{'_type'} = "CommentNav";
+
+ return $h;
+}
+
sub User
{
my ($u) = @_;
@@ -3368,6 +3376,26 @@
return LJ::S2::Link("#", ## actual link is javascript: onclick='....'
$ctx->[S2::PROPS]->{"text_comment_expand"});
}
+ if ($key eq "hide_comments") {
+ ## show "Hide/Show" link if the comment has any children
+ # only show hide/show comments if using jquery
+ if ( LJ::BetaFeatures->user_in_beta( $remote => "journaljquery" ) && @{ $this->{replies} } > 0 ) {
+ return LJ::S2::Link("#", ## actual link is javascript: onclick='....'
+ $ctx->[S2::PROPS]->{"text_comment_hide"});
+ } else {
+ return $null_link;
+ }
+ }
+ if ($key eq "unhide_comments") {
+ ## show "Hide/Unhide" link if the comment has any children
+ # only show hide/show comments if using jquery
+ if ( LJ::BetaFeatures->user_in_beta( $remote => "journaljquery" ) && @{ $this->{replies} } > 0 ) {
+ return LJ::S2::Link("#", ## actual link is javascript: onclick='....'
+ $ctx->[S2::PROPS]->{"text_comment_unhide"});
+ } else {
+ return $null_link;
+ }
+ }
}
sub Comment__print_multiform_check
@@ -3536,7 +3564,25 @@
my $title = $opts->{title} ? " title='" . LJ::ehtml($opts->{title}) . "'" : "";
my $class = $opts->{class} ? " class='" . LJ::ehtml($opts->{class}) . "'" : "";
- return "<a href='$this->{expand_url}'$title$class onClick=\"Expander.make(this,'$this->{expand_url}','$this->{talkid}'); return false;\">$text</a>";
+ my $onclick = "";
+ # if we're in top-only mode, then we display the expand link as
+ # the unhide ('show x comments') message
+
+ if ( $this->{"hide_children"} ) {
+ my $comment_count = $this->{'showable_children'};
+
+ $text = LJ::ehtml( get_plural_phrase( $ctx, $comment_count, "text_comment_unhide" ) );
+ my $remote = LJ::get_remote();
+
+ # unhide only works with jquery; if the user isn't in the jquery
+ # beta, drop back down to the no-javascript option
+ if ( LJ::BetaFeatures->user_in_beta( $remote => "journaljquery" ) ) {
+ $onclick = " onClick=\"Expander.make(this,'$this->{expand_url}','$this->{talkid}', false, true); return false;\"";
+ }
+ } else {
+ $onclick = " onClick=\"Expander.make(this,'$this->{expand_url}','$this->{talkid}', false); return false;\"";
+ }
+ return"<a href='$this->{expand_url}'$title$class$onclick>$text</a>";
}
sub Comment__print_expand_link
@@ -3544,6 +3590,94 @@
$S2::pout->(Comment__expand_link(@_));
}
+# creates the (javascript) link that hides comments under this comment.
+sub Comment__print_hide_link
+{
+ my ($ctx, $this, $opts) = @_;
+ $opts ||= {};
+
+ my $comment_count = $this->{'showable_children'};
+
+ my $prop_text = LJ::ehtml( get_plural_phrase( $ctx, $comment_count, "text_comment_hide" ) );
+
+ my $text = LJ::ehtml($opts->{text});
+ $text =~ s/&nbsp;/ /gi; # allow in the text
+
+ my $opt_img = LJ::CleanHTML::canonical_url($opts->{img_url});
+
+ # if they want an image change the text link to the image,
+ # and add the text after the image if they specified it as well
+ if ($opt_img) {
+ my $width = $opts->{img_width};
+ my $height = $opts->{img_height};
+ my $border = $opts->{img_border};
+ my $align = LJ::ehtml($opts->{img_align});
+ my $alt = LJ::ehtml($opts->{img_alt}) || $prop_text;
+ my $title = LJ::ehtml($opts->{img_title}) || $prop_text;
+
+ $width = defined $width && $width =~ /^\d+$/ ? " width=\"$width\"" : "";
+ $height = defined $height && $height =~ /^\d+$/ ? " height=\"$height\"" : "";
+ $border = defined $border && $border =~ /^\d+$/ ? " border=\"$border\"" : "";
+
+ $align = $align =~ /^\w+$/ ? " align=\"$align\"" : "";
+ $alt = $alt ? " alt=\"$alt\"" : "";
+ $title = $title ? " title=\"$title\"" : "";
+
+ $text = "<img src=\"$opt_img\"$width$height$border$align$title$alt />$text";
+ } elsif (!$text) {
+ $text = $prop_text;
+ }
+
+ my $title = $opts->{title} ? " title='" . LJ::ehtml($opts->{title}) . "'" : "";
+ my $class = $opts->{class} ? " class='" . LJ::ehtml($opts->{class}) . "'" : "";
+
+ $S2::pout->("<a href='#cmt$this->{talkid}'$title$class onClick=\"Expander.hideComments(this, '$this->{talkid}'); return false;\">$text</a>");
+}
+
+# creates the (javascript) link that unhides comments under this comment.
+sub Comment__print_unhide_link
+{
+ my ($ctx, $this, $opts) = @_;
+ $opts ||= {};
+
+ my $comment_count = $this->{'showable_children'};
+
+ my $prop_text = LJ::ehtml( get_plural_phrase( $ctx, $comment_count, "text_comment_unhide" ) );
+
+ my $text = LJ::ehtml($opts->{text});
+ $text =~ s/&nbsp;/ /gi; # allow in the text
+
+ my $opt_img = LJ::CleanHTML::canonical_url($opts->{img_url});
+
+ # if they want an image change the text link to the image,
+ # and add the text after the image if they specified it as well
+ if ($opt_img) {
+ my $width = $opts->{img_width};
+ my $height = $opts->{img_height};
+ my $border = $opts->{img_border};
+ my $align = LJ::ehtml($opts->{img_align});
+ my $alt = LJ::ehtml($opts->{img_alt}) || $prop_text;
+ my $title = LJ::ehtml($opts->{img_title}) || $prop_text;
+
+ $width = defined $width && $width =~ /^\d+$/ ? " width=\"$width\"" : "";
+ $height = defined $height && $height =~ /^\d+$/ ? " height=\"$height\"" : "";
+ $border = defined $border && $border =~ /^\d+$/ ? " border=\"$border\"" : "";
+
+ $align = $align =~ /^\w+$/ ? " align=\"$align\"" : "";
+ $alt = $alt ? " alt=\"$alt\"" : "";
+ $title = $title ? " title=\"$title\"" : "";
+
+ $text = "<img src=\"$opt_img\"$width$height$border$align$title$alt />$text";
+ } elsif (!$text) {
+ $text = $prop_text;
+ }
+
+ my $title = $opts->{title} ? " title='" . LJ::ehtml($opts->{title}) . "'" : "";
+ my $class = $opts->{class} ? " class='" . LJ::ehtml($opts->{class}) . "'" : "";
+
+ $S2::pout->("<a href='$this->{expand_url}'$title$class onClick=\"Expander.unhideComments(this, '$this->{talkid}'); return false;\">$text</a>");
+}
+
sub Page__print_trusted
{
my ($ctx, $this, $key) = @_;
diff -r fecd2b3c1a0b -r 2259a0756378 cgi-bin/LJ/S2/EntryPage.pm
--- a/cgi-bin/LJ/S2/EntryPage.pm Fri Sep 09 14:51:13 2011 +0800
+++ b/cgi-bin/LJ/S2/EntryPage.pm Fri Sep 09 16:57:23 2011 +0800
@@ -32,8 +32,8 @@
$p->{'_type'} = "EntryPage";
$p->{'view'} = "entry";
$p->{'comment_pages'} = undef;
+ $p->{'comment_navbar'} = undef;
$p->{'comments'} = [];
- $p->{'comment_pages'} = undef;
# setup viewall options
my ($viewall, $viewsome) = (0, 0);
@@ -98,12 +98,14 @@
# add the comments
my $view_arg = $get->{'view'} || "";
my $flat_mode = ($view_arg =~ /\bflat\b/);
+ my $top_only_mode = ($view_arg =~ /\btop-only\b/);
my $view_num = ($view_arg =~ /(\d+)/) ? $1 : undef;
my %userpic;
my %user;
my $copts = {
'flat' => $flat_mode,
+ 'top-only' => $top_only_mode,
'thread' => $get->{thread} ? ( $get->{thread} >> 8 ) : 0,
'page' => $get->{'page'},
'view' => $view_num,
@@ -165,7 +167,7 @@
$edittime_poster = DateTime_tz($comment->edit_time, $pu);
}
- $threadroot_url = $comment->threadroot_url( LJ::viewing_style_args( %$get ) ) if $com->{parenttalkid};
+ $threadroot_url = $comment->threadroot_url( $style_arg ) if $com->{parenttalkid};
}
my $subject_icon = undef;
@@ -248,6 +250,7 @@
'subject' => LJ::ehtml($com->{'subject'}),
'subject_icon' => $subject_icon,
'talkid' => $dtalkid,
+ 'ditemid' => $entry->ditemid,
'text' => $text,
'userpic' => $comment_userpic,
'time' => $datetime,
@@ -276,6 +279,9 @@
'edittime_poster' => $edittime_poster,
'edit_url' => $edit_url,
timeformat24 => $remote && $remote->use_24hour_time,
+ 'showable_children' => $com->{'showable_children'},
+ 'hide_children' => $com->{'hide_children'},
+ 'hidden_child' => $com->{'hidden_child'},
};
# don't show info from suspended users
@@ -409,6 +415,13 @@
$copts->{'out_itemfirst'} = $copts->{'out_itemlast'} = undef;
}
+ # 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'},
+ });
+
$p->{'comment_pages'} = ItemRange({
'all_subitems_displayed' => ($copts->{'out_pages'} == 1),
'current' => $copts->{'out_page'},
@@ -418,7 +431,7 @@
'total' => $copts->{'out_pages'},
'total_subitems' => $copts->{'out_items'},
'_url_of' => sub {
- my $sty = $flat_mode ? "view=flat&" : "";
+ my $sty = $flat_mode ? "view=flat&" : $top_only_mode ? "view=top-only&" : "";
return "$permalink?${sty}page=" . int($_[0]) .
($style_arg ? "&$style_arg" : '');
},
diff -r fecd2b3c1a0b -r 2259a0756378 cgi-bin/LJ/S2Theme.pm
--- a/cgi-bin/LJ/S2Theme.pm Fri Sep 09 14:51:13 2011 +0800
+++ b/cgi-bin/LJ/S2Theme.pm Fri Sep 09 16:57:23 2011 +0800
@@ -1012,11 +1012,13 @@
text_comment_expand
text_comment_from
text_comment_frozen
+ text_comment_hide
text_comment_ipaddr
text_comment_parent
text_comment_posted
text_comment_reply
text_comment_thread
+ text_comment_unhide
color_comment_title
color_comment_title_background
font_comment_title
diff -r fecd2b3c1a0b -r 2259a0756378 cgi-bin/LJ/Talk.pm
--- a/cgi-bin/LJ/Talk.pm Fri Sep 09 14:51:13 2011 +0800
+++ b/cgi-bin/LJ/Talk.pm Fri Sep 09 16:57:23 2011 +0800
@@ -920,6 +920,7 @@
# userpicref -- hashref to load userpics into, or undef to
# not load them.
# userref -- hashref to load users into, keyed by userid
+# top-only -- boolean; if set, only load the top-level comments
#
# returns:
# array of hashrefs containing keys:
@@ -940,6 +941,9 @@
# - _loaded => 1 (if fully loaded, subject & body)
# unknown items will never be _loaded
# - _show => {0|1}, if item is to be ideally shown (0 if deleted, screened, or filtered)
+# - showable_children - count of showable children for this comment
+# - hidden_child => {0|1}, if this comment is hidden by default
+# - hide_children => {0|1}, if this comment has its children hidden
# - echi (explicit comment hierarchy indicator)
sub load_comments
{
@@ -1035,6 +1039,11 @@
if ($sum) {
$showable_children{$post->{'parenttalkid'}} += $sum;
unshift @{$children{$post->{'parenttalkid'}}}, $post->{'talkid'};
+ # record the # of showable children for each comment (though
+ # not for the post itself (0))
+ if ( $post->{parenttalkid} ) {
+ $posts->{$post->{parenttalkid}}->{'showable_children'} = $showable_children{$post->{'parenttalkid'}};
+ }
}
}
@@ -1151,7 +1160,13 @@
## expand first reply to top-level comments
## %expand_children - list of comments, children of which are to expand
- my %expand_children = map { $_ => 1 } @top_replies;
+ my %expand_children;
+ unless ( $opts->{'top-only'} ) {
+ ## expand first reply to top-level comments
+ ## %expand_children - list of comments, children of which are to expand
+ %expand_children = map { $_ => 1 } @top_replies;
+ }
+
my (@subjects_to_load, @subjects_ignored);
while (@check_for_children) {
@@ -1159,14 +1174,14 @@
next unless defined $children{$cfc};
foreach my $child (@{$children{$cfc}}) {
- if (@posts_to_load < $page_size || $expand_children{$cfc} || $opts->{expand_all}) {
+ if ( ! $opts->{'top-only'} && ( @posts_to_load < $page_size || $expand_children{$cfc} || $opts->{expand_all} ) ) {
push @posts_to_load, $child;
## expand only the first child, then clear the flag
delete $expand_children{$cfc};
- }
- elsif (@posts_to_load < $page_size) {
- push @posts_to_load, $child;
} else {
+ if ( $opts->{'top-only'} ) {
+ $posts->{$child}->{'hidden_child'} = 1;
+ }
if (@subjects_to_load < $max_subjects) {
push @subjects_to_load, $child;
} else {
@@ -1189,11 +1204,17 @@
$posts_loaded = LJ::get_talktext2($u, @posts_to_load);
$subjects_loaded = LJ::get_talktext2($u, {'onlysubjects'=>1}, @subjects_to_load) if @subjects_to_load;
foreach my $talkid (@posts_to_load) {
+ if ( $opts->{'top-only'} ) {
+ $posts->{$talkid}->{'hide_children'} = 1;
+ }
next unless $posts->{$talkid}->{'_show'};
$posts->{$talkid}->{'_loaded'} = 1;
$posts->{$talkid}->{'subject'} = $posts_loaded->{$talkid}->[0];
$posts->{$talkid}->{'body'} = $posts_loaded->{$talkid}->[1];
$users_to_load{$posts->{$talkid}->{'posterid'}} = 1;
+ if ( $opts->{'top-only'} ) {
+ $posts->{$talkid}->{'hide_children'} = 1;
+ }
}
foreach my $talkid (@subjects_to_load) {
next unless $posts->{$talkid}->{'_show'};
diff -r fecd2b3c1a0b -r 2259a0756378 htdocs/js/jquery.threadexpander.js
--- a/htdocs/js/jquery.threadexpander.js Fri Sep 09 14:51:13 2011 +0800
+++ b/htdocs/js/jquery.threadexpander.js Fri Sep 09 16:57:23 2011 +0800
@@ -1,3 +1,8 @@
+/*
+ * This handles the thread expansion for comments. It also handles
+ * the show/hide functionality for comments.
+ */
+
(function($) {
// makes the given comment element displayed fully.
function setFull(commentElement, full) {
@@ -11,12 +16,15 @@
return $("td.spacer img", element);
}
- // Returns the given talkid, plus the talkids of all comments that are
- // replies to this talkid.
- function getReplies(LJ, talkid) {
- var returnValue = [ talkid ];
+ // Returns the talkids of all comments that are replies to this talkid,
+ // plus the given talkid if includeSelf is called.
+ function getReplies(LJ, talkid, includeSelf) {
+ var returnValue = [];
+ if (includeSelf) {
+ returnValue.push(talkid);
+ }
for (var i = 0; i < LJ[talkid].rc.length; i++) {
- returnValue = returnValue.concat(getReplies(LJ, LJ[talkid].rc[i]));
+ returnValue = returnValue.concat(getReplies(LJ, LJ[talkid].rc[i], true));
}
return returnValue;
}
@@ -27,7 +35,7 @@
}
// ajax expands the comments for the given talkid
- $.fn.expandComments = function(LJ, expand_url, talkid, isS1) {
+ $.fn.expandComments = function(LJ, expand_url, talkid, isS1, unhide) {
element = this;
// if we've already been clicked, just return.
if (element.hasClass("disabled")) {
@@ -47,22 +55,22 @@
datatype: "html",
timeout: 30000,
success: function(data) {
- doJqExpand(LJ, data, talkid, isS1);
- },
+ element.doJqExpand(LJ, data, talkid, isS1, unhide);
+ },
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);
+ }
} );
};
// callback to handle comment expansion
- function doJqExpand(LJ, data, talkid, isS1) {
+ $.fn.doJqExpand = function(LJ, data, talkid, isS1, unhide) {
var updateCount = 0;
// check for matching expansions on the page
- var replies = getReplies(LJ, talkid);
+ 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
@@ -73,11 +81,12 @@
var newComment = $("#cmt" + cmtId, data);
if (newComment && newComment.attr('id') == 'cmt' + cmtId) {
if (isS1) {
- var oldWidth = getS1SpacerObject(cmtElement).width();
- getS1SpacerObject(newComment).width(oldWidth);
- }
+ var oldWidth = getS1SpacerObject(cmtElement).width();
+ getS1SpacerObject(newComment).width(oldWidth);
+ }
cmtElement.html($(newComment).html())
.trigger( "updatedcontent.comment" );
+ $(".cmt_show_hide_default", cmtElement).show();
LJ[cmtId].full = true;
if (! isS1) {
setFull(cmtElement, true);
@@ -91,9 +100,67 @@
// 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);
}
}
+ // returns the comment elements for the given talkids.
+ function getReplyElements(replies) {
+ var returnValue = [];
+ for (var cmtIdCnt = 0; cmtIdCnt < replies.length; cmtIdCnt++) {
+ var cmtId = replies[cmtIdCnt];
+ if (/^\d*$/.test(cmtId)) {
+ var cmtElement = $("#cmt" + cmtId);
+ returnValue.push(cmtElement);
+ }
+ }
+ return returnValue;
+ }
+
+ // hides all the comments under this comment.
+ $.fn.hideComments = function(LJ, talkid, isS1) {
+ var replies = getReplies(LJ, talkid, false);
+ var replyElements = getReplyElements(replies);
+ for (var i = 0; i < replyElements.length; i++) {
+ if (isS1) {
+ replyElements[i].hide();
+ } else {
+ replyElements[i].slideUp("fast");
+ }
+ }
+
+ $("#cmt" + talkid + "_hide").hide();
+ $("#cmt" + talkid + "_unhide").show();
+ }
+
+ // shows all the comments under this comment.
+ $.fn.unhideComments = function(LJ, talkid, isS1) {
+ var replies = getReplies(LJ, talkid, false);
+ var replyElements = getReplyElements(replies);
+ for (var i = 0; i < replyElements.length; i++) {
+ // we're revealing the entire tree, so the subcomments should
+ // all show the hide option, not the unhide option.
+ $(".cmt_hide", replyElements[i]).show();
+ $(".cmt_unhide", replyElements[i]).hide();
+ if (isS1) {
+ replyElements[i].show();
+ } else {
+ replyElements[i].slideDown("fast");
+ }
+ }
+
+ // and this comment itself should show hide.
+ $("#cmt" + talkid + "_hide").show();
+ $("#cmt" + talkid + "_unhide").hide();
+ }
+
+ // reveal all hide links on document ready, so we don't have them if
+ // we don't have javascript enabled.
+ $(document).ready(function() {
+ $(".cmt_show_hide_default").show();
+ });
+
$.threadexpander = {
config: {
text: {
@@ -102,10 +169,20 @@
}
}
};
+
})(jQuery);
+// globals for backwards compatibility
Expander = {
- make: function(element, url, dtid, isS1) {
- $(element).expandComments(LJ_cmtinfo, url, dtid, isS1);
+ make: function(element, url, dtid, isS1, unhide) {
+ $(element).expandComments(LJ_cmtinfo, url, dtid, isS1, unhide);
+ },
+
+ hideComments: function(element, dtid, isS1) {
+ $(element).hideComments(LJ_cmtinfo, dtid, isS1);
+ },
+
+ unhideComments: function(element, dtid, isS1) {
+ $(element).unhideComments(LJ_cmtinfo, dtid, isS1);
}
};
diff -r fecd2b3c1a0b -r 2259a0756378 htdocs/talkread.bml
--- a/htdocs/talkread.bml Fri Sep 09 14:51:13 2011 +0800
+++ b/htdocs/talkread.bml Fri Sep 09 16:57:23 2011 +0800
@@ -70,6 +70,8 @@
link talk.commentpermlink
deleted .subjectdeleted
nosubject .nosubject
+ hide talk.hide
+ unhide talk.unhide
maxcomments .maxcomments
);
foreach (keys %T) { $T{$_} = $ML{$T{$_}}; }
@@ -343,11 +345,13 @@
my $view_arg = $GET{'view'} || "";
my $flat_mode = ($view_arg =~ /\bflat\b/);
+ my $top_only = ($view_arg =~ /\btop-only\b/);
my $view_num = ($view_arg =~ /(\d+)/) ? $1 : undef;
my %user;
my $opts = {
'flat' => $flat_mode,
+ 'top-only' => $top_only,
'thread' => $thread,
'page' => $GET{'page'},
'view' => $view_num,
@@ -416,17 +420,64 @@
my $htmlid = LJ::Talk::comment_htmlid( $dtid );
+ my $hidestyle = $post->{'hidden_child'} ? " style=\"display: none;\"" : "";
if ($post->{'state'} eq "D") {
- $ret .= "<p><a name='$htmlid'></a><table summary='' class='delcomment'><tr>";
+ $ret .= "<div 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></tr></table>\n";
+ $ret .= "<td>$ML{'.deletedpost'}</td>";
+ if ($post->{'hide_children'} && $post->{'children'} && @{$post->{'children'}}) {
+ if ( grep {! $_->{_loaded} and !($_->{state} eq "D")} @{$post->{'children'}} ) {
+ my $url = LJ::Talk::talkargs( $talkurl, "thread=$dtid", $style_args ) . LJ::Talk::comment_anchor( $dtid );
+ $ret .= "<td>";
+ # if we're in top-only mode, then we display the
+ # expand link as the unhide ('show x comments')
+ # message
+ if ( LJ::BetaFeatures->user_in_beta( $remote => "journaljquery" ) ) {
+ $ret .= qq[(<a href='$url' onClick="Expander.make(this,'$url','$dtid',true,true);return false;">];
+ $ret .= BML::ml( 'talk.unhide', { num => $post->{'showable_children'} } );
+ $ret .= qq[</a>)</span>];
+ } else {
+ # unhide only works with jquery; if the user
+ # isn't in the jquery beta, drop back down to
+ # the no-javascript option
+ $ret .= qq[(<a href='$url'>];
+ $ret .= BML::ml( 'talk.unhide', { num => $post->{'showable_children'} } );
+ $ret .= qq[</a>)</span>];
+ }
+ $ret .= "</td>";
+ }
+ }
+ $ret .= "</tr></table></div>\n";
} elsif ($post->{'state'} eq "S" && !$post->{'_loaded'} && !$post->{'_show'}) {
- $ret .= "<p><a name='$htmlid'></a><table summary='' class='screenedcomment'><tr>";
+ $ret .= "<p><a name='$htmlid'></a><table summary='' class='screenedcomment'$hidestyle><tr>";
$ret .= "<td class='spacer'><img src='$LJ::IMGPREFIX/dot.gif' alt='' height='1' width='" . ($opts->{'depth'} * 25) . "'></td>";
my $screenedtext = $ML{'.screenedpost'};
- $ret .= "<td>$screenedtext</td></tr></table>\n";
+ $ret .= "<td>$screenedtext</td>";
+ if ($post->{'hide_children'} && $post->{'children'} && @{$post->{'children'}}) {
+ if ( grep {! $_->{_loaded} and !($_->{state} eq "D")} @{$post->{'children'}} ) {
+ my $url = LJ::Talk::talkargs( $talkurl, "thread=$dtid", $style_args ) . LJ::Talk::comment_anchor( $dtid );
+ $ret .= "<td>";
+ # if we're in top-only mode, then we display the
+ # expand link as the unhide ('show x comments')
+ # message
+ if ( LJ::BetaFeatures->user_in_beta( $remote => "journaljquery" ) ) {
+ $ret .= qq[(<a href='$url' onClick="Expander.make(this,'$url','$dtid',true,true);return false;">];
+ $ret .= BML::ml( 'talk.unhide', { num => $post->{'showable_children'} } );
+ $ret .= qq[</a>)</span>];
+ } else {
+ # unhide only works with jquery; if the user
+ # isn't in the jquery beta, drop back down to
+ # the no-javascript option
+ $ret .= qq[(<a href='$url'>];
+ $ret .= BML::ml( 'talk.unhide', { num => $post->{'showable_children'} } );
+ $ret .= qq[</a>)</span>];
+ }
+ $ret .= "</td>";
+ }
+ }
+ $ret .= "</tr></table>\n";
} elsif ($pu && $pu->is_suspended && !$viewsome) {
- $ret .= "<p><a name='$htmlid'></a><table summary='' class='suspendedcomment'><tr>";
+ $ret .= "<p><a name='$htmlid'></a><table summary='' class='suspendedcomment'$hidestyle><tr>";
$ret .= "<td class='spacer'><img src='$LJ::IMGPREFIX/dot.gif' alt='' height='1' width='" . ($opts->{'depth'} * 25) . "'></td>";
$ret .= "<td>$ML{'.replysuspended'}";
if (LJ::Talk::can_delete($remote, $u, $up, $userpost)) {
@@ -603,8 +654,38 @@
$ret .= "(<a href='$url'>$T{'thread'}</a>) ";
if ((grep {! $_->{_loaded} and !($_->{state} eq "D")} @{$post->{'children'}}) && $show_thread_expander) {
- $ret .= qq[(<a href='$url' onClick="Expander.make(this,'$url','$dtid',true);return false;">$T{'expand'}</a>)];
- }
+ if ( $post->{'hide_children'} ) {
+ # if we're in top-only mode, then we display the
+ # expand link as the unhide ('show x comments')
+ # message
+ if ( LJ::BetaFeatures->user_in_beta( $remote => "journaljquery" ) ) {
+ $ret .= qq[(<a href='$url' onClick="Expander.make(this,'$url','$dtid',true,true);return false;">];
+ $ret .= BML::ml( 'talk.unhide', { num => $post->{'showable_children'} } );
+ $ret .= qq[</a>)</span>];
+ } else {
+ # unhide only works with jquery; if the user
+ # isn't in the jquery beta, drop back down to
+ # the no-javascript option
+ $ret .= qq[(<a href='$url'>];
+ $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>)];
+ }
+ if ( $show_thread_expander ) {
+ if ( LJ::BetaFeatures->user_in_beta( $remote => "journaljquery" ) ) {
+ my $hideclass = $post->{'hide_children'} ? "" : " cmt_show_hide_default";
+
+ $ret .= qq[ <span id="cmt${dtid}_hide" class="cmt_hide$hideclass" style="display:none;">(<a href='#' onClick="Expander.hideComments(this,'$dtid',true);return false;">];
+ $ret .= BML::ml( 'talk.hide', { num => $post->{'showable_children'} } );
+ $ret .= qq[</a>)</span>];
+ $ret .= qq[ <span id="cmt${dtid}_unhide" style="display: none;" class="cmt_unhide">(<a href='#' onClick="Expander.unhideComments(this,'$dtid',true);return false;">];
+ $ret .= BML::ml( 'talk.unhide', { num => $post->{'showable_children'} } );
+ $ret .= qq[</a>)</span>];
+ }
+ }
}
$ret .= "</font></p><br />";
@@ -616,7 +697,7 @@
# link to message
my $url = LJ::Talk::talkargs( $talkurl, "thread=$dtid", $style_args ) . LJ::Talk::comment_anchor( $dtid );
- $ret .= "<div id='$htmlid'><table summary=''><tbody><tr>";
+ $ret .= "<div 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') {
@@ -684,6 +765,18 @@
}
}
+ $ret .= "<br>\n";
+
+ # comment nav
+ my $view_mode = $flat_mode ? "flat" : $top_only ? "top-only" : "threaded";
+
+ if ( $view_mode eq "threaded" ) {
+ $ret .= "(<a href = '" . BML::self_link( { view => 'flat' } ) . "#comments'>" . BML::ml('.commentnav.flat') . "</a>) (<a href = '" . BML::self_link( { view => 'top-only' } ) . "#comments'>" . BML::ml('.commentnav.toponly') . "</a>)";
+ } elsif ( $view_mode eq "flat" ) {
+ $ret .= "(<a href = '" . BML::self_link( { view => '' } ) . "#comments'>" . BML::ml('.commentnav.threaded') . "</a>) (<a href = '" . BML::self_link( { view => 'top-only' } ) . "#comments'>" . BML::ml('.commentnav.toponly') . "</a>)";
+ } 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>)";
+ }
$ret .= "</b></p>";
$ret .= "<div align='center'>" . LJ::make_qr_target('top') . "</div>" if $remote;
diff -r fecd2b3c1a0b -r 2259a0756378 htdocs/talkread.bml.text
--- a/htdocs/talkread.bml.text Fri Sep 09 14:51:13 2011 +0800
+++ b/htdocs/talkread.bml.text Fri Sep 09 16:57:23 2011 +0800
@@ -7,6 +7,12 @@
.comment.screened.subject=(screened)
+.commentnav.flat=Flat
+
+.commentnav.threaded=Threaded
+
+.commentnav.toponly=Top-level comments only
+
.confirm.action=Are you sure you want to delete the selected comments?
.deletedpost=<b>(Deleted post)</b>
--------------------------------------------------------------------------------

no subject
no subject
no subject