The DOM provides various functions to modify the document.
You can create new elements using the createElement()
function of the document. It takes one argument, the tag name of the element to create. You can then set attributes of the element using the setAttribute()
function and append it to the XUL document using the appendChild()
function. For example, the following will add a button to a XUL window:
<script> function addButton(){ var aBox = document.getElementById("aBox"); var button = document.createElement("button"); button.setAttribute("label","A new Button"); aBox.appendChild(button); } </script> <box id="aBox" width="200"> <button label="Add" oncommand="addButton();"/> </box>
getElementById()
, which is the container to add a new button to. The function getElementbyID() does not know that the box it is looking for happens to be containing the tag that has the oncommand attribute that referenced it. getElementById() only knows the box it is looking to find has an id with the value "aBox". This is a subtle dependency between the function and the XUL element to which you should pay attention.createElement()
function to create a new button. Note this button is not visible, nor is it attached to anything yet.setAttribute()
function.appendChild()
function of the particular box found by getElementbyID() is called to add the button to it. At this point, the button is attached to a visible box, so it becomes visible as well.The createElement()
function will create the default type of element for the document. For XUL documents, this generally means that a XUL element will be created. For an HTML document, an HTML element will be created, so it will have the features and functions of an HTML element instead. The createElementNS()
function may be used to create elements in a different namespace.
The appendChild()
function is used to add an element as a child of another element. Three related functions are the insertBefore()
, replaceChild()
and removeChild
functions. The syntax of these functions is as follows:
parent.appendChild(child); parent.insertBefore(child, referenceChild); parent.replaceChild(newChild, oldChild); parent.removeChild(child);
It should be fairly straightforward from the function names what these functions do.
insertBefore()
function inserts a new child node before an existing one. This is used to insert into the middle of a list of children of the parent element instead of at the end like appendChild()
does.replaceChild()
function removes an existing child and adds a new one in its place at the same position in the list of its parent element.removeChild()
function removes a child from the list of its parent element.Note that for all these functions, the object referred to by the variable referenceChild or the variables newChild and oldChild must already exist or an error occurs. Likewise the object referred to by the variable child which is to be removed must already exist or an error occurs.
It is often the case that you want to remove an existing element and add it somewhere else. If so, you can just add the element without removing it first. Since a node may only be in one place at a time, the insertion call will always remove the node from its existing location first. This is a convenient way to move nodes around in the document.
To copy nodes however, you may call the cloneNode()
function. This function makes a copy of an existing node so that you can add it somewhere else. The original node will stay where it is. It takes one boolean argument which indicates whether to copy all of the node's children or not. If false, only the node is copied, such that the copy won't have any children. If true, all of the children are copied as well. This is done recursively, so for large tree structures make sure that this is desired before passing true to the cloneNode()
function. Here is an example:
<hbox height="400"> <button label="Copy" oncommand="this.parentNode.appendChild(this.nextSibling.cloneNode(true));"/> <vbox> <button label="First"/> <button label="Second"/> </vbox> </hbox>
When the Copy button is pressed..
nextSibling
of the button
, which will be the vbox
element.cloneNode()
functionappendChild()
.Note that some elements, such as
and listbox
provide some additional specialized modification functions which you should use instead when you can. These are described in the next section.menulist
The main XUL elements such as buttons, checkboxes and radio buttons may be manipulated using a number of script properties. The properties available are listed in the element reference as those available are different for each element. Common properties that you will manipulate include the
, label
, value
and checked
properties. They set or clear the corresponding attribute as necessary.disabled
Here is a simple example which changes the label on a button:
<button label="Hello" oncommand="this.label = 'Goodbye';"/>
When the button is pressed, the label
is changed. This technique will work for a variety of different elements that have labels. For a textbox, you can do something similar for the
property.value
<button label="Add" oncommand="this.nextSibling.value += '1';"/> <textbox/>
This example adds a '1' to the textbox each time the button is pressed. The nextSibling
property navigates from the button (this) to the next element, the textbox. The += operator is used to add to the current value so a 1 will be added onto the end of the existing text. Note that you can still enter text into the textbox. You can also retrieve the current label or value using these properties, as in the following example:
<button label="Hello" oncommand="alert(this.label);"/>
Checkboxes have a
property which may be used to check or uncheck the checked
. It should be easy to determine how this is used. In this next example, we reverse the state of the checkbox
property whenever the button is pressed. Note that while the checked
and label
properties are strings, the value
property is a boolean property which will be set either true or false.checked
setAttribute("checked", "false")
instead, because the XBL isn't initiated yet.)<button label="Change" oncommand="this.nextSibling.checked = !this.nextSibling.checked;"/> <checkbox label="Check for messages"/>
Radio buttons may be selected as well using properties, however since only one in a group may be selected at a time, the others must all be unchecked when one is checked. You don't have to do this manually of course. The radiogroup's
property may be used to do this. The selectedIndex
property may be used to retrieve the index of the selected radio button in the group and well as change it.selectedIndex
It is common to disable particular fields that don't apply in a given situation. For example, in a preferences dialog, one might have the choice of several possibilities, but one choice allows additional customization. Here is an example of how to create this type of interface.
<script> function updateState(){ var name = document.getElementById("name"); var sindex = document.getElementById("group").selectedIndex; name.disabled = sindex == 0; } </script> <radiogroup id="group" onselect="updateState();"> <radio label="Random name" selected="true"/> <hbox> <radio label="Specify a name:"/> <textbox id="name" value="Jim" disabled="true"/> </hbox> </radiogroup>
In this example a function updateState() is called whenever a select event is fired on the radio group. This will happen whenever a radio button is selected. This function will retrieve the currently selected
element using the radio
property. Note that even though one of the radio buttons is inside an selectedIndex
, it is still part of the radio group. If the first radio button is selected (index of 0), the textbox is enabled by setting its hbox
property to true. If the second radio button is selected, the textbox is enabled.disabled
The next section will provide more details about manipulating radio groups as well as manipulating lists.