可置換風格:讓樣式表們輪流上陣

嗯,你已經建了個自己的網頁,把它用結構化的 XHTML 標記好了。 作爲一個能幹的小小網頁設計師,你還用樣式表規劃了文檔的外觀。你甚至還實現了一個小小的飛躍,做了好幾個拿來替換的樣式表,打算用它們來展示展示你的實力。

好極了。不過現在,你恐怕需要一個支持各種瀏覽器的方法來靈活的切換於這些樣式表之間。

一、給你的站點置備樣式

樣式表可以與文檔通過一個 link 元素的列表關聯起來,這個列表放在文檔的 head 部分。來自外部的樣式表和文檔可能有這麼幾種關係:永久的、首選的與可變的。

1. 永久的

這類樣式表一直啓用着 (也就是說,狀態一直是"on"), 當然它們是與其他活動的樣式表結合使用的。它們可以用來存放各種樣式表均共享的那些規則。要使之永久啓用,rel 屬性得設爲"stylesheet",而且不設置 title 屬性。

比如說要讓 paul.css 這個樣式表永久啓用,可以在 head 中包含如下 link 元素:

<link rel="stylesheet" type="text/css" href="paul.css" /> 


2. 首選的

這些頁面是缺省啓用的 (它們在頁面載入時被設爲"on")。 當用戶選擇了一個拿來替換的樣式表時,它們就被禁用了。

要使一個樣式表成爲首選的,可以把 rel 屬性設爲"stylesheet",還得一併設置好 title 屬性。

當然也能把不止一個的樣式表放在一組裏邊,只要給它們相同的 title屬性就行了。這些樣式表將被成組的啓用和禁用。如果定義了超過一組的樣式表,第一組將優先。要使 paul.css 成爲首選的, 得添上 title 屬性,再給默認的樣式一個名字。

<link rel="stylesheet" type="text/css" href="paul.css" title="bog standard" /> 


3. 可變的

這些樣式表可以提供給訪問者作爲可選項來代替首選的樣式表。它們能允許訪問者選擇他或她喜歡的方案,讓這個站點個性化。它們還可以用於提高網站的親和力。

要制定一個可置換的樣式表,rel 屬性可以被設置爲"alternate stylesheet",title 屬性也是不可少的。和"首選"的那類樣式表一樣,可變樣式表也能通過設置同樣的 title 屬性來組織到一起。

還是用前面的例子吧,要使 paul.css 成爲一個可變樣式表,"alternate"必須加在 rel 屬性上。

<link rel="alternate stylesheet" type="text/css" href="paul.css" title="wacky" /> 


注意,所有這些關係只對用 link 元素引入的外部樣式表有效。

二、切換樣式

一個文檔剛被載入時,永久樣式和首選樣式都將被立即應用到文檔上。而此後可變的樣式表能夠由用戶自己選擇。W3C 告訴我們,瀏覽器必須讓我們自由選擇喜歡的樣式表,並建議它提供一個下拉菜單或者工具條來實現這個。

迄今爲止,一切看起來都不錯。我們有了幾個樣式表,訪問者可以通過菜單選擇自己喜歡的一個。但我們很快發現了一個問題,很大的問
題。Mozilla 在"view"菜單欄下提供了一個菜單來讓選擇想要的樣式表。但 Microsoft Internet Explorer (MSIE) 卻沒提供這樣的菜單,所以就算我們有很多樣式表,卻沒法在 MSIE 中用到它們。

這裏有一小段 JavaScript,通過 DOM 來提供一種 MSIE 和 Mozilla用戶通用的樣式表選擇方式。用戶們的偏好還能存入 cookie 中。同時因爲我們照 W3C 的囑咐使用的 link 標記,所以這個 JavaScript並不影響 Mozilla菜單的可用性,所以這可以認爲是一種適度的"向下兼容"。

三、這個腳本

首先我們這個腳本必須能夠區分上面三種不同的樣式表類型。相對來說這還是挺簡單的,畢竟我們只需要檢查每個 link 元素的兩個屬性
而已。

這是否一個到樣式表的鏈接?

HTMLLinkElement.getAttribute("rel").indexOf("style") != -1 


有沒有設置 title 屬性?

HTMLListElement.getAttribute("title") 


rel 屬性是否包含了"alternate"關鍵詞?

HTMLLinkElement.getAttribute("rel").indexOf("alt") != -1 


注意,我們只檢查"alt"字符串, 因爲有些瀏覽器裏,接受的用於標示可選樣式表的關鍵字是"alternative"而非"alternate"。

我們可以寫一個函數,運用這三個檢查來進行樣式表的切換。它致力於遍歷文檔中的每個 link 元素,禁用掉所有我們不希望啓用的首選和可變樣式表,同時啓用所有我們打算啓用的首選和可變樣式表。

還要注意的是, 只有首選和可變的樣式表 link 元素纔有 title 屬性。

於是,這個切換函數大致就像這個樣子:

引用內容: 

function setActiveStyleSheet(title) {
var i, a, main;
for(i=0; (a = document.getElementsByTagName("link")); i++) {
if(a.getAttribute("rel").indexOf("style") != -1
&& a.getAttribute("title")) {
a.disabled = true;
if(a.getAttribute("title") == title) a.disabled = false;
}
}

 


四、Cookie

現在我們可以變換樣式表了,很好。就這樣我們有了一個能夠個性化的頁面,非常好。但我們還是沒有一個能夠個性化的站點。因爲這種對樣式表的偏好僅被應用在當前頁上,一旦離開了這個頁面,偏好就丟失了。這個問題可以由 cookie 來矯正它。

我們需要一個新的函數來返回當前的樣式表,以供存儲到 cookie 中。同時我們還需要另外兩個函數來讀寫 cookie。

只要尋找已啓用的首選和可選型樣式表、檢查它們的 title看看是不是滿足要求,就能返回當前樣式表的 title 了。

具體來說,首先我們又一次的遍歷文檔中所有的 link 元素,檢查 link 的是否一個樣式表,如果是的話,再檢查它是否有 title。 這就能判斷出我們它是否首選的或可選的樣式。

最後一步是檢查這個樣式表啓用了沒有。如果這三個檢查都返回true,這一定就是當前的樣式表,可以返回它的 title。

這個函數就像這樣:

引用內容: 

function getActiveStyleSheet() {
var i, a;
for(i=0; (a = document.getElementsByTagName("link")); i++) {
if(a.getAttribute("rel").indexOf("style") != -1
&& a.getAttribute("title")
&& !a.disabled) return a.getAttribute("title");
}
return null;

 


由於本文是一篇關於樣式的文章,而 cookie 卻完全是另一個的話題,所以我不會在此解釋下面這兩個關於 cookie 的函數。當然我還是把它附於下邊,以便你取用 (這些函數是由 ALA 的作者 Peter-Paul Koch寫的)。

引用內容: 

function createCookie(name,value,days) {
if (days) {
var date = new Date();
date.setTime(date.getTime()+(days*24*60*60*1000));
var expires = "; expires="+date.toGMTString();
}
else expires = "";
document.cookie = name+"="+value+expires+"; path=/";
}

function readCookie(name) {
var nameEQ = name + "=";
var ca = document.cookie.split(';');
for(var i=0;i < ca.length;i++) {
var c = ca;
while (c.charAt(0)==' ') c = c.substring(1,c.length);
if (c.indexOf(nameEQ) == 0) return c.substring(nameEQ.length,c.length);
}
return null;

 


我們必須給當前窗口添加 onload 和 onunload 事件監聽器才能啓用這些 cookie 函數。

1. onLoad

W3C 給對象規定了一個 DOM Level 2 屬性,"disabled", 也就是說在樣式表應用到文檔時就將這個屬性設爲 false便可禁用掉那個樣式表了。這個屬性在 Mozilla 中正確實現了,但在 MSIE 中卻沒有。

可是 MSIE 卻自己給 link 準備了一個也叫"disabled"的 HTML 屬性,初始化時,所有的 link 元素的這個屬性都被設爲了 false。

我們可以把首選的樣式表傳給一個 setActiveStyleSheet() 函數,使得 MSIE 的 disabled 屬性可以像 DOM Level 2 的 disabled 屬性那樣 (採用同樣的方法) 設置。(實質上, 我們是把這兩個屬性都設置了一遍。)

要找出哪些纔是首選的樣式表,還得用到一個新的函數。因爲這個函數和 getActiveStyleSheet() 太像了, 所以我想不需要解釋什麼,不過它大概就像這樣:

引用內容: 

function getPreferredStyleSheet() {
var i, a;
for(i=0; (a = document.getElementsByTagName("link")); i++) {
if(a.getAttribute("rel").indexOf("style") != -1
&& a.getAttribute("rel").indexOf("alt") == -1
&& a.getAttribute("title")
) return a.getAttribute("title");
}
return null;

 


在 onload 函數中,我們首先設置好 title 變量, 這個變量的值要麼是已經存進 cookie 裏面的先前那個樣式表的 title,要麼cookie 裏沒有,就是我們首選的樣式表的 title 了。 我們很自然地把這個cookie 命名爲"style"。

下一步我們把 title 變量傳給 setActiveStyleSheet() 函數。於是onload 函數就像這樣:

引用內容: 

window.onload = function(e) {
var cookie = readCookie("style");
var title = cookie ? cookie : getPreferredStyleSheet();
setActiveStyleSheet(title);

 


注意,這個 onload 函數最好在 onload 事件之前調用,這才能使文檔在一開始就按照我們的喜好用正確的樣式表呈現出來。

如果你決定這麼做的話,得確保這個函數在在其他函數和 link 元素都定義好以後才被調用。

2. onUnload

在 onunload 事件時保存 cookie 就簡單得多了。我們只需要使用那個 getActiveStyleSheet() 函數來獲取啓用的樣式表, 把它保存進cookie 中即可。因而這個函數是這樣的:

引用內容: 

window.onunload = function(e) {
var title = getActiveStyleSheet();
createCookie("style", title, 365);

 


五、統統放在一起吧

你可以把這些函數包含於你的文檔中,便能使你的網站更加性感了。如果希望一切從簡的話,我已經把這些函數一齊放進了一個 JavaScript 文件中,你馬上就可以下載下來,放進你的站點中。

下載 styleswitcher.js (../scripts/styleswitcher.js)

你可以在你的文檔 head 部分中加入一個 script 元素來包含這個文件,但得確保它放在樣式表的 link 元素下邊。HTML 代碼是這樣的:

引用內容: 

<script type="text/javascript" 
src="/scripts/styleswitcher.js"></script> 
 


要讓訪問者改變啓用的樣式表,你可以使用 JavaScript 的 onClick事件。比如說要提供切換於以"default"和"paul"爲 title 的兩套樣式表之間的選項,可以使用如下 HTML:

引用內容: 

<a href="#" 
οnclick="setActiveStyleSheet('default'); 
return false;">change style to default</a>

<a href="#" 
οnclick="setActiveStyleSheet('paul'); 
return false;">change style to paul</a> 
 


一旦訪問者選擇了一套樣式表,它的 title 就被存放在了 cookie 中,如果你希望在整個站點都呈現同樣的一套樣式表的話,那這個站點的每個頁面都必須在 head 部分包含相同的樣式表和 JavaScript的鏈接。

http://www.zjwz.net/beyond/blogview.asp?logID=262
發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章