CAMWEST: Cyclists’ Action Movement West

Website Changes

Martin Olmos started this web site back around 2000, and we all agree he did a great job. It has been very hard to step into his shoes. He used Macromedia Dreamweaver as his main tool for editing the site. He has moved from Sydney to do even greater things.

Nick Urbanik has now tried to step into his shoes. Nick has a 19" monitor with 1920 pixels across. At that resolution, a table-based design fixed at 646 pixels results in a narrow strip of text surrounded by empty screen. Now Nick does not like that, so he resolved to change the original table-based layout of the web site to use a design that uses CSS positioning that can use the entire width of the web browser at any resolution.

He also resolved to use non-proprietary, standards conforming valid XHTML and CSS. The result makes the HTML much smaller and simpler than before, so also much easier to edit.

The site was built using GNU's web production tool Emacs  :-).

(Technical note: the program Nick wrote to convert the site.)

Valid XHTML 1.0! Powered by GNU Made with Emacs Viewable With Any Browser

The Menus and IE 5

Not content with that, Nick decided to inflict a menu system on you all. Unfortunately, it jumped around in Internet Explorer 5.0 until Holly Bergevin explained how to fix it. Now it works on IE5, IE5.5 and IE6, and all the other browsers I have tested, including Safari on a Mac, Firefox, Konqueror, Opera 9.

It should also display properly on Netscape 4.x and other older browsers, and also on hand-held devices, and should be accessible by screen readers for people with sight problems, such as Jaws.

Please let me know if this web site is not accessible to you.

Now this web site is best viewed with Any Browser. Viewable With Any Browser

Printing

We have a print style sheet — that means, if you print any page on this site, it should print with proper margins, and without the sidebars and menus, automatically. Please let me know if this doesn't work for your browser/printer.

#!/usr/bin/perl -Tw ############################################# # show-comments.pl # # Allows for the display of # comments to a Web page from site visitors. # ############################################# use strict; use CGI (); use POSIX (); use Digest::MD5 qw(md5_hex); use Fcntl qw(:DEFAULT :flock); use Apache2::Reload; use lib qw(/home/camwest/comments/lib); use Comments qw(:all); #use CommentCaptchas (); #use CommentVisitors (); use constant MAX_AGE => 60 * 24 * 60 * 60; # 60 days worth of seconds. #################### # main script body #################### # retrieve and validate configuration settings my $config = get_configuration(); # some CGI DoS protections $CGI::POST_MAX = $config->{'max_comment_chars'}+5000; $CGI::DISABLE_UPLOADS = 1; # initialize CGI object my $cgi = CGI->new(); # validate program branch my @all_actions = qw(rss display); my $valid_actions = join('|', @all_actions); my $branch = ($cgi->param('action') || 'display'); $branch = 'invalid_action' unless ($branch =~ /^($valid_actions)$/i); # condense the configurations, based on this article's section $config = condense_configs($config, get_section(($cgi->param('article_key') || $ENV{'DOCUMENT_URI'}), $config)); print $branch eq 'rss' ? $cgi->header(-type => 'text/xml; charset=utf-8') : $cgi->header(); my $captcha = q{}; # main program branch display_comments($cgi, $config, $captcha) if ($branch =~ /^display$/i); rss_comments($cgi, $config, $captcha) if ($branch =~ /^rss$/i); invalid_action($cgi, $config, $captcha) if ($branch =~ /^invalid_action$/i); #################### # end main script #################### ############################################## # subroutines ############################################## ############################################## # display_comments # # Displays the approved comments for the # selected article # sub display_comments { my ($cgi, $config, $captcha) = @_; my $article_key = get_article_key($config, $cgi, $ENV{'DOCUMENT_URI'}); my $article_comments = get_article_comments($config, $article_key); my @comments = $article_comments ? @{$article_comments} : (); # the next call adds the 'sort_key' to the comment hashes @comments = @{sort_comments($config,\@comments)}; # passed in from the caller, if necessary my $start_comment = 0; $cgi->param('start_comment') and ($cgi->param('start_comment') =~ /^(\d+)$/) and ($start_comment = $1); $start_comment = 0 if ($start_comment > scalar(@comments)); my $previous_comment = $start_comment - $config->{'comments_per_page'}; $previous_comment = 0 unless ($previous_comment > 0); my $template = get_template($config, $config->{'display_comment_list_template'}); my $article_key_format = key_to_document($article_key); my $edit_profile_link = q{}; if ($config->{'visitor_registration_enabled'} && $cgi->param('logged_in')) { my $visitor = $cgi->param('visitor_record'); $edit_profile_link = $config->{'add_comment_script'} . '?action=register_profile&article_key=' . $article_key_format; } my $comments_processed = 0; my @comment_page_loop = (); my $now = time; foreach my $comment_hash (@comments) { $comments_processed++; next unless ($comments_processed > $start_comment); # Don't show comments older than MAX_AGE: next if $now - $comment_hash->{edit_date} > MAX_AGE; (my $reply_to = get_comment_key($comment_hash)) =~ s/^.*\-//; $reply_to = $comment_hash->{'reply_to'} . '-' . $reply_to if exists $comment_hash->{'reply_to'} && $comment_hash->{'reply_to'}; my $thread_level = $comment_hash->{'sort_key'} ? length($comment_hash->{'sort_key'}) / 6 : 1; my $comment_number = exists($comment_hash->{'sequence_id'}) ? ($comment_hash->{'sequence_id'} + 1) : q{}; # Setup the visitor profile link for this submitter, # if one exists and the feature is enabled my $view_profile_link = q{}; if ($config->{visitor_registration_enabled}) { my $visitor = CommentVisitors->get( 'email_address' => $comment_hash->{user_email}, 'directory' => $config->{visitor_profile_directory} ); if ($visitor && $visitor->exists && ($visitor->status ne 'new') && ($visitor->status ne 'pending')) { $view_profile_link = $config->{visitor_profile_link} . '?action=view_profile' . '&article_key=' . $article_key_format . '&visitor_id=' . $visitor->user_id; $comment_hash->{user_name} = $visitor->display_name; $comment_hash->{user_url} = $visitor->home_page; $comment_hash->{visitor_status} = $visitor->status; $comment_hash->{post_count} = $visitor->post_count; $comment_hash->{is_logged_in_visitor} = ($cgi->param('logged_in') && ($cgi->param('logged_in') eq $visitor->email_address)) ? 1 : 0; } } push @comment_page_loop, { edited_by => $comment_hash->{edited_by}, edit_date => format_date($config, $comment_hash->{edit_date}), approved_by => $comment_hash->{approved_by}, show_comment_script => $config->{show_comment_script}, add_comment_script => $config->{add_comment_script}, pub_date => format_date($config, $comment_hash->{pub_date}), reply_href => $config->{add_comment_script} . '?article_key=' . $article_key_format . '&action=submit&reply_to=' . $reply_to, reply_to => $reply_to, is_reply_to => $comment_hash->{reply_to} || q{}, article_key => $article_key_format, thread_level => $thread_level, 'threadlevel' . $thread_level => 1, comment_number => $comment_number, admin_flag => $comment_hash->{admin_flag} ? 1 : 0, visitor_registration_enabled => $config->{visitor_registration_enabled} ? 1 : 0, is_logged_in_visitor => $comment_hash->{is_logged_in_visitor} || q{}, posts => $comment_hash->{post_count} || 0, view_profile_link => $view_profile_link || q{}, edit_profile_link => $edit_profile_link || q{}, status => $comment_hash->{visitor_status} || q{}, format_name => $comment_hash->{user_name} || q{}, format_email => $comment_hash->{user_email} || q{}, format_url => $comment_hash->{user_url} || q{}, format_date => format_date($config, $comment_hash->{submit_date}), format_subj => xml_to_comment($comment_hash->{user_subj}, $config), format_text => xml_to_comment($comment_hash->{user_text}, $config) }; last if (@comment_page_loop >= $config->{comments_per_page}); } $comments_processed = 0 if ($comments_processed >= @comments); # Setup view profile link for logged in user my $view_profile_link = q{}; if ($cgi->param('logged_in')) { my $visitor = $cgi->param('visitor_record'); $view_profile_link = $config->{'visitor_profile_link'} . '?action=view_profile' . '&article_key=' . $article_key_format . '&visitor_id=' . $visitor->user_id; } $template->param( comment_loop => \@comment_page_loop, article_key => $article_key_format, next_comment => $comments_processed, start_comment => $start_comment, previous_comment => $previous_comment, previous_href => (($start_comment) ? $article_key_format . '?start_comment=' . $previous_comment : q{}), next_href => (($comments_processed) ? $article_key_format . '?start_comment=' . $comments_processed : q{}), logged_in => $cgi->param('logged_in') || q{}, visitor_registration_enabled => $config->{visitor_registration_enabled} ? 1 : 0, visitor_registration_required => $config->{visitor_registration_required} ? 1 : 0, publish_on_submit => $config->{publish_on_submit} ? 1 : 0, edit_profile_link => $edit_profile_link || q{}, user_name => $cgi->param('user_name') || q{}, user_email => $cgi->param('user_email') || q{}, user_url => $cgi->param('user_url') || q{}, user_text => q{}, user_subj => q{}, reply_to => q{}, reply_name => q{}, reply_date => q{}, reply_subj => q{}, captcha_enabled => $config->{captcha_enabled}, captcha_word => q{}, captcha_hash => ($captcha) ? $captcha->hash : q{}, captcha_img => ($captcha) ? $captcha->image_url : q{}, captcha_mp3 => ($captcha) ? $captcha->audio_url : q{}, use_recaptcha => $captcha ? ($captcha->captcha_system eq 'recaptcha') : q{}, recaptcha_use_javascript => $config->{recaptcha_use_javascript} || q{}, recaptcha_theme => $config->{recaptcha_theme} || q{}, recaptcha_tabindex => $config->{recaptcha_tabindex} || 0, recaptcha_public_key => $config->{recaptcha_public_key} || q{}, recaptcha_error => $captcha ? ($captcha->recaptcha_error || q{}) : q{}, max_comment_chars => $config->{max_comment_chars}, max_subject_chars => $config->{max_subject_chars}, article_name => get_article_name($config,$article_key), view_profile_link => $view_profile_link, profile_login_link => $config->{add_comment_script} . '?article_key=' . $article_key_format . '&action=profile_login', profile_logout_link => $config->{add_comment_script} . '?article_key=' . $article_key_format . '&action=profile_logout', register_profile_link => $config->{add_comment_script} . '?article_key=' . $article_key_format . '&action=register_profile', add_comment_script => $config->{add_comment_script}, show_comment_script => $config->{show_comment_script}, ); print $template->output; } # # end display_comments ############################################## ############################################## # rss_comments # # Displays approved comments as an RSS feed # (or whatever format the "rss_template" happens # to be. Always sorted in date order (most # recent first) here. # sub rss_comments { my ($cgi, $config, $captcha) = @_; my $article_key = get_article_key($config, $cgi, $ENV{DOCUMENT_URI}); my $article_name = get_article_name($config,$article_key); my $article_comments = get_article_comments($config, $article_key); my @comments = $article_comments ? @{$article_comments} : (); $article_key = key_to_document($article_key); $article_name = comment_to_xml($article_name, $config); $article_name =~ s/\&(g|l)t\;/\&\;$1t\;/g; $article_name =~ s/\[/\<\;/g; $article_name =~ s/\]/\>\;/g; # always sort in reverse date order here @comments = sort {$b->{submit_date} <=> $a->{submit_date}} @comments; # load template my $template = get_template($config, $config->{rss_template}); # build main comment loop my @comment_loop = (); my $feed_pub_date = 0; my $feed_build_date = 0; my $comments_added = 0; my $feed_link = $cgi->url(-base=>1) . $article_key; foreach my $comment_hash (@comments) { if ($comments_added < $config->{comments_per_rss}) { # Setup the visitor profile if ($config->{visitor_registration_enabled}) { my $visitor = CommentVisitors->get( email_address => $comment_hash->{user_email}, directory => $config->{visitor_profile_directory} ); if ($visitor && $visitor->exists) { $comment_hash->{user_name} = $visitor->display_name; $comment_hash->{user_url} = $visitor->home_page; $comment_hash->{user_email} = $visitor->email_address; } } foreach (qw(user_text user_subj)) { next unless $comment_hash->{$_}; $comment_hash->{$_} =~ s/\&(g|l)t\;/\&\;$1t\;/g; $comment_hash->{$_} =~ s/\[/\<\;/g; $comment_hash->{$_} =~ s/\]/\>\;/g; } my $comment_number = exists($comment_hash->{sequence_id}) ? ($comment_hash->{sequence_id} + 1) : q{}; push @comment_loop, { feed_link => $feed_link, comment_number => $comment_number, user_text => $comment_hash->{user_text}, comment_pubdate => POSIX::strftime('%a, %d %b %Y %T GMT', gmtime($comment_hash->{pub_date})), comment_submitdate => POSIX::strftime('%a, %d %b %Y %T GMT', gmtime($comment_hash->{submit_date})), comment_editdate => POSIX::strftime('%a, %d %b %Y %T GMT', gmtime($comment_hash->{edit_date})), user_name => $comment_hash->{user_name} || q{}, user_email => $comment_hash->{user_email} || q{}, user_url => $comment_hash->{user_url} || q{}, user_subj => $comment_hash->{user_subj} || q{}, }; $comments_added++; } $feed_pub_date = $comment_hash->{pub_date}; $feed_build_date = $comment_hash->{pub_date} unless ($feed_build_date); } $template->param( comment_loop => \@comment_loop, feed_link => $feed_link, feed_pubdate => POSIX::strftime('%a, %d %b %Y %T GMT', gmtime($feed_pub_date)), feed_builddate => POSIX::strftime('%a, %d %b %Y %T GMT', gmtime($feed_build_date)), article_key => $article_key, article_name => $article_name, admin_name => $config->{admin_name}, admin_email => $config->{admin_email}, version => $Comments::VERSION, ); print $template->output; } # # end rss_comments ############################################## ############################################## # invalid_action # # We come here if the user submits an invalid # action code or if the action is invalid for # some other reason (for example, a profile # related action when visitor registrations # are disabled). # sub invalid_action { my ($cgi, $config, $captcha) = @_; my $article_key = get_article_key($config, $cgi, $ENV{DOCUMENT_URI}); # Retrieve the display template my $template = get_template($config, $config->{invalid_action_template}); $template->param( show_comment_script => $config->{show_comment_script}, add_comment_script => $config->{add_comment_script}, article_key => key_to_document($article_key), ); print $template->output; } # # end invalid_action ##############################################

Contact Us

contact (AT) camwest.pps.com.au

Coming Rides

Articles

Home | About Us | Projects | News | Rides | Advocacy | Links