The Hello Friends example can be extended to produce a phone list.
The simplest approach is to list each person in a separate
<P>
(paragraph).
These paragraphs can be appended to the contents of an
HtmlDocument derived class.
The default mainBody method renders the accumulated document contents.
import crawdad class PhoneListDoc (crawdad.HtmlDocument): def listEveryone (self, roster): for aPerson in roster: self.listPerson (aPerson) def listPerson (self, aPerson): firstName, lastName, phone = aPerson self.append (self.P (firstName, " ", lastName, ": ", phone))
The listEveryone method expects a list of tuples.
This list might be retrieved from a database or read from a file.
Each tuple is passed to listPerson, which creates the <P>
element.
The various HTML methods, like P, accept any number of contents, which may be strings, numbers, other HTML elements, or any object that has a printable representation. The HTML methods also accept lists or tuples of these contents. Lists and tuples of contents can be nested inside other lists or tuples.
To generate the HTML, create a PhoneList object, call its listEveryone method with a roster, and call its printHtml method. For example,
>>> roster = rosterFileToTupleList ("roster.txt") >>> doc = PhoneListDoc () >>> doc.listEveryone (roster) >>> doc.printHtml () <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> <HTML><HEAD><TITLE>Untitled document</TITLE> </HEAD> <BODY><P>Sara Barebait: 265-7665</P> <P>Nathan Bitebalm: 375-9962</P> <P>Mary Bonebank: 264-6094</P> ... <P>Cindy Wiseface: 375-3987</P> <P>Beth Wokefact: 264-7271</P> <P>Sam Zerofame: 264-6649</P> </BODY> </HTML>
The names will stand out more if they are displayed in bold text.
Change listPerson to surround the name with <B>
(bold) tags.
def listPerson (self, aPerson): firstName, lastName, phone = aPerson self.append (self.P ( self.B (firstName, " ", lastName, ":"), " ", phone))
Now each <P>
element contains a <B>
element
and two strings.
The <B>
elements contain four strings.
Running this version generates bold names:
>>> doc.printHtml () <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> <HTML><HEAD><TITLE>Untitled document</TITLE> </HEAD> <BODY><P><B>Sara Barebait:</B> 265-7665</P> <P><B>Nathan Bitebalm:</B> 375-9962</P> <P><B>Mary Bonebank:</B> 264-6094</P> ...
Phone lists can be quite long, so they include headings
for each letter of the alphabet.
listEveryone can be modified to consider heading
for each person.
The headerFor method does the work of checking
the initial letter and generating an <H2>
(heading 2) header when needed.
def listEveryone (self, roster): self.headerLetter = "" for aPerson in roster: self.headerFor (aPerson) self.listPerson (aPerson) def headerFor (self, aPerson): firstName, lastName, phone = aPerson if self.headerLetter == lastName [0]: return self.headerLetter = lastName [0] self.append (self.H2 (self.headerLetter))
This version generates alphabetic headings:
>>> doc.printHtml () <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> <HTML><HEAD><TITLE>Untitled document</TITLE> </HEAD> <BODY><H2>B</H2> <P><B>Sara Barebait:</B> 265-7665</P> <P><B>Nathan Bitebalm:</B> 375-9962</P> <P><B>Mary Bonebank:</B> 264-6094</P> <H2>C</H2> <P><B>Ellen Cavebath:</B> 265-0020</P> <P><B>Ken Cavebath:</B> 265-1460</P> <P><B>Carol Cedebats:</B> 375-3352</P> ...
Web users do not like to scroll through long lists. A quick index at the top of the page lists the heading letters and provides a link to the corresponding heading later in the document. With Crawdad, the quick index can be built in parallel with the main phone list.
First, define methods to implement the quick index:
def startQuickIndex (self): self.quickIndex = self.P () self.append (self.quickIndex) def addLetterToQuickIndex (self, aLetter): self.quickIndex.append (self.anchor ("#" + aLetter, aLetter), " ")
When startQuickIndex is called, it appends an empty <P>
element to the document.
Later, when addLetterToQuickIndex is called, <A>
(anchor)
elements are appended to the initially empty quick index paragraph.
The quick index element could contain up to 26 anchors.
Note that no HTML is generated by these methods; they simply construct
a tree-like representation of the document in memory.
listEveryone is modified to start a quick index before listing anyone.
def listEveryone (self, roster): self.startQuickIndex () self.headerLetter = "" for aPerson in roster: self.headerFor (aPerson) self.listPerson (aPerson)
headerFor is also modified. It must generate headings that include anchors with name attributes. Crawdad's name method handles that. Whenever a heading is generated, the heading letter must be added to the quick index with addLetterToQuickIndex.
def headerFor (self, aPerson): firstName, lastName, phone = aPerson if self.headerLetter == lastName [0]: return self.headerLetter = lastName [0] self.append (self.H2 (self.name (self.headerLetter, self.headerLetter))) self.addLetterToQuickIndex (self.headerLetter)
This version generates a phone list with a quick index on top.
>>> doc.printHtml () <!DOCTYPE HTML PUBLIC "-//W3C//DTD HTML 3.2 Final//EN"> <HTML><HEAD><TITLE>Untitled document</TITLE> </HEAD> <BODY><P><A HREF="#B">B</A> <A HREF="#C">C</A> <A HREF="#D">D</A> <A HREF="#E">E</A> <A HREF="#F">F</A> <A HREF="#G">G</A> <A HREF="#H">H</A> <A HREF="#I">I</A> <A HREF="#J">J</A> <A HREF="#K">K</A> <A HREF="#L">L</A> <A HREF="#M">M</A> <A HREF="#N">N</A> <A HREF="#O">O</A> <A HREF="#P">P</A> <A HREF="#R">R</A> <A HREF="#S">S</A> <A HREF="#T">T</A> <A HREF="#U">U</A> <A HREF="#W">W</A> <A HREF="#Z">Z</A> </P> <H2><A NAME="B">B</A></H2> <P><B>Sara Barebait:</B> 265-7665</P> <P><B>Nathan Bitebalm:</B> 375-9962</P> <P><B>Mary Bonebank:</B> 264-6094</P> <H2><A NAME="C">C</A></H2> <P><B>Ellen Cavebath:</B> 265-0020</P> <P><B>Ken Cavebath:</B> 265-1460</P> <P><B>Carol Cedebats:</B> 375-3352</P> ...