^zhurnaly   -   Random   -   Recent Changes   -   Running Logbook   -   Help   -   RSS

Scrapbook Bookmarklet Version 0.1

A "bookmarklet" looks just like a web browser bookmark, but instead of a static address like http://zhurnaly.com it contains a tiny Javascript program to do something dynamic. A couple of weeks ago my wife, Paulette, was talking about how handy it would be to have a quick-and-easy way to take clippings from a web page. She wanted to highlight a snippet and single-click save it, along with a reference to where it came from. I've often wished for the same thing. To do it using the ZhurnalyWiki or a text editor takes a back-and-forth series of copy/paste maneuvers, more than slightly inconvenient.

So how to grab a text selection and stash it with the source URL? It took me an embarrassingly long amount of messing around to relearn enough Javascript and Perl, but now I've got a pre-beta prototype. This "Scrapbook" bookmarklet throws the information to a small program on the zhurnaly.com server which catches it and appends it to an HTML file. To try it out, copy this text and put it into a bookmark in your browser:

javascript:location.href='http://zhurnaly.com/cgi-bin/scrapbook.cgi?X='+encodeURIComponent(location.href)+'&Y='+encodeURIComponent(window.getSelection())

To use the Scrapbook, highlight some text on a web page and click the Scrapbook bookmarklet. You'll see the address of the page as a link, followed by the selected text. Neat! The default demo scrapbook lives at http://zhurnaly.com/scrapbook.html.

Of course, a public scrapbook is likely to accumulate a lot of garbage, could get erased at any time, and isn't appropriate for material you don't want everybody in the world to see. If you want to experiment with your own semi-private scrapbook, just drop a note to z(at)his(dot)com and I'll set one up for you to play with. Note that this "Version 0.1" scrapbook has all sorts of weaknesses. In particular, it can't accept more than a few paragraphs of text at a time, it doesn't handle formatted text or images, and it lacks a way to clear out the scrapbook and start over (without asking me). Maybe in version 0.2 it will be better.

Meanwhile, if you have a web server and want to experiment with it yourself, here's the source code:

#!/usr/bin/perl
# ^z = Mark Zimmermann = z(at)his(dot)com --- 2010-12-18 - 2010-12-25
# 
# this is a CGI-BIN script to take a URL of the form
#     http://host.com/cgi-bin/scrapbook.cgi?X=http://source.com/url&Y=selected_text
# from a scrapbook-bookmarklet, and put the source URL and any selected text into a "scrapbook.html" file
# 
# LIMITATIONS:
#   - can't accept more than ~2kB of selected text (URL length limitation)
#   - lacks one-click clear/reset/initialize scrapbook file, with backup/safety-net
#   - requires access to the server to install and run CGI-BIN file
#   - needs specially-crafted scrapbook-bookmarklet
#   - lacks any security
#
# FORMAT: scrapbook.html has a header section followed by a body tag, the scrapbook items,
# and an anchor <a name="SCRAPBOOK_END"></a> to let the browser to jump to the end
# of the file after a scrapbook item has been posted
#
# SCRAPBOOK-BOOKMARKLET:
#      javascript:location.href='http://zhurnaly.com/cgi-bin/scrapbook.cgi?X='+encodeURIComponent(location.href)+'&Y='+encodeURIComponent(window.getSelection())

undef $/;                         # grab entire files at once
$domain = "http://zhurnaly.com";  # set this to domain where CGI-BIN and scrapbook reside
$file_prefix = "../httpdocs/";    # set this to prefix to get from CGI-BIN to scrapbook directory
$scrapbook = "scrapbook.html";    # set this to scrapbook file name
$scrapbook_end = "SCRAPBOOK_END"; # set this to scrapbook end anchor name

$file = "$file_prefix$scrapbook";
$end_tag = "<a name=\"$scrapbook_end\"></a>";  # HTML marker near end of scrapbook file
$qs = $ENV{'QUERY_STRING'};

# parse query string, decode, store variables
my ($item, %item);
foreach $_ (split(/&/, $qs)) {
	s/\+/ /g;
	s/\%([A-Fa-f0-9]{2})/pack('C', hex($1))/eg;
	($_, $item) = split (/=/, $_, 2);
	$item{$_} = $item;
}

# change all newlines in selected text into <br> tags
$item{"Y"} =~ s/\n/\<br\>/g;

# assemble new scrapbook item: HTML link to source document, selected text, and divider line
$new_scrap = "<a href=$item{'X'}>$item{'X'}</a><br>\n$item{'Y'}<br>\n<hr>\n";

open(F, "$file");
$body = <F>;
close(F);

# put new scrapbook item into scrapbook page just before the SCRAPBOOK_END tag
$body =~ s/$end_tag/$new_scrap$end_tag/;

open(F, ">$file");
print F $body;
close(F);

# redirect browser to display end of scrapbook page
print "Content-type: text/html\n\n";
print "<head><meta http-equiv=\"Refresh\" content=\"0; url=$domain/$scrapbook#$scrapbook_end\"></head>";

To make the scrapbook page display nicely, you can begin it with something like this, customized of course for your own domain:

<!DOCTYPE html PUBLIC "-//W3C//DTD HTML 4.01 Transitional//EN"
     "http://www.w3.org/TR/html4/loose.dtd">
<html>
<head>
<meta http-equiv="Content-Type" content="text/html; charset=utf-8">
<title>SCRAPBOOK</title>
<style type="text/css">@import "zhurnaly.css";</style>
</head>
<body>
Scrapbook for accumulating URLs and short selections (^_^)
<hr>
<a name="SCRAPBOOK_END"></a>
</body>
</html>

If you find this at all interesting please let me know — and especially suggest improvements and new features (and how to implement them, if you're really enthusiastic). Tnx!

^z - 2010-12-26

I like this!