5

I want to replace the 'reply' link with button. As an intermediate solution I styled the link as a button with CSS, but I want it to be a real html 'button' element. The reason is, I do not want the reply links being visible to search engines, instead of it, I want to handle clicks on buttons with javascript.

I only found this 10 year old discussion on drupal site: https://www.drupal.org/node/33170.

I created a custom comment.tpl.php and tried to modify the $links['comment']['#links']['comment-reply'] array, but without success.

  • Where did you try to modify the array? What function/hook? Or did you modify it in the template file comment.tpl.php? – Beebee Aug 25 '15 at 17:05
  • I tried to modify it in a comment.tpl.php template file – hennadiy.verkh Aug 25 '15 at 17:08
5

There are two methods below. Both are equally effective except the second one requires that the <button> element be taken out of the list of links and put elsewhere in the template. This is either annoying or awesome depending on what outcome you're going for.

Method 1: Override MYTHEME_links()

In Drupal 7, you can turn the comment "Reply" link into a <button> element by overriding core's theme_links() function. It isn't pretty, but it's effective.

Add the function below to your theme's template.php file (replace "MYTHEME" with your theme name). Clear your cache for the change to take effect.

function MYTHEME_links($variables) {
  $links = $variables ['links'];
  $attributes = $variables ['attributes'];
  $heading = $variables ['heading'];
  global $language_url;
  $output = '';

  if (count($links) > 0) {
    // Treat the heading first if it is present to prepend it to the
    // list of links.
    if (!empty($heading)) {
      if (is_string($heading)) {
        // Prepare the array that will be used when the passed heading
        // is a string.
        $heading = array(
          'text' => $heading,
          // Set the default level of the heading.
          'level' => 'h2',
        );
      }
      $output .= '<' . $heading ['level'];
      if (!empty($heading ['class'])) {
        $output .= drupal_attributes(array('class' => $heading ['class']));
      }
      $output .= '>' . check_plain($heading ['text']) . '</' . $heading ['level'] . '>';
    }

    $output .= '<ul' . drupal_attributes($attributes) . '>';

    $num_links = count($links);
    $i = 1;

    foreach ($links as $key => $link) {
      $class = array($key);

      // Add first, last and active classes to the list of links to help out themers.
      if ($i == 1) {
        $class [] = 'first';
      }
      if ($i == $num_links) {
        $class [] = 'last';
      }
      if (isset($link ['href']) && ($link ['href'] == $_GET ['q'] || ($link ['href'] == '<front>' && drupal_is_front_page()))
         && (empty($link ['language']) || $link ['language']->language == $language_url->language)) {
        $class [] = 'active';
      }
      $output .= '<li' . drupal_attributes(array('class' => $class)) . '>';

      if (isset($link ['href'])) {
        if ($key == 'comment-reply') {
          // Special handling for comment 'Reply' link.
          $output .= '<button type="button">' . $link ['title'] . '</button>';
        }
        else {
          // Pass in $link as $options, they share the same keys.
          $output .= l($link ['title'], $link ['href'], $link);
        }
      }

      elseif (!empty($link ['title'])) {
        // Some links are actually not links, but we wrap these in <span> for adding title and class attributes.
        if (empty($link ['html'])) {
          $link ['title'] = check_plain($link ['title']);
        }
        $span_attributes = '';
        if (isset($link ['attributes'])) {
          $span_attributes = drupal_attributes($link ['attributes']);
        }
        $output .= '<span' . $span_attributes . '>' . $link ['title'] . '</span>';
      }

      $i++;
      $output .= "</li>\n";
    }

    $output .= '</ul>';
  }

  return $output;
}

Breaking it down...

This bit of code:

      if (isset($link ['href'])) {
        // Pass in $link as $options, they share the same keys.
        $output .= l($link ['title'], $link ['href'], $link);
      }

was changed to

      if (isset($link ['href'])) {
        if ($key == 'comment-reply') {
          // Special handling for comment 'Reply' link.
          $output .= '<button type="button">' . $link ['title'] . '</button>';
        }
        else {
          // Pass in $link as $options, they share the same keys.
          $output .= l($link ['title'], $link ['href'], $link);
        }
      }

Of course you'll need to customize the output with whatever you need, whether it be a <form> wrapper or onclick attribute.

Unfortunately we can't use theme('button'...) because that would give us an input element. Of course we could change that by overriding theme_button() but that would affect all input elements on the site, and you would still need to override theme_links() in order to call it.

Method 2: MYTHEME_preprocess_comment()

If you don't mind taking "Reply" out of the links list altogether, this method will also work. It uses the comment preprocessor to unset the link, but not before taking the value of the URL and stuffing it into a new variable.

Again, add the function below to your theme's template.php file (replace "MYTHEME" with your theme name).

function MYTHEME_preprocess_comment(&$variables) {
  if (isset($variables['content']['links']['comment']['#links']['comment-reply'])) {
    $variables['reply_url'] = $variables['content']['links']['comment']['#links']['comment-reply']['href'];
    unset($variables['content']['links']['comment']['#links']['comment-reply']);
  }
}

Then add this (or a variation of it) wherever you would like it to appear in your copy of comment.tpl.php:

<?php if (isset($reply_url)): ?>
<button onclick="window.location.href='<?php print $reply_url ?>'">Reply</button>
<?php endif; ?>

Clear your cache for the change to take effect.

  • I chose the second method because of less copy/paste of code. But I made it a little bit simpler. Instead of creating the MYTHEME_preprocess_comment function, I simply unset the $content['links']['comment']['#links']['comment-reply'] variable in the comment.tpl.php, and add a button as you have shown in your answer. – hennadiy.verkh Aug 26 '15 at 8:21
  • 1
    Cool. It's just generally a good idea to keep logic out of template files, which is why I suggest the preprocessor. Glad to help. – othermachines Aug 26 '15 at 8:28

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service, privacy policy and cookie policy

Not the answer you're looking for? Browse other questions tagged or ask your own question.