function showWindow(url, focusHere, height, width, title) {
	window.open(url, title, "height=" + height + ",width=" + width
			+ ",resizable=yes,scrollbars=yes,status=yes");
	if (focusHere == 'true') {
		window.focus();
	}
}

var divSwap = function(element, container) {
	var div = document.getElementById(container);
	var nodeList = div.childNodes;
	var queue = Effect.Queues.get('menuScope');

	if (queue.toArray().length < 1) {
		if (Element.visible(element) == false) {
			for (i = 0; i < nodeList.length; i++) {
				if (nodeList.item(i).nodeName == "DIV"
						&& nodeList.item(i).id != element) {
					if (Element.visible(nodeList.item(i)) == true) {
						Effect.SlideUp(nodeList.item(i), {
							queue : {
								position : 'end',
								scope : 'menuScope',
								limit : 2
							}
						})
					}
				}
			}
			Effect.SlideDown(element, {
				queue : {
					position : 'end',
					scope : 'menuScope',
					limit : 2
				}
			})
		}
	}
}

/**
 * Utility functions and classes (C)2006 elab
 */

is_ie = !!(window.attachEvent && !window.opera);

if (!Array.prototype.push) {
	Array.prototype.push = function(el) {
		this[this.length] = el;
	};
}

var WRollback = function(element, mouseOverFunction, mouseOutFunction) {
	this.element = $(element);
	this.over = mouseOverFunction;
	this.out = mouseOutFunction;
	this.element.onmouseover = mouseOverFunction;
	this.element.onmouseout = mouseOutFunction;
};
WRollback.prototype.disable = function() {
	this.element.onmouseover = null;
	this.element.onmouseout = null;
};
WRollback.prototype.enable = function() {
	this.element.onmouseover = this.over;
	this.element.onmouseout = this.out;
};

/**
 * Make a button show and hide a div. the div also hides when you click outside
 * of it if closeOnDocumentClick is true.
 * 
 * ex: new WTogglePopup('theButtonId','theContentDivId',true);
 */
var WTogglePopup = function(button, div, closeOnDocumentClick, callback) {
	this.button = $(button);
	this.div = $(div);
	this.duration = 0.2;
	this.effect = 'appear';
	this.closeOnDocumentClick = closeOnDocumentClick || false;
	this.callback = callback || function() {
	};
	this.button.onclick = this.toggle.bind(this); // Element.observe won't
													// cancel the link click
}
WTogglePopup.prototype.toggle = function() {
	options = {
		duration : this.duration
	};

	if (this.closeOnDocumentClick) {
		options.afterFinish = function() {
			if (Element.visible(this.div)) {
				document.onclick = this.hideIfVisible.bind(this);
				this.callback(true);
			} else {
				document.onclick = null;
				this.callback(false);
			}
		}.bind(this);
	} else {
		options.afterFinish = function() {
			if (Element.visible(this.div)) {
				this.callback(true);
			} else {
				this.callback(false);
			}
		}.bind(this);
	}

	Effect.toggle(this.div, this.effect, options);
	return false;
};
WTogglePopup.prototype.hideIfVisible = function() {
	if (Element.visible(this.div)) {
		this.toggle();
	}
	return true;
};

/*
 * scraps.js
 * 
 * Various helper functions for Sitebuilder2 that are required on several pages
 * but are not included in the Prototype or Scriptaculous libraries.
 */

/*
 * Call this function within a keypress function, to cancel any default action
 * this keypress might have.
 */
cancelDefaultEvents = function(keyEvent) {
	if (keyEvent.preventDefault)
		keyEvent.preventDefault();
	keyEvent.returnValue = false;
};

/*
 * WCookie(name) - load a cookie with this name
 * WCookie(name,value,[hours],[path]) - create and save a cookie with this
 * name/value, optionally specifying the hours to expiry, and a path (default
 * '/')
 */
var WCookie = function(name, value, hours, path) {
	this.name = name;

	// set some defaults
	this.expires = '';
	this.path = '/';
	this.value = '';

	if (value) {
		this.value = value;
		if (hours) {
			this.hours = hours;
			this.expires = '; expires=' + WCookie
					._getGMTStringForHoursAhead(hours);
		} else {
			this.expires = '';
		}
		if (path) {
			this.path = path;
		} else {
			this.path = '/';
		}
		this.save();
	} else {
		this.value = this.load();
	}
};

WCookie._getGMTStringForHoursAhead = function(hours) {
	var date = new Date();
	date.setTime(date.getTime() + (hours * 60 * 60 * 1000));
	return date.toGMTString();
};

WCookie.prototype.load = function() {
	var nameEQ = this.name + "=";
	var ca = document.cookie.split(';');
	for ( var i = 0; i < ca.length; i++) {
		var c = ca[i];
		while (c.charAt(0) == ' ')
			c = c.substring(1, c.length);
		if (c.indexOf(nameEQ) == 0)
			return c.substring(nameEQ.length, c.length);
	}
	return null;
};

WCookie.prototype.save = function() {
	document.cookie = this.name + '=' + this.value + this.expires + '; path='
			+ this.path;
};

WCookie.prototype.erase = function() {
	this.value = '';
	this.hours = -1;
	this.expires = '; expires=' + WCookie
			._getGMTStringForHoursAhead(this.hours);
	this.save();
};

/**
 * StringBuilder class. When appending strings repeatedly, this is MUCH faster
 * than using strings directly, ESPECIALLY in Internet Explorer.
 */
// Initializes a new instance of the StringBuilder class
// and appends the given value if supplied
if (typeof (StringBuilder) == "undefined") {
	var StringBuilder = function(value) {
		this.strings = new Array("");
		this.append(value);
	}
	// Appends the given value to the end of this instance.
	StringBuilder.prototype.append = function(value) {
		if (value)
			this.strings.push(value);
	}
	// Clears the string buffer
	StringBuilder.prototype.clear = function() {
		this.strings.length = 1;
	}
	// Converts this instance to a String.
	StringBuilder.prototype.toString = function() {
		return this.strings.join("");
	}
}

/*
 * Use instead of encodeURIComponent() on its own because they do not take into
 * account multi-byte characters (such as Chinese symbols)
 */
String.prototype.postEncode = function() {
	var output = new StringBuilder();
	var size = this.length;
	for ( var i = 0; i < size; i++) {
		var c = this.charCodeAt(i).toString();
		if (c > 127) {
			output.append('%26%23');
			output.append(c);
			output.append('%3B');
		} else {
			output.append(encodeURIComponent(this.substr(i, 1)));
		}
	}
	return output.toString();
};

/*
 * Similar to postEncode but creates plain HTML entities, rather than URL
 * encoded HTML entities.
 */
String.prototype.characterEscape = function() {
	var output = new StringBuilder();
	var size = this.length;
	for ( var i = 0; i < size; i++) {
		var c = this.charCodeAt(i).toString();
		if (c > 127) {
			output.append('&#');
			output.append(c);
			output.append(';');
		} else {
			output.append(this.substr(i, 1));
		}
	}
	return output.toString();
};

/*
 * Removes leading and trailing whitespace from a string
 */
String.prototype.trim = function() {
	return this.replace(/^\s\s*/, '').replace(/\s\s*$/, '');
}

/*
 * Extensions to the Prototype library to serialise a form using
 * String.postEncode() as specified above
 */
var WForm = {

	postEncode : function(form) {
		var elements = Form.getElements($(form));
		var queryComponents = new Array();

		for ( var i = 0; i < elements.length; i++) {
			var queryComponent = WForm.Element.postEncode(elements[i]);
			if (queryComponent)
				queryComponents.push(queryComponent);
		}

		return queryComponents.join('&');
	},

	Element : {
		postEncode : function(element) {
			element = $(element);
			var method = element.tagName.toLowerCase();
			var parameter = Form.Element.Serializers[method](element);
			var key = element.name.postEncode();

			var values = parameter.constructor != Array ? [ parameter ]
					: parameter;

			return values.map(function(value) {
				return key + '=' + value.postEncode();
			}).join('&');
		}
	}
};

// Global Ajax responder used by Ajax.MultiComplete class below.
Ajax.Responders.register( {
	onCreate : function(request) {
		if (request.options.multiComplete) {
			request.options.multiComplete.add(request);
		}
	},
	onComplete : function(request) {
		if (request.options.multiComplete) {
			request.options.multiComplete.done(request);
		}
	}
});

/*
 * Track a collection of AJAX requests, triggering callbacks when all are
 * complete.
 * 
 * onComplete will always fire. Then onSuccess will fire if ALL were successful,
 * otherwise onFailure will fire.
 * 
 * c = new Ajax.MultiCompleter({onComplete: function(){ alert("tada") }}; new
 * Ajax.Request(url, { multiComplete : c }); new Ajax.Request(url2, {
 * multiComplete : c }); new Ajax.Request(url3, { multiComplete : c });
 * c.finishedAdding(); //necessary otherwise it will never fire. // "tada" will
 * be shown only when all three are complete.
 */
Ajax.MultiCompleter = function(opts) {
	var n = Prototype.emptyFunction;
	this.onComplete = opts.onComplete || n;
	this.onSuccess = opts.onSuccess || n;
	this.onFailure = opts.onFailure || n;
	this.onLoading = opts.onLoading || n;
	this.reset();
	this.loaded = false;
	this.loading = false;
}
Ajax.MultiCompleter.prototype = {
	add : function(r) {
		this.tasks.push(r);
		if (!this.loading)
			this.onLoading();
	},
	done : function(r) {
		this.numberFinished++;
		if (this.allAdded) {
			this._checkFinished();
		}
	},
	finishedAdding : function() {
		this.allAdded = true;
		this._checkFinished();
	},
	_checkFinished : function() {
		if (this.numberFinished >= this.tasks.length) {
			this.loaded = true;
			this.loading = false;
			this.onComplete();
			var failed = false;
			$A(this.tasks).each(function(t) {
				if (t.transport.status < 200 || t.transport.status >= 300) {
					failed = true;
					throw $break;
				}
			})
			if (failed) {
				this.onFailure();
			} else {
				this.onSuccess();
			}
			this.reset();
		}
	},
	reset : function() {
		this.tasks = [];
		this.numberFinished = 0;
		this.allAdded = false;
		this.fired = false;
	},
	onComplete : function() {
	},
	onSuccess : function() {
	},
	onFailure : function() {
	}
};

// Track AJAX requests so we can cancel 'old' ones.
Ajax.currentRequests = {};
Ajax.Responders
		.register( {
			onCreate : function(request) {
				if (request.options.onlyLatestOfClass
						&& Ajax.currentRequests[request.options.onlyLatestOfClass]) {
					// if a request of this class is already in progress,
					// attempt to abort it before launching this new request
					try {
						Ajax.currentRequests[request.options.onlyLatestOfClass].transport
								.abort();
					} catch (e) {
					}
				}
				// keep note of this request object so we can cancel it if
				// superceded
				Ajax.currentRequests[request.options.onlyLatestOfClass] = request;
			},
			onComplete : function(request) {
				if (request.options.onlyLatestOfClass) {
					// remove the request from our cache once completed so it
					// can be garbage collected
			Ajax.currentRequests[request.options.onlyLatestOfClass] = null;
		}
	}
		});

Ajax.Responders.register( {
	onException : function(r, e) {
		if (window.console)
			console.error(e);
	}
});

// Backward compatibility
var addEvent = function(obj, type, fn) {
	Event.observe(obj, type, fn)
}

var sbrToAbsoluteUrl = function(relativeUrl) {
	var absoluteUrl = relativeUrl;
	if (absoluteUrl.indexOf(':') < 0) {
		var path = '' + window.location.href;
		var bases = document.getElementsByTagName('base');
		if (bases.length > 0) {
			path = bases[0].href;
		}
		if (absoluteUrl.indexOf('/') === 0) {
			absoluteUrl = absoluteUrl.substring(1);
			path = path.substring(0, path.indexOf('/', 7));
		}
		if (path.charAt(path.length - 1) != '/') {
			path += '/';
		}
		absoluteUrl = path + absoluteUrl;
	}
	return absoluteUrl;
};

Object.extend(Event, {
	onDOMReady : function(f) {
		if (document.loaded) {
			// Woah, woah, dom:loaded has already happened! Just call the
			// function now.
		f.call();
	} else {
		document.observe("dom:loaded", f);
	}
}
});
