作者:excelence轉貼 整理日期:2004年6月15日
本文不只是關於JavaScript的,它是關於Notes/Domino中的JavaScript的!
雖然如是說,不過還是值得一看!
希望你有所收獲!
親密接觸單選按鈕、復選框和JavaScript的一些有趣的事情
我將以對象模型和一些常用對象開始,因為JavaScript裡的一切都是從對象展開的。記住,本文不只是關於JavaScript的,它是關於Notes/Domino中的JavaScript的。
窗口
窗口是對象模型的頂端對象。通常來說,窗口就是你的浏覽器。如果你的窗口裡有幀結構,那麼每個幀結構都依次是一個小窗口,包含在頂層窗口——浏覽器中。我會在另一篇文章裡談幀結構,現在,我們來看浏覽器裡只有一個Web頁面的情況。
窗口有它的屬性,比如它的地址(也就是它的URL),浏覽器底部的狀態條上的文字等等;它也有方法,比如打開和關閉。通常來說,因為窗口在對象層次的頂層,JavaScript就假設Window已經存在了,你不必去刻意寫上它,也就是說“window.location”和“location”的作用是相同的。
窗口裡是Web頁面,它的對象層次從文檔(document)開始。你可以用Window.document來引用它,或者就是簡單的document。每個窗口只有一個文檔(document)。依據你的浏覽器的不同,文檔(document)有幾個變化多樣的選項。在MSIE中,document.all數組包含了文檔(document)中所有的對象。在Netscape Navigator的某些版本中,你可以訪問document.layers數組。每一種浏覽器關於對象的解釋都不一樣,但是表單數組(forms array)在所有的浏覽器中都是可以訪問的。
理論上講,每個文檔(document)包含至少一個表單(form),但是可以包含多個。然而,在Notes中,除非明確寫出用來完成特定功能的HTML代碼(我從來沒那麼做過),通常只有一個表單。但是,因為可以有多個表單,所以你在引用表單時,還是得通過數組元素來引用表單,下標從0開始。不像LotusScript那樣,用圓括號來括住下標數字,比如doc.CompanyName(0),在JavaScript中你通常會看到引用數組下標的數字是括在方括號中的。因此,你應該用下面的方式引用表單:
window.document.forms[0];
或者簡寫成:
document.forms[0];
嚴格來說,上面的方法並不是唯一引用表單的方式,下面都是引用表單的合法的表達式:
document.forms[0];
document.forms(0);
document.forms.0;
然而,你經常看到的還是帶方括號的方式。注意,我在每行語句的末尾加了分號,這是在JavaScript中和公式語言的相似之處之一。你應該在每一條語句的末尾加上分號。和公式語言不同的是,在JavaScript中分號並不總是必需的。有些浏覽器和其他浏覽器比起來,它們可以運行沒有分號的JavaScript語句,所以,盡管有時你可以不用加分號,但是你最好養成每一條語句都加分號的習慣。
當你接觸到表單後,你就已經為訪問你最關心的元素做好了准備。表單是域、按鈕、文本、圖像和其他元素的容器,你將在表單中用JavaScript來處理這些元素。
簡單的幾個元素
對於LotusScript,有件事值得一提:除了Rich-Text域外的元素,如文本、單選框、列表框、復選框等,你可以用幾乎相同的代碼取得它們的值。例如:如果有一個“Location”域,不論它是何種類型,你都可以用下面的LotusScript代碼取得它的值:
fieldVals = doc.Location
或者這樣:
fieldVals = doc.GetItemValue("Location")
在LotusScript中,域的類型對於你要取值(值數組)的代碼並不重要。不幸的是,這對於JavaScript並不適用。在JavaScript中,不同類型的域除了顯示選項(比如單選框、復選框或者文本)外,並不像在Notes裡那樣,它們是不同的類型的對象,每一個都要用不同的方式去引用。其實,那也不是絕對的,有些對象是相似的,但是引用過程並不像在LotusScript裡那麼流暢。你會發現,你將花費很多時間手動尋找你的代碼中的域(名)錯誤來使它們正常運行,那看起來很糟糕。
你首先要知道的一點是:在JavaScript中,沒有所謂的Rich-Text域,在HTML中更沒有。Notes裡提供了一個可以放在浏覽器裡的富文本Java(不是JavaScript)小程序,從而可以得到富文本的一些功能,但是你並不能用JavaScript來對它編程,而且它也不是一個真正的HTML對象類型。
更讓Notes開發人員驚訝的是,在Web上還沒有數字型或時間型的域。HTML的域都是文本型的。盡管你能用它們來收集數字信息,如數量或單價,而保存的數據依然是文本。為了像數字一樣使用它,你必須把它轉換成數字類型。我將在後面詳細講解它。現在,要意識到一切都是文本,就像你在Notes的@Prompt對話框裡輸入的信息一樣。
圖 1
建立表單
為了理解得更深入,你將在我的幫助下做一個小實驗。打開Domino Designer,創建一個新表單,在表單上創建一個名為“Get editable field value”的按鈕和一個名為“CreatedBy”的文本域,把此域的缺省值設成:@V3UserName(如圖1)。
如果你用R5的設計器(Designer),請把觸發按鈕的語言改成JavaScript。如果你像我一樣用R6的設計器(Designer),就要稍微麻煩一些。在Notes/Domino6(ND6)中,你可以像在浏覽器中使用JavaScript一樣在Notes客戶端中使用JavaScript。更重要的是,同一個按鈕在不同的客戶端裡能運行不同的代碼。在圖2中,你將會看到一些選項,你將決定所寫的代碼是在Notes(“客戶端”)還是在浏覽器(“Web”)裡運行。
圖 2
圖 3
這個功能當你在不同的環境裡運行不同的代碼時非常有用,但是當你要在兩種環境裡運行同樣的代碼時怎麼辦呢?當然有比拷貝按鈕代碼更好的方法,你可以在右邊的下拉列表中選擇最下面的Common JavaScript來為兩種環境同時編寫代碼(如圖3)。
在本例中,選擇“Common JavaScript”。
在按鈕腳本中,輸入提示用戶CreatedBy域值的代碼。如果你看過前一篇文章,你就知道可以用點來分隔JavaScript裡的各個層級元素。你的按鈕腳本應該如下所示:
alert(document.forms[0].CreatedBy.value);
需要注意的是,JavaScript區分大小寫。這個規則不只對JavaScript元素(文檔、表單等)有效(首字母小寫),對域的名字同樣有效。你在域中用的什麼大小寫效果,在代碼中必須如實反映。在浏覽器中試驗一下按鈕的功能[Design>Preview in Web Browser>Internet Explorer(或者你自己的浏覽器)]。如果你使用Domino R6的設計器(Designer),你可以在Notes客戶端中進行試驗(Design>Preview in Notes)。
圖 4
如果你在用一個本地數據庫進行試驗(對應的是在服務器上),在浏覽器中你看到的用戶名將是“Anonymous”,而不是你的名字,然而在Notes客戶端中卻是你的名字。原因是當你用Web頁面的方式訪問本地數據庫時,你沒有登錄到服務器,浏覽器不知道你是誰。但是在Notes中,不論是本地還是服務器,你必須登錄才能使用系統。這就是兩種客戶端之間微妙的差別。
另一個區別是在Web上沒有計算域,但並不意味著你不能在你的表單裡加入計算域。你可以加入計算域,計算值將會在Web頁中顯示,除非域是隱藏的。關鍵是即使域就在那裡顯示,而HTML通常的處理是沒有定義域。如果你把CreatedBy域改成計算域而不是可編輯的,在重新測試時你就會明白我所說的意思,你會得到和圖4類似的提示信息。
但是當你在Notes客戶端(R6)裡運行時,即使是計算域也沒有任何錯誤。坦白地說,我還沒有對這個功能是好還是壞下結論,但那就是我們所得到的結果。
這裡產生的錯誤非常重要,你要開始理解JavaScript裡產生的錯誤,因為它對你的代碼調試有很大的用處。那麼當它提示你“document.forms.0.CreatedBy.value”為null值或不是對象時,意味著沒有得到你想要的數據。
當你返回到浏覽器裡,在背景上單擊右鍵,選擇“查看源文件”時,你會看到隱藏在Web頁面下的HTML代碼。你簡單浏覽代碼時,會看到對按鈕和計算域的引用,如下所示:
<input type="button" onclick="alert(document.forms[0].CreatedBy.value);" value="Get editable field value">
<p>Created By:Anonymous
當你對頁面進行過排版的話,你的代碼裡可能會有字體、段落或其他的標記混雜在按鈕和計算域的代碼裡。那些是格式化文檔用的,在此處的討論中可以略過不看。注意看“Anonymous”是表單上的另一個單詞,它沒有任何的標記在兩旁來提示你它是從域產生的。在源代碼中,Anonymous和“Created By”沒有任何區別:兩個在域前面的靜態文本(如果你已經登錄,你將看到你的名字而不是Anonymous)。
為了比較一下,把CreatedBy域改回可編輯文本,保存表單,回到浏覽器並刷新頁面,再看頁面的源文件,將會如下所示:
<input type="button" onclick="alert(document.forms[0].CreatedBy.value);" value="Get editable field value">
<p>Created by:<input name="CreatedBy" value="Anonymous">
代替單詞Anonymous(或是你的名字)的是域的HTML代碼(或者嚴格地講,是HTML的文本輸入框)。它的名字是“CreatedBy”,值是“Anonymous”。這些是通過JavaScript能取得的屬性,而普通的文本卻沒有這些屬性。所以你不能用JavaScript來引用計算域,至少在浏覽器中如此。還有一點令人迷惑的就是當文檔在非編輯狀態下時,即使是可編輯域,也不能用JavaScript來引用它。換句話說,當你保存了文檔再次打開,但沒有把它設置成編輯模式時,頁面的HTML代碼將和CreatedBy域是計算域時相同。另外一個關於JavaScript的有趣的現象是:在Domino以外,我們沒有太多的機會去處理表單的編輯和非編輯狀態,而對於我們Domino開發者來說,這可是個大問題。
你注意到按鈕和域都轉換成輸入對象了嗎?那就是HTML的工作方式。使人迷惑的是兩個對象都有value這個屬性。對於按鈕,value是“Get editable field value”,我想應該是按鈕的標簽,但是域的value值卻是它的實際值。一些其他類型的對象同時有value屬性和text屬性。如果你像我一樣,那麼你有時就會搞不清楚什麼是什麼!就我的經驗而談,最簡單的辦法是讀Web頁面的HTML代碼。
多值
HTML的域沒有Notes的域那樣的多值屬性。可以試一下:在表單上加入第二個按鈕和第二個域。把域命名為“Letters”,類型為可編輯文本,選中“允許多值(Allow multiple values)”復選框。將默認值寫成如下的字母列表:
"A":"B":"C":"D":"E":"F":"G"
把按鈕命名為“Get multiple values”並鍵入如下的JavaScript代碼:
alert(document.forms[0].Letters.value);
你可以用不同的分隔符來改變此域的值,但是當你單擊按鈕時,你會注意到,不論你用什麼分隔符,提示你的總是域的所有值。這和在Notes客戶端中運行的@Formulas和LotusScript形成了對比。用@Prompt,你得到的提示只是域的第一個值:“A”。你用LotusScript同樣也只能顯示一個值,但是你要指定數組下標,否則將得到一個錯誤提示。公式和LotusScript都不能在提示語句中得到多值域的所有值。
原因就是,在Notes的語言中,確實有多個值在域中。對於HTML和JavaScript來說,只有一個值。再次看Web頁面的源代碼你會發現和下面類似的代碼:
<input name="Letters" value="A;B;C;D;E;F;G">
注意它的值是用“一對”雙引號引起來的帶分隔符的值。以後將會詳細討論如何分隔單獨的值,但現在,你應該意識到多值在Web上並不是確切的多值(至少對於文本輸入框是如此)。其他類型域的處理方式和文本域將會不同。
單選按鈕
另一個有趣的地方是單選按鈕,就Notes和Web頁面而言,Notes裡的單選按鈕是一個有多個值的單個域,在Web上是同名的輸入文本框的數組。為了理解以上所述,請看下面的例子:
在表單上,加入另一個新域,名字為“RadioButtn”。正像它的名字一樣,把它改成單選框類型的域。在域屬性窗口的第二個標簽中,輸入下列選項和別名(圖5):
圖 5
One | A
Two | B
Three | C
Four | D
把此域的缺省值設成第一個選項的別名,也就是帶引號的字母“A”。現在在浏覽器裡預覽表單,再看源文件,你會看到單選按鈕的代碼和正常域的代碼有很大區別。HTML代碼看起來將和下面的類似:
<input type="radio" name="RadioButtn" value="A" checked>One<br>
<input type="radio" name="RadioButtn" value="B">Two<br>
<input type="radio" name="RadioButtn" value="C">Three<br>
<input type="radio" name="RadioButtn" value="D">Four
在這裡你要注意一些要點。首先,所有的4個單選按鈕對象有同一個名字:RadioButtn,這樣一來,HTML和JavaScript就知道它們是同一個數組裡的對象。其次,每個選項的值是選項的別名,並不是看到的文字(例如“One”、“Two”等)。這和在Notes中保存的是別名是一樣的,保存的不是看到的文本(當然如果沒有別名的話,保存的值和文本就是一樣的了)。最後,你選中第一個選項的方法是在HTML語句中用的“checked”單詞,它被加在了第一個單選按鈕的語句裡。
如果你再加入另外的一個按鈕,用和取其他兩個域值同樣的方法來取RadioButtn的值的話,你會得到一個奇怪的錯誤,也就是用下面的代碼:
alert(document.forms[0].RadioButtn.value);
你將會看到一個提示“undefined”的錯誤對話框(如圖6)。
圖 6
這裡的問題並不是沒有定義它的值。畢竟如上面所示,單選按鈕的代碼中共有4個值。也就是說,問題出在RadioButtn本身,至少是現在用在這裡的那個。單選按鈕是一個輸入選項的數組,如果你想要知道其中一個元素的值,必須指定是哪一個,試試下面的代碼:
alert(document.forms[0].RadioButtn[0].value);
好,返回的是當前域的值“A”,但是當你選擇其他的選項時再單擊按鈕,你得到的依然是“A”,而不是你所選擇的值,還是不太妙。
為了得到選擇的選項的值,首先要知道哪個選項被選中了,然後在alert語句中,用那個選中的選項的下標值來正確地引用當前選項的值。也就是說,如果第一個選項被選中,你應該取RadioButtn[0].value,如果第二個選項被選中,你就應該取RadioButtn[1].value,依此類推。
在JavaScript中,某些類型的域具有selectedIndex屬性,代表當前選中選項的數組下標值。然而單選按鈕並不是那麼幸運,同樣,復選框也沒能逃脫厄運。要想得到當前選中的單選按鈕的值,你必須在RadioButtn數組元素中查找“checked”屬性。和LotusScript相比,LotusScript就能像操作其他類型的域一樣來取得單選按鈕當前被選中的值。這是一件非常麻煩的事,但是,它就是那樣的。
下面是按鈕的代碼:
var doc = document.forms[0];
for(i = 0; i <
doc.RadioButtn.length; i++){
if(doc.RadioButtn.checked){
alert(doc.RadioButtn.value);
break;
}
}
這裡馬上就出現了幾個新概念,讓我花點兒時間來解釋一下。首先,如果你讀過前面那篇文章,你就會知道“var”是在JavaScript裡用來聲明變量或給變量賦值用的,就好比LotusScript裡的“Dim”和“Set”。既然這樣,為了避免一遍一遍地輸入document.forms[0],我就把document.forms[0]賦給變量doc以備後用:
var doc = document.forms[0];
下面是循環,循環體中沒有代碼時的樣子如下:
for(i = 0; i < doc.RadioButtn.length; i++){
}
你是不是有點眼花缭亂?我以前每次看到類似這樣的代碼就眼暈,但是它並不像它看起來那麼糟。首先,花括號只是用來包含循環體的。JavaScript的for循環有三個選項:
1. 計數變量以及它的初始值(i=0);
2. 如何知道繼續循環(i < doc.RadioButtn.length);
3. 如何累計計數變量(i++)。
首先是i=0,很簡單,我使用了變量i並且它的初始值為0。
第二部分:i<doc.RadioButtn.length,它可有點兒不太直觀。JavaScript的length屬性具有不同的使用環境,如果你要檢查一個普通文本域的length,比如在表單上的CreatedBy域(document.forms[0].CreatedBy.length),你會發現length是域中文本的字符個數。比如Anonymous,length就是9。對於數組,比如RadioButtn數組,length是數組中元素的個數。不像數組下標那樣從0開始,length從1開始。因此,如果RadioButtn數組的最後一個元素下標是3,length的值就是4。在循環中,我讓i從0開始計數循環,直到它小於4為止。因此,循環體共循環4次,i的值分別是0,1,2,3,以數組的最後一個元素的下標結束(我承認有點兒混亂)。
循環體中的第三個參數:i++,對於LotusScript開發人員來說是一個低級錯誤。這是在JavaScript中的簡寫方式,i++的值和i=i+1的值是一樣的。實際上,你可以在循環中用兩種形式的任何一種,所以下面這種寫法和上面的寫法是等價的:
for(i = 0; i < doc.RadioButtn.length; i = i + 1){
}
i=i+1同樣可以正常運行,但是問題是沒有人那麼做,因為你習慣i++後,它更短小、更簡單。它的價值在於,你還可以寫i--,和i=i-1是一樣的,當然,在這個循環裡它不能運行。用i++你還可以做許多看起來很有趣的事情,但那是以後的事了。
再來看循環:三個參數用分號分隔並由圓括號包圍,循環體代碼用花括號包圍,循環體中是一個if語句:
if(doc.RadioButtn.checked){
}
這裡的判斷真假的語句同樣也用圓括號包圍。試驗中的doc.RadioButtn.checked看起來沒有提供充足的信息,但它和循環一起構成了一個JavaScript的簡寫方式。如果用LotusScript的方式呢?我首先會去檢查當前的RadioButton元素是不是等於checked,像下面的方式:
doc.RadioButton[0] = "checked"
由於checked是一個屬性而不是一個值,所以上面的代碼不能正確運行。你還會注意到在HTML中它並沒有用引號引起來。其實,checked是一種"是"或者"不是"的東西。更准確一點說,它不是真就是假,所以那個if語句的意思就是:如果RadioButtn的這個元素是checked(被選中的),即:為真,那麼就做下面的事情……這裡的試驗看起來有點奇怪,因為始終沒有提到真假。如果那讓你感到不舒服,你還可以很輕松地這樣寫if語句:
if(doc.RadioButtn.checked == true){
}
注意這裡的true全部是小寫而且有兩個等號。和LotusScript中不同,JavaScript裡的等號(=)只是用來把一個值賦給另一個什麼東西:
var doc = document.forms[0];
為了比較兩個項目是否相等,你必須使用兩個等號。在我的頭腦裡,我想它的意思是:doc.RadioButtn.checked等於true,這樣來幫我記住要用兩個等號。雙符號標記同樣適用於&符號(使用一個時用來追加或連接字符;使用兩個時表示“and”,比如在一個if語句裡用兩個判斷條件時)。
最後,在if語句裡是一個alert語句,緊跟著一個break。break就是JavaScript裡的Exit For。它終止循環,因為一個單選按鈕只能有一個選項被選中。
如果你把所有的代碼都放入按鈕裡,你就會看到無論你選擇單選按鈕的哪個選項,單擊按鈕後都能正確的顯示出選項的值。非常棒,現在你對JavaScript已經入門了。
復選框
復選框和單選按鈕類似。在表單上,復制單選按鈕域並改名為"CheckBx",更改域的類型為"CheckBox(復選框)",保存表單,刷新Web頁面並查看源文件。你將看到復選框的HTML代碼和RadioButtn的幾乎一模一樣:
<input type="checkbox" name="CheckBx" value="A" checked>One<br>
<input type="checkbox" name="CheckBx" value="B">Two<br>
<input type="checkbox" name="CheckBx" value="C">Three<br>
<input type="checkbox" name="CheckBx" value="D">Four
真正的區別不是域名,而是類型是復選框,不是單選按鈕。另外一個區別就是你可以選擇復選框中的多個值,盡管你還要像操作單選按鈕那樣遍歷整個復選框來確定哪個選項被選中,但是你不能在全部檢查完是否選中之前停止遍歷動作。按鈕中用來檢查復選框選中的代碼會像下面的樣子:
var doc = document.forms[0];
for(i = 0; i < doc.CheckBx.length; i++){
if(doc.CheckBx.checked){
alert(doc.CheckBx.value);
}
}
我確信到現在為止,你應該多多少少熟悉這些代碼了,因為這和單選按鈕基本一樣,除了域名的改變和去掉了"bread"語句。在一個實用的程序中,這些代碼所做的工作比我做的要多得多,但是首先我希望你很舒服地學完這些基本內容。
等待更多的對象
你還有幾個類型的域需要了解,每一種都有自己的特性,但那是另一篇文章的素材。現在,你可能要用自己的試驗來熟悉這裡的例子了。你也可能要向表單中加入更多的、我還沒有涉及到的域,並查看它們的HTML源文件,那是我們下次的開始部分,再見。
參考資源
本文摘自 2003.6 《Lotus Magazine 簡體中文版》:《Lotus Magazine 簡體中文版》作為國內第一個專注於IBM Lotus技術的刊物,其內容主要源自美國Lotus方面的相關頂級技術刊物,面向廣大Lotus管理及開發人員,向您展示最新最前沿的Lotus相關技術。歡迎 申請贈閱。
Lotus相關專題 :如果您是對Lotus感興趣的開發人員,想進一步了解Lotus產品家族,熟悉Lotus產品是如何和IBM其他的產品一起協同工作的,Lotus是如何支持諸如XML、Web服務等等業界的開放標准的,如何用Lotus進行J2EE的開發,即刻訪問 IBM developerWorks 中國網站的 Lotus相關專題 。在這裡,我們為您精心收集了相關的文章、教程、紅皮書,相信對您的開發會有所幫助。
關於活動下拉列表框和模糊查詢的問題
我欲在下拉列表框中輸入部分文字,再將從數據表class中模糊查詢的結果在下拉項中顯示出來,寫了如下代碼,但<select>中不讓自己輸入內容,請教高手們應該如何解決?<% dim tianjian
%>
<script language = "JAVAscript">
var onecount;
coecount=0;
function changelocation(locationid)
{
var locationid=this.classid.text;
tiaojian=locationid;
<%
strConnString = "Provider=Microsoft.Jet.OLEDB.4.0;Data Source=" & Server.MapPath("Database/bgxt.mdb")
set db = Server.CreateObject("ADODB.Connection")
db.open strConnString
Set rs= Server.CreateObject("ADODB.Recordset")
sql="select * from class where Nclass like '"&tiaojian&"'"
rs.open sql,db,1,1
count=0
do while not rs.eof
%>
subcat[<%=count%>]=new array("<%=trim(rs("Nclass"))%>","<%= trim(rs("classid"))%>","<%= trim(rs("Nclassid"))%>");
<% rs.movenext
loop
rs.close
%>
onecount=<%=count%>;
document.myfrom.classid.length=0;
var locationid=locationid;
var i;
for(i=0;i<onecount;i++)
{
document.myform.classid.options[document.myform.classid.length]=new option(subcat[i][0],subcat[i][1]);
document.myform.classid.length=documen.myform.classid.lenght+1;
}
</script>
<form name="myform" method="post" action="temp1.asp">
<table width="75%" border="1">
<tr>
<td width="55%"><div align="center">
<select name="classid" size="1" onchange=changelocation(this)>
</select> </div></td>
</tr>
</table>