是className,可不是class
注意JavaScript使用的是className去訪問class屬性,因為class是一個保留關鍵字,因為將來JavaScript可能開始支援像Java一樣的類。
我們在討論style屬性時遇到了棘手的細節問題和瀏覽器差異性帶來的麻煩,正如同經曆一場驚濤駭浪。而class和id的更改則像是沙漠裡一片平靜的綠洲,瀏覽器們在這裡和諧相處。思考這個例子:
p {
color: #000000; /* black */
}
p.emphasis {
color: #cc0000; /* red */
}
<p id="test">Test</p>
最初,該段落沒有定義class,所以它的字型顏色是黑色。不過,一行JavaScript就足以改變它的樣式:
document.getElementById('test').className = 'emphasis';
瞬間文字變成了紅色。如果想要改變回來,你可以按如下操作:
document.getElementById('test').className = '';
你移除了樣式,該段落恢複到預設的p{}規則。
對於一個實際應用中的例子,看看“限長的文本輸入區”。計數器有這樣的結構和呈現樣式(該結構由JavaScript動態產生,不過那不影響這個例子):
<div class="counter"><span>12</span>/1250</div>
div.counter {
font-size: 80%;
padding-left: 10px;
}
span.toomuch {
font-weight: 600;
color: #cc0000;
}
當指令碼發現使用者輸入的文字一定達到了最大長度,它修改作為計數器的<span>的class為toomuch:
[限長的文本輸入區,第20~23行]
if (currentLength > maxLength)
this.relatedElement.className = 'toomuch';
else
this.relatedElement.className = '';
現在,作為計數器的<span>字型變成粗體和紅色。
id的變更以幾乎完全一樣的方式工作:
p {
color: #000000; /* black */
}
p#emphasis {
color: #cc0000; /* red */
}
<p>Test</p>
document.getElementsByTagName('p')[0].id = 'emphasis';
該段落的文字再次變成了紅色。但是,我建議你不要過多改變id。除了作為CSS的鉤子,它們也常常作為JavaScript的鉤子,改變它們可能存在不確定的副作用。
增加class
通常,你不會給一個元素的class設定新值,而只是添加一個class。因為你不希望移除元素已經擁有的任何樣式。因為CSS允許複合樣式,新class所包含的樣式被添加到元素上,不會移除任何已經存在的class的CSS指令。
“表單驗證”中的writeError()和removeError()函數是一個很好的例子。一般來說我會給表單域應用好幾個class,因為圖形設計師經常對輸入框使用兩個甚至三個寬度。當一個表單域包含錯誤的時候,我希望添加一個特別的警告樣式,但我不希望攪亂該元素已經擁有的樣式。所以,我不能簡單地覆蓋舊的class值,那樣我將失去已經指定的寬度。
看這樣的情形:
<input class="smaller" name="name" />
input.smaller {
width: 75px;
}
input.errorMessage {
border-color: #cc0000;
}
最開始,輸入框的寬度是75px。如果指令碼設定class為'errorMessage'並且刪除舊值,表單域會得到一個紅色的邊框,但也失去了它的寬度,而那樣的話可能會讓使用者感到非常迷惑。
因此,我是添加了errorMessage class:
[表單驗證,第105~106行]
function writeError(obj,message) {
obj.className += ' errorMessage';
這段代碼取得已存在的className並在其後附加一個新的class,在它之前加一個空格。這個空格分隔新的class和任何對象可能已經擁有的class值。現在輸入框除了擁有75px寬度之外,如我們所願地得到了紅色邊框。該表單域現在應用了兩個class,HTML就好像這樣:
<input class="smaller errorMessage" name="name" />
Class在Mozilla中的名稱與空白
你可能注意到removeError()移除class的值errorMessage的時候沒有前置的空格。那是因為一個瀏覽器的bug。當你添加errorMessage到一個原來沒有值的class的時候,Mozilla會刪除前置空格。如果我們隨後執行replace(/ errorMessage/,''),Mozilla不能移除class,它找不到字串errorMessage,因為前置空格已經不在了。
移除class
一旦使用者修正了她的錯誤,class的值errorMessage應該被移除,但任何原來的class,比如smaller,不應該受到影響。removeError()函數提供了這個功能:
[表單驗證,第119~120行]
function removeError() {
this.className = this.className.replace(/errorMessage/,'');
它先取得元素的class然後替換字串'errorMessage'為''(一個Null 字元)。errorMessage從class的值中被取走,但對其他的值沒有影響。表單域失去了紅色的邊框顏色,但依然維持75px的寬度。