close

看到 李忠憲sean@tp.edu.tw 老師的這篇文章,忽覺茅塞頓開...

JavaScript 觀念終於比較清楚了

From 網路文章

http://newweb.syups.tp.edu.tw/documents/memo/Jscript/jscript.htm


動態網頁程式設計

李忠憲sean@tp.edu.tw

2004/9/10 初稿
2005/11/17修改

動態網頁概念

DHTML是 Dynamic HTML 的簡稱,相較於 HTML 它更強調網頁的動態表現,所謂動態網頁即是指:網頁在瀏覽器中能依據參觀者的操作或時間狀態的變化適時地改變網頁內容。由於 HTML 僅能依靠標記語法來展現網頁內容,並沒有動態改變的能力,因此必須將網頁內容物件模型化(DOM)接著透過 Script 語言來操控它的內容,另外再結合事件驅動機制以便反映參觀者的操作,同時為了讓動態網頁能展現更精彩的視覺變化,又加上了串接樣式表 (CSS:Cascading Style Sheet)的支援,如果用公式來表示,可以寫為:

DHTML = DOM + Events + Script + CSS

 

網頁物件模型(DOM)

物件這個名詞在程式設計領域裡,是一個很重要的觀念,它是從靜態的資料結構(例如:陣列) 蛻變出來的。既然我們可以把靜態的資料結合組裝成各種結構,是不是也可以應用同一種思維把片段程式碼重新組裝成獨立的有機結構?基於這個想法而發明了物件 導向程式設計,運用這個方法寫程式,我們可以根據程式的需求盡情地重新組合物件,就有如將積木組合成千變萬化的各種形狀一樣。例如:網頁不也是從有限的標 籤中組合成無限的版面變化。

程式運作需要使用變數或把變數組合成資料結構,有時候程式也需要輸入或輸出變數值,因此所 謂物件應該包含: 內建函式、私有或公用變數、變數預設值,而其中某些關鍵變數值可以從物件外部直接指定或變更。以上所談的雖然只是物件的基本概念,其它更重要的概念(例 如:物件類別、物件繼承、函式覆疊、函式多形化、從屬物件、執行實體......等等)在本次課程中用不到,就不予介紹了。

雖然微軟公司也引用物件導向設計觀念,來處理網頁物件模型(DOM),但是它卻又自己發明許多新名詞,譬如:內建函式被改稱為方法(method),變數則被稱為屬性

在討論網頁物件模型之前,為了讓往後的敘述能夠更清楚的表達概念,我們有必要先知道幾個專有名詞, 在底下的 HTML 語法中:

<a id="mymail" href="mailto:sean@tp.edu.tw">sean@tp.edu.tw</a>

a 稱為標籤(TAG), href 稱為 a 標籤的屬性,使用雙引號夾住的字串稱為參數,/a 則稱為結束標籤。 id 這個新屬性是為了配合 Script 程式設計而增加的,並非 HTML 的固有屬性,一般在討論 HTML 標籤時都會將它忽略,該屬性的參數 mymail 就是 a 標籤的識別代號。

我們把它物件模型化以後,上述的標籤就會變成一個物件容器,這個容器的範圍是從 <a> 一直到 </a>,上述的 href 屬性就變成此物件的變數,而屬性的參數就轉變成變數值,變數值可以透過 Script 語言直接指定,例如:

mymail.href="http://www.syups.tp.edu.tw"

網頁內容物件化以後,除了可以隨意變更屬性的值之外,容器內的顯示內容也可以變更,如果想把上述超連結標記中的 sean@tp.edu.tw 字串改為 "三玉國小",程式如下:

mymail.innerTEXT="三玉國小"

在 DOM 中除了將所有的標籤轉換為對應的物件外,為了方便程式寫作還把同一性質的物件匯集成物件集合(物件組成的陣列),例如把網頁中所有的超連結集合成為 anchors 陣列,因此上述 mymail 物件還可以寫成:

document.anchors("mymail") 或 document.anchors(0)

註:document 就是 <html> 這個標籤的物件化。

 

DOM 樹狀階層結構

在 IE DOM 裡面,最大的物件是 window,它也是 DOM 裡面少數沒有對應標籤的物件之一,window 事實上就是 IE 主程式所開啟的視窗,我們可以透過它來呼叫 IE 的程式功能表或狀態列。window 有六個從屬物件和一個物件集合,表列如下:

navigator

這個物件用來偵測瀏覽器名稱、廠商、版本、能力...等
external 這個物件用來呼叫 IE 主程式功能表
history 也就是瀏覽器中的歷史清單,用來跳到上一頁或下一頁
location 這個物件就是 IE 的網址列
screen 這個物件就是目前桌面的螢幕設定
event

雖然每個物件都有自己的事件處理器,但若是要寫一個互動遊戲,需要規劃每個鍵盤按鍵的功能,就不能沒有一個綜觀全局的前置處理器,event 物件可以說是所有事件的統一指揮中心

document 這個物件就是對應到整個網頁的內容(從 <html> 到 </html>)
frames

是框架物件的集合,假如網頁有使用框架的話,則在 window 與 document 之間,將會多出這一層

對於程式寫作來說,我們應該把焦點放在 document 物件上,底下列出 document 物件常用的從屬物件及物件集合,分述如下:

body

這個物件對應 <body> 標籤,用來處理背景圖及捲軸棒樣式
all

所有標籤對應物件的集合(body 物件不算,因為一份文件只有一個 body)

anchors 所有 <a> 標籤的集合
applets 所有控制元件(<applet> 標籤)的集合,例如:JAVA、Flash、AVI電影、統計圖表....等
embeds 文件中所有 <embeds> 標籤的集合
filters CSS 視覺濾鏡的集合
frames 所有嵌入框架(<iframe> 標籤)的集合
forms 所有輸入表單(<form> 標籤)的集合
images 所有圖片(<img> 標籤)的集合
stylesheets 所有樣式性質的集合(定義在 <style> 標籤裡的才算)

DOM 中除了最大的 window 物件以外,其它的物件都有所謂上層物件(或稱為父物件),而我們在表達物件的不同階層時,是使用 . 來連接上層物件與從屬物件,例如:document 物件可以表示為:

window.document

在上一小節的範例中:

<a id="mymail" href="mailto:sean@tp.edu.tw">sean@tp.edu.tw</a>

我們要存取這個超連結,雖然可以簡略寫為:

mymail.href="http://www.syups.tp.edu.tw"

但正式的寫法應該是:

window.document.anchors("mymail").href="http://www.syups.tp.edu.tw"

我們再以底下的例子來練習一下:假設某一個網頁上有一個表單其 id 為 addForm,該表單中有一個文字方塊 id 為 email,那麼我們就可以使用底下的語法來讀取參觀者輸入的郵件地址:

mail_addr=window.document.forms("addForm").elements("email").value
或簡寫為
mail_addr=window.document.addForm.email.value
或寫為
mail_addr=window.document.all("email").value
或是省略 window 和 document
mail_addr=addForm.email.value

對於開發 Java Script 程式來說,了解並熟悉如何存取物件,是至關重要的一件事,希望在這個小節結束之前,讀者都能熟習上面這些語法。

 

事件驅動與沸升

事件驅動並非為了 DHTML 而發明的,事實上整個 windows 作業系統就是以事件驅動的方式在運作。當參觀者移動滑鼠游標在 IE 的視窗內游走時,滑鼠的游標位置就會透過滑鼠驅動程式回報給作業系統,作業系統將此一事件轉換成描述字串,稱為事件訊息(event message),事件訊息會被傳送給所有執行中的程式,讓程式自己決定是否要回應或忽略,假設該訊息傳送給 IE 主程式,主程式依據座標判斷,發現滑鼠游標正移到網頁的某圖片上,因此決定給予回應。於是呼叫該圖片的事件處理程式出來執行。

網頁物件化以後,為了讓程式設計師能根據不同事件自由地處理回應方式,因此在每個物件上設計有事件處理器,此一程式容器為事先定義好的空函式,其內容可以由程式設計師自由取代,以上面的例子來說明,假設該圖片的 onMouseOver 處理器已經填入一支叫做 change_pic 的函式,如下:

<img id=mypic src="title1.jpg" onMouseOver="change_pic()">

然後,程式設計師便可以在事件處理程式 change_pic 中,讓該圖片進行動態切換,例如:

<script>
function change_pic() {
    mypic.src="title2.jpg"
}
</script>

由於網頁上不同的物件能允許的操作不同,例如:文字方塊可以輸入,而按鈕不能輸入;按鈕可以按,而文字標籤(<label>)不能按,因此並非所有物件的事件處理器都一樣多,例如:在 body 標籤中就不存在 onMouseOver 這個處理器。

另外,網頁的物件經常是 "大餅包小餅",而事件的觸發也會沿著物件的階層結構逐漸遞移。不過要特別注意的是:作業系統由於要管理的程式繁多複雜,如果事件是由上層物件配發給從屬 物件去處理,等到分配完畢開始處理時,恐怕會曠日費時!因此,事件的處理是由末端的從屬物件優先處理,處理不來時才交給上層物件負責,以免發生末梢神經潰 爛的問題。

舉個實例來說明,當我們在一個文字方塊上滾動滑鼠滾輪時,由於文字方塊並沒有 onScroll 事件處理器,因此它並沒有足夠的能力回應這個動作,於是事件就被傳遞給 它的上層 Form 表單處理,但由於 Form 表單一樣欠缺 onScroll 事件處理器,它並不知道如何去因應滾輪事件,於是又再次向上層物件求助,將事件交由 document 處理!接著我們就會看到網頁上下捲動了!

這種事件從 "小餅傳給大餅" 的現象,我們稱為事件沸升。如果我們不想把已經發生的事件通知上層物件,則可以在事件處理器中傳回 false 。例如:

<a href="http://www.google.com" onClick="return false">快按我!沒事發生</a>

觀察上面的 HTML 語法,我們發現當參觀者按下超連結時,onClick 事件處理器會傳回 false,也就是說,超連結物件告訴它的上層物件 window,叫它不要理會超連結被觸發的事實。於是原本應該觸發 window 物件上的 onUnload 事件,這時就不會被觸發,載入新網頁的動作遭到阻止,網頁當然就不會切換到 www.google.com!

哪些網頁物件具有哪些事件處理器呢?請參考研習所發的 Java Script 參考書籍,裡面有詳盡資料可供翻閱參考。

 

串接樣式表(CSS)

串接樣式表是為了弭補 HTML 的排版功能不足而設計的,透過 CSS 原本 HTML 表現不出來的聲光效果,現在已經獲得大幅度的改善 。所以當我們使用 MS Word 編輯 doc 的文件時,可以原封不動地轉換成網頁顯示出來,其關鍵就在於使用了 CSS。

CSS 讓 HTML 標籤有了底下的新功能:

  1. 能夠以像素(px)為單位精準的定位:過去只能使用相對位置來佈置版面,透過 CSS 允許改用絕對位置來擺放網頁元件。

  2. 將色彩及背景變化擴充給所有的容器物件:過去不能設定段落的背景,不能讓表單元件顯示顏色,不能改變邊框的大小樣式,現在透過 CSS 愛怎麼變就怎麼變!

  3. 網頁上的元件具備 2.5D 的圖層概念:透過 z-index 這個性質,可以讓網頁元件互相交疊,配合 Script 程式設計出各種動畫演出的效果!

  4. 能夠將網頁元件暫時隱藏或顯現:程式設計師使用這個新的 visibility 性質,很容易設計出可以摺收的功能表單。

為了與 HTML 相結合,CSS 被設計成 HTML 標籤的一個屬性 style,例如:

<div id=mydiv style="color: #FF0000 ; font-size: 11pt">這段文字使用 CSS 排版</div>

而參數"color: #FF0000 ; font-size: 11pt" 還可以進一步分析,colorfont-size 稱為性質,當性質超過一個以上時,中間用 ; 隔開。

初學者經常分不清屬性與性質這兩個專有名詞到底有何不同,經過以上的說明應該能夠分得清楚!

在網頁物件模型中,style 標籤不會被轉換成變數,而是轉換成變數集合,例如:要改變上面那個 div 標籤中的文字顏色,可以寫成:

mydiv.style.color="#00FF00"

而非寫成:

mydiv.style="color: #00FF00"

CSS 除了上面已經介紹過的嵌入式寫法,還有其他兩種不同寫法。第二種寫法是將所有屬性會用到的排版樣式定義在 <head> 和 </head> 中間,例如:

<style>

</style>

採用這種宣告式的寫法與嵌入式寫法不同的地方,在於可以指定作用範圍。 嵌入式寫法只作用於單一物件,而宣告式的寫法如果是指定作用標籤(上例第一行),則該網頁上所有同一標籤的物件, 都會一起套用該樣式。如果是指定物件編號(ID,如上例第二行),那麼所有要套用該樣式的物件,就必須將 ID 指定為 mydiv

比較特別的是,使用宣告式的寫法還可以指定要套用的狀態,例如:a:hover 代表當滑鼠移過超連結標籤時的特殊狀態,而 body:print 代表當文件被送到印表機列印時的特殊狀態。

第三種方式則是將CSS的設計寫在一個獨立的純文字類型檔案中,而在每一頁網頁開頭載入這個樣式表,這樣的方式比較適合大型的網站,例如學校官方網站。

當網頁數量多到一定的量的時候,我們會採取將 CSS 作成獨立的一個文字檔,再由網頁套用,這樣我們可以只要變更CSS 的設計就 可以讓所有的網頁一起更換風格了。 這樣還有一個好處是我們可以指定某個 URL 的 CSS 檔案套用在這台伺服器上的 CSS 檔案。

本機
<link rel="stylesheet" type="text/css" href="style.css">
連到別台伺服器
<link rel="stylesheet" type="text/css" href="http://www.xxps.tp.edu.tw/css/style.css">

這樣的樣式表通常經過精心規劃和設計,因為考慮較多,指定的元件樣式也相對增多。下面這個例子中,作者甚至也把整個網站都不讓別人按滑鼠右鍵的『秘密』JavaScript 也一併放入這個CSS檔案中:

檔名: style.css

body                   { background-image: url("/images/bk.jpg"); background-attachment: fixed }
a:link, a:visited   { color: #009; background: none; text-decoration:none; }
a:hover, a:active { color: #fff;
                              background: #666;
                              text-decoration: underline; }
</style>
<script>
document.onmousedown = noSourceExplorer;
function noSourceExplorer() {
        if (event.button == 2 | event.button == 3) {
                alert("按右鍵?麥哥看啦");
       }
}
</script>

注意:這個檔案不用再寫 <style> 和 </style> 標籤,因為在 <link rel="stylesheet" ...... > 中已經宣告過了,IE 會自己在檔案開頭加上 <style> 標籤,在結尾加上 </style> 標籤。上面的範例之所以加上 </style> 純粹只是為了銜接 <script> 而已。

另外,我們也可以把好幾種設定好的不同元件的幾個樣式表 CSS 檔,用@import 讀到同一個樣式表中,不過要記得要把這些 @import 的樣式表寫在 body 樣式之前,否則 @import 會失效。例如:

<style type="text/css" media="print, handheld">
@import "table.css";
@import url("../css/title.css");
@import url("http://www.xxps.tp.edu.tw/css/form.css");
body    {background-color:#ddeeff; }
</style>

雖說樣式表非常好用,但樣式表在不同的瀏覽器有著不同的屬性設定,有的功能支援有的不支援,Mac/Linux PC上的 Netscape Navigator/Mozilla 等新版瀏覽器也支援不少新的 CSS 屬性設定,如果您設計的網頁或程式要提供的對象是電腦玩家,基於尊重訪客,可能就要多花點心血了解不同瀏覽器上設計的限制;如果對象大多是家庭、學生、老師類型的使用者,使用的瀏覽器大部分是以 IE5.0~6.0 為主,設計上就比較單純了。

對於一個 Web 網頁程式設計者而言,在 CGI 原始碼中,想要手動編寫大量的 HTML 標籤,來改變介面風格,實在是太辛苦了。想建構一個令人賞心悅目的風格的網頁介面的設計人員,為了能節省修改網頁的時間和提高工作的效率,更須仰賴 CSS 的控制。因為只要修改一個站台外掛的 CSS 檔中的設計,總比去修改整個站台中成千上萬個網頁裡的樣式表,來的有效率多了。

更多的樣式表性質和控制方法,請參閱研習發放的 CSS 語法參考字典。

 

第一支程式

或許您已經發現,前面介紹的 DHTML 部分內容 ,在實作上我們常會使用到 JavaScript 。

平常我們使用到 JavaScript 大多是用來作一些網頁特效、或用來讓瀏覽器互動性更強,或將檢查使用者表單是否填寫正確的工作交由 Client 端電腦分擔,我們希望透過下面的實習課程,讓您能深入了解 JavaScript 控制網頁元件的特性和語法,也特別要學習表單上的元件控制,因為那對 Web-base 應用程式的開發來說非常重要。

一般說來 JavaScript 可以放在 <html> 標籤內的任意位置, 但當它執行時,如果須與網頁元件互動,則須擺放在特定位置,以下面範例而言,必須擺放在 <body> 標籤內才行。它用 <script> 標簽作為開頭,以  </script> 作為結束。開頭可以加上使用的語言類型(VBScript 或 JavaScript),像這樣:<script language="JavaScript">(此標籤內的英文字母大小寫均可接受 ),如果沒有指定語言時預設使用 JavaScript。例如:

<html>
<head><title>第一課</title></head>
<body>
    <script>
        alert("JScript 向您問好!")
    </script>
</body>
</html>

JScript 程式碼的部分是會區分大小寫的,所以我們不能像寫 HTML 標籤一樣,任意混用大小寫!

 

註解怎樣寫?

像 html 一樣,您可以在 JScript 裡面插入註解行。標明註解的方法有兩種:

<script language="JavaScript">
    //這是註解文字,不會被瀏覽器執行
    /* 這個段落也都是註解
        不會被瀏覽器執行
        真的,不騙你*/
</script>

 

讓 JScript 跨越平台

W3C 所制定的 DHTML 標準雖然被 NetScape 和 MicroSoft 兩大瀏覽器廠商支援,但兩家廠商的做法卻不統一,因此也就引發了 JavaScript 無法跨越平台的苦果。事實上要跨越平台並不難,只是寫程式時要多費點心,首先是偵測瀏覽器平台:

<script>
      ns= (document.layers) ? true : false
      ie= (document.all) ? true : false
      .................. 省略的地方請見後文...................
</script>

上面程式使用三元運算子來判斷瀏覽器平台,這個三元運算子其實就是 IF 敘述的簡略寫法,改寫第一行如下:

      if (document.layers) {
          ns=true
      } else {
          ns=false
      }

得知瀏覽器平台後,在寫程式遇到兩個平台語法不同的地方,就可以用程式技巧避免,例如,要改變底下標籤的顏色:

<div id=mydiv style="color: #FF0000">這段文字使用 CSS 排版</div>

NS 的寫法是:

document.mydiv.color="black"

document.layers("mydiv").color="black"

MS 的寫法是:

mydiv.style.color="black"

document.all("mydiv").style.color="black"

使用變數就可以讓兩個平台相容:

if (ns)   obj=document.layers("mydiv")
if (ms)  obj=document.all("mydiv").style
obj.color="black"

兩平台的差異,除了上述物件模型的不同外, CSS 支援的情形也不同,需要特別留意。舉例如下:

性質

Netscape IE
left 50 50px
top 100 100px
visibility show visible

 

當網頁碰上 JScript 錯誤

Java Script 在網頁上展現效果時,常常會因為網路擁塞,網頁傳輸進行到一半時,有時候 Java Script 尚未傳完,這個時候使用者不耐煩了,去操作網頁上的某個元件,或使用滑鼠不小心觸動了某一個事件時,瀏覽器會發現該事件所控制的 Script 程式碼不存在(還沒傳回來),而跳出一個偵錯訊息的詢問視窗,要求進行網頁偵錯。

有時候剛好反過來,Java Script雖然已經傳好了,但是某些網頁元件如圖片、表單、或按鈕等,因傳輸速度不良,尚未載入到瀏覽器上,這時候,若是您設計的 Java Script 程式碼,嘗試去改變該元件的屬性時(例如改背景顏色等),就會造成 Java Script 執行錯誤,還是送您一個偵錯視窗!

在設計上,這兩種錯誤其實是可以避免的,可以參考下列方法:

  1. 第一種方法是把您寫的 Java Script 放在 HTML 文件的 <HEAD> 和 </HEAD> 之間,那麼當網頁準備要顯示在瀏覽器時,程式一定已經完全傳輸完畢了。這種方法可以避免第一類型的錯誤。

  2. 需要改變到網頁元件屬性的程式碼,必須撰寫包裝在函式裡,然後去檢查網頁是否已經傳完,如果傳完就允許執行。這樣可以避免第二類型錯誤。

  3. 怎樣檢查網頁是否已經傳完了呢?我們可以設定一個變數(例如:ok),然後在 <BODY> 的 onLoad 事件中去改變這個 ok 變數的值,因為 onLoad 事件只有在瀏覽器備妥網頁文件時才會觸發。當 onLoad 事件完成,傳回 ok = 1 ,如此一來,我們只要檢查變數的值有沒有變成 1 ,就可以得知網頁是否已經備妥!

舉例來說:前文跨越平台的程式中,我們將網頁上的某個 <div> 物件存到一個變數裡,以便解決相容問題,而在程式執行時,假如網頁還沒有載入完成(瀏覽器尚未將 <div> 標籤處理好),這時候就不能透過變數去存取該物件,否則會造成 Java Script 執行錯誤。為了避免此錯誤發生,我們改寫程式如下:

<html>
<head>
<script>
      ns= (document.layers) ? true : false
      ie= (document.all) ? true : false

      function init() {
          if (ns)   obj=document.layers("mydiv")
          if (ms)  obj=mydiv.style
      }
</script>
</head>
<body onload="init()">
<div id=mydiv style="color: #FF0000" onMouseOver=" obj.color='black' ">這段文字使用 CSS 排版</div>
</body>      
</html>

當 Java Script 程式內嵌在事件處理器時,如果會使用到雙引號,務必改寫為單引號,以免因雙引號過多造成程式無法解讀。

 

控制瀏覽視窗

window 物件可以用來操控視窗、蹦現對話框或開啟新視窗,分述如下表:




window.status="歡迎光臨本站" 變更狀態列顯示內容

w=window.outerWidth
h=window.outerHeight

取得視窗大小
window.resizeTo(500,400) 變更視窗大小
window.moveTo(100,50) 移動視窗位置

window.scrollTo(400,0)
window.scrollBy(0,50)

捲動視窗到特定座標
捲動特定的像素

window.print() 列印視窗內容




window.alert("嗨!您好嗎?") 顯示蹦現訊息
ok=window.confirm("確定嗎?")

顯示確認視窗
ok 為真時,代表參觀者按下確認鈕

name=window.prompt("您的大名:")

顯示輸入視窗
name 為輸入的字串




window.open("mypage.htm") 將網頁開啟在新視窗
window.showModelessDialog("a.htm") 開啟的新視窗無法改變外觀
window.showModalDialog("a.htm") 不但無法改變外觀,而且會獨占桌面
window.showHelp("readme.htm") 用說明文件方式開啟新視窗

開啟視窗函式還可以指定視窗的外觀,這部分的參數非常多,請自行參考研習用書的附錄,裡面有詳細說明!

以上程式範例,window 這個字是可以省略不寫的,所以把 window.alert() 寫成 alert() 也可以正常執行。

 

呼叫 IE 主程式功能表

external 物件用來執行 IE 主程式功能表內的動作,例如:想要把網頁加入我的最愛裡面,可以使用底下的程式:

external.AddFavorite("http://www.syups.tp.edu.tw", "台北市士林區三玉國小")

想要將網頁設定在桌面上,可以使用底下的程式:

external.AddDesktopCmponent("http://www.syups.tp.edu.tw", "台北市士林區三玉國小", 100,0,800,600)

external 物件其它可以呼叫的函式還有:

AddChannel

加入頻道,所謂頻道是指訂閱後會自動更新以方便離線閱讀的網站內容

AutoCompleteSaveForm

將表單內容存入自動完成

AutoScan

自動搜尋與指定字串相關的網頁

ImportExportFavorites

匯入或匯出我的最愛

IsSubscribed

檢查用戶端是否已經訂閱某頻道

NavigateAndFind

連到指定的網頁,並且將指定字串標示為選取狀態

ShowBrowserUI

開啟作業系統各種設定對話框

詳細用法請參考
http://msdn.microsoft.com/workshop/author/dhtml/reference/objects/external.asp

 

讓程式跨越框架

window 物件是 DHTML 模型的最上層,簡單說就是目前的視窗,它也可以是被某個框架頁包住的視窗 。在一個有多框架頁(Frame) 的 window 物件裡,它使用 frames 物件集合來儲存每一個框架,但同時每一個被切割的框架,也都內含一個 window 物件,如下圖:

frame 1

[主選單]

window.frames(0)

frame 2

[內容]

window.frames(1)

在這個範例中 window 物件(注意: window 後面沒有加上 's')是最頂層,也就是我們說的父視窗,每個切割的 frame 都是 window 物件的子集合,對於左邊的 [主選單] 視窗,我們可以用 window.frames(0) 來表示。

當我們在 [主選單] 網頁中寫程式要控制右邊的 [內容] 網頁時,必須寫成 parent.window.frames(1) ,這時由於程式位於下層的 [主選單] 網頁 中,要先用 parent 去參照到上層的父視窗,然後才能存取右邊的框架。如果直接寫成 window.frames(1) 則因為 [主選單] 網頁本身並未再分割成數個框架,而導致程式發生錯誤,跳出 "物件不存在" 的錯誤訊息。 (parent 是一個指標型的變數,它用來參照其它物件。除了 parent 之外,在控制框架時,也經常使用其它兩個指標:top 和 self,前者參照到最頂層的父視窗,後者參照到目前程式所在位置的框架)

因此,如果我們想要在 [主選單] 中放一個超連結,讓網頁參觀者點一下就可以關閉視窗,可以這樣寫:

<a href="javascript: parent.close()">關閉</a>   還記得嗎?window 物件可以省略不寫。

在上面範例中,有別於以往的是,我們不再使用事件驅動來呼叫這支程式,而是改用超連結呼叫它,關鍵字 javascript: 相當於 URL 中的 http: ,是用來定義超連結的類型。當我們使用超連結呼叫 Java Script 時,不要忘記先宣告超連結類型為 javascript:!

 

載入新網頁

location 物件含有目前網頁的 URL 資訊,藉由變更 URL 字串,我們就可以重新整理目前網頁或載入新網頁,範例如下:

<input type="button" value="三玉國小" onClick=" location='http://www.syups.tp.edu.tw' ">

結合 window 物件的框架指標變數 top 和 self,我們還可以讓載入的網頁不會被別的框架頁包住:

<script>
if (self != top) top.location = self.location
</script>

當站台內容分類龐雜,如果把所有目錄顯示出來,框架會一大堆,假設我們把框架設計成前文的樣子,那麼我們就應該讓參觀者在左邊框架的 [主選單] 網頁上點按超連結時,不但 在右邊 [內容] 框架中載入新的網頁,同時也在 [主選單] 框架中載入適當的次選單網頁。也就是說,按一個超連結同時變更兩個框架的內容,程式如下:

<script>
function load_page(left,right) {
      self.location=left
      parent.frames(1).location=right
}
</script>
<a href="javascript: load_page('圖書室次選單.htm','圖書室歡迎畫面.htm')">書香園地</a>

作業:請在 "圖書室次選單.htm" 網頁中設計一個 "回上層" 的超連結,讓網頁的兩個框架一起復原!

注意:當使用 location 載入網頁時,必須確認文件中沒有 <base target=""> 標籤,否則程式將無法正常運作!

 

控制跳頁

history 物件提供 go 這個方法,讓程式設計師可以自由操縱視窗的跳頁功能:

<input type="button" value="上一頁" onClick="history.go(-1)">
<input type="button" value="下一頁" onClick="history.go(1)">

作業:請將上面範例改用超連結方式設計!

 

偵測瀏覽器

navigator 物件通常用來取得瀏覽器的廠牌和版本資訊。下面的例子檢查瀏覽器是否為 IE,如果不是就蹦現警告訊息。

<script>
function check_browser() {
    aname = navigator.appName.toUpperCase()
    if (aname.indexOf("MICROSOFT") < 0)   alert("請使用 IE 瀏覽本站!")
}
</script>

在上面的範例程式中,我們共使用了兩個 Java Script 內建的字串處理函式,toUpperCase() 用來把字串通通改為大寫字母,indexOf() 用來尋找子字串出現的位置,尋找時是由左而右,找不到傳回 -1,出現在字串開頭則傳回 0,出現在第二個字母則傳回 1,依此類推。

比較特殊的是在 Java Script 中,字串是被當成物件的,而非普通的變數,因此想把小寫 abc 換成大寫 ABC,必須寫成:

mystr="abc"
mystr=mystr.toUpperCase()

 

瀏覽器的行為(behavior)

為了配合 ASP.NET 的發展,IE5 以後增加了行為(behavior)這個性質,表面上看它是 CSS 眾多性質中的一個,而事實上它卻可以把事先寫好的 JavaScript 定義給某一個標籤,當成該標籤的內建函式(方法 method)。

我們先來看看如何替一個標籤定義其行為:

<img id=mypic style="behavior: url('http://.../mybehavior.js')">

上面範例雖然使用完整的 URL 來載入 JavaScript,但是您也可以使用相對路徑來載入它。

從程式設計的實務面來看,使用或不使用 behavior 來開發程式,並沒有差別,套句微軟的說法,是會使程式碼更有可讀性。當然,這問題是見仁見智,如果您經常上網閱讀 JavaScript 網站,就會發現喜歡採用傳統物件導向方法來設計程式的人,通常都認為 behavior 是一種脫褲子放屁的設計。有趣的是:微軟公司似乎也擔心大家不喜歡使用 behavior 來開發程式,因此也提供了一堆預先寫好的函式,稱之為預設行為(default behavior)

<a href="#" style="behavior: url(#default#homepage)">設為首頁</a>

上面的例子中,將預設行為函式庫內的 homepage 函式組載入成為 a 標籤的方法(method),接著就可以直接呼叫該函式庫提供的函式 sethomePage(),例如:

<a href="#" style="behavior: url(#default#homepage)" onclick="this.sethomePage('http://www.syups.tp.edu.tw')">設為首頁</a>

下面的範例是用來偵測瀏覽器有否安裝 Media Player,如果沒有則跳到純文字版本的網頁,程式中呼叫 isComponentInstalled() 函式來檢查系統登錄中是否含有 Media Player 的機碼 {22D6F312-B0F6-11D0-94AB-0080C74C7E95}:

<head>
<script>
function check_mplayer() {
      if ( !mybrowser.isComponentInstalled("{22D6F312-B0F6-11D0-94AB-0080C74C7E95}","ComponentID") ) location="no_vedio.htm"
}
</script>
</head>
<body id=mybrowser style="behavior: url(#default#clientcaps)" onload="check_mplayer()">

預設行為函式庫中總共有下列函式組,每一個函式組均內含數量不等的函式,限於篇幅,我們就不在這裡詳列每個函式,請自行參考微軟公司的 MSDN 知識庫 behavior (DHTML Behaviors)

anchorClick

開啟 web 網站資料夾視窗(在網芳裡看得到)

anim

改變 DirectAnimation 動畫物件的動作或播放 DirectSound 聲音

clientCaps

用來管理 IE 的外掛程式,下載、安裝、檢查狀態、版本序號...等

download

下載檔案,並在檔案下載完畢後執行自己撰寫的 JavaScript 函式

homePage

設定首頁、檢查是否已設為首頁、跳回首頁

httpFolder

功能與 anchorClick 相同,但可把視窗開在框架內

mediaBar

開啟和管理 IE 內建的多媒體工具列

saveFavorite

當網頁已被加入我的最愛時,可以透過此函式組讀取或改名

saveHistory

當網頁已被加入歷史紀錄時,可以透過此函式組讀取上次瀏覽紀錄

saveSnapshot

當網頁被存成 HTML 時,可以將 input 標籤中的輸入值一併儲存

userData

將 JavaScript 變數或物件屬性儲存於 client 的硬碟中,以便後續處理。和 Cookie 不同的是,這些資料不會傳回給 server

作業:下面的程式執行時會出現何種錯誤訊息?

<a href="#" onclick="this.sethomePage('http://www.syups.tp.edu.tw')">設為首頁</a>

 

檢查螢幕解析度

screen物件可以取得使用者的螢幕資訊,例如:長、寬、顏色數更新率等。通常當作警示用途,或更貼心一點,直接轉移到適合螢幕瀏覽的網頁。

<script>
if (screen.width<800) {
      alert("天哪!!您是甚麼時代的人哪???您用的螢幕解析度是用640*480,實在是太低了,\n本網站建議您至少要設為800*600以上 !本站網頁畫面顯示才比較正確喔!")
}
</script>

上例中 \n 用來輸出換行符號,由於 alert 函式不支援 HTML 語法,所以不能使用 <br> 代替。

作業:請利用 screen 物件,將大小為 500*400 的視窗置中(使用 window.moveTo() 函式)!

 

控制網頁文件內容

document 物件是網頁元件中的上層物件,要改變任何網頁上的元件內容,必須透過 document 物件中的物件集合來進行存取,這一點在前文討論 DOM 樹狀階層結構時已經說明過。但由於它的使用率非常高,字母太多寫程式不方便,因此它可以直接簡寫為 this,當各位讀者從別人的程式中看到 this.title.src 這樣的語法時,就可以把它看成是 document.title.src。

document 物件本身也可以用來輸出網頁內容、改變網頁背景及設定捲軸,常用的功能表列如下:

document.write("<b>Hello!</b>") 輸出網頁內容
document.title="歡迎光臨三玉國小" 改變標題列的內容
refresh_date=document.lastModified 讀取網頁的最新修改日期
prev_page=document.referrer 參觀者是從哪一頁連過來這裡的
document.bgColor="white" 改變背景顏色
document.fgColor="blue" 改變文字顏色
document.body.background="bk.jpg" 改變背景圖
document.body.style.overflow="hidden" 取消網頁捲軸

下面這個範例,教您把最後修改日期顯示在網頁上,以後若有修改網頁,日期將會自動更新:

<script>
document.write("本網頁最後修改時間為 " + document.lastModified)
</script>

『"本網頁最後修改時間為"』是一個字串,要注意的是使用 Document.write 方法時,後面如果接著的是字串,就需要加上雙引號。字串後面如果接著的是一個變數,就要用加號『+』來連接。

讓我們再試一試 "referrer" ,它能顯示您是從哪個網頁連到這裡來的:

<script>
document.write("謝謝!您是從以下網址連來的 " + document.referrer)
</script>

作業:請設計一個網頁,可以使用超連結來改變背景色, 譬如:當參觀者按 "黑" 時,背景色就改為黑色。請至少設計五個顏色!

 

隱藏與顯現

透過 CSS 中的 visibility 性質,我們可以自由操控一個網頁元件什麼時候要出現,什麼時候隱藏。底下的範例,當參觀者將滑鼠游標移到超連結上,將會出現站台說明,移開滑鼠游標時,說明會自動隱藏:

<script>
function show(obj) {
      document.all(obj).style.visibility="visible"
}
function hide(obj) {
      document.all(obj).style.visibility="hidden"
}
</script>
<a href="http://www.syups.tp.edu.tw" onMouseOver="show('syups_tip')" onMouseOut="hide('syups_tip')">三玉國小</a>
<div id="syups_tip" style="visibility: hidden">本 校榮獲教育部中階資訊種子學校,歡迎您到校參訪!</div>

上面 show 函式如果改成底下的寫法,那麼觸發 onMouseOver 事件時,就可以直接呼叫 show() 而不需要代入參數,但是我們比較建議上面的寫法,因為它比較有彈性:

function show() {
      syups_tip.style.visibility="visible"
}

作業:請設計一個遊戲網頁,網頁上擺放數張圖片,當滑鼠游標移到圖片上時,圖片即自動隱藏,滑鼠游標移開後又再度出現!

 

控制表單物件

複習一下前面學過的語法,對於一個有表單的網頁,Java Script 是這樣存取它的 :

document.表單名稱.元件名稱.value

運用這個語法,我們可以檢查文字方塊是否已經輸入,如果未輸入則可以將輸入游標鎖定在文字方塊上:

<script>
function check_empty() {
        if (document.test.cname.value == "") document.test.cname.focus()
}
</script>
<form name="test">
    您的大名:<input type="text" size="10" name="cname" onBlur="check_empty()">
</form>

請注意我們給這個表單取了個名字,語法是 name ="表單的名字",例題中,我們的表單叫做 test。表單中的文字方塊也取了名字叫做 cname,因此參觀者輸入的字串,就可以用 document.test.cname.value 讀取。

focus 是網頁元件共通的方法,透過這個內建函式,我們可以讓任何網頁元件取得焦點,對文字方塊來說,一旦它取得焦點,輸入游標就會跟著移動回來。

onBlur 事件處理器專門用來處理失焦事件,當滑鼠點選文字方塊以外的元件,或是按鍵盤 TAB 鍵跳到其他網頁元件上時,都會觸發該文字方塊的失焦事件。

由上面的例子我們可以看出,只要我們把表單物件裡面的每個元件,都賦予名稱(name) ,這樣 JavaScript 就能夠隨意控制它了。

 

檢查表單輸入

在程式應用上,表單通常有許多個輸入元件,如果使用失焦事件來逐一檢查輸入是否正確,雖然程式很好寫,但寫起來很囉唆。像這樣的情形,我們就會想要盡其功於一役。

如果要一次檢查多個輸入元件,有兩個方法:

  1. 在表單送出之前會觸發 onSubmit 表單傳送事件,這個時候進行檢查,如果檢查發現有問題,則阻斷事件沸升,這樣表單就不會做傳送動作。

  2. 自己設計一個按鈕或超連結,給參觀者輸入完畢後去按它,然後我們在 onClick 事件去檢查表單內容,如果檢查有問題,則將焦點移到該輸入元件上,沒問題則使用表單物件的 submit 方法將表單資料送出。

採用第一種寫法程式比較簡潔,為許多資深程式設計師愛用;採用第二種寫法難度較低,適合初學者。因此在這裡僅介紹第二種寫法:

<form name="test">
大名: <input type="text" name="uname">
信箱: <input type="text" name="email">
意見: <input type="text" name="words">
<input type="button" value="我寫好了,幫我寄出" onClick="check_form()">
</form>
<script>
function check_form() {
        error=0
        answer1 = document.test.uname
        answer2 = document.test.email
        answer3 = document.test.words
        if ( answer1.value == "" ) {
              error++
              alert("您忘記輸入姓名!")
              answer1.focus()
       } else if ( answer2.value == "" ) {
              error++
              alert("您忘記輸入信箱地址!")
              answer2.focus()
       } else if ( answer3.value == "") {
              error++
              alert("您忘記填寫意見!")
              answer3.focus()
       }
       if (error==0) document.test.submit()
}
</script>

作業: 請設計一個網頁,輸入身高、體重後,檢查是否過重,若過重請蹦現警告訊息,否則蹦現鼓勵訊息。(體脂肪指數=體重除以身高的平方,體重單位為公斤,身高單位為公尺,體脂肪指數超過 22 就算是過重)

 

使用正規表達式

正規表達式可以讓我們更輕鬆地進行字串處理,是 C 語言裡面非常通用的一組函式庫,幸運的是 Java Script 不但語法沿襲自 C 語言,連正規表達式也一併支援了 。Java Script 使用 RegExp 物件來實作正規表達式中的字串擷取和取代功能,而比較單純的字串比對,則設計成為字串物件的 match 函式,例如要比對字串是否為大寫 ABC,可以寫為:

mystr="abc"
if (  mystr.match(/ABC/)  ) alert("這個字串找不到 ABC")

從上面的例子可以看出,比對失敗時,會傳回錯誤號碼(視同為真),比對成功傳回 null(視同為假),更複雜的比對,需要一些特殊字元的幫助:

^

代表字串開頭,^A 代表第一個字母必須為 A
$ 代表字串結尾,A$ 代表最後一個字母必須為 A
- 用來表示比對範圍,0-9 代表 0 到 9 任一個數字
. 代表任意字元
? 比對次數為 0 次或 1 次,A? 代表 A 可有可無
+ 比對次數為 1 次以上,A+ 代表 A 或 AA 或 AAA .......
{} 指定比對次數,0-9{2} 代表連續兩個字都必須是數字
| 就是邏輯運算中的 or
\ 這是脫逸字元,\. 代表要比對 . 這個字元,而非任意字元
\d 用來比對數字,也可以寫成 0-9
\S 用來比對文數字,也可以寫成 0-9a-zA-Z
g 全域比對,代表比對成功後,其餘字母也依同樣條件比對,直到字串結束
i 代表比對時忽略大小寫

下面列出常用的幾種比對方式:

mystr.match(/[^0-9]/g)

檢查 mystr 字串是否為數值
mystr.match(/[^a-z]/gi) 檢查 mystr 字串是否為英文字
mystr.math(/^(\d{4})\/(\d{2})\/(\d{2})/) 檢查是否為 yyyy/mm/dd 格式
mystr.math(/^0(\d?)-(\d{7,8})/) 檢查是否為國內電話號碼格式
mystr.math(/^09(\d{2})-(\d{6})/) 檢查是否為國內手機號碼格式
mystr.math(/^([01]?[0-9]|2[0-3]):([0-5][0-9])/) 檢查是否為 24 時制 hh:mm 時間格式
mystr.math(/^\S+@\S+(\.\S+)+$/) 檢查是否為電子郵件地址
mystr.math(/^http:\/\/.+/) 檢查是否為 URL
mystr.math(/^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}/) 檢查是否為 IP

 

自動產生表單檢查程式

使用 FrontPage 來編輯表單時,可以自動幫我們產生檢查表單的 Java Script 程式,步驟如下:

這個網頁存檔之後,請使用瀏覽器來預覽,查看網頁原始碼,就會發現 Java Script 程式已經寫好了,我們只要將它複製下來,稍作修改就可以直接使用,省去自行開發程式的時間!

作業:請說明使用 FrontPage 自動產生的 Java Script 有哪些缺點?

 

懶人選取法

在某些應用場合裡,我們要讓參觀者點選的項目實在是非常多,底下就是其中一種情形:

請點選您要訂閱的項目:
最新消息  行事曆    網路朝會   榮譽榜
校外教學  校務討論版  訪客留言版  教學文件
有獎徵答  意見調查   技術討論版  場地借用

為了讓參觀者能更快速的進行選取動作,我們可以設計 "全選"、"全不選"、"反向選取" 功能,讓參觀者按一下就能選取複數核取框(checkbox)。

要做到這三個功能,首先必須重新認識一下 Form 物件,Form 物件有一個從屬物件 elements,看名稱就可以猜想得到它是個物件集合,也就是說,Form 表單中所有的輸入元件,都會依照出現順序擺放在 elements 物件集合中,我們只要逐一改變 elements 集合裡各個元件的選取狀態,就能做出全選的效果。Form 物件有一個 lenght 變數,它紀錄著表單裡元件的數量,我們可以根據這個數字來設計迴圈執行次數。

假設 Form 物件的名稱為 myForm,程式如下:

for (i=1; i<myForm.length; i++) {
    if (myForm.elements(i).type=="checkbox") alert("第" + i + "個元件是核取框")

底下是懶人選取法的完整程式,這支程式擁有很好的彈性,可以套用在任何複雜的表單上,而不須修改程式碼,只要代入不同的參數即可:

function sall(thisform) {
    for (i=1; i<thisform.length; i++) {
        if (thisform.elements(i).type=="checkbox") thisform.elements(i).checked = 1;
    }
}

function snone(thisform) {
    for (i=1; i<thisform.length; i++) {
        if (thisform.elements(i).type=="checkbox") thisform.elements(i).checked = 0;
    }
}

function srev(thisform) {
    for (i=1; i<thisform.length; i++) {
        if (thisform.elements(i).type=="checkbox") {
            thisform.elements(i).checked = !thisform.elements(i).checked;
        }
    }
}

作業:請整合本節 "點選訂閱項目" 的範例,和懶人選取法的程式,設計成可以正常運作的網頁。

 

下拉式清單的應用

在程式設計時我們常常會使用下拉式清單(select 物件)來讓使用者可以有數項選擇,這裡用幾個網站的超連結作為範例:

<form name="target">
    <select name="site" onChange="going()">
        <option>--請點選您的目的地--</option>
        <option value="http://www.google.com">去 Google 找資料</option>
        <option value="http://web.tp.edu.tw">去市網中心</option>
        <option value="http://www.syups.tp.edu.tw/">去三玉國小</option>
    </select>
</form>
<script>
function going() {
        choice=document.target.site.selectedIndex
        location=document.target.site.options[choice].value
}
</script>

下拉式清單內的選項稱為 option 物件,所有的選項物件集合成為 options 陣列,我們可以代入陣列索引值來存取每一個選項物件,例如:site.options[0] 就代表 site 下拉式清單中的第一個選項物件,而 site.options[0].value 就代表第一個選項的傳回值。

當使用者點了 target 表單內的下拉式清單 site,並選取了某個選項時,該選項的索引值就會被紀錄在site.selectedIndex 變數中,我們把該索引值代入 options 陣列,就可以取得被選中的選項。

作業: 請讓參觀者從下拉式清單選取自己的出生日期,並算出他已經活了多久!

提示:

先產生一個日期物件:mydate = new Date()
今年度可以用 mydate.getYear() 取得
本月份可以用 mydate.getMonth() 取得,0 代表一月,11 代表十二月
今天的日期可以用 mydate.getDay() 取得
至於日期的減法,應該不需要說明了吧!

 

與時間共舞

window 物件提供兩個內建函式 setTimeout 及 setInterval 來實作計時器,透過這兩個函式的作用,讓我們的程式可以根據時間變化來運作,例如:我們設計一個線上測驗,希望參觀者在三十秒內填答,超過時間就自動跳出測驗結果,程式如下:

<form name="test">
請問三玉國小的網址是 <input type="text" name="url">
<a href="javascript: show_result() ; clearTimeout()">我填好了</a>
</form>
<script>
function show_result() {
        answer=document.test.url.value
        if (answer.indexOf("www.syups.tp.edu.tw") >=0 ) {
              alert("答對了!")
        } else {
              alert("答錯了!")
       }
}

setTimeout("show_result()",30000)
</script>

當把兩行以上的 Java Script 程式寫成一行時,記得中間要使用 ; 隔開,以免程式解讀錯誤。

上面的網頁被載入後,參觀者須在三十秒內填答完畢,如果在時限內完成,則可以直接按下 "我填好了" 超連結,這時 show_result 程式就會判斷答案正不正確,執行完畢並呼叫 window 物件的 clearTimeout 函式將計時器取消作用,以免 show_result 程式反覆執行。如果參觀者未在三十秒內回答問題,在經過 30000 毫秒後,也會自動執行 show_result 函式。

setInterval 函式的用法與 setTimeout 不同,前者會週而復始反覆執行,後者只在時間到時執行一次而已。 除此之外,還有一個不同點,setTimeout 執行完畢後計時器就會失效,而 setInterval 不會,所以必須要呼叫 clearInterval 函式來清除它。

作業一:利用 setInterval 的特性,請設計一個網頁每隔 5 秒鐘變更一次背景色。

作業二:請設計一個網頁自動向上捲動的功能,以方便參觀者閱讀網頁上的文章(使用 window.scrollBy() 函式)。

 

網頁動畫

網頁動畫的設計必須依靠一個浮動的圖層,在該圖層我們可以顯示圖片或文字,然後改變圖層的位置來移動圖片,作出動畫效果。

所謂圖層,可以使用 <div> 來實作,將它設定為絕對位置,方法如下:

<div style="position: absolute">這裡可以自由擺放圖片或文字</div>

要移動這個圖層,必須先設定圖層的座標,如下:

<div style="position: absolute; left:400; top:200">這裡可以自由擺放圖片或文字</div>

底下就是一個簡單的動畫範例:(請抓這一張圖測試)

<script>
sx=400
sy=200

function walk() {
        x=Math.floor(Math.random()*40-20)
        y=Math.floor(Math.random()*40-20)
        sx+=x
        sy+=y
        egg.style.left=sx
        egg.style.top=sy
}

setInterval("walk()",500)
</script>
<div id="egg" style="position: absolute; left:400; top:200">
<img src="egg.gif" border="0">
</div>

上面的程式中,呼叫了 Java Script 的數學函式庫 Math,這個函式庫裡的函式非常多,在此不一一介紹,程式中使用的 Math.floor() 函式用來捨去小數,而 Math.random() 用來產生亂數,亂數是介於 0~1 之間的數,乘以 40 以後會變成 0~40 之間的數,再減去 20,則變成 -20~20 之間的數,取成整數後,與圖片的位置相加(sx+=x 就是 sx=sx+x 的簡略寫法),作為下一個移動的座標。移動圖片時,直接改變圖層 <div> 的 left 和 top 性質即可。

作業:請加上 if 條件判斷,讓可愛的蛋頭不會跑到視窗範圍外。

 

物件導向程式設計

使用物件導向觀念來設計程式,最大的好處就是可以讓程式保持更大的彈性,使得物件有可能在其他不同場合中被引用,節省開發成本。我們就以前面介紹的網頁動畫程式為例,使用物件導向觀念重新改寫程式,讓大家了解這種設計方法的優點。

在傳統的程式寫作中,我們必須要紀錄動畫角色所在的座標,才能根據這個座標去移動角色,如上一小節的範例程式,我們宣告了兩個全域變數來做這件事:

sx = 400
sy = 200

現在我們把主角蛋頭,當成是一個獨立的物件 egg,那麼上面提到的(sx,sy)座標就是這個物件最重要的兩個屬性,依照習慣可以寫成 egg.sx 和 egg.sy。在 Java Script 中要把某個變數設定成某個物件的屬性,必需寫一支稱為建構元的函式:

funcion makeEgg() {
        this.sx = 400
        this.sy = 200
}

程式中的 this 關鍵字,是 egg 物件對自己的稱呼(就像每台電腦都稱自己為 localhost 一樣)。有了建構元以後,我們就可以用底下的方式來建立 egg 物件:

egg = new makeEgg()

當然,我們把預設座標寫死在建構元裡,並不是一個好主意,為了保持彈性,我們改寫建構元如下:

funcion makeEgg(x,y) {
        this.sx = x
        this.sy = y
}

現在我們可以在建構 egg 物件的同時指定它的座標:

egg = new makeEgg(400,200)

到目前為止,我們還得考慮另一個問題:egg 物件必須仰賴網頁上的浮動圖層來呈現影像,因此假如網頁沒有依據 egg 物件的需求,量身訂做該有的標籤(TAG),最後這支程式仍然無法運作,結果與傳統程式寫作沒有什麼不同!

如果我們希望將來在其他網頁上引用 egg 物件時,可以不必去理會應該設計哪些網頁元件來配合演出,最好還是先在建構元中,自己產生網頁元件:

funcion makeEgg(x,y,n) {
        this.id = "egg" + n
        this.sx = x
        this.sy = y
        document.write('<div id="' + this.id + '" style="position: absolute; left:' + this.sx + '; top:' + this.sy + '"><img src="egg.gif" border="0"></div>')
}

當然對 egg 物件來說,僅是擁有自己的屬性還不夠,還需要能移動位置的方法(也就是函式),我們把上一小節的範例程式抄下來修改一下:

function walk() {
        x=Math.floor(Math.random()*40-20)
        y=Math.floor(Math.random()*40-20)
        this.sx+=x
        this.sy+=y
        document.all(this.id).style.left= this.sx
        document.all(this.id).style.top= this.sy
}

這支函式是要當成 egg 物件的方法,與設定物件的屬性一樣,必須寫在建構元裡面:

funcion makeEgg(x,y,n) {
        this.id = "egg" + n
        this.sx = x
        this.sy = y
        this.walk = walk
        document.write('<div id="' + this.id + '" style="position: absolute; left:' + this.sx + '; top:' + this.sy + '"><img src="egg.gif" border="0"></div>')
}

現在我們可以執行 egg.walk() 讓蛋頭移動了,完整程式如下:

<script>
function makeEgg(x,y,n) {
        this.id="egg"+n
        this.sx=x
        this.sy=y
        this.walk=walk
        document.write('<div id="' + this.id + '" style="position: absolute; left:' + this.sx + ';top:' + this.sy + '"><img src="egg.gif" border="0"></div>')
}

function walk() {
        x=Math.floor(Math.random()*40-20)
        y=Math.floor(Math.random()*40-20)
        this.sx+=x
        this.sy+=y
        document.all(this.id).style.left= this.sx
        document.all(this.id).style.top= this.sy
}

egg = new makeEgg(400,200,1)
setInterval("egg.walk()",500)
happy_egg = new makeEgg(100,200,2)
setInterval("happy_egg.walk()",200)
</script>

 

使用 cookie

cookie 是一種在 Web Server 和瀏覽器間雙向傳遞的小元件,它可以將 Server 上某支程式的執行結果暫時儲存在 Client 端,當 Client 端提出瀏覽網頁的要求時,必須先送回該資料給 Server 端,這時候,Server 就可以根據 cookie 所攜帶的資料,來了解這個 Client 曾經到過哪些網頁,執行過哪些程式,執行結果是什麼,以便提供適切的服務給該名參觀者。

在下面的範例中,我們將練習使用 cookie 來儲存參觀者所偏好的背景色,當參觀者再度光臨時,就會使用那個顏色作為背景來歡迎他,無論參觀者人數多寡,透過 cookie,Server 將會得知所有參觀者的不同偏好!

首先,先來解釋一下程式運作原理,前面說過 cookie 資料是儲存在參觀者的硬碟裡,IE 將 cookie 從硬碟讀取出來後,匯整成為網頁物件,而這個物件就叫做 cookie 物件,在網頁物件模型中 cookie 物件算是 document 的從屬物件。當我們把變數和變數值記錄到 cookie 裡面時,可以寫為:

document.cookie= "bgcolor=#80FFFF"

其中 bgcolor 是變數名稱,#80FFFF 是變數值,中間以 = 分隔。

變數一旦寫入 cookie 後,就會與其它 cookie 資料放在一起,看起來就像這樣:

visited=20; bgcolor=#80FFFF; lastdate=2004/09/15

因此要從 cookie 物件中,將剛才寫入的變數值取出來,就有點困難了!首先必須先算出 cookie 資料的總長度,然後使用 Java Script 的內建函式 indexOf() 搜尋字串 "bgcolor=",以上面的例子來說,因為 "bgcolor=" 是出現在 cookie 資料中的第十三個字母,所以搜尋結果應該是 12,把 12 加上 "bgcolor=" 的長度,得到 20,也就是說 bgcolor 這個變數的值是放在 cookie 資料的第二十個字母的地方。

找出變數值字串的起點後,接下來必須找出終點,我們知道 cookie 的每兩個變數中間都使用 ; 區隔,因此接著從第二十個字母往右搜尋 ";",執行結果為 27。如果沒有找著 ";",那麼該變數一定是 cookie 裡的最後一筆資料,我們可以直接使用前面算出的 cookie 總長度,作為變數值的結束位置。

最後使用 Java Script 的內建函式 substring(),將第二十個字母到第二十七個字母取出來,這就是當初寫入 cookie 的 bgcolor 變數 的值。

完整程式如下:

<script>
function get_cookie(name) {
    search=name + "="
    if (document.cookie.length > 0) {
        offset = document.cookie.indexOf(search)
        if (offset >= 0) {
            offset += search.length
            end = document.cookie.indexOf(";", offset)
            if (end == -1) end=document.cookie.length
            return unescape(document.cookie.substring(offset, end))
       }
   }
   return null
}
 
function setcolor() {
      choice=document.back.colar.selectedIndex
      new_colar=document.back.colar.options[choice].value
      document.bgColor= new_colar
      document.cookie= "bgcolor=" + new_colar
}

if (get_cookie("bgcolor")!="") document.bgColor=get_cookie("bgcolor")
</script>
<form name="back">
<select name="colar">
<option value="white">--選擇背景顏色--</option>
<option value="#F0F0F0">淡灰色</option>
<option value="#80FFFF">天藍色</option>
<option value="#C6C6FF">淺紫色</option>
<option value="white">純白色</option>
</select>
<input type="button" value="Go!" onClick="setcolor()"></p>
</form>

選好顏色後,請您重新整理這個網頁,您會發現它還記得您設定的顏色,未來程式寫作時,您隨時都可以取回來作判斷。

作業: 請使用 cookie 紀錄使用者到訪的次數,並在網頁上秀出次數和歡迎訊息。

 

互動式網頁教材製作

底下這些單元,是筆者因應教育推廣的需要而設計的,雖然政府推行資訊融入各科已經多年,但大多數的網頁教材仍以呈現靜態教學資料為主,複雜的互動設計(如:Flash、Authorware) 又門檻過高,一般老師難以製作,因此藉由 Java Script 來開發互動性強的網頁範本,一般老師即使完全不懂程式運作原理,只要稍加教導就能立即套用,製作互動式網頁教材再也不是遙不可及的夢想!

底下就來教如何套用這些範本,各位老師不妨也在自己的學校推行!

配合題 填充題 選擇題 簡答題
過關遊戲 填充測驗 選擇測驗 隨堂測驗
智慧拼盤 快問快答 圖片拖曳

附錄:(DHTML 物件屬性方法速查ASP 內建物件及物件速查卡IIS等候逾時時間表VB Script 功能)



 

 

arrow
arrow
    全站熱搜
    創作者介紹
    創作者 羅伯特 的頭像
    羅伯特

    Thinking in Robert

    羅伯特 發表在 痞客邦 留言(0) 人氣()