Main Page Content
Give The User Control Over Your Fonts With Perl
The Basic Idea
Exactly as with Adrian's original, it comes in three parts:- Check to see if the browser will do CSS. If so, set a cookie saying so (so we don't have to check again).
- Check to see if the user has requested a non-default size. If so, set a cookie registering this preference.
- Using the cookies, deliver an appropriate stylesheet, chosen from small, medium and large, and query-string encoded links to the alternative sized-versions of the same page.
The Code
Set the cookies
One problem which Perl/Apache SSIs have is that cookies have to be sent with the HTTP headers. However, SSIs aren't interpreted until after these have been sent for the page you're building with SSI. Therefore, throwing the cookies out by putting them in normal SSIs as ASP does:Response.Cookies("TextSize") = "Normal"
won't work. Which is a shame. However, you can set cookies with any files you send as page elements, like images. And Perl/CGI can send images just as well as it can text. Solution: Send a dummy 1px image (say your normal transparent pixel) from a CGI with the cookie(s) in its HTTP headers.. Which is exactly what the following script does. It:- Checks to see if the browser is CSS-compatible. This is basically IE or NS 4+, and Opera as well - note that if IE6 doesn't report itself as IE5, then you will need to edit this script. NS6 pretends to be NS5, so we're OK on that score. I've also specifically excluded browsers such as iCab and Lynx, which allow users to choose to use UA strings which claim version4/5 compatibility. They also allow users to make up their own, but that's another issue.
- Checks to see if there is a querystring of the form:
textsize=something
- Sets cookies appropriately for each of the above by delivering an image content-type with cookie headers.
#!/usr/bin/perl############################################################################### font_cookie.cgi Version 1.0 ## Copyright 2000 Martin Burns scripts@easyweb.co.uk ## based on ASP code by Adrian Roselli ## Created 21/9/00 Last Modified 21/9/00 ################################################################################ COPYRIGHT NOTICE ## Copyright [and -left] 1999-2000 Martin Burns and Adrian Roselli. ## All Rights Reserved except as provided below. ## ## font_cookie.cgi may be used and modified free of charge by anyone so long ## as this copyright notice and the comments above remain intact. By using ## this code you agree to indemnify Martin Burns, EasyWeb Design and Adrian ## Roselli from any liability that might arise from its use. # # ## This script is released under the GPL. ## Selling the code for this program or any derivative work is expressly ## forbidden. A full copy of the GPL can be found in the Code section of ## http://evolt.org. In all cases copyright and this header must remain ## intact. ################################################################################# ASP Code by Adrian Roselli from http://roselli.org## Provided free for evolt.org and its members.## No catches, just give me credit.## This browser detection only detects IE4.x and## NN4.x, please modify it as you see fit to get## the 5.x and alternate manufacturer CSS-capable## browsers.## Last change July 10, 1999The way you get this onto your page is by pretending it's a standard image:############################################################################
# Set some variables ##############################################################################Testing:#use diagnostics;#$ENV{'QUERY_STRING'} = 'textsize=larger';#$ENV{'HTTP_USER_AGENT'} = 'Mozilla/4.0'; #(compatible; MSIE 5.5; Windows98)#$ENV{'SERVER_NAME'} = 'www.easyweb.co.uk';#$ENV{'HTTP_COOKIE'} = 'browser=css';## Get the browser name and version number$USERAGENT = $ENV{'HTTP_USER_AGENT'};##initialise other vars
#%in="";#%cookie="";$REQUIRE_DIR = '/full/path/to/dir/with/subroutines/like/your/cgi-bin/';$YES=1;$NO=0;$CSS=$NO;############################################################################# Get Required subroutines which need to be included. ############################################################################## Push the $REQUIRE_DIR onto the @INC array for include file directories.
if ($REQUIRE_DIR ne '') {
push(@INC, $REQUIRE_DIR);}# Require Necessary Routines for this script to run.
require 'cgi-lib.pl'; #ye olde faithful########################
## Browser Determination ## Check the UserAgent string to see## if it contains Mozilla or MSIE, and then## to see if it has 4. or 5. in the version number## or alternatively is Operaif ( ((($USERAGENT =~ /mozilla/i) ($USERAGENT =~ /msie/i)) && (($USERAGENT =~ /4./) ($USERAGENT =~ /5./))) ($USERAGENT =~ /opera/i)) { $CSS=$YES;}##Cut out sneaky ones like iCab which allow users to set the UA string
@sneakybrowsers = ( 'icab', 'lynx');foreach $browser (@sneakybrowsers) { if ($USERAGENT =~ /$browser/i) {$CSS = $NO}}## If the cookie Browser has no value,
## then perform the followingif (($ENV{'HTTP_COOKIE'} !~ /browser=/i) && ($CSS)) { ## Sets a variable for the cookie so that the ## browser is marked as CSS-capable $cookie{'browser'} = 'css';}################
## Set Text Size## If the URL does not have a ?size=value
## appended to it (meaning the user clicked## one of the links), then perform the following#if (!&ReadParse) {# print &PrintHeader, "<!-- script parse error ($!)-->";#}&ReadParse;if (($in{'textsize'}) && ($CSS)) { $cookie{'textsize'} = $in{'textsize'}; #testing #print $cookie{'textsize'}} ################## Start the headersprint "Content-Type: text/html";################
## Output the cookiesif ((%cookie) && ($CSS)) {foreach $variable (keys %cookie) {
$cookie_var = $cookie{"$variable"}; print "Set-Cookie: $variable=$cookie_var\; domain=$ENV{'SERVER_NAME'}\; path=\/\;"; }}###############
## Output the image## if you want to force the image not to be cached$pragma='Pragma: no-cache';$expires='Expires: Wed, 26 Feb 1997 08:21:57 GMT'; #ie in the past$tmpfile="/full/path/to/your/public_html/resources/transparent.gif";
open( FROM, "< $tmpfile" );binmode FROM;binmode STDOUT;# Print out the contents of the image file.
print "Content-type: image/gif";print $expires,"";print $pragma,"";print "";while (<FROM>) {
print $_; }close FROM;
################# End the headersprint "";
<img src="/cgi-bin/font_cookie.cgi?<!--#ECHO VAR="QUERY_STRING"-->" height="1" width="1" alt="" />
(The <!--#ECHO VAR="QUERY_STRING"-->
bit just makes sure that any query strings applied to the page get passed to the CGI. This will principally be textsize=something
.) The only downside to getting the cookies out like this is that a cookie won't be available to the rest of your script until after the first page the user hits on your site - users will only be able to choose their font size from the second page they visit.Choose a size
Obviously, the simple way to give the users choice over which size of fonts they are to receive is to put a bunch of SSI links on the page like this:<a href="<!--#ECHO VAR="DOCUMENT_URI"-->?textsize=large"<Large fonts</a><a href="<!--#ECHO VAR="DOCUMENT_URI"-->?textsize=normal"<Medium fonts</a><a href="<!--#ECHO VAR="DOCUMENT_URI"-->?textsize=small"<Small fonts</a>
But then the user has to know what size they have at present, and develop a mental model for your font calibration. It's also a bit silly to give the choice of the current size, as it won't do anything! A much more elegant solution is to only give relative choices of larger or smaller than the present size. This means that when you're at the smallest size, you only give the choice of 'Larger', and when you're at the largest size, you only give the choice of 'Smaller'. What this script does is the logic behind that, working out the current size and only delivering appropriate choices which users can instinctively grasp.############################################################################### cssResize - css_resize.cgi Version 1.0 ## Copyright 2000 Martin Burns scripts@easyweb.co.uk ## based on ASP code by Adrian Roselli ## Created 21/9/00 Last Modified 21/9/00 ################################################################################ COPYRIGHT NOTICE ## Copyright [and -left] 1999-2000 Martin Burns and Adrian Roselli. ## All Rights Reserved except as provided below. ## ## cssResize may be used and modified free of charge by anyone so long ## as this copyright notice and the comments above remain intact. By using ## this code you agree to indemnify Martin Burns, EasyWeb Design and Adrian ## Roselli from any liability that might arise from its use. # # ## This script is released under the GPL. ## Selling the code for this program or any derivative work is expressly ## forbidden. A full copy of the GPL can be found in the Code section of ## http://evolt.org. In all cases copyright and this header must remain ## intact. ################################################################################# Code by Adrian Roselli from http://roselli.org
## Provided free for evolt.org and its members.## No catches, just give me credit.## Make sure you supply your own images, rollovers,## whatever. These are just suggestions, especially## since text links are not always attractive.## Last change July 10, 1999## Request the cookie Browser and see if it is a
## CSS-capable browser, based on your previous work.## This ensures that you do not display the buttons## if the browser cannot use them.#Testing
#use diagnostics;##Set a variable or two
#testing#$ENV{'HTTP_COOKIE'} = 'textsize=small';#$ENV{'QUERY_STRING'} = 'textsize=large';$USER_AGENT = $ENV{'HTTP_USER_AGENT'};require 'cgi-lib.pl';&ReadParse;%size = ('large', '', 'normal', '', 'small', '');#Testing
#$ENV{'HTTP_COOKIE'} = 'textsize=normal; browser=css';#$ENV{'HTTP_COOKIE'} = 'browser=css';#$ENV{'DOCUMENT_URI'} = '/cv/index2.html';if ($ENV{'HTTP_COOKIE'} =~ /browser=css/i) { $PAGE = $ENV{'DOCUMENT_URI'}; if ($ENV{'HTTP_COOKIE'} =~ /textsize=(large small normal)/i) { $textsize=$1; } elsif ($USER_AGENT =~ /windows/i) {
$textsize='small'; } else {$textsize='normal'}
##Check for query strings if ($in{'textsize'}) { $textsize = $in{'textsize'}; } $size{$textsize}='yes';
# print "$textsize"; ###########
## Output the start of the block - YMMV print qq <h4 class="css_swap">Text not right?</h4> ; print qq <p class="css_swap"> ; if ($size{"large"}) { ## If the text is set to large, offer the option to reduce to normal print qq <a href="$PAGE?textsize=normal">Reduce Text</a> ; } elsif ($size{"small"}) { ## If the text is set to small, offer the option to enlarge to normal print qq <a href="$PAGE?textsize=normal">Enlarge Text</a> ; } else { ## If the text is normal, offer the option to enlarge or reduce print qq <a href="$PAGE?textsize=large">Enlarge Text</a><br /> ; print qq <a href="$PAGE?textsize=small">Reduce Text</a><br /> ; ###########
## Output the end of the block - YMMV print q </p> ; }
} else { print "<!--No variation for you, sorry-->";}print "";
Interesting sidenote:You bring this into your page at the point where you want the options to appear with a standard SSI exec call:
I've made the code more readable by using the Perlq
and
<!--#exec cmd="/full/path/to/your/cgi-bin/css_resize.cgi"-->
Deliver the stylesheet
The last thing we need to do is to deliver the appropriate stylesheet, either the one chosen by the user, or a sensible default where the user either thinks that the basic size is OK, or (on that vital first page before the cookie is set) hasn't yet seen the options. I've set it up such that Windows machines get the small size as default, and Macs, Unix boxen etc get the normal (middle) size. Naturally, this will depend on how you set up the fonts in your stylesheets. In mine, the normal body text is set as follows:- Large: 12pt
- Normal: 11pt
- Small: 10pt
<link rel="stylesheet" href="/resources/large.css">
<link rel="stylesheet" href="/resources/normal.css">
<link rel="stylesheet" href="/resources/small.css">
And here's the code to deliver it:#!/usr/bin/perl############################################################################### cssSwap - css_swap.cgi Version 1.0 ## Copyright 2000 Martin Burns scripts@easyweb.co.uk ## based on ASP code by Adrian Roselli ## Created 21/9/00 Last Modified 21/9/00 ################################################################################ COPYRIGHT NOTICE ## Copyright [and -left] 1999-2000 Martin Burns and Adrian Roselli. ## All Rights Reserved except as provided below. ## ## cssSwap may be used and modified free of charge by anyone so long ## as this copyright notice and the comments above remain intact. By using ## this code you agree to indemnify Martin Burns, EasyWeb Design and Adrian ## Roselli from any liability that might arise from its use. # # ## This script is released under the GPL. ## Selling the code for this program or any derivative work is expressly ## forbidden. A full copy of the GPL can be found in the Code section of ## http://evolt.org. In all cases copyright and this header must remain ## intact. ################################################################################# Code by Adrian Roselli from http://roselli.org## Provided free for evolt.org and its members.## No catches, just give me credit.## Make sure you point to the right style sheets.## Last change July 10, 1999##Set a variable or two
#testing#$ENV{'HTTP_COOKIE'} = 'textsize=small';require 'cgi-lib.pl';$size='';$stylesheet_ref='<link rel="stylesheet" href="/resources/';$USER_AGENT=$ENV{'HTTP_USER_AGENT'};## Iterate through the size options, with
## a default if there are no matches.if ($ENV{'HTTP_COOKIE'} =~ /textsize=(large small normal)/i) {
$size=$1;} elsif ($USER_AGENT =~ /windows/i) { $size='small';} else {$size='normal'} ################
## Check for query string vars## If the URL does not have a ?size=value
## appended to it (meaning the user clicked## one of the links), then perform the following#if (!&ReadParse) {# print &PrintHeader, "<!-- script parse error ($!)-->";#}&ReadParse;if ($in{'textsize'}) { $size = $in{'textsize'}; #testing #print $cookie{'textsize'}} #&PrintHeader;
#print $ENV{'QUERY_STRING'};print $stylesheet_ref.$size.".css\" \/>";
#print $ENV{'HTTP_COOKIE'};
And once again, you bring this into your page (in the <head>
section of course) with an SSI exec call: <!--#exec cmd="/full/path/to/your/cgi-bin/css_swap.cgi"-->