添加屬性(Adding PropertIEs)
在這一節,我們將學習怎樣為XBL元素增加自定義屬性。
XBL接口
通過JavaScript和DOM,可以對元素的屬性進行訪問。在XBL中,你可以為元素自定義屬性,當然也可以為元素添加方法。而你需要做的只是獲得這個元素的引用(使用getElementById或者類似的方法),就可以直接訪問屬性或者調用方法。
你可以為元素增加三種類型的子項。字段(Fields)用於保存簡單值。屬性(PropertIEs)用來保存那些可能會被其他代碼調用或者修改的值。方法(Methods)是那些可以執行的函數。
這三種子項都要在implementation元素中定義,而implementation元素必須是binding元素的子元素。通過implementation元素,你就可以定義任何的fIEld、property和method元素了,基本語法如下所示:
<binding id="element-name">
<content>
-- content goes here --
</content>
<implementation>
<field name="fIEld-name-1"/>
<field name="fIEld-name-2"/>
<field name="fIEld-name-3"/>
<property name="property-name-1"/>
<property name="property-name-2"/>
<property name="property-name-3"/>
.
.
.
<method name="method-name-1/>
-- method content goes here --
</method>
.
.
.
</implementation>
</binding>
字段(FIElds)
你可以使用fIEld元素來定義字段。通常情況下,字段會對應於元素上的特性(attribute),比如說和label或者disabled特性對應,但這不是必須的。
fIEld元 素的name特性用於標識字段的名稱。在腳本中,你可以通過這個名稱對字段進行操作。下面的例子建立了一個button,按鈕的作用就是生成並保存一個隨 機數。你可以通過調用button的number屬性來多次調用這個相同的隨機數。例子中大部分的操作都是在oncommand處理程序中完成的。在後續 的教程中,我們會把這些操作放到XBL中。
XUL:
<box id="random-box" class="randomizer"/>
<button label="Generate"
oncommand="document.getElementById('random-box').number=Math.random();"/>
<button label="Show"
oncommand="alert(document.getElementById('random-box').number)"/>
XBL:
<binding id="randomizer">
<implementation>
<fIEld name="number"/>
</implementation>
</binding>
在綁定項中我們定義了一個number字段,用於保存一個隨機數。另外兩個按鈕分別用於生成和獲取這個隨機數。對元素的屬性進行賦值和取值的語法是 非常類似的。在這個例子中,在XUL的box元素內部沒有定義子元素,在XBL中也沒有定義任何匿名內容,這樣做是完全有效的。
這個例子還有瑕疵,因為這個字段沒有設置默認值。我們可以向fIEld標記下面添加內容,來作為這個字段的默認值。
<fIEld name="number">
25
</fIEld>
這個操作將把25作為默認值分配給number字段。實際上,你可以在fIEld元素的內部使用一段腳本,通過計算來獲得默認值,這在有些時候可能是必須的。比如說,下面的字段將使用當前日期作為默認值。
<fIEld name="currentTime">
new Date().getTime();
</fIEld>
屬性(PropertIEs)
有時候,我們需要對賦給屬性的值進行校驗,或者你可能要對賦的值進行動態的運算。比如說,你需要一個屬性來保存當前時間,而這個值要在取值的時候進行更新。這時候你就需要用property標記來代替fIEld標記了,他們的功能很相似,但是property有一些額外的功能。
你可以在onget和onset特性下面定義代碼,這些代碼會在調用屬性或者修改屬性的時候執行。你需要為每個property元素添加onget和onset,這兩個元素內部要編寫讀取和修改屬性時用到的腳本。
比如說,你可以把一段計算當前時間的腳本代碼賦值給onget。這樣無論什麼時候訪問這個屬性的值,onget的腳本就會被執行並返回這個值。腳本必須把屬性的值當成返回值返回。
onset處理程序和onget很類似,但是調用時間不同。onget內的腳本會在你向屬性賦值的時候被調用。這裡的腳本應該把屬性值保存起來,或者對屬性值進行校驗。舉例來說,有一些屬性可能會只允許保存數值類型,而且應該禁止向這類屬性賦文本類型的值。
<property name="size"
onget="return 77;"
onset="alert('Changed to:'+val); return val;"/>
這個屬性只要調用就會始終返回77。而賦值的時候,就會把要賦的值顯示出來。特別變量val用來保存屬性的值,而且要在onset內部對其進行賦值。使用這個變量對屬性值進行校驗和保存。在onset代碼內部,同樣需要把新賦的值返回。
下面介紹一個典型案例:
有兩個元素,一個叫做“banana”,另外一個叫做“orange”。每個元素都有一個自定義屬性“size”。當下面這段代碼被執行的時候:
banana.size = orange.size;
orange的size屬性會通過onget腳本計算後返回。
banana的size屬性的onset內的腳本,會把通過val變量傳過來的值通過某種方式賦給banana的size屬性。
注意和字段不同的是,屬性無法保存任何值。如果在沒有設置onset處理程序的前提下對屬性進行賦值會導致異常。你需要使用獨立的字段來充當保存有實際值的屬性。而且這些屬性等同於在XBL元素上定義的特性。下面的例子映射了屬性和元素上特性之間的關系:
<property name="size"
onget="return this.getAttribute('size');"
onset="return this.setAttribute('size',val);"
/>
無論何時,如果在腳本中調用size屬性,都會調用使用property定義的屬性,這樣就間接的調用了元素上定義的同名特性。而當腳本對屬性進行賦值時,實際上是對元素上的特性進行賦值。這樣帶來很大的便利性,無論你修改屬性還是特性,都可以使兩項得到同步。
對於onget和onset特性有一種可以替換的語法,當onget和onset內部的腳本很長時,這種語法就顯得特別適用。可以在getter子元素下編寫腳本,替代在onget特性中編寫腳本。同樣,你也可以用setter元素來替換onset特性,下面是一個例子:
<property name="number">
<getter>
return this.getAttribute('number');
</getter>
<setter>
var v = parseInt(val,10);
if (!isNaN(v)) return this.setAttribute('number',''+v);
else return this.getAttribute('number');"
</setter>
</property>
例子中的屬性只可以保存整數類型的值,多余的字符會被忽略,如果輸入的不是數值,則value的值不會發生改變。這些所有的操作都是在setter元素內的代碼中完成的。屬性的真實值被保存在number特性中。
你可以根據實際情況來選擇使用哪種語法來建立get和set處理程序。
如果你在fIEld或者property標記中設置readonly特性的值為true,那麼這個字段或者屬性就是只讀的。任何嘗試對只讀屬性進行賦值的操作都會導致異常。
下一節我們將探討如何向XBL元素中添加方法。