カテゴリー
オライリーJavaScript

新しいスタイルシートの作成

完全に新しいスタイルシートを作成し、ドキュメントに追加することもできる。

example 16-6 新しいスタイルシートの作成

/*
*スタイルシートにドキュメントを追加し、指定したスタイルを挿入していく
*style引数には文字列またはオブジェクトを指定できる
*文字列の場合は、スタイルシートのテキストとみなす
*オブジェクトの場合は、各プロパティ名がセレクタとなり、プロパティの値が対応するスタイルになる
*/
function addStyles(styles) {
	var styleElt, styleSheet;
	if (document.createStyleSheet) {
		styleSheet = document.createStyleSheet();
	} else {
		var head = document.getElementsByTagName("head")[0];
		styleElt = document.createElement("style");
		head.appendChild(styleElt);

		//新しいスタイルシートは末尾に追加する
		styleSheet = document.styleSheets[document.styleSheets.length-1];
	}

	//styleをこのスタイルシートに挿入していく
	if (typeof style === "string") {
		//引数は、スタイルシートテキスト
		if (styleElt) styleElt.innerHTML = styles;
		else styleSheet.cssText = styles;
	} else {
		//引数は、挿入するルールを保持するオブジェクト
		var i = 0;
		for(selector in styles) {
			if (styleSheet.insertRule) {
				var rule = selector + "{" + styles[selector] + "}";
				styleSheet.insertRule(rule, i++);
			} else {
				styleSheet.addRule(selector, styles[selector], i++)
			}
		}
	}
}
カテゴリー
オライリーJavaScript

スタイルシートルールの取得、挿入、削除

CSSStyleSheetオブジェクトでは、スタイルシートを有効/無効にできるAPIだけでなく、
スタイルシートのスタイルルールを読み出したり、挿入したり、削除したりするためのAPIも定義されている。

document.styleSheets[]配列の要素は、CSSStyleSheetオブジェクトです。
このCSSStyleSheetオブジェクトのcssRules[]配列には、スタイルシートのルールが含まれている

var firstRule = document.styleSheets[0].cssRules[0];

IEは、cssRulesプロパティの代わりに、rulesという名前のプロパティを使う。
cssRule[]配列の要素も、rules[]配列の要素も、CSSRuleオブジェクト。
CSSRuleオブジェクトには、2つのプロパティがある。
selectorTextプロパティ
このルールのCSSセレクタが保持される

styleプロパティ
このセレクタに関連付けられたスタイルを表す、CSSStyleDeclarationオブジェクトの参照が格納される

insertRule()メソッド
deleteRule()メソッド

IEは、
addRule()
removeRule()

カテゴリー
オライリーJavaScript

スタイルシートの有効化と無効化

ここで紹介する方法は、最も単純な方法ですが、
最も可搬性があり、最も安全に使える方法。
style要素、link要素、CSSStyleSheetオブジェクトには、
disabledプロパティが定義されている。
このプロパティをJavaScriptから読み出したり設定したりする。
disabledプロパティをtrueにすると、style要素、link要素、スタイルシートは無効となり、
ブラウザから無視される。

function disableStylesheet(ss) {
    if(typeof ss === "bumber")
        document.stylesheets[ss].disabled = true;
    else {
        var sheets = document.querySelectorAll(ss);
        for(var i=0; i < sheets.length; i++)
            sheets[i].disabled = true;
    }
}
カテゴリー
オライリーJavaScript

スタイルシートの制御

スタイルシート自体をスクリプトから制御することもできる
スタイルシート自体をスクリプトから制御するときには、2種類のオブジェクトを操作する
Elementオブジェクト
CSSStyleSheetオブジェクト

カテゴリー
オライリーJavaScript

CSSクラスの制御

インラインのstyleプロパティを使って個々のCSSスタイルをスクリプトから制御する代わりに、
HTML要素のclassNameプロパティを使って、HTMLのclass属性の値をスクリプトから制御する方法もある
要素のclass属性が変われば、その要素に適用されるスタイルセレクタが変わり、
結果として、一度に複数のCSSスタイルを変更できる。

.attention {
     background-color: yellow;
     font-weight: bold;
     border: solid black 2px;
 }

classという識別子は、JavaScriptでは予約語
このため、HTMLのclass属性をJavaScriptから使うときは、classNameという名前を使う。

function grabAttention(e) { e.className = "attention" }
function releaseAttention(e) { e.className = "" }

HTML要素は、複数のCSSクラスに属することができる。
class属性には、空白で区切ってクラス名のリストを記述する。
上記の例は、classNameプロパティには、クラス名がないか1つしか指定しないものと想定している。
つまり、複数のクラスを指定しているときは、既存のクラスを上書きしてうまく動かない。

HTML5では、すべての要素にclassListプロパティを定義することで、問題に対処している。
classListプロパティの値は、DOMTokenList
DOMTokenListは、読み出し専用の配列のようなオブジェクト
このオブジェクトの要素として、個々のクラス名が格納される。

DOMTokenListで定義されているメソッド
add()メソッド、remove()メソッド
要素のクラス属性に対して、クラス名を追加したり削除したりできる

toggle()メソッド
指定したクラス名が存在していなければ追加し、存在していれば削除する

contains()メソッド
クラス属性に指定したクラス名が含まれているかどうかをテストする

DOMTokenListは生きた状態で表す。

example 16-5 classList(): classNameをCSSクラスのセットとして扱う

/*
*もしあれば、eのclassListプロパティを返す
*なければ、eに対するDOMTokenList APIをシミュレートするオブジェクトを返す
*返されたオブジェクトには、contains()、add()、remove()、toggle()、toString()メソッドがある
*これらのメソッドで、要素eのクラスのセットをテストしたり変更したりする
*classListプロパティがネイティブでサポートされていれば、返されたオブジェクトが、
*配列のようなオブジェクトになり、lengthをもし、配列のインデクスプロパティを持つ
*シミュレートされたDOMTokenListは、配列のようなオブジェクトではなく、
*toArray()メソッドを持つ
*このメソッドは、クラス名を要素として持つ本当の配列が返される
*/
function classList(e) {
	if (e.classList) return e.classList;	//存在すれば、e.classListを返す
	else return new CSSClassList(e);	//存在しなければ、シミュレートする
}

//CSSClassListは、DOMTokenListをシミュレートするJavaScriptクラス
function CSSClassList(e) { this.e = e }

//classNameにクラスcが含まれていれば、trueを返す。それ以外はfalseを返す
CSSClassList.prototype.contains = function(c) {
	//cが正当なクラス名かどうかをチェックする
	if (c.length === 0 || c.indexOf(" ") != -1) 
		throw new Error("Incalid class name: '" + c + "'");
	//まず、一般的な場合をチェックする
	var classes = this.e.className;
	if (!classes) return false;	//eにはクラスがない
	if (classes === c) return true;	//eが完全に一致するクラスを1つだけ持つ場合

	//上記以外の場合は、RegExpを使ってcを単語単位で検索する
	//正規表現中の\bは、単語境界にマッチする
	return classes.search("\\b" + c + "\\b") != -1;
};

//存在しなければ、cをe.classNameに追加する
CSSClassList.prototype.add = function(c) {
	if (this.contains(c)) return;	//すでに存在していれば、何もしない
	var classes = this.e.className;
	if (classes && classes[classes.length-1] != " ")
		c = " " + c;	//必要であれば、空白を追加する
	this.e.className += c;	//cをclassNameに追加する
};

//e.classNameからcをすべて削除する
CSSClassList.prototype.remove = function(c) {
	//cが正当なクラスかどうかを確認する
	if (c.length === 0 || c.indexOf(" ") != -1) 
		throw new Error("Incalid class name: '" + c + "'");
	//cを単語単位で削除する。末尾のスペースも削除する
	var pattern = new RegExp("\\b" + c + "\\b\\s*", "g");
	this.e.className = this.e.className.replace(pattern, "");
};

//すでに存在していなければ、cをe.classNameに追加して、trueを返す
//存在していれば、e.classNameからすべてのcを削除して、falseを返す
CSSClassList.prototype.toggle = function(c) {
	if (this.contains(c)) {	//e.classNameにcが含まれていれば
		this.remove(c);	//削除する
		return false;
	} else {	//含まれていなければ
		this.add(c);	//追加する
		return true;
	}
};

//e.className自身を返す
CSSClassList.prototype.toString = function() { return this.e.className; };

//e.className中の名前を返す
CSSClassList.prototype.toArray = function() {
	return this.e.className.match(/\b\w+\b/g) || [];
};
カテゴリー
オライリーJavaScript

算出スタイルの取得

ある要素のstyleプロパティは、要素のインラインスタイルです。
インラインスタイルは、スタイルシートをすべて上書きする。

CSSプロパティを設定して、要素の見た目を変更したいのであれば、styleプロパティを操作するのがよい。
しかし、実際にある要素の適用されているスタイルを取得したい場合には、styleプロパティは役にたたないのが普通。
実際にある要素に適用されているスタイルを取得したい場合
算出スタイルが必要

ある要素の算出スタイルは、インラインスタイルの他に、リンクされたすべてのスタイルシート中の
適用可能なスタイルルールから、ブラウザが引き出した(算出した)プロパティ値のセットです。
このプロパティ値のセットが、要素を表示するときに実際に使われる。

インラインスタイルと同じように、算出スタイルはCSSStyleDeclarationオブジェクトを使って表せれる。
しかし、インラインスタイルとは異なり、算出スタイルは読み出し専用。

ある要素の算出スタイルを取得するには、
WindowsオブジェクトのgetComputedStyle()メソッドを使う。
getComputedStyle()メソッドの戻り値は、指定した要素に適用されるすべてのスタイルを表す
CSSStyleDeclarationオブジェクトです。

var title = document.getElementById("sectiontitle");
var titlestyles = window.getComputedStyle(element, null);

最初の引数
算出スタイルを取得したい要素を指定する

2番目の引数
null、空文字を指定する。
":before"、":after"、":first^line"、":first-letter" などのCSS疑似要素を表す文字列も指定できる

example 16-4 算出スタイルを取得し、インラインスタイルに設定する

//要素eのテキストサイズを、指定した米率で拡大縮小する
function scale(e, factor) {
	//算出スタイルを使って、テキストの現在のサイズを取得する
	var size = parseInt(window.getComputedStyle(e, "").fontSize);
	//そして、インラインスタイルに拡大縮小したいサイズを設定する
	e.style.fontSize = factor * size + "px";
}

//要素eの背景色を指定した量だけ変更する
//factor > 1の場合は色を明るくし、factor < 1の場合は色を黒くする
function scaleColor(e, factor) {
	var color = window.getComputedStyle(e, "").backgroundColor;	//取得する
	var components = color.match(/[\d\.]+/g);	//RGBの各要素を解釈する
	for (var i = 0; i < 3; i++) {	//RGBの各値をループする
		var x = Number(components[i] * factor;	//倍率を掛ける
			x = Math.round(Math.min(Math.max(x, 0), 255));	//値を範囲の丸める
			components[i] = String(x);
	}
	if (components.length == 3) {	//rgb()色
		e.style.backgroundColor = "rgb(" + components.join() + ")";
	} else {	//rgba()色
		e.style.backgroundColor = "rgba(" + components.join() + ")";
	}
}
カテゴリー
オライリーJavaScript

CSSアニメーション

example 16-3 CSSアニメーション

//要素eを相対位置指定に変換し、左右に「シェイク」する
//最初の引数には、要素オブジェクトまた要素のidを指定する
//2版値の引数に関数を渡した場合は、アニメーションが完了するまで
//eを引数にして、その関数を呼び出す
//3番目の引数で、どのくらいeをシェイクするかを指定する。デフォルトは5ピクセル
//4番目の引数で、シェイクする時間を指定する。デフォルトは500ミリ秒
function shake(e, oncomplete, distance, time) {
	//引数を処理する
	if (typeof e ==="string") e = document.getElementById(e);
	if (!time) time = 500;
	if (!distance) distance = 5;

	var originalStyle = e.style.cssText;	//eの元のスタイルを保存する
	e.style.position = "relative";	//eを相対位置指定要素にする
	var start = (new Date()).getTimer();	//アニメーション開始時刻を記憶する
	animate();	//アニメーションを開始する

	//この関数は経過時間をチェックし、eの位置を更新する
	//アニメーションが完了したら、eを元の状態に戻す
	//まだ完了していない場合は、eの位置を更新し、再実行をスケジュールする
	function animate() {
		var now = (new Date()).getTime();	//現在時刻を取得する
		var elapsed = now - start;	//開始からの経過時間
		var fraction = elapsed / time;	//全体のなん%か?

		if (fraction < 1) {		//アニメーションがまだ完了していないならば
			//アニメーションの完了率をパラメータとする関数を使って、
			//eのx座標を計算する。ここでは、正弦関数を使っている
			//4πに完了率を掛けて、左右に2回シェイクする
			var x = distance * Math.sin(fraction*4*Math.PI);
			e.style.left = x + "px";

			//25ミリ秒後または完了時時刻に再実行する
			//なめらかに動くように、毎秒40フレームでアニメーションを動かす
			setTimeout(animate, Math.min(25, time-elapsed));
		} else {	//アニメーションが完了している
			e.style.cssText = originalStyle;	//元のスタイルに戻す
			if (oncomplete) oncomplete(e);	//完了通知用コールバックを呼び出す
		}
	}
}

//完全に不透明な状態から、timeミリ秒後に完全な透明状態にする
//この関数が呼び出されたとき、eは完全に不透明と想定
//oncomplete(省略可能)に関数を指定した場合は、
//アニメーションが完了したときに、eを引数に、この関数が呼び出される
//time省略時は500ミリ秒となる
//この関数はIEでは動作しない。
//ただし、opacity以外にIEの非標準のfilterプロパティを
//変更するようにすれば、IEでも動作する
function fadeOut(e, oncomplete, time) {
	if (typeof e === "string") e = document.getElementById(e);
	if (!time) time = 500;

	//Math.sqrtを単純な「イメージング関数」として使うことで、
	//アニメーションを少し非線形にする
	//つまり、最初は透明になる速度が速く、だんだん遅くなる
	var ease = Math.sqrt;

	var start = (new Date()).getTime();	//アニメーションの開始時刻を記録
	animate();	//アニメーションを開始

	function animate() {
		var elapsed = (new Date()).getTime() - start;	//経過時刻
		var fraction = elapsed / time;	//完了率
		if (fraction < 1) {		//アニメーションが完了していない場合
			var opacity = 1 - ease(fraction);	//要素の不透明度を計算する
			e.style.opacity = String(opacity);	//eに設定する
			setTimeout(animate, Math.min(25, time-elapsed));	//次のフレームをスケジュールする
		} else {	//アニメーションが完了している
			e.style.opacity = "0";	//完全に透明にする
			if (oncomplete) oncomplete(e);	//完了時にコールバックを呼び出す
		}
	}
}

setTimeout()メソッド、setInterval()メソッド
と組み合わせて、アニメーションを実現できる

jQueryなどのクライアントサイドライブラリでは、あらかじめ視覚効果が定義されているのが普通
複雑な視覚効果を作りたいのでないなら、アニメーション関数を書く必要はない
視覚効果ライブラリ
Scriptaculous
http://script.aculo.us/
http://scripty2.com/

CSS3 Transitionsモジュール
スタイルシート中でアニメーションを指定する方法を定義している
スクリプト処理はまったく必要ない
次のようなCSSを書くだけ

.fadeable { transition: opacity .5s ease-in }

「fadeable」要素の半透明度が変化するときには、0.5秒間で、アニメーションを使って
現在の値から新しい値に変化する。

カテゴリー
オライリーJavaScript

インラインスタイルの制御

CSSを制御する方法の中で最も直感的な方法は、個々のドキュメント要素のstyle属性を変更する
style属性はElementオブジェクトのプロパティでJavaScriptから制御できる

styleプロパティの値は、CSSStyleDeclarationオブジェクト
CSSStyleDeclarationオブジェクトのスタイルプロパティを操作する場合、すべての値は文字列形式で指定する

e.style.fontSize = "24pt";
e.style.fontWeight = "bold";
e.style.color = "blue";

JavaScriptでのCSS属性の命名規則
CSSでハイフンを含むプロパティ名(ケバブケース)は、JavaScriptではエラーとなる。

    e.style.font-size = "24pt";     //構文エラー

キャメルケースに変換する
    font-family -> fontFamily
    border-left-width -> borderLeftWidth

CSSプロパティ名がJavaScriptの予約語の場合は、「css」という接頭語をつける

float -> cssFloat

HTML要素のstyle属性は、その要素のインラインスタイルになる
インラインスタイルは、スタイルシート中で指定されたスタイルを上書きする。

getAttribute()メソッド
setAttribute()メソッド
CSSStyleDeclarationオブジェクトのcssTextプロパティ
も使える

カテゴリー
オライリーJavaScript

例:半透明のウィンドウを重ね合わせる

example 16-2 CSSを使ってウィンドウを表示する


<!DOCTYPE html>
<html lang="ja">
<head>
	<meta charset="UTF-8">
	<title>O'REILLY JavaScript Sample</title>
	<style type="text/css">
	/*
	* 次のCSSスタイルシートは「ウィンドウ」視覚効果を作るために、
	* ドキュメントのボディ中で使用する3つのスタイルルールを定義する
	* このルールでは、位置指定プロパティを使って、ウィンドウ全体のサイズを設定し、
	* その構成要素の位置を指定する。
	* ウィンドウのサイズを変更する場合は、
	* 以下の3つのルールの位置指定プロパティも変更する必要がある
	*/
	div.window {
		position: absolute;
		width: 300px; height: 200px;
		border: 3px outset gray;
	}
	
	div.titlebar {
		position: absolute;
		top: 0px; height: 18px;
		width: 290px;
		background-color: #aaa;
		border-bottom: groove gray 2px;
		padding: 3px 5px 2px 5px;
		font: bold 11pt sans-serif;
	}
	
	div.content {
		position: absolute;
		top: 25px;
		height: 165px;
		width: 290px;
		padding: 5px;
		overflow: auto;
		background-color: #fff;
	}
	
	div.translucent {
		opacity: .75;
		-moz-opacity: .75;
		filter: alpha(opacity=75);
	}
	</style>
</head>
<body>
<h1>example 16-2 CSSを使ってウィンドウを表示する</h1>
<!-- ウィンドウを定義するにた次のようにする -->
<!-- "window" div中に、"title div"と"content" divを入れ子にする -->
<!-- 注意: style属性を使って、スタイルシートのスタイルに対して、位置指定を追加している -->
<div class="window" style="left: 10px; top: 10px; z-index: 10;">
	<div class="titlebar">Test Window</div>
	<div class="content">
	1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />0<br />
	1<br />2<br />3<br />4<br />5<br />6<br />7<br />8<br />9<br />0<br />
	</div>
</div>

<!-- 場所と色とフォントの重さを変えて、別のウィンドウを作成する -->
<div class="window" style="left: 75px; top: 110px; z-index: 20;">
	<div class="titlebar">Another Window</div>
	<div class="content translucent" style="backgroung-color:#ccc; font-wight: bold;">
	This is another window. Its<tt>z-index</tt>puts it on top of the other one.
	CSS styles make its content area translucent in browsers that support that.
	</div>
</div>

</body>
</html>
カテゴリー
オライリーJavaScript

overflowとclip

overflowとclipプロパティを使えば、要素の一部だけを表示できる。

overflowプロパティに指定可能な値
visible
コンテンツがはみ出した場合、要素のボックスの外側に描画する。
デフォルト値

hidden
はみ出した要素は、サイズや位置指定で定義された領域の外側には何もコンテンツを表示しない

scroll
要素のボックス中に水平、垂直スクロールバーが常に表示される
コンテンツがボックスサイズをはみ出した場合、ユーザはスクロールバーを使って、
コンテンツをスクロールして見ることができる。

auto
常にスクロールバーを表示するのではなく、コンテンツが要素のサイズをはみ出した場合にのみ
スクロールバーを表示する

clipプロパティでは、要素がはみ出したかどうかにかかわらず、要素のどの部分を表示するのかを
正確に指定できる。

clipプロパティの書式
rect(top right bottom left)

style="clip: rect(0px 100px 100px 0px);"

%は利用できない
カンマで区切らない