首先,我們需要著重介紹一些概念,以給你提供一些使這個“奇跡”得以發生的組成部分。太輕易地洩露伏筆對於講故事來說不是個好的形式,所以那些不願意在一開始就看到就結局的人就應該在這裡先走開一下。
這個綜合體的第一部分是定寬
字體的使用。Internet Explorer 和Netscape的兩種標准定寬字體分別是 CourIEr New和Lucida Console。大部分的網頁設計都不是完全使用標准字體,但它們是這個特定技術 工作的必要條件,正象上面兩個畫面所顯示的,它們看起來不錯。
進一步解釋,定寬字體就是一種字體,對這種字體的所有字符來說每個字符所占據的空間都是相同的。所以你可能想要采取一定的步驟以確保,這些定寬字體中的某一個或另一個已經安裝在組成你的目標觀眾的客戶機上。如果要用你的浏覽器看看目前這些字體是否已經安裝,在IE5中到Tools | Internet Options下,在Internet Options窗口的General 標簽上點擊 Fonts 按鈕。你就會看到一個名為 Plain Text Font的區:
這就是當前安裝的全部定寬字體的列表。對於Netscape 4 和更高版本,到Edit |
PReferences ,在 tree-vIEw中展開 Appearance並選擇 Fonts。在那有一個Fixed Width Fonts的下拉列表。
第二部分是將某個特定的字體申請到選項列表中的能力。在IE4及以上版本中,可以用以下方式申請一個字體:
< SELECT name="mySelect" style=FONT-FAMILY: Lucida Console, CourIEr New; >
對Netscape,你可以圍繞選項列表使用Font標記:
< FONT FACE="Lucida Console, CourIEr New" >< /FONT >
第三部分就是無間斷空間&nbsp和管道字符的使用。
在下一部分我將演示一個簡單的完全編碼的多選項列表的例子。最後一部分將演示在上下文使用
數據庫調用的多選項列表函數,並將探索一些可能的參數選擇。
基本的多欄選項列表
作 者 : 青蘋果工作室 本文點擊次數:4755
以下的Html例子示范多欄選項列表的最基本形式:
< Html >
< HEAD >
< TITLE >Simple Multi-Column Select List< /TITLE >
< /HEAD >
< BODY >
< FORM >
< FONT FACE="Lucida Console, CourIEr New" >
< SELECT name="sel1" size=3 >
< OPTION VALUE="1" >
John |Ch
ips |
Intel |Hillsboro
< OPTION VALUE="2" >
Sue |Wotz |
Microsoft |Redmond
< OPTION VALUE="3" >
Nathan |Babb |
Eprise |Framingham
< /SELECT >
< /FONT >
< /FORM >
< /BODY >
< /Html >
列表選項包含FirstName、 LastName、 Company 和 City。為了正確地安排第一欄的格式,我們必須發現字節數最多的名字''Nathan'',然後為全部7個字符增加一個無間斷空間。然後我們給John和Sue增加適當數量的空格,使它成為7個字符,在結尾增加管道符號,現在我們就有了一個格式化了的欄。
要注意我們在以上代碼中增加了< FONT > 標記。這是為了在Netscape上使用考慮,因為Netscape不象 IE能夠識別字體屬性。還要注意< FORM > 標記的出現。這也是Netscape 的要求。IE允許你繪制表單域、 選項列表等,不用將它們放在< FORM > 標記中,而在Netscape ,如果想要提取表單控制的話,就要求 表單的標記。
使用這種方法有明顯的缺陷。比如說,不容易向列表中增加一個記錄,尤其是當它的大小與編碼確定的空間不適合的時候。另外,這種類型的列表難以維護,尤其是當你不是創建編碼的那個人的時候。 在下一部分我將向你演示如何用代碼動態創建一個多欄選項列表。
擴展的多欄選項列表(一)
作 者 : 青蘋果工作室 本文點擊次數:4755
我所執行的多欄選項列表是一個叫做
ASPOptionListMulti()的函數。如果你想跳過解釋直接進入代碼部分,可以在文章結尾處找到供下載的函數。下載的函數包含以下幾個文件:
simpleSelect.htm
multicolumnlist.mdb
example.ASP
connect.inc
aspFunction.ASP
simpleSelect.htm 是前面第一個例子的代碼。我的動態例子使用的數據庫是
Access ,其數據源是 multicolumnlist.mdb 。通過運行example.ASP 腳本就可以看到這個動態例子實際執行情況。這個文件中包含connect.inc 以建立與數據庫的連接,aspFunction.asp 進行對ASPOptionListMulti() 的函數調用。
如下表中所列的,我的多欄列表函數有10個參數。我不想在ASPOptionListMulti()的數據恢復方面多花時間。在接下來的討論中,假設存在某種類型的數據源,你將在函數中處理返回的行。在這個例子中,我假設我所存儲的程序沒有參數。我也不再深入解釋這個函數是如何調用的。如果你想知道函數是如何被調用的,可以在下載處參考例子。
proc - 生成存儲的程序名
parmname - 用於sp調用的可選參數名 (可傳遞單個值或數組)
parmval - 用於sp調用的可選參數值 (可傳遞單個值或數組)
val - 選項列表的值欄
selval - 如果是空字符串就不選擇。如果它在選項列表中,就作為所選擇的值被傳遞。
column -在選項列表中代表欄的一個數組。
maxcollen - 一個欄的最大可能長度。 -1 就關閉。可以是單個值,對於多欄就是數組。
name - 選項列表的名字。
firstopt - 確定第一個選項是否為空。如果是"|*" 那麼就無選項。如果傳遞了一個值,那麼它就是 第一個選項的值(推薦使用0或1)。
style - 字體必須是固定長度(CourIEr New 或 Lucida Console)。其它字體的參數選擇也可以傳遞。
optattr - 你可能想要包含在選項列表(如函數調用、屬性等)中的供選擇的屬性(完全引用)。
size -1是普通,2或更多是多選(行)。
以下代碼是函數聲明及它的其它參數。
Function ASPOptionListMulti(proc, parmname, parmval, val, selval, column, maxcollen, name, firstopt, style, optattr, size)
On Error Resume Next
對於我們這個特定情況,你可能想要在函數的最開頭包含一個On Error Resume Next 語句。把這個語句放在代碼中允許代碼在發生錯誤的情況下繼續執行(也許在返回的記錄集中,代碼在某一行中遇到了一個意外的值)。代碼中有這個語句,你還可以建立選項列表的內容。缺點是在發生錯誤的情況,你的應用程序用戶將不能直接向你報告錯誤,也許這個錯誤會導致下一個錯誤,使你的調試工作更加困難。
代碼的下一個重要部分是浏覽器類型的簡單測試。當我們最後建立選項列表時,我們需要區分開IE 和 Netscape ,因為兩者在指定字體和型號時對選項列表的處理是不同的。為了簡單起見,我將不深入到有關浏覽器兼容性的代碼,因為我還想集中在代碼的關鍵概念上。如果你想知道更多有關兼容性的 問題,你可以參考本文結尾處提供的代碼。
strUA = Request.ServerVariables("HTTP_USER_AGENT")
If Instr(strUA, "MSIE") Then
browserType = "IE"
End If
接下來是對數據庫進行調用,以恢復我們創建多欄列表時所想要使用的記錄集。變量
rsselect 包含返回的設定結果。我是通過一個DCOM 對象spServerObj來實現對數據庫的調用的,在數組中傳遞 參數及其值。但是通過ASP用ADO進行調用也同樣簡單,在這個例子中用一個簡單的選擇語句來恢復記錄集。
Set rsSelect = spServerObj.callAnyProc(proc, parmname, parmval)
或者象在例子中那樣:
Set rsSelect = MyConn.Execute(SQL_query)
然後,我們調整用來容納多選項列表的欄名的值的數組的維數。你可以在開始時就定義好它的維數,但是我們按照討論的流程,在這裡設定數組的維數。所以,在column參數中傳遞的元素數就是在 多欄選項列表中的欄數。
Redim finalMaxLenArray(UBound(column))
第一個主要代碼區是收集格式信息以正確地創建選項列表。代碼區實質上做兩件事。首先,它確定我們的最大欄寬。第二,代碼要將找到的最大欄寬與maxcollen 參數中傳遞的任意值進行協調。
擴展的多欄選項列表(二)
作 者 : 青蘋果工作室 本文點擊次數:4755
與我的例子正相反,你可能希望明確地設置欄寬,而不是在運行的過程中確定最大寬度。代碼區的第一半在記錄集中循環,找到最大值長度,並將它存儲在相應的finalMaxLenArray 索引中。
有一件事需要指出的是你可以將Do?/CODE > 循環安排在外面,For Next循環在裡面。這樣的方法也許更有效,但是我覺得這樣不符合直覺,所以我就沒有改動代碼。
''Loop for formatting the select list values
For i = 0 to UBound(column)
maxStrLenTemp = 0
finalMaxLenArray(i) = 0
'' Loop through recordset to determine the maximum length string
'' in given column
If Not rsSelect.BOF Then rsSelect.MoveFirst
Do While Not rsSelect.EOF
maxStrLenTemp = Len(Trim(rsSelect(CStr(Trim(column(i))))))
If Not IsNull(maxStrLenTemp) Then
If CInt(maxStrLenTemp) > CInt(finalMaxLenArray(i)) Then
finalMaxLenArray(i) = maxStrLenTemp
End If
rsSelect.MoveNext
Loop
'' If the derived col length is greater than the maxcollen parameter
'' then reset col length.
If IsArray(maxcollen) = True Then
If CInt(maxcollen(i)) < > -1 Then
If finalMaxLenArray(i) > CInt(maxcollen(i)) Then
finalMaxLenArray(i) = CInt(maxcollen(i))
End If
Else
If CInt(maxcollen) < > -1 Then
If finalMaxLenArray(i) > CInt(maxcollen) Then
finalMaxLenArray(i) = CInt(maxcollen)
End If
End If
Next
也許你能注意到,在以上代碼中進行了許多整理Trim(exampleVar) 和重塑CInt(examplevar)工作。當你 處理返回的記錄集值時,應該將結果進行一下整理,去掉一些額外的空白。養成整理返回值的習慣能 節約許多調試的時間,是個很好的編碼習慣。當對兩個值進行比較時,將值重塑成所希望的數據類型 也是很好的。因為ASP只有一種數據類型variant,如果不將它們進行重塑的話,簡單的比較過程也會變得難以預料。有時候重塑是多余的(甚至不必要)--但是,我的觀點是只要有疑問,就進行重塑。
代碼的下一部分就是我們實際構造選項列表的地方。現在我們已經有了所需要的格式信息(包含在 finalMaxLenArray中),可以在確定的欄寬的基礎上創建選項列表的單獨的行。開始我們設置 選項列表的第一部分:
< SELECT id="< %=name% >" class="ASPmultiselect"
name="< %=name% >" size="< %=size% >" < %=optattr% > >
這裡我們用許多參數設置選項列表的屬性,如大小、字體(只對IE有效,可以為定寬字體傳遞Font 類屬性)。你可以使用optattr 參數來規定其它任何屬性或列表中所需要的
JavaScript 函數。另外,有時候我打亂ASP代碼而直接寫HTML,而不用ASP的Response.Write 來寫出Html。在保持代碼區不被打斷這方面,有些開發人員是純粹主義者,而我卻覺得這樣帶來的麻煩多於方便。
firstopt參數允許我創建一個空白第一選項,其值與我的參數值相等。如果我將值設置為等於|* , 那麼就沒有空白第一選項。
< % If Trim(firstopt) < > "|*" Then% >
< OPTION VALUE="< %=firstopt% >" >
< % End If% >
然後通過調用MoveFirst Method,將記錄集初始化到它的起點。
< %
''Build the select list now that we have formating info.
If Not rsSelect.BOF Then rsSelect.MoveFirst
Do While Not rsSelect.EOF
然後設置一個臨時變量來保存我們的返回值。這個值最終就是多欄選項列表中給定行的索引值。
valTemp = Trim(rsSelect(val))
下面我們在欄數組中循環。這個數組包含記錄集欄值的名,它被用來為我們的列表返回值。
For n = 0 to UBound(column)
然後我們測試空值。如果值為空,就用空字符串代替它。
If Not IsNull(rsSelect(column(n))) Then
descTemp = Trim( rsSelect(desc(n)))
Else
descTemp = ""
End If
擴展的多欄選項列表(三)
作 者 : 青蘋果工作室 本文點擊次數:4755
下面我們來確定哪裡的欄值長度與我們預先確定的最大長度相關。如果它較大,就將其截斷,反之就增加無間隔空格,使字符串成為用finalMaxLenArray()測量的正確長度。
''strDif Can be negative number if maxcollen is in effect.
strDif = CInt(finalMaxLenArray(n)) - Len(descTemp)
If strDif < 0 Then
descTemp = Mid(descTemp, 1, finalMaxLenArray(n) + 1)
Else
For x = 0 to strDif ''0 for one extra
descTemp = descTemp & " "
Next
End If
然後我們在字符串結尾處增加"|" 字符,然後將那個字符串增加到最後的字符串finalDesc上。 注意循環的次數要與選項列表中的欄數相當,這樣結束時就可以有一個完整的選項列表行。
If n < > UBound(column) Then descTemp = descTemp & "|"
strDif = 0
然後:
finalDesc = finalDesc & descTemp
Next
% >
然後我們就寫出我們的選項值。如果你希望在列表中有經過選擇的值,就要使用許多參數。一旦我們寫完行就回到開頭,將一些參數重新設置成空字符串,用下一個記錄集行將整個過程重做一遍。一旦所有這些選項都寫出來之後,就關閉記錄集和連接,終止函數。為了組合一個錯誤句柄程序,你可能 希望函數返回一個成功代碼。
< OPTION < %If (Not IsNull(selval) Or Trim(selval) < > "") _
And selval = valTemp Then
Response.Write("SELECTED")% > VALUE="< %=valTemp% >" >< %=finalDesc% >
< %
finalDesc = ""
valTemp = ""
rsSelect.MoveNext
Loop
% >
< /OPTION >
< /SELECT >
< %
Set rsSelect = Nothing
End Function
% >
你可以看到,在創建這些多欄列表時包含一些overhead ,無論是在運行的時候還是在最終將它們展示給用戶的時候。有時候調試這些創建列表的ASP代碼是很頭疼的。但是,它們是以有序的方式和正確的位置表現許多信息的很好的方式,是值得花費這些代價的。