Update (200911-08): I've stopped using this, because it made the archive generating fail in mysterious ways...

As you might have seen I have now these nice (opinions may vary) "more..." links in my blog. This is done with some JavaScript and shell foo and in this entry I will explain how I did it.

The setup also works with text browsers and people who disable JavaScript. In the latter case you will get the normal nb behavior where you see the entire article. When using a text browser you also see the entire article but there is also a (non functional) 'more' link.

User side

When writing a blog entry the only thing you need to do is to put the following on a line

- read more -

(technically you need more -'s to make it work, but this will suffice for this example).

Anything you type below that line will become collapsible with a 'more' link. Anything above will be directly visible.

Implementation

First a shell script which reads your entire blog entry and replaces the - read more- with the html and JavaScript to make it work.

#!/bin/bash
EPOCH=$(date +%s)
ART_ID="art_$$_$EPOCH"
HREF_ID="href_$$_$EPOCH"
DATA=$(cat)

# escape galore
repl="<script type=\"text\/javascript\">\n\
<!--\n\
function toggle_visibility(id, anchor) {\n\
   var e = document.getElementById(id);\n\
   var a = document.getElementById(anchor);\n\
   if(e.style.display == 'block') {\n\
      e.style.display = 'none';\n\
      a.innerHTML = \"\&laquo; more ...\";\n\
   } else {\n\
      e.style.display = 'block';\n\
      a.innerHTML = \"\&laquo; less\";\n\
   }\n\
}\n\
\/\/-->\n\
<\/script>\n\
<div class=\"readmore\">\n\
<a class=\"readmore\" style=\"display: none;\" id=\"$HREF_ID\"\n\
href=\"javascript:\/\/\" onclick=\"toggle_visibility(\'$ART_ID\', \'$HREF_ID\');\">\
\&raquo; more ...<\/a>\n\
<\/div>\n\
<div id=\"$ART_ID\">\n\
<script type=\"text\/javascript\">\n\
<!--\n\
e = document.getElementById('$ART_ID');\n\
e.style.display = 'none';\n\
e = document.getElementById('$HREF_ID');\n\
e.style.display = 'block';\n\
\/\/-->\n\
<\/script>\n\
"
if echo "$DATA" | egrep -q -- '-{3,}.?read.more.?-{3,}'; then
echo "$DATA" | sed -r "s/-{3,}.?read.more.?-{3,}/$repl/"
echo "</div> <!-- id=$ART_ID -->";
else
echo "$DATA"
fi

As I'm using stdin twice I am capturing it in the variable $DATA.

The variable $repl is filled and is used by sed the replace - read more-. It was a real pain to correctly quote everything (as you might see).

The JavaScript trick to do this collapsing can be easily found on the internet (google: hide/show divs).

interfacing with nanobloggger

You need to edit two templates, entry.htm and permalink.htm, in the first one you enable the 'read more'-feature and the latter you need to get rid of the '- read more -' line.

entry.htm

In entry.htm replace

$NB_EntryBody

with

$(echo "$NB_EntryBody" | ${BLOG_DIR}/bin/readmore)

Adjust this to where you have saved the shell script from above.

permalink.htm

On your permalink page this read more stuff is ridiculous, so there we must get rid of it.

Where it says

$NB_EntryBody

replace that with

$(echo "$NB_EntryBody" | sed -r 's/-{3,}.?read.more.?-{3,}//')

to filter out the line.

Tags: nanoblogger, site

2 comments

Small update:

If you are using markdown to write your blog entries you need to make sure the javascript and div stuff isn't put in a paragraph.

This will lead to a block element inside a inline element and will make you page fail to validate.

another update


Note that these read more lines also appear in your rss/atom feeds. So they need to be filtered out.

For /usr/share/nanoblogger/plugins/rss2.sh I changed the following. Where it says
NB_RSS2EntryExcerpt="$NB_EntryBody"
change that to:

NB_RSS2EntryExcerpt=$(echo "$NB_EntryBody" | \
sed -r 's/-{3,}.?read.more.?-{3,}//')


So that the line is filtered out. Same applies for atom.sh

Comments are closed

If you really, really want to comment, please mail miek@miek.nl.

0 comments in moderator queue