//---------------------------------+
//  CARPE  D i s p l a y  1.0 Beta |
//  2008 - 07 - 13                 |
//  By Tom Hermansson Snickars     |
//  Copyright CARPE Design         |
//  http://carpe.ambiprospect.com/ |
//---------------------------------+

// JavaScript Document
CARPE.Displays = {
	elements:			[],

	// CARPE Display constants.
	defaultParent:		(document.forms[0] ? document.forms[0] : document.body),
	defaultFrom:		0,
	defaultTo:			100,
	defaultLabel:		'',
	defaultPrefix:		'',
	defaultSuffix:		'',
	nameValueSeparator:	'-',
	displayClassName:	'carpe-display', // The class names for the displays.
	idPrefix:			'auto', // Prefix used for auto-generated display element IDs.
	idSeparator:		'-',
	prefixClassName:	'carpe-display-prefix',
	screenClassName:	'carpe-display-screen',
	suffixClassName:	'carpe-display-suffix',
	panelClassName:		'carpe-display-panel',

	// Method 'init': Loops through display elements and puts them in the array CARPE.Displays.elements
	init: function() {
		CARPE.Displays.elements = CARPE.getElementsByClass(CARPE.Displays.displayClassName);
		for (var i in CARPE.Displays.elements) { // Loops through display elements.
			if (!document.getElementById(CARPE.Displays.panelClassName + // If the display is not yet present in the page.
					CARPE.Displays.nameValueSeparator + CARPE.Displays.elements[i].id)) {
				new CARPE.Display(CARPE.Displays.elements[i]); // Create a new display object.
			}
		}
		return;
	}
};
// The Display class constructor
CARPE.Display = function(elmnt, params, location, values) { // values: array, function f(x) or object {from: num, to: num, steps: num}.
	if (elmnt) {
		if (typeof elmnt === 'string') {
			this.id = elmnt;
			this.elmnt = document.getElementById(elmnt) ? document.getElementById(elmnt) : null;
		} else if (elmnt.nodeType == 1) {
			if ((elmnt.tagName.toLowerCase() == 'input') || (elmnt.tagName.toLowerCase() == 'select')) {
				this.elmnt = elmnt;
			}
		}
	}
	this.elmnt = this.elmnt ? this.elmnt : document.createElement('input');
	// The Display ID
	if (!this.elmnt.id && !this.id) {
		this.id = 0;
		var idBase = CARPE.Displays.displayClassName + CARPE.Displays.idSeparator + 
			CARPE.Displays.idPrefix + CARPE.Displays.idSeparator;
		while (document.getElementById(idBase + this.id)) this.id++;
		this.elmnt.id = idBase + this.id;
	}
	this.id = this.elmnt.id || this.id;
	// The Display Classname
	if (this.elmnt.className) {
		if (this.elmnt.className.indexOf(CARPE.Displays.displayClassName) == -1) {
			this.elmnt.className = this.elmnt.className + ' ' + CARPE.Displays.displayClassName;
		}
	} else {
		this.elmnt.className = CARPE.Displays.displayClassName;
	}
	// Default values
	if (this.elmnt.options) {
		this.options = this.elmnt.options;
		this.index = this.elmnt.selectedIndex;
		this.stops = this.options.length;
		this.from = 0;
		this.to = this.stops - 1;
		this.value = (this.index > -1) ? this.options[this.index] : '';
	}
	else {
		this.from = CARPE.Displays.defaultFrom;
		this.to = CARPE.Displays.defaultTo;
		this.stops = CARPE.Displays.defaultStops;
		this.value = this.elmnt.value;
	}
	this.prefix = '';
	this.suffix = '';
	// Properties supplied as constructor arguments.
	if (params) { 
		this.value = params.value ? parseFloat(params.value) : this.value;
		this.stops = params.stops ? parseInt(params.stops, 10) : this.stops;
		if (params.target) {
			this.target = (typeof params.target == 'string') ? document.getElementById(params.target) : params.target;
		}
		this.feedback = !!params.feedback;
	}
	// Default values
	// User values
	this.classNames = (this.elmnt.className) ? this.elmnt.className.split(' ') : [];
	this.properties = [];
	for (var i = 0; i < this.classNames.length; i++) {
		var name = this.classNames[i].split('-')[0];
		var value = this.classNames[i].substring(name.length + 1, this.classNames[i].length); 
		switch (name) {
		case 'from':		this.from = parseInt(value, 10); break;
		case 'to':			this.to = parseInt(value, 10); break;
		case 'target':      this.target = document.getElementById(value); break;
		case 'source':      this.source = document.getElementById(value); break;
		case 'feedback':    this.feedback = !!value; break;
		case 'label':    	this.label = value; break;
		case 'prefix':    	this.prefix = value.toString().replace('_', ' '); break;
		case 'suffix':    	this.suffix = value.toString().replace('_', ' '); break;
		case 'decimals':	this.decimals = parseInt(value, 10); break;
		case 'stops':       this.stops = parseInt(value, 10); break;
		default: break;
		}
	}
	if (this.elmnt.parentNode) {
		this.parent = this.elmnt.parentNode;
	} 
	else {
		this.parent = CARPE.Displays.defaultParent;
		if (location) {
			if (location.parent) { 
				this.parent = (typeof location.parent === 'string') ?
					document.getElementById(location.parent) : location.parent;
			} 
			if (location.before) {
				this.before = (typeof location.before === 'string') ?
					document.getElementById(location.before) : location.before;
					this.parent = this.before.parentNode;
			}
			if (location.after) {
				this.after = (typeof location.after === 'string') ?
					document.getElementById(location.after) : location.after;
					this.parent = this.after.parentNode;
			}
		}
		// The display's location in the DOM
		if (!this.before && !this.after) {
			this.parent.appendChild(this.elmnt);
		} else if (this.before) {
			this.parent.insertBefore(this.elmnt, this.before);
		} else if (this.after) {
			var node = this.after.nextSibling;
			while (node.nodeType != 1) node = node.nextSibling;
			this.parent.insertBefore(this.elmnt, node);
		}
	}
	// The display panel
	this.panel = document.createElement('a');
	this.panel.setAttribute('href', 'javascript: void 0;');
	this.parent.appendChild(this.panel);
	this.panel.className = CARPE.Displays.panelClassName;
	this.panel.id = CARPE.Sliders.panelClassName + CARPE.Displays.idSeparator + this.id;
	
	// The display screen
	this.screen = document.createElement('div');
	this.screen.className = CARPE.Displays.screenClassName;
	this.panel.appendChild(this.screen);
	this.screen.id = CARPE.Displays.screenClassName + CARPE.Displays.idSeparator + this.id;
	this.screen.innerHTML = this.elmnt.value;

	// The hidden value container
	this.valueElmnt = document.createElement('input');
	this.valueElmnt.setAttribute('type', 'hidden');
	this.valueElmnt.setAttribute('name', this.name);
	this.valueElmnt.className = this.className;
	this.parent.insertBefore(this.valueElmnt, this.elmnt);
	this.parent.removeChild(this.elmnt);
	this.valueElmnt.id = this.id;
	// this.valueElmnt.display = this;
	this.valueElmnt.setValue = this.setValue.bind(this);
	// this.setValue.bind(this.valueElmnt);
	// this.panel.onfocus = this.makeFocused.bind(this);
	// this.panel.onblur = this.makeBlurred.bind(this);
	
	// Add display to array of displays:
	CARPE.Displays.elements.concat(this);
};
// The Slider class:
CARPE.Display.prototype = {
	keyHandler: function(evnt) {
		if (!evnt) { evnt = window.event; } // Get the key event.
		if (evnt) {
			var key = evnt.which || evnt.keyCode; // Get the key code.
			if ((key == CARPE.KEY_RIGHT) || (key == CARPE.KEY_UP)) { // Right or up.
				this.change(1);
				return false;
			}
			else if ((key == CARPE.KEY_LEFT) || (key == CARPE.KEY_DOWN)) { // Left or down.
				this.change(-1);
				return false;
			}
		}
		return true;
	},
	change: function(increment) {
		if (this.stops > 1) {
			return this.value = this.options ? this.options[this.index + increment] : value;
		}
		else {
			this.value = this.value + increment;
			return this;
		}
	},
	// Class method 'setValue': Sets value of the display.
	// Intended as a 'public' method for user scripts, and when the display is a passive target for another form element.
	setValue: function(value) {
		if (this.options) {
			this.valueElmnt.value = this.options[Math.round(value * (this.options.length - 1))].text;
		}
		else if (this.stops > 1) {
			this.valueElmnt.value = Math.round((this.stops - 1) * value) /
				(this.stops - 1) * (this.to - this.from) + this.from;
		} else {
			this.valueElmnt.value = value * (this.to - this.from) + this.from;
		}
		this.screen.innerHTML = this.prefix + this.valueElmnt.value + this.suffix;
		return this;
	},
	update: function(feedback) {
		if (this.source) {
			if (this.source.hasOwnProperty('value')) {
				this.setValue();
				this.source.value;
			}
			if (this.target.hasOwnProperty('setValue')) {
				this.target.setValue(this.elmnt.value, this.feedback);
			}
			else {
				this.target.value = this.elmnt.value;
			}
		}
	}
};

// Make sure the page is loaded before the slider initiation starts.
CARPE.addLoadEvent(CARPE.Displays.init);

