// Invasion of the Body Switchers

// This copyright statement must remain in place for both personal and commercial use

// ***********************************************************************************

// Creative Commons License -- http://creativecommons.org/licenses/by-nc-nd/2.0/

// Original concept and article by Malarkey (Andy Clarke) -- http://www.stuffandnonsense.co.uk/

// DOM scripting by Brothercake (James Edwards) -- http://www.brothercake.com/

// Create element and attributes based on a method by beetle -- http://www.peterbailey.net/

//************************************************

//open initialisation function

function iotbs() { switcher = new switchManager();

//************************************************







/*****************************************************************************

 Define switching controls

*****************************************************************************/





//create a switcher form ('container-id', 'label')

var screenSwitcher = new bodySwitcher('screen-switcher', 'Hintergrund wählen');



//add a new class option ('classname', 'label')

screenSwitcher.defineClass('default', 'FloralGreen');

screenSwitcher.defineClass('bg01', 'Bambus');

screenSwitcher.defineClass('bg02', 'BirdsGreen');

screenSwitcher.defineClass('bg03', 'Ornament01');

screenSwitcher.defineClass('bg04', 'Ornament02');

screenSwitcher.defineClass('bg05', 'ChineseGreen');

screenSwitcher.defineClass('bg06', 'BirdsBeige');

screenSwitcher.defineClass('bg07', 'FloralDark');

screenSwitcher.defineClass('bg08', 'Grün');

screenSwitcher.defineClass('bg09', 'Beige');

screenSwitcher.defineClass('bg10', 'Grau');

screenSwitcher.defineClass('bg11', 'Schwarz');

screenSwitcher.defineClass('bg12', 'Mint');

screenSwitcher.defineClass('bg13', 'Azur');

screenSwitcher.defineClass('bg14', 'Violet');

screenSwitcher.defineClass('bg15', 'Rose');

/*****************************************************************************

*****************************************************************************/







//close initialisation function

};





//global preferences manager reference

var switcher;





//setup initialisation function

//.. gecko, safari, konqueror and generic

if(typeof window.addEventListener != 'undefined')

{

	window.addEventListener('load', iotbs, false);

}

//.. opera 7

else if(typeof document.addEventListener != 'undefined')

{

	document.addEventListener('load', iotbs, false);

}

//.. win/ie

else if(typeof window.attachEvent != 'undefined')

{

	window.attachEvent('onload', iotbs);

}





//preferences manager

function switchManager()

{

	//string for storing the overall custom classname

	//I was originally storing it in the body class name directly

	//but 1.7+ mozilla builds were not honouring the trailing whitespace we need

	this.string  = '';



	//store reference to body element

	this.body = document.getElementsByTagName('body')[0];



	//store the initial classname

	this.initial = this.body.className;



	//if the default classname is empty, add "iotbs"

	//because we need there to be at least one classname already -

	//the leading and trailing space in each custom classname is required,

	//but you can't set the body classname as " something" (beginning with a leading space)

	//because that may not work in Opera 7

	if(this.initial == '')

	{

		this.initial = 'itobs';

	}



	//look for a stored cookie

	this.cookie = this.read();



	//if it exists

	if(this.cookie != null)

	{

		//store cookie value to string

		this.string = this.cookie;



		//set new body class name

		this.body.className = this.initial + this.string;

	}



	//*** dev

	//document.title = '<' + this.body.className.replace(/ /g,'+') + '>   [' + this.string.replace(/ /g,'+') + ']';



};



//set a cookie method

switchManager.prototype.set = function(days)

{

	//format expiry date

	this.date = new Date();

	this.date.setTime(this.date.getTime() + ( days *24*60*60*1000));



	//store the string, replacing spaces with '#' so that leading spaces are preserved

	this.info = this.string.replace(/ /g,'#');



	//if the value is empty, set its expiry in the past to delete the cookie

	if(this.info == '') { this.date.setTime(0); }



	//create the cookie

	document.cookie = 'bodySwitcher=' + this.info

		+ '; expires=' + this.date.toGMTString()

		+ '; path=/';



};





//read a cookie method

switchManager.prototype.read = function()

{

	//set null reference so we always have something to return

	this.cookie = null;



	//if a cookie exists

	if(document.cookie)

	{

		//if it's our cookie

		if(document.cookie.indexOf('bodySwitcher')!=-1)

		{

			//extract and store relevant information (turning '#' back into spaces)

			this.cookie = document.cookie.split('bodySwitcher=');

			this.cookie = this.cookie[1].split(';');

			this.cookie = this.cookie[0].replace(/#/g,' ');

		}

	}



	return this.cookie;

};





//switcher form constructor

function bodySwitcher(divid, label)

{



	//create an associate array of classnames for this option

	//so we can later iterate through and remove them from the custom classname string

	this.classes = [];



	//start counting options, because we'll need the index of each option as it's created

	//so that an option can be selected by default if necessary

	this.options = 0;



	//outer form

	this.attrs = { 'action' : '' };

	this.form = this.createElement('form', this.attrs);

	document.getElementById(divid).appendChild(this.form);



	//fieldset inside form

	this.fieldset = this.createElement('fieldset');

	this.form.appendChild(this.fieldset);



	//label inside fieldset

	this.attrs = { 'for' : 'select-' + divid };

	this.label = this.createElement('label', this.attrs);

	this.fieldset.appendChild(this.label);



	//span inside label containing label text

	this.attrs = { 'text' : label };

	this.span = this.createElement('span', this.attrs);

	this.label.appendChild(this.span);



	//select inside label

	this.attrs = { 'id' : 'select-' + divid };

	this.select = this.createElement('select', this.attrs);

	this.label.appendChild(this.select);



	//create a global [within this scope] reference to 'this'

	var self = this;



	//bind onchange handler

	this.select.onchange = function()

	{



		//run through classnames array

		this.classLen = self.classes.length;

		for(var i=0; i < this.classLen; i++)

		{

			//remove this key (custom class name) from string

			switcher.string = switcher.string.replace(' ' + self.classes[i] + ' ','');

		}



		//get new value from option

		this.chosen = this.options[this.options.selectedIndex].value;



		//if it isn't default then add to string

		//we need both a leading and a trailing space to work with

		//to avoid confusion with identical leading or trailing substrings in classnames,

		//such as "high" and "highcontrast" or "large-serif" and "small-serif"

		if(this.chosen != 'default')

		{

			switcher.string += ' ' + this.chosen + ' ';

		}



		//set new body class name

		switcher.body.className = switcher.initial + switcher.string;



		//store changes to a cookie which expires a year from now

		switcher.set(365)



		//*** dev

		//document.title = '<' + switcher.body.className.replace(/ /g,'+') + '>   [' + switcher.string.replace(/ /g,'+') + ']';



	};



};



//add a new class option method

bodySwitcher.prototype.defineClass = function(key, val)

{

	//option inside select

	this.attrs = { 'value' : key, 'text' : val };

	this.option = this.createElement('option', this.attrs);

	this.select.appendChild(this.option);



	//check for cookie value

	if(switcher.cookie != null)

	{

		//if value contains this key

		if(switcher.cookie.indexOf(' ' + key + ' ')!=-1)

		{

			//select this option

			this.select.selectedIndex = this.options;

		}

	}



	//store the classname

	this.classes[this.options] = key;



	//increase option count

	this.options ++;



};



//create element and attributes method -- http://www.codingforums.com/showthread.php?s=&postid=151108

bodySwitcher.prototype.createElement = function(tag, attrs)

{

	//detect support for namespaced element creation, in case we're in the XML DOM

	this.ele = (typeof document.createElementNS != 'undefined') ? document.createElementNS('http://www.w3.org/1999/xhtml',tag) : document.createElement(tag);



	//run through attributes argument

	if(typeof attrs != 'undefined')

	{

		for(var i in attrs)

		{

			switch(i)

			{

				//create a text node

				case 'text' :

					this.ele.appendChild(document.createTextNode(attrs[i]));

					break;



				//create a class name

				case 'class' :

					this.ele.className = attrs[i];

					break;



				//create a for attribute

				case 'for' :

					this.ele.setAttribute('htmlFor',attrs[i]);

					break;



				//create a generic attribute using IE-safe attribute creation

				default :

					this.ele.setAttribute(i,'');

					this.ele[i] = attrs[i];

					break;

			}

		}

	}

	return this.ele;

};