30 Dec 2006
This document describes a means of maintaining state in a XUL document, as well as observing changes to an application's state.
The appStorage
window attribute may be used to retrieve a
StorageList
object which provides a per-domain Storage area. Unlike the storage areas provided
by the globalStorage, the data within an appStorage is only
available until the application terminates. The Storage objects retrieved in this
manner otherwise operate identically.
Both the appStorage and
globalStorage StorageList objects may take a chrome URL
to retrieve a storage area for a particular chrome package identifier.
When calling the StorageList's namedItem method, if the domain argument
begins with the string 'chrome://', then a chrome storage area is retrieved. If the
domain of the calling script is not a chrome domain or otherwise doesn't have access
to the chrome domain, then a security exception must be thrown. Otherwise, the chrome
package id is determined by finding the first slash character (U+002F) after the
'chrome://' prefix and taking all characters between those exclusively. If the slash
character does not exist, then all characters between the 'chrome://' prefix and the
end of the string exclusively are used. The storage area for that package id is then
returned. This effectively means that characters after the first slash have no effect
on which storage area is returned.
Chrome storage areas behave identically to other storage areas.
Chrome will likely need a means of storing objects other than strings.
When a chrome storage area is changed, a storage event is fired on all other documents containing chrome URLs. The domain of this event is the string 'chrome://' concatenated with the chrome package id as calculated above.
The XUL <observes> element may be used to observe changes to a chrome storage area, as well as DOM attribute changes to another element.
The type DOM attribute
on the <observes> element is used to specify the type of storage area to listen
for changes to. Possible values for this attribute are:
element: the default value, used to listen to changes to another
element. The id of the element to listen to should be specified by the
element attribute. The specifics of this process are described later.
It is recommended to leave the type attribute out if this value is
used, as it is the default value.session: listen to changes in a session storage area.app: listen to changes in an application storage area.global: listen to changes in an global storage area.Regardless of the type specified for the <observes> element, it may need to determine the element that will receive the change, called the observing element. If the parent node of the <observes> element is an <observesset> element, then the observing element is the <observes> element itself. Otherwise, it is the parent node of the <observes> element.
When the type attribute on an <observes>
element is set to either session, app or
global, the observer listens to changes to a storage area. It only
listens to changes to a storage area of the appropriate type. Changes to storage
areas of other types are not examined.
The domain attribute
is used to filter the observer such that it only listens to changes to the storage
area of a particular domain. For chrome storages, the domain attribute should be set
to the string 'chrome://' concatenated with the chrome package id to listen to.
The key attribute
may be used to filter the observer such that it only listens to changes to particular
keys. The observer will ignore changes to other keys. The value of the
key attribute should be the key to listen to.
The attribute
attribute specifies the name of the attribute to modify on the
observing element when the storage data changes.
When the value of the key and domain is changed, the value of the specified attribute
is set to that value. If the attribute attribute is not specified, no
attribute is set.
Here are some examples of observers:
<observerset onbroadcast="dosomething();">
<observes type="global" domain="www.example.com"/>
<observes type="app" domain="chrome://testapp" key="seen-once"/>
<observes type="app" domain="chrome://testapp" key="seen-once"
attribute="value"/>
<observerset>
The first observer listens to all changes to the global storage for the domain
'www.example.com'. If any key within global storage changes, either by being set,
modified or removed, the observer is notified of the change. This example uses the
broadcast event to listen for changes, as explained in a
later section. Note that there is no means of
determining which key was actually changed.
The second observer listens to the application storage for the chrome package
'testapp'. However, as the key attribute has been set, it is only
notified of the changes to the key 'seen-once'. Within the broadcast
event listener, the value of this key could be examined.
The third observer is similar to the second except that the value
attribute of the <observes> element is set to the value of the 'seen-once'
key whenever it is changed.
<button id="details-button" label="Details...">
<observes type="global" domain="chrome://testapp"
key="hidedetails" attribute="hidden"/>
</button>
<button label="Hide" oncommand="globalStorage['chrome://testapp'].hidedetails = true"/>
When the type attribute on an <observes>
element is set to element or not specified, the observer is used to
listen for changes to the attributes of another element within the same document.
The element
attribute specifies the id of another element within the
same document. If the id matches the id of the <obseves> element itself, or
doesn't match the id of any element within the document, the <observes>
element has no effect and observes nothing. If the value of the element
attribute is modified, then the observer must stop observing the element specified
by the old value and begin observing changes to the new element. Inserting an
<observes> element into a document causes it to begin observing changes the
the specified element, while removing one fron a document causes it to stop
observing changes.
If the element attribute refers to an id that doesn't match an element
within the same document, the observer does nothing. Inserting an element matching
this id does not cause the observer to begin observing changes.
The attribute
attribute specifies the name of the attribute to listen for changes to. When the
value of the attribute of the element being observed (specified by the
element attribute) changes, the same attribute on the
observing element should be set to the same value. If
the attribute is removed, then the same attribute on the
observing element element should be removed. Thus,
after a change to this attribute to the element being observed, the methods
hasAttribute and getAttribute should return the same values
for both the observing element and the observed
element. Changing the attributes directly on the
observing element does not cause the observed element
to change in any way.
If the attribute attribute is set to the value *, or
is not specified, then all attributes are observed except the id,
ref and persist attributes. This functions as with
observing a single attribute, except any attribute modified on the observed
element causes the corresponding attribute on the
observing element to be set to the same value.
The <broadcaster> element is a convenient placeholder when several element observers wish to observe an attribute change. Any attribute is valid on the <broadcaster> element. Typically, several observers will observe a broadcaster so that a change made to the attributes of a broadcaster will propagate to all of the other elements.
The observes
attribute applies to any XUL element. It is a shorthand for defining a child
<observes> element with the attribute attribute set to
*. The value of the observes attribute is used as the
value for the observer's element attribute. When using the attribute
form, the element becomes the observing element.
If the observes attribute is set or modified on an element, then it
will begin observing the element with the id in the same document specified by the
value of the attribute. If an element with this id does not exist in the document,
then the observer does not observe anything. Adding an element to the document
with this id does not cause the observe to start observing that element.
Removing the observes attribute from an element causes the observer
to stop observing that element.
Thus, the following two examples are equivalent:
<button label="Show" observes="show-toolbar"/> <button label="Show"> <observes element="show-toolbar"/> </button>
The broadcast
event, which bubbles, is not cancellable, and has no default action is fired on
the <observes> element whenever a change is made that affects the observer.
The broadcast event is fired only when using the <observes>
element and is not fired at all when using the shorthand
observes attribute.
In this example, the dosomething() method will be called when the
show-images key is changed with the application storage area for the
'sample' chrome package.
<observes type="app" domain="chrome://sample"
key="show-images" onbroadcast="dosomething();"/>
Add stuff about commands here.
XUL provides a automatic persistent storage which is more convenient when storing the state of the attributes of an element. The persistent attribute store saves the state of attributes when they are changed, and restores them again when the document with the same URI is loaded again.
The persist attribute
on an element specifies a space-separated list of attribute names that should be
persisted for that element. If the element does not have an id, then the persist
attribute has no effect. Otherwise, whenever an attribute contained within the
list of attributes specified by the persist attribute is changed on that element,
the new value is saved in the
persistent attribute store in such a way
that the value can be restored later as described below. If an attribute is removed,
an indication of this should also be stored.
When the URI of the document of an element with a persisted attribute is later
loaded again (whether the same document or another document), the value of that
attribute is set to the persisted value. This should also restore the state of
removed attributes such that the element should not have the attribute. The process
of restoring persisted attributes is done during or after parsing the document, but
before the load event is fired on the document. Persistence also applies
to a generation element created from a template when it is inserted into the
document. Other than the elements existing in the document when it is parsed, or
template generation elements, elements inserted later do not have persisted
attributes applied. Persisted attributes are restored regardless of whether the
attribute to restore is contained with the list specified by the
persist attribute when restoring it.
Adding, changing or removing the persist attribute on an element only affects later attribute changes to the element and does not change the persistent attribute store. (unless the persist attribute is itself contained within the list of attributes to persist, in which case it should be stored as with any other attribute).
In order for this to work, the persistent attribute store will need to store the document's URI, the id of the element, the attribute name and the attribute value.