by Owen Graupman
Personal information managers have always been one of the most popular applications for a computer. This chapter will show you how to make a World Wide Web-based personal information manager that allows the user to store to-do's, appointments, and e-mail addresses with a few simple clicks of the mouse.
Two very important techniques are used to create this interactive page:
Dynamic page creation is one of the hottest topics in page creation. A dynamic page changes in response to the environment, user input, or a variety of other information. The WWW PIM uses VBScript to generate the entire page based on the current date and information stored by the user.
Persistent storage through cookies allows visitors to this page to store their appointments in small text files called cookies, which reside on their local computer and can be recalled at any time. Many sites today use cookies to store information about the user. Some of the most common uses are to store color preferences or information provided by the user like their name and address. Because a cookie is just a text file managed by the browser, client-side security is very good. Even if a miscreant person was able to place a virus in a cookie, the file contains headers and footers that would prevent the code from running and infecting your system.
Before you go running off to explore cookies, keep in mind that cookies will only work when the page is loaded from an HTTPD server. Loading this page locally will produce a blank page that will not store any data.
When a user loads this page from the Internet, VBScript goes to work parsing through the cookie to pull out information for each of the categories of data. It then formats this information into HTML and writes it directly into the document context as HTML.
When a user clicks on any item, whether it's a to-do, address, or appointment, message boxes prompt the user through creating a new item. The information is then placed into the cookie and the page reloaded.
You can see how the finished example looks in Figure 24.1, and the entire HTML and VBScript code in Listing 24.1.
Figure 24.1 : The finished WWW Personal Information Manager.
Listing 24.1. The WWW Personal Information Manager code listing.
1: <!DOCTYPE HTML PUBLIC "-//IETF//DTD HTML//EN"> 2: 3: <HTML> 4: 5: <HEAD> 6: <TITLE>WWW Personal Information Manager</title> 7: </HEAD> 8: 9: <BODY BGCOLOR="#FFFFFF" LANGUAGE="VBSCRIPT"> 10: <H1 ALIGN=CENTER>WWW Personal Information Manager</H1> 11: <P ALIGN=CENTER><FONT SIZE=2>Welcome to the WWW Personal Information Manager. You can use this site to store to-do's, appointments, 12: and email addresses. This information is stored on your local computer via cookies. To add, edit, or delete an item, click on the item 13: number in the list and follow the prompts.</FONT></P> 14: <P ALIGN=CENTER><FONT SIZE=2>NOTE: This page must be accessed from the Internet or information will not get stored in the cookie. </FONT></P> 15: <CENTER> 16: <TABLE CELLPADDING=0 CELLSPACING=5 WIDTH=100%> 17: <SCRIPT LANGUAGE="VBSCRIPT"><!-- 18: Call docCreate 19: 20: Sub setVariable(sVariableName, varVariableValue) 21: Document.Cookie = sVariableName & "=" & varVariableValue & ";expires=Monday, 28-Sep-98 12:00:00 GMT" 22: end sub 23: 24: Function readVariable(sVariableName) 25: Dim iLocation 26: Dim iNameLength 27: Dim iValueLength 28: Dim iNextSemicolon 29: Dim sTemp 30: 31: iNameLength = Len(sVariableName) 32: iLocation = InStr(Document.Cookie, sVariableName) 33: If iLocation = 0 Then 34: readVariable = "" 35: Else 36: sTemp = Right(Document.Cookie, Len(Document.Cookie) - iLocation + 1) 37: If Mid(sTemp, iNameLength + 1, 1) <> "=" Then 38: readVariable = "" 39: Else 40: iNextSemicolon = InStr(sTemp, ";") 41: If iNextSemicolon = 0 Then iNextSemicolon = Len(sTemp) + 1 42: If iNextSemicolon = (iNameLength + 2) Then 43: readVariable = "" 44: Else 45: iValueLength = iNextSemicolon - iNameLength - 2 46: readVariable = Mid(sTemp, iNameLength + 2, iValueLength) 47: End If 48: End If 49: End if 50: end function 51: 52: Sub killVariable(sVariableName) 53: setVariable sVariableName, "NULL;expires=Monday, 01-Jan-95 12:00:00 GMT" 54: end sub 55: 56: Sub addTodo(iRecord) 57: Dim sTodo 58: Dim iChoice 59: 60: iChoice = MsgBox("Do you want to add or delete this item? Click yes to add or no to delete.", 3, "Add/Delete Item") 61: Select Case iChoice 62: Case 6 63: sTodo = InputBox("What do you want to do?", "Add To-Do") 64: Call setVariable("%%TD" & Trim(iRecord), sTodo) 65: Case 7 66: killVariable "%%TD" & Trim(iRecord) 67: Case 2 68: Exit Sub 69: End Select 70: window.navigate "wwwpim.htm" 71: End Sub 72: 73: Sub addAppt(m,d,y) 74: Dim sAppt 75: Dim TempAppt 76: 77: TempAppt = readVariable("%%AP" & Trim(m) & "/" & Trim(d) & "/" & Trim(y)) 78: 79: If Len(Trim(TempAppt)) > 0 Then 80: sAppt = InputBox("Please enter or edit your appointment list for today", "Add/Edit Appointment", readVariable("%%AP" & Trim(m) & "/" & Trim(d) & "/" & Trim(y))) 81: Else 82: sAppt = InputBox("Please enter or edit your appointment list for today", "Add/Edit Appointment") 83: End If 84: If Len(Trim(sAppt)) > 0 Then 85: Call setVariable("%%AP" & Trim(m) & "/" & Trim(d) & "/" & Trim(y), sAppt) 86: Else 87: killVariable("%%AP" & Trim(m) & "/" & Trim(d) & "/" & Trim(y)) 88: End If 89: window.navigate "wwwpim.htm" 90: End Sub 91: 92: Sub addAddr(iRecord) 93: Dim Addr 94: Dim iChoice 95: iChoice = MsgBox("Do you want to add or delete this item? Click yes to add or no to delete.", 3,"Add/Delete Item") 96: 97: Select Case iChoice 98: Case 6 99: Addr=InputBox("What address do you want to add?", "Add Email Address") 100: Call setVariable("%%AD" & Trim(iRecord), Addr) 101: Case 7 102: killVariable "%%AD" & Trim(iRecord) 103: Case 2 104: Exit Sub 105: End Select 106: window.navigate "wwwpim.htm" 107: End Sub 108: 109: Sub ApptStat(m,d,y) 110: Dim sTemp 111: 112: sTemp = CStr(d & " " & readVariable("%%AP" & m & "/" & d & "/" & y)) 113: If Len(Trim(sTemp)) > 0 AND readVariable("%%AP" & m & "/" & d & "/" & y) <> "NULL" Then 114: window.status = sTemp 115: Else 116: window.status = CStr(d) 117: End If 118: End Sub 119: 120: Function makTD_URL(iRecord) 121: If Trim(readVariable("%%TD" & Trim(iRecord))) <> "NULL" Then 122: makTD_URL = "<A LANGUAGE=VBScript HREF=#null onClick=addTodo(" & Trim(iRecord) & ")>" & iRecord & ". " & readVariable("%%TD" & Trim(iRecord)) & "</A>" 123: Else 124: makTD_URL = "<A LANGUAGE=VBScript HREF=#null onClick=addTodo(" & Trim(iRecord) & ")>" & iRecord & ". </A>" 125: End If 126: End Function 127: 128: Function makAD_URL(iRecord) 129: If Trim(readVariable("%%AD" & Trim(iRecord))) <> "NULL" Then 130: makAD_URL = "<A LANGUAGE=VBScript HREF=#null onClick=addAddr(" & Trim(iRecord) & ")>" & iRecord & ". " & "</a>" & "<A HREF=mailto:" & readVariable("%%AD" & Trim(iRecord)) & ">" & readVariable("%%AD" & Trim(iRecord)) & "</A>" 131: Else 132: makAD_URL = "<A LANGUAGE=VBScript HREF=#null onClick=addAddr(" & Trim(iRecord) & ")>" & iRecord & ". " & "</A>" 133: End If 134: End Function 135: 136: Function makAP_URL(m,d,y) 137: Dim stAppt 138: 139: stAppt = readVariable("%%AP" & m & "/" & d & "/" & y) 140: If Len(Trim(stAppt)) > 0 AND Trim(stAppt) <> "NULL" Then 141: sTemp = "<A LANGUAGE=VBScript HREF=#null onClick=" 142: sTemp = sTemp & Chr(34) 143: sTemp = sTemp & "Call addAppt(" & m & ", " & d & ", " & y & ")" 144: sTemp = sTemp & Chr(34) 145: sTemp = sTemp & " onMouseOver=" 146: sTemp = sTemp & Chr(34) 147: sTemp = sTemp & "Call ApptStat(" & m & ", " & d & ", " & y & ")" & Chr(34) & ">" 148: sTemp = sTemp & d & "!</a>" 149: Else 150: sTemp = "<A LANGUAGE=VBScript HREF=#null onClick=" 151: sTemp = sTemp & Chr(34) 152: sTemp = sTemp & "Call addAppt(" & m & ", " & d & ", " & y & ")" 153: sTemp = sTemp & Chr(34) 154: sTemp = sTemp & " onMouseOver=" 155: sTemp = sTemp & Chr(34) 156: sTemp = sTemp & "Call ApptStat(" & m & ", " & d & ", " & y & ")" & Chr(34) & ">" 157: sTemp = sTemp & d & "</A>" 158: End If 159: makAP_URL = sTemp 160: End Function 161: 162: Sub docCreate 163: Dim sDocument 164: sDocument = "<TD ALIGN=LEFT VALIGN=TOP WIDTH=35%><CENTER><B>To Do</B></ CENTER>" 165: sDocument = sDocument & Chr(13) & Chr(10) & "<HR>" 166: For i = 1 to 10 167: sDocument = sDocument & "<BR>" & makTD_URL(i) 168: Next 169: sDocument = sDocument & "</TD><TD ALIGN=CENTER VALIGN=MIDDLE WIDTH=30%>" 170: sDocument = sDocument & makCalendar() 171: sDocument = sDocument & "</TD><TD ALIGN=LEFT VALIGN=TOP WIDTH=35%>" 172: sDocument = sDocument & "<CENTER><B>ADDRESSES</B></CENTER>" 173: sDocument = sDocument & Chr(13) & Chr(10) & "<HR>" 174: For j = 1 to 10 175: sDocument = sDocument & "<BR>" & makAD_URL(j) 176: Next 177: 178: sDocument = sDocument & "</TD></TR>" 179: sDocument = sDocument & Chr(13) & Chr(10) & "</TABLE>" 180: 181: Document.Write sDocument 182: 183: End Sub 184: 185: Function makCalendar() 186: m=Month(Now()) 187: y=Year(Now()) 188: 189: FirstDay = WeekDay(Dateserial(y,m,1)) 190: DaysInMonth= Day(Dateserial(y,m+1,1)-1) 191: ThisMonth=GMonth(Month(Dateserial(y,m,1)), true) & " " & Year(Dateserial(y,m,1)) 192: 193: sCalendar="" 194: sCalendar=sCalendar & "<CENTER><TABLE BORDER=1 CELLPADDING=2>" 195: sCalendar=sCalendar & "<TR><TH COLSPAN=7>" & ThisMonth & "</TH>" 196: sCalendar=sCalendar & "<TR><TH WIDTH=50 ALIGN=CENTER>Sun</TH><TH WIDTH=50 ALIGN=CENTER>Mon</TH><TH WIDTH=50 ALIGN=CENTER>Tue</TH><TH WIDTH=50 ALIGN=CENTER>Wed</TH><TH WIDTH=50 ALIGN=CENTER>Thu</TH><TH WIDTH=50 ALIGN=CENTER>Fri</TH><TH WIDTH=50 ALIGN=CENTER>Sat</TH></TR>" 197: 198: ictrDay=0 199: For Row=1 to 6 200: sCalendar=sCalendar & "<TR>" 201: For Col=1 to 7 202: sCalendar=sCalendar & "<TD WIDTH=50 ALIGN=CENTER>" 203: If Row=1 AND Col=FirstDay then 204: ictrDay=1 205: End If 206: If ictrDay = 0 Then 207: sCalendar=sCalendar & " " 208: End If 209: If ictrDay <> 0 Then 210: If ictrDay <= DaysInMonth Then 211: sCalendar=sCalendar & makAP_URL(m,ictrDay,y) 212: End If 213: If ictrDay > DaysInMonth Then 214: sCalendar=sCalendar & " " 215: End If 216: ictrDay=ictrDay+1 217: End if 218: sCalendar=sCalendar & "</TD>" 219: Next 220: sCalendar=sCalendar & "</TR>" 221: Next 222: sCalendar=sCalendar & "</TABLE>" 223: makCalendar = sCalendar 224: End Function 225: 226: Function GMonth(iMonth, fLongShort) 227: Select Case iMonth 228: Case 1 229: If fLongShort = true then GMonth="January" else GMonth="Jan" 230: Case 2 231: If fLongShort = true then GMonth="February" else GMonth="Feb" 232: Case 3 233: If fLongShort = true then GMonth="March" else GMonth="Mar" 234: Case 4 235: If fLongShort = true then GMonth="April" else GMonth="Apr" 236: Case 5 237: If fLongShort = true then GMonth="May" else GMonth="May" 238: Case 6 239: If fLongShort = true then GMonth="June" else GMonth="Jun" 240: Case 7 241: If fLongShort = true then GMonth="July" else GMonth="Jul" 242: Case 8 243: If fLongShort = true then GMonth="August" else GMonth="Aug" 244: Case 9 245: If fLongShort = true then GMonth="September" else GMonth="Sep" 246: Case 10 247: If fLongShort = true then GMonth="October" else GMonth="Oct" 248: Case 11 249: If fLongShort = true then GMonth="November" else GMonth="Nov" 250: Case 12 251: If fLongShort = true then GMonth="December" else GMonth="Dec" 252: End Select 253: End Function 254: 255: --></SCRIPT> 256: </TABLE> 257: </CENTER> 258: </BODY> 259: 260: </HTML> 261:
Looking at the source reveals quite a bit of VBScript code and very little HTML. Almost the entire page is generated by VBScript as it is loaded. We accomplish this feat through several routines, which are broken up into the following areas:
Cookies (or more properly, magic cookies) provide a means for browsers to store persistent information without the need for access to CGI scripts, custom executables, or other means of data storage and retrieval. I use a 'variable' metaphor for working with cookies as described in the following sections:
An easy way to access random pieces of information from a cookie is through variable assignment. By assigning a recognizable name to persistent information, you can easily pull out relevant pieces from the cookie using a simple subroutine.
The WWW PIM uses three different types of variables to store information. It uses %%TDx where x is the record number to store to-do's, %%ADx where x is the record number for addresses, and, finally, %%APmm/dd/yyyy for appointment dates.
The code in Listing 24.2 is used to read a variable from within the cookie.
Listing 24.2. The readVariable() function.
1: Function readVariable(sVariableName) 2: Dim iLocation 3: Dim iNameLength 4: Dim iValueLength 5: Dim iNextSemicolon 6: Dim sTemp 7: 8: iNameLength = Len(sVariableName) 9: iLocation = InStr(Document.Cookie, sVariableName) 10: If iLocation = 0 Then 11: readVariable = "" 12: Else 13: sTemp = Right(Document.Cookie, Len(Document.Cookie) - iLocation + 1) 14: If Mid(sTemp, iNameLength + 1, 1) <> "=" Then 15: readVariable = "" 16: Else 17: iNextSemicolon = InStr(sTemp, ";") 18: If iNextSemicolon = 0 Then iNextSemicolon = Len(sTemp) + 1 19: If iNextSemicolon = (iNameLength + 2) Then 20: readVariable = "" 21: Else 22: iValueLength = iNextSemicolon - iNameLength - 2 23: readVariable = Mid(sTemp, iNameLength + 2, iValueLength) 24: End If 25: End If 26: End if 27: end function 28:
The readVariable() function takes a single parameter-the variable name to read-and returns the value of that variable. The readVariable() function accomplishes this through several iterations of InStr and Mid. This works fine for storing numerical information, but you run into a problem when storing random character information. Let's say you create a variable called Appt, which stores appointment information. Now if a user enters Dentist Appt in their appointment information, InStr can return the wrong chunk of information, or worse, complete garbage. The readVariable() function attempts to reduce this possibility by searching for an equal sign (=) immediately after the string being sought. To further reduce the chances of this problem occurring, routines append %% to the beginning of each variable name.
The page uses the same subroutine to both write and delete variables from the cookie. Just like those found on the store shelves, all magic cookies have expiration dates. By default, an entry in a cookie will expire when the browser is closed, which isn't very persistent. Imagine what would happen if your daily planner erased itself every time you closed the cover.
The setVariable routine in Listing 24.3 takes a pair of parameters: The former is the variable name, and the latter its corresponding value. It then appends an expiration date of September 28, 1998, to the end of the cookie.
Listing 24.3. The setVariable routine.
1: 2: Sub setVariable(sVariableName, varVariableValue) 3: Document.Cookie = sVariableName & "=" & varVariableValue & ";expires=Monday, 28- Sep-98 12:00:00 GMT" 4: end sub 5:
Correspondingly, the killVariable routine in Listing 24.4 sets the variable to NULL, appends an expiration date of January 1, 1995, and then calls the setVariable routine. Watchful readers will note that using killVariable will create an entry with two expiration dates. Fortunately for us, the second date is ignored and then deleted.
Listing 24.4. The killVariable routine.
1: 2: Sub killVariable(sVariableName) 3: setVariable sVariableName, "NULL;expires=Monday, 01-Jan-95 12:00:00 GMT" 4: end sub
The code uses five functions to create the statements needed to display the information in HTML format. These functions are divided into two related areas:
The first set of functions is used to create a single <A HREF> statement that displays the stored data, if any, and provides the necessary code to edit the item.
The second set of functions is similar to the first, but also generates a table in addition to one of the HREF functions.
The following three functions in Listings 24.5, 24.6, and 24.7 are used to create a single <A HREF> statement. The first two take only the record number as a parameter and pass back a formatted string that can be written directly into the document. Listing 24.7, makAP_URL(), takes the month, day, and year for the current record.
The code in Listing 24.6, which is used to create the address code, takes the address provided and converts it to a mailto: directive so that a user can easily mail someone on the address list by clicking on the address, or edit the record by clicking on the number.
In addition to the code to edit an appointment, the makAP_URL() function also contains an onMouseOver event to place the current appointment in the status bar.
Listing 24.5. The makTD_URL() function.
1: 2: Function makTD_URL(iRecord) 3: If Trim(readVariable("%%TD" & Trim(iRecord))) <> "NULL" Then 4: makTD_URL = "<A LANGUAGE=VBScript HREF=#null onClick=addTodo(" & Trim(iRecord) & ")>" & iRecord & ". " & readVariable("%%TD" & Trim(iRecord)) & "</A>" 5: Else 6: makTD_URL = "<A LANGUAGE=VBScript HREF=#null onClick=addTodo(" & Trim(iRecord) & ")>" & iRecord & ". </A>" 7: End If 8: End Function 9:
Listing 24.6. The makAD_URL() function.
1: 2: Function makAD_URL(iRecord) 3: If Trim(readVariable("%%AD" & Trim(iRecord))) <> "NULL" Then 4: makAD_URL = "<A LANGUAGE=VBScript HREF=#null onClick=addAddr(" & Trim(iRecord) & ")>" & iRecord & ". " & " </a>" & "<A HREF=mailto:" & readVariable("%%AD" & Trim(iRecord)) & ">" & readVariable("%%AD" & Trim(iRecord)) & "</A>" 5: Else 6: makAD_URL = "<A LANGUAGE=VBScript HREF=#null onClick=addAddr(" &Trim(iRecord) & ")>" & iRecord & ". " & "</A>" 7: End If 8: End Function 9:
Listing 24.7. The makAP_URL() function.
1: 2: Function makAP_URL(m,d,y) 3: Dim stAppt 4: 5: stAppt = readVariable("%%AP" & m & "/" & d & "/" & y) 6: If Len(Trim(stAppt)) > 0 AND Trim(stAppt) <> "NULL" Then 7: sTemp = "<A LANGUAGE=VBScript HREF=#null onClick=" 8: sTemp = sTemp & Chr(34) 9: sTemp = sTemp & "Call addAppt(" & m & ", " & d & ", " & y & ")" 10: sTemp = sTemp & Chr(34) 11: sTemp = sTemp & " onMouseOver=" 12: sTemp = sTemp & Chr(34) 13: sTemp = sTemp & "Call ApptStat(" & m & ", " & d & ", " & y & ")" & Chr(34) & ">" 14: sTemp = sTemp & d & "!</a>" 15: Else 16: sTemp = "<A LANGUAGE=VBScript HREF=#null onClick=" 17: sTemp = sTemp & Chr(34) 18: sTemp = sTemp & "Call addAppt(" & m & ", " & d & ", " & y & ")" 19: sTemp = sTemp & Chr(34) 20: sTemp = sTemp & " onMouseOver=" 21: sTemp = sTemp & Chr(34) 22: sTemp = sTemp & "Call ApptStat(" & m & ", " & d & ", " & y & ")" & Chr(34) & ">" 23: sTemp = sTemp & d & "</A>" 24: End If 25: makAP_URL = sTemp 26: End Function
The final set of HREF functions is the makCalendar() function (see Listing 24.8), which iterates through several loops to create a calendar out of an embedded table based on the current month and year, and the GMonth() function (see Listing 24.9), which provides the month names for makCalendar().
Listing 24.8. The makCalendar() function.
1: 2: Function makCalendar() 3: m=Month(Now()) 4: y=Year(Now()) 5: 6: FirstDay = WeekDay(Dateserial(y,m,1)) 7: DaysInMonth= Day(Dateserial(y,m+1,1)-1) 8: ThisMonth=GMonth(Month(Dateserial(y,m,1)), true) & " " & Year(Dateserial(y,m,1)) 9: 10: sCalendar="" 11: sCalendar=sCalendar & "<CENTER><TABLE BORDER=1 CELLPADDING=2>" 12: sCalendar=sCalendar & "<TR><TH COLSPAN=7>" & ThisMonth & "</TH>" 13: sCalendar=sCalendar & "<TR><TH WIDTH=50 ALIGN=CENTER>Sun</TH><TH WIDTH=50 ALIGN=CENTER>Mon</TH><TH WIDTH=50 ALIGN=CENTER>Tue</TH><TH WIDTH=50 ALIGN=CENTER>Wed</TH><TH WIDTH=50 ALIGN=CENTER>Thu</TH><TH WIDTH=50 ALIGN=CENTER>Fri</TH><TH WIDTH=50 ALIGN=CENTER>Sat</TH></TR>" 14: 15: ictrDay=0 16: For Row=1 to 6 17: sCalendar=sCalendar & "<TR>" 18: For Col=1 to 7 19: sCalendar=sCalendar & "<TD WIDTH=50 ALIGN=CENTER>" 20: If Row=1 AND Col=FirstDay then 21: ictrDay=1 22: End If 23: If ictrDay = 0 Then 24: sCalendar=sCalendar & " " 25: End If 26: If ictrDay <> 0 Then 27: If ictrDay <= DaysInMonth Then 28: sCalendar=sCalendar & makAP_URL(m,ictrDay,y) 29: End If 30: If ictrDay > DaysInMonth Then 31: sCalendar=sCalendar & " " 32: End If 33: ictrDay=ictrDay+1 34: End if 35: sCalendar=sCalendar & "</TD>" 36: Next 37: sCalendar=sCalendar & "</TR>" 38: Next 39: sCalendar=sCalendar & "</TABLE>" 40: makCalendar = sCalendar 41: End Function 42:
The makCalendar()function creates a table definition, creates the month banner and the seven weekday columns, and then loops through the remaining rows and columns, calling the makAP_URL() function from Listing 24.7 to place the date. The makAP_URL() function appends an exclamation mark to the end of a date that contains an appointment.
The GMonth() function takes a pair of arguments, the month number, and a boolean value to determine whether it should return a long month like January or a short month like Jan. Although the short month is not used, it produces a value that can be used in the expiration field of a cookie so that you can expand this example to create time-sensitive to-do's.
Listing 24.9. The GMonth() function.
1: Function GMonth(iMonth, fLongShort) 2: Select Case iMonth 3: Case 1 4: If fLongShort = true then GMonth="January" else GMonth="Jan" 5: Case 2 6: If fLongShort = true then GMonth="February" else GMonth="Feb" 7: Case 3 8: If fLongShort = true then GMonth="March" else GMonth="Mar" 9: Case 4 10: If fLongShort = true then GMonth="April" else GMonth="Apr" 11: Case 5 12: If fLongShort = true then GMonth="May" else GMonth="May" 13: Case 6 14: If fLongShort = true then GMonth="June" else GMonth="Jun" 15: Case 7 16: If fLongShort = true then GMonth="July" else GMonth="Jul" 17: Case 8 18: If fLongShort = true then GMonth="August" else GMonth="Aug" 19: Case 9 20: If fLongShort = true then GMonth="September" else GMonth="Sep" 21: Case 10 22: If fLongShort = true then GMonth="October" else GMonth="Oct" 23: Case 11 24: If fLongShort = true then GMonth="November" else GMonth="Nov" 25: Case 12 26: If fLongShort = true then GMonth="December" else GMonth="Dec" 27: End Select 28: End Function 29:
An application is completely useless if it doesn't provide the user any feedback. In order to keep the WWW PIM from being completely useless, we need to add some code that creates an interface for the user to edit and view information from the page. This code is broken down into two separate groups:
The add routines in Listings 24.10, 24.11, and 24.12 provide an interface for the user to input, edit, or delete information. Each routine displays one or more message boxes and prompts the user for the necessary information. Depending on whether the user is adding, editing, or deleting information, each routine then calls either setVariable or killVariable.
The addTodo and addAddr routines both display a generic message box like the one in Figure 24.2.
Figure 24.2 : The Add/Delete Item message box.
Listing 24.10. The addTodo routine.
1: 2: Sub addTodo(iRecord) 3: Dim sTodo 4: Dim iChoice 5: 6: iChoice = MsgBox("Do you want to add or delete this item? Click yes to add or no to delete.", 3, "Add/Delete Item") 7: Select Case iChoice 8: Case 6 9: sTodo = InputBox("What do you want to do?", "Add To-Do") 10: Call setVariable("%%TD" & Trim(iRecord), sTodo) 11: Case 7 12: killVariable "%%TD" & Trim(iRecord) 13: Case 2 14: Exit Sub 15: End Select 16: window.navigate "wwwpim.htm" 17: End Sub 18:
Listing 24.10 displays an input box that looks like Figure 24.3.
Figure 24.3 : The Add To-Do dialog.
Listing 24.11. The addAppt routine.
1: 2: Sub addAppt(m,d,y) 3: Dim sAppt 4: Dim TempAppt 5: 6: TempAppt = readVariable("%%AP" & Trim(m) & "/" & Trim(d) & "/" & Trim(y)) 7: 8: If Len(Trim(TempAppt)) > 0 Then 9: sAppt = InputBox("Please enter or edit your appointment list for today", "Add/Edit Appointment", readVariable("%%AP" & Trim(m) & "/" & Trim(d) & "/" & Trim(y))) 10: Else 11: sAppt = InputBox("Please enter or edit your appointment list for today", "Add/Edit Appointment") 12: End If 13: If Len(Trim(sAppt)) > 0 Then 14: Call setVariable("%%AP" & Trim(m) & "/" & Trim(d) & "/" & Trim(y), sAppt) 15: Else 16: killVariable("%%AP" & Trim(m) & "/" & Trim(d) & "/" & Trim(y)) 17: End If 18: window.navigate "wwwpim.htm" 19: End Sub 20:
Listing 24.11 displays an input box like the one in Figure 24.4.
Figure 24.4 : The Add/Edit Appointment dialog.
Listing 24.12 displays an input box like the one in Figure 24.5.
Figure 24.5 : The Add/Delete address routine.
Listing 24.12. The addAddr routine.
1: 2: Sub addAddr(iRecord) 3: Dim Addr 4: Dim iChoice 5: iChoice = MsgBox("Do you want to add or delete this item? Click yes to add or no to delete.", 3,"Add/Delete Item") 6: 7: Select Case iChoice 8: Case 6 9: Addr=InputBox("What address do you want to add?", "Add Email Address") 10: Call setVariable("%%AD" & Trim(iRecord), Addr) 11: Case 7 12: killVariable "%%AD" & Trim(iRecord) 13: Case 2 14: Exit Sub 15: End Select 16: window.navigate "wwwpim.htm" 17: End Sub 18:
The ApptStat routine (see Listing 24.13) is called by the onMouseOver event associated with each day. When the mouse passes over a date, this routine is called and the current appointment is placed in the status bar.
Listing 24.13. The ApptStat routine.
1: 2: Sub ApptStat(m,d,y) 3: Dim sTemp 4: 5: sTemp = CStr(d & " " & readVariable("%%AP" & m & "/" & d & "/" & y)) 6: If Len(Trim(sTemp)) > 0 AND readVariable("%%AP" & m & "/" & d & "/" & y) <> "NULL" Then 7: window.status = sTemp 8: Else 9: window.status = CStr(d) 10: End If 11: End Sub
Now that we've covered all the routines that support generation of the page, we have one last procedure to cover, the docCreate routine.
The docCreate procedure in Listing 24.14 encapsulates all the previous functions to generate all of the HTML for the page. It creates each column one at a time, filling in each cell with an <HREF> from one of the mak() functions, and then it calls document.write to append the new content to the document.
Listing 24.14. The docCreate procedure.
1: 2: Sub docCreate 3: Dim sDocument 4: sDocument = "<TD ALIGN=LEFT VALIGN=TOP WIDTH=35%><CENTER><B>To Do</B></CENTER>" 5: sDocument = sDocument & Chr(13) & Chr(10) & "<HR>" 6: For i = 1 to 10 7: sDocument = sDocument & "<BR>" & makTD_URL(i) 8: Next 9: sDocument = sDocument & "</TD><TD ALIGN=CENTER VALIGN=MIDDLE WIDTH=30%>" 10: sDocument = sDocument & makCalendar() 11: sDocument = sDocument & "</TD><TD ALIGN=LEFT VALIGN=TOP WIDTH=35%>" 12: sDocument = sDocument & "<CENTER><B>ADDRESSES</B></CENTER>" 13: sDocument = sDocument & Chr(13) & Chr(10) & "<HR>" 14: For j = 1 to 10 15: sDocument = sDocument & "<BR>" & makAD_URL(j) 16: Next 17: 18: sDocument = sDocument & "</TD></TR>" 19: sDocument = sDocument & Chr(13) & Chr(10) & "</TABLE>" 20: 21: Document.Write sDocument 22: 23: End Sub 24:
After trying this sample, you can see how to create Web applications that can easily store and retrieve complex sets of information and display them to the user.
Here's a few challenges for you to extend your WWW Personal Information Manager: