DOM には文書を変更するために、色々な関数が用意されています。
要素の新規作成
文書 (document
) の createElement()
関数を使うことで、新規の要素を作成することが可能です。 この関数は、引数を 1 つ取り、そこに作成する要素のタグ名を渡します。 作成した後は、 その要素に対して、setAttribute()
関数を使用して属性の設定を行っていき、 完了したら、appendChild()
関数を使用して XUL 文書に追加することができます。 XUL ウインドウにボタンを追加する例を、以下に示します。
<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()
関数によって取得します。 - 次に、
createElement()
関数で新規にボタンを作成します。 - 続いて、
setAttribute()
関数でボタンのラベルに「A Button」を設定します。 - 最後に、ボックスに対して
appendChild()
関数を呼び出して、ボタンをボックスに追加します。
createElement()
関数は、その文書に応じたデフォルトの型の要素を作成します。 つまり、XUL 文書の場合は、一般に XUL 要素が作成されることを意味します。 また、HTML 文書の場合は、かわりに HTML 要素が作成されて HTML 要素の特徴と機能を持つことになります。 なお、異なる名前空間の要素を作成するには createElementNS()
関数が利用できます。
appendChild()
関数は、要素を別の要素の子要素として追加するときに使用します。 これに関連する関数として、insertBefore()
、replaceChild()
、removeChild
の 3 つがあります。 この 3 つの関数の構文を、以下に示します。
parent.appendChild(child); parent.insertBefore(child, referenceChild); parent.replaceChild(newChild, oldChild); parent.removeChild(child);
これらの関数の機能は、その名前が示すままのものになります。
insertBefore()
関数は、新しい子ノードを、既存の別の子ノードの前に挿入します。これはappendChild()
が、要素を一連の子要素の最後に追加するのに対し、間のどこかに挿入したい場合に使用します。replaceChild()
関数は、既存の子要素を削除して、その場所に新たな要素を追加します。- 最後の
removeChild()
関数は、既存のノードを削除します。
これらのどの関数においても、参照する子要素、あるいは取り除かれることになる子要素は、存在していないとエラーになる点に注意してください。
既存の要素を、取り除いて別のどこかに追加したくなることはしばしばあります。 その場合は、要素を取り除く操作は必要はなく、単に追加するだけでかまいません。 ノードは、DOM 上には、同時に 1 つの場所にしか置くことができないため、挿入系の呼び出しでは、まず最初に、追加するノードを元の場所から取り除くことが常に行われます。 これは、文書内でノードの位置を動かすときに便利な方法です。
ノードのコピー
また、ノードをコピーするためには cloneNode()
関数を使用します。 この関数は、既存のノードのコピーを作成して、どこか別の場所に追加します。 このとき、元のノードは元の場所に残されます。 また、この関数は真偽値の引数を 1 つ取って、子ノードも全てコピーするかどうかを指示します。 この値が false の場合は、ノード自身のみがコピーされ、子ノードのコピーは行われません。 また、値が true の場合は、全ての子ノードが同じようにコピーされます。 この動作は再帰的に行われるので、大きなツリー構造を持つノードの場合は、cloneNode()
関数に true を渡す前に、本当に必要かどうかを確かめておくべきでしょう。 以下に例を示します。
<hbox height="400"> <button label="Copy" oncommand="this.parentNode.appendChild(this.nextSibling.cloneNode(true));"/> <vbox> <button label="First"/> <button label="Second"/> </vbox> </hbox>
Copy ボタンが押されると..
nextSibling
関数によって、
に隣接する次の要素であるbutton
が取得されます。vbox
cloneNode()
関数によって、取得した要素のコピーが作成されます。appendChild()
関数によって、作成したコピーを DOM に追加します。
や listbox
などの一部の要素には、変更操作のために専用の関数が追加で用意されています。 これらの要素を変更する場合は、可能なら専用の関数の方を使うべきであることに注意してください。 これらについては、次のセクションで説明する予定です。menulist
基本的な要素の操作
ボタンやチェックボックス、ラジオボタンといった主要な XUL 要素は、いくつかのスクリプトプロパティを通して操作することが可能です。 利用できるプロパティは各要素で異なっているため、詳細は XUL 要素リファレンスの一覧で確認してください。 これらの要素を操作するための共通プロパティとしては、
、label
、value
、checked
などがあります。 これらのプロパティは、必要に応じて対応する属性の設定や消去を行います。disabled
label と value プロパティの例
以下に、ボタンのラベルを変更するための簡単な例を示します。
<button label="Hello" oncommand="this.label = 'Goodbye';"/>
ボタンが押されたとき、そのボタンのラベルが変更されます。 この技法は、ラベルを持っている他のたくさんの要素に対しても有効です。 また、テキスト入力欄については、
プロパティを使って類似のことが可能です。value
<button label="Add" oncommand="this.nextSibling.value += '1';"/> <textbox/>
この例では、ボタンが押される度にテキスト入力欄に'1'
が追加されていきます。 nextSibling
プロパティによって、ボタン (this) から次の隣接要素であるテキスト入力欄へ誘導しています。 そして、+=
演算子は、現在の値に加算するために使われるため、そのとき入力されているテキストの末尾に 1 が付加されることになります。 この場合も、依然としてテキスト入力欄へ入力することも可能であることを補足しておきます。 また、これらのプロパティを通して、現在のラベルや要素の値を取得することも可能です。 以下に、例を示します。
<button label="Hello" oncommand="alert(this.label);"/>
チェックボックスの状態変更
チェックボックスには
プロパティがあり、チェックボックスをチェックしたり解除したりするために使用できます。 このプロパティの使い方は、あなたが考えている内容とおそらく同じです。 次の例では、ボタンが押されるごとに、checked
プロパティの状態を反転させます。 なお、checked
や label
が文字列プロパティであるのに対して、 value
は、true か false のみが設定可能な、真偽値プロパティであることに注意してください。checked
<button label="Change" oncommand="this.nextSibling.checked = !this.nextSibling.checked;"/> <checkbox label="Check for messages"/>
ラジオボタン (
) もプロパティを用いて選択可能ですが、グループ内で選択できるのは、同時に 1 つだけなので、1 つがチェックされた場合、他のものはチェックされていないようにしなければなりません。 もちろん、この処理をアプリケーション開発者がいちいち行う必要はなく、ラジオグループ の radio
プロパティを利用して、自動的に行わせることが可能です。 また、selectedIndex
プロパティは、変更だけではなく、グループ内で何番目のラジオボタンが選択されているかを示すインデックスを取得するためにも利用できます。selectedIndex
要素の無効化と有効化
状況に応じて、特定のフィールドが適用されないように無効にしておくのは、ありふれた手法だと思います。 例えば、いくつかの選択肢から 1 つを選ぶような入力があり、その中の 1 つを選んだ場合だけ、さらに詳細なカスタマイズが可能になるような設定ダイアログを作成する場合、この手法が使用できます。 以下に、このようなインターフェイスを作成する例を示します。
<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>
この例では、ラジオグループに対して select イベントが発生したときに updateState()
関数が呼び出されます。 (この呼び出しは、ラジオボタンが選択されるたびに発生します)。 この関数は、現在選択されている
要素を、radio
プロパティから取得します。 このとき、ラジオボタンのうちの 1 つは、直接ラジオグループには置かれず、selectedIndex
内に置かれていますが、これも依然としてラジオグループに含まれていることを注記しておきます。 最初のラジオボタンが選択されると、(インデックスが 0) テキスト入力欄の hbox
プロパティは true にされるため、無効になります。 また、2 番目のラジオボタンが選択されると、テキスト入力欄は有効になります。disabled
次のセクションでは、ラジオグループとリストに対する操作の詳細について説明します。