[sword-devel] Re: Sword Web Interface!

John Keiser sword-devel@crosswire.org
22 Jul 2001 02:45:21 -0400


--=-bMIdz5xZzjQ6Qkx/GGfy
Content-Type: text/plain

Coupla small fixes attached.  It was coloring always on browse and Revelation 22 went into an infinite loop.

--John


On 22 Jul 2001 02:12:15 -0400, John Keiser wrote:
> Well, all this Perl stuff has come to fruition.  I have completed a
> fairly nice-looking Web interface to Sword that allows you to search and
> compare multiple translations (kind of slow because it actually performs
> the search in every translation) and browse chapter by chapter.  Search
> terms are highlighted even in browse.  You can enter arbitrary
> book/chapter/verse ranges and it will display everything.
> 
> And it works with mod_perl, so SWMgr should be staying around!!  I'll
> have to check whether it actually is sometime, but mod_perl is supposed
> to do something like that.
> 
> I have attached the CGI script as well as the image.  All you need is
> to:
> - install sword, some Bible modules and the Sword-0.3 package I sent
> earlier
> - put the script in cgi-bin or mod_perl dir somewhere
> - make it executable
> - put the image somewhere
> - set the image_dir (at the top of the script) to where the image is
> (from the web--if it's in your docroot)
> 
> Or to try it out, go here:
> http://cy209696-a.cospgs1.co.home.com/~john/perl/sword.pl
> (If name resolution doesn't work:)
> http://24.253.114.106/~john/perl/sword.pl
> 
> Please don't pound my poor little box too hard though :)
> 
> --John
> 

--=-bMIdz5xZzjQ6Qkx/GGfy
Content-Type: text/x-perl
Content-Disposition: attachment; filename=sword.pl
Content-ID: 995784319.16985.1.camel@cy209696-a
Content-Transfer-Encoding: 7bit

#!/usr/bin/perl

use strict;

use Sword;
use CGI;

# CONFIG
my $image_dir="/~john/sword";

my $p = new CGI;

print $p->header;
print <<"EOM";
<HEAD>
<TITLE>Sword Bible Interface</TITLE>
</HEAD>
<BODY BGCOLOR=lightgray>
<CENTER><A HREF=sword.pl><IMG BORDER=0 SRC="$image_dir/sword_web.gif"></A></CENTER>
EOM

sub next_chapter {
	my ($mod, $book, $chap) = @_;

	if($chap >= $mod->get_num_chapters($book)) {
		my @books = $mod->get_books;
		my $book_num = $mod->{BOOKS}{$book}{real_book_num};
		if($book_num == (@books - 1)) {
			return "";
		} else {
			return $books[$book_num + 1] . " 1";
		}
	} else {
		return "$book " . ($chap+1);
	}
}

sub prev_chapter {
	my ($mod, $book, $chap) = @_;

	if($chap <= 1) {
		my @books = $mod->get_books;
		my $book_num = $mod->{BOOKS}{$book}{real_book_num};
		if($book_num == 0) {
			return "";
		} else {
			return $books[$book_num - 1] . " " . $mod->get_num_chapters($book);
		}
	} else {
		return "$book " . ($chap-1);
	}
}

sub print_verse_range {
	my ($p, $mods, @range) = @_;

	my @mods = @{$mods};
	my $search = $p->param("search");

	#
	# Print header
	#
	print "<TABLE BORDER=1>\n";
	print "<TR>\n";
	print "<TD>&nbsp;</TD>\n";
	
	foreach my $mod (@mods) {
		print "<TH>", $mod->get_name(), "</TH>\n";
	}

	print "</TR>\n";
	
	#
	# Set up loop
	#

	my @vis;
	foreach my $mod (@mods) {
		push @vis, $mod->get_iterator();
	}
	my $prev_book;
	my $prev_chapter;

	my $result_ind = 0;
	my ($result_low, $result_high) = Sword::Module::_as_verse_range($range[$result_ind]);
	foreach my $vi (@vis) {
		$vi->go_to_verse($result_low);
	}

	do {
		if($vis[0]->get_book ne $prev_book || $vis[0]->get_chapter_num != $prev_chapter) {
			$prev_book = $vis[0]->get_book;
			$prev_chapter = $vis[0]->get_chapter_num;
			my $q = new CGI($p);
			my $chap = prev_chapter($mods[0], $vis[0]->get_book, $vis[0]->get_chapter_num);
			$q->param("browse", $chap);
			my $prev_url = $q->self_url if $chap;
			$chap = next_chapter($mods[0], $vis[0]->get_book, $vis[0]->get_chapter_num);
			$q->param("browse", $chap);
			my $next_url = $q->self_url if $chap;
			$chap = $vis[0]->get_book . " " . $vis[0]->get_chapter_num;
			$q->param("browse", ($vis[0]->get_book . " " . $vis[0]->get_chapter_num));
			my $chap_url = $q->self_url if $chap;;

			print "<TR>\n";
			print "<TD colspan=", (@vis + 1), "><CENTER><B>";

			if($prev_url) {
				print "<A HREF='$prev_url'>&lt;&lt;</A>&nbsp;&nbsp;";
			}
			if($chap_url) {
				print "<A HREF='$chap_url'>$prev_book $prev_chapter</A>";
			}
			if($next_url) {
				print "&nbsp;&nbsp;<A HREF='$next_url'>&gt;&gt;</A>";
			}
			print "</B></CENTER></TD>\n";
			print "</TR>\n";
		}
		print "<TR>\n";
		print "<TH>", $vis[0]->get_key, "</TH>\n";
		foreach my $vi (@vis) {
			my $verse = $vi->get_verse;
			if($search && $verse =~ s/($search)/<B><I>$1<\/I><\/B>/g) {
				print "<TD BGCOLOR=green>$verse</TD>\n";
			} else {
				print "<TD>$verse</TD>\n";
			}
		}
		print "</TR>\n";

		my $is_last_verse = 0;
		foreach my $vi (@vis) {
			$is_last_verse = 1 if ! $vi->next;
		}
		if($is_last_verse || $mods[0]->verse_greater($vis[0]->get_key(), $result_high)) {
			$result_ind++;
			last if $result_ind >= @range;
			($result_low, $result_high) = Sword::Module::_as_verse_range($range[$result_ind]);
			foreach my $vi (@vis) {
				$vi->go_to_verse($result_low);
			}
		}
	} while($result_ind < @range);

	#
	# Print footer
	#
	print "</TABLE>\n";
}


if($p->param("browse")) {
	my @mod_names = $p->param("mod_name");
	my @mods;
	foreach my $mod_name (@mod_names) {
		my $mod = Sword::get_module($mod_name);
		push @mods, $mod;
	}
	my @verse_range = $mods[0]->parse_verse_range($p->param("browse"), 0, 1);
	print_verse_range $p, \@mods, @verse_range;
} elsif($p->param("search")) {
	my @mod_names = $p->param("mod_name");
	my @search_results;
	my @mods;

	foreach my $mod_name (@mod_names) {
		my $mod = Sword::get_module($mod_name);
		push @mods, $mod;
		my @sr = $mod->search_verses($p->param("search"));
		@search_results = $mod->union_verse_list(\@search_results, \@sr);
	}

	if(!@search_results) {
		print "<H2><FONT COLOR=red>I'm afraid your search didn't turn up anything.  Try again, better luck!</FONT></H2>\n";
	} else {
		print_verse_range $p, \@mods, @search_results;
	}
} else {
# MAIN FORM
	print qq^
<CENTER>
<H2>Search/Browse</H2>

<FORM METHOD=get NAME=mainform>
<TABLE>
<TR>
<TD COLSPAN=2><CENTER>Enter a list of books/chapters and verses you want to look up<BR>
(Enter nothing to perform a normal search.)</CENTER></TD>
</TR>
<TR>
<TD><B>Books/Chapters:</B><BR>
(i.e. Acts 17-18;John 3:16)</TD>
<TD><INPUT TYPE=text NAME=browse></TD>
</TR>
<TR>
<TD COLSPAN=2><CENTER>Enter a search term or a verse you wish to lookup<BR>
(enter a book/chapter to browse and highlight searched terms):</CENTER></TD>
</TR>
<TR>
<TD><B>Search/Verse:</B></TD>
<TD><INPUT TYPE=text NAME=search></TD>
</TR>
<TD>Choose modules:</TD>
<TD>
<SELECT MULTIPLE NAME=mod_name>
^;
	my $first_one = 1;
	foreach my $mod_name (Sword::get_modules) {
		if($first_one) {
			print qq^<OPTION SELECTED VALUE="$mod_name">$mod_name</OPTION>
^;
			$first_one = 0;
		} else {
			print qq^<OPTION VALUE="$mod_name">$mod_name</OPTION>
^;
		}
	}

	print qq^</SELECT>
</TD>
</TR>
<TR>
<TD COLSPAN=2><INPUT TYPE=submit></TD>
</TR>
</TABLE>
</FORM>

</CENTER>
^;
}

print << "EOM";
<BR>
<BR>
<CENTER><ADDRESS><A HREF="http://www.johnkeiser.com">John Keiser</A> was here!  This stuff is under the <A HREF="http://www.gnu.org/copyleft/gpl.html">GPL</A>.  Copyleft (C) 2001.</ADDRESS></CENTER>
</BODY>
</HTML>
EOM


--=-bMIdz5xZzjQ6Qkx/GGfy--