// IOTBS1.3 :: Invasion of the Body Switchers
// ***********************************************
// This copyright statement must remain in place for both personal and commercial use
// GNU General Public License -- http://www.gnu.org/copyleft/gpl.html
// ***********************************************
// Original concept by Andy Clarke -- http://www.stuffandnonsense.co.uk/
// DOM scripting by brothercake -- http://www.brothercake.com/
// Create element and attributes based on a method by beetle -- http://www.peterbailey.net/
//************************************************
function iotbs() { //open initialisation function 
//************************************************

//initialise the preferences manager ('canvas-element')
switcher = new switchManager('body');

/*****************************************************************************
 Define switching controls
*****************************************************************************/

var printSwitcher = new bodySwitcher('print-switcher', '');
printSwitcher.defineClass('default', 'Print Recipe With All Images');
printSwitcher.defineClass('noImages', 'Print Recipe With No Images');
printSwitcher.defineClass('oneImage', 'Print Recipe With Finished Image Only');


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



//close initialisation function
};


//global switch manager reference
var switcher;


//DOM-ready watcher
function domReady()
{
	//start or increment the counter
	this.n = typeof this.n == 'undefined' ? 0 : this.n + 1;

	//if DOM methods are supported, and the body element exists
	if(typeof document.getElementsByTagName != 'undefined' && (document.getElementsByTagName('body')[0] != null || document.body != null))
	{
		//if this is not mac/ie
		if(!(typeof document.all != 'undefined' && typeof window.opera == 'undefined' && typeof document.mimeType == 'undefined'))
		{
			//initialise IOTBS
			iotbs();
		}
	}

	//otherwise if we haven't reached 60 (so timeout after 15 seconds)
	else if(this.n < 60)
	{
		//restart the watcher
		setTimeout('domReady()', 250);
	}
};
//start the watcher
domReady();


//switch manager 
function switchManager(canvas)
{
	//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 canvas element
	//if the canvas is 'body' and the document.body object exists, use that reference
	//because in older moz builds (eg ns7.1) document.getElementsByTagName('body')[0] is undefined
	//unless this script is in the body section (which it isn't)
	this.canvas = canvas == 'body' && typeof document.body != 'undefined' ? document.body : document.getElementsByTagName(canvas)[0];

	//store the initial classname
	this.initial = this.canvas.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 a classname attribute as " something" (beginning with a leading space)
	//because that fails in some Opera 7 builds
	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 canvas class name
		this.canvas.className = this.initial + this.string;
	}


	//add a DOM memory cleaner for win/ie
	if(typeof window.attachEvent != 'undefined')
	{
		window.attachEvent('onunload', function()
		{
			//for each item in the document.all collection
			for(var i=0; i<document.all.length; i++)
			{
				//set its onchange property to null
				//so that if this object is one of our selectors
				//the property can be garbage collected
				document.all[i]['onchange'] = null;
			}
		});
	}
};

//set a cookie method
switchManager.prototype.set = function(days)
{
	//format expiry date
	var thedate = new Date();
	thedate.setTime(thedate.getTime() + ( days *24*60*60*1000));
	
	//store the string, replacing spaces with '#' so that leading spaces are preserved
	var info = this.string.replace(/ /g,'#');
	
	//if the value is empty, set its expiry in the past to delete the cookie
	if(info == '') { thedate.setTime(0); }
	
	//create the cookie
	document.cookie = 'bodySwitcher=' + info
		+ '; expires=' + thedate.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 and it's ours
	if(document.cookie && document.cookie.indexOf('bodySwitcher=')!=-1)
	{
		//extract and store relevant information (turning '#' back into spaces)
		this.cookie = document.cookie.split('bodySwitcher=')[1].split(';')[0].replace(/#/g,' ');
	}
	
	return this.cookie;
};


//switcher-control constructor
function bodySwitcher(divid, label)
{
	//don't continue if the container doesn't exist
	if(document.getElementById(divid) == null) { return false; }

	//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
	var attrs = { 'action' : '' };
	var frm = document.getElementById(divid).appendChild(this.create('form', attrs));

	//fieldset inside form
	var fieldset = frm.appendChild(this.create('fieldset'));

	//label inside fieldset
	attrs = { 'for' : 'select-' + divid };
	var labele = fieldset.appendChild(this.create('label', attrs));

	//span inside label containing label text
	attrs = { 'text' : label };
	labele.appendChild(this.create('span', attrs));

	//select inside label
	attrs = { 'id' : 'select-' + divid };
	this.select = labele.appendChild(this.create('select', attrs));

	//create a global [within this scope] reference to 'this'
	var self = this;

	//bind onchange handler
	this.select.onchange = function()
	{
		//run through classnames array
		var len = self.classes.length;
		for(var i=0; i<len; i++)
		{
			//remove this key (custom class name) from string
			switcher.string = switcher.string.replace(' ' + self.classes[i] + ' ','');
		}

		//get new value from option
		var 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(chosen != 'default')
		{
			switcher.string += ' ' + chosen + ' ';	
		}
		
		//set new canvas class name
		switcher.canvas.className = switcher.initial + switcher.string;

		//store changes to a cookie which expires a year from now
		switcher.set(365);
		
		//*** dev
		//document.title = '<' + switcher.canvas.className.replace(/ /g,'+') + '>   [' + switcher.string.replace(/ /g,'+') + ']';

	};
	
	return true;
};

//add a new class option method
bodySwitcher.prototype.defineClass = function(key, val)
{
	//don't continue if the select doesn't exist
	if(typeof this.select == 'undefined') { return false; }
	
	//option inside select
	var attrs = { 'value' : key, 'text' : val }; 
	this.select.appendChild(this.create('option', attrs));

	//if the cookie exists, and the value contains this key
	if(switcher.cookie != null && 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 ++;

	return true;
};

//create element and attributes method -- http://www.codingforums.com/showthread.php?s=&postid=151108
bodySwitcher.prototype.create = function(tag, attrs)
{
	//detect support for namespaced element creation, in case we're in the XML DOM
	var 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' :
					ele.appendChild(document.createTextNode(attrs[i]));
					break;
				
				//create a class name
				case 'class' : 
					ele.className = attrs[i];
					break;
				
				//create a for attribute 
				case 'for' : 
					ele.setAttribute('htmlFor',attrs[i]);
					break;
				
				//create a generic attribute using IE-safe attribute creation
				default : 
					ele.setAttribute(i,'');
					ele[i] = attrs[i];
					break;
			}
		}
	}
	return ele;
};