Javascriptで思った通りのプログラミングができるようになってきた、ユゲタです。
でも、細かな操作は、過去に自分で書いたプログラムのコピペで行うことも多いんですが、
これが非常に効率が良く、仕事などであれば、想定工数の半分以下でできてしまうという場合も、
ここ最近多いわけです。
とにかく経験値の多いプログラムは、悩みどころがどんどん減るという理屈なんでしょうね。
自社ASPサービスの構築
そして、今回自社商品のASPサービスを開発してみようと思い、プログラムを書いていたんですが、
効率のいいCSSのセットをしようと思ったところ、
デフォルトで読み込んでいるCSSファイルのスタイルシートデータを、javascriptで書き換えるというのが、
カスタマイズをする効率性が高いと思って、実際にやってみたところ、少しコツがいることがわかったので、その備忘録を残しておくことにした。
ちなみに、最近の個人的なASPモジュール(javascriptライブラリ)のセットは、
1. 基本Javascriptの読み込み
2. 関連モジュールの読み込み(cssや他のjsライブラリ)
3. onloadイベントを待って処理開始
この方法でほぼ全てのASP処理が実施できるので、このやりかたを追求しているのですが、もう少し効率のいい方法があれば、すぐに乗り換えるかもしれません。
cssデータの書き換え方法
まず簡単なサンプルを作ってみます。
<!DOCTYPE html>
<html>
<head>
<meta charset="utf-8">
<link class="test" rel="stylesheet" href="test.css" />
</head>
<body>
<div class="test"></div>
</body>
</html>
.test{
width:100px;
height:100px;
background-color:red;
}
これで、次のような赤い四角が表示されます。
ちょっと特殊にしているのは、変更したいスタイルシートのlinkタグにclass名を付けています。
これを、青色に変換するように、cssを書き換えてみます。
まず、htmlのheadタグ内に次のjsを読み込むタグを追加
<script src="test.js"></script>
(function(){
function MAIN(){
this.change_css();
}
MAIN.prototype.change_css = function(){
// 任意class名で、linkタグを取得
let ss = this.get_ss("test");
if(!ss){return;}
for(let i=0; i<ss.cssRules.length; i++){
let rule = ss.cssRules[i];
if(rule.selectorText !== ".test"){continue;}
rule.style.setProperty("background-color" , "blue" , "");
}
};
MAIN.prototype.get_ss = function(className){
const styleSheets = Array.from(document.styleSheets).filter((styleSheet) => !styleSheet.href || styleSheet.href.startsWith(window.location.origin));
for(let ss of styleSheets){
if(ss.ownerNode.className === className){
return ss;
}
}
return null;
};
switch(document.readyState){
case "complete" : new MAIN();break;
default : window.addEventListener("load" , (function(options){new MAIN()}).bind(this));break;
}
})();
少し長い感じがしますが、できる限り短く書くようにしてみました。
そして無事に青色が確認できました。
ちょびっと解説
Javascriptの中身を解説します。
まず、ボクのスタンダードなjavascriptの書き方ですが、
無名関数内で全ての処理を実行するようにしています。
これは、商用で使うときや、ライブラリ化する時に非常に有効な方法なので、
真似してもらった方がいいかもです。
switch(document.readyState){
case "complete" : new MAIN();break;
default : window.addEventListener("load" , (function(options){new MAIN()}).bind(this));break;
}
一番下にかかれている、この命令は、ページ読み込みが完了している場合と、読み込み完了していない場合で、MAIN関数の起動を変更するための記述で、
これもほぼお決まりの書き方にしています。
それを、MAINという関数を作って、全ての処理をMAIN関数のpropertyで処理すると、それぞれの関数どうしは、thisを使ってやり取りができるというjavascript特有のやり方で実装します。
ただし、イベントでの関数実行や、setTimeoutなどを使う場合は、.bind(this)を付けて、thisを継承していくのが、慣れないとしんどいかもしれませんが・・・
そして、
MAIN.prototype.get_ss = function(className){
const styleSheets = Array.from(document.styleSheets).filter((styleSheet) => !styleSheet.href || styleSheet.href.startsWith(window.location.origin));
for(let ss of styleSheets){
if(ss.ownerNode.className === className){
return ss;
}
}
return null;
};
この"get_ss"という関数で、class名を付けたlinkタグを選択しているのですが、ブラウザ対応のための書き方をしていて、
比較的安定した取得ができるので、ボクはこれをコピペして使っています。
for(let i=0; i<ss.cssRules.length; i++){
let rule = ss.cssRules[i];
if(rule.selectorText !== ".test"){continue;}
rule.style.setProperty("background-color" , "blue" , "");
}
最後に、取得したstylesheet情報をssに格納して、
その中のselectorをfor文でまわしています。
そして、selector部分の文字列を取得できる"selectorText"という値を判定して、
判定したselector内の情報に、通常のsetPeroperty方式でstyleのセットを行います。
複数の情報を切り替えたい場合は、selector、propertyのそれぞれの分岐を増やしてあげるだけでいいんですが、
今回はやりませんが、cssに入っていないselectorを追加したい場合は、
"insertRule"という命令で、行う必要がありますが、
これらの操作を簡単にできるスニペットを書いておくと便利かもしれませんね。
気が向いたら作っておきたいと思います。
あ、そうそう
マルチブラウザ対応したい場合、少しコードを書き直す必要があるので、
https://wiki.bit-hive.com/tomizoo/pg/Javascript%20cssRules
こちらのページに、詳しく書かれていて参考になります。
とりあえず、今回は、簡単にcssの内容を書き換える方法だけを残しておきました。
0 件のコメント:
コメントを投稿