// IOTBS2.1 :: Invasion of the Body Switchers - Look Who's Switching Too
// >>> "The Director's Cut"
//      Generates the switching controls as definition-lists and links
// ***********************************************
// 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/
//************************************************


//switcher-control constructor
function bodySwitcher(divid, label, isnative, selected)
{
	//if load-mode is in use, and this is not ie, and this is the master of the native switching group
	if(switcher.path != null && !switcher.isie && typeof isnative != 'undefined' && isnative == 'yes')
	{
		//compile preferred/alternate stylesheets collection
		//and integrate with native switching
		switcher.integrate(
			this, //reference to this bodySwitcher object
			divid //switching control id
			);
	}

	//create an array for storing the switcher's option classnames and labels as they're added
	//so we can later iterate through and remove them from the custom classname string
	this.classes = [];

	//don't continue if the container doesn't exist
	if(document.getElementById(divid) == null) { return false; }

	//create an array of labels (text labels for each class)
	//to store as values in javascript: URIs
	this.labels = [];

	//definition list
	var attrs = { 'id' : 'select-' + divid };
	this.dl = document.getElementById(divid).appendChild(switcher.create('dl', attrs));

	//definition term [switcher heading containing label text]
	attrs = { 'text' : label };
	this.dl.appendChild(switcher.create('dt', attrs));

	//"selected" text
	this.selected = typeof selected != 'undefined' ? selected : '';

	return true;
};


//add a new class option method
bodySwitcher.prototype.defineClass = function(key, val)
{
	//store the classname
	this.classes[this.classes.length] = key;

	//don't continue if the list doesn't exist
	if(typeof this.dl == 'undefined') { return false; }

	//create a reference to 'this'
	var self = this;

	//store the link text labels
	this.labels[this.labels.length] = val;

	//definition inside list
	var item = this.dl.appendChild(switcher.create('dd'));

	//add selected class name to definition
	item.className = 'selected';

	//if key is default
	if(key == 'default')
	{
		//add plain text inside definition
		var link = item.appendChild(document.createTextNode(val + this.selected));
	}


	//else if cookie exists and its value matches this key
	else if(switcher.cookie != null && switcher.cookie.indexOf(' ' + key + ' ')!=-1)
	{
		//add plain text inside definition
		link = item.appendChild(document.createTextNode(val + this.selected));

		//if this is *not* the default item
		if(key != 'default')
		{
			//turn default text back into a link
			//we're doing it this way, instead of just creating a default link
			//because at the point where the default item is created
			//we don't know whether it should be a link or not
			//so we create it as plain text to begin with, and convert it here
			//because we know, now, that the default should be a link
			var defitem = this.dl.childNodes[1];

			//remove selected class name
			defitem.className = '';

			//remove the text node
			this.dl.childNodes[1].removeChild(defitem.firstChild);

			//and replace it with a link to select the default
			var attrs = { 'href' : 'javascript:void("' + this.classes[0] + '", "' + this.labels[0] + '")', 'text' : this.labels[0] };
			link = defitem.appendChild(switcher.create('a', attrs));
		}
	}

	//else if cookie doesn't exist or value doesn't contains this key
	else
	{
		//remove selected class name
		item.className = '';

		//add link inside definition
		//javascript: uri is used to store key value
		//and so that the link is navigable with the keyboard
		attrs = { 'href' : 'javascript:void("' + key + '", "' + val + '")', 'text' : val, 'class' : key };
		link = item.appendChild(switcher.create('a', attrs));
	}


	//bind onclick handler to definition item
	item.onclick = function()
	{
		//if this item has no links, don't continue
		if(this.getElementsByTagName('a').length == 0) { return false; }

		//get definitions in this list
		var items = self.dl.getElementsByTagName('dd');

		//for each definition
		var len = items.length;
		for(var i=0; i<len; i++)
		{
			//if it's this one
			if(items[i] == this)
			{
				//store the value of i
				//which is the index of this option in the switcher group
				var ind = i;
				break;
			}
		}

		//save the current switcher state
		switcher.save(
			self.dl.id.replace('select-', ''), //convert id of selector into switcher ident (label)
			self.classes[ind], //get key from class array
			ind, //the index of this option in the switcher group
			self //a reference to this bodySwitcher object
			);

		//redraw the list
		self.redraw(ind, this);

		return true;
	};

	return true;
};


//redraw the DD items with links or selected text as appropriate
bodySwitcher.prototype.redraw = function(ind, link)
{
	//get definitions in this list
	var items = this.dl.getElementsByTagName('dd');
	var len = items.length;

	//for each definition
	for(var i=0; i<len; i++)
	{
		//if it's the previously selected value it will only be a text node
		if(items[i].firstChild.nodeName == '#text')
		{
			//remove "selected" class name from definition
			items[i].className = '';

			//remove the text node
			items[i].removeChild(items[i].firstChild);

			//and replace it with a link to reselect this style
			var attrs = { 'href' : 'javascript:void("' + this.classes[i] + '", "' + this.labels[i] + '")', 'text' : this.labels[i], 'class' : this.classes[i] };
			items[i].appendChild(switcher.create('a', attrs));
		}
	}


	//we're doing this outside the previous loop
	//because the previous process needs to have run over the whole list already
	//so that the link we're sending focus to in this process definitely exists

	//if this option the last item, send focus to the first item
	//if it's any other item, send focus to the next item
	//this is because the activated link just had the focus
	//and removing a focussed element can cause
	//the page focus caret to be lost or reset to the top
	//an added benefit is that it allows you to toggle between
	//all styles in a group by repeatedly pressing enter
	items[(ind == len - 1 ? 0 : ind + 1)].firstChild.focus();

	//remove the link
	link.removeChild(link.firstChild);

	//add a text node label to replace the link
	link.appendChild(document.createTextNode(this.labels[ind] + this.selected));

	//add "selected" class name to definition
	items[ind].className = 'selected';
};


//update the switcher interface from programatic option changes
bodySwitcher.prototype.update = function(ind)
{
	//redraw the list, if the switcher control exists
	if(typeof this.dl != 'undefined')
	{
		this.redraw(ind, this.dl.getElementsByTagName('dd')[ind]);
	}
};

