動的スタイルシートの作成

category-icon

 こんばんは。だいぶ日も長くなってきましたね。

 さて、小生のブログで、「エクセルデータをHTMLテーブルに変換」というエントリーを書いて、そこでppBlog用に見栄えの良いTABLEを作成してくれるページLink を公開していました。早速、使って下さったユーザーの方から、ppBlogをリスト表示にしていると、テーブルのスタイルシートが有効になっていないとのご指摘がありました。確かに、リスト表示での個別スタイルシート指定はすっかり対応を忘れていました。

 というわけで、ppBlogでは記事毎にスタイルシートやJavaScriptを指定することが可能ですが、あまり知られていない気もするので簡単に使い方を書いておきます。スタイルシート(CSS)を指定したければ、記事のどこでも良いので、[style][/style]で囲った中の記述がCSSとして認識されます。記述はまんまCSSと同じです。具体例を挙げると以下のような感じ。

[style]
.article-content table { border-color: tomato; }
[/style]

とか。.article-contentは、記事内容要素に対するクラス名です。記事の個別表示のときは、記事ボックスはひとつしかないので問題ありませんが、複数の記事が表示されている場合、上の例だと、別の記事にテーブルが含まれていたら(クラス名が同じため)そこにも反映されてしまいます。なので、これを回避するには、指定したい記事の固有IDを利用すると良いです。ppBlogでは、すべての記事にUID1234567890のようなIDが割り振られます。

[style]
#UID1234567890 .article-content table {
  border-color: tomato; /* IDを利用して適応先の .article-content を絞り込む */
} 
[/style]

追記 2009/02/19 18:56:29 考えてみると、このUIDを付加する作業は、ppBlogの方で自動的にやるべきかなぁ。次バージョンではそうしようと思います。

 記事ごとのJavaScript指定も同じように、[script][/script]で囲った中に記述すればOKです。

[script]
alert("Bonjour, tout le monde!"); /* 普通にJavaScriptを記述 */
[/script]

 前置きが長くなりましたが、本題。最初に挙げたリンク先Link のソースを見れば分かりますが、動的にスタイル指定を適応させる処理を入れています。同じような処理は、ppBlogで使っているソースハイライト表示用のsyntax.jsLink でも使っていますが、ここでは、上記エクセルコピペのテーブル変換の部分を抜粋してみます。

var sheet = d.styleSheets && d.styleSheets[0]; /* 最初のスタイルシートを取得 */

var rulesCSS = { /* JSON形式で要素毎のスタイルを指定 */
  'table' : 'border: solid 1px gray; margin: 2em auto; border-collapse: collapse;',
  'table td' : 'border: solid 1px gray; padding: 2px; text-align: right;',
  'table th' : 'border: solid 1px gray; padding: 2px; text-align: center;',
  'thead tr th' : 'background: #eeffff;',
  'tbody tr th' : 'background: #ffeeee;'
};

for (var el in rulesCSS){
 if(sheet.addRule){ /* IE 向け */
  sheet.addRule(el, rulesCSS[el]);
 } else {  /* Firefox, Safari, Opera 向け */
  sheet.insertRule(el + '{' + rulesCSS[el] + '}', sheet.cssRules.length);
 }
}

 このように、予めJSON配列などに適応させたいCSSを記述している時は、こんな感じで動的に変更させることが出来るのですが、「普通のCSSの記述」つまり

<style type="text/css">
  table { border: solid 1px gray; margin: 2em auto; border-collapse: collapse; }
  table td { border: solid 1px gray; padding: 2px; text-align: right; }
  table th { border: solid 1px gray; padding: 2px; text-align: center; }
  thead tr th { background: #eeffff; }
  tbody tr th { background: #ffeeee; }
</style>

を、このまま適応させたいときもあると思います。ppBlogでは、リスト表示モードというのがあり、記事の読み込みにはAjaxを活用しています。この際に、最初の方で紹介した、記事ごとのCSS記述があると、まさにこんな感じで、テキストとしてCSSの記述も読み込みます。で、それを処理するのを忘れていました、という最初の話に戻るのですが、その辺の処理は以下のようにしてみました。lib.jsの256行目あたりからの部分ですが、IEとMozilla系で処理が違うので条件付きコンパイルを使っています。

if(!o("#css4list")){ /* ID#css4list を持つオブジェクトがなければ */
 oParts.create("style#css4list", null, o("head")); /* ID名css4listを持つSTYLE要素をHEAD要素の子要素として追加 */
 newCSS = o("#css4list").$; /* HTMLStyleElementオブジェクトの取得 */
 newCSS.type = "text/css";
} else newCSS = o("#css4list").$;
 /*@cc_on @*//*@if(1) newCSS.styeSheet.cssText = css[1]; @else@*/
 newCSS.textContent = ""; /* 前に適応させたCSSをクリア */
 newCSS.appendChild(d.createTextNode(css[1])); /* 新たにCSSを設定 */
/*@end@*/

 リストモードでは記事は常にひとつしか表示されないので、ひとつ動的スタイルシート用のHTMLStyleElementを用意しておけば十分です。IEとMozilla系では、そこから先の処理が違います。IEでは、スタイルシートオブジェクトから操作。

HTMLStyleElement.styleSheet.cssText = (先に挙げたような素のCSSテキスト);

 Mozilla系では、DOMオブジェクトとして操作。

HTMLStyleElement.appendChild(document.createTextNode(先に挙げたような素のCSSテキスト));

 複数行にわたるCSSテキストを一気に適応させたいときは、こんな感じでしょうか。

ちなみに、[object HTMLStyleElement]から[object CSSStyleSheet]にアクセス?する際もIEとMozilla系では違いますね。IE8では、だいぶ歩み寄りが見られたような気もするけど。

[object HTMLStyleElement].styleSheet = [object CSSStyleSheet] /* IE */
[object HTMLStyleElement].sheet = [object CSSStyleSheet] /* Mozilla */

なので上のスクリプトの例では、IEの処理部分は以下のように書いても同じです。

document.styleSheets[document.styleSheets.length - 1].cssText = css[1];

つまり

newCSS.styleSheet == document.styleSheets[document.styleSheets.length - 1];

まぁこんなとこですかねぇ。そろそろアップデートせねば。。


— posted by martin at 11:48 am   commentComment [12]  pingTrackBack [0]

T: Y: ALL: Online:
Created in 0.0058 sec.
prev
2009.2
next
1 2 3 4 5 6 7
8 9 10 11 12 13 14
15 16 17 18 19 20 21
22 23 24 25 26 27 28