Hi !
I wonder how to put all the comments and the "add a comment" link in a collapsible fieldset ?
Could you tell me in wich file do I have to specify that please ?

Thank you .

Matt

Comments

ufku’s picture

i think it's only possible with javascript. try adding this code into your theme's page file just before the closing </body> tag

<script type="text/javascript">
if (cTop = document.getElementById("comment")) {
  var cFieldset = document.createElement("FIELDSET");
  var cLegend = document.createElement("LEGEND");
  cFieldset.appendChild(cLegend);
  var cParent = cTop.parentNode;
  var cNext = cTop.nextSibling;
  cFieldset.appendChild(cTop);
  var cCount = 0;
  while (cNext) {
    if (cNext.tagName=="DIV") cCount++;
    cCopy = cNext;
    cNext = cNext.nextSibling;
    cFieldset.appendChild(cCopy);
  }
  cFieldset.className = "collapsible" + ((location.href.indexOf('#comment')==-1) ? " collapsed" : "");
  cLegend.innerHTML = "<?php print t('Comments') ?> ("+cCount+")";
  cParent.appendChild(cFieldset);
  if ("function" != typeof(window.isJsEnabled)) {
    document.write("<script type=\"text/javascript\" src=\"<?php print $base_path ?>misc/drupal.js\"><\/script>");
  }
  if ("function" != typeof(window.collapseAutoAttach)) {
    document.write("<script type=\"text/javascript\" src=\"<?php print $base_path ?>misc/collapse.js\"><\/script>");
  }
}
</script>

--
Geneticists from METU

justin3’s picture

thanks ufku!

this should be part of the core... its a very worthwhile option.

i was actually looking for a variation of this. trying to figure out how to add an admin button to every comment, so a moderator could set troll comments to collapsed- so they're not completely deleted, but just minimized so as not to clutter up the discussion. then users could click to a javascript link to unfold the comments as needed.

NicolasH’s picture

Similar to the Digg approach of hiding "dugg down" comments below a chosen threshold minus the democracy. But it might be more appropriate for a smaller site...

SomebodySysop’s picture

I tried putting this code into the page.tpl.php of a 5.1 site but it doesn't work. Any suggestions?

JohnG-1’s picture

... but rather than but the whole thread into one collapsible fieldset, I would like to make each comment collapsible ... so initially the comments appear like threaded list - collapsed, but each one can be 'opened' individually in context (not on a new page).

Any pointers welcome.

turin’s picture

It works perfectly.

You just have to change the second line from

if (cTop = document.getElementById("comment")) {

to

if (cTop = document.getElementById("comments")) {

As the CSS id of the comments DIV is now "comments". And it works just fine :)

gbowman’s picture

By changing comment to comments (as above) this works for me, however the number in brackets does not count correctly, it just shows (0).

I tried using $count = comment_num_all($node->nid);print $count (from http://drupal.org/node/347726) which works on the single story page, but not for a page with multiple stories. I presume it doesn't know what nid it should be counting??

Any ideas?

Many Thanks
Graham

ufku’s picture

Add the below code to your theme's script.js(create if not exists or somehow insert this code into your pages)

$(document).ready(function() {
  var $comments = $('#comments');
  if (!$comments.size()) return;
  var count = $comments.find('.comment').size();
  var label = Drupal.formatPlural(count, '1 comment', '@count comments');
  var $legend = $(document.createElement('legend')).html(label);
  var fsetclass = 'comments collapsible' + (location.href.search(/#(comment|new)/) == -1 ? ' collapsed' : '');
  var $fset = $(document.createElement('fieldset')).addClass(fsetclass);
  $fset.insertBefore($comments).append($legend).append($comments);
  Drupal.behaviors.collapse($fset.parent());
});
gbowman’s picture

Thanks for your suggested script, this time it counts the comments correctly but doesn't show the comments when clicked, just appears as text with the lines either side as though it should be a collaspible fieldset.

IE is reporting Webpage error details

Message: Object doesn't support this property or method
Line: 670
Char: 3
Code: 0

Which refers to Drupal.behaviors.collapse($fset.parent());

Maybe the answer lies somewhere inbetween the two. Unfortunately I can't work out exactly what each one is doing to figure it out :(

gbowman’s picture

I've suprised myself and managed to get a combination of the 2 to work. Here's what I ended up with

<script type="text/javascript">
if (cTop = document.getElementById("comments")) {
  var $comments = $('#comments');
  var count = $comments.find('.comment').size();
  var cFieldset = document.createElement("FIELDSET");
  var cLegend = document.createElement("LEGEND");
  cFieldset.appendChild(cLegend);
  var cParent = cTop.parentNode;
  var cNext = cTop.nextSibling;
  cFieldset.appendChild(cTop);
  cFieldset.className = "collapsible" + ((location.href.indexOf('#comment')==-1) ? " collapsed" : "");
  cLegend.innerHTML = "<?php print t('Comments') ?> ("+count+")";
  cParent.appendChild(cFieldset);
  if ("function" != typeof(window.isJsEnabled)) {
    document.write("<script type=\"text/javascript\" src=\"<?php print $base_path ?>misc/drupal.js\"><\/script>");
  }
  if ("function" != typeof(window.collapseAutoAttach)) {
    document.write("<script type=\"text/javascript\" src=\"<?php print $base_path ?>misc/collapse.js\"><\/script>");
  }
}
</script>

This is probably not the most efficient way of doing this but it works on my install!

ufku’s picture

It requires misc/collapse.js to be included in the page.
You may add it using drupal_add_js('misc/collapse.js'); in your node.tpl.php

gbowman’s picture

Ahh that did it! Much appreciated!

tamasco’s picture

This solution works perfectly. But I need to make individual comments collapsible. Is there a way to do this or modify the solution provided here to that effect?

Many thanks!
Tamasco

garryi’s picture

Similarity, is there a way of showing 2 or 3 comments while all other comments are collapsed? And when clicking on 'expand' all other comments show. Can this be done?

tamasco’s picture

Subscribing...

areynolds’s picture

You should be able to figure out how to apply your collapse technique to every div with the class ".comment" by iterating through with .each(). Although I haven't done this, I did use code from this thread to collapse multiple #comments sections (I have a Q/A view that displays a question node with attached answer nodes; all of them can have #comments divs and I wanted to collapse all of them):

$(document).ready(function() {
  $( 'div[id^=comments]' ).each(function(index, comments) {
  	var $comments = $( comments );
  	if ($comments.length == 0) return;
  	var count = $comments.find('.comment').size();
  	var label = Drupal.formatPlural(count, '1 comment', '@count comments');
  	var $legend = $(document.createElement('legend')).html(label);
  	var fsetclass = 'comments collapsible' + (location.href.search(/#(comment|new)/) == -1 ? ' collapsed' : '');
  	var $fset = $(document.createElement('fieldset')).addClass(fsetclass);
  	$fset.insertBefore($comments).append($legend).append($comments);
  	Drupal.behaviors.collapse($fset.parent());
  });	
});

If you see anything wrong with this technique, please tell me. I haven't done browser testing yet, so I'll probably get boned by IE and have to revise using the other code.

--Alec

Tandem

alvinlb’s picture

I just started looking for this functionality yesterday.

The solution posted by Ufku (many thanks Ufku!) works great. The only problem I'm having is that the comments
are collapsed, but the comment form is expanded. When the user clicks to show comments, another comment form expands, so two comment forms show. I'm probably doing something wrong! Can anyone help?

In case I haven't explained myself very well, you can see what I mean here..

http://www.athenacontemporaryart.com/drupal/aroomwithaview

Thanks :-)

gawi’s picture

What is the solution for Drupal 7 ?

TIA

ufku’s picture

Put this code in your script.js

(function($) {$(function() {
  var $comments = $('#comments');
  if (!$comments.size()) return;
  var count = $comments.find('.comment').size();
  // if (!count) return; // Do nothing when there is no comment.
  var label = Drupal.formatPlural(count, '1 comment', '@count comments');
  var $legend = $(document.createElement('legend')).html('<span class="fieldset-legend">' + label + '</span>');
  var fsetclass = 'comments collapsible' + (location.href.search(/#(comment|new)/) == -1 ? ' collapsed' : '');
  var $fset = $(document.createElement('fieldset')).addClass(fsetclass);
  var $fsetwrap = $(document.createElement('div')).addClass('fieldset-wrapper');
  $fset.insertBefore($comments).append($legend).append($fsetwrap);
  $fsetwrap.append($comments);
  var attach = function() {Drupal.behaviors.collapse.attach($fset.parent(), Drupal.settings);};
  Drupal.behaviors.collapse ? attach() : $.getScript(Drupal.settings.basePath + 'misc/collapse.js', attach);
});})(jQuery);

Note that, yourtheme/script.js is no longer automatically loaded in d7. You need to manually add it to theme's info file.

scripts[] = script.js
gawi’s picture

Oh my God! It works!

Thanks ufku, You're the best!

bollerfant’s picture

Thank you!

bollerfant’s picture

Hi,
when using that script, everything is fine until i log out. when i'm NOT logged in, i cannot expand the comments. do someone have a solution for this with this script here or another solution in form of a script/module ?

earwax’s picture

When I am logged in, I cannot expand the comments. Using Drupal 7

marriswetha’s picture

I have kept the above code in my theme/script.js . still is not not working.

earwax’s picture

You need to manually add it to theme's info file.

scripts[] = script.js
Anonymous’s picture

it works for me but what would be the code for displaying all comments on pageload and just the "post new comment" area collapsed?

regards

glesage’s picture

Hi,

I'd like to know if this still applies for latest D7 version (7.x-3.x?). I tried it and it only collapse some comments, but I am unable to expand them...?
Could anybody post the content on collapse.js just for me to check?

Thanks for the help.

earwax’s picture

(function ($) {

/**
 * Toggle the visibility of a fieldset using smooth animations.
 */
Drupal.toggleFieldset = function (fieldset) {
  var $fieldset = $(fieldset);
  if ($fieldset.is('.collapsed')) {
    var $content = $('> .fieldset-wrapper', fieldset).hide();
    $fieldset
      .removeClass('collapsed')
      .trigger({ type: 'collapsed', value: false })
      .find('> legend span.fieldset-legend-prefix').html(Drupal.t('Hide'));
    $content.slideDown({
      duration: 'fast',
      easing: 'linear',
      complete: function () {
        Drupal.collapseScrollIntoView(fieldset);
        fieldset.animating = false;
      },
      step: function () {
        // Scroll the fieldset into view.
        Drupal.collapseScrollIntoView(fieldset);
      }
    });
  }
  else {
    $fieldset.trigger({ type: 'collapsed', value: true });
    $('> .fieldset-wrapper', fieldset).slideUp('fast', function () {
      $fieldset
        .addClass('collapsed')
        .find('> legend span.fieldset-legend-prefix').html(Drupal.t('Show'));
      fieldset.animating = false;
    });
  }
};

/**
 * Scroll a given fieldset into view as much as possible.
 */
Drupal.collapseScrollIntoView = function (node) {
  var h = document.documentElement.clientHeight || document.body.clientHeight || 0;
  var offset = document.documentElement.scrollTop || document.body.scrollTop || 0;
  var posY = $(node).offset().top;
  var fudge = 55;
  if (posY + node.offsetHeight + fudge > h + offset) {
    if (node.offsetHeight > h) {
      window.scrollTo(0, posY);
    }
    else {
      window.scrollTo(0, posY + node.offsetHeight - h + fudge);
    }
  }
};
/**
 * Scroll a given fieldset into view as much as possible.
 */
Drupal.collapseScrollIntoView = function (node) {
  var h = document.documentElement.clientHeight || document.body.clientHeight || 0;
  var offset = document.documentElement.scrollTop || document.body.scrollTop || 0;
  var posY = $(node).offset().top;
  var fudge = 55;
  if (posY + node.offsetHeight + fudge > h + offset) {
    if (node.offsetHeight > h) {
      window.scrollTo(0, posY);
    }
    else {
      window.scrollTo(0, posY + node.offsetHeight - h + fudge);
    }
  }
};

Drupal.behaviors.collapse = {
  attach: function (context, settings) {
    $('fieldset.collapsible', context).once('collapse', function () {
      var $fieldset = $(this);
      // Expand fieldset if there are errors inside, or if it contains an
      // element that is targeted by the uri fragment identifier.
      var anchor = location.hash && location.hash != '#' ? ', ' + location.hash : '';
      if ($('.error' + anchor, $fieldset).length) {
        $fieldset.removeClass('collapsed');
      }

      var summary = $('<span class="summary"></span>');
      $fieldset.
        bind('summaryUpdated', function () {
          var text = $.trim($fieldset.drupalGetSummary());
          summary.html(text ? ' (' + text + ')' : '');
        })
        .trigger('summaryUpdated');

      // Turn the legend into a clickable link, but retain span.fieldset-legend
      // for CSS positioning.
      var $legend = $('> legend .fieldset-legend', this);

      $('<span class="fieldset-legend-prefix element-invisible"></span>')
        .append($fieldset.hasClass('collapsed') ? Drupal.t('Show') : Drupal.t('Hide'))
        .prependTo($legend)
        .after(' ');

      // .wrapInner() does not retain bound events.
      var $link = $('<a class="fieldset-title" href="#"></a>')
        .prepend($legend.contents())
        .appendTo($legend)
        .click(function () {
          var fieldset = $fieldset.get(0);
          // Don't animate multiple times.
          if (!fieldset.animating) {
            fieldset.animating = true;
            Drupal.toggleFieldset(fieldset);
          }
          return false;
        });

      $legend.append(summary);
    });
  }
};

})(jQuery);

Good luck. We are all counting on you!

cesar.brod@gmail.com’s picture

I have tried all of these approaches on this thread on D7 and none of them worked. I also have looked for this functionality in a module but I am not able to find it.

earwax’s picture

I gave up on this happening in the drupal way. I think the only way I am going to fix this problem is to go into my theme file and hack it up pure PHP/javascript/HTML style.

Anonymous’s picture

Lios’s picture

Not working correctly for me. It does collapse the comments, but there's no way to open them :( I'm using drupal 7.10.

leramulina’s picture

I tried this script. And collapsing group appeares, but comments are outside of it. Just exactly after collapsed group.

I use Aquia Prosper theme.

leramulina’s picture

Thank you for this code.

But I have an issue. I've got comments on my pages and also field comments. I mean there are attached photos to fields. And all the photos can be commented.

So, when I use your script I can make comments to the node collapsible. But comments to fields made with module collapsible_comments are not.

How to collapse both types of comments?

leramulina’s picture

Can you tell me please, how to make this collapsible group closed by default?

Thank you!

carlbowles100’s picture

Hi,

Great bit of code, thank you

I've got it working perfect for logged in users, but for anon users, it simply won't expand and when clicked, nothing happens

Could you tell me how to fix this please?

carlbowles100’s picture

Anyone still trying to make comments collapsible, here's how I've done it...

Use the Comments block module to make the comments available as a block

Then installed the Collapsiblock module to make that block collapsible

Easy!

lk7889’s picture

If all you want to do is make your comments area div collapsible in Drupal 7, I found this article to be a lot of help:
http://timonweb.com/painless-collapsible-divs-drupal

With that article's help, I added the following to my node.tpl.php:

$collapsed_content = render($content['comments']);
print theme('ctools_collapsible', array('handle' => 'Click here to view/add comments', 'content' => $collapsed_content, 'collapsed' => TRUE)); 

It needs some styling help but it's the basic functionality that I was looking for.

The beauty of this solution is that you could use this to make just about anything collapsible in your theme- not just comments.

schiavone’s picture

I like this method best because it re-purposes code and is extensible to other elements.

sertaconay’s picture

Let's make the comments collapsible one by one.

First, we need comment.tpl.php file in theme folder. If it doesn't exist, copy from comment module folder or create one.

Example comment.tpl.php:


<div class="comment<?php print ($comment->new) ? ' comment-new' : ''; print ' '. $status ?> clear-block">
  <?php print $picture ?>

  <?php if ($comment->new): ?>
    <span class="new"><?php print $new ?></span>
  <?php endif; ?>

  <h3><?php print $title ?></h3>

  <div class="submitted">
    <?php print $submitted ?>
  </div>

  <div class="content">
    <?php print $content ?>
    <?php if ($signature): ?>
    <div class="user-signature clear-block">
      <?php print $signature ?>
    </div>
    <?php endif; ?>
  </div>

  <?php print $links ?>
</div>

Now, here is the magic. As you know Drupal has its own collapsible style. Why shouldn't we use Drupal way instead of other way? (:
So, put this code under the line which starts with div class="comment"

<fieldset class="collapsible collapsed">
<legend>  <?php print $author ?></legend>
<div class="fieldset-wrapper">

We opened a fieldset tag. $author is comment's owner. Look for other variables in comment.tpl.php under comment module folder.

Then, close fieldset and div tags. Put them under php endif;


</div>
</fieldset>

and ready. It's simple, isn't it? (:

jermsv1’s picture

so i tried a bunch of ways as suggested here

The thing I ended up doing since I was trying to basically just put all the "comments" stuff into a collapsible fieldset is outlined here:

-Go into the Content Type -> Manage Display.

-Create an empty fieldset called something like "Comments" (You'll need fieldset/fieldcollection modules)

-Once you have the group, grab the field_groupname for later use in code.

-In your theme's template.php, or whereever you have the render arrays you'll have something like this to basically add the "comments" object into the group fieldset you just created

function mytheme_preprocess_node(&$vars, $hook){
    $tempField = null;

            // Copy the comments / comment form into a variable.
    $tempField = $vars['content']['comments']; 

            // Rename some of the labels, use the markup
    $tempField['#title'] = "DMS URL";
    $tempField['#field_name'] = "field_comments";
    $tempField[0]['#markup'] = $vars['content']['comments'];

            // Add it into the group (fieldset/group name you copied)
    $vars['content']['group_commentsgroup']['field_comments'] = $tempField;
}

This will basically add your comments markup into an empty fieldset/group you created using node's manage display using fieldset/fieldcollection. Also, I was using ajax_comments for this..