Chapter 24

WWW Personal Information Manager

by Owen Graupman


CONTENTS

Overview

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.

How It Works

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 &  "&nbsp;"

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 &  "&nbsp;"

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: 


Creating the Page

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:

Working with Cookies

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:

The Variable Metaphor

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.

Reading Variables

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.

Writing and Deleting Variables

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


Creating Dynamic HTML

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.

Creating HREFs from Scratch

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


Creating the Calendar

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 &  "&nbsp;"

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 &  "&nbsp;"

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: 


Presenting Information

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

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

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


Tying It All Together

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

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: 


Review

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: