第一步:分析問題(Analizing the problem)
建立一個好的指令碼,第一步應該是去分析哪些是你要完成的:我們想要建立一個照片的投影片效果,並且我們想要保持維護的方便。
如何建立一個投影片效果
在一個網站上擁有投影片有幾種方法:
在文檔中包含所有的圖片。
當他運行在無 JavaScript 狀態,這是一個安全的選擇。而且,當頁面被載完,所有的圖片也會將被載完。然而,這個方式只適用於少量的圖片。
在文檔中包含第一張圖片,並且有一個建立投影片功能的伺服器端指令碼。
這也是相當安全的,但是對於終端使用者來說,這是非常令人厭煩的——因為我不想載入整個頁面,僅想得到下一張照片。但對頁面展示和廣告點選比較有效,這也是為什麼大量的新聞網站使用這個方法。
在文檔中包含第一張圖片,並按需載入其他圖片。
這個方法令你厭煩的是,必須依賴於 JavaScript ,並且要有一個維護照片列表的 JavaScript 數組。你還需提供一個載入指標,用來顯示使用者一些正在發生的事情。
在我們的案例中,我們採取下面的圖片列表,用向前和向後的按鈕把他變成一個投影片效果,並且一個指標告訴我們,照片總數中的哪張照片是當前顯示的。
<ul id="slideshow">
<li><img src="img/flat1.jpg" alt="Hallway" /></li>
<li><img src="img/flat2.jpg" alt="Hob" /></li>
<li><img src="img/flat3.jpg" alt="Bathroom" /></li>
<li><img src="img/flat4.jpg" alt="Living Room" /></li>
<li><img src="img/flat5.jpg" alt="Bedroom" /></li>
</ul>
最後的輸出會看起來像例子中的投影片效果。
依賴關係檢查
我們這裡有一些元素依賴於 JavaScript 產生:文字指標和向前和向下的連結。為了保持我們解決方案的可用性,我們需要確保一些事情:
僅當 JavaScript 可用(使用者信賴我們提供給他們使用的功能)時,這些元素應該出現。一個連結,不能做任何違反使用者對我們的信任的事情。
不論輸入裝置(讓我們不要依賴使用者是否有滑鼠),互動式元素都應該可用。
圖片不應該被隱藏,除非使用者能再次訪問他們。在技術上,僅顯示第一張圖片,且沒有向前和向後的連結是預留退路的做法,但是為什麼要使用者已下載所有的圖片僅只看到第一張?
第二步:規劃指令碼(Planning the Script)
一旦你已經評估了問題,並挑選出你想使用的解決方案,你便可以開始規劃指令碼。本質上,我們的指令碼應該做這些:
檢查投影片列表是否存在,並且包含一些圖片(有理由為一張圖片建立一個投影片效果嗎?)。
隱藏所有的照片,但不是第一個。
建立向前和向後的連結,和一個顯示我們在哪的指標。
添加事件處理常式,使連結增加或減少當前顯示的圖片編號。
確保投影片效果沒有超出範圍,當圖片編號小於 0 ,他應該變為最後一張圖片,反過來類似。
不同的功能處理
我們有一些方法處理這個問題。其中之一是使用 DOM 遍曆每個 LI 條目並隱藏他。在這個事件監聽函數,我們先隱藏先前顯示的 LI (如果有的話),並顯示當前的這個。
註:顯示和隱藏代替圖片的 LI 更有意義,因為他允許維護者在每個投影片上添加其他的元素,比如,一些標題。
這個方法的問題在於,我們在 JavaScript 中做必要的樣式改變,這意味著如果有需要比剛才我們指令碼中改變 display 從 block 到 none 更複雜的樣式改變,將使指令碼變得更雜亂(沒有從行為中分離表現)。
樣式留給 CSS 解析器
更簡潔的方法是將所有的外觀改變(在所有清單項目下載完之後隱藏某些)都留給瀏覽器的 CSS 解析器。在我們的例子中,我們可以在投影片中使用一個 CSS 規則很容易地隱藏所有的清單項目,並用一個特定的 class 重寫當前條目的樣式。
HTML:
<ul id="slideshow">
<li><img src="img/flat1.jpg" alt="Hallway" /></li>
<li><img src="img/flat2.jpg" alt="Hob" /></li>
<li><img src="img/flat3.jpg" alt="Bathroom" /></li>
<li><img src="img/flat4.jpg" alt="Living Room" /></li>
<li><img src="img/flat5.jpg" alt="Bedroom" /></li>
</ul>
CSS:
#slideshow li{
display:none;
}
#slideshow li.current{
display:block;
}
唯一的問題是,如果我們使 CSS 和 JavaScript 不可用,訪客將永遠不能訪問到其他圖片。因此,我們需要僅當 JavaScript 可用時,應用這些樣式。技巧是,當 JavaScript 可用,在投影片的 UL 上應用 class ,例如名為 js 。這允許我們僅當 JavaScript 可用時,顯示效果,通過在 CSS 中簡單的修改:
CSS:
#slideshow.js li{
display:none;
}
#slideshow.js li.current{
display:block;
}
這個 class 的鉤子(hook)也能被用來對投影片的靜態和動態版本提供一個完全不同的外觀。
我們所有的指令碼需要做的是,通過移除或添加 current 的 class 來顯示和隱藏當前及以前的照片。
為了確保我們的指令碼將不會影響同一頁面上的其他指令碼,我們將建立一個主要的對象,並在其上構造所有的方法和屬性。這可以確保我們的 init() 函數將不會被覆蓋或覆蓋其他任何相同名字的函數。
JavaScript:
slideshow = {
current:0, // 當前投影片編碼
init:function(){
// 初始化和設定事件處理函數
},
show:function(e){
// 事件監聽器
}
}
第三步、基本的工具方法( Essential Tools)
現在,我們有了規劃和建立我們指令碼的架構。是時候思考我們需要完成這個功能的一些工具方法。在其最低要求的情況下,DOM 指令碼的協助庫應該包括:
一個註冊事件處理函數的方法,我們目前將使用 John Resig 的 addEvent() 方法。
添加和移除 CSS 樣式名的方法。
一個覆蓋 HTML 元素預設行為的方法。我們不希望出現連結的目標頁,而僅是執行指令碼。
我們添加這些工具方法到主要的對象上,並準備開始:
JavaScript:
slideshow = {
current:0, // 當前投影片編碼
init:function(){
// 初始化和設定事件處理函數
},
show:function(e){
// 事件監聽器
},
addEvent:function( obj, type, fn ) {
if ( obj.attachEvent ) {
obj['e'+type+fn] = fn;
obj[type+fn] = function(){
obj['e'+type+fn]( window.event );
}
obj.attachEvent('on'+type, obj[type+fn] );
} else
obj.addEventListener( type, fn, false );
},
removeClass:function(o,c){
var rep=o.className.match(' ‘+c)?' ‘+c:c;
o.className=o.className.replace(rep,”);
},
addClass:function(o,c){
var test = new RegExp(”(^|\\s)”+c+”(\\s|$)”).test(o.className);
if(!test){o.className+=o.className?' ‘+c:c;}
},
cancelClick:function(e){
if (window.event){
window.event.cancelBubble = true;
window.event.returnValue = false;
}
if (e && e.stopPropagation && e.preventDefault){
e.stopPropagation();
e.preventDefault();
}
}
}
當文檔完全載完,第一件事情就是需要執行 init() 方法: