なるべくDOM標準に沿うようにCSS切替スクリプトを書いてみる試み。
いちゆうさんのスタイルシート切り替えスクリプトを元にしています。
付随的な特徴:
/*
csskks.js
Author: KITAMURA Akatsuki <kits@akatuskinishisu.net>
Version: 2005-04-16
*/
if (document.getElementsByTagName) {
/* ======================= 設定 ======================= */
/* 選択フォームのラベル */
var label = 'style: ';
/* スタイルを適用しない時の選択肢名 */
var nostyle = 'no style';
/* 選択フォームを含むdiv要素のclass名 */
var selectformclass = 'selectstylesheet';
/* 選択フォームのselect要素のid名 */
var selectelementid = 'styleselectelement';
/* cookieの名前 */
var cname = 'STYLESHEET';
/* cookieを設定するサイトのパス */
var cpath="/";
/* cookieの有効日数 */
var cdays = 10;
/* ==================================================== */
/* 初期化 */
/* グローバル変数の設定 */
var di = document.implementation;
var sss = getStyleSheets();
var isOpera = window.opera && navigator.userAgent.match(new RegExp('Opera[/ ]7'));
var isMacIE = !isOpera && navigator.userAgent.match(new RegExp('MSIE 5.+Mac'));
/* ページ遷移時にもcookieを保存 */
/* (MozillaのUIでスタイルを切り替えた場合のため) */
if (!isOpera) addEvent(window, 'unload', setCookie);
/* 以降はページ読み込み完了時に実行 */
addEvent((isOpera ? document : window), 'load', initialize);
}
/* 初期化(ページ読み込み完了後) */
function initialize() {
/* スタイル適用 */
setStyle();
/* 選択フォームを追加 */
appendSelectForm();
}
/* cookieに保存された名前のスタイルを適用する */
function setStyle() {
/* cookieからスタイル名を取得 */
var stitle = getCookie();
if (!stitle) return;
/* スタイルの変更 */
applyStyle(stitle);
}
/* 選択フォームを追加 */
function appendSelectForm() {
/* スタイル名のリストを取得 */
var stitles = new Array();
for (var i = 0; i < sss.length; i++) {
if (!sss[i].title || isStyleElement(sss[i])) continue;
/* 既に同じスタイル名がある場合は除く */
var isSameTitle = false;
for (var j = 0; j < i; j++) {
if (sss[j].title == sss[i].title) {
isSameTitle = true;
break;
}
}
if (!isSameTitle) {
stitles[stitles.length] = sss[i].title;
}
}
stitles[stitles.length] = nostyle;
/* 選択フォームを生成 */
ndiv = makeSelectForm(stitles);
/* 選択フォームを本文に追加 */
var nbody = document.getElementsByTagName('body')[0];
nbody.insertBefore(ndiv, nbody.firstChild);
/* 選択フォームの状態を変更 */
var currentStyleTitle = getStyleTitle() || nostyle;
var nsel = document.getElementById(selectelementid);
for (i = 0; i < stitles.length; i++) {
if (currentStyleTitle == stitles[i]) {
nsel.selectedIndex = i;
break;
}
}
/* 選択フォームにスタイルを設定 */
selectFormStyle(ndiv);
/* 選択フォーム変更時イベントを設定 */
addEvent(nsel, 'change', changeSelectForm);
}
/* 選択フォームを含むdiv要素を生成 */
function makeSelectForm(stitles) {
var ndiv = createHTMLElement('div');
ndiv.className = selectformclass;
if (isMacIE) {
var divHTML = '<label>' + label;
divHTML += '<select id="' + selectelementid + '">';
for (var i = 0; i < stitles.length; i++) {
divHTML += '<option>' + stitles[i] + '</option>';
}
divHTML += '</select></label>';
ndiv.innerHTML = divHTML;
} else {
var nsel = createHTMLElement('select');
nsel.id = selectelementid;
var nlabel = createHTMLElement('label');
ndiv.appendChild(nlabel);
nlabel.appendChild(document.createTextNode(label));
nlabel.appendChild(nsel);
for (i = 0; i < stitles.length; i++) {
var nopt = createHTMLElement('option');
nopt.appendChild(document.createTextNode(stitles[i]));
nsel.appendChild(nopt);
}
}
return ndiv;
}
/* フォームで選択された名前のスタイルを適用する */
function changeSelectForm() {
var nsel = document.getElementById(selectelementid);
var stitle = nsel.options[nsel.selectedIndex].text;
/* Mozillaだったら nsel.value でもOK */
applyStyle(stitle);
}
/* スタイルの適用 */
function applyStyle(stitle) {
for (var i = 0; i < sss.length; i++) {
sss[i].disabled = (sss[i].title == stitle || !sss[i].title || isStyleElement(sss[i])) ? false : true;
stitle == nostyle && (sss[i].disabled = true);
}
setCookie();
}
/* スタイル名をcookieへ保存 */
function setCookie() {
/* 現在適用されているスタイルの名前を取得 */
var stitle = getStyleTitle() || nostyle;
var c = cname + '=' + escape(stitle) + ';' + 'path=' + cpath;
/* 有効日数が設定されていれば追加 */
if (cdays) {
var cexp = new Date();
cexp.setTime(cexp.getTime() + 1000*60*60*24*cdays);
c += ';expires=' + cexp.toGMTString();
}
document.cookie = c;
}
/* cookieからスタイル名を取得 */
function getCookie() {
var c = document.cookie + ';';
var cindex = c.indexOf(cname + '=');
if (cindex == -1) return false;
var clen = c.indexOf(';', cindex + cname.length + 1);
return unescape(c.substring(cindex + cname.length + 1, clen));
}
/* イベントを追加する */
function addEvent(obj, eventType, func) {
if (di && di.hasFeature('HTMLEvents', '2.0')) {
/* DOM2 HTMLEvents対応 */
obj.addEventListener(eventType, func, false);
} else if (obj.attachEvent) {
/* WinIE5-6用 */
obj.attachEvent('on' + eventType, func);
} else {
/* MacIE5用 */
obj['on' + eventType] = func;
}
}
/* StyleSheetオブジェクトがstyle要素かどうかを判定 */
function isStyleElement(ss) {
if (di && di.hasFeature('StyleSheets', '2.0')) {
/* DOM2 Style Sheetss対応 */
var ssnode = ss.ownerNode;
/* xml-stylesheet処理命令の時 */
if (ssnode.nodeType == 7) return false;
/* style要素の時 */
if (ssnode.nodeType == 1 && ssnode.localName.toLowerCase() == 'style') return true;
/* それ以外 */
return false;
} else {
/* WinIE5-6はStyleSheets.ownerNodeが使えないので */
/* href属性の有無で判定 */
return (ss.href ? false : true);
}
}
/* HTML要素を作成する */
function createHTMLElement(tagname) {
if ( (di && di.hasFeature('Core', '2.0')) || isOpera) {
/* DOM2 Core対応 or Opera */
return document.createElementNS('http://www.w3.org/1999/xhtml', tagname);
} else {
/* IE5-6用 */
return document.createElement(tagname);
}
}
/* 現在適用されているスタイルの名前を取得 */
function getStyleTitle() {
for (var i = 0; i < sss.length; i++) {
if (isStyleElement(sss[i])) continue;
if (sss[i].title && !sss[i].disabled) return sss[i].title;
}
return false;
}
/* 選択フォームのスタイル設定 */
/* (スタイル無しの場合にも選択フォームの位置を保つため) */
function selectFormStyle(element) {
element.style.position = 'absolute';
element.style.top = '10px';
element.style.right = '10px';
element.style.zIndex = '100';
}
/* スタイルシートリストを取得 */
function getStyleSheets() {
if (
document.styleSheets &&
document.styleSheets[0] &&
document.styleSheets[0].title != null
) {
return document.styleSheets;
}
var slinks = new Array();
var links = document.getElementsByTagName('link');
for (var i = 0; i < links.length; i++) {
if (
links[i].rel &&
links[i].rel.toLowerCase().indexOf('stylesheet') != -1 &&
links[i].title
) {
slinks[slinks.length] = links[i];
}
}
return slinks;
}
<!-- HTMLの場合 -->
<link rel="stylesheet" type="text/css"
title="Style A" href="styleA.css">
<link rel="alternate stylesheet" type="text/css"
title="Style B" href="styleB.css">
<script type="text/javascript"
src="csskks.js" charset="Shift_JIS"></script>
<!-- XHTMLの場合 -->
<link rel="stylesheet" type="text/css"
title="Style A" href="styleA.css" />
<link rel="alternate stylesheet" type="text/css"
title="Style B" href="styleB.css" />
<script type="text/javascript"
src="csskks.js" charset="Shift_JIS"></script>
生成される選択フォームは以下のような物になります(見易さのため空白と改行を入れていますが、実際にはタグ間の空白・改行は挿入されません)。
<div class="selectstylesheet">
<label>style:
<select id="styleselectelement">
<option>Style A</option>
<option>Style B</option>
<option>no style</option>
</select>
</label>
</div>
本スクリプトは(取り敢えず)BSDライセンスに従うものとします。
よろしければ追加していって下さいませ。
参考にもさせて頂いています(感謝)。