DOMによるWeb Application Clientの可能性

DOMにより、エレメントを変化(へんげ)させる

『DOMにより、エレメントを見つけ出す』で、ドキュメント内から要素(エレメント)を見つけ出す、代表的な方法をいくつか紹介しました。

このコンテンツでは、見つけ出した要素を、あれやこれやする方法を紹介します。

ここで紹介する機能は、『CSS Object Model (CSSOM)』として、仕様が公開されています。興味が有ればご覧ください。

スタイルが気になる?

要素さえ見つけてしまえば、後は好きなように料理できます。サイズ・色・表示/非表示なども、簡単に変更できます。スタイルを変えてしまえば良いのです。

とても簡単なサンプル

下記の例では、colorChangeというIDを持った要素の前景色(文字)を、赤に変更します。

変更したスタイルを元に戻すには、空文字を代入します。

但し、html上でインラインスタイルが指定してある場合、それが上書きされてしまうので、正しく元に戻りません。

DOMで処理したいドキュメントには、インラインスタイルを使わない方が、幸せになれるかもしれません。

ボタンをクリックすると、前の文字の色が変わります。

ここの色が変わります

要素のstyle属性は、"CSS Object Model (CSSOM)" で定義された、CSSStyleDeclarationオブジェクトです。

アプリケーションからは、このオブジェクトを通して、各要素のインラインスタイルにアクセスすることができます。

じゃあ、background-colorはどうやって変更する?

document.getElementById(ID).style.background-color = 'red';では、エラーとなってしまいます。

JavaScriptのフィールド(属性)名には、'-'(ハイフン)が使えないからです。

CSSのプロパティは、単語を'-'でつなげる、チェインケースという命名規則で名前が付いていますが、JavaScript(や他のだいたいの言語)では、単語の先頭を大文字にするキャメルケースという命名規則で、スタイルのプロパティを定義しています。

背景色を変更したい場合は、下記のようになります。

また、連想配列を使えば、下記のような記述もできます。こちらであれば、CSSの通常のプロパティ名が使えます。

ここの背景色が変わります

いくつかの例

消し去る

この要素が消え去る

非表示にする

この要素が見えなくなる

不可視とするだけなので、displaynoneを指定する場合と異なり、レイアウトには影響しません。

サイズを変更する

大きくなります

カーソルを変更する

カーソルがボタンの上に有ると変わらないので、すこと動かしてみてください。

位置を変更する

対象要素のposition(ポジション)に、absoluteを指定する必要があります。

青い点が動きます。衝突チェックなどしていないので、何処までも動き回ります。

emって言われてもなあ

CSSでサイズや位置を指定するとき、px単位ではなく、文字サイズをベースとしたemを使うことも多いと思います。

しかし、プログラムから操作する場合は、px単位で操作したい場合があります。

もちろん、offsetTopoffsetWidthといった、DOMのプロパティもありますが、getComputedStyleメソッドを使えば、CSSの設定からWebブラウザが算出した結果を取得することもできます。

ボーダーやパディングを除いたコンテンツ領域のサイズを知りたい場合も、DOMのプロパティから算出するより容易に取得できます。

このサンプルでは、下記のHTMLを使用します。

上記HTMLに、下記のCSSを適用します。

idoutの要素(黒のボーダーで囲まれている要素)の計算済みスタイルの取得は、以下のようになります。

取得した内容は下記のようになります。比較のために他のプロパティの内容も表示します。

out.offsetLeftout.offsetTop out.offsetWidthout.offsetHeight
out.clientLeftout.clientTop out.clientWidthout.clientHeight
outStyle.leftoutStyle.top outStyle.widthoutStyle.height

算出された結果は、小数点以下まで保持されているので、数値に変換する場合にparseFloatを使えば、最終的な誤差が小さくなります。

チマチマやってられないときは

これまでの方法は、個々のタグに対して、スタイルを変更するものでした。

しかし、状況によっては、複数のタグを一度に変更したい場合が有ります。

このような場合、スタイルシートの内容を、セレクタ毎に設定することができます。

まず、ドキュメントからスタイルシートのリストを取得します。

let styleList = document.styleSheets;

このリストの中には、link要素でリンクされたスタイルシートや、style要素で直接記述されたスタイルシート等が含まれます。

リストから、スタイルシートを取得します。

let styleSheet = styleList[n];

次に、スタイルシートの中から、必要なCSSRuleオブジェクトを検索します。このとき、セレクタ名称などで検索する方法は提供されないので、自分で用意することになります。

必要なCSSRuleオブジェクトさえ見つければ、後は特定のタグのスタイルを変更する場合と、大差有りません。但し、直接スタイルを変更できるのは、typeSTYLE_RULEFONT_FACE_RULEPAGE_RULECSSRuleだけである点に注意が必要です。

また、同じセレクタを複数回定義している様な(カスケードしている)場合、当然同じセレクタ名称が複数見つかる事にも、注意する必要が有るでしょう。

下の例は、指定されたセレクタ名称のCSSRuleオブジェクトを返す関数です。

@importでインポートされたスタイルシート等にも対応させるために、CSSRuleselectorTextを判定する前に、CSSRule.typeCSSRule.STYLE_RULECSSRule.PAGE_RULEである事をチェックしています。それ以外のタイプのCSSRuleには、selectorTextが存在しません。

上の関数を使って、日英を切替えるサンプルを作ってみました。「翻訳」ボタンを押すと、日英が切り替わります。

実際のコードはこのページのソースを参照してください。

これは、ペンです。

This is a pen.

私の名前はマイクです。

My name is Mike.

『DOMによる...』というタイトルについて

このコンテンツの初版を作成していた2003年頃は、XMLもHTMLもCSSもEventもサーバとの送受信も、全てDocument Object Model (DOM)という形で、仕様が策定されていたので、『DOMによる...』というタイトルとしました(これからはDOMの時代だ!と思ってた頃です)。

しかし、(たぶん)XHTMLあたりからW3Cへの風当たりが怪しくなり、いつの間にか、そのあたりで策定されていた仕様は、宙ぶらりんのまま消えてしまいました。

とは言うものの、『DOMによる...』に代わる良いタイトルが思い浮かばないので、このまま行くことにしました。

何か思い浮かんだら、変えるかもしれません。