﻿/*

		Preferred Style Generator (PSG)
		version 3.3.3.20050706 (スタイル選択機能のみ)
		Written by TYLIGHT
		
		この JavaScript は修正 BSD ライセンスで配布します。

*/

function disableWarning(){
	return true;
}
window.onerror = disableWarning;

var PSG = {
	/*----------------- 設定ここから -----------------*/
	Config : {
		Cookie : {
			// クッキーが有効なドメイン名を指定します。空だとURLから自動的に取得します (文字列)
			// 例: "homepage2.gifty.com"
			domain : "cineforbidden.hp.infoseek.co.jp",
			
			// "/" から始まるクッキーが有効なパスを指定します。空だとURLから自動的に取得します (文字列)
			// 例: "/oreore/"
			path : "/novel_cine/aide/"
		},
		StyleSheet : {
			// どの ID を持つ要素にセレクトボックスを配置するか (文字列)
			// 空だと、次の要素名の設定を使って配置します
			targetElementID : "css_select",
			
			// どの要素にセレクトボックスを配置するか (文字列)
			// 上の設定で ID を指定した場合は無視されます
			targetElementName : "body",
			
			// その要素の何番目に挿入するか。0 ではなく 1 から数えます。(数値)
			// 上の設定で ID を指定した場合は無視されます
			targetElementIndex : 1,
			
			// 選択リストの直前に挿入する文字列。空でもいい (文字列)
			text : "style sheet theme ",
			
			// 上で設定した要素の前に挿入するなら true, 後ろに追加するなら false
			isBefore : true,
			
			// 上で指定した要素の外に追加するなら true
			// 要素の中に追加するなら false
			// body 要素や html 要素を挿入対象にする場合は false にしてください。
			isOut : false,
			
			// 設定スタイルの保持日数(一度でも再来訪すればまた数え直します) (数値)
			// 0 を指定するとブラウザ終了まで有効。
			expdays : 30,
						
			// 優先/代替 CSS 全て適用しない状態を選択リストに含めるなら true, 含めないなら false
			enableNoStyle : false,
			
			// 優先/代替 CSS 一切適用無しの名前 (文字列)
			noStyleName : "なし"
		}
	},
	/*----------------- 設定ここまで -----------------*/






	/**
	* @access public
	* @return boolean 了承されたかどうか
	* その動作を本当にしてよいのか聞く。
	*/
	really : function(){
		return confirm("OK ?");
	},




	Arrays : {
		/**
		* @access public
		* @param mixed[] 検索対象配列
		* @param value mixed 検索するオブジェクト
		* @return boolean 対象配列に既にオブジェクトが存在していれば true, そうでなければ false
		* 配列の値の重複チェックなどに使用。
		* hasKey も作るかもしれないので has でなく hasValue という名前。
		*/
		hasValue : function( array, value ){
			for(var i in array){
				if(array[i] == value){
					return true;
				}
			}
			return false;
		}
	},



	DOM : {
		namespace : {
			xhtml1 : "http://www.w3.org/1999/xhtml",
			xhtml2 : "http://www.w3.org/2002/06/xhtml2/"
		},
		
		/**
		* @access public
		* @return object(HTMLHtmlElement) ページ内のルート要素 or null
		*/
		getRootElement : function(){
			/* document.all(0) が要素とは限らない為 document.all 非使用 [Feedback 2004-12-19] */
			if(document.documentElement){
				return document.documentElement;
			} else if (document.getElementsByTagName){
				return document.getElementsByTagName("*")[0];
			} else {
				return null;
			}
		},
		
		/**
		* @access public
		* @return boolean 最低限の DOM が扱えるかどうか
		*/
		canDOM : function(){
			var D = document;
			var E = PSG.DOM.getRootElement();
			if( E == null ) return false;
			return new Boolean(
				D.getElementById &&
				D.getElementsByTagName &&
				D.createElement &&
				D.createTextNode &&
				E.getAttribute &&
				E.setAttribute &&
				E.removeAttribute &&
				E.appendChild &&
				E.removeChild &&
				E.insertBefore
			);
		},
		
		/**
		* @access public
		* @return boolean 文書が XHTML かどうか
		*/
		isXHTML : function(){
			if( PSG.DOM.canDOM() == false ) return false;
			
			var root = PSG.DOM.getRootElement();
			/*
			XHTML/1.1 はルート要素に xmlns 属性が定義されなければならない
			HTML なら namespaceURI は null
			Opera7 は getAttribute では xmlns 属性が取得できない (getAttributeNode なら Object が返る)
			WinIE6 は namespaceURI プロパティが存在しない
			*/
			return new Boolean( root.getAttribute("xmlns") || root.namespaceURI );
		},
		
		/**
		* @access public
		* @param tagName String 生成する要素名
		* @return object(HTML*Element) 生成された要素
		* XHTML / HTML のどちらであるかを自動的に判断して指定要素を生成します。
		* XHTML の場合に生成される要素の名前空間は XHTML/1.x 共通のものです。
		*/
		createElement : function( elementName ){
			elementName = elementName.toLowerCase();
			return PSG.DOM.isXHTML() && document.createElementNS ? document.createElementNS(PSG.DOM.namespace.xhtml1, elementName) : document.createElement(elementName);
		},
		
		/**
		* @access public
		* @param newNode object(DOMNode) refNode に追加するノード
		* @param refNode object(DOMNode) ノードが追加されるノード
		* @return object|null 自動補完が加わったかもしれない newNode
		* 対象のノードが DL,UL,OL のいずれかであれば newNode に適切に要素を加えて返します。
		* 対象ノードが null か DOM が扱えなければ null を返します。
		*/
		addElementImpl : function( newNode, refNode ){
			if( PSG.DOM.canDOM() == false || !refNode ) return null;
			
			/* Feedback from ALIMIKA SATOMI 2004-12-19 */
			var regxp = new RegExp("^(HTML:)?(UL|OL|DL)$", "i"); // XHTML [Opera7] 対策
			if( regxp.test(refNode.nodeName) ){
				var parentElement;
				if(refNode.nodeName.toUpperCase().indexOf("DL") != -1 ){
					parentElement = PSG.DOM.createElement("dd");
				} else {
					parentElement = PSG.DOM.createElement("li");
				}
				if( newNode.id ){
					parentElement.id = newNode.id + "_PARENT";
				}
				parentElement.appendChild(newNode);
				return parentElement;
			} else {
				return newNode;
			}
		},
		
		/**
		* @access public
		* @param newElement object(DOMElementNode) 新しく追加する要素
		* @param targetElement object(DOMNode) 追加対象の要素
		* @param isBefore boolean 追加対象の要素の前に追加するのかどうか (後ろなら false)
		* @param isOut boolean 追加対象要素の外に追加するのかどうか (中なら false)
		* @return object(DOMElementNode) 追加した newElement
		*
		* 新しい要素を追加対象要素の前後どちらかに追加します。
		* 追加対象要素が UL/OL/DL のいずれかである場合は適切に要素を補充した後に
		* それを新しい要素として追加します。返り値はここで生成された新しい要素です。
		* UL/OL/DL ではなければそのまま追加し、返り値の要素も最初の新しい要素と変化しません。
		* DOM をサポートしていない場合は何もせずに null を返します。
		*/
		addElement : function( newElement, targetElement, isBefore, isOut ){
			if( PSG.DOM.canDOM() == false ) return null;
			
			if( isBefore ){
				if( isOut ){
					newElement = PSG.DOM.addElementImpl( newElement, targetElement.parentNode );
					targetElement.parentNode.insertBefore( newElement, targetElement );
				} else {
					newElement = PSG.DOM.addElementImpl( newElement, targetElement );
					targetElement.insertBefore( newElement, targetElement.firstChild );
				}
			} else {
				if( isOut ){
					newElement = PSG.DOM.addElementImpl( newElement, targetElement.parentNode );
					targetElement.parentNode.insertBefore( newElement, targetElement.nextSibling );
				} else {
					newElement = PSG.DOM.addElementImpl( newElement, targetElement );
					targetElement.appendChild( newElement );
				}
			}
			return newElement;
		}
	},



	Event : {
		/**
		* @access public
		* @param object object(DOMElementNode) イベントを登録する要素
		* @param event String イベント名
		* @param listener Function イベント発生時に自動実行する関数
		* @param useCapture boolean キャプチャするかどうからしい……
		* @return void
		*
		* イベントの登録を行う。
		*/
		addEvent : function( object, event, listener, useCapture ){
			if(object.addEventListener){
				object.addEventListener( event, listener, useCapture ? true : false ); // Standard DOM
			} else if(object.attachEvent){
				object.attachEvent( "on"+event, listener ); // For IE
			}
		},
		
		/*
		* @access public
		* @param listener Function ページ読み込み完了時に自動実行する関数
		* @return void
		*/
		addLoadEvent : function( listener ){
			PSG.Event.addEvent( window, "load", listener, false );
		}
	},



	Cookie : {
		/**
		* @access public
		* @param name String 取得するクッキーの名前
		* @return String|null クッキーが存在しなければ null、そうでなければクッキーの値
		*/
		getCookie : function(name){
			var start, end;
			var c = document.cookie;
			
			if(c.indexOf(name + '=') != -1){
				start = c.indexOf(name + '=');
				end = c.indexOf( ';', start + name.length+1 );
				if(end == -1){
					end = c.length;
				}
				var value = c.substring( start + name.length+1, end );
				return decodeURIComponent ? decodeURIComponent(value) : unescape(value) ;
			}
			return null;
		},
	
		/**
		* @access public
		* @param name String 設定するクッキーの名前
		* @param value String 設定する値
		* @param expdays int クッキー有効日数
		* @param domain String クッキーを有効にするドメイン
		* @param path String クッキーを有効にするパス
		* @return void
		*/
		setCookie : function(name,value,expdays,domain,path){
			if( value == null ) throw "Invalid Value";
			if( !expdays ) expdays = 0; // -1 だと Firefox/1.0 ではその場で削除されるようだ
			if( !domain ) domain = location.hostname; // 空設定等の場合の対処
			if( !path ) path = location.pathname.substring(0,location.pathname.lastIndexOf("/")+1 ); // 空設定等の場合の対処
			
			value = encodeURIComponent ? encodeURIComponent(value) : escape(value) ;
			
			var c = name + "=" + value;
			c += "; domain=" + domain;
			c += "; path=" + path;
			if(expdays != 0){
				var expires = new Date();
				expires.setTime(expires.getTime() + 1000*60*60*24*expdays);
				c += "; expires=" + expires.toGMTString();
			}
			document.cookie = c;
		}
	},



	StyleSheet : {
		selectID : "PSGSSSBOX", // セレクトボックスに付けるID。内部的にも使用するので重要
		formID : "PSGSSS", // PSG Style Sheet Selecter の略。フォーム要素の ID。CSS で制御しやすいように付けている
		
		/**
		* @access protected
		* @return object[](styleSheets[]|HTMLLinkElement[]) 優先/代替スタイルシートに関連している styleSheets オブジェクト(それが利用できなければ link 要素)の配列
		*
		* styleSheets オブジェクトから title があるものだけを返します。
		* styleSheets オブジェクトが利用できない場合は代わりに link 要素から取得します。
		* 返り値に永続スタイルシートは含みません。
		* link 要素での取得の場合に DOM がサポートされていなければ空配列を返します。
		*/
		getStyleSheets : function(){
			var i;
			var sheets = new Array();
			if( document.styleSheets ){
				var csses = document.styleSheets;
				for(i=csses.length-1; i>=0; i--){
					if( csses[i].title ){
						sheets.unshift(csses[i]);
					}
				}
			} else {
				if( PSG.DOM.canDOM() == false ) return new Array();
				
				var objLinks = document.getElementsByTagName("link");
				for(i=objLinks.length-1; i>=0; i--){ // この場合は for(var i in objLinks) は正常動作しません！
					if(
					objLinks[i].getAttribute("rel") &&
					objLinks[i].getAttribute("rel").toLowerCase().indexOf("stylesheet") != -1 &&
					objLinks[i].getAttribute("title") ){
						sheets.unshift(objLinks[i]);
					}
				}
			}
			return sheets;
		},
		
		/**
		* @access public
		* @param sheet String 適用するスタイルシート名
		* @return void
		*
		* sheet と同一名のスタイルシートを有効に、それ以外を無効にします。
		* 永続スタイルシートには影響を及ぼしません。
		* DOM がサポートされていなければ何もしません。
		*/
		changeStyleSheet : function(sheet){
			if( !sheet || PSG.DOM.canDOM() == false ) return;
			
			var sheets = PSG.StyleSheet.getStyleSheets();
			for(var i in sheets){
				/* WinIE6 は以下のようにするとページ読み込み時に何故か全てのスタイルを無効にする。Fxxk。
				sheets[i].disabled = (sheets[i].getAttribute("title") != sheet);
				*/
				sheets[i].disabled = true;
				var title = sheets[i].title;
				if( !title ) title = sheets[i].getAttribute("title");
				if(title == sheet){
					sheets[i].disabled = false;
				}
			}
			PSG.Cookie.setCookie("sheet", sheet, PSG.Config.StyleSheet.expdays, PSG.Config.Cookie.domain, PSG.Config.Cookie.path );
		},
		
		/**
		* @access protected
		* @return void
		* 選択スタイル名によるクラス名の再設定と実際の CSS の切り替えを行う。
		* イベントで割り当てられて実行される。
		*/
		handleStyleSheet : function(){
			var selectElement = document.getElementById(PSG.StyleSheet.selectID);
			var sheet = selectElement.options[selectElement.selectedIndex].text;
			var options = selectElement.options;
			for(var i=options.length-1; i>=0; i--){
				options[i].className = (options[i].text == sheet) ? "enable" : "disable";
			}
			PSG.StyleSheet.changeStyleSheet(sheet);
		},
		
		
		/**
		* @access public
		* @return void
		*
		* link 要素で指定されているスタイルシートのタイトルを一覧でセレクトボックスとして出力します。
		* 出力は div 要素に select 要素を含めた形で行われます。
		* form 要素には PSG.StyleSheet.formID を付けます。
		* select 要素には PSG.StyleSheet.selectID を付けます。
		* このセレクトボックスは選択項目が変更されると
		* 自動的に適切な changeStyleSheet() を実行されるよう設定されます。
		* また、現在有効なスタイルの項目は選択状態にされます。
		* DOM がサポートされていなければ何もしません。
		*/
		createController : function(){
			if( PSG.DOM.canDOM() == false ) return;
			
			var selectForm = PSG.DOM.createElement("form");
			var div = PSG.DOM.createElement("div");
			var select = PSG.DOM.createElement("select");
			var sheet = PSG.Cookie.getCookie("sheet");
			var sheets = PSG.StyleSheet.getStyleSheets();
			
			selectForm.id = PSG.StyleSheet.formID;
			selectForm.setAttribute("action", location.href); // form 要素には action 属性が必須
			select.id = PSG.StyleSheet.selectID;
			
			/*
			同一の title 属性を持つスタイルシートの link が複数あると
			option が重複するためセレクトボックスに含める前にチェックします [Feedback 2004-12-19]
			*/
			var titles = new Array();
			for(var i in sheets){
				var title = sheets[i].title;
				if( !title ) title = sheets[i].getAttribute("title");
				if( PSG.Arrays.hasValue(titles, title) == false ){
					titles.unshift(title);
					var opt = PSG.DOM.createElement("option");
					opt.appendChild( document.createTextNode(title) );
					select.appendChild(opt);
					if( title == sheet ){
						select.selectedIndex = i;
						opt.className = "enable";
					} else {
						opt.className = "disable";
					}
				}
			}
			
			/* 優先/代替スタイル一切適用無し状態が設定で有効なら追加 */
			if( PSG.Config.StyleSheet.enableNoStyle && PSG.Config.StyleSheet.noStyleName ){
				var nostyle = PSG.DOM.createElement("option");
				nostyle.appendChild( document.createTextNode(PSG.Config.StyleSheet.noStyleName) );
				select.appendChild(nostyle);
				if( sheet == PSG.Config.StyleSheet.noStyleName ){
					select.selectedIndex = titles.length;
					nostyle.className = "enable";
				} else {
					nostyle.className = "disable";
				}
			}
			
			/* テキストを追加 */
			if( PSG.Config.StyleSheet.text ){
				var label = PSG.DOM.createElement("label");
				label.setAttribute("for", PSG.StyleSheet.selectID ); // Feedback from ALIMIKA SATOMI 2004-12-19
				label.appendChild( document.createTextNode(PSG.Config.StyleSheet.text) );
				div.appendChild(label);
			}
			div.appendChild(select);
			selectForm.appendChild(div);
			
			PSG.Event.addEvent( select, "change", PSG.StyleSheet.handleStyleSheet );
			try{
				var targetElement;
				if( PSG.Config.StyleSheet.targetElementID ){
					targetElement = document.getElementById(PSG.Config.StyleSheet.targetElementID);
				} else {
					targetElement = document.getElementsByTagName(PSG.Config.StyleSheet.targetElementName)[PSG.Config.StyleSheet.targetElementIndex-1];
				}
				PSG.DOM.addElement( selectForm, targetElement, PSG.Config.StyleSheet.isBefore, PSG.Config.StyleSheet.isOut );
			}catch(err){}
		},
		
		/*
		* @access public
		* @return void
		*
		* 以前のスタイルシート設定を読み込んで、そのスタイルを反映させます。
		* クッキーがなんらかの理由で存在しなければ何もしません。
		*/
		init : function(){
			var sheet = PSG.Cookie.getCookie("sheet");
			if( sheet != null ){
				PSG.StyleSheet.changeStyleSheet(sheet);
			}
		}
	}
}

/*
*
*********** 関数のイベント登録や即座の実行 *************
# スクリプト全体を無効化する時はここをコメントアウトすると楽
*/
PSG.Event.addLoadEvent( PSG.StyleSheet.createController );
PSG.StyleSheet.init(); // 表示スタイルをレンダリング開始前に切り替える


/*
*	PSG 配布先 - read a little
*		http://readalittle.net/
*
*	local variable : tabstop=4, charset=utf-8, newline=CR+LF
\e
*/
