七転び八起きブログ

JavaScriptで読み込むCSSファイルをまるっと動的に入れ替えるには

2007年01月26日   :: JavaScript

今勤めている会社のサービス関連で、あったら便利だなーと思って、半年ほど前に作ったツールがありまして。

ツールって言っても、ラジオボタンをポチポチと選んでいくと動的にそのページで読み込んでいるCSSファイルが変わるっていういだけの単純なシロモノです。

要は
  :大きい文字サイズ    :標準の文字サイズ
みたいなものを細かく組み合わせた奴です。

要はサイトのテンプレートをお客さんに選んでもらう時に、掛け算すると100種類以上になるテンプレートの中から(100種類以上のCSSがあるわけじゃなくて、CSSの組み合わせで100種類以上になる)、サムネイルだけで一つ選んでもらうのは、なかなかしんどいかなと思ったので作ったプレビューツールです。

JavaScriptでちょこちょこと作っていたら、仕組みとしてはなんとかなったのですが、どうもブラウザで問題が。

最初はこのへんのコレクションを使ってやってました。

 document.all.tags('LINK')
 document.getElementsByTagName('LINK')

このhrefプロパティを変えて、やってたわけです。だけどこれが大体お客さんの10%くらいが落ちて使えなかったそうです。
FirefoxとかOperaは問題ないのですが、とにかくIEがダメ。うちのお客さんはほとんどIEなのでこれはマズイ。


一度

 document.getElementsByTagName('LINK').item(i).href = "" ;
 document.getElementsByTagName('LINK').item(i).href = "xxx.css"

っていう風に一旦空にしてから新しいCSSを読み込ませるようにしたら結構良くなったのですが、それでもまだ落ちまして。もうちょっとなんとかしたいな、と思いつつ忙しさにかまけてそのままにしていました。

で、最近そのJavaScriptを別のシステムに組み込まないといけなくなったのでブラッシュアップすることに。それでなんとなく、link要素じゃなくて、document.styleSheets経由でやったらどうかなと思ってやってみた。

 document.styleSheets[n].href = "xxx.css"

そしたら、ビンゴでした。全然落ちなくなりました。なぜ?

しかも、こいつのhref属性ってReadOnlyなんです。でもなぜかIEでは書き込めてしまう。IE7でも書き込めてしまった。なぜ。

仕様書見ると

// Introduced in DOM Level 2:
interface StyleSheet {
  readonly attribute DOMString type;
     attribute boolean disabled;
  readonly attribute Node ownerNode;
  readonly attribute StyleSheet parentStyleSheet;
  readonly attribute DOMString href;
  readonly attribute DOMString title;
  readonly attribute MediaList media;
};

http://www.w3.org/TR/DOM-Level-2-Style/stylesheets.html#StyleSheets-StyleSheet

…やっぱり readonly 。Firefoxだとこれは動かないので、Firefoxが正しい挙動ですね。

そもそも元々のdocument.getElementsByTagNameを使うやり方でFirefoxとかは落ちなかったので、ブラウザを振り分けてIEだけdocument.styleSheetsを使うことで、結果的には満足いく感じになったのですが、なんか後味が…。

JavaScriptは難しいですなぁ…。あ、FireBugって本当に便利ですね。びっくり。もっと早く使えばよかった…。

■Firebug | Firefox Add-ons | Mozilla Corporation
  https://addons.mozilla.org/firefox/1843/


ちなみにこんなソースでやってました。振り分け部分は省略。
ラジオボタンのonChangeイベントをきっかけにぐるぐる回してました。the力技。

function changeCSS(cssColorName,cssMainName){
  var targetObj = document.getElementsByTagName('LINK') ;
   targetObj.item(1).href = "" ;
  targetObj.item(1).href = cssColorName ;
  targetObj.item(0).href = "" ;
   targetObj.item(0).href = cssMainName ;
}

function changeCSS(cssColorName,cssMainName){
   if( document.styleSheets ){
     var css_list = document.styleSheets ;
     css_list[0].href = cssMainName ;
     css_list[1].href = cssColorName ;
   }
}

■トラックバック

このエントリーのトラックバックURL:
http://www.7korobi8oki.com/mt/mt-tb.cgi/100

■コメントはこちらから

mail TOP