Solved

How can I toggle (show/hide) comments on a node in Drupal 7

Posted on 2013-02-04
17
1,541 Views
Last Modified: 2013-02-14
I've been thinking about mobile web. Most nodes have a chunk of primary content, then what I'll call secondary content (related content to the current node, but not the main focus) and tertiary content (navigation, footers, headers etc). I would like to focus on primary content and keep the rest as minimal as possible.

The tertiary bit isn’t a problem, mostly theming stuff with media queries. The primary content isn’t too hard to sort out. Drupal seems to do a fine job of separating these things. Where I’m having trouble is the secondary content, particularly comments.

What I would like to do is:      

Don’t automatically show comments

If there are no comments, don’t show anything (drupal does this by default)

If there are comments, show a link, preferably with a comment count “ 14 comments” or something like that

A person selects the link and the comments are exposed.

Ideally this would be happen programmatically, not just hiding the comment block with CSS, don’t want it to load unless requested.

Ajax load would be nice so the page doesn’t reload

Any ideas on how I can do this?
0
Comment
Question by:itkadmin
  • 9
  • 6
  • 2
17 Comments
 
LVL 12

Expert Comment

by:junipllc
ID: 38851540
Just from a quick search I came up with these, but I'm not sure if they will work 100% in your situation. I typically start a module search by finding one on Drupal.org, then looking in the lower-right corner of the page for related modules. I've found some real gems that way...and some not-so-good ones. :)

http://drupal.org/project/ajax_comments
http://drupal.org/project/hidden_comment

I've used AJAX Comments before and I know it has a lot of options, so it may be able to satisfy some (or maybe all?) of your requirements. However, if you can't find a module or combination of modules that does what you need, there is always the option of using theming to do what you need.

Depending on the base theme you're using, or really just the theme and its support components, you can create and edit your template files (for example, comment.tpl.php) to programmatically style the way a comment or set of comments is rendered. Best practice, however, is to put any preprocessing into preprocess functions. These are usually found in template.php inside your theme.

The other option is to create a module to do this, which will apply to all themes instead of just one. Much of the code will be similar, and if you haven't coded a module before this would probably be a good one to start on. You may need to create one if things get too complicated for simple theming.

By the way, hiding content using CSS instead of doing it "The Drupal Way" is discouraged, so I definitely applaud you and support you in that cause :)

Those are all of the thoughts I have at the moment, and that should get you started, at least in the path to getting this done. I'd start with a module search, then move to actual coding if that doesn't result with something you can use. AJAX is very easy to implement in Drupal (especially with Chaos Tools (ctools)), so don't rule out doing your own if you're familiar with the concepts.

Disclaimer: the above is all stream of consciousness and I haven't gone back to proof it, so hopefully it makes sense!

Let me (us) know if you have any questions along the way!

Cheers,

Mike
0
 
LVL 2

Author Comment

by:itkadmin
ID: 38851946
Hi

Thanks for this.

I've done the module search, nothing that does what I'm looking for. I toyed with the idea of removing comments from the template, using views to make a comment block then use some Jquery to show the block.

problem is - I'm not fond of the views mark-up. The comment module provides sone nice RDF. Also, this solution would be back to hiding with CSS.

I haven't a clue how to start with module building. I'm one of those guys who works in one window and googles everything I want to do in the other window.
0
 
LVL 16

Expert Comment

by:HagayMandel
ID: 38852369
Another approach is to generate a new template file for a node, that will contain the node itself, and a view that will encapsulate the comments (as links with comment count etc)
Ajax can be easily applied, via views again,and the whole thing is proper Drupal's way.
0
 
LVL 2

Author Comment

by:itkadmin
ID: 38854677
I can give the views method a go. I tried something similar before and couldn't find a way to theme threaded comments. Views didn't apply any different classes to comments that were replies to comments.

I'm not sure what you mean by making a template file for a node that contains the node. Sounds mysterious and cryptic!
0
 
LVL 2

Author Comment

by:itkadmin
ID: 38856990
It looks like doing this programmatically is going to be beyond my abilities.

I sort of found a solution, though not the sleekest, it works.

I can use Ctools and a bit of php in the node template like so
<?php 
	 $collapsed_content = render($content['comments']);
	 if ($comment_count > 0 && $comment_count < 2): /*this should handle single comments*/
	 print theme('ctools_collapsible', array('handle' => $comment_count, 'content' => $collapsed_content, 'collapsed' => TRUE)); 
	 elseif ($comment_count > 2): /*this is for multiple comments*/
	 print theme('ctools_collapsible', array('handle' => $comment_count, 'content' => $collapsed_content, 'collapsed' => TRUE)); 
	 endif;
 ?>

Open in new window


You can see it work here http://www.craigclark.ca/content/notebook/2012/november/do (the '9' below the big image on the left)

This collapses things (though just hiding them, not exactly what I was looking for), it doesn't show a comments link if there are no comments on the node. What I would like to do is work with plurals, so I get "1 comment" or "2 comments" etc. What I don't know is how to add some text for "comment" or "comments". I assume "comment" would go on line 4 somewhere after array('handle' => $comment_count, and "comments" would go on line 6 somewhere.

How do I add that in? What I have here returns only a number.

I'm not strong on PHP, figured this much out with info provided in node template file, ctools tutorial and PHP elseif manual.
0
 
LVL 2

Author Comment

by:itkadmin
ID: 38857828
Changed a bit, to deal with plurals

Its not quite what I was hoping, I think calling the comments to load on request is beyond what I know how to do.

This works in the template and just shows/hides comments using ctools, for what it is, does it look correct?

<?php 
	 $collapsed_content = render($content['comments']);
	 if ($comment_count > 0 && $comment_count < 2):
	 print theme('ctools_collapsible', array('handle' => "{$comment_count} comment", 'content' => $collapsed_content, 'collapsed' => TRUE)); 
	 elseif ($comment_count > 2):
	 print theme('ctools_collapsible', array('handle' => "{$comment_count} comments", 'content' => $collapsed_content, 'collapsed' => TRUE)); 
	 endif;
?> 

Open in new window

0
 
LVL 16

Expert Comment

by:HagayMandel
ID: 38858268
If your'e already messing with node template, simply create a view of comments (where the contextual filter will be node id from the url), and embed it  (see how) in your template file.
0
 
LVL 12

Expert Comment

by:junipllc
ID: 38859015
I second HagayMandel's solution to embed a view. It's simple, elegant, and quick to implement.
0
Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

 
LVL 2

Author Comment

by:itkadmin
ID: 38863841
I followed the instructions  views_embed_view

I put the following in template.php and everything broke, telling me I had an error at line 41.
What is wrong with line 41?
<?php

/**Add .js for dropdown menu on devices**/
drupal_add_js('sites/all/themes/at_subtheme_craigclark/scripts/show_hide_menu.js');


/**
* Remove the comment filters' tips
*/
function at_subtheme_craigclark_filter_tips($tips, $long = FALSE, $extra = '') {
  return '';
}
/**
* Remove the comment filter's more information tips link
*/
function at_subtheme_craigclark_filter_tips_more_info () {
  return '';
}

function at_subtheme_craigclark_preprocess_page(&$variables){

    if (arg(0)=="user" || arg(0)=="users" ){

        unset ($variables['page']['content']['system_main']['user_picture']);
    }
}

function views_embed_view($name, $display_id = 'default') {
  $args = func_get_args();
  array_shift($args); // remove $name
  if (count($args)) {
    array_shift($args); // remove $display_id
  }

  $view = views_get_view($name);
  if (!$view || !$view->access($display_id)) {
    return;
  }

  return $view->preview($display_id, $args);
}

Open in new window

0
 
LVL 16

Expert Comment

by:HagayMandel
ID: 38864532
All you need to do is to USE this function.:)

views_embed_view($name, $display_id = 'default');

where $name = YOUR VIEW MACHINE NAME
$display_id =  YOU DISPLAY ID // The machine name of the display, default is 'default'
0
 
LVL 2

Author Comment

by:itkadmin
ID: 38867720
Thank you

I'm not getting errors anymore, which is good. I'm getting a white screen, which is bad. I think I'm doing something wrong in template.php

If you have time, could you please take a look? I've attached template.php, the view and the node template.
view-in-node.zip
0
 
LVL 16

Accepted Solution

by:
HagayMandel earned 500 total points
ID: 38870069
Create the view of comments with a contextual filter of content nid with default value grabbed from the url:
$view = new view();
$view->name = 'mycomments';
$view->description = '';
$view->tag = 'default';
$view->base_table = 'comment';
$view->human_name = 'mycomments';
$view->core = 7;
$view->api_version = '3.0';
$view->disabled = FALSE; /* Edit this to true to make a default view disabled initially */

/* Display: Master */
$handler = $view->new_display('default', 'Master', 'default');
$handler->display->display_options['use_more_always'] = FALSE;
$handler->display->display_options['access']['type'] = 'perm';
$handler->display->display_options['cache']['type'] = 'none';
$handler->display->display_options['query']['type'] = 'views_query';
$handler->display->display_options['exposed_form']['type'] = 'basic';
$handler->display->display_options['pager']['type'] = 'full';
$handler->display->display_options['style_plugin'] = 'default';
$handler->display->display_options['row_plugin'] = 'fields';
/* Relationship: Comment: Content */
$handler->display->display_options['relationships']['nid']['id'] = 'nid';
$handler->display->display_options['relationships']['nid']['table'] = 'comment';
$handler->display->display_options['relationships']['nid']['field'] = 'nid';
$handler->display->display_options['relationships']['nid']['required'] = TRUE;
/* Field: Comment: Title */
$handler->display->display_options['fields']['subject']['id'] = 'subject';
$handler->display->display_options['fields']['subject']['table'] = 'comment';
$handler->display->display_options['fields']['subject']['field'] = 'subject';
$handler->display->display_options['fields']['subject']['label'] = '';
$handler->display->display_options['fields']['subject']['alter']['word_boundary'] = FALSE;
$handler->display->display_options['fields']['subject']['alter']['ellipsis'] = FALSE;
/* Sort criterion: Comment: Post date */
$handler->display->display_options['sorts']['created']['id'] = 'created';
$handler->display->display_options['sorts']['created']['table'] = 'comment';
$handler->display->display_options['sorts']['created']['field'] = 'created';
$handler->display->display_options['sorts']['created']['order'] = 'DESC';
/* Contextual filter: Content: Nid */
$handler->display->display_options['arguments']['nid']['id'] = 'nid';
$handler->display->display_options['arguments']['nid']['table'] = 'node';
$handler->display->display_options['arguments']['nid']['field'] = 'nid';
$handler->display->display_options['arguments']['nid']['relationship'] = 'nid';
$handler->display->display_options['arguments']['nid']['default_action'] = 'default';
$handler->display->display_options['arguments']['nid']['default_argument_type'] = 'node';
$handler->display->display_options['arguments']['nid']['summary']['number_of_records'] = '0';
$handler->display->display_options['arguments']['nid']['summary']['format'] = 'default_summary';
$handler->display->display_options['arguments']['nid']['summary_options']['items_per_page'] = '25';
/* Filter criterion: Comment: Approved */
$handler->display->display_options['filters']['status']['id'] = 'status';
$handler->display->display_options['filters']['status']['table'] = 'comment';
$handler->display->display_options['filters']['status']['field'] = 'status';
$handler->display->display_options['filters']['status']['value'] = 1;
$handler->display->display_options['filters']['status']['group'] = 1;
$handler->display->display_options['filters']['status']['expose']['operator'] = FALSE;
/* Filter criterion: Content: Published */
$handler->display->display_options['filters']['status_node']['id'] = 'status_node';
$handler->display->display_options['filters']['status_node']['table'] = 'node';
$handler->display->display_options['filters']['status_node']['field'] = 'status';
$handler->display->display_options['filters']['status_node']['relationship'] = 'nid';
$handler->display->display_options['filters']['status_node']['value'] = 1;
$handler->display->display_options['filters']['status_node']['group'] = 1;
$handler->display->display_options['filters']['status_node']['expose']['operator'] = FALSE;
$translatables['mycomments'] = array(
  t('Master'),
  t('more'),
  t('Apply'),
  t('Reset'),
  t('Sort by'),
  t('Asc'),
  t('Desc'),
  t('Items per page'),
  t('- All -'),
  t('Offset'),
  t('« first'),
  t('‹ previous'),
  t('next ›'),
  t('last »'),
  t('Content'),
  t('All'),
);

Open in new window

Then in the node.tpl.php simply replace:
<?php print render($content['comments']); ?>

Open in new window

with:
<?php print views_embed_view('mycomments', 'default'); ?> 

Open in new window

(in this case the view machine name is mycomments).
0
 
LVL 2

Author Comment

by:itkadmin
ID: 38881403
Thanks!

That got the view into the node. I didn't have to do anything to the template.php.

back to HagayMandel's original reccomendation, I can generate the view I want, showing comment counts etc, what I don't know how to do in views is make it so I have a link with the comment count (I can get the comment count no problem) and have it open a displayt of all the comments when selected.

What I'm trying to avoid is having viewers see the comments unless they want to see the comments.
0
 
LVL 16

Expert Comment

by:HagayMandel
ID: 38883623
OK conclusions:
Paste in your node.tpl.php this code instead of the 'print render($content['comments'])' section'

<?php
$view = views_get_view_result('mycomments', 'default');
if (count($view)>0) {
	drupal_add_js('misc/collapse.js');
	print '<fieldset class=" collapsible collapsed">
  <legend><span class="fieldset-legend">Total number of comments:</b>' . count($view) . '</span></legend>
  <div class="fieldset-wrapper">';
	for ($i = 0; $i < count($view); $i++){
	$vars = get_object_vars($view[$i]);
  print '<a href = "/comment/'. $vars['cid'] .'/#comment-' . $vars['cid'] . '">' . $vars['comment_subject'] . '</a><br />';
	}
  print '</div></fieldset>';
}
?>

Open in new window

This will create a collapsible field set with a list of linked comments.
You can condition the whole code based on a content type as well.

Hagay
0
 
LVL 2

Author Comment

by:itkadmin
ID: 38885251
That mostly works.

Only glitch is that on the node page it collapses, but doesn't expand. http://www.craigclark.ca/test 
if you click the "add a new comment" link ( http://www.craigclark.ca/comment/reply/36#comment-form )  then the "total number of comments: 3" collapse works as it should.
0
 
LVL 16

Assisted Solution

by:HagayMandel
HagayMandel earned 500 total points
ID: 38886725
Add the render function to the script:

	<?php
	$view = views_get_view_result('mycomments', 'default');
	if (count($view)>0) {
		render($content['comments']); 	
		drupal_add_js('misc/collapse.js');
		print '<fieldset class=" collapsible collapsed">
		<legend><span class="fieldset-legend">Total number of comments:</b>' . count($view) . '</span></legend>
		<div class="fieldset-wrapper">';
		for ($i = 0; $i < count($view); $i++){
		$vars = get_object_vars($view[$i]);
		print '<a href = "/comment/'. $vars['cid'] .'/#comment-' . $vars['cid'] . '">' . $vars['comment_subject'] . '</a><br />';
		}
		print '</div></fieldset>';
	}
?>

Open in new window

Pay attention: You do loose the adding comments this way!
If you want it to show, add:
print '<a href ="/comment/reply/' . $node->nid . '#comment-form">'  . t('Add new comment') . '</a>'; 

Open in new window

0
 
LVL 2

Author Closing Comment

by:itkadmin
ID: 38888797
Thank you for all the time you've put into this.
0

Featured Post

Is Your Active Directory as Secure as You Think?

More than 75% of all records are compromised because of the loss or theft of a privileged credential. Experts have been exploring Active Directory infrastructure to identify key threats and establish best practices for keeping data safe. Attend this month’s webinar to learn more.

Question has a verified solution.

If you are experiencing a similar issue, please ask a related question

This article is for those that are having major problems with users upload files such as pictures to their profile. The solution is simple and has to do with correcting the directory paths. With some experimenting and testing i got it fixed. Note…
RTL (right to left) web applications aiming for audiences speaking languages like Hebrew or Arabic, are generally more complicated than the same applications aiming for audiences speaking Latin based languages. The main difference lies of course …
When you create an app prototype with Adobe XD, you can insert system screens -- sharing or Control Center, for example -- with just a few clicks. This video shows you how. You can take the full course on Experts Exchange at http://bit.ly/XDcourse.
The Email Laundry PDF encryption service allows companies to send confidential encrypted  emails to anybody. The PDF document can also contain attachments that are embedded in the encrypted PDF. The password is randomly generated by The Email Laundr…

914 members asked questions and received personalized solutions in the past 7 days.

Join the community of 500,000 technology professionals and ask your questions.

Join & Ask a Question

Need Help in Real-Time?

Connect with top rated Experts

21 Experts available now in Live!

Get 1:1 Help Now