《JavaScript DOM程式設計藝術》筆記:JavaScript圖片庫 (三)
-
標記
<!DOCTYPE html> <html lang = "en"> <head> <meta charset = "utf-8"/> <title>Image Callery</title> </head> <body> <h1>Snapshots</h1> <ul> <li> <a href="image/btn_acomlete_1.png" title="A fireworks display">Firework</a> </li> <li> <a href="image/btn_acomlete_2.png" title="A cup of tea">tea</a> </li> <li> <a href="image/btn_allcomlete_1.png" title="A red rose">Rose</a> </li> <li> <a href="image/btn_allcomlete_2.png" title="A lalala">Big bar</a> </li> </ul> </body> </html>
通過增加佔位符圖片的辦法在這個主頁上為圖片預留一個瀏覽區域。
再點選某個連結的時候,攔截這個網頁的預設行為。
再點選某個連結的時候把佔位符圖片替換為與那個連線相對應的圖片。
先在圖片清單的末尾插入
<img id="placeholder" src="image/img_receive.png" alt="my image gallery" />
Javascript
為了把佔位符圖片替換成想要檢視的圖片,需要改變他的src屬性。setAttribute是完成這項工作的最佳選擇。
首先命名一個函式,用來展示圖片,function showPic(whichpic)
whichpic代表一個元素節點,具體地說,那是一個指向某個圖片的<a>元素。我需要分解出圖片的檔案路徑,這可以通過在whichpic元素上呼叫getAttribute得到,只要把href作為引數傳遞給getAttribute就行了
whichpic。getAttribute("href")
將這個路徑存入變數source:
var source = whichpic.getAttribute("href");
接下來,還需要獲取佔位符圖片
var placeholder = document.getElementById("plaeholder");
使用setAttribute對placeholder元素的src屬性進行重新整理。
placeholder.setAttribute("src",source);
非DOM解決方案
setAttribute方法是第一級DOM的組成部分,它可以設定任意元素節點的任意屬性。
不使用setAttribute方法也可以改變圖片的src屬性。
element.value = “the new value";element.setAttribute("value","the new value");
改變圖片的src
placeholder.src = source;
function showPic(whichpic){
var source = whichpic.getAttribute("href");
var placeholder = document.getElementById("placeholder");
placeholder.setAttribute("src",source);
}
引用javascript函式
在</body>標籤之前新增
<script type = "text/javascript" src = "scripts/showPic.js"></script>
事件處理函式
事件處理函式的作用是,在特定事件發生時呼叫特定的js程式碼。滑鼠懸停呼叫onmouseover滑鼠離開
onmouseout事件,點選事件onclick。
showPic()函式需要一個引數:一個帶href屬性的元素節點引數。把onclick事件嵌入到一個連線中時,需要把這個連結本身作showPic函式的引數。
使用this關鍵字。這個關鍵字在這的含義是這個物件。具體到當前的例子,this表示這個<a>元素節點:
showPic(this)
新增事件處理函式語法:
event = "JavaScript statement(s)";
JavaScript程式碼包含在一對引號之間。我們可以把任意數量的javascript語句放在這對引號之間,用分號隔開。
onclick = "showPic(this)";
只是把處理函式放在圖片列表的一個連結中,會出現點選連結是不僅showPic函式被呼叫,連結被點選的預設行為也會被呼叫。
函式處理機制:在給某個元素添加了事件處理函式之後,一旦發生事件,相應的js程式碼就會得到執行。被呼叫的js程式碼可以返回一個值,這個值將被傳遞給那個事件處理函式。例如我們可以給某個連結新增一個onclick函式,並讓這個處理函數出發js程式碼返回true或false,這樣一來,當這個連結被點選時,如果那段js程式碼的返回值是true,onclick事件處理函式就認為這個連結被點選了;反之如果是false,onclick事件處理函式就認為這個連線沒有被點選。
<!DOCTYPE html>
<html lang = "en">
<head>
<meta charset = "utf-8"/>
<title>Image Callery</title>
</head>
<body>
<h1>Snapshots</h1>
<ul>
<li>
<a href="image/btn_acomlete_1.png" onclick="showPic(this);return false;" title="A fireworks display">Firework</a>
</li>
<li>
<a href="image/btn_acomlete_2.png" onclick="showPic(this);return false;" title="A cup of tea">tea</a>
</li>
<li>
<a href="image/btn_allcomlete_1.png"onclick="showPic(this);return false;" title="A red rose">Rose</a>
</li>
<li>
<a href="image/btn_allcomlete_2.png"onclick="showPic(this);return false;" title="A lalala">Big bar</a>
</li>
<img id="placeholder" src="image/img_receive.png" alt="my image gallery" />
</ul>
<script>
function showPic(whichpic){
var source = whichpic.getAttribute("href");
var placeholder = document.getElementById("placeholder");
placeholder.setAttribute("src",source);
}
</script>
</body>
</html>
-
對這個函式進行擴充套件
圖片庫裡的每個文件都有一個title屬性。可以把這個屬性取出來並讓它和相應的圖片一同顯示在網頁上。title屬性的值可以用getAttribute輕而易舉地得到。
var text = whichPic.getAttribute("title");
光提取title還不夠,我們還需要把它插入到html文件中。為完成這一工作,我們需要用到DOM屬性。
-
childNodes屬性
在一棵節點樹上,childNodes屬性可以獲取任何一個元素的所有子元素,他是一個包含這個元素全部子元素的陣列:
element.chilldNodes
要獲取一個文件的body元素的全體子元素。先使用getElementsByTagName得到body元素,因為每份文件只有一個body元素,所以使用getElementsByTagName("body")方法所返回的陣列中的第一個也是唯一一個元素:
var body_element = document.getElementsByTagName("body")[0];
現在body_element已經指向了那個文件的body元素。接下來,可以用如下所示的語法獲取body元素的全體子元素
body_element.childNodes
把下面的函式新增到程式碼中
function countBodyChildren(){
var body_element = document.getElementsByTagName("body")[0];
alert(body_element.childNodes.length);
}
我們需要這個函式在頁面載入時執行,而這需要使用onload事件處理函式在後面新增
window.onload = countBodyChildren;
這段程式碼的作用是頁面載入時呼叫countBodyChildren函式、
-
nodeType屬性
根據此html文件結構body元素應該只有3個子元素,一個hl元素一個ul元素和一個img元素。可是,countBodyChildren()函式給出來的數字卻遠大於此,這是因為文件樹的節點型別並非只有元素節點一種。
由childNodes屬性返回的陣列包含所有型別的節點,而不僅僅是元素結點。事實上,文件裡幾乎每一樣東西都是一個節點,甚至連空格和換行都會被解釋為節點,而他們也全都包含在childNodes屬性所返回的陣列中。
因此countBodyChildren的返回結果才會那麼大。
還好沒一個節點都有nodeType屬性,這個屬性可以讓我們知道自己正與哪一種節點打交道。
node.nodeType//獲得節點nodeType屬性
alert(body_element.nodeType);
元素節點 nodeType屬性值是1.
屬性節點 nodeType屬性值是2
文字節點 nodeType屬性值是3
-
在標記裡增加一段描述
為增加我的圖片庫函式,我決定委會一個文字節點。我們在顯示圖片的時候把這個文字節點的值替換成目標圖片的連結的title的值。
首先,需要為目標文字安排顯示位置。在img標籤後新增一個獨一無二id值這樣就能在js中方便的引用它。
<p id="description">Choose an image.</p>
var text = whichpic.getAttribute("title");//獲取whichpic物件的title屬性並把值存入text
為了方便地引用id為description的文字段落,建立一個新的變數來存放它:
var description = document.getElementById("description");
改完後
function showPic(whichpic){
var source = whichpic.getAttribute("href");
var placeholder = document.getElementById("placeholder");
placeholder.setAttribute("src",source);
var text = whichpic.getAttribute("title");//獲取whichpic物件的title屬性並把值存入text
var description = document.getElementById("description");
}
如果想要改變一個文字節點的值,那就使用DOM提供的nodeValue屬性,它用來得到(和設定)一個節點的值:
node.nodeValue
但這裡有一個必須注意的細節:在用nodeValue屬性獲取description物件的值時,得到的並不是包含在這個段落裡的文字。
<p>元素本身的nodeValue屬性是一個空值,而你真正需要的是<p>元素所包含的文字的值。
包含在<p>元素裡的文字時另一種節點,他是<p>元素的第一個子節點。因此,你想要得到的其實是它的第一個子節點的nodeValue屬性值。
description.childNodes[0].nodeValue;
這個呼叫的返回值才是我們正尋找的Choose an image 這個值來自childNodes陣列的第一個元素。
fristChild 和lastChild屬性
陣列元素childNodes[0]有個更直觀易讀的同義詞。無論何時何地,只要需要訪問childNodes陣列的第一個元素,都可以把它寫成firstChild,
childNodes陣列的最後一個元素,如果不想通過lastChild屬性去訪問這個節點則要使用node.childNodes[node.childNodes.length-1]
利用nodeValue屬性重新整理這段描述
var text = whichpic.getAttribute("title");//獲取whichpic物件的title屬性並把值存入text
var description = document.getElementById("description");
description.firstChild.nodeValue = text;
重新整理文字。
美化
//css程式碼
body
{
font-family: "Helvetice","Arial",serif;
color: #333;
background-color: #ccc;
margin: 1em 10%;
}
h1{
color: #333;
background-color: transparent;
}
a{
color: #c60;
background-color: :transparent;
font-weight: bold;
text-decoration: none;
}
ul{
padding: 0;
}
li{
float:left;
padding: 1em;
list-style: none;
}
img{
display: :block;
clear: both;
}
<head>
<meta charset = "utf-8"/>
<title>Image Callery</title>
<link rel="stylesheet" href="layout.css" media="screen"/>
</head>