
/**
 * smenu
 *
 * @package smenu
 * @version 2.0.1
 * @copyright Creative Pulse 2007-2009
 * @license http://www.gnu.org/copyleft/gpl.html GNU/GPL
 * @link http://www.creativepulse.eu/goto/smenu
 */

function Smenu(iname, host_id) {
	this.iname = iname;
	this.host_id = host_id;
	this.menuitems = new Array();

	// look for IE6
	var ver = navigator.userAgent.toLowerCase().match(/msie (\d(.\d*)?)/);
	this.ie6 = ver && ver[1] && ver[1] < 7;
}

Smenu.prototype.init = function (params) {
	// clean up from a previous initialization
	if (this.menuitems.length > 0) {
		this.host_obj = document.getElementById(this.host_id);
		if (this.host_obj) {
			for (var k in this.menuitems) if (this.menuitems.hasOwnProperty(k)) {
				var mi = this.menuitems[k];
				if (mi.outer_obj) {
					mi.outer_obj.removeChild(mi.inner_obj);
					this.host_obj.removeChild(mi.outer_obj);
				}
			}
		}
		this.menuitems = new Array();
	}

	if (this.itv)
		clearTimeout(this.itv);

	// initialize variables
	this.host_obj = null;
	this.interval = typeof params.interval != 'number' || params.interval < 1 ? 20 : params.interval;
	this.itv = 0;
	this.speed = typeof params.speed != 'number' || params.speed < 1 ? 1 : params.speed;
	this.minstep = typeof params.minstep != 'number' || params.minstep < 0 ? 0 : params.minstep;
	this.maxstep = typeof params.maxstep != 'number' || params.maxstep < 0 ? 0 : params.maxstep;
	this.hor = typeof params.hor != 'boolean' ? true : params.hor;
	this.align = typeof params.align != 'number' ? 0 : params.align;
	this.movtype = typeof params.movtype != 'string' ? 'elastic' : params.movtype;
	this.anitype = typeof params.anitype != 'string' ? 'static' : params.anitype;
	this.small_size = 0;
	this.standby_size = 0;
	this.min_size = typeof params.min_size != 'number' || params.min_size < 0 ? 0 : params.min_size;
	this.large_size = typeof params.large_size != 'number' || params.large_size < 0 ? 0 : params.large_size;
	this.sel_permanent = typeof params.sel_permanent != 'boolean' ? true : params.sel_permanent;
	this.def_item = typeof params.def_item != 'number' || params.def_item < 0 ? 0 : params.def_item;
	this.def_outer_class_norm = typeof params.def_outer_class_norm != 'string' ? '' : params.def_outer_class_norm;
	this.def_outer_class_sel = typeof params.def_outer_class_sel != 'string' ? '' : params.def_outer_class_sel;
	this.def_inner_class_norm = typeof params.def_inner_class_norm != 'string' ? '' : params.def_inner_class_norm;
	this.def_inner_class_sel = typeof params.def_inner_class_sel != 'string' ? '' : params.def_inner_class_sel;
	this.sel_k = -1;
}

Smenu.prototype.add_item = function (params) {
	var def_values = {
		id: '',
		outer_class_norm: '',
		outer_class_sel: '',
		inner_class_norm: '',
		inner_class_sel: '',
		html: '',
		html_ie6: '',
		html_srcid: '',
		link: '',
		linktype: 0,
		bgimage: '',
		bgimagerepeat: '',
		bgcolor: '',
		size: 0
	}

	// set defaults to undefined parameters
	for (var k in def_values) if (def_values.hasOwnProperty(k)) {
		if (typeof params[k] == 'undefined')
			params[k] = def_values[k];
	}

	if (this.ie6 && params.html != '' && params.html_ie6 != '')
		params.html = params.html_ie6;

	if (params.outer_class_norm == '' && this.def_outer_class_norm != '')
		params.outer_class_norm = this.def_outer_class_norm;

	if (params.outer_class_sel == '' && this.def_outer_class_sel != '')
		params.outer_class_sel = this.def_outer_class_sel;

	if (params.inner_class_norm == '' && this.def_inner_class_norm != '')
		params.inner_class_norm = this.def_inner_class_norm;

	if (params.inner_class_sel == '' && this.def_inner_class_sel != '')
		params.inner_class_sel = this.def_inner_class_sel;

	// add item
	this.menuitems.push(params);
}

Smenu.prototype.runit = function () {
	this.host_obj = document.getElementById(this.host_id);
	if (this.host_obj) {
		this.size = this.hor ? this.host_obj.offsetWidth : this.host_obj.offsetHeight;

		var elastic_size = this.size;
		var static_size = 0;

		var elastic_count = 0;
		this.last_elastic_k = -1;
		for (var k in this.menuitems) if (this.menuitems.hasOwnProperty(k)) {
			var mi = this.menuitems[k];
			if (mi.size == 0) {
				elastic_count++;
				this.last_elastic_k = k;
			}
			else {
				elastic_size -= mi.size;
				static_size += mi.size;
			}
		}
		this.correction_k = this.last_elastic_k;

		this.standby_size = elastic_count == 0 ? 0 : Math.floor(elastic_size / elastic_count);
		this.last_standby_size = this.standby_size + (this.size - static_size - this.standby_size * elastic_count);

		if (this.min_size > this.standby_size)
			this.min_size = this.standby_size;

		// count all except the selected item
		elastic_count--;
		if (elastic_count <= 0) {
			this.large_size = elastic_size;
			this.small_size = elastic_size;
		}
		else {
			if (this.large_size == 0 && this.movtype == 'plastic')
				this.small_size = 0;
			else if (this.large_size == 0 || this.large_size >= elastic_size)
				this.small_size = Math.floor(elastic_size * 0.3 / elastic_count);
			else
				this.small_size = Math.floor((elastic_size - this.large_size) / elastic_count);

			if (this.small_size < this.min_size)
				this.small_size = this.min_size;

			this.large_size = elastic_size - elastic_count * this.small_size;
		}

		switch (this.movtype) {
			case 'plastic':
				// find open item
				var def_item = this.def_item - 1;
				var last_item = -1, open_item = -1;
				for (var k in this.menuitems) if (this.menuitems.hasOwnProperty(k)) {
					if (this.menuitems[k].size == 0) {
						if (k == def_item) {
							open_item = k;
							break;
						}
						last_item = k;
					}
				}

				if (open_item == -1)
					open_item = last_item;

				// update menu item properties
				for (var k in this.menuitems) if (this.menuitems.hasOwnProperty(k)) {
					var mi = this.menuitems[k];
					if (mi.size == 0) {
						if (k == open_item) {
							mi.cursz = this.large_size;
							mi.trgsz = this.large_size;
						}
						else {
							mi.cursz = this.small_size;
							mi.trgsz = this.small_size;
						}
					}
					else {
						mi.cursz = mi.size;
						mi.trgsz = mi.size;
					}
				}

				break;

			case 'elastic':
			default:
				// update menu item properties
				for (var k in this.menuitems) if (this.menuitems.hasOwnProperty(k)) {
					var mi = this.menuitems[k];
					if (mi.size == 0) {
						if (k == this.last_elastic_k) {
							mi.cursz = this.last_standby_size;
							mi.trgsz = this.last_standby_size;
						}
						else {
							mi.cursz = this.standby_size;
							mi.trgsz = this.standby_size;
						}
					}
					else {
						mi.cursz = mi.size;
						mi.trgsz = mi.size;
					}
				}
		}

		// load menu items
		for (var k in this.menuitems) if (this.menuitems.hasOwnProperty(k)) {
			var mi = this.menuitems[k];

			mi.curspeed = 0;

			mi.outer_obj = document.createElement('div');
			this.host_obj.appendChild(mi.outer_obj);

				mi.outer_obj.style.overflow = 'hidden';

				if (this.hor) {
					mi.outer_obj.style.cssFloat = 'left';
					mi.outer_obj.style.styleFloat = 'left';
					mi.outer_obj.style.width = mi.cursz + 'px';
					mi.outer_obj.style.height = this.host_obj.offsetHeight + 'px';
				}
				else {
					mi.outer_obj.style.width = this.host_obj.offsetWidth + 'px';
					mi.outer_obj.style.height = mi.cursz + 'px';
				}

				mi.outer_obj.smenu_iname = this.iname;
				mi.outer_obj.smenu_mik = k;

				if (mi.link != '' && mi.linktype >= 0)
					mi.outer_obj.style.cursor = 'pointer';

				if (mi.id != '')
					mi.outer_obj.id = mi.id;

				mi.outer_obj.className = mi.outer_class_norm;

				if (mi.size == 0) {
					mi.outer_obj.onmouseover = function () {
						document[this.smenu_iname].handle_mouseover(this.smenu_mik);
					}

					mi.outer_obj.onmouseout = function () {
						document[this.smenu_iname].handle_mouseout(this.smenu_mik);
					}
				}

			mi.inner_obj = document.createElement('div');
			mi.outer_obj.appendChild(mi.inner_obj);

				if (this.hor) {
					mi.inner_obj.style.width = this.large_size + 'px';
					mi.inner_obj.style.height = this.host_obj.offsetHeight + 'px';
				}
				else {
					mi.inner_obj.style.width = this.host_obj.offsetWidth + 'px';
					mi.inner_obj.style.height = this.large_size + 'px';
				}

				mi.inner_obj.className = mi.inner_class_norm;
			
				if (mi.html != '')
					mi.inner_obj.innerHTML = mi.html;
			
				if (mi.html_srcid != '') {
					var src_obj = document.getElementById(mi.html_srcid);
					if (src_obj)
						mi.inner_obj.innerHTML = src_obj.innerHTML;
				}

				if (mi.bgcolor != '')
					mi.inner_obj.style.backgroundColor = mi.bgcolor;
				
				if (mi.bgimage != '') {
					mi.inner_obj.style.backgroundImage = 'url(' + mi.bgimage + ')';

					if (mi.bgimagerepeat != '')
						mi.inner_obj.style.backgroundRepeat = mi.bgimagerepeat;
				}

			if (this.align == 1) {
				if (this.hor)
					mi.outer_obj.scrollLeft = this.large_size - mi.cursz;
				else
					mi.outer_obj.scrollTop = this.large_size - mi.cursz;
			}
		}

		if (this.movtype == 'plastic' && open_item > -1 && this.sel_permanent) {
			this.sel_k = open_item;
			var mi = this.menuitems[this.sel_k];
			mi.outer_obj.className = mi.outer_class_sel;
			mi.inner_obj.className = mi.inner_class_sel;
		}

		var obj = document.createElement('div');
		this.host_obj.appendChild(obj);
		obj.style.clear = 'both';
	}
}

Smenu.prototype.handle_mouseover = function (mik) {
	if (this.sel_k > -1) {
		this.menuitems[this.sel_k].outer_obj.className = this.menuitems[this.sel_k].outer_class_norm;
		this.menuitems[this.sel_k].inner_obj.className = this.menuitems[this.sel_k].inner_class_norm;
		this.sel_k = -1;
	}
	
	var animate = false;
	for (var k in this.menuitems) if (this.menuitems.hasOwnProperty(k)) {
		var mi = this.menuitems[k];
		
		if (mi.size == 0)
			mi.trgsz = k == mik ? this.large_size : this.small_size;

		if (mi.trgsz != mi.cursz)
			animate = true;
	}

	this.correction_k = mik;
	this.sel_k = mik;
	this.menuitems[this.sel_k].outer_obj.className = this.menuitems[this.sel_k].outer_class_sel;
	this.menuitems[this.sel_k].inner_obj.className = this.menuitems[this.sel_k].inner_class_sel;

	if (animate && this.itv == 0)
		this.itv = setTimeout('document["' + this.iname + '"].rhythm();', this.interval);
}

Smenu.prototype.handle_mouseout = function (mik) {
	if (!this.sel_permanent && this.sel_k > -1) {
		this.menuitems[this.sel_k].outer_obj.className = this.menuitems[this.sel_k].outer_class_norm;
		this.menuitems[this.sel_k].inner_obj.className = this.menuitems[this.sel_k].inner_class_norm;
		this.sel_k = -1;
	}

	if (this.movtype == 'elastic') {
		var animate = false;
		for (var k in this.menuitems) if (this.menuitems.hasOwnProperty(k)) {
			var mi = this.menuitems[k];

			if (mi.size == 0) {
				if (k == this.last_elastic_k)
					mi.trgsz = this.last_standby_size;
				else
					mi.trgsz = this.standby_size;
			}

			if (mi.trgsz != mi.cursz)
				animate = true;
		}

		if (animate && this.itv == 0)
			this.itv = setTimeout('document["' + this.iname + '"].rhythm();', this.interval);
	}
}

Smenu.prototype.rhythm = function () {
	this.itv = 0;
	var animate = false;
	var rsp, total = 0;
	for (var k in this.menuitems) if (this.menuitems.hasOwnProperty(k)) {
		var mi = this.menuitems[k];
		if (mi.trgsz != mi.cursz) {
			mi.prvsz = mi.cursz;

			switch (this.anitype) {
				case 'fastslow':
					rsp = Smenu_rhythm_fastslow(mi.cursz, mi.trgsz, mi.curspeed, this.speed, this.minstep, this.maxstep);
					break;

				case 'slowfast':
					rsp = Smenu_rhythm_slowfast(mi.cursz, mi.trgsz, mi.curspeed, this.speed, this.minstep, this.maxstep);
					break;

				case 'static':
				default:
					rsp = Smenu_rhythm_static(mi.cursz, mi.trgsz, mi.curspeed, this.speed, this.minstep, this.maxstep);
			}

			mi.cursz = rsp.new_size;
			mi.curspeed = rsp.new_speed;

			if (rsp.animate)
				animate = true;
		}

		total += mi.cursz;
	}

	var diff = this.size - total;
	if (diff != 0 && this.correction_k > -1)
		this.menuitems[this.correction_k].cursz += diff;

	for (var k in this.menuitems) if (this.menuitems.hasOwnProperty(k)) {
		var mi = this.menuitems[k];
		if (mi.prvsz != mi.cursz) {
			if (mi.cursz <= 0) {
				mi.outer_obj.style.display = 'none';
			}
			else {
				if (mi.prvsz <= 0)
					mi.outer_obj.style.display = 'block';

				if (this.hor) {
					mi.outer_obj.style.width = mi.cursz + 'px';
				}
				else {
					mi.outer_obj.style.height = mi.cursz + 'px';
				}
			}
		}
	}

	if (this.align == 1) {
		for (var k in this.menuitems) if (this.menuitems.hasOwnProperty(k)) {
			var mi = this.menuitems[k];
			if (mi.cursz > 0) {
				if (this.hor)
					mi.outer_obj.scrollLeft = this.large_size - mi.cursz;
				else
					mi.outer_obj.scrollTop = this.large_size - mi.cursz;
			}
		}
	}

	if (animate && this.itv == 0)
		this.itv = setTimeout('document["' + this.iname + '"].rhythm();', this.interval);
}


function Smenu_rhythm_static(cursz, trgsz, curspeed, speed, minstep, maxstep) {
	if (cursz != trgsz) {
		var diff = Math.round(speed);

		if (diff < 1)
			diff = 1;

		if (minstep > 0 && diff < minstep)
			diff = minstep;

		if (maxstep > 0 && diff > maxstep)
			diff = maxstep;

		if (cursz < trgsz) {
			cursz += diff;
			if (cursz > trgsz)
				cursz = trgsz;
		}
		else {
			cursz -= diff;
			if (cursz < trgsz)
				cursz = trgsz;
		}
	}

	return {
		new_size: cursz,
		new_speed: curspeed,
		animate: cursz != trgsz
	}
}

function Smenu_rhythm_fastslow(cursz, trgsz, curspeed, speed, minstep, maxstep) {
	if (cursz != trgsz) {
		var diff = Math.floor(Math.abs(trgsz - cursz) * speed / 100);

		if (diff < 1)
			diff = 1;

		if (minstep > 0 && diff < minstep)
			diff = minstep;

		if (maxstep > 0 && diff > maxstep)
			diff = maxstep;

		if (cursz < trgsz) {
			cursz += diff;
			if (cursz > trgsz)
				cursz = trgsz;
		}
		else {
			cursz -= diff;
			if (cursz < trgsz)
				cursz = trgsz;
		}
	}

	return {
		new_size: cursz,
		new_speed: curspeed,
		animate: cursz != trgsz
	}
}

function Smenu_rhythm_slowfast(cursz, trgsz, curspeed, speed, minstep, maxstep) {
	if (cursz != trgsz) {
		curspeed += speed;
		var diff = Math.floor(curspeed);

		if (diff < 1)
			diff = 1;

		if (minstep > 0 && diff < minstep)
			diff = minstep;

		if (maxstep > 0 && diff > maxstep)
			diff = maxstep;

		if (cursz < trgsz) {
			cursz += diff;
			if (cursz > trgsz)
				cursz = trgsz;
		}
		else {
			cursz -= diff;
			if (cursz < trgsz)
				cursz = trgsz;
		}

		if (cursz < 0)
			cursz = 0;

		if (cursz == trgsz)
			curspeed = 0;
	}

	return {
		new_size: cursz,
		new_speed: curspeed,
		animate: cursz != trgsz
	}
}

