/*--- Utility functions -----------------------------------------------------*/
// see http://simon.incutio.com/archive/2004/05/26/addLoadEvent

function addLoadEvent(func) {
  var oldonload = window.onload;
  if (typeof window.onload != 'function') {
    window.onload = func;
  } else {
    window.onload = function() {
      oldonload();
      func();
    }
  }
}

function findPosX(obj) {
	var curleft = 0;
	if (obj.offsetParent)
	{
		while (obj.offsetParent)
		{
			curleft += obj.offsetLeft
			obj = obj.offsetParent;
		}
	}
	else if (obj.x)
		curleft += obj.x;
	return curleft;
}

function findPosY(obj)
{
	var curtop = 0;
	if (obj.offsetParent)
	{
		while (obj.offsetParent)
		{
			curtop += obj.offsetTop
			obj = obj.offsetParent;
		}
	}
	else if (obj.y)
		curtop += obj.y;
	return curtop;
}

function mozContains(parent, child) {
	var found = false;
	if (parent == child) return true;

	for (var i = 0; i < parent.childNodes.length; i++) {
		found = mozContains(parent.childNodes[i], child);
		if (found) return found;
	}
	return found;
}

/*--- Menu objects ----------------------------------------------------------*/

/**
*	Menu object.
*/
function Menu() {
	Menu._static = this;
	this.shown = null;
	this.groups = new Array();
	this.trigger = new Array();
	this.timeout = 400;
	this.offsetTop = 24;
	this.interval = 500;

	window.onresize 	= Menu._static.checkHidden;
	// track mouse position to hide menu <div>
	document.body.onmousemove = checkMousePosition;
}

/**
*	Continually checks if mouse is on menu div.
*	@param	object	Event object for Gecko browsers (automatically).
*/
function checkMousePosition(e) {
	var target = (window.event) ? (window.event.srcElement) : e.target;

	if (target.className.match(/top_nav|menu|catalog/)) {
		return;
	}

	if (Menu._static && Menu._static.shown) {
		Menu._static.shown.style.visibility = 'hidden';
	}
}

/**
*	Monitors whether mouse gets over a certain
*	area in the HTML page and hides the menu if so.
*	@access	public
*	@static
*/
Menu.checkMouseMotion = function() {
	if (Menu._static && Menu._static.shown) {
		Menu._static.checkHidden();
	}
}

Menu.prototype.addGroup = function(group) {
	this.groups[this.groups.length] = group;
	this.trigger[group.groupName] = null;
}

Menu.prototype.addTrigger = function(groupName, element) {
	this.trigger[groupName] = element;
	element.onmouseover = this.display;
}

Menu.prototype.build = function() {
	for (var i = 0; i < this.groups.length; i++) {
		this.groups[i].build();
	}
}

Menu.prototype.display = function() {
	Menu._static.show(this);
}

Menu.prototype.findGroup = function(b) {
	for (a in this.trigger) {
		if (this.trigger[a] == b) {
			return a;
		}
	}
	return false;
}

Menu.prototype.checkHidden = function() {
	if (Menu._static && Menu._static.shown) {
		Menu._static.shown.style.visibility = 'hidden';
	}
}

Menu.prototype.hide= function(e) {
	var target = (window.event) ? (window.event.toElement) : e.relatedTarget;
	var parent = Menu._static.shown;

	// don't get out if mouse is over menu/button
	if (target.className.match(/top_nav|menu/)) {
		return;
	}

	if (parent.contains && !parent.contains(target)) {
		// IE
		window.setTimeout(Menu._static.checkHidden, Menu._static.timeout);

	} else if (!mozContains(parent, target)) {
		// Gecko
		window.setTimeout(Menu._static.checkHidden, Menu._static.timeout);
	}
	// ? default hiding after say, 10 seconds?
}

Menu.prototype.show = function(elem) {
	if (this.shown) {
		this.shown.style.visibility = 'hidden';
	}

	var div = document.getElementById('menuGroup' + this.findGroup(elem));
	var x = findPosX(elem) + "px";
	var y = (findPosY(elem) + this.offsetTop) + "px";

	// don't show div if not content was in menu group
	if (div.childNodes.length != 0) {
		div.style.top = y;
		div.style.left = x;
		div.style.visibility = 'visible';
		div.onmouseout = this.hide;
	}
	this.shown = div;
}




/**
*	Menu group object
*/
function MenuGroup(groupName) {
	this.groupName = groupName;
	this.items = new Array();
	this.joining = '-1';
}

MenuGroup.prototype.addItem = function(item) {
	this.items[this.items.length] = item;
}

MenuGroup.prototype.setJoining = function(idart) {
	this.joining = idart;
}

MenuGroup.prototype.build = function() {
	var div = document.createElement('div');
	div.className = 'menuGroup';
	div.id = 'menuGroup' + this.groupName;

	// fill with items
	for (var i = 0; i < this.items.length; i++) {
		if (this.items[i].url.match(new RegExp('idart=' + this.joining))) {
			div.appendChild(this.joinItems(this.items[i], this.items[i+1]));
			i++;
		} else {
			div.appendChild(this.items[i].build());
		}
	}
	document.body.appendChild(div);
}

MenuGroup.prototype.joinItems = function(first, last) {
	var out = first.build();
	var slash = document.createTextNode(' / ');
	out.appendChild(slash);

	var out2 = last.build();
	out.appendChild(out2.getElementsByTagName('a')[0]);
	return out;
}

/**
*	MenuItem object.
*/
function MenuItem(text, url, external) {
	this.text = text;
	this.url = url;
	this.external = external;
}

MenuItem.prototype.build = function() {
	var d = document.createElement("div");
	var a = document.createElement("a");
	a.className = 'menuLink';
	a.appendChild(document.createTextNode(this.text));
	a.href = this.url;

	if (this.external) {
		a.target = '_blank';
	}

	d.className = 'menuItem';
	d.appendChild(a);
	return d;
}


/*--- Open picture detail window --------------------------------------------*/

var pictureWinCount = 0;
var pictureWindows = [];

/**
*	Opens/focuses detail windows for picture detail views.
*	@param	string	URL for image to load. Must be relative to /peters root directory!
*	@param	int		Width of window.
*	@param	int		Height of window.
*	@param	int		Inner margin of window.
*/
function openPicture(imgUrl, imgWidth, imgHeight, offset) {
	var pictureName = "picture" + pictureWinCount;
	var path = 'js/picturedetails.php?image=' + escape(imgUrl) + "&height=" + imgHeight + "&width=" + imgWidth + "&margin=" + offset;

	if (pictureWindows[pictureName] && !pictureWindows[pictureName].closed) {
		pictureWindows[pictureName].focus();

	} else {
		pictureWinCount++;
		pictureName = "picture" + pictureWinCount;
		win = window.open(
			path,
			"picture" + pictureWinCount,
			"width=" 	+ (imgWidth 	+ (2 * offset)) + "," +
			"height=" 	+ (imgHeight 	+ (2 * offset))
		);
		pictureWindows["picture" + pictureWinCount]	= win;
	}
}

/*--- Composer window stuff -------------------------------------------------*/

/**
*	Opens composer window.
*	@param	object	Reference to input field into which
*					selected composer name will be written
*/
function openComposerWindow() {

	if (window['composerWin'] && !composerWin.closed) {
		composerWin.focus();

	} else {
		composerWin = window.open(
			"front_content.php?idart=89&idcat=77",
			"",
			"height=500, width=640, scrollbars=1, resizable=yes"
		);
	}
}

/**
*	Handles click on composer links in popup window.
*/
function handleClick(link) {
	var id = link.id.replace(/composer/, '');
	var name = link.innerHTML.replace(/\(.+?\)/, '').replace(/^\s+/, '');
	opener.handleSelectedComposer(id, name);
	self.close();
}

/**
*	Makes something with the composer name/id passed back from
*	the composer window.
*/
function handleSelectedComposer(id, name) {
	document.forms['formular'].elements['search[composerId]'].value = id;
	document.forms['formular'].elements['search[composer]'].value = name;
}

// back button script
function button(location) {
	top.location = location
}

/*--- Replacing of option lists ---------------------------------------------*/

/**
*	Instrument data
*/
function InstrumentItem(id, name) {
	this.id 	= id;
	this.name	= name;

	this.toString = function() {
		return this.name;
	}
}

/**
*	This control makes the content of one designated SelectList
*	dependent on the user's selection in a separate SelectList, aka
*	a Combobox.
*	@param	mixed	Collection of objects used for replacement.
*/
function ReplaceControl(data) {
	/**
	*	A collection of replacement objects.
	*	@var	mixed	Most typically an array.
	*	@access	private
	*/
	this._data = data;

	/**
	*	The watched list whose selections replace the _into list.
	*	@var	object	SelectList object.
	*	@access	private
	*/
	this._from = null;

	/**
	*	The list to be replaced.
	*	@var	object	SelectList object.
	*	@access	private
	*/
	this._into = null;

	/**
	*	Check the selected value from watched list if it's valid.
	*	@param	string	Selected value in first list.
	*	@access	public
	*/
	this.checkSelection = function(input) {
		return ('group' + input in this._data);
	}

	/**
	*	Write a default entry for the target select list
	*	if no valid replacement objects could be found in this._data.
	*	@access	public
	*/
	this.defaultValue = function() {
		this._into.options.length = 0;
		this._into.options[0] = new Option("Alle", 0);
		this._into.options[0].selected = true;
	}

	/**
	*	Retrieves a selection of the data array to be used
	*	for the writing of new <option> elements
	*	@param	string	Selected value in first list.
	*	@access	public
	*/
	this.getReplaceData = function(id) {
		var firstOption = new Array(
			//	new first option with standard text
			{id: 0, toString: function(){ return 'Alle' } }
		);

		var data = firstOption.concat(this._data['group' + id]);
		return data;
	}

	/**
	*	Construct an <option> element.
	*	@param	mixed	Value from data array.
	*	@access	public
	*/
	this.makeOption = function(dataset) {
		return new Option(dataset, dataset.id);
	}

	/**
	*	Observe two select lists for changes.
	*	@param	object	SelectList to listen for changes.
	*	@param	object	SelectList which will be rewritten.
	*	@access	public
	*/
	this.observe = function(from, into) {
		this._from = from;
		this._into = into;
		this._from.onchange = this._handleOnChange;

		//	Make the handler method self-aware of this object
		//	by setting a reference to this to a property of
		//	the HTML element it is attached to.
		this._from._observer = this;
	}

	/**
	*	Replace the options in the targeted select list.
	*	@param	string	Selected value in first list.
	*	@access	public
	*/
	this.replaceLists = function(input) {
		var items = this.getReplaceData(input);
		this._into.length = 0;
		for (var i = 0; i < items.length; i++) {
			this._into[this._into.length] = this.makeOption(items[i]);
		}
		this._into[0].selected = true;
	}

	/**
	*	Event handler for onchange event of select list
	*	from which the other list is dependent on.
	*	@access	private
	*/
	this._handleOnChange = function() {
		var value = this.options[this.options.selectedIndex].value;

		if (this._observer.checkSelection(value)) {
			this._observer.replaceLists(value);
		} else {
			this._observer.defaultValue();
		}
	}

	this.onchange = function(selectList) {
		var value = selectList.options[selectList.options.selectedIndex].value;

		if (this.checkSelection(value)) {
			this.replaceLists(value);
		} else {
			this.defaultValue();
		}
	}
}

