Unlike Wordpress, Drupal offers no way in core to put a read more link inline with the teaser. Out-of-the-box Drupal’s teaser customizing is very basic. You may either 1- insert in your posting an HTML comment à la Wordpress, <!--break-->, to tell Drupal where you want your teaser to end (in Wordpress, you’ll type the Quicktag <!--more--> instead), or 2- you leave it up to Drupal to make a teaser out of the n first words of the post. Drupal will take that teaser and the full content and store them separately in the database. In Wordpress, by default, you’ll find a “more...” link at the end of the teaser, inviting you to read the full posting. Drupal does offer a “read more” link, but you’ll find it with the other posting links, away from the teaser. Chances are : readers will miss that link and believe that the teaser is all there is to read in the posting.
This article describes a simple hack to remedy the situation. It works in Drupal 4.7 and 5.
UPDATE April 8th, 2008 : it works in Drupal 6 as well. Make sure your code accounts for the change in the l() function signature. For this, refer yourself to the Drupal API — follow the link.
Decide on which HTML text you want to display as your read more link. Will that be “more...” like in Wordpress, or “more »»” ? That text will become YOUR_TEXT_FOR_THE_LINK in the hack below. If you need to use a special character, use an entity :
Character you want to display | Corresponding entity |
---|---|
» | » |
→ | → |
⇒ | ⇒ |
In a text editor, open the file modules/node/node.module if you’re using Drupal 5.x, or, alternatively, modules/node.module if you’re using Drupal 4.7.x.
Look for the definition of the function node_prepare(). Once you find it, add to it the following line of code :
<?php
function node_prepare($node, $teaser = FALSE) {
$node->readmore = (strlen($node->teaser) < strlen($node->body));
if ($teaser == FALSE) {
$node->body = check_markup($node->body, $node->format, FALSE);
}
else {
/* Beginning of hack -- modified by YOUR_NAME */
if($node->readmore) {
$node->teaser .= ' '. l(t('YOUR_TEXT_FOR_THE_LINK'),
'node/' . $node->nid, array('class' => 'read-more',
'title' => 'Read the rest of this posting.'),
NULL, NULL, TRUE, TRUE);
}
/* End of hack */
$node->teaser = check_markup($node->teaser, $node->format, FALSE);
}
$node->content['body'] = array(
'#value' => $teaser ? $node->teaser : $node->body,
'#weight' => 0,
);
return $node;
}
?>
Do you want to remove the existing read more link that’s added by Drupal to the posting links ? Add two lines of code instead :
<?php
function node_prepare($node, $teaser = FALSE) {
$node->readmore = (strlen($node->teaser) < strlen($node->body));
if ($teaser == FALSE) {
$node->body = check_markup($node->body, $node->format, FALSE);
}
else {
/* Beginning of hack -- modified by YOUR_NAME */
if($node->readmore) {
$node->teaser .= ' '. l(t('YOUR_TEXT_FOR_THE_LINK'),
'node/' . $node->nid, array('class' => 'read-more',
'title' => 'Read the rest of this posting.'),
NULL, NULL, TRUE, TRUE);
$node->readmore = FALSE; // To remove the default read more link
}
/* End of hack */
$node->teaser = check_markup($node->teaser, $node->format, FALSE);
}
$node->content['body'] = array(
'#value' => $teaser ? $node->teaser : $node->body,
'#weight' => 0,
);
return $node;
}
?>
Upload your edited file to your server.
There is one contributed module that does this, but it modifies the teaser after the teaser has been filtered, instead of before. That module is bloated, i.e. about 200 lines of code... while we’re only adding two lines here, with surgical precision and no performance hit.
The read more link we’re generating is a URL that points to the alias of the full posting as in http://11heavens.com/read-more-link. It’s very important to generate a URL here, rather than a web-root relative link like /read-more-link, because teasers are displayed in RSS feeds, on other web sites. We don’t want that read more link to point to a non-existant node on the other web site.
You may want to change the class and title attributes of the link. The title attribute in the code sample above is Read the rest of this posting.
It is what’s used in English by default for the read more link that’s with the other node links, i.e. in $links.
In the l() call, we’re using TRUE as sixth (6th) argument because we want an absolute path, that is, a URL, for the link. And we’re adding TRUE as seventh (7th) argument if we’re using HTML entities in our read more link.
l($text, $path, $attributes = array(), $query = NULL, $fragment = NULL, $absolute = FALSE, $html = FALSE)
- $absolute
- Whether to force the output to be an absolute link (beginning with http:). Useful for links that will be displayed outside the site, such as in an RSS feed.
- $html
- Whether the title is HTML, or just plain-text. For example for making an image a link, this must be set to TRUE, or else you will see the encoded HTML. Same thing if you are using HTML entities, you need to set it to TRUE, or else you will see something like
read more ⇒
.