網頁製作 網頁製作

網站規劃與設計上課補充教材

網站規劃與設計 > 課程內容 > 第 13 堂課 - javascript 與 DOM 基礎

第 13 堂課 - javascript 與 DOM 基礎

所謂的 HTML5 其實是 HTML 標記 + Javascript APIs + CSS3 等綜合起來的資料,那個 javascript 連同一堆 APIs 是當中相當重要的互動成份!CSS 與 HTML 就是前面幾堂課所講的內容了。因此,你就知道 javascript 有多重要了!因為,要達成可以跟用戶互動,沒這東西,還真麻煩! 不過,你就得要學學基礎程式語法,還有理解一下整個網頁的樹狀模型 (Document Object Model, 文件物件模型),基本上,javascript 會靠著 DOM 來處理網頁的互動呢!
  • 13.1: 簡易的 DOM 介紹
  • 13.2: 取得網頁上元素資料的手段
  • 13.3: 迴圈與判斷
  • 13.4: 時間的應用
  • 13.5: 時間倒數、跑馬燈、問候語
  • 13.6: 參考資料
  • 13.7: 課後練習

13.1: 簡易的 DOM 介紹

在開始 DOM 的介紹之前,我們先來聊聊一般來說,瀏覽器從伺服器或本機的檔案當中取得網頁資料後,是如何進行呈現的呢? 基本上的流程大致上是這樣的:

  1. 瀏覽器載入 html5 的網頁,同時載入了 CSS, Java script 與影音資料等多媒體項目;
  2. 瀏覽器分析了網頁內容,依據各個標記的父元素與子元素的內容,建立了 DOM 文件模型;
  3. 載入的 java script 開始根據 DOM 模型,在特定的元素之間與使用者互動;
  4. 如果設定得宜,更多的 java script APIs 就開始一起應用了(例如影音多媒體)

基本上,一般網頁都是將全部的資料都下載完畢後,這才開始進行後續資料的運作。而第 2 步驟裡面的說明是怎麼回事呢?從前面幾章的資料來看, 我們知道整個網頁的 HTML 文件都是從 HTML 開始的,然後 HTML 裡面主要有 head 以及 body 兩個標籤,而 body 內部的標籤就有夠多的了! 從第六章開始玩弄的方塊 (CSS box) 也能知道,大概有所謂的父元素與子元素,那麼這些元素之間就有相關性 (有父有子),將這些資料依據父子關係串在一起, 這就是最單純的 DOM 樹狀模式模型了。從 wiki 的圖示當中,我們大概可以看出個大概:

習題的完成示意圖

除了這個元素之間的相依性之外,每一個元素都可有擁有許多的屬性,然後這些屬性除了可以讓 CSS 靜態的改變之外,也可以透過 javascript 的程式與互動功能,讓這些元素的屬性被動態修改,因此就會有許多的變化產生。那麼 javascript 可以做哪些元素的屬性處理呢? 基本上, javascript 可以根據 DOM 進行如下的行為:

  • javascript 可以新增、移除 HTML 網頁裡面的所有元素
  • javascript 可以刪除、修改、新增所有元素的相關屬性資料
  • javascript 可以變更元素的 CSS 風格樣式
  • javascript 可以與已經存在的各個元素進行互動,包括滑鼠與鍵盤的事件觸發等
  • javascript 放置在網頁的哪裡呢?

那麼瀏覽器怎麼知道網頁裡面的資料是一般的 HTML 標記還是 CSS 標記,還是 javascript 的網頁程式呢?一般來說,最簡單的 javascript 是放置在這裡:

// 放在整個網頁的最上方,直接放入程式碼的方法
<html>
<head>
	...
	<script>
		javascript here...
	</script>
</head>
...

就是整個網頁最上方的部份。當然,我們也可以使用外部程式呼叫的方式來執行,就像是我們之前要學 bootstrap 時,就已經將某個 javascript 抓到瀏覽器內了! 忘記了嘛?瞧一瞧:

// 放在整個網頁的最上方,呼叫外部程式的方法!很重要!未來常用!
<!DOCTYPE html>
<html lang="zh-Hant-TW">
<head>
  <title>Bootstrap 4 example page</title>
  <meta charset="utf-8">
  <meta name="viewport" content="width=device-width, initial-scale=1">
  <link rel="stylesheet" href="https://maxcdn.bootstrapcdn.com/bootstrap/4.1.3/css/bootstrap.min.css">
  <script src="https://ajax.googleapis.com/ajax/libs/jquery/3.3.1/jquery.min.js"></script>
  <script src="https://cdnjs.cloudflare.com/ajax/libs/popper.js/1.14.3/umd/popper.min.js"></script>
  <script src="https://maxcdn.bootstrapcdn.com/bootstrap/4.1.3/js/bootstrap.min.js"></script>
</head>

不過,很多時候,某些比較小的程式,可能會隨著版面的編排來放置到相關元素的身旁,這樣修改起來似乎也比較容易與直覺。 因此,很多時刻也會直接將程式碼整合到按鈕事件的觸發當中,例如底下的範例:

<button type="button"
onclick="document.getElementById('demo').innerHTML = Date()">
Click me to display Date and Time.</button>

<p id="demo"></p>

上述的範例,就是直接將程式碼放置到 button 這個按鈕標記當中!使用的是滑鼠點擊 (onclick) 所觸發的事件!但是後面那一大段文字你目前可能看不懂!沒關係! 你先知道,該段文字就是透過 DOM 的功能,讓 javascript 去取得使用 id 設計的元素名稱,並且進一步去修改該元素的內部文字而已。 不過,如果是某些需要更多資訊的處理任務時,也可以將 <script> 放置到 body 裡面,例如這樣:

<button type="button"
onclick="myfunction()">
Click me to display Date and Time.</button>

<script>
function myfunction() {
	document.getElementById('demo').innerHTML = Date();
}
</script>

<p id="demo"></p>

大致上,基本的 javascript 放置的程式碼位置就如上所示,好了!知道之後,準備來動動腦囉!

13.2: 取得網頁上元素資料的手段

根據 DOM 的模型,我們可以透過 javascript 的幾個方式來取得網頁上面的元件!同時,根據取得的元素的方法不同,而有不一樣的資料類型喔! 舉例來說,使用 id (不是 class 喔!) 進行資料的取得將是『唯一』的,因此該資料的取得就會是單一的變數。而使用 name 或 標記 (tag) 來取得元素的話,因為網頁上很多元素會定義相同的名稱 (例如表單的單選資料) 或相同的標記 (例如清單的 li 或圖片的 img),因此,這些方式取得的變數,就會是『陣列』的形式喔!

至於 javascript 取得網頁上面的元件方式中,必須要從『整個網頁 (document)』的角度去思考,因此,取得元素的控制權, 就會有底下的幾種語法:

  • document.getElementById("id_name"):透過 id 名稱取得控制權,單一變數
  • document.getElementsByName("name_name"):透過 name 取得控制權,陣列變數
  • document.getElementsByTagName("tag_name"):透過標記的名稱取得控制權,陣列變數

要注意喔,javascript 與 HTML 不一樣,javascript 的語法是有大小寫分別的,所以,上面的 3 個語法中,Element 與 By 與 Id, Name, TagName 的大小寫部份要注意~另外,除了第一個是單一變數,所以使用 Element 之外,底下兩個是陣列變數,所以是複數的 Elements 喔! 尾巴多了個 s 啦!

  • 屬性參數的取得與變更

javascript 要處理取得的元素的控制權後,想要修改該元素的任何資料,都是使用小數點加上屬性的方式來處理的。 舉例來說,假設有個圖片的 HTML 碼寫這樣:

<img id="img1" src="dir1/img1.ipg" alt="check" />

那麼我們想要控制 img 的 src 時,基本上是這樣處理的:

document.getElementById("img1").src="newfilename.jpg";

看到了嘛?透過 getElementById 取得了 img1 的這個元素之後,將後續檔名的 src 修改掉了!就這麼簡單! 如果要更改 style 呢?那就變成這樣:

document.getElementById("img1").style.border="1px solid grey";

在上面的 style 後面小數點可以接的屬性就多了!因為 CSS 的屬性相當多的緣故。此外,如果按下某個按鈕之後, 整個動作才能進行,則可以使用 button 來做處理!然後透過 OnClick 這個事件來觸發 javascript 的程式碼! 有點像這樣:

<img id="img1" src="dir1/img1.ipg" alt="check" />

<button type="button"
onclick="myfunction()">
按我改變圖片</button>

<script>
function myfunction() {
	document.getElementById('img1').src = "newfilename.jpg";
}
</script>

讓我們簡單的玩一玩吧!

例題 13.2.A:我們想要修改 10.1.C 例題當中的背景資料,請將 unit10-1-3.php 另存新檔為 unit13-2-1.php, 然後在 include/menu_form.php 裡面新增一條連結,方便讀取網頁。 然後完成底下的任務:
  1. 先修改資料擺放的位置,意即將 PHP 的幾個變數修改一下:
    $mypage  = 'page2';	// page1 ~ page6
    $mypage2 = 'page20'; 	// 子選單頁面
    
  2. 將 (h4) 的抬頭資料修改成『我的第一個 javascript 網頁』
  3. 在 <pre .../> 的元素內,增加一個 id="test1" 的資料,定義出 id 的名稱。
  4. 在文件的最底下,增加底下的資料:
  5. <button Onclick="myfun()">按我改變資料</button>
    <script>
    function myfun() {
      var mypre = document.getElementById("test1");		// 取得元素的控制權
      mypre.style.backgroundColor="rgba(0,255,0,0.3)";	// 改變背景色,注意 Color 是大寫
      mypre.style.border="5px solid blue";			// 改變框線的資料
    }
    </script>
    
當你完成上述的資料後,修改一下相關的資料,包括變更框線格式,以及背景色,看看整個網頁畫面能不能被你更動呢? 這就是最簡單的 javascript 資料了! 製作完成的頁面會有點像這樣: 例題的完成示意圖 例題的完成示意圖
  • 透過 innerHTML 修改元素的內部文字

除了修改元素的相關屬性之外,如果我們想要修改的是元素內部的文字呢?這該如何處理? 舉例來說,我們想要取得目前 javascript 所在的瀏覽器的本地端時間,可以透過一個 Date() 的函數來取得, 問題是,我們如何將時間參數塞入網頁的某個元素內呢?其實也不難,透過底下的範例來玩玩:

例題 13.2.B:將 unit13-2-1.php 另存新檔為 unit13-2-2.php, 然後在 include/menu_form.php 裡面新增一條連結,方便讀取網頁。 然後完成底下的任務:
  1. 將 (h4) 的抬頭資料修改成『透過 innerHTML 插入新的文字資訊』
  2. 用 p 顯示『按下底下的按鈕,我將會顯示目前的時間參數喔!』
  3. 建立一個 id 名稱為 test2 的 div 方塊,內容為『等等會切換成時間』
  4. 建立一個按鈕,當按下按鈕時,會主動執行名為『 myfun() 』的 javascript 函數
  5. 建立 myfun() 函數,這個函數內容是:
    1. 使用 getElementById 取得 test2 的元素
    2. 讓上述取得的元素變數 (假設為 mydate) 內容為 Date() 這個函數
製作完成來到網頁上面點選按鈕,你就可以看到實際的成果了!另外要注意的是,這個時間是瀏覽器上面系統的時間, 不是 Server 的時間喔! 製作完成的頁面會有點像這樣: 例題的完成示意圖 例題的完成示意圖

因為 javascript 是在瀏覽器上面運作的一種網頁程式語言,因此:『javascript 是在瀏覽器上面運作』的!這一件事很重要! 因為,javascript 預設所抓取的任何資料,基本上,都是從瀏覽器,就是用戶端的資源來的!因此,這個時間當然就是 client 端的時間! 並不是 Server 的時間喔!要注意!要注意!

這個 innerHTML 可以用在很多地方,真的是很好用的一個小工具!

13.3: 迴圈與判斷

我們可以使用迴圈的方法來處理某些資料的應用~舉例來說,我們在 PHP 的第 9 章一直在稿九九乘法對吧! 但是那個是在 Server 上面運算喔!如果想要在瀏覽器上面直接用本機的運算功能來處理呢?就用 javascript 喔! 至於一般常見的固定迴圈功能,可以使用底下的方式來處理:

var i;
for ( i=1; i<=9; i++ ) {
	program here!!!
}
  • 九九乘法表練習

以上面這個程式碼為例,我們讓整個『 program here!!! 』進行 9 次的迴圈運作,每次運作時,那個 i 的變數都會加 1 (i++), 所以,通常這種情況下, i 都會用到『 program here 』當中!看不懂嘛?來,我們來測試一下繪製出當初用 PHP 製作的九九乘法表。

例題 13.3.A:將 unit13-2-2.php 另存新檔為 unit13-3-1.php, 然後在 include/menu_form.php 裡面新增一條連結,方便讀取網頁。 然後完成底下的任務:
  1. 將 (h4) 的抬頭資料修改成『javascript 的九九乘法表製作』
  2. 建立一個 id 名稱為 my99 的 div 方塊,內容為『等等會顯示九九乘法表』
  3. 建立一個按鈕,當按下按鈕時,會主動執行名為『 myfun() 』的 javascript 函數
  4. 建立 myfun() 函數,這個函數內容是:
    1. 因為九九乘法,所以需要兩個變數,現在請用 var 宣告兩個名為 x y 的變數,並且宣告一個名為 mymsg 的字串變數, 這個字串設定為空值 ("");
    2. 請透過『 for ( x=1; x<=9; x++ ) { ... } 』設計出兩層迴圈;
    3. 在迴圈內,請使用 mymsg = mymsg + ( x*y ); 之類的方式來讓資料累積起來
    4. 在兩層迴圈的中間部份,加入 br 來進行換行的動作。
    5. 使用 getElementById 取得 my99 的元素
    6. 讓剛剛輸出的 99 乘法表取代 my99 的內容 (innerHTML)
製作完成的頁面會有點像這樣: 例題的完成示意圖 例題的完成示意圖
  • 九九乘法表用表格格式化

上面的例題出現的資料並沒有編排的結果,有點亂七八糟。如果想要讓他的輸出比較好看些,就得要加上類似表格 (table) 的資料。 現在,請修改上述的程式碼,讓輸出的結果除了以表格處理好之外,還可以有比較好的輸出結果。看看有沒有辦法輸出成底下的模樣:

例題 13.3.B:將 unit13-3-1.php 另存新檔為 unit13-3-2.php,然後在 include/menu_form.php 裡面新增一條連結,方便讀取網頁。 然後完成底下的任務:
  1. 將 (h4) 的抬頭資料修改成『javascript 的九九乘法表製作 - 增加表格格式化』
  2. 將迴圈內的輸出改成表格,且『橫的第一列』只輸出 1~9,還有『直的第一列』也是僅輸出 1~9 喔!
  3. 為了達成上述的輸出,因此,可能迴圈要從 0~9 才行,然後你可能要這樣想:
    • 當 x==0 且 y==0 時,輸出 9x9 (最左上角)
    • 當 x==0 且 y!=0 時,輸出 y 值 (最左側的直行)
    • 當 x!=0 且 y==0 時,輸出 x 值 (最上方的橫列)
    • 當 x!=0 且 y!=0 時,輸出 x*y 值
  4. table 的相關 bootstrap 類別可以加上『table table-striped table-hover table-sm table-primary text-center』
製作完成的頁面會有點像這樣: 例題的完成示意圖
  • 全選與全不選的按鈕功能

在前一章的例題 12.4.D 的午餐選擇的題目中,雖然已經加上 label 來讓使用者比較好勾選了,不過,如果能夠有『全選』或『全不選』, 似乎會更容易處理的!那麼有沒有可能增加這些功能呢?其實也是可能的,而且也不怎麼難!透過類似底下的功能來處理:

var varname = document.getElementsByName("名稱") ;
varname[0].checked = true;
varname[1].checked = true;
...

你得要注意,在 javascript 裡面,是否勾選使用的是『是或否 (true or false)』,所以,這裡就得要使用布林值 (對或錯) 來處理。 來來來,我們處理一下例題 12.4.D 的內容之後,你就能夠大概理解了:

例題 13.3.C:將 unit12-4-4.php 另存新檔為 unit13-3-3.php,然後在 include/menu_form.php 裡面新增一條連結,方便讀取網頁。 然後完成底下的任務:
  1. 將 (h4) 的抬頭資料修改成『以 javascript 製作全選/全不選按鈕』
  2. 在該檔案最下方增加兩個按鈕,其中一個按鈕為『全選』,且會執行 myyes() 的程式,另一個則為『全不選』, 點選之後則執行 myno() 的程式。
  3. 在 myyes() 函數中,透過 getElementsByName 來取得 okfood[] 的『陣列』資料,然後進行如下動作:
    • 以 for 迴圈,指定 i=0 ~ i<陣列.length 的數值
    • 將 varname[i].checked 指定為 true。
  4. 同理,在 myno() 的函數中,將 checked 指定為 false 囉!
製作完成的頁面會有點像這樣: 例題的完成示意圖

這樣就很容易進行勾選、不勾選進行相關的任務了!一切以方便使用者的角度來處理思考喔!

  • 直覺式的勾選功能

上面的例題當中,我們還得要設計兩個按鈕才行~有沒有可能製作另一個選擇的方框 (checkbox),當使用者勾選就給予全選, 使用者取消勾選則是全不選?似乎可以呢!整個思考的角度就是:

  1. 製作一個 checkbox 的按鈕,並給予一個 id 的名字
  2. 使用 getElementById 取得該元素的控制權
  3. 使用 getElementsByName 取得 okfood[] 的控制權
  4. 讓 myok 這個變數等於第 b 步驟的 .checked 結果
  5. 透過前一個例題的方式,以迴圈讓系統變成全選或全不選。

講是不難,實際做看看呢?

例題 13.3.D:將 unit13-3-3.php 另存新檔為 unit13-3-4.php,然後在 include/menu_form.php 裡面新增一條連結,方便讀取網頁。 然後完成底下的任務:
  1. 將前一題留下來的按鈕刪除,然後在複選的最上方增加一個類似的 checkbox 按鈕,只是不要給 name, 但是給 id 為 myok 的名字,同時給予 label 以及說明為『全選/全不選』的樣式, 另外,透過 OnClick="myfun()" 來觸發 myfun() 函數
  2. 在 myfun() 裡面,進行如下的任務:
    1. 指定 myok 變數,內容為取得 myok 的 .checked 內容
    2. 指定 okfood 變數,內容為取得 okfoodp[] 的控制權
    3. 透過 for 迴圈,讓 okfood[i].checked = myok 就好了!
製作完成的頁面會有點像這樣: 例題的完成示意圖

這樣就完成了全部選擇的目的了!輕鬆又愉快!

13.4: 時間的應用

針對網頁來說,很多時候,我們可能需要時間方面的控制!舉例來說,我們在 CSS 動畫章節裡面的習題,不是曾經使用過淡出淡入的功能? 之前那個網頁同學們應該是花了不少心思吧!?因為考慮 CSS 的動畫變動情況,好像很有點麻煩。如果我們直接使用 javascript 去修改 src 的內容呢?不就可以立刻更新頁面了?很簡單!我們就來玩玩看!

  • 設定時間參數

要完成這些任務,首先,我們得要來處理處理『一個循環運作的程式碼!』處理的方法,有點像這樣;

var timer = setInterval("myfun()",1000);
function myfun() {
	program here....
}

那個 setInterval 裡面的兩個參數,前面的就是我們要進行的函數,後面的則是多久進行一次,單位是毫秒,也就是 10-3 秒。所以,上面的意思是,每 1 秒鐘進行一次 myfun() 這個函數內的程式碼。那如果這個函數不要再繼續執行呢?就使用底下的程式碼, 就能夠將那個 myfun() 的運作停止了:

clearInterval(timer);

事實上,那個 timer 的名稱是可變的,你倒不需要一定要使用 timer 這個關鍵字!只是,我們知道 timer 就是定時器嘛! 當然是使用這個專有名詞比較好記憶啦。

  • 直接修改 img 的 src 內容

我們在例題 10.4.1 裡面不是使用過旋轉木馬幻燈片嘛?裡面就有 5 張解析度相同的圖片。現在,讓我們直接以 javascript 簡易幻燈片的方式來製作類似的功能。

例題 13.4.A:將 unit13-3-4.php 另存新檔為 unit13-4-1.php,然後在 include/menu_form.php 裡面新增一條連結,方便讀取網頁。 然後完成底下的任務:
  1. 將 (h4) 抬頭的內容改為:『使用 javascript 製作建議的幻燈片功能』
  2. 建立一個寬 600 像素,高 500 像素的方塊,內部藏了兩個元素:
    • 一個 img 元素,預設圖片為 ex10_4_a1.jpg,alt 為『第 6 屆畢展』,寬度為 100%,id 為 myimg;
    • 一個按鈕 (button),按下按鈕觸發 myfun() 函數,使用『 btn btn-primary 』類別樣式,文字為『按我改變』
  3. 在底下的 <script> 當中,先指定幾個東西:
    var myindex = 0;
    var myphoto = ["images/ex10_4_a1.jpg", "images/ex10_4_a2.jpg", "images/ex10_4_a3.jpg", 
                   "images/ex10_4_a4.jpg", "images/ex10_4_a5.jpg"];
    
    其中 myindex 為即將作為照片索引的任務,myphoto[] 則是實際紀錄照片的網址位置
  4. 在 function myfun() 裡面,指定每 3 秒鐘進行一次 myrun() 的函數執行
  5. 在 function myrun() 裡面:
    1. 指定 myimg 的變數,該變數取得 myimg ID 的元素控制權
    2. 指定 myimg.src 為 myphoto[index] 這個網址
    3. 讓 myindex 加 1
    4. 當 myindex 大於等於 myphoto[] 的個數時,就讓 myindex 歸零
製作完成的頁面會有點像這樣: 例題的完成示意圖

很快喔!就可以處理這個類似幻燈片立即抽換的功能!

  • 加入淡出淡入功效

上面的動作有點突兀~就是立刻切換這樣~有沒有辦法像是 bootstrap 這樣,可以有淡出淡入的功能呢?有的!我們有個 opacity 的 style 可以處理! 當 opacity 為 0 代表整個圖片是透明的,如果是 1 代表圖片不透明~這樣就能實現淡出淡入的功效了!現在假設一張圖片有 5 秒鐘的顯示時間, 同時『假設每 0.1 秒分析一次網頁』,那麼:

  1. 利用 0.5 秒的時間讓圖片從 0 到 1 的透明度 (每 0.1 秒變更一次,所以是 0, 0.2, 0.4, 0.6, 0.8 到 1 這樣),這樣一開始圖片就有淡入的效果;
  2. 中間的 4 秒鐘是 OK 沒問題的展示 (靜態)
  3. 最後的 0.5 秒讓圖片從 1 到 0 展示透明度 (從 0.8, 0.6, 0.4, 0.2 到 0 ),這樣就變成淡出的效果了!
  4. 當時間到達 5 秒鐘時,將計數歸 0 ,然後更改圖片網址 (src),之後重來一次圖片展示的淡入淡出效果!

講起來很難,寫起來其實也不容易~不過,至少我們知道『函式運作的時間解析應該要是 0.1 秒鐘』這個概念~然後還要『有一個計數器』, 如果是 5 秒,那麼這個計數器應該要從 0~49 共 50 個,每 0.1 秒計算次數一次 (時間累加),這樣就可以處理計數器的設計問題。

例題 13.4.B:將 unit13-4-1.php 另存新檔為 unit13-4-2.php,然後在 include/menu_form.php 裡面新增一條連結,方便讀取網頁。 然後完成底下的任務:
  1. 在 myindex = 0 底下新增兩個變數的初始化,分別是 mycheck = 0 以及 myfilter = 0.0,其中 mycheck 用來作為計數器, myfilter 用來作為遮罩 (透明度) 的變數值,由於透明度是 0~1 之間,因此是浮點數:
    var mycheck  = 0;
    var myfilter = 0.0;
    
  2. 將 setInteval 裡面的時間,改成 100 這個 0.1 秒執行一次的情況
  3. 在 function myrun() 裡面,增加底下的程式碼:
    function myrun() {
    	// 取得元素的控制權
    	var myimg = document.getElementById("myimg");
    	if ( mycheck < 5 ) {
    		// 最前面 0.5 秒的淡入功效
    		myfilter = mycheck / 5.;
    	} else if ( mycheck >= 45 ) {
    		// 最後 0.5 秒的淡出功效
    		myfilter = ( 49-mycheck )/5.;
    	} else {
    		// 其他時間就是靜態不動!
    		myfilter = 1.;
    	}
    	// 修改透明度的地方!
    	myimg.style.opacity = myfilter;
    	// 計數器累加!
    	mycheck++;
    	// 計數器累加到 5 秒鐘的那個時簡單,進行 (1)換圖片 (2)計數器歸零 的動作
    	if ( mycheck >= 50 ) {
    		// 換圖片的功能
    		myindex++;
    		myimg.src = myphoto[myindex];
    		myimg.alt = "第 " + (myindex+6) + " 屆畢業展";
    		// 圖片的計數器也歸零的條件
    		if ( myindex >= ( myphoto.length -1 ) ) myindex = 0;
    		mycheck = 0;
    	}
    }
    
製作完成的頁面會有點像這樣: 例題的完成示意圖

這樣每 5 秒就可以處理好一張圖示的淡出淡入功能。不過,如果你想要改變時間呢?哇!程式碼裡面的 45, 49, 50 通通要修改!好煩喔! 所以,請進行底下的修正!讓我們可以方便修改秒數!

例題 13.4.C:將 unit13-4-2.php 另存新檔為 unit13-4-3.php,然後在 include/menu_form.php 裡面新增一條連結,方便讀取網頁。 然後完成底下的任務:
  1. 在腳本裡面,新增加一個 mytime 的初始值,預設值為 50,例如:
    var mytime = 20;	// 秒數 * 10 的結果,此例為 5 秒
    
  2. 將程式碼當中的 45 改成 ( mytime-5 )
  3. 將程式碼當中的 49 改成 ( mytime-1 )
  4. 將程式碼當中的 50 改成 mytime
寫完之後重新刷新一次並且執行看看,之後沒有問題,就將 mytime 改成 20 測試看看結果。
  • 開機就載入 window.onload 效果

上面這個函數有點蠢~因為還得要按下按鈕才會開始進行圖片的輪替~真的是有點蠢!有沒有辦法在網頁載入到瀏覽器完畢後,瀏覽器就自己執行呢? 可以的!也不難~透過 window.onload = function_name; 來處理即可!

例題 13.4.D:將 unit13-4-3.php 另存新檔為 unit13-4-4.php,然後在 include/menu_form.php 裡面新增一條連結,方便讀取網頁。 然後完成底下的任務:
  1. 將 img 增加一個 style 樣式, opacity: 0,讓圖片一開始就是透明的!
  2. 在 script 裡面,增加底下的程式碼:
    window.onload = myfun();
    

有夠簡單的吧!讓程式碼自動在 window 載入 (load) 之後,立刻執行 myfun() 這隻函數!這樣畫面就自動淡出淡入~ 不用像之前 CSS 動畫般,得要想盡辦法~所以,會程式碼真的比較好!對吧!

  • 亂數展示圖片內容

最後,如果不想要循環展示,而是內容隨機展示呢?其實也不是太困難~如同第 12 章的 PHP 裡面談到 rand 可以隨機取得亂數, 那麼 javascript 則是透過亂數處理!如下所示:

Math.random();			// 0~0.999 之間的一個亂數,注意,數值是 0 ~ 0.9999 無限逼近於 1
Math.random() * 10 + 1;		// 1~10 之間的一個浮點數亂數
Math.floor(Math.random()*10+1);	// 1~10 之間的一個整數亂數

但是,因為我們需要的是 0 ~ (myphoto.length-1) 之間的整數,因此應該要寫成:

Math.floor(Math.random()*myphoto.length);
例題 13.4.E:將 unit13-4-4.php 另存新檔為 unit13-4-5.php,然後在 include/menu_form.php 裡面新增一條連結,方便讀取網頁。 然後完成底下的任務:
  1. 在 script 裡面,將 myindex++ 抽換掉,變成由上述由亂數取得的樣式
  2. 將圖片計數器歸零的那行刪除,不再需要了。

簡單的進行這件事情,你的圖片就可以變成隨機的播放,而不是循環的播放了喔!

13.5: 時間倒數、跑馬燈、問候語

其實時間的應用在網頁上很重要!例如在某些郵局、銀行的頁面,會主動的倒數 10 ~ 15 分鐘,等到時間倒數結束,就會讓使用者自動登出! 這樣對於使用者來說,比較有保障 (例如忘記登出就跑走了之類的...)。因此,我們就來瞭解一下這方面的時間任務!

  • 時間倒數與跳轉頁面的功能

其實,在上面的 13.4 小節裡面,就談到很多的時間倒數的細節,現在這樣,假設你有一個網頁,內容就是會倒數 30 秒, 等到 30 秒結束後,就會跳轉到首頁去,那該如何是好?首先,每倒數一秒,就會在螢幕上面顯示目前的剩餘時間, 當剩餘時間到 0 的時候,就使用底下的方式重新導向首頁:

window.location.href = "index.php";

廢話就不多說了,趕緊來處理一下這個案例看看:

例題 13.5.A:將 unit13-4-5.php 另存新檔為 unit13-5-1.php,然後在 include/menu_form.php 裡面新增一條連結,方便讀取網頁。 然後完成底下的任務:
  1. 將 h4 抬頭內容改為『可以跳轉頁面的倒數功能』
  2. 將不要的項目先刪除,然後:
    • 增加一個 p,並說明一下倒數結束後,就會回到首頁的資訊這樣。
    • 增加一個 id 為 mytime 的 div 變數,預設內容為 30 這樣的數值
  3. 在 <script> 裡面設定數個初始值資料,包括:
    • 設定一個 timer,每一秒鐘會進行一次 myfun() 的函數運作
    • 取得 mytime 元素的控制權,就取名為 mytime 即可
    • 設定 myinit 的初始值,為 mytime.innerHTML 的數值
  4. myfun() 函數的運作有點像這樣:
    1. 針對 myinit 進行遞減 (myinit--);
    2. 讓 mytime.innerHTML 的值於 myinit (就會倒數了)
    3. 當 myinit 等於 0 的時候,就使用上述的 window.location.href 導向 index.php 囉!
製作完成的頁面會有點像這樣: 例題的完成示意圖

未來,你只要在 myfun() 裡面補上你想進行的任務,例如做個 session_destroy 之類的!哈哈!就等於是將用戶強制登出囉! 大概的處理方案就是這樣囉!

  • 跑馬燈的設計

有時候我們會看到新聞入口網站,裡面都會有斗大的標題,有的會以跑馬燈的形式來展示。現在我們就來模仿一下這些使用 javascript 所設計的跑馬燈。 要注意喔!雖然 HTML 裡面有個名為 marquee 的跑馬燈語法,不過這種語法已經過時而被 W3C 捨棄了,因此不要再使用這種方法來處理跑馬燈喔! OK!那就讓我們來玩玩這種設計。

其實跑馬燈就跟我們前面玩的畫面輪播很類似,只是一個是圖形,一個是文字而已。此外,我們可能會加上一些動態的設計, 圖片就使用淡入淡出,但是文字呢?我們就用類似 top: NNxp 的方式來讓該文字跑掉,應該就可以了!

例題 13.5.B:將 unit13-5-1.php 另存新檔為 unit13-5-2.php,然後在 include/menu_form.php 裡面新增一條連結,方便讀取網頁。 然後完成底下的任務:
  1. 修改 h4 的抬頭資料,就設定為『變動式跑馬燈』即可
  2. 給予一個獨立的 p 段落,內容就寫『每數秒鐘就會變更一則新聞內容喔!』的模樣
  3. 給予一個方塊,並給予這些 CSS 樣式: border: 1px solid gray; width: 500px; height: 35px; position: relative; padding: 5px; overflow: hidden;,其中最重要的是位置與溢出效應!此外,高度與 padding 也要經過設計才行!
  4. 在上面這個 div 裡面放一個 p 段落,id 設定為 mynew,CSS 樣式給予:position: absolute; top: 5px;, 裡面文字放了『準備新聞當中』,設計完畢之後,觀看一下網頁的結果。
  5. 在 javascript 的初始值當中,給予底下的設定:
    var myindex=0;		// 新聞的位置
    var mytime = 200;	// 秒數 * 40 的結果,此例為 5 秒
    var mycheck=0;		// 作為滑動的功能檢驗
    var mytop = 0;		// 位置參數的項目
    var mynews = new Array();
    mynews[0] = "<a href='index.php'>看看我的首頁</a>";
    mynews[1] = "<a href='http://tw.yahoo.com'>看看雅虎新聞</a>";
    mynews[2] = "<a href='http://www.ksu.edu.tw'>崑山首頁</a>";
    mynews[3] = "<a href='https://www.google.com'>查查 Google 重點</a>";
    mynews[4] = "<a href='httsp://www.youtube.com'>Youtube 有新的影片嘛?</a>";
    mynews[5] = "<a href='aboutme.php'>看看我是誰</a>";
    
  6. 瀏覽器準備好之後,就開始執行 myfun() 函數
  7. 在 myfun() 函數中,設定 timer 為每 25 毫秒執行一次 myrun() 函數
  8. 在 myrun() 函數中,進行如下的動作:
    1. 設定 mynew 變數,為取得 mynew 元素的控制權
    2. 判斷 mycheck 的數值,用來作為控制新聞文字位置的處置 (top: NNpx)
      • 若 mycheck 小於 20 (最先的0.5秒),則
        mytop = 40 - (mytime -20) + 5;
      • 若 mycheck 大於 ( mytime - 20 )(最後的0.5秒),則
        mytop = 5 - ( mycheck + 20 - mytime ) * 2;
      • 若皆否,則 mytop 指定為 5
    3. 透過『mynew.style.top = mytop + "px"; 』 來讓文字進行滑動的效果
    4. 將 mycheck 加 1
    5. 判斷 mycheck 是否 >= mytime,若成立才進行底下的任務:
      • 讓 myindex +1
      • 讓 mynew 的內容變成新的 mynews[myindex]
      • 若 myindex 的數值大於等於 ( mynews 的個數 -1 ),則 myindex 歸零
      • mycheck 歸零
製作完成的頁面會有點像這樣: 例題的完成示意圖

由於文字的內容是會變動的,加上會有移動的效果,所以,就會顯的比較有特色啦!大家可以自行玩玩看!

  • Javascript 的時間函數與時間功能

javascript 可以透過 Date() 取得目前瀏覽器所在的系統時間,設定的方法類似這樣:

var mydate = new Date();

承上,如果需要針對 mydate 這個時間變數進行各項應用的話,你可能得要瞭解底下的各個函數功能!

  • mydate.toString():取得所有的時間參數;
  • mydate.getFullYear():取得西元年
  • mydate.getMonth():取得月份,不過是從 0~11 喔!所以換算成為我們的月份,必須要加上 1 才行!
  • mydate.getDate():取得日期,從 1~31 喔!
  • mydate.getHours():取得小時值,從 0 - 23 喔!
  • mydate.getMinutes():取得分鐘,從 0~59 喔!
  • mydate.getSeconds():取得秒鐘,從 0~59 喔!
  • mydate.getWeeks():取得秒鐘,從 0~59 喔!
  • 更多詳細說明:https://www.w3schools.com/jsref/jsref_obj_date.asp

我們在第九章的例題 9.1.F 裡面就曾經使用過時間問候語,當時採用的時間其實是 Server 端的時間,因此與瀏覽器端的時間可能是存在差異的! 如果要使用當地時間,當然是以瀏覽器的時間為宜!雖然我們都知道現在的系統時間已經很多了~不過,我們還是想要將時間藏在網頁上, 感覺比較漂亮些~而且這個時間還需要能夠自己變動~那該如何處理呢?

例題 13.5.C:將 unit13-5-2.php 另存新檔為 unit13-5-3.php,然後在 include/menu_form.php 裡面新增一條連結,方便讀取網頁。 然後完成底下的任務:
  1. 修改 h4 的抬頭資料,就設定為『時間問候語』即可
  2. 增加一個 id=mymsg 的 p ,風格樣式增加 margin-bottom 為 0 的狀態,不需要內容。
  3. 我們想讓三個時間 (小時、分鐘、秒鐘) 分開,因此使用一個 div 內建 3 個固定寬度的 span 來分別放置資料即可。
    • 外部的 div 先給予這些樣式: border: 1px solid gray; width: 300px; padding-left: 10px;
    • 三個 span 的樣式都給這樣: width: 20px;
    • 三個 span 個別的 id 從左而右依序給予 thh, tmm, tss 的識別名稱。
  4. 在 script 裡面,先給予底下數個元素的控制權取得:
    // 取得元素的控制權
    var thh = document.getElementById("thh");
    var tmm = document.getElementById("tmm");
    var tss = document.getElementById("tss");
    var msg = document.getElementById("mymsg");
    
  5. 當瀏覽器準備好了之後,就執行 myrun() 函數
  6. 設計名為 myfun() 的函數,內容只是設定這樣 (每秒鐘執行一次 myrun()):
    var timer = setInterval("myrun()", 1000);
    
  7. 設計名為 myrun() 的函數,內容大概是:
    1. 設計三個變數,分別為 old_th, old_tm, old_ts,分別取得 thh, tmm, tss 的 innerHTML (取得原有的小時、分鐘、秒數)
    2. 設計 mydate = new Date() 變數,以瞭解目前的實際時間
    3. 透過 mydate 的相關函數,取得小時、分鐘、秒鐘的時間 (new_th, new_tm, new_ts),要注意,當小於等於 9 時,要在數值前補 0 ,例如 01, 02...
    4. 如果 new_th 不等於 old_th 就變更 thh.innerHTML 成為 new_th,tmm, tss 也相同動作
    5. 再次透過 mytime 取得目前的實際小時值,並根據小時值回傳底下的訊息:
      // 時間問候語
      var mytime = mydate.getHours();
      var mymsg = "";
      if ( mytime >= 6 && mytime < 11 ) mymsg = "早安!歡迎!";
      if ( mytime >=11 && mytime < 15 ) mymsg = "午安!加油";
      if ( mytime >=15 && mytime < 17 ) mymsg = "下午好!努力再努力!";
      if ( mytime >=17 && mytime < 19 ) mymsg = "下午好!下班回家要小心交通!";
      if ( mytime >=19 && mytime < 22 ) mymsg = "晚上好!收拾心情靜靜思考~";
      if ( mytime >=22                ) mymsg = "晚上好!該是洗洗睡的時間了!";
      if (                mytime <  6 ) mymsg = "深夜問題多,平安回家最好了!";
      msg.innerHTML = mymsg;
      
製作完成的頁面會有點像這樣: 例題的完成示意圖

事實上,上面的程式碼你可以將他藏在網頁的任何一個位置上,例如放在左側的子導覽列上方,也是一個不錯的地方!可以有跟使用者溝通的資訊處! 此外,包括底圖、底色、某些風格特色等等,也可以透過這個時間參數的運作,來提供相關的變化!這也是讓你的網頁可以隨時變動的特效喔!

13.6: 參考資料

13.7: 課後練習

  1. (100%)完成今天所有的課堂上面的實做,並且依據課堂上所說的,全部的例題都需要在子導覽列加上超連結。