There's ungoing debate about how Drupal should handle teasers, body and whether it should combine them or separate them. This topic was born from Steven's Teaser Splitter patch: http://drupal.org/node/107061 but there are other threads discussing this issue.

I've spent a few hours trying to see this from a UI perspective while also taking into consideration JS on/off and newbies not familiar with Drupal.

The original idea of Steven to introduce a teaser/body split/join is always good for extra usability. We should use definitely use it, but read below first.

We have content types (Admin > Content > Content Types) and we also have post settings (Admin > Content > Post Settings). What Drupal is lacking behind is the ability to specify teaser on/off and "teaser size" per content type. This then solves the first round of usability problems while corrects some of the weird core behaviour other contrib modules are trying to fix (e.g. excerpt.module).

Now say we enabled teasers for Foo content type (and we've given it a 200 character limit). When we create a new Foo page currently we get one body textarea. This should really be split into Teaser textarea and a Body textarea. This then solves the second round of usability problems but we just made it a little less intuitive by introducing the extra textarea. This is where Steven's patch CAN do its magic with joining the two textareas and then defining the cut off point between teaser and body content.

Either way, we need to add a checkbox to the workflow area (or any ideas?) to say: Include teaser in body.

That's all there is to it. Questions and comments welcome.

Comments

Lowell’s picture

I like to frame my body content into tables to give it some horizontal layout control, ie placing an image next to the text

for this reason I prefer to have a separate text area for teasers, otherwise my body content gets chopped and the

tags and
tags (I think) get confused.
modul’s picture

Why don't you make use of the $teaser variable in your templates? Assuming you have various node-yourcontenttype.tpl.php, you can easily implement all sorts of things with that $teaser. It works in 5.x, at least. Don't know about 4.7.x.

if ($teaser == 1) {
  echo "Whatever you want, in teaser view.";
} else {
  echo "Something else now, because you're in full view.";
}

- You can play with the length - just show a substring, depending on which tpl file you're using.
- Show (or don't show) certain CCK fields, commenting options etc., depending on whether $teaser is true or not, depending on which node type you're displaying etc.
- $teaser is also available in field-field_something.tpl.php, the template files for CCK fields.

It's really quite flexible this way. Your suggestion of making the teaser more approachable in the administration section is, of course, always welcome, but for the time being, I can do live with the above approach.

Your suggestion to have two textareas, hmm, that's not my choice. Joomla works like that, and it was something I disliked immediately. I designed something to circumvent this, and allow my users to write their stuff only in the "teaser"/intro area. Whenever I needed a teaser, I made on through code. Physically dividing a text feels highly artificial and counter-intuitive to me.

Ludo

BioALIEN’s picture

Ludo, I know there are ways to achieve this at present, via CCK, excerpts.module or even hacking core. But this proposal is to find the final solution to go into core itself.

I know having two textareas is a slight setback, but it will only appear if set to visible in your content type and even then, it will only be like that for JS disabled. Because Steven's patch can handle the merging of the two textareas.

So yes, it will work the same way as Joomla and all the other "normal" use cases in other CMS out there. Because this is typically what you expect from a teaser and a body. The current Drupal way of handling those is flawed both from a DB storage perspective and from a usability standpoint. There's no way to *switch off* teasers so the approach outlined above eliminates this.

---
Dee
iScene Interactive :: iScene.eu

Chill35’s picture

There are two weaknesses about teaser in Drupal core.

  1. It seems like such a limitation to have a teaser be defined in core as "the beginning MARKUP up to markup character x".

    There should be IN CORE a way to make a teaser be what it really is semantically-speaking : something that will grab your interest and make you want to read the FULL thing. Can be a summary, can be the beginning sentences WITHOUT the picture that finds itself in the markup, etc. So +1 for the possibility of an added textarea for teaser :)
    This added field could be turned on and off. And all this could be customized in the administrator control panel, ov course.

  2. ALSO, I think that it's about time that a readmore link INLINE with the teaser becomes an optional admin setting as well.

    Just like we can set in the administrator control panel the length used to chop off a content to make a teaser automatically, we should in my opinion add the option to add a read more LINK, with the teaser, when the teaser differs from the content. It is not obvious at all that there is something more to read, from a "read more" link that finds itself separate from the text, among other links like "add a comment".

    I am aware that much can be done in the node template, but placing a link INLINE with the teaser is not easy.
    It requires to actually modify the teaser.

    There is a contributed module that does that, and does it poorly in my opinion (at best it can). It is functional but bloated (to no fault of the module's maintainer). It uses all of this code to add a simple link inline, a functionality that requires TWO LINES of code change in core (minus the admin settings), and I will come to this next :

    From ed_readmore.module (only an excerpt) :

    /**
     *
     * Fix "read more" flag
     * From the most excellent angry donuts site: http://www.angrydonuts.com/the_nuisance_of_the_read_more_fl
     * From author: Note that I'm using a lot of arguments to l() -- I'm telling it to provide an 'absolute' 
     * path, because these teasers often go out to RSS, and providing an absolute path is much, much safer.
     */ 
    function ed_readmore_nodeapi(&$node, $op, $teaser, $page) {
      if ($op == 'view') {
        if (variable_get('ed_readmore_readmore_tweak', ED_READMORE_READMORE_TWEAK_DEFAULT) && $teaser && $node->readmore) {
          // deal with broken strrpos on php4
          if (_ed_readmore_is_php4()) {
            $find_last = '_ed_readmore_strrpos_string';
          }
          else {
            $find_last = 'strrpos';
          }
          $readmore_url = l(variable_get('ed_readmore_text', t(ED_READMORE_TEXT_DEFAULT)), "node/$node->nid", NULL, NULL, NULL, TRUE, TRUE);
          $node->readmore = false;
          //
          // since we are blowing away some of the implicit info ($node->readmore) let's remember that this was a teaser
          $node->is_teaser = TRUE;
          if (variable_get('ed_readmore_readmore_inline', ED_READMORE_READMORE_INLINE_DEFAULT)) {
            $read_more = "<span class='read-more'>" . $readmore_url . "</span>";
            // int strrpos ( string haystack, string needle [, int offset] )
            // substr_replace ( mixed string, string replacement, int start [, int length] )
            $marker_to_insert_at = '</p>';
            $final_p_pos = $find_last($node->teaser, $marker_to_insert_at); // php4 gotcha - will search only for first char of marker!  (supports only single char search)
            if (!($final_p_pos ===FALSE)) {
              $node->teaser = substr_replace($node->teaser, $read_more, $final_p_pos, 0); // account for length of </p> string
            } else {
              $node->teaser .= $read_more; // not found, so just append it
            }
          }
          else { // just add it at the bottom of the teaser, please.
            $node->teaser .= "<div class='read-more'>" . $readmore_url . "</div>";
          }
        }
      }
    
    }
    
    ###################################################
    #
    # DESCRIPTION:
    # This function returns the last occurance of a string,
    # rather than the last occurance of a single character like
    # strrpos does. It also supports an offset from where to
    # start the searching in the haystack string.
    #
    # ARGS:
    # $haystack (required) -- the string to search upon
    # $needle (required) -- the string you are looking for
    # $offset (optional) -- the offset to start from
    #
    # RETURN VALS:
    # returns integer on success
    # returns false on failure to find the string at all
    #
    # lifted from http://us3.php.net/manual/en/function.strrpos.php#67559
    #
    ###################################################
    
    function _ed_readmore_strrpos_string($haystack, $needle, $offset = 0) {
      if(trim($haystack) != "" && trim($needle) != "" && $offset <= strlen($haystack)) {
        $last_pos = $offset;
        $found = false;
        while(($curr_pos = strpos($haystack, $needle, $last_pos)) !== false) {
          $found = true;
          $last_pos = $curr_pos + 1;
        }
        if($found) {
          return $last_pos - 1;
        }
        else {
          return false;
        }
      }
      else {
        return false;
      }
    }
    

    Wereas all that is required in core is TWO lines changed in node.module in the function node_prepare() :

    Here I am not checking if the teaser is actually different than the content. That's the line that's missing.
    (On my web site the teaser is always different from the body).

    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 {
        // ******** Modified by Caroline Schnapp *********
        if ($node->readmore) {
       $node->teaser .= '&nbsp;'. l(t('Read&nbsp;more&nbsp;&rarr;'),  'node/' . $node->nid, array('class' => 'thereIsMoreToRead', 'title' => 'Read the rest of this posting.'), NULL, NULL, TRUE, TRUE);
       }
       // ******** END OF MODIFICATION ***************
        $node->teaser = check_markup($node->teaser, $node->format, FALSE);
      }
      return $node;
    }
    

    On the next line (next to the modification), the existing call to check_markup takes care of adding the ending </p> or </div> (or whatever) to make the HTML of the teaser correct and valid, if such tag is necessary.

Caroline
A coder's guide to file download in Drupal
Who am I | Where are we
11 heavens

misty3’s picture

Teaser Options which admin can set ( various settings for various node types ):

administer » settings » content types » a specific content type ( eg. blog ) » workflow

Teaser or summary or intro or whatever it is called

default options
radiobuttons - choose any one
disabled
enabled , automatic teaser [ first 'n' words from content ]
enabled, teaser text area box [ separate stuff from main content ]
enabled , automatic teaser with thumbnail picture [ 1st image ]
enabled, teaser text area box with thumbnail picture [ 1st image ]

if teaser text area is enabled
radiobuttons - choose any one
keep the text box above the body text area
keep the text box below the body text area

Collapse teaser text area option
check box

if teaser text area is enabled but user keeps it empty
radiobuttons - choose any one
automatic teaser
node title
full post

if teaser with image
radiobuttons - choose any one
left align image with wrapping text
right align image with wrapping text
image ,line break, then text
text, line break, then image

How many words if automatic teaser
text(number) input or number dropdown

What code if custom break wanted [ rather than 'n' words ] in automatic teaser
text input
example code <--teaser-->

Show Teaser on specific pages:
radiobuttons - choose any one
Show on every page except the listed pages.
Show on only the listed pages.
Show if the following PHP code returns TRUE (PHP-mode, experts only).

In addition to this an access control may be added for teaser textarea boxes eg. allowing only admins or certain blogger role to have this. though if we go by 'per content type' this may not be necessary.

Some frills ( or features in some cms-es ) can be adding "forward" and "print" link to teasers.

Best regards

vm’s picture

This is overcomplicating what the splitter intends to do, IMO. The intention is allows users and admins to not have to use <!--break-->

I don't think such a simple feature would need 8 settings on its own.

misty3’s picture

How do you then give the system/site admin the option

to offer or not offer a separate text box for teaser
which by default can be collapsible/non-collapsible
and can / cannot contain thumbnail image

and also allow the specific needs of specific pages to show the teasers ?

These are the options for the admin only who already tackles a plethora of more than 100 or more options. The enduser or the visitor will not be seeing so much options :-)

Having enabled the admin with various options is what drupal flexibilty is all about, in my humble opinion.

Like to know what your exact suggestion is in this matter.

Best regards

vm’s picture

I don't have a suggestion in the matter of the UI on the admin side. Mainly because the feature being discussed isn't a rewrite of how teasers are handled in core, from my reading of it. It sets out to stop users and/or admins from having to use the pseudo tag. <!--break--> and thats it, nothing more nothing less.

Per your additions to the splitter, the code would also then, have to be smart enough not to place a button that says "split at cursor" in a case where an admin has set it to seperate at "n" characters. Again though, my reading of the entire issue did not uncover a desire to "change" the way drupal core handles teasers in total.

Chill35’s picture

It sets out to stop users and/or admins from having to use the pseudo tag.

and thats it, nothing more nothing less.

WRONG. Because the new patch gives the option of making the teaser part of the content or not. If a teaser is not part of the content, it can become anything at all, e.g. a 'summary'. It is much more than a debate between putting a <!--break--> or a <break> or let users 'put their cursor where they want their break to be'.

http://acko.net/dumpx/teaser.png

See the checkbox ?

Caroline
Who am I | Where are we
11 heavens

Chill35’s picture

I would add an option to add an inline readmore link when the teaser is different from the content. But then again, ANYONE can hack code for that. However, the thing is if many, many people end up hacking core for something then maybe it should be put into core.

I love the image settings.

I like EVERYTHING about these settings, misty.

That's an awesome, complete, clear presentation of everything I need a teaser to be.

I am not sure about the latest word that's used for teaser in the issue thread : 'summary'. The teaser can be a summary, but in most cases it won't be that, so it may confuse people. It did confuse me. Has anyone seen the latest screenshot ? http://acko.net/dumpx/teaser.png

Caroline
A coder's guide to file download in Drupal
Who am I | Where are we
11 heavens

misty3’s picture

Thanks Chill35

Yes thats confusing to me too, I mentioned it in that page.
Probably the admin can have the option to define human readable name of teaser as 'teaser' or'summary' or 'abc' or 'xyz' or whatever for her/his installation of drupal ......

Chill, since you are a long time user can you take this recommendation for teaser [ "everything you need a teaser to be." ] to appropriate ears and then probably its implementation ?
http://drupal.org/node/134657

Best regards

Chill35’s picture

I may be a long time user but I am nowhere near anyone within the circle of the Drupal influentsia.
I added a follow-up to your feature request : http://drupal.org/node/134657

PS : yep, that's a play on words between intelligentsia, influence and influenza.

Caroline
A coder's guide to file download in Drupal
Who am I | Where are we
11 heavens

Steven’s picture

This whole discussion is useless unless everyone tries out what we currently have in core, and how the separate teaser checkbox and such works.

Anyone want to put up a demo?

--
If you have a problem, please search before posting a question.

BioALIEN’s picture

Steven,

Misty3 has posted an initial screenshot for demo purposes here:
http://drupal.org/files/issues/teaser-workflow-per-content-type.GIF

Bare in mind, this is still at an early stage and a lot of cruft will be simplified as soon as I'm finished with it.

FYI, an issue has been setup for this now here: http://drupal.org/node/134657
---
Dee
iScene Interactive :: iScene.eu

Chill35’s picture

My 'read more link inline with teaser' hack in core wasn't very good, because it didn't produce a URL. It's important to produce a URL, i.e. a link that starts with http://mySite.com/, because teasers are displayed in feeds. And you're modifying the teaser here.

Here's the new hack (I edited my code above as well) :

In modules/node/node.module, find the node_prepare() definition.

function node_prepare($node, $teaser = FALSE) {
  // First we'll overwrite the existing node teaser and body with
  // the filtered copies! Then, we'll stick those into the content
  // array and set the read more flag if appropriate.
  $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 Caroline */
    if($node->readmore) {
      $node->teaser .= '&nbsp;'. 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;
}

Notes :

1. The read more link is a URL that points to the alias as in http://website.com/does-steven-have-a-girlfriend

2. Replace the class and title attributes with what you want. The title attribute Read the rest of this posting. is what's used in English by default for the read more link that's with the other $links.

3. Replace YOUR_TEXT_FOR_THE_LINK with your own HTML. (By the way, the following entity, &rarr; is an arrow : →). Use 'FALSE' as last argument for the l(), as I have done above, so that entities are displayed. Otherwise, you'll get something like Read&nbsp;more&nbsp;&rarr; instead of Read more →.

4. $node->readmore = FALSE; gets rid of the default 'read more' link that comes bundled with the other posting links, away from the teaser.

Caroline
The read more link
A coder's guide to file download in Drupal
Who am I | Where are we
11 heavens