// spica javascript libraries - changer.js
// == written by Takuya Otani <takuya.otani@gmail.com> ===
// == Copyright (C) 2006 SimpleBoxes/SerendipityNZ Ltd. ==

// [History] ====
// ver 0.01 [2006/09/06] changed StyleChanger._finish to set cookie properly
// ver 0.00 [2006/08/11] the first release.

// === window ===
window.eventPosition = function(ev)
{
	var pos = { x:0, y:0 };
	pos.x = ev.pageX || ev.clientX || 0;
	pos.y = ev.pageY || ev.clientY || 0;
	return pos;
}
// === cookie ===
function Cookie(option)
{
	this._setting = {
		domain: window.location.hostname,
		path: '/',
		expire: 10
	};
	this.set_option(option);
	return this;
}
Cookie.prototype = {
	set_option : function(option)
	{
		for (var key in option)
			this._setting[key] = option[key];
	},
	get : function(name)
	{
		var cookies = document.cookie.split(';');
		for (var i=0,n=cookies.length;i<n;i++)
		{
			cookies[i] = cookies[i].replace(/^\s*/,'');
			var value = cookies[i].split('=',2);
			if (value[0] == name) return unescape(value[1]);
		}
		return null;
	},
	set : function(name,value)
	{
		var cookies = [];
		cookies.push([name,escape(value)].join('='));
		if (this._setting.expire)
		{ // expires
			var date = new Date();
			date.setTime(date.getTime() + (this._setting.expire * 24 * 3600 * 1000));
			cookies.push(['expires',date.toGMTString()].join('='));
		}
		if (this._setting.path)
			cookies.push(['path',this._setting.path].join('='));
		if (this._setting.domain)
			cookies.push(['domain',this._setting.domain].join('='));
		document.cookie = cookies.join('; ');
	}
};
// === style sheet ===
function StyleSheets()
{
	this.sheets = [];
	this.names  = {};
	this.preferred = null;
	this.active = null;
	return this._init();
}
StyleSheets.prototype = {
	_init : function()
	{
		var links = document.getElementsByTagName('link');
		var check = document.styleSheets;
		if (check)
		{ // There is styleSheets object.
			for (var i=0,n=check.length;i<n;i++)
			{
				if (!check[i].title) continue;
				this.sheets.push({title:check[i].title,entity:check[i]});
			}
			// document.styleSheets indicates active style only on Safari.
			// So we need to collect alternate styles by another way instead of styleSheets.
			if (Browser.isSafari)
				check = false;
		}
		for (var i=0,n=links.length;i<n;i++)
		{
			if (links[i].getAttribute('rel').indexOf('style') == -1) continue;
			var title = links[i].getAttribute('title');
			if (!title) continue;
			if (!check)
				this.sheets.push({title:title,entity:links[i]});
			this.names[title] = links[i].getAttribute('id');
			if (links[i].getAttribute('rel').indexOf('alt') == -1) // not alternative
				this.preferred = title;
		}
		return this;
	},
	set_active : function(title)
	{
		if (this.active == title) return; // nothing to do
		for (var i=0,n=this.sheets.length;i<n;i++)
		{
			this.sheets[i].entity.disabled = true;
			if (title == this.sheets[i].title)
				this.sheets[i].entity.disabled = false;
		}
		if (Browser.isSafari)
		{ // Safari does not handle disable flag for styles.
			// So we need to change rel value to switch style.
			for (var i=0,n=this.sheets.length;i<n;i++)
			{
				var style = this.sheets[i].entity;
				style.setAttribute('rel',(style.disabled) ? 'alternate stylesheet' : 'stylesheet');
			}
		}
		this.active = title;
	},
	get_name : function(title)
	{
		if (!title) return;
		return this.names[title];
	}
};
// === changer ===
function StyleChanger(option)
{
	// default settings
	this._setting = {
		dir    : './',
		imag   : '.jpg',
		marker : '_marker.gif',
		offset : 20,
		target : 'stylechanger',
		select : false,
		sel_id : 'changer-marker',
		popup  : 'changer-popup',
		mark   : '\u25A0'
	};
	for (var key in option)
		this._setting[key] = option[key];
	this.cookie = new Cookie();
	this.styles = new StyleSheets();
	this.images = {};
	this.popup = null;
	return this._init();
}
StyleChanger.prototype = {
	_init : function()
	{
		var self = this;
		self._init_style();
		Event.register(window,'load',function() { self._init_popup() });
		Event.register(window,'load',function() { self._init_style() });
		Event.register(window,'unload',function() { self._finish() });
		return self;
	},
	_init_popup : function()
	{
		var pref = this._setting;
		if (!pref.popup) return this._init_marker();
		var body = document.getElementsByTagName('body')[0];
		if (!body) return;
		// generating popup box
		this.popup = document.createElement('div');
		this.popup.setAttribute('id',pref.popup);
		this.popup.style.position = 'absolute';
		this.popup.style.zIndex = '1000';
		this.popup.style.top = '0px';
		this.popup.style.left = '0px'
		this.popup.style.visibility = 'hidden';
		body.appendChild(this.popup);
		// getting thumbnail images
		var sheets = this.styles.sheets;
		for (var i=0,n=sheets.length;i<n;i++)
		{
			var image = new Image;
			var name  = this.styles.get_name(sheets[i].title);
			image.src = [pref.dir,name,pref.imag].join('');
			this.images[sheets[i].title] = image;
		}
		this._init_marker();
	},
	_init_marker : function()
	{
		var pref = this._setting;
		var sheets = this.styles.sheets;
		if (sheets.length == 0) return;
		// getting target block
		var target = document.getElementById(pref.target);
		if (target)
		{ // we have target, so we need to clear the content.
			target.innerHTML = '';
		}
		else
		{ // we don't have target, so we should create it.
			var body = document.getElementsByTagName('body')[0];
			if (!body) return
			target = document.createElement('div');
			target.setAttribute('id',pref.target);
			body.appendChild(target);
		}
		// generating selector
		if (target && pref.select)
		{
			var selector = document.createElement('select');
			selector.setAttribute('id',pref.sel_id);
			target.appendChild(selector);
			target = selector;
		}
		if (!target) return;
		// add available styles into target
		for (var i=0,n=sheets.length;i<n;i++)
		{
			var title = sheets[i].title;
			var name  = this.styles.get_name(sheets[i].title);
			if (pref.select)
			{
				var marker = new Option;
				var number = target.options.length;
				marker.text = title;
				target.options[number] = marker;
				if (this.styles.active == title)
					target.options[number].selected = true;
			}
			else
			{
				var marker = (pref.marker && pref.marker != '')
					? document.createElement('img')
					: document.createElement('span');
				if (pref.marker && pref.marker != '')
					marker.setAttribute('src',[pref.dir,name,pref.marker].join(''));
				else
					marker.innerHTML = pref.mark;
				marker.setAttribute('id',[pref.sel_id,i].join(''));
				this._set_marker(marker,title);
				target.appendChild(marker);
			}
		}
		if (target && pref.select)
		{
			var self = this;
			Event.register(target,'change',function() { self._change_option(target) });
		}
	},
	_init_style : function()
	{
		this.styles.set_active(this.cookie.get('style'));
	},
	_finish : function()
	{
		this.cookie.set('style',this.styles.active);
	},
	_set_marker : function(marker,title)
	{
		var self = this;
		Event.register(marker,'mouseover',function(e) { self._enable_image(e,title) });
		Event.register(marker,'mouseout',function() { self._disable_image() });
		Event.register(marker,'click',function() { self._change_style(title) });
	},
	_enable_image : function(evt,title)
	{
		var offset = this._setting.offset;
		var pos = eventPosition(Event.getEvent(evt));
		if (!this.popup) return;
		var imag = document.createElement('img');
		var text = document.createElement('p');
		imag.setAttribute('src',this.images[title].src);
		text.innerHTML = title;
		this.popup.style.visibility = 'visible';
		this.popup.style.left = [pos.x + offset,'px'].join('');
		this.popup.style.top  = [pos.y + offset,'px'].join('');
		this.popup.innerHTML = '';
		this.popup.appendChild(imag);
		this.popup.appendChild(text);
	},
	_disable_image : function()
	{
		if (this.popup)
			this.popup.style.visibility = 'hidden';
	},
	_change_style : function(title)
	{
		this.styles.set_active(title);
		this._disable_image();
	},
	_change_option : function(selector)
	{
		var list = selector.options;
		for (var i=0,n=list.length;i<n;i++)
		{
			if (list[i].selected)
			{
				this._change_style(list[i].text);
				break;
			}
		}
	}
};
var StyleChanger = new StyleChanger({
	select : true,               // enabling selector
	dir    : './',               // image directory
	imag   : '.jpg',             // thumbnail suffix
	marker : '_marker.gif',      // marker suffix
	offset : 20,                 // offset for popup
	target : 'stylechanger',     // target id for changer
	sel_id : 'changer-selector', // selector id (it works marker id prefix for markers)
	popup  : 'changer-popup',    // popup id
	mark   : '\u25A0'            // marker's symbol if it's required
});
