/*** protos.lightbox.js ***/

/******************************************************************************
Name:    Highslide JS
Version: 3.2.7 (September 9 2007)
Author:  Torstein Hønsi
Support: http://vikjavev.no/highslide/forum
Email:   See http://vikjavev.no/megsjol

Licence:
Highslide JS is licensed under a Creative Commons Attribution-NonCommercial 2.5
License (http://creativecommons.org/licenses/by-nc/2.5/).

You are free:
	* to copy, distribute, display, and perform the work
	* to make derivative works

Under the following conditions:
	* Attribution. You must attribute the work in the manner  specified by  the
	  author or licensor.
	* Noncommercial. You may not use this work for commercial purposes.

* For  any  reuse  or  distribution, you  must make clear to others the license
  terms of this work.
* Any  of  these  conditions  can  be  waived  if  you  get permission from the 
  copyright holder.

Your fair use and other rights are in no way affected by the above.
******************************************************************************/

var hs = {

// Apply your own settings here, or override them in the html file.  
graphicsDir : 'plugins/system/protos.lightbox/',
restoreCursor : "zoomout.cur", // necessary for preload
expandSteps : 10, // number of steps in zoom. Each step lasts for duration/step milliseconds.
expandDuration : 250, // milliseconds
restoreSteps : 10,
restoreDuration : 250,
allowMultipleInstances: true,
hideThumbOnExpand : true,
captionSlideSpeed : 1, // set to 0 to disable slide in effect
outlineWhileAnimating : false, // not recommended, animation gets jaggy on slow systems.
outlineStartOffset : 3, // ends at 10
marginLeft : 10,
marginRight : 35, // leave room for scrollbars + outline
marginTop : 10,
marginBottom : 35, // leave room for scrollbars + outline
numberOfImagesToPreload : 5,
zIndexCounter : 1001, // adjust to other absolutely positioned elements
fullExpandIcon : 'fullexpand.gif',
fullExpandTitle : 'Expand to actual size',
restoreTitle : 'Click to close image, click and drag to move. Use arrow keys for next and previous.',
focusTitle : 'Click to bring to front',
loadingText : 'Loading...',
loadingTitle : 'Click to cancel',
loadingOpacity : 0.75,
showCredits : true, // you can set this to false if you want
creditsText : '',
creditsHref : '',
creditsTitle : '',
enableKeyListener : true,

// These settings can also be overridden inline for each image
anchor : 'auto', // where the image expands from
align : 'auto', // position in the client (overrides anchor)
targetX: null, // the id of a target element
targetY: null,
captionId : null,
captionTemplateId : null,
slideshowGroup : null, // defines groups for next/previous links and keystrokes
spaceForCaption : 30, // leaves space below images with captions
minWidth: 200,
minHeight: 200,
allowSizeReduction: true, // allow the image to reduce to fit client size. If false, this overrides minWidth and minHeight
outlineType : 'drop-shadow', // set null to disable outlines
wrapperClassName : null, // for enhanced css-control

		
// END OF YOUR SETTINGS


// declare internal properties
preloadTheseImages : [],
continuePreloading: true,
expandedImagesCounter : 0,
expanders : [],
overrides : [
	'anchor',
	'align',
	'targetX',
	'targetY',
	'outlineType',
	'outlineWhileAnimating',
	'spaceForCaption', 
	'wrapperClassName',
	'minWidth',
	'minHeight',
	'captionId',
	'captionTemplateId',
	'allowSizeReduction',
	'slideshowGroup'
],
overlays : [],
pendingOutlines : {},
clones : {},
faders : [],
ie : (document.all && !window.opera),
safari : navigator.userAgent.indexOf("Safari") != -1,
hasFocused : false,

$ : function (id) {
	return document.getElementById(id);
},

push : function (arr, val) {
	arr[arr.length] = val;
},

createElement : function (tag, attribs, styles, parent, nopad) {
	var el = document.createElement(tag);
	if (attribs) hs.setAttribs(el, attribs);
	if (nopad) hs.setStyles(el, {padding: 0, border: 'none', margin: 0});
	if (styles) hs.setStyles(el, styles);
	if (parent) parent.appendChild(el);	
	return el;
},

setAttribs : function (el, attribs) {
	for (var x in attribs) {
		el[x] = attribs[x];
	}
},

setStyles : function (el, styles) {
	for (var x in styles) {
		try { 
			if (hs.ie && x == 'opacity') el.style.filter = 'alpha(opacity='+ (styles[x] * 100) +')';
			else el.style[x] = styles[x]; 
		}
		catch (e) {}
	}
},

ieVersion : function () {
	arr = navigator.appVersion.split("MSIE");
	return parseFloat(arr[1]);
},

clientInfo : function ()	{
	var iebody = document.compatMode && document.compatMode != "BackCompat" 
		? document.documentElement : document.body;
	
	this.width = hs.ie ? iebody.clientWidth : self.innerWidth;
	this.height = hs.ie ? iebody.clientHeight : self.innerHeight;
	this.scrollLeft = hs.ie ? iebody.scrollLeft : pageXOffset;
	this.scrollTop = hs.ie ? iebody.scrollTop : pageYOffset;
} ,

position : function(el)	{ 
	var parent = el;	
	var p = { x: parent.offsetLeft, y: parent.offsetTop };
	while (parent.offsetParent)	{
		parent = parent.offsetParent;
		p.x += parent.offsetLeft;
		p.y += parent.offsetTop;
		if (parent != document.body && parent != document.documentElement) {
			p.x -= parent.scrollLeft;
			p.y -= parent.scrollTop;
		}
	}
	return p;
},

expand : function(a, params, custom) {
	try {
		new HsExpander(a, params, custom);
		return false;		
	} catch (e) { return true; }	
},

focusTopmost : function() {
	var topZ = 0, topmostKey = -1;
	for (i = 0; i < hs.expanders.length; i++) {
		if (hs.expanders[i]) {
			if (hs.expanders[i].wrapper.style.zIndex && hs.expanders[i].wrapper.style.zIndex > topZ) {
				topZ = hs.expanders[i].wrapper.style.zIndex;
				
				topmostKey = i;
			}
		}
	}
	if (topmostKey == -1) hs.focusKey = -1;
	else hs.expanders[topmostKey].focus();
},

closeId : function(id) { // for text links
	return hs.close(id);
},

close : function(el) {
	try { hs.getExpander(el).doClose(); } catch (e) {}
	return false;
},

getAdjacentAnchor : function(key, op) {
	var aAr = document.getElementsByTagName('A'), hsAr = {}, activeI = -1, j = 0;
	for (i = 0; i < aAr.length; i++) {
		if (hs.isHsAnchor(aAr[i]) && ((hs.expanders[key].slideshowGroup == hs.getParam(aAr[i], 'slideshowGroup')))) {
			hsAr[j] = aAr[i];
			if (hs.expanders[key] && aAr[i] == hs.expanders[key].a) {
				activeI = j;
			}
			j++;
		}
	}
	return hsAr[activeI + op];
},

getParam : function (a, param) {
	try {
		var s = a.onclick.toString().replace(/\s/g, ' ').split('{')[2].split('}')[0];
		if (hs.safari) { // stupid bug
			for (var i = 0; i < hs.overrides.length; i++) {
				s = s.replace(hs.overrides[i] +':', ','+ hs.overrides[i] +':').replace(new RegExp("^\\s*?,"), '');
			}
		}
		eval('var arr = {'+ s +'};');
		if (arr[param]) return arr[param];
		else return hs[param];
	} catch (e) {
		return hs[param];
	}
},

getSrc : function (a) {
	var src = hs.getParam(a, 'src');
	if (src) return src;
	return a.rel.replace(/_slash_/g, '/') || a.href;
},

getNode : function (id) {
	var node = hs.$(id), clone = hs.clones[id], a = {};
	if (!node && !clone) return null;
	if (!clone) {
		clone = node.cloneNode(true);
		clone.id = '';
		hs.clones[id] = clone;
		return node;
	} else {
		return clone.cloneNode(true);
	}
},

purge : function(d) {
	if (!hs.ie) return;
	var a = d.attributes, i, l, n;
    if (a) {
        l = a.length;
        for (i = 0; i < l; i += 1) {
            n = a[i].name;
            if (typeof d[n] === 'function') {
                d[n] = null;
            }
        }
    }
    if (hs.geckoBug && hs.geckoBug(d)) return;
	a = d.childNodes;
    if (a) {
        l = a.length;
        for (i = 0; i < l; i += 1) {
            hs.purge(d.childNodes[i]);
        }
    }
},

previousOrNext : function (el, op) {
	var exp = hs.getExpander(el);	
	try { hs.getAdjacentAnchor(exp.key, op).onclick(); } catch (e) {}
	try { exp.doClose(); } catch (e) {}	
	return false;
},

previous : function (el) {
	return hs.previousOrNext(el, -1);
},

next : function (el) {
	return hs.previousOrNext(el, 1);	
},

keyHandler : function(e) {
	if (!e) e = window.event;
	if (!e.target) e.target = e.srcElement; // ie
	if (e.target.form) return; // form element has focus
	
	var op = null;
	switch (e.keyCode) {
		case 34: // Page Down
		case 39: // Arrow right
		case 40: // Arrow down
			op = 1;
			break;
		case 33: // Page Up
		case 37: // Arrow left
		case 38: // Arrow up
			op = -1;
			break;
		case 27: // Escape
		case 13: // Enter
			op = 0;
	}
	if (op !== null) {
		hs.removeEventListener(document, 'keydown', hs.keyHandler);
		try { if (!hs.enableKeyListener) return true; } catch (e) {}
		
		if (e.preventDefault) e.preventDefault();
    	else e.returnValue = false;
		if (op == 0) {
			try { hs.getExpander().doClose(); } catch (e) {}
			return false;
		} else {
			return hs.previousOrNext(hs.focusKey, op);
		}
	} else return true;
},

registerOverlay : function (overlay) {
	hs.push(hs.overlays, overlay);
},

getWrapperKey : function (element) {
	var el, re = /^highslide-wrapper-([0-9]+)$/;
	// 1. look in open expanders
	el = element;
	while (el.parentNode)	{
		el = el.parentNode;
		if (el.id && el.id.match(re)) return el.id.replace(re, "$1");
	}
	// 2. look in thumbnail
	el = element;
	while (el.parentNode)	{
		if (el.tagName && hs.isHsAnchor(el)) {
			for (key = 0; key < hs.expanders.length; key++) {
				exp = hs.expanders[key];
				if (exp && exp.a == el) return key;
			}
		}
		el = el.parentNode;
	}
},

getExpander : function (el) {
	try {
		if (!el) return hs.expanders[hs.focusKey];
		if (typeof el == 'number') return hs.expanders[el];
		if (typeof el == 'string') el = hs.$(el);
		return hs.expanders[hs.getWrapperKey(el)];
	} catch (e) {}
},

cleanUp : function () {
	for (i = 0; i < hs.expanders.length; i++) {
		if (hs.expanders[i] && hs.expanders[i].isExpanded) hs.focusTopmost();
	}
},

mouseClickHandler : function(e) 
{	
	if (!e) e = window.event;
	if (e.button > 1) return true;
	if (!e.target) e.target = e.srcElement;
	if (e.target.form) return;
	
	var fobj = e.target;
	while (fobj.parentNode
		&& !(fobj.className && fobj.className.match(/highslide-(image|move|html)/)))
	{
		fobj = fobj.parentNode;
	}

	if (!fobj.parentNode) return;
	
	hs.dragExp = hs.getExpander(fobj);
	
	if (fobj.className.match(/highslide-(image|move)/)) {
		var isDraggable = true;
		var wLeft = parseInt(hs.dragExp.wrapper.style.left);
		var wTop = parseInt(hs.dragExp.wrapper.style.top);			
	}

	if (e.type == 'mousedown') {
		if (isDraggable) // drag or focus
		{
			if (fobj.className.match('highslide-image')) hs.dragExp.content.style.cursor = 'move';
			
			hs.wLeft = wLeft;
			hs.wTop = wTop;
			
			hs.dragX = e.clientX;
			hs.dragY = e.clientY;
			hs.addEventListener(document, 'mousemove', hs.mouseMoveHandler);
			if (e.preventDefault) e.preventDefault(); // FF
			
			if (hs.dragExp.content.className.match(/highslide-(image|html)-blur/)) {
				hs.dragExp.focus();
				hs.hasFocused = true;
			}
			return false;
		}
		else if (fobj.className.match(/highslide-html/)) { // just focus
			hs.dragExp.focus();
			hs.dragExp.redoShowHide();
			hs.hasFocused = false; // why??
		}
		
	} else if (e.type == 'mouseup') {
		hs.removeEventListener(document, 'mousemove', hs.mouseMoveHandler);
		if (isDraggable && hs.dragExp) {
			if (fobj.className.match('highslide-image')) {
				fobj.style.cursor = hs.styleRestoreCursor;
			}
			var hasMoved = wLeft != hs.wLeft || wTop != hs.wTop;
			if (!hasMoved && !hs.hasFocused && !fobj.className.match(/highslide-move/)) {
				hs.dragExp.onClick();
			} else if (hasMoved || (!hasMoved && hs.hasHtmlexpanders)) {
				hs.dragExp.redoShowHide();
			}
			hs.hasFocused = false;
		
		} else if (fobj.className.match('highslide-image-blur')) {
			fobj.style.cursor = hs.styleRestoreCursor;		
		}
	}
},

mouseMoveHandler : function(e)
{
	if (!hs.dragExp || !hs.dragExp.wrapper) return;
	if (!e) e = window.event;

	hs.dragExp.x.min = hs.wLeft + e.clientX - hs.dragX;
	hs.dragExp.y.min = hs.wTop + e.clientY - hs.dragY;
	
	var w = hs.dragExp.wrapper;
	
	w.style.left = hs.dragExp.x.min +'px';
	w.style.top  = hs.dragExp.y.min +'px';
	
	if (hs.dragExp.objOutline) {
		var o = hs.dragExp.objOutline;
		o.table.style.left = (hs.dragExp.x.min - o.offset) +'px';
		o.table.style.top = (hs.dragExp.y.min - o.offset) +'px';
	}	
	return false;
},

addEventListener : function (el, event, func) {
	try {
		el.addEventListener(event, func, false);
	} catch (e) {
		try {
			el.detachEvent('on'+ event, func);
			el.attachEvent('on'+ event, func);
		} catch (e) {
			el['on'+ event] = func;
		}
	} 
},

removeEventListener : function (el, event, func) {
	try {
		el.removeEventListener(event, func, false);
	} catch (e) {
		try {
			el.detachEvent('on'+ event, func);
		} catch (e) {
			el['on'+ event] = null;
		}
	}
},

isHsAnchor : function (a) {
	return (a.onclick && a.onclick.toString().replace(/\s/g, ' ').match(/hs.(htmlE|e)xpand/));
},

preloadFullImage : function (i) {
	if (hs.continuePreloading && hs.preloadTheseImages[i] && hs.preloadTheseImages[i] != 'undefined') {
		var img = document.createElement('img');
		img.onload = function() { hs.preloadFullImage(i + 1); };
		img.src = hs.preloadTheseImages[i];
	}
},

preloadImages : function (number) {
	if (number && typeof number != 'object') hs.numberOfImagesToPreload = number;
	var re, j = 0;
	
	var aTags = document.getElementsByTagName('A');
	for (i = 0; i < aTags.length; i++) {
		a = aTags[i];
		re = hs.isHsAnchor(a);
		if (re && re[0] == 'hs.expand') {
			if (j < hs.numberOfImagesToPreload) {
				hs.preloadTheseImages[j] = hs.getSrc(a); 
				j++;
			}
		}
	}
	
	// preload outlines
	new HsOutline(hs.outlineType, function () { hs.preloadFullImage(0)} );
	
	// preload cursor
	var cur = hs.createElement('img', { src: hs.graphicsDir + hs.restoreCursor });
},

genContainer : function () {
	if (!hs.container) {
		hs.container = hs.createElement('div', 
			null, 
			{ position: 'absolute', left: 0, top: 0, width: '100%', zIndex: hs.zIndexCounter }, 
			document.body,
			true
		);
	}	
},

fade : function (el, o, oFinal, dir, i) {
	o = parseFloat(o);
	el.style.visibility = (o <= 0) ? 'hidden' : 'visible';
	if (o < 0 || (dir == 1 && o > oFinal)) return;
	if (i == null) i = hs.faders.length;
	if (typeof(el.i) != 'undefined' && el.i != i) {
		clearTimeout(hs.faders[el.i]);
		o = el.tempOpacity;
	}
	el.i = i;
	el.tempOpacity = o;
	el.style.visibility = (o <= 0) ? 'hidden' : 'visible';
	hs.setStyles(el, { opacity: o });
	hs.faders[i] = setTimeout(function() { 
			hs.fade(el, Math.round((o + 0.1 * dir)*100)/100, oFinal, dir, i);
	 	}, 25);
}
}; // end hs object

//-----------------------------------------------------------------------------
HsOutline = function (outlineType, onLoad) {
	this.onLoad = onLoad;
	this.outlineType = outlineType;
	var v = hs.ieVersion(), tr;
	
	this.hasAlphaImageLoader = hs.ie && v >= 5.5 && v < 7;
	this.hasPngSupport = !hs.ie || (hs.ie && v >= 7);
	if (!outlineType || (!this.hasAlphaImageLoader && !this.hasPngSupport)) {
		if (onLoad) onLoad();
		return;
	}
	
	hs.genContainer();
	this.table = hs.createElement(
		'table',
		{	
			cellSpacing: 0 // saf
		},
		{
			visibility: 'hidden',
			position: 'absolute',
			zIndex: hs.zIndexCounter++,
			borderCollapse: 'collapse'
		},
		hs.container,
		true
	);
	this.tbody = hs.createElement('tbody', null, null, this.table);
	
	this.td = Array();
	for (var i = 0; i <= 8; i++) {
		if (i % 3 == 0) tr = hs.createElement('tr', null, null, this.tbody, true);
		this.td[i] = hs.createElement('td', null, null, tr, true);
		var style = i != 4 ? { lineHeight: 0, fontSize: 0} : { position : 'relative' };
		hs.setStyles(this.td[i], style);
	}
	this.td[4].className = outlineType;
	
	this.preloadGraphic(); 
};

HsOutline.prototype.preloadGraphic = function () {	
	var src = hs.graphicsDir + "outlines/"+ this.outlineType +".png";
				
	var appendTo = hs.safari ? hs.container : null;
	this.graphic = hs.createElement('img', null, { position: 'absolute', left: '-9999px', 
		top: '-9999px' }, appendTo, true); // for onload trigger
	
	var pThis = this;
	this.graphic.onload = function() { pThis.onGraphicLoad(); };
	
	this.graphic.src = src;
};

HsOutline.prototype.onGraphicLoad = function () {
	var o = this.offset = this.graphic.width / 4;
	var pos = [[0,0],[0,-4],[-2,0],[0,-8],0,[-2,-8],[0,-2],[0,-6],[-2,-2]];
	for (var i = 0; i <= 8; i++) {
		if (pos[i]) {
			if (this.hasAlphaImageLoader) {
				var w = (i == 1 || i == 7) ? '100%' : this.graphic.width +'px';
				var div = hs.createElement('div', null, { width: '100%', height: '100%', position: 'relative', overflow: 'hidden'}, this.td[i], true);
				hs.createElement ('div', null, { 
						filter: "progid:DXImageTransform.Microsoft.AlphaImageLoader(sizingMethod=scale, src='"+ this.graphic.src + "')", 
						position: 'absolute',
						width: w, 
						height: this.graphic.height +'px',
						left: (pos[i][0]*o)+'px',
						top: (pos[i][1]*o)+'px'
					}, 
				div,
				true);
			} else {
				hs.setStyles(this.td[i], { background: 'url('+ this.graphic.src +') '+ (pos[i][0]*o)+'px '+(pos[i][1]*o)+'px'});
			}
			
			// common
			var dim = 2 * o;
			hs.setStyles (this.td[i], { height: dim +'px', width: dim +'px' } );
		}
	}
	
	hs.pendingOutlines[this.outlineType] = this;
	if (this.onLoad) this.onLoad();
};

HsOutline.prototype.destroy = function() {
	hs.purge(this.table);
	try { this.table.parentNode.removeChild(this.table); } catch (e) {}
};

//-----------------------------------------------------------------------------
// The expander object
HsExpander = function(a, params, custom, contentType) {
	hs.continuePreloading = false;
		
	this.custom = custom;
	// override inline parameters
	for (i = 0; i < hs.overrides.length; i++) {
		var name = hs.overrides[i];
		if (params && typeof params[name] != 'undefined') this[name] = params[name];
		else this[name] = hs[name];
	}
	
	// get thumb
	var el;
	if (params && params.thumbnailId) el = hs.$(params.thumbnailId);
	else el = a.getElementsByTagName('IMG')[0];
	if (!el) el = a;
	
	// cancel other
	for (i = 0; i < hs.expanders.length; i++) {
		if (hs.expanders[i] && hs.expanders[i].thumb != el && !hs.expanders[i].onLoadStarted) {
			hs.expanders[i].cancelLoading();
		}
	}
	// check if already open
	for (i = 0; i < hs.expanders.length; i++) {
		if (hs.expanders[i] && hs.expanders[i].a == a) {
			hs.expanders[i].focus();
			return false;
		}		
	}

	if (!hs.allowMultipleInstances) {
		try { hs.expanders[hs.expandedImagesCounter - 1].doClose(); } catch (e){}
	}
	
	var key = this.key = hs.expandedImagesCounter++;
	hs.expanders[this.key] = this;
	if (contentType == 'html') {
		this.isHtml = true;
		this.contentType = 'html';
	} else {
		this.isImage = true;
		this.contentType = 'image';
	}
	this.a = a;
	
	this.thumbsUserSetId = el.id || a.id;
	this.thumb = el;		
	
	this.overlays = [];

	var pos = hs.position(el); 
	
	// instanciate the wrapper
	this.wrapper = hs.createElement(
		'div',
		{
			id: 'highslide-wrapper-'+ this.key,
			className: this.wrapperClassName
		},
		{
			visibility: 'hidden',
			position: 'absolute',
			zIndex: hs.zIndexCounter++
		}, null, true );
	this.wrapper.onmouseover = function (e) { 
    	try { hs.expanders[key].onMouseOver(); } catch (e) {} 
    };
    this.wrapper.onmouseout = function (e) { 
    	try { hs.expanders[key].onMouseOut(); } catch (e) {}
	};
	
	// store properties of thumbnail
	this.thumbWidth = el.width ? el.width : el.offsetWidth;		
	this.thumbHeight = el.height ? el.height : el.offsetHeight;
	this.thumbLeft = pos.x;
	this.thumbTop = pos.y;
	
	// thumb borders
	this.thumbOffsetBorderW = (this.thumb.offsetWidth - this.thumbWidth) / 2;
	this.thumbOffsetBorderH = (this.thumb.offsetHeight - this.thumbHeight) / 2;
	
	// get the wrapper
	hs.genContainer();
	if (hs.pendingOutlines[this.outlineType]) {
		this.connectOutline();
		this[this.contentType +'Create']();
	} else if (!this.outlineType) {
		this[this.contentType +'Create']();
	} else {
		this.displayLoading();
		var pThis = this;
		new HsOutline(this.outlineType, 
			function () { 
				pThis.connectOutline();
				pThis[pThis.contentType +'Create']();
			} 
		);
	}
	
};

HsExpander.prototype.connectOutline = function(x, y) {	
	var w = hs.pendingOutlines[this.outlineType];
	this.objOutline = w;
	hs.pendingOutlines[this.outlineType] = null;
};

HsExpander.prototype.displayLoading = function() {
	if (this.onLoadStarted || this.loading) return;
		
	this.originalCursor = this.a.style.cursor;
	this.a.style.cursor = 'wait';
	
	if (!hs.loading) {
		hs.loading = hs.createElement('a',
			{
				className: 'highslide-loading',
				title: hs.loadingTitle,
				innerHTML: hs.loadingText
			},
			{
				position: 'absolute',
				opacity: hs.loadingOpacity
			}, hs.container
		);
	}
	
	this.loading = hs.loading;
	this.loading.href = 'javascript:hs.expanders['+ this.key +'].cancelLoading()';
	this.loading.visibility = 'visible';		
	
	this.loading.style.left = (this.thumbLeft + this.thumbOffsetBorderW 
		+ (this.thumbWidth - this.loading.offsetWidth) / 2) +'px';
	this.loading.style.top = (this.thumbTop 
		+ (this.thumbHeight - this.loading.offsetHeight) / 2) +'px';
	setTimeout(
		"if (hs.expanders["+ this.key +"] && hs.expanders["+ this.key +"].loading) "
		+ "hs.expanders["+ this.key +"].loading.style.visibility = 'visible';", 
		100
	);
};

HsExpander.prototype.imageCreate = function() {
	var key = this.key;

	var img = document.createElement('img');
    this.content = img;
    img.onload = function () { try { hs.expanders[key].onLoad(); } catch (e) {} };
    img.className = 'highslide-image';
    img.style.visibility = 'hidden'; // prevent flickering in IE
    img.style.display = 'block';
	img.style.position = 'absolute';
	img.style.maxWidth = 'none';
    img.style.zIndex = 3;
    img.title = hs.restoreTitle;
    if (hs.safari) hs.container.appendChild(img);
    // uncomment this to flush img size:
    // if (hs.ie) img.src = null;
	img.src = hs.getSrc(this.a);
	
	this.displayLoading();
};

HsExpander.prototype.onLoad = function() {
	try { 
	
		if (!this.content) return;
		if (this.onLoadStarted) return; // old Gecko loop
		else this.onLoadStarted = true;
		
			   
		if (this.loading) {
			this.loading.style.visibility = 'hidden';
			this.loading = null;
			this.a.style.cursor = this.originalCursor || '';
		}
		if (this.isImage) {			
			this.newWidth = this.content.width;
			this.newHeight = this.content.height;
			this.fullExpandWidth = this.newWidth;
			this.fullExpandHeight = this.newHeight;
			
			this.content.width = this.thumbWidth;
			this.content.height = this.thumbHeight;
			
		} else if (this.htmlGetSize) this.htmlGetSize();
		
		this.marginBottom = hs.marginBottom;
		this.getCaption();
		
		this.wrapper.appendChild(this.content);
		this.content.style.position = 'relative'; // Saf
		if (this.caption) this.wrapper.appendChild(this.caption);
		this.wrapper.style.left = this.thumbLeft +'px';
		this.wrapper.style.top = this.thumbTop +'px';
		hs.container.appendChild(this.wrapper);
		
		// correct for borders
		this.offsetBorderW = (this.content.offsetWidth - this.thumbWidth) / 2;
		this.offsetBorderH = (this.content.offsetHeight - this.thumbHeight) / 2;
		var modMarginRight = hs.marginRight + 2 * this.offsetBorderW;
		this.marginBottom += 2 * this.offsetBorderH;
		
		var ratio = this.newWidth / this.newHeight;
		var minWidth = this.allowSizeReduction ? this.minWidth : this.newWidth;
		var minHeight = this.allowSizeReduction ? this.minHeight : this.newHeight;
		
		var justify = { x: 'auto', y: 'auto' };
		if (this.align == 'center') {
			justify.x = 'center';
			justify.y = 'center';
		} else {
			if (this.anchor.match(/^top/)) justify.y = null;
			if (this.anchor.match(/right$/)) justify.x = 'max';
			if (this.anchor.match(/^bottom/)) justify.y = 'max';
			if (this.anchor.match(/left$/)) justify.x = null;
		}
		
		client = new hs.clientInfo();		
		
		// justify
		this.x = { 
			min: parseInt(this.thumbLeft) - this.offsetBorderW + this.thumbOffsetBorderW,
			span: this.newWidth,
			minSpan: this.newWidth < minWidth ? this.newWidth : minWidth,
			justify: justify.x,
			target: this.targetX,
			marginMin: hs.marginLeft, 
			marginMax: modMarginRight,
			scroll: client.scrollLeft,
			clientSpan: client.width,
			thumbSpan: this.thumbWidth
		};
		var oldRight = this.x.min + parseInt(this.thumbWidth);
		this.x = this.justify(this.x);
		this.y = { 
			min: parseInt(this.thumbTop) - this.offsetBorderH + this.thumbOffsetBorderH,
			span: this.newHeight,
			minSpan: this.newHeight < minHeight ? this.newHeight : minHeight,
			justify: justify.y,
			target: this.targetY,
			marginMin: hs.marginTop, 
			marginMax: this.marginBottom, 
			scroll: client.scrollTop,
			clientSpan: client.height,
			thumbSpan: this.thumbHeight
		};
		var oldBottom = this.y.min + parseInt(this.thumbHeight);
		this.y = this.justify(this.y);
		
		if (this.isHtml) this.htmlSizeOperations();	
		if (this.isImage) this.correctRatio(ratio);

		var x = this.x;
		var y = this.y;
		
		this.show();
	} catch (e) {
		if (hs.expanders[this.key] && hs.expanders[this.key].a) 
			window.location.href = hs.getSrc(hs.expanders[this.key].a);
	}
};

HsExpander.prototype.show = function () {
	// Selectbox bug
	var imgPos = {x: this.x.min - 20, y: this.y.min - 20, w: this.x.span + 40, h: this.y.span + 40 + this.spaceForCaption};
	hs.hideSelects = (hs.ie && hs.ieVersion() < 7);
	if (hs.hideSelects) this.showHideElements('SELECT', 'hidden', imgPos);
	// Iframes bug
	hs.hideIframes = (window.opera || navigator.vendor == 'KDE' || (hs.ie && hs.ieVersion() < 5.5));
	if (hs.hideIframes) this.showHideElements('IFRAME', 'hidden', imgPos);
	
	// Make outline ready	
	if (this.objOutline && !this.outlineWhileAnimating) this.positionOutline(this.x.min, this.y.min, this.x.span, this.y.span);
	var o2 = this.objOutline ? this.objOutline.offset : 0;
	
	// Apply size change		
	this.changeSize(
		1,
		this.thumbLeft + this.thumbOffsetBorderW - this.offsetBorderW,
		this.thumbTop + this.thumbOffsetBorderH - this.offsetBorderH,
		this.thumbWidth,
		this.thumbHeight,
		this.x.min,
		this.y.min,
		this.x.span,
		this.y.span, 
		hs.expandDuration,
		hs.expandSteps,
		hs.outlineStartOffset,
		o2
	);
};

HsExpander.prototype.justify = function (p) {
	
	var tgt, dim = p == this.x ? 'x' : 'y';
	if (p.target && p.target.match(/ /)) {
		tgt = p.target.split(' ');
		p.target = tgt[0];
	}
	if (p.target && hs.$(p.target)) {
		p.min = hs.position(hs.$(p.target))[dim];
		if (tgt && tgt[1] && tgt[1].match(/^[-]?[0-9]+px$/)) p.min += parseInt(tgt[1]);
		
	} else if (p.justify == 'auto' || p.justify == 'center') {
		var hasMovedMin = false;
		var allowReduce = true;
		
		// calculate p.min
		if (p.justify == 'center') p.min = Math.round(p.scroll + (p.clientSpan - p.span - p.marginMax) / 2);
		else p.min = Math.round(p.min - ((p.span - p.thumbSpan) / 2)); // auto
		
		if (p.min < p.scroll + p.marginMin) {
			p.min = p.scroll + p.marginMin;
			hasMovedMin = true;		
		}
		
		if (p.span < p.minSpan) {
			p.span = p.minSpan;
			allowReduce = false;
		}
		// calculate right/newWidth
		if (p.min + p.span > p.scroll + p.clientSpan - p.marginMax) {
			if (hasMovedMin && allowReduce) p.span = p.clientSpan - p.marginMin - p.marginMax; // can't expand more
			else if (p.span < p.clientSpan - p.marginMin - p.marginMax) { // move newTop up
				p.min = p.scroll + p.clientSpan - p.span - p.marginMin - p.marginMax;
			} else { // image larger than client
				p.min = p.scroll + p.marginMin;
				if (allowReduce) p.span = p.clientSpan - p.marginMin - p.marginMax;
			}
			
		}
		
		if (p.span < p.minSpan) {
			p.span = p.minSpan;
			allowReduce = false;
		}
		
	} else if (p.justify == 'max') {
		p.min = Math.floor(p.min - p.span + p.thumbSpan);
	}
		
	if (p.min < p.marginMin) {
		tmpMin = p.min;
		p.min = p.marginMin; 
		if (allowReduce) p.span = p.span - (p.min - tmpMin);
	}
	return p;
};

HsExpander.prototype.correctRatio = function(ratio) {
	var x = this.x;
	var y = this.y;
	var changed = false;
	if (x.span / y.span > ratio) { // width greater
		var tmpWidth = x.span;
		x.span = y.span * ratio;
		if (x.span < x.minSpan) { // below minWidth
			x.span = x.minSpan;	
			y.span = x.span / ratio;
		}
		changed = true;
	
	} else if (x.span / y.span < ratio) { // height greater
		var tmpHeight = y.span;
		y.span = x.span / ratio;
		changed = true;
	}
	
	if (changed) {
		x.min = parseInt(this.thumbLeft) - this.offsetBorderW + this.thumbOffsetBorderW;
		x.minSpan = x.span;
		this.x = this.justify(x);
		
		y.min = parseInt(this.thumbTop) - this.offsetBorderH + this.thumbOffsetBorderH;
		y.minSpan = y.span;
		this.y = this.justify(y);
	}
};

HsExpander.prototype.changeSize = function(dir, x1, y1, w1, h1, x2, y2, w2, h2, dur, steps, oo1, oo2) {
	var dW = (w2 - w1) / steps,
	dH = (h2 - h1) / steps,
	dX = (x2 - x1) / steps,
	dY = (y2 - y1) / steps,
	dOo = (oo2 - oo1) /steps,
	t,
	exp = "hs.expanders["+ this.key +"]";
	for (i = 1; i <= steps; i++) {
		w1 += dW;
		h1 += dH;
		x1 += dX;
		y1 += dY;
		oo1 += dOo;
		t = Math.round(i * (dur / steps));
		
		var s = "try {";
		if (i == 1) {
			s += exp +".content.style.visibility = 'visible';"
				+ "if ("+ exp +".thumb.tagName == 'IMG' && hs.hideThumbOnExpand) "+ exp +".thumb.style.visibility = 'hidden';"
		}
		if (i == steps) {
			w1 = w2;
			h1 = h2;
			x1 = x2;
			y1 = y2;
			oo1 = oo2;
		}
		s += exp +"."+ this.contentType +"SetSize("+ Math.round(w1) +", "+ Math.round(h1) +", "
			+ Math.round(x1) +", "+ Math.round(y1) +", "+ Math.round(oo1);
		s += ");} catch (e) {}";
		setTimeout(s, t);
	}
	if (dir == 1) {
		setTimeout('try { '+ exp +'.objOutline.table.style.visibility = "visible"; } catch (e){}', t);
		setTimeout('try { '+ exp +'.onExpanded(); } catch(e){}', t+50);
	}
	else setTimeout('try { '+ exp +'.onEndClose(); } catch(e){}', t);
		
};

HsExpander.prototype.imageSetSize = function (w, h, x, y, offset) {
	try {
		this.content.width = w;
		this.content.height = h;
		
		if (this.objOutline && this.outlineWhileAnimating) {
			var o = this.objOutline.offset - offset;
			this.positionOutline(x + o, y + o, w - 2 * o, h - 2 * o, 1);
		}
		
		hs.setStyles ( this.wrapper,
			{
				'visibility': 'visible',
				'left': x +'px',
				'top': y +'px'
			}
		);
		
	} catch (e) { window.location.href = hs.getSrc(this.a);	}
};

HsExpander.prototype.positionOutline = function(x, y, w, h, vis) {
	if (!this.objOutline) return;
	var o = this.objOutline;
	if (vis) o.table.style.visibility = 'visible';
	o.table.style.left = (x - o.offset) +'px';
	o.table.style.top = (y - o.offset) +'px';
	o.table.style.width = (w + 2 * (this.offsetBorderW + o.offset)) +'px';
	w += 2 * (this.offsetBorderW - o.offset);
	h += + 2 * (this.offsetBorderH - o.offset);
	o.td[4].style.width = w >= 0 ? w +'px' : 0;
	o.td[4].style.height = h >= 0 ? h +'px' : 0;
	if (o.hasAlphaImageLoader) o.td[3].style.height = o.td[5].style.height = o.td[4].style.height;
};

HsExpander.prototype.onExpanded = function() {
	
	this.isExpanded = true;
	this.focus();
	if (this.isHtml && this.objectLoadTime == 'after') this.writeExtendedContent();
	this.createCustomOverlays();
	if (hs.showCredits) this.writeCredits();
	
	if (this.caption) this.writeCaption();
	
	if (this.fullExpandWidth > this.x.span) this.createFullExpand();
	if (!this.caption) this.onDisplayFinished();
};

HsExpander.prototype.onDisplayFinished = function() {
	var key = this.key;
	var outlineType = this.outlineType;
	new HsOutline(outlineType, function () { 
		try { hs.expanders[key].preloadNext();	} catch (e) {}
	});
};

HsExpander.prototype.preloadNext = function() {
	var next = hs.getAdjacentAnchor(this.key, 1);	
	if (next.onclick.toString().match(/hs\.expand/)) 
		var img = hs.createElement('img', { src: hs.getSrc(next) });
};

HsExpander.prototype.cancelLoading = function() {
	this.a.style.cursor = this.originalCursor;	
	if (this.loading) hs.loading.style.visibility = 'hidden';		
	hs.expanders[this.key] = null;
};

HsExpander.prototype.writeCredits = function () {
	var credits = hs.createElement('a',
		{
			href: hs.creditsHref,
			className: 'highslide-credits',
			innerHTML: hs.creditsText,
			title: hs.creditsTitle
		}
	);
	this.createOverlay(credits, 'top left');
};

HsExpander.prototype.getCaption = function() {
	if (!this.captionId && this.thumbsUserSetId)  this.captionId = 'caption-for-'+ this.thumbsUserSetId;
	if (this.captionId) {
		this.caption = hs.getNode(this.captionId);
	}
	if (this.captionTemplateId) {
		var s = (this.caption) ? this.caption.innerHTML : '';
		this.caption = hs.getNode(this.captionTemplateId);
		if (this.caption) this.caption.innerHTML
			= this.caption.innerHTML.replace(/\s/g, ' ').replace('{caption}', s);
	}		
	if (this.caption) this.marginBottom += this.spaceForCaption;

};

HsExpander.prototype.writeCaption = function() {
	try {
		this.wrapper.style.width = this.wrapper.offsetWidth +'px';	
		this.caption.style.visibility = 'hidden';
		this.caption.className += ' highslide-display-block';
		
		var height;
		if (hs.ie && (hs.ieVersion() < 6 || document.compatMode == 'BackCompat')) {
			height = this.caption.offsetHeight;
		} else {
			var temp = hs.createElement('div', {innerHTML: this.caption.innerHTML}, 
				null, null, true); // to get height
			this.caption.innerHTML = '';
			this.caption.appendChild(temp);	
			height = this.caption.childNodes[0].offsetHeight;//parseInt(hs.getStyle(this.caption, 'height'));
			this.caption.innerHTML = this.caption.childNodes[0].innerHTML;
		}
		hs.setStyles(this.caption, { overflow: 'hidden', height: 0, zIndex: 2 });
		
		if (hs.captionSlideSpeed) {
			step = Math.round(height/50);
			if (step == 0) step = 1;
			step = step * hs.captionSlideSpeed;
		} else {
			this.placeCaption(height, 1);
			return;
		}

		var t = 0;
		for (var h = height % step; h <= height; h += step, t += 10) {
			var end = (h == height) ? 1 : 0;
			var eval = "try { "
				+ "hs.expanders["+ this.key +"].placeCaption("+ h +", "+ end +");"
				+ "} catch (e) {}";			
			setTimeout (eval, t);
		}
	
	} catch (e) {}	
};

HsExpander.prototype.placeCaption = function(height, end) {
	if (!this.caption) return;
	this.caption.style.height = height +'px';
	this.caption.style.visibility = 'visible';
	this.y.span = this.wrapper.offsetHeight - 2 * this.offsetBorderH;
	var o = this.objOutline;
	if (o) {
		o.td[4].style.height = (this.wrapper.offsetHeight - 2 * this.objOutline.offset) +'px';
		if (o.hasAlphaImageLoader) o.td[3].style.height = o.td[5].style.height = o.td[4].style.height;
	}
	if (end) this.onDisplayFinished();
};

HsExpander.prototype.showHideElements = function (tagName, visibility, imgPos) {
	var els = document.getElementsByTagName(tagName);
	if (els) {			
		for (i = 0; i < els.length; i++) {
			if (els[i].nodeName == tagName) {  
				var hiddenBy = els[i].getAttribute('hidden-by');
				 
				if (visibility == 'visible' && hiddenBy) {
					hiddenBy = hiddenBy.replace('['+ this.key +']', '');
					els[i].setAttribute('hidden-by', hiddenBy);
					if (!hiddenBy) els[i].style.visibility = 'visible';				
					
				} else if (visibility == 'hidden') { // hide if behind
					var elPos = hs.position(els[i]);
					elPos.w = els[i].offsetWidth;
					elPos.h = els[i].offsetHeight;
				
					var clearsX = (elPos.x + elPos.w < imgPos.x || elPos.x > imgPos.x + imgPos.w);
					var clearsY = (elPos.y + elPos.h < imgPos.y || elPos.y > imgPos.y + imgPos.h);
					var wrapperKey = hs.getWrapperKey(els[i]);
					if (!clearsX && !clearsY && wrapperKey != this.key) { // element falls behind image
						if (!els[i].currentStyle || (els[i].currentStyle && els[i].currentStyle['visibility'] != 'hidden')) { // IE
							if (!hiddenBy) {
								els[i].setAttribute('hidden-by', '['+ this.key +']');
							} else if (!hiddenBy.match('['+ this.key +']')) {
								els[i].setAttribute('hidden-by', hiddenBy + '['+ this.key +']');
							}
							els[i].style.visibility = 'hidden';	  
						}
					} else if (hiddenBy == '['+ this.key +']' || hs.focusKey == wrapperKey) { // on move
						els[i].setAttribute('hidden-by', '');
						els[i].style.visibility = 'visible';
					} else if (hiddenBy && hiddenBy.match('['+ this.key +']')) {
						els[i].setAttribute('hidden-by', hiddenBy.replace('['+ this.key +']', ''));
					}
				}   
			}
		}
	}
};

HsExpander.prototype.focus = function() {
	// blur others
	for (i = 0; i < hs.expanders.length; i++) {
		if (hs.expanders[i] && i == hs.focusKey) {
			var blurExp = hs.expanders[i];
			blurExp.content.className += ' highslide-'+ blurExp.contentType +'-blur';
			if (blurExp.caption) {
				blurExp.caption.className += ' highslide-caption-blur';
			}
			if (blurExp.isImage) {
				blurExp.content.style.cursor = hs.ie ? 'hand' : 'pointer';
				blurExp.content.title = hs.focusTitle;	
			}
		}
	}
	
	// focus this
	this.wrapper.style.zIndex = hs.zIndexCounter++;
	if (this.objOutline) this.objOutline.table.style.zIndex = this.wrapper.style.zIndex;
	
	this.content.className = 'highslide-'+ this.contentType;
	if (this.caption) {
		this.caption.className = this.caption.className.replace(' highslide-caption-blur', '');
	}
	
	if (this.isImage) {
		this.content.title = hs.restoreTitle;
		
		hs.styleRestoreCursor = window.opera ? 'pointer' : 'url('+ hs.graphicsDir + hs.restoreCursor +'), pointer';
		if (hs.ie && hs.ieVersion() < 6) hs.styleRestoreCursor = 'hand';
		this.content.style.cursor = hs.styleRestoreCursor;
	}
	
	hs.focusKey = this.key;	
	hs.addEventListener(document, 'keydown', hs.keyHandler);
	
};

HsExpander.prototype.onClick = function() {
	this.doClose();
};

HsExpander.prototype.doClose = function() {
	hs.removeEventListener(document, 'keydown', hs.keyHandler);
	try {
		this.isClosing = true;
		
		var x = parseInt(this.wrapper.style.left);
		var y = parseInt(this.wrapper.style.top);
		var w = (this.isImage) ? this.content.width : parseInt(this.content.style.width);
		var h = (this.isImage) ? this.content.height : parseInt(this.content.style.height);
		
		if (this.objOutline) {
			if (this.outlineWhileAnimating) this.positionOutline(x, y, w, h);
			else if (this.preserveContent) this.objOutline.table.style.visibility = 'hidden';
			else this.objOutline.destroy();
		}
		
		// remove children
		var n = this.wrapper.childNodes.length;
		for (i = n - 1; i >= 0 ; i--) {
			var child = this.wrapper.childNodes[i];
			if (child != this.content) {
				hs.purge(this.wrapper.childNodes[i]);
				this.wrapper.removeChild(this.wrapper.childNodes[i]);
			}
		}
		if (this.isHtml) this.htmlOnClose();
		
		this.wrapper.style.width = 'auto';
		this.content.style.cursor = 'default';
		var o2 = this.objOutline ? this.objOutline.offset : 0;
		
		this.changeSize(
			-1,
			x,
			y,
			w,
			h,
			this.thumbLeft - this.offsetBorderW + this.thumbOffsetBorderW,
			this.thumbTop - this.offsetBorderH + this.thumbOffsetBorderH,
			this.thumbWidth,
			this.thumbHeight, 
			hs.restoreDuration,
			hs.restoreSteps,
			o2,
			hs.outlineStartOffset
		);
		
	} catch (e) {
		this.onEndClose();
	} 
};

HsExpander.prototype.onEndClose = function () {
	this.thumb.style.visibility = 'visible';
	
	if (hs.hideSelects) this.showHideElements('SELECT', 'visible');
	if (hs.hideIframes) this.showHideElements('IFRAME', 'visible');
	
	if (this.isHtml && this.preserveContent) this.sleep();
	else {
		if (this.objOutline && this.outlineWhileAnimating) this.objOutline.destroy();
		hs.purge(this.wrapper);
		if (hs.ie && hs.ieVersion() < 5.5) this.wrapper.innerHTML = ''; // crash
		else this.wrapper.parentNode.removeChild(this.wrapper);
	}
	hs.expanders[this.key] = null;

	hs.cleanUp();
};

HsExpander.prototype.createOverlay = function (el, position, hideOnMouseOut, opacity) {
	if (typeof el == 'string') el = hs.getNode(el);
	if (!el || typeof el == 'string' || !this.isImage) return;
	
	var overlay = hs.createElement(
		'div',
		null,
		{
			'left' : 0,
			'top' : 0,
			'position' : 'absolute',
			'zIndex' : 3,
			'visibility' : 'hidden'
		},
		this.wrapper,
		true
	);
	if (opacity) hs.setStyles(el, { 'opacity': opacity });
	el.className += ' highslide-display-block';
	overlay.appendChild(el);	
	
	var left = this.offsetBorderW;
	var dLeft = this.content.width - overlay.offsetWidth;
	var top = this.offsetBorderH;
	var dTop = this.content.height - overlay.offsetHeight;
	
	if (!position) position = 'center center';
	if (position.match(/^bottom/)) top += dTop;
	if (position.match(/^center/)) top += dTop / 2;
	if (position.match(/right$/)) left += dLeft;
	if (position.match(/center$/)) left += dLeft / 2;
	overlay.style.left = left +'px';
	overlay.style.top = top +'px';
	
	if (hideOnMouseOut) overlay.setAttribute('hideOnMouseOut', true);
	if (!opacity) opacity = 1;
	overlay.setAttribute('opacity', opacity);
	hs.fade(overlay, 0, opacity, 1);
	
	hs.push(this.overlays, overlay);
};

HsExpander.prototype.createCustomOverlays = function() {
	for (i = 0; i < hs.overlays.length; i++) {
		var o = hs.overlays[i];
		if (o.thumbnailId == null || o.thumbnailId == this.thumbsUserSetId) {
			this.createOverlay(o.overlayId, o.position, o.hideOnMouseOut, o.opacity);
		}
	}
};

HsExpander.prototype.onMouseOver = function () {
	for (i = 0; i < this.overlays.length; i++) {
		var o = this.overlays[i];
		if (o.getAttribute('hideOnMouseOut'))
			hs.fade(o, 0, o.getAttribute('opacity'), 1);
	}
};

HsExpander.prototype.onMouseOut = function() {
	for (i = 0; i < this.overlays.length; i++) {
		var o = this.overlays[i];
		if (o.getAttribute('hideOnMouseOut')) 
			hs.fade(o, o.getAttribute('opacity'), 0, -1);
	}
};

HsExpander.prototype.createFullExpand = function () {
	var a = hs.createElement(
		'a',
		{
			href: 'javascript:hs.expanders['+ this.key +'].doFullExpand();',
			title: hs.fullExpandTitle
		},
		{
			background: 'url('+ hs.graphicsDir + hs.fullExpandIcon+')',
			display: 'block',
			margin: '0 10px 10px 0',
			width: '45px',
			height: '44px'
		}, null, true
	);
	
	this.createOverlay(a, 'bottom right', true, 0.75);
	this.fullExpandIcon = a;
};

HsExpander.prototype.doFullExpand = function () {
	try {
		hs.purge(this.fullExpandIcon);
		this.fullExpandIcon.parentNode.removeChild(this.fullExpandIcon);
		this.focus();
		
		this.x.min = parseInt(this.wrapper.style.left) - (this.fullExpandWidth - this.content.width) / 2;
		if (this.x.min < hs.marginLeft) this.x.min = hs.marginLeft;		
		this.wrapper.style.left = this.x.min +'px';
		
		var borderOffset = this.wrapper.offsetWidth - this.content.width;		
		
		this.content.width = this.fullExpandWidth;
		this.content.height = this.fullExpandHeight;
		
		this.x.span = this.content.width;
		this.wrapper.style.width = (this.x.span + borderOffset) +'px';
		
		this.y.span = this.wrapper.offsetHeight - 2 * this.offsetBorderH;
		this.positionOutline(this.x.min, this.y.min, this.x.span, this.y.span);
		
		// reposition overlays
		for (var i = 0; i < this.overlays.length; i++) {
			hs.purge(this.overlays[i]);
			this.overlays[i].parentNode.removeChild(this.overlays[i]);
		}	
		if (hs.showCredits) this.writeCredits();
		this.createCustomOverlays();
		
		this.redoShowHide();
	
	} catch (e) {
		window.location.href = this.content.src;
	}
};

// on end move and resize
HsExpander.prototype.redoShowHide = function() {
	var imgPos = {
		x: parseInt(this.wrapper.style.left) - 20, 
		y: parseInt(this.wrapper.style.top) - 20, 
		w: this.content.offsetWidth + 40, 
		h: this.content.offsetHeight + 40 + this.spaceForCaption
	};
	if (hs.hideSelects) this.showHideElements('SELECT', 'hidden', imgPos);
	if (hs.hideIframes) this.showHideElements('IFRAME', 'hidden', imgPos);

};

// set handlers
hs.addEventListener(document, 'mousedown', hs.mouseClickHandler);
hs.addEventListener(document, 'mouseup', hs.mouseClickHandler);
hs.addEventListener(window, 'load', hs.preloadImages);

/*** ajax_1.3.js ***/


function Jax()
{var loadingTimeout=400;var iframe;this.loadingFunction=function(){};this.doneLoadingFunction=function(){};this.stringify=function(arg){var c,i,l,o,u,v;switch(typeof arg){case'object':if(arg){if(arg.constructor==Array){o='';for(i=0;i<arg.length;++i){v=this.stringify(arg[i]);if(o&&(v!==u)){o+=',';}
if(v!==u){o+=v;}}
return'['+o+']';}else if(typeof arg.toString!='undefined'){o='';for(i in arg){v=this.stringify(arg[i]);if(v!==u){if(o){o+=',';}
o+=this.stringify(i)+':'+v;}}
return'{'+o+'}';}else{return;}}
return'';case'unknown':case'undefined':case'function':return u;case'string':arg=arg.replace(/"/g,"\\\"");l=arg.length;o='"';for(i=0;i<l;i+=1){c=arg.charAt(i);if(c>=' '){if(c=='\\'||c=='"'){o+='\\';}
o+=c;}else{switch(c){case'"':o+='\\"';break;case'\b':o+='\\b';break;case'\f':o+='\\f';break;case'\n':o+='\\n';break;case'\r':o+='\\r';break;case'\t':o+='\\t';break;default:c=c.charCodeAt();o+='\\u00';o+=Math.floor(c/16).toString(16);o+=(c%16).toString(16);}}}
return o+'"';default:return String(arg);}}
this.getRequestObject=function()
{if(window.XMLHttpRequest){http_request=new XMLHttpRequest();}else if(window.ActiveXObject){var msxmlhttp=new Array('Msxml2.XMLHTTP.4.0','Msxml2.XMLHTTP.3.0','Msxml2.XMLHTTP','Microsoft.XMLHTTP');for(var i=0;i<msxmlhttp.length;i++){try{http_request=new ActiveXObject(msxmlhttp[i]);}catch(e){http_request=null;}}}
if(!http_request){alert('Unfortunatelly you browser doesn\'t support this feature.');return false;}
return http_request;}
this.$=function(sId)
{if(!sId){return null;}
var returnObj=document.getElementById(sId);if(!returnObj&&document.all){returnObj=document.all[sId];}
return returnObj;}
this.addEvent=function(obj,type,fn){if(obj.attachEvent){obj['e'+type+fn]=fn;obj[type+fn]=function(){obj['e'+type+fn](window.event);}
obj.attachEvent('on'+type,obj[type+fn]);}else{obj.addEventListener(type,fn,false);}}
this.removeEvent=function(obj,type,fn){if(obj.detachEvent){obj.detachEvent('on'+type,obj[type+fn]);obj[type+fn]=null;}else{obj.removeEventListener(type,fn,false);}}
this.submitITask=function(comName,func,postData,responseFunc){var xmlReq=this.buildXmlReq(comName,func,postData,responseFunc,true);this.loadingFunction();if(!this.iframe){this.iframe=document.createElement('iframe');this.iframe.setAttribute("id",'ajaxIframe');this.iframe.setAttribute("height",0);this.iframe.setAttribute("width",0);this.iframe.setAttribute("border",0);this.iframe.style.visibility='hidden';document.body.appendChild(this.iframe);this.iframe.src=xmlReq;}else{this.iframe.src=xmlReq;}}
this.extractIFrameBody=function(iFrameEl){var doc=null;if(iFrameEl.contentDocument){doc=iFrameEl.contentDocument;}else if(iFrameEl.contentWindow){doc=iFrameEl.contentWindow.document;}else if(iFrameEl.document){doc=iFrameEl.document;}else{alert("Error: could not find sumiFrame document");return null;}
return doc.body;}
this.buildXmlReq=function(comName,func,postData,responseFunc,iframe){var xmlReq='';if(iframe){xmlReq+='?';}
else{xmlReq+='&';}
xmlReq+='option='+comName;xmlReq+='&no_html=1';xmlReq+='&task=azrul_ajax';xmlReq+='&func='+func;if(postData){xmlReq+="&"+postData;}
return xmlReq;}
this.submitTask=function(comName,func,postData,responseFunc){var xmlhttp=this.getRequestObject();var targetUrl=jax_live_site;xmlhttp.open('POST',targetUrl,true);xmlhttp.onreadystatechange=function(){if(xmlhttp.readyState==4){if(xmlhttp.status==200){jax.doneLoadingFunction();jax.processResponse(xmlhttp.responseText);}else{}}}
var id=1;var xmlReq=this.buildXmlReq(comName,func,postData,responseFunc);this.loadingFunction();xmlhttp.setRequestHeader('Content-Type','application/x-www-form-urlencoded');xmlhttp.send(xmlReq);}
this.processIResponse=function(){jax.doneLoadingFunction();var resp=(this.extractIFrameBody(this.iframe).innerHTML);resp=resp.replace(/&lt;/g,"<");resp=resp.replace(/&gt;/g,">");resp=resp.replace(/&amp;/g,"&");resp=resp.replace(/&quot;/g,'"');resp=resp.replace(/&#39;/g,"'");this.processResponse(resp);}
this.processResponse=function(responseTxt){var result=eval(responseTxt);for(var i=0;i<result.length;i++){var cmd=result[i][0];var id=result[i][1];var property=result[i][2];var data=result[i][3];var objElement=this.$(id);switch(cmd){case'as':if(objElement){eval("objElement."+property+"=  data \; ");}
break;case'al':if(data){alert(data);}
break;case'ce':this.create(id,property,data);break;case'rm':this.remove(id);break;case'cs':var scr=id+'(';if(this.isArray(data)){scr+='(data[0])';for(var l=1;l<data.length;l++){scr+=',(data['+l+'])';}}else{scr+='data';}
scr+=');';eval(scr);break;default:alert("Unknow command: "+cmd);}}
delete responseTxt;}
this.isArray=function(obj){if(obj){return obj.constructor==Array;}
return false;}
this.buildCall=function(comName,sFunction){}
this.icall=function(comName,sFunction){var arg="";if(arguments.length>2){for(var i=2;i<arguments.length;i++){var a=arguments[i];if(this.isArray(a)){arg+="arg"+i+"="+this.stringify(a)+"&";}else if(typeof a=="string"){var t=new Array('_d_',encodeURIComponent(a));arg+="arg"+i+"="+this.stringify(t)+"&";}else{var t=new Array('_d_',encodeURIComponent(a));arg+="arg"+i+"="+this.stringify(t)+"&";}}}
if(jax_site_type=='1.5'){this.submitTask(comName,sFunction,arg);}else{this.submitITask(comName,sFunction,arg);}}
this.call=function(comName,sFunction){var arg="";if(arguments.length>2){for(var i=2;i<arguments.length;i++){var a=arguments[i];if(this.isArray(a)){arg+="arg"+i+"="+this.stringify(a)+"&";}else if(typeof a=="string"){a=a.replace(/"/g,"&quot;");var t=new Array('_d_',encodeURIComponent(a));arg+="arg"+i+"="+this.stringify(t)+"&";}else{var t=new Array('_d_',encodeURIComponent(a));arg+="arg"+i+"="+this.stringify(t)+"&";}}}
this.submitTask(comName,sFunction,arg);}
this.create=function(sParentId,sTag,sId){var objParent=this.$(sParentId);objElement=document.createElement(sTag);objElement.setAttribute('id',sId);if(objParent){objParent.appendChild(objElement);}}
this.remove=function(sId){objElement=this.$(sId);if(objElement&&objElement.parentNode&&objElement.parentNode.removeChild)
{objElement.parentNode.removeChild(objElement);}}
this.getFormValues=function(frm){var objForm;objForm=this.$(frm);if(!Array.prototype.indexOf)
{Array.prototype.indexOf=function(elt)
{var len=this.length;var from=Number(arguments[1])||0;from=(from<0)?Math.ceil(from):Math.floor(from);if(from<0)
from+=len;for(;from<len;from++)
{if(from in this&&this[from]===elt)
return from;}
return-1;};}
var postData=new Array();if(objForm&&objForm.tagName=='FORM'){var formElements=objForm.elements;var assCheckbox=new Array();var assCntIdx=0;var arrayHiddenValues=new Array();var arrayHiddenCount=0;if(formElements.length>0){for(var i=0;i<formElements.length;i++)
{if(!formElements[i].name)
{continue;}
if(formElements[i].type&&(formElements[i].type=='radio'||formElements[i].type=='checkbox')&&formElements[i].checked==false)
{continue;}
var name=formElements[i].name;if(name)
{if(formElements[i].type=='select-multiple')
{postData[i]=new Array();for(var j=0;j<formElements[i].length;j++)
{if(formElements[i].options[j].selected===true)
{var value=formElements[i].options[j].value;postData[i][j]=new Array(name,encodeURIComponent(value));}}}
else if(formElements[i].type=='checkbox')
{if(assCheckbox.indexOf(formElements[i].name)==-1)
{assCheckbox[assCntIdx]=formElements[i].name
assCntIdx++;}}
else if(formElements[i].type=='hidden')
{if(arrayHiddenValues.indexOf(formElements[i].name)==-1)
{arrayHiddenValues[arrayHiddenCount]=formElements[i].name;arrayHiddenCount++;}}
else
{var value=formElements[i].value;value=value.replace(/"/g,"&quot;");postData[i]=new Array(name,encodeURIComponent(value));}}}}
if(arrayHiddenValues.length>0)
{for(var i=0;i<arrayHiddenValues.length;i++)
{var hiddenElement=document.getElementsByName(arrayHiddenValues[i]);if(hiddenElement)
{if(hiddenElement.length>1)
{var curLen=postData.length;postData[curLen]=new Array();for(var j=0;j<hiddenElement.length;j++)
{var value=hiddenElement[j].value;value=value.replace(/"/g,"&quot;");postData[curLen][j]=new Array(arrayHiddenValues[i],encodeURIComponent(value));}}
else
{var value=hiddenElement[0].value;value=value.replace(/"/g,"&quot;");postData[postData.length]=new Array(arrayHiddenValues[i],encodeURIComponent(value));}}}}
if(assCheckbox.length>0)
{for(var i=0;i<assCheckbox.length;i++)
{var objCheckbox=document.getElementsByName(assCheckbox[i]);if(objCheckbox)
{if(objCheckbox.length>1)
{var tmpIdx=0;var curLen=postData.length;postData[curLen]=new Array();for(var j=0;j<objCheckbox.length;j++)
{if(objCheckbox[j].checked)
{var value=objCheckbox[j].value;value=value.replace(/"/g,"&quot;");postData[curLen][j]=new Array(assCheckbox[i],encodeURIComponent(value));tmpIdx++;}}}
else
{if(objCheckbox[0].checked)
{var value=objCheckbox[0].value;value=value.replace(/"/g,"&quot;");postData[postData.length]=new Array(assCheckbox[i],encodeURIComponent(value));}}}}}}
return postData;}}
function jax_iresponse(){jax.processIResponse();}
var jax=new Jax();

/*** soundmanager2.js ***/

/*!
   SoundManager 2: Javascript Sound for the Web
   --------------------------------------------
   http://schillmania.com/projects/soundmanager2/

   Copyright (c) 2007, Scott Schiller. All rights reserved.
   Code provided under the BSD License:
   http://schillmania.com/projects/soundmanager2/license.txt

   V2.95b.20100101
*/

/*jslint undef: true, bitwise: true, newcap: true, immed: true */

var soundManager = null;

function SoundManager(smURL, smID) {

  this.flashVersion = 8;           // version of flash to require, either 8 or 9. Some API features require Flash 9.
  this.debugMode = false;           // enable debugging output (div#soundmanager-debug, OR console if available+configured)
  this.debugFlash = false;         // enable debugging output inside SWF, troubleshoot Flash/browser issues
  this.useConsole = true;          // use firebug/safari console.log()-type debug console if available
  this.consoleOnly = false;        // if console is being used, do not create/write to #soundmanager-debug
  this.waitForWindowLoad = false;  // force SM2 to wait for window.onload() before trying to call soundManager.onload()
  this.nullURL = 'null.mp3';       // path to "null" (empty) MP3 file, used to unload sounds (Flash 8 only)
  this.allowPolling = true;        // allow flash to poll for status update (required for whileplaying() events, peak, sound spectrum functions to work.)
  this.useFastPolling = false;     // uses 1 msec flash timer interval (vs. default of 20) for higher callback frequency, best combined with useHighPerformance
  this.useMovieStar = false;	   // enable support for Flash 9.0r115+ (codename "MovieStar") MPEG4 audio+video formats (AAC, M4V, FLV, MOV etc.)
  this.bgColor = '#ffffff';        // movie (.swf) background color, '#000000' useful if showing on-screen/full-screen video etc.
  this.useHighPerformance = false; // position:fixed flash movie can help increase js/flash speed, minimize lag
  this.flashLoadTimeout = 1000;    // msec to wait for flash movie to load before failing (0 = infinity)
  this.wmode = null;		       // mode to render the flash movie in - null, transparent, opaque (last two allow layering of HTML on top)
  this.allowFullScreen = true;     // enter full-screen (via double-click on movie) for flash 9+ video
  this.allowScriptAccess = 'always'; // for scripting the SWF (object/embed property), either 'always' or 'sameDomain'

  this.defaultOptions = {
    'autoLoad': false,             // enable automatic loading (otherwise .load() will be called on demand with .play(), the latter being nicer on bandwidth - if you want to .load yourself, you also can)
    'stream': true,                // allows playing before entire file has loaded (recommended)
    'autoPlay': false,             // enable playing of file as soon as possible (much faster if "stream" is true)
    'onid3': null,                 // callback function for "ID3 data is added/available"
    'onload': null,                // callback function for "load finished"
    'whileloading': null,          // callback function for "download progress update" (X of Y bytes received)
    'onplay': null,                // callback for "play" start
    'onpause': null,               // callback for "pause"
    'onresume': null,              // callback for "resume" (pause toggle)
    'whileplaying': null,          // callback during play (position update)
    'onstop': null,                // callback for "user stop"
    'onfinish': null,              // callback function for "sound finished playing"
    'onbeforefinish': null,        // callback for "before sound finished playing (at [time])"
    'onbeforefinishtime': 5000,    // offset (milliseconds) before end of sound to trigger beforefinish (eg. 1000 msec = 1 second)
    'onbeforefinishcomplete':null, // function to call when said sound finishes playing
    'onjustbeforefinish':null,     // callback for [n] msec before end of current sound
    'onjustbeforefinishtime':200,  // [n] - if not using, set to 0 (or null handler) and event will not fire.
    'multiShot': true,             // let sounds "restart" or layer on top of each other when played multiple times, rather than one-shot/one at a time
    'multiShotEvents': false,      // fire multiple sound events (currently onfinish() only) when multiShot is enabled
    'position': null,              // offset (milliseconds) to seek to within loaded sound data.
    'pan': 0,                      // "pan" settings, left-to-right, -100 to 100
    'volume': 100                  // self-explanatory. 0-100, the latter being the max.
  };

  this.flash9Options = {           // flash 9-only options, merged into defaultOptions if flash 9 is being used
    'isMovieStar': null,           // "MovieStar" MPEG4 audio/video mode. Null (default) = auto detect MP4, AAC etc. based on URL. true = force on, ignore URL
    'usePeakData': false,          // enable left/right channel peak (level) data
    'useWaveformData': false,      // enable sound spectrum (raw waveform data) - WARNING: CPU-INTENSIVE: may set CPUs on fire.
    'useEQData': false,            // enable sound EQ (frequency spectrum data) - WARNING: Also CPU-intensive.
    'onbufferchange': null,	       // callback for "isBuffering" property change
    'ondataerror': null		       // callback for waveform/eq data access error (flash playing audio in other tabs/domains)
  };

  this.movieStarOptions = {    // flash 9.0r115+ MPEG4 audio/video options, merged into defaultOptions if flash 9+movieStar mode is enabled
    'onmetadata': null,		   // callback for when video width/height etc. are received
    'useVideo': false,		   // if loading movieStar content, whether to show video
    'bufferTime': null		   // seconds of data to buffer before playback begins (null = flash default of 0.1 seconds - if AAC playback is gappy, try up to 3 seconds)
  };

  // jslint global declarations
  /*global SM2_DEFER, sm2Debugger, alert, console, document, navigator, setTimeout, window */

  var SMSound = null; // defined later
  var _s = this;
  var _sm = 'soundManager';
  this.version = null;
  this.versionNumber = 'V2.95b.20100101';
  this.movieURL = null;
  this.url = null;
  this.altURL = null;
  this.swfLoaded = false;
  this.enabled = false;
  this.o = null;
  this.id = (smID || 'sm2movie');
  this.oMC = null;
  this.sounds = {};
  this.soundIDs = [];
  this.muted = false;
  this.isFullScreen = false; // set later by flash 9+
  this.isIE = (navigator.userAgent.match(/MSIE/i));
  this.isSafari = (navigator.userAgent.match(/safari/i));
  this.debugID = 'soundmanager-debug';
  this.debugURLParam = /([#?&])debug=1/i;
  this.specialWmodeCase = false;
  this._onready = [];
  this._debugOpen = true;
  this._didAppend = false;
  this._appendSuccess = false;
  this._didInit = false;
  this._disabled = false;
  this._windowLoaded = false;
  this._hasConsole = (typeof console != 'undefined' && typeof console.log != 'undefined');
  this._debugLevels = ['log', 'info', 'warn', 'error'];
  this._defaultFlashVersion = 8;
  this._oRemoved = null;
  this._oRemovedHTML = null;

  var _$ = function(sID) {
    return document.getElementById(sID);
  };

  this.filePatterns = {
    flash8: /\.mp3(\?.*)?$/i,
    flash9: /\.mp3(\?.*)?$/i
  };

  this.netStreamTypes = ['aac', 'flv', 'mov', 'mp4', 'm4v', 'f4v', 'm4a', 'mp4v', '3gp', '3g2']; // Flash v9.0r115+ "moviestar" formats
  this.netStreamPattern = new RegExp('\\.('+this.netStreamTypes.join('|')+')(\\?.*)?$', 'i');

  this.filePattern = null;
  this.features = {
    buffering: false,
    peakData: false,
    waveformData: false,
    eqData: false,
    movieStar: false
  };

  this.sandbox = {
    'type': null,
    'types': {
      'remote': 'remote (domain-based) rules',
      'localWithFile': 'local with file access (no internet access)',
      'localWithNetwork': 'local with network (internet access only, no local access)',
      'localTrusted': 'local, trusted (local+internet access)'
    },
    'description': null,
    'noRemote': null,
    'noLocal': null
  };

  this._setVersionInfo = function() {
    if (_s.flashVersion != 8 && _s.flashVersion != 9) {
      alert(_s._str('badFV',_s.flashVersion,_s._defaultFlashVersion));
      _s.flashVersion = _s._defaultFlashVersion;
    }
    _s.version = _s.versionNumber+(_s.flashVersion == 9?' (AS3/Flash 9)':' (AS2/Flash 8)');
    // set up default options
    if (_s.flashVersion > 8) {
      _s.defaultOptions = _s._mergeObjects(_s.defaultOptions, _s.flash9Options);
      _s.features.buffering = true;
    }
    if (_s.flashVersion > 8 && _s.useMovieStar) {
      // flash 9+ support for movieStar formats as well as MP3
      _s.defaultOptions = _s._mergeObjects(_s.defaultOptions, _s.movieStarOptions);
      _s.filePatterns.flash9 = new RegExp('\\.(mp3|'+_s.netStreamTypes.join('|')+')(\\?.*)?$', 'i');
      _s.features.movieStar = true;
    } else {
      _s.useMovieStar = false;
      _s.features.movieStar = false;
    }
    _s.filePattern = _s.filePatterns[(_s.flashVersion != 8?'flash9':'flash8')];
    _s.movieURL = (_s.flashVersion == 8?'soundmanager2.swf':'soundmanager2_flash9.swf');
    _s.features.peakData = _s.features.waveformData = _s.features.eqData = (_s.flashVersion > 8);
  };

  this._overHTTP = (document.location?document.location.protocol.match(/http/i):null);
  this._waitingforEI = false;
  this._initPending = false;
  this._tryInitOnFocus = (this.isSafari && typeof document.hasFocus == 'undefined');
  this._isFocused = (typeof document.hasFocus != 'undefined'?document.hasFocus():null);
  this._okToDisable = !this._tryInitOnFocus;

  this.useAltURL = !this._overHTTP; // use altURL if not "online"
  var flashCPLink = 'http://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager04.html';

  this.strings = {
    notReady: 'Not loaded yet - wait for soundManager.onload() before calling sound-related methods',
    appXHTML: _sm+'_createMovie(): appendChild/innerHTML set failed. May be app/xhtml+xml DOM-related.',
    swf404: _sm+': Verify that %s is a valid path.',
    tryDebug: 'Try '+_sm+'.debugFlash = true for more security details (output goes to SWF.)',
    checkSWF: 'See SWF output for more debug info.',
    localFail: _sm+': Non-HTTP page ('+document.location.protocol+' URL?) Review Flash player security settings for this special case:\n'+flashCPLink+'\nMay need to add/allow path, eg. c:/sm2/ or /users/me/sm2/',
    waitFocus: _sm+': Special case: Waiting for focus-related event..',
    waitImpatient: _sm+': Getting impatient, still waiting for Flash%s...',
    waitForever: _sm+': Waiting indefinitely for Flash...',
    needFunction: _sm+'.onready(): Function object expected',
    badID: 'Warning: Sound ID "%s" should be a string, starting with a non-numeric character',
	fl9Vid: 'flash 9 required for video. Exiting.',
	noMS: 'MovieStar mode not enabled. Exiting.',
	spcWmode: _sm+'._createMovie(): Removing wmode, preventing win32 below-the-fold SWF loading issue',
	currentObj: '--- '+_sm+'._debug(): Current sound objects ---',
	waitEI: _sm+'._initMovie(): Waiting for ExternalInterface call from Flash..',
	waitOnload: _sm+': Waiting for window.onload()',
	docLoaded: _sm+': Document already loaded',
	onload: _sm+'.initComplete(): calling soundManager.onload()',
	onloadOK: _sm+'.onload() complete',
	init: '-- '+_sm+'.init() --',
	didInit: _sm+'.init(): Already called?',
	flashJS: _sm+': Attempting to call Flash from JS..',
	noPolling: _sm+': Polling (whileloading()/whileplaying() support) is disabled.',
	secNote: 'Flash security note: Network/internet URLs will not load due to security restrictions. Access can be configured via Flash Player Global Security Settings Page: http://www.macromedia.com/support/documentation/en/flashplayer/help/settings_manager04.html',
	badRemove: 'Warning: Failed to remove flash movie.',
	peakWave: 'Warning: peak/waveform/eqData features unsupported for non-MP3 formats',
	shutdown: _sm+'.disable(): Shutting down',
	queue: _sm+'.onready(): Queueing handler',
	smFail: _sm+': Failed to initialise.',
	smError: 'SMSound.load(): Exception: JS-Flash communication failed, or JS error.',
	manURL: 'SMSound.load(): Using manually-assigned URL',
	onURL: _sm+'.load(): current URL already assigned.',
	badFV: 'soundManager.flashVersion must be 8 or 9. "%s" is invalid. Reverting to %s.'
  };

  this._str = function() { // o [,items to replace]
    var params = Array.prototype.slice.call(arguments); // real array, please
	var o = params.shift(); // first arg
	var str = _s.strings && _s.strings[o]?_s.strings[o]:'';
	if (str && params && params.length) {
      for (var i=0, j=params.length; i<j; i++) {
	    str = str.replace('%s',params[i]);
	  }
	}
    return str;
  };

  // --- public methods ---
  this.supported = function() {
    return (_s._didInit && !_s._disabled);
  };

  this.getMovie = function(smID) {
    return _s.isIE?window[smID]:(_s.isSafari?_$(smID) || document[smID]:_$(smID));
  };

  this.loadFromXML = function(sXmlUrl) {
    try {
      _s.o._loadFromXML(sXmlUrl);
    } catch(e) {
      _s._failSafely();
      return true;
    }
  };

  this.createSound = function(oOptions) {
    var _cs = 'soundManager.createSound(): ';
    if (!_s._didInit) {
      throw _s._complain(_cs+_s._str('notReady'), arguments.callee.caller);
    }
    if (arguments.length == 2) {
      // function overloading in JS! :) ..assume simple createSound(id,url) use case
      oOptions = {
        'id': arguments[0],
        'url': arguments[1]
      };
    }
    var thisOptions = _s._mergeObjects(oOptions); // inherit SM2 defaults
    var _tO = thisOptions; // alias
    if (_tO.id.toString().charAt(0).match(/^[0-9]$/)) { // hopefully this isn't buggy regexp-fu. :D
      _s._wD(_cs+_s._str('badID',_tO.id), 2);
    }
    _s._wD(_cs+_tO.id+' ('+_tO.url+')', 1);
    if (_s._idCheck(_tO.id, true)) {
      _s._wD(_cs+_tO.id+' exists', 1);
      return _s.sounds[_tO.id];
    }
    if (_s.flashVersion > 8 && _s.useMovieStar) {
      if (_tO.isMovieStar === null) {
        _tO.isMovieStar = (_tO.url.match(_s.netStreamPattern)?true:false);
      }
      if (_tO.isMovieStar) {
        _s._wD(_cs+'using MovieStar handling');
      }
      if (_tO.isMovieStar && (_tO.usePeakData || _tO.useWaveformData || _tO.useEQData)) {
        _s._wDS('peakWave');
        _tO.usePeakData = false;
        _tO.useWaveformData = false;
        _tO.useEQData = false;
      }
    }
    _s.sounds[_tO.id] = new SMSound(_tO);
    _s.soundIDs[_s.soundIDs.length] = _tO.id;
    // AS2:
    if (_s.flashVersion == 8) {
      _s.o._createSound(_tO.id, _tO.onjustbeforefinishtime);
    } else {
      _s.o._createSound(_tO.id, _tO.url, _tO.onjustbeforefinishtime, _tO.usePeakData, _tO.useWaveformData, _tO.useEQData, _tO.isMovieStar, (_tO.isMovieStar?_tO.useVideo:false), (_tO.isMovieStar?_tO.bufferTime:false));
    }
    if (_tO.autoLoad || _tO.autoPlay) {
      // TODO: does removing timeout here cause problems?
      if (_s.sounds[_tO.id]) {
        _s.sounds[_tO.id].load(_tO);
      }
    }
    if (_tO.autoPlay) {
      _s.sounds[_tO.id].play();
    }
    return _s.sounds[_tO.id];
  };

  this.createVideo = function(oOptions) {
	var fN = 'soundManager.createVideo(): ';
    if (arguments.length == 2) {
      oOptions = {
        'id': arguments[0],
        'url': arguments[1]
      };
    }
    if (_s.flashVersion >= 9) {
      oOptions.isMovieStar = true;
      oOptions.useVideo = true;
    } else {
      _s._wD(fN+_s._str('f9Vid'), 2);
      return false;
    }
    if (!_s.useMovieStar) {
      _s._wD(fN+_s._str('noMS'), 2);
    }
    return _s.createSound(oOptions);
  };

  this.destroySound = function(sID, bFromSound) {
    // explicitly destroy a sound before normal page unload, etc.
    if (!_s._idCheck(sID)) {
      return false;
    }
    for (var i=0; i<_s.soundIDs.length; i++) {
      if (_s.soundIDs[i] == sID) {
        _s.soundIDs.splice(i, 1);
        continue;
      }
    }
    // conservative option: avoid crash with flash 8
    // calling destroySound() within a sound onload() might crash firefox, certain flavours of winXP+flash 8??
    // if (_s.flashVersion != 8) {
    _s.sounds[sID].unload();
    // }
    if (!bFromSound) {
      // ignore if being called from SMSound instance
      _s.sounds[sID].destruct();
    }
    delete _s.sounds[sID];
  };

  this.destroyVideo = this.destroySound;

  this.load = function(sID, oOptions) {
    if (!_s._idCheck(sID)) {
      return false;
    }
    _s.sounds[sID].load(oOptions);
  };

  this.unload = function(sID) {
    if (!_s._idCheck(sID)) {
      return false;
    }
    _s.sounds[sID].unload();
  };

  this.play = function(sID, oOptions) {
	var fN = 'soundManager.play(): ';
    if (!_s._didInit) {
      throw _s._complain(fN+_s._str('notReady'), arguments.callee.caller);
    }
    if (!_s._idCheck(sID)) {
      if (typeof oOptions != 'Object') {
        oOptions = {
          url: oOptions
        }; // overloading use case: play('mySound','/path/to/some.mp3');
      }
      if (oOptions && oOptions.url) {
        // overloading use case, creation+playing of sound: .play('someID',{url:'/path/to.mp3'});
        _s._wD(fN+'attempting to create "'+sID+'"', 1);
        oOptions.id = sID;
        _s.createSound(oOptions);
      } else {
        return false;
      }
    }
    _s.sounds[sID].play(oOptions);
  };

  this.start = this.play; // just for convenience

  this.setPosition = function(sID, nMsecOffset) {
    if (!_s._idCheck(sID)) {
      return false;
    }
    _s.sounds[sID].setPosition(nMsecOffset);
  };

  this.stop = function(sID) {
    if (!_s._idCheck(sID)) {
      return false;
    }
    _s._wD('soundManager.stop('+sID+')', 1);
    _s.sounds[sID].stop();
  };

  this.stopAll = function() {
    _s._wD('soundManager.stopAll()', 1);
    for (var oSound in _s.sounds) {
      if (_s.sounds[oSound] instanceof SMSound) {
        _s.sounds[oSound].stop(); // apply only to sound objects
      }
    }
  };

  this.pause = function(sID) {
    if (!_s._idCheck(sID)) {
      return false;
    }
    _s.sounds[sID].pause();
  };

  this.pauseAll = function() {
    for (var i=_s.soundIDs.length; i--;) {
      _s.sounds[_s.soundIDs[i]].pause();
    }
  };

  this.resume = function(sID) {
    if (!_s._idCheck(sID)) {
      return false;
    }
    _s.sounds[sID].resume();
  };

  this.resumeAll = function() {
    for (var i=_s.soundIDs.length; i--;) {
      _s.sounds[_s.soundIDs[i]].resume();
    }
  };

  this.togglePause = function(sID) {
    if (!_s._idCheck(sID)) {
      return false;
    }
    _s.sounds[sID].togglePause();
  };

  this.setPan = function(sID, nPan) {
    if (!_s._idCheck(sID)) {
      return false;
    }
    _s.sounds[sID].setPan(nPan);
  };

  this.setVolume = function(sID, nVol) {
    if (!_s._idCheck(sID)) {
      return false;
    }
    _s.sounds[sID].setVolume(nVol);
  };

  this.mute = function(sID) {
	var fN = 'soundManager.mute(): ';
    if (typeof sID != 'string') {
      sID = null;
    }
    if (!sID) {
      _s._wD(fN+'Muting all sounds');
      for (var i=_s.soundIDs.length; i--;) {
        _s.sounds[_s.soundIDs[i]].mute();
      }
      _s.muted = true;
    } else {
      if (!_s._idCheck(sID)) {
        return false;
      }
      _s._wD(fN+'Muting "'+sID+'"');
      _s.sounds[sID].mute();
    }
  };

  this.muteAll = function() {
    _s.mute();
  };

  this.unmute = function(sID) {
	var fN = 'soundManager.unmute(): ';
    if (typeof sID != 'string') {
      sID = null;
    }
    if (!sID) {
      _s._wD(fN+'Unmuting all sounds');
      for (var i=_s.soundIDs.length; i--;) {
        _s.sounds[_s.soundIDs[i]].unmute();
      }
      _s.muted = false;
    } else {
      if (!_s._idCheck(sID)) {
        return false;
      }
      _s._wD(fN+'Unmuting "'+sID+'"');
      _s.sounds[sID].unmute();
    }
  };

  this.unmuteAll = function() {
    _s.unmute();
  };

  this.toggleMute = function(sID) {
    if (!_s._idCheck(sID)) {
      return false;
    }
    _s.sounds[sID].toggleMute();
  };

  this.getMemoryUse = function() {
    if (_s.flashVersion == 8) {
      // not supported in Flash 8
      return 0;
    }
    if (_s.o) {
      return parseInt(_s.o._getMemoryUse(), 10);
    }
  };

  this.disable = function(bNoDisable) {
    // destroy all functions
    if (typeof bNoDisable == 'undefined') {
      bNoDisable = false;
    }
    if (_s._disabled) {
      return false;
    }
    _s._disabled = true;
    _s._wDS('shutdown', 1);
    for (var i=_s.soundIDs.length; i--;) {
      _s._disableObject(_s.sounds[_s.soundIDs[i]]);
    }
    _s.initComplete(bNoDisable); // fire "complete", despite fail
    // _s._disableObject(_s); // taken out to allow reboot()
  };

  this.canPlayURL = function(sURL) {
    return (sURL?(sURL.match(_s.filePattern)?true:false):null);
  };

  this.getSoundById = function(sID, suppressDebug) {
    if (!sID) {
      throw new Error('SoundManager.getSoundById(): sID is null/undefined');
    }
    var result = _s.sounds[sID];
    if (!result && !suppressDebug) {
      _s._wD('"'+sID+'" is an invalid sound ID.', 2);
      // soundManager._wD('trace: '+arguments.callee.caller);
    }
    return result;
  };

  this.onready = function(oMethod, oScope) {
    // queue a callback, with optional scope
    // a status object will be passed to your handler
    /*
    soundManager.onready(function(oStatus) {
	  alert('SM2 init success: '+oStatus.success);
	});
	*/
    if (oMethod && oMethod instanceof Function) {
      if (_s._didInit) {
        _s._wDS('queue');
      }
      if (!oScope) {
        oScope = window;
      }
      _s._addOnReady(oMethod, oScope);
      _s._processOnReady();
      return true;
    } else {
      throw _s._str('needFunction');
    }
  };

  this.oninitmovie = function() {
    // called after SWF has been appended to the DOM via JS (or retrieved from HTML)
    // this is a stub for your own scripts.
  };

  this.onload = function() {
    // window.onload() equivalent for SM2, ready to create sounds etc.
    // this is a stub for your own scripts.
    soundManager._wD('soundManager.onload()', 1);
  };

  this.onerror = function() {
    // stub for user handler, called when SM2 fails to load/init
  };

  // --- "private" methods ---
  this._idCheck = this.getSoundById;

  this._complain = function(sMsg, oCaller) {
    // Try to create meaningful custom errors, w/stack trace to the "offending" line
    var sPre = 'Error: ';
    if (!oCaller) {
      return new Error(sPre+sMsg);
    }
    var e = new Error(''); // make a mistake.
    var stackMsg = null;
    if (e.stack) {
      // potentially dangerous: Try to return a meaningful stacktrace where provided (Mozilla)
      try {
        var splitChar = '@';
        var stackTmp = e.stack.split(splitChar);
        stackMsg = stackTmp[4]; // try to return only the relevant bit, skipping internal SM2 shiz
      } catch(ee) {
        // oops.
        stackMsg = e.stack;
      }
    }
    if (typeof console != 'undefined' && typeof console.trace != 'undefined') {
      console.trace();
    }
    var errorDesc = sPre+sMsg+'. \nCaller: '+oCaller.toString()+(e.stack?' \nTop of stacktrace: '+stackMsg:(e.message?' \nMessage: '+e.message:''));
    // See JS error/debug/console output for real error source, stack trace / message detail where possible.
    return new Error(errorDesc);
  };

  var _doNothing = function() {
    return false;
  };

  _doNothing._protected = true;

  this._disableObject = function(o) {
    for (var oProp in o) {
      if (typeof o[oProp] == 'function' && typeof o[oProp]._protected == 'undefined') {
        o[oProp] = _doNothing;
      }
    }
    oProp = null;
  };

  this._failSafely = function(bNoDisable) {
    // general failure exception handler
    if (typeof bNoDisable == 'undefined') {
      bNoDisable = false;
    }
    if (!_s._disabled || bNoDisable) {
      _s._wDS('smFail', 2);
      _s.disable(bNoDisable);
    }
  };

  this._normalizeMovieURL = function(smURL) {
    var urlParams = null;
    if (smURL) {
      if (smURL.match(/\.swf(\?.*)?$/i)) {
        urlParams = smURL.substr(smURL.toLowerCase().lastIndexOf('.swf?')+4);
        if (urlParams) {
          return smURL; // assume user knows what they're doing
        }
      } else if (smURL.lastIndexOf('/') != smURL.length - 1) {
        smURL = smURL+'/';
      }
    }
    return (smURL && smURL.lastIndexOf('/') != -1?smURL.substr(0, smURL.lastIndexOf('/')+1):'./')+_s.movieURL;
  };

  this._getDocument = function() {
    return (document.body?document.body:(document.documentElement?document.documentElement:document.getElementsByTagName('div')[0]));
  };

  this._getDocument._protected = true;

  this._setPolling = function(bPolling, bHighPerformance) {
    if (!_s.o || !_s.allowPolling) {
      return false;
    }
    _s.o._setPolling(bPolling, bHighPerformance);
  };

  this._createMovie = function(smID, smURL) {
    var specialCase = null;
    var remoteURL = (smURL?smURL:_s.url);
    var localURL = (_s.altURL?_s.altURL:remoteURL);
    if (_s.debugURLParam.test(window.location.href.toString())) {
      _s.debugMode = true; // allow force of debug mode via URL
    }
    if (_s._didAppend && _s._appendSuccess) {
      return false; // ignore if already succeeded
    }
    _s._didAppend = true;

    // safety check for legacy (change to Flash 9 URL)
    _s._setVersionInfo();
    _s.url = _s._normalizeMovieURL(_s._overHTTP?remoteURL:localURL);
    smURL = _s.url;

    if (_s.useHighPerformance && _s.useMovieStar && _s.defaultOptions.useVideo === true) {
      specialCase = 'soundManager note: disabling highPerformance, not applicable with movieStar mode+useVideo';
      _s.useHighPerformance = false;
    }

    _s.wmode = (!_s.wmode && _s.useHighPerformance && !_s.useMovieStar?'transparent':_s.wmode);


    if (_s.wmode !== null && _s.flashLoadTimeout !== 0 && (!_s.useHighPerformance || _s.debugFlash) && !_s.isIE && navigator.platform.match(/win32/i)) {
      _s.specialWmodeCase = true;
      // extra-special case: movie doesn't load until scrolled into view when using wmode = anything but 'window' here
      // does not apply when using high performance (position:fixed means on-screen), OR infinite flash load timeout
      _s._wDS('spcWmode');
      _s.wmode = null;
    }

    if (_s.flashVersion == 8) {
      _s.allowFullScreen = false;
    }

    var oEmbed = {
      name: smID,
      id: smID,
      src: smURL,
      width: '100%',
      height: '100%',
      quality: 'high',
      allowScriptAccess: _s.allowScriptAccess,
      bgcolor: _s.bgColor,
      pluginspage: 'http://www.macromedia.com/go/getflashplayer',
      type: 'application/x-shockwave-flash',
      wmode: _s.wmode,
      allowfullscreen: (_s.allowFullScreen?'true':'false')
    };

    if (_s.debugFlash) {
      oEmbed.FlashVars = 'debug=1';
    }

    if (!_s.wmode) {
      delete oEmbed.wmode; // don't write empty attribute
    }

    var oMovie = null;
    var tmp = null;
    var movieHTML = null;
    var oEl = null;

    if (_s.isIE) {
      // IE is "special".
      oMovie = document.createElement('div');
      movieHTML = '<object id="'+smID+'" data="'+smURL+'" type="'+oEmbed.type+'" width="'+oEmbed.width+'" height="'+oEmbed.height+'"><param name="movie" value="'+smURL+'" /><param name="AllowScriptAccess" value="'+_s.allowScriptAccess+'" /><param name="quality" value="'+oEmbed.quality+'" />'+(_s.wmode?'<param name="wmode" value="'+_s.wmode+'" /> ':'')+'<param name="bgcolor" value="'+_s.bgColor+'" /><param name="allowFullScreen" value="'+oEmbed.allowFullScreen+'" />'+(_s.debugFlash?'<param name="FlashVars" value="'+oEmbed.FlashVars+'" />':'')+'<!-- --></object>';
    } else {
      oMovie = document.createElement('embed');
      for (tmp in oEmbed) {
        if (oEmbed.hasOwnProperty(tmp)) {
          oMovie.setAttribute(tmp, oEmbed[tmp]);
        }
      }
    }

    var oD = null;
    var oToggle = null;

if (_s.debugMode) {

    oD = document.createElement('div');
    oD.id = _s.debugID+'-toggle';
    oToggle = {
      position: 'fixed',
      bottom: '0px',
      right: '0px',
      width: '1.2em',
      height: '1.2em',
      lineHeight: '1.2em',
      margin: '2px',
      textAlign: 'center',
      border: '1px solid #999',
      cursor: 'pointer',
      background: '#fff',
      color: '#333',
      zIndex: 10001
    };

    oD.appendChild(document.createTextNode('-'));
    oD.onclick = _s._toggleDebug;
    oD.title = 'Toggle SM2 debug console';

    if (navigator.userAgent.match(/msie 6/i)) {
      oD.style.position = 'absolute';
      oD.style.cursor = 'hand';
    }

    for (tmp in oToggle) {
      if (oToggle.hasOwnProperty(tmp)) {
        oD.style[tmp] = oToggle[tmp];
      }
    }

}

    var oTarget = _s._getDocument();

    if (oTarget) {

      _s.oMC = _$('sm2-container')?_$('sm2-container'):document.createElement('div');

      var extraClass = (_s.debugMode?' sm2-debug':'')+(_s.debugFlash?' flash-debug':'');

      if (!_s.oMC.id) {
        _s.oMC.id = 'sm2-container';
        _s.oMC.className = 'movieContainer'+extraClass;
        // "hide" flash movie
        var s = null;
        oEl = null;
        if (_s.useHighPerformance) {
          s = {
            position: 'fixed',
            width: '8px',
            height: '8px',
            // must be at least 6px for flash to run fast. odd? yes.
            bottom: '0px',
            left: '0px',
            overflow: 'hidden'
            // zIndex:-1 // sit behind everything else - potentially dangerous/buggy?
          };
        } else {
          s = {
            position: 'absolute',
            width: '8px',
            height: '8px',
            top: '-9999px',
            left: '-9999px'
          };
        }
        var x = null;
        if (!_s.debugFlash) {
          for (x in s) {
            if (s.hasOwnProperty(x)) {
              _s.oMC.style[x] = s[x];
            }
          }
        }
        try {
          if (!_s.isIE) {
            _s.oMC.appendChild(oMovie);
          }
          oTarget.appendChild(_s.oMC);
          if (_s.isIE) {
            oEl = _s.oMC.appendChild(document.createElement('div'));
            oEl.className = 'sm2-object-box';
            oEl.innerHTML = movieHTML;
          }
          _s._appendSuccess = true;
        } catch(e) {
          throw new Error(_s._str('appXHTML'));
        }
      } else {
        // it's already in the document.
        if (_s.debugMode || _s.debugFlash) {
          _s.oMC.className += extraClass;
        }
        _s.oMC.appendChild(oMovie);
        if (_s.isIE) {
          oEl = _s.oMC.appendChild(document.createElement('div'));
          oEl.className = 'sm2-object-box';
          oEl.innerHTML = movieHTML;
        }
        _s._appendSuccess = true;
      }

      if (_s.debugMode && !_$(_s.debugID) && ((!_s._hasConsole || !_s.useConsole) || (_s.useConsole && _s._hasConsole && !_s.consoleOnly))) {
        var oDebug = document.createElement('div');
        oDebug.id = _s.debugID;
        oDebug.style.display = (_s.debugMode?'block':'none');
        if (_s.debugMode && !_$(oD.id)) {
          try {
            oTarget.appendChild(oD);
          } catch(e2) {
            throw new Error(_s._str('appXHTML'));
          }
          oTarget.appendChild(oDebug);
        }
      }
      oTarget = null;
    }

    if (specialCase) {
      _s._wD(specialCase);
    }

    _s._wD('-- SoundManager 2 '+_s.version+(_s.useMovieStar?', MovieStar mode':'')+(_s.useHighPerformance?', high performance mode, ':', ')+((_s.useFastPolling?'fast':'normal')+' polling')+(_s.wmode?', wmode: '+_s.wmode:'')+(_s.debugFlash?', flash debug mode':'')+' --', 1);
    _s._wD('soundManager._createMovie(): Trying to load '+smURL+(!_s._overHTTP && _s.altURL?' (alternate URL)':''), 1);
  };

  this._writeDebug = function(sText, sType, bTimestamp) { // aliased to this._wD()
    if (!_s.debugMode) {
      return false;
    }
    if (typeof bTimestamp != 'undefined' && bTimestamp) {
      sText = sText+' | '+new Date().getTime();
    }
    if (_s._hasConsole && _s.useConsole) {
      var sMethod = _s._debugLevels[sType];
      if (typeof console[sMethod] != 'undefined') {
        console[sMethod](sText);
      } else {
        console.log(sText);
      }
      if (_s.useConsoleOnly) {
        return true;
      }
    }
    var sDID = 'soundmanager-debug';
    var o = null;
    try {
      o = _$(sDID);
      if (!o) {
        return false;
      }
      var oItem = document.createElement('div');
      if (++_s._wdCount % 2 === 0) {
        oItem.className = 'sm2-alt';
      }
      // sText = sText.replace(/\n/g,'<br />');
      if (typeof sType == 'undefined') {
        sType = 0;
      } else {
        sType = parseInt(sType, 10);
      }
      oItem.appendChild(document.createTextNode(sText));
      if (sType) {
        if (sType >= 2) {
          oItem.style.fontWeight = 'bold';
        }
        if (sType == 3) {
          oItem.style.color = '#ff3333';
        }
      }
      // o.appendChild(oItem); // top-to-bottom
      o.insertBefore(oItem, o.firstChild); // bottom-to-top
    } catch(e) {
      // oh well
    }
    o = null;
  };
  this._writeDebug._protected = true;
  this._wdCount = 0;
  this._wdCount._protected = true;
  this._wD = this._writeDebug;

  this._wDS = function(o,errorLevel) {
    if (!o) {
	  return '';
	} else {
	  return _s._wD(_s._str(o),errorLevel);
	}
  };
  this._wDS._protected = true;

  this._wDAlert = function(sText) {
    alert(sText);
  };

  if (window.location.href.indexOf('debug=alert')+1 && _s.debugMode) {
    _s._wD = _s._wDAlert;
  }

  this._toggleDebug = function() {
    var o = _$(_s.debugID);
    var oT = _$(_s.debugID+'-toggle');
    if (!o) {
      return false;
    }
    if (_s._debugOpen) {
      // minimize
      oT.innerHTML = '+';
      o.style.display = 'none';
    } else {
      oT.innerHTML = '-';
      o.style.display = 'block';
    }
    _s._debugOpen = !_s._debugOpen;
  };

  this._toggleDebug._protected = true;

  this._debug = function() {
    _s._wDS('currentObj', 1);
    for (var i=0, j = _s.soundIDs.length; i<j; i++) {
      _s.sounds[_s.soundIDs[i]]._debug();
    }
  };

  this._debugTS = function(sEventType, bSuccess, sMessage) {
    // troubleshooter debug hooks
    if (typeof sm2Debugger != 'undefined') {
      try {
        sm2Debugger.handleEvent(sEventType, bSuccess, sMessage);
      } catch(e) {
        // oh well	
      }
    }
  };

  this._debugTS._protected = true;

  this._mergeObjects = function(oMain, oAdd) {
    // non-destructive merge
    var o1 = {}; // clone o1
    for (var i in oMain) {
      if (oMain.hasOwnProperty(i)) {
        o1[i] = oMain[i];
      }
    }
    var o2 = (typeof oAdd == 'undefined'?_s.defaultOptions:oAdd);
    for (var o in o2) {
      if (o2.hasOwnProperty(o) && typeof o1[o] == 'undefined') {
        o1[o] = o2[o];
      }
    }
    return o1;
  };

  this.createMovie = function(sURL) {
    if (sURL) {
      _s.url = sURL;
    }
    _s._initMovie();
  };

  this.go = this.createMovie; // nice alias

  this._initMovie = function() {
    // attempt to get, or create, movie
    if (_s.o) {
      return false; // may already exist
    }
    _s.o = _s.getMovie(_s.id); // (inline markup)
    if (!_s.o) {
      if (!_s.oRemoved) {
        // try to create
        _s._createMovie(_s.id, _s.url);
      } else {
        // try to re-append removed movie after reboot()
        if (!_s.isIE) {
          _s.oMC.appendChild(_s.oRemoved);
        } else {
          _s.oMC.innerHTML = _s.oRemovedHTML;
        }
        _s.oRemoved = null;
        _s._didAppend = true;
      }
      _s.o = _s.getMovie(_s.id);
    }
    if (_s.o) {
      // _s._wD('soundManager._initMovie(): Got '+_s.o.nodeName+' element ('+(_s._didAppend?'created via JS':'static HTML')+')',1);
      if (_s.flashLoadTimeout > 0) {
        _s._wDS('waitEI');
      }
    }
    if (typeof _s.oninitmovie == 'function') {
      setTimeout(_s.oninitmovie, 1);
    }
  };

  this.waitForExternalInterface = function() {
    if (_s._waitingForEI) {
      return false;
    }
    _s._waitingForEI = true;
    if (_s._tryInitOnFocus && !_s._isFocused) {
      _s._wDS('waitFocus');
      return false;
    }
    if (_s.flashLoadTimeout > 0) {
      if (!_s._didInit) {
        var p = _s.getMoviePercent();
        _s._wD(_s._str('waitImpatient',(p == 100?' (SWF loaded)':(p > 0?' (SWF '+p+'% loaded)':''))));
      }
      setTimeout(function() {
        var p = _s.getMoviePercent();
        if (!_s._didInit) {
          _s._wD(_sm+': No Flash response within reasonable time after document load.\nLikely causes: '+(p === null || p === 0?'Loading '+_s.movieURL+' may have failed (and/or Flash '+_s.flashVersion+'+ not present?), ':'')+'Flash blocked or JS-Flash security error.'+(_s.debugFlash?' '+_s._str('checkSWF'): ''), 2);
          if (!_s._overHTTP) {
            _s._wDS('localFail', 2);
            if (!_s.debugFlash) {
              _s._wDS('tryDebug', 2);
            }
          }
          if (p === 0) {
            // 404, or blocked from loading?
            _s._wD(_s._str('swf404',_s.url));
          }
          _s._debugTS('flashtojs', false, ': Timed out'+(_s._overHTTP)?' (Check flash security or flash blockers)':' (No plugin/missing SWF?)');
        }
        // if still not initialized and no other options, give up
        if (!_s._didInit && _s._okToDisable) {
          _s._failSafely(true); // don't disable, for reboot()
        }
      },
      _s.flashLoadTimeout);
    } else if (!_s._didInit) {
      _s._wDS('waitForever');
    }
  };

  this.getMoviePercent = function() {
    return (_s.o && typeof _s.o.PercentLoaded != 'undefined'?_s.o.PercentLoaded():null);
  };

  this.handleFocus = function() {
    if (_s._isFocused || !_s._tryInitOnFocus) {
      return true;
    }
    _s._okToDisable = true;
    _s._isFocused = true;
    _s._wD('soundManager.handleFocus()');
    if (_s._tryInitOnFocus) {
      // giant Safari 3.1 hack - assume window in focus if mouse is moving, since document.hasFocus() not currently implemented.
      window.removeEventListener('mousemove', _s.handleFocus, false);
    }
    // allow init to restart
    _s._waitingForEI = false;
    setTimeout(_s.waitForExternalInterface, 500);
    // detach event
    if (window.removeEventListener) {
      window.removeEventListener('focus', _s.handleFocus, false);
    } else if (window.detachEvent) {
      window.detachEvent('onfocus', _s.handleFocus);
    }
  };

  this.initComplete = function(bNoDisable) {
    if (_s._didInit) {
      return false;
    }
    _s._didInit = true;
    _s._wD('-- SoundManager 2 '+(_s._disabled?'failed to load':'loaded')+' ('+(_s._disabled?'security/load error':'OK')+') --', 1);
    if (_s._disabled || bNoDisable) {
      // _s._wD('soundManager.initComplete(): calling soundManager.onerror()',1);
      _s._processOnReady();
      _s._debugTS('onload', false);
      _s.onerror.apply(window);
      return false;
    } else {
      _s._debugTS('onload', true);
    }
    if (_s.waitForWindowLoad && !_s._windowLoaded) {
      _s._wDS('waitOnload');
      if (window.addEventListener) {
        window.addEventListener('load', _s._initUserOnload, false);
      } else if (window.attachEvent) {
        window.attachEvent('onload', _s._initUserOnload);
      }
      return false;
    } else {
      if (_s.waitForWindowLoad && _s._windowLoaded) {
        _s._wDS('docLoaded');
      }
      _s._initUserOnload();
    }
  };

  this._addOnReady = function(oMethod, oScope) {
    _s._onready.push({
      'method': oMethod,
      'scope': (oScope || null),
      'fired': false
    });
  };

  this._processOnReady = function() {
    if (!_s._didInit) {
      // not ready yet.
      return false;
    }
    var status = {
      success: (!_s._disabled)
    };
    var queue = [];
    for (var i=0, j = _s._onready.length; i<j; i++) {
      if (_s._onready[i].fired !== true) {
        queue.push(_s._onready[i]);
      }
    }
    if (queue.length) {
      _s._wD(_sm+': Firing '+queue.length+' onready() item'+(queue.length > 1?'s':''));
      for (i = 0, j = queue.length; i<j; i++) {
        if (queue[i].scope) {
          queue[i].method.apply(queue[i].scope, [status]);
        } else {
          queue[i].method(status);
        }
        queue[i].fired = true;
      }
    }
  };

  this._initUserOnload = function() {
    window.setTimeout(function() {
      _s._processOnReady();
      _s._wDS('onload', 1);
      // call user-defined "onload", scoped to window
      _s.onload.apply(window);
      _s._wDS('onloadOK', 1);
    });
  };

  this.init = function() {
    _s._wDS('init');
    // called after onload()
    _s._initMovie();
    if (_s._didInit) {
      _s._wDS('didInit');
      return false;
    }
    // event cleanup
    if (window.removeEventListener) {
      window.removeEventListener('load', _s.beginDelayedInit, false);
    } else if (window.detachEvent) {
      window.detachEvent('onload', _s.beginDelayedInit);
    }
    try {
      _s._wDS('flashJS');
      _s.o._externalInterfaceTest(false); // attempt to talk to Flash
      if (!_s.allowPolling) {
        _s._wDS('noPolling', 1);
      } else {
        _s._setPolling(true, _s.useFastPolling?true:false);
      }
      if (!_s.debugMode) {
        _s.o._disableDebug();
      }
      _s.enabled = true;
      _s._debugTS('jstoflash', true);
    } catch(e) {
      _s._wD('js/flash exception: '+e.toString());
      _s._debugTS('jstoflash', false);
      _s._failSafely(true); // don't disable, for reboot()
      _s.initComplete();
      return false;
    }
    _s.initComplete();
  };

  this.beginDelayedInit = function() {
    // _s._wD('soundManager.beginDelayedInit()');
    _s._windowLoaded = true;
    setTimeout(_s.waitForExternalInterface, 500);
    setTimeout(_s.beginInit, 20);
  };

  this.beginInit = function() {
    if (_s._initPending) {
      return false;
    }
    _s.createMovie(); // ensure creation if not already done
    _s._initMovie();
    _s._initPending = true;
    return true;
  };

  this.domContentLoaded = function() {
    if (document.removeEventListener) {
      document.removeEventListener('DOMContentLoaded', _s.domContentLoaded, false);
    }
    _s.go();
  };

  this._externalInterfaceOK = function(flashDate) {
    // callback from flash for confirming that movie loaded, EI is working etc.
    // flashDate = approx. timing/delay info for JS/flash bridge
    if (_s.swfLoaded) {
      return false;
    }
    var eiTime = new Date().getTime();
    _s._wD('soundManager._externalInterfaceOK()'+(flashDate?' (~'+(eiTime - flashDate)+' ms)':''));
    _s._debugTS('swf', true);
    _s._debugTS('flashtojs', true);
    _s.swfLoaded = true;
    _s._tryInitOnFocus = false;

    if (_s.isIE) {
      // IE needs a timeout OR delay until window.onload - may need TODO: investigating
      setTimeout(_s.init, 100);
    } else {
      _s.init();
    }

  };

  this._setSandboxType = function(sandboxType) {
    var sb = _s.sandbox;
    sb.type = sandboxType;
    sb.description = sb.types[(typeof sb.types[sandboxType] != 'undefined'?sandboxType:'unknown')];
    _s._wD('Flash security sandbox type: '+sb.type);
    if (sb.type == 'localWithFile') {
      sb.noRemote = true;
      sb.noLocal = false;
      _s._wDS('secNote', 2);
    } else if (sb.type == 'localWithNetwork') {
      sb.noRemote = false;
      sb.noLocal = true;
    } else if (sb.type == 'localTrusted') {
      sb.noRemote = false;
      sb.noLocal = false;
    }
  };

  this.reboot = function() {
    // attempt to reset and init SM2
    _s._wD('soundManager.reboot()');
    if (_s.soundIDs.length) {
      _s._wD('Destroying '+_s.soundIDs.length+' SMSound objects...');
    }
    for (var i=_s.soundIDs.length; i--;) {
      _s.sounds[_s.soundIDs[i]].destruct();
    }
    // trash ze flash
    try {
      if (_s.isIE) {
        _s.oRemovedHTML = _s.o.innerHTML;
      }
      _s.oRemoved = _s.o.parentNode.removeChild(_s.o);
      _s._wD('Flash movie removed.');
    } catch(e) {
      // uh-oh.
      _s._wDS('badRemove', 2);
    }

    // actually, force recreate of movie.
    _s.oRemovedHTML = null;
    _s.oRemoved = null;

    _s.enabled = false;
    _s._didInit = false;
    _s._waitingForEI = false;
    _s._initPending = false;
    _s._didAppend = false;
    _s._appendSuccess = false;
    _s._disabled = false;
    _s._waitingforEI = true;
    _s.swfLoaded = false;
    _s.soundIDs = {};
    _s.sounds = [];
    _s.o = null;
    for (i = _s._onready.length; i--;) {
      _s._onready[i].fired = false;
    }
    _s._wD(_sm+': Rebooting...');
    window.setTimeout(soundManager.beginDelayedInit, 20);
  };

  this.destruct = function() {
    _s._wD('soundManager.destruct()');
    _s.disable(true);
  };

  // SMSound (sound object)
  SMSound = function(oOptions) {
    var _t = this;
    this.sID = oOptions.id;
    this.url = oOptions.url;
    this.options = _s._mergeObjects(oOptions);
    this.instanceOptions = this.options; // per-play-instance-specific options
    this._iO = this.instanceOptions; // short alias
    // assign property defaults (volume, pan etc.)
    this.pan = this.options.pan;
    this.volume = this.options.volume;

    this._lastURL = null;

    this._debug = function() {
      if (_s.debugMode) {
        var stuff = null;
        var msg = [];
        var sF = null;
        var sfBracket = null;
        var maxLength = 64; // # of characters of function code to show before truncating
        for (stuff in _t.options) {
          if (_t.options[stuff] !== null) {
            if (_t.options[stuff] instanceof Function) {
              // handle functions specially
              sF = _t.options[stuff].toString();
              sF = sF.replace(/\s\s+/g, ' '); // normalize spaces
              sfBracket = sF.indexOf('{');
              msg[msg.length] = ' '+stuff+': {'+sF.substr(sfBracket+1, (Math.min(Math.max(sF.indexOf('\n') - 1, maxLength), maxLength))).replace(/\n/g, '')+'... }';
            } else {
              msg[msg.length] = ' '+stuff+': '+_t.options[stuff];
            }
          }
        }
        _s._wD('SMSound() merged options: {\n'+msg.join(', \n')+'\n}');
      }
    };

    this._debug();

    this.id3 = {
      /* 
    Name/value pairs set via Flash when available - see reference for names (download documentation):
    http://livedocs.macromedia.com/flash/8/
    Previously-live URL:
    http://livedocs.macromedia.com/flash/8/main/wwhelp/wwhimpl/common/html/wwhelp.htm?context=LiveDocs_Parts&file=00001567.html
    (eg., this.id3.songname or this.id3['songname'])
   */
    };

    this.resetProperties = function(bLoaded) {
      _t.bytesLoaded = null;
      _t.bytesTotal = null;
      _t.position = null;
      _t.duration = null;
      _t.durationEstimate = null;
      _t.loaded = false;
      _t.playState = 0;
      _t.paused = false;
      _t.readyState = 0; // 0 = uninitialised, 1 = loading, 2 = failed/error, 3 = loaded/success
      _t.muted = false;
      _t.didBeforeFinish = false;
      _t.didJustBeforeFinish = false;
      _t.isBuffering = false;
      _t.instanceOptions = {};
      _t.instanceCount = 0;
      _t.peakData = {
        left: 0,
        right: 0
      };
      _t.waveformData = {
        left: [],
        right: []
      };
      _t.eqData = [];
      // dirty hack for now: also have left/right arrays off this, maintain compatibility
      _t.eqData.left = [];
      _t.eqData.right = [];
    };

    _t.resetProperties();

    // --- public methods ---
    this.load = function(oOptions) {
      if (typeof oOptions != 'undefined') {
        _t._iO = _s._mergeObjects(oOptions);
        _t.instanceOptions = _t._iO;
      } else {
        oOptions = _t.options;
        _t._iO = oOptions;
        _t.instanceOptions = _t._iO;
        if (_t._lastURL && _t._lastURL != _t.url) {
          _s._wDS('manURL');
          _t._iO.url = _t.url;
          _t.url = null;
        }
      }

      if (typeof _t._iO.url == 'undefined') {
        _t._iO.url = _t.url;
      }

      _s._wD('soundManager.load(): '+_t._iO.url, 1);
      if (_t._iO.url == _t.url && _t.readyState !== 0 && _t.readyState != 2) {
        _s._wDS('onURL', 1);
        return false;
      }
      _t.url = _t._iO.url;
      _t._lastURL = _t._iO.url;
      _t.loaded = false;
      _t.readyState = 1;
      _t.playState = 0; // (oOptions.autoPlay?1:0); // if autoPlay, assume "playing" is true (no way to detect when it actually starts in Flash unless onPlay is watched?)
      try {
        if (_s.flashVersion == 8) {
          _s.o._load(_t.sID, _t._iO.url, _t._iO.stream, _t._iO.autoPlay, (_t._iO.whileloading?1:0));
        } else {
          _s.o._load(_t.sID, _t._iO.url, _t._iO.stream?true:false, _t._iO.autoPlay?true:false); // ,(_tO.whileloading?true:false)
          if (_t._iO.isMovieStar && _t._iO.autoLoad && !_t._iO.autoPlay) {
            // special case: MPEG4 content must start playing to load, then pause to prevent playing.
            _t.pause();
          }
        }
      } catch(e) {
        _s._wDS('smError', 2);
        _s._debugTS('onload', false);
        _s.onerror();
        _s.disable();
      }

    };

    this.unload = function() {
      // Flash 8/AS2 can't "close" a stream - fake it by loading an empty MP3
      // Flash 9/AS3: Close stream, preventing further load
      if (_t.readyState !== 0) {
        _s._wD('SMSound.unload(): "'+_t.sID+'"');
        if (_t.readyState != 2) { // reset if not error
          _t.setPosition(0, true); // reset current sound positioning
        }
        _s.o._unload(_t.sID, _s.nullURL);
        // reset load/status flags
        _t.resetProperties();
      }
    };

    this.destruct = function() {
      // kill sound within Flash
      _s._wD('SMSound.destruct(): "'+_t.sID+'"');
      _s.o._destroySound(_t.sID);
      _s.destroySound(_t.sID, true); // ensure deletion from controller
    };

    this.play = function(oOptions) {
	  var fN = 'SMSound.play(): ';
      if (!oOptions) {
        oOptions = {};
      }
      _t._iO = _s._mergeObjects(oOptions, _t._iO);
      _t._iO = _s._mergeObjects(_t._iO, _t.options);
      _t.instanceOptions = _t._iO;
      if (_t.playState == 1) {
        var allowMulti = _t._iO.multiShot;
        if (!allowMulti) {
          _s._wD(fN+'"'+_t.sID+'" already playing (one-shot)', 1);
          return false;
        } else {
          _s._wD(fN+'"'+_t.sID+'" already playing (multi-shot)', 1);
        }
      }
      if (!_t.loaded) {
        if (_t.readyState === 0) {
          _s._wD(fN+'Attempting to load "'+_t.sID+'"', 1);
          // try to get this sound playing ASAP
          //_t._iO.stream = true; // breaks stream=false case?
          _t._iO.autoPlay = true;
          // TODO: need to investigate when false, double-playing
          // if (typeof oOptions.autoPlay=='undefined') _tO.autoPlay = true; // only set autoPlay if unspecified here
          _t.load(_t._iO); // try to get this sound playing ASAP
        } else if (_t.readyState == 2) {
          _s._wD(fN+'Could not load "'+_t.sID+'" - exiting', 2);
          return false;
        } else {
          _s._wD(fN+'"'+_t.sID+'" is loading - attempting to play..', 1);
        }
      } else {
        _s._wD(fN+'"'+_t.sID+'"');
      }
      if (_t.paused) {
        _t.resume();
      } else {
        _t.playState = 1;
        if (!_t.instanceCount || _s.flashVersion > 8) {
          _t.instanceCount++;
        }
        _t.position = (typeof _t._iO.position != 'undefined' && !isNaN(_t._iO.position)?_t._iO.position:0);
        if (_t._iO.onplay) {
          _t._iO.onplay.apply(_t);
        }
        _t.setVolume(_t._iO.volume, true); // restrict volume to instance options only
        _t.setPan(_t._iO.pan, true);
        _s.o._start(_t.sID, _t._iO.loop || 1, (_s.flashVersion == 9?_t.position:_t.position / 1000));
      }
    };

    this.start = this.play; // just for convenience
    this.stop = function(bAll) {
      if (_t.playState == 1) {
        _t.playState = 0;
        _t.paused = false;
        // if (_s.defaultOptions.onstop) _s.defaultOptions.onstop.apply(_s);
        if (_t._iO.onstop) {
          _t._iO.onstop.apply(_t);
        }
        _s.o._stop(_t.sID, bAll);
        _t.instanceCount = 0;
        _t._iO = {};
        // _t.instanceOptions = _t._iO;
      }
    };

    this.setPosition = function(nMsecOffset, bNoDebug) {
      if (typeof nMsecOffset == 'undefined') {
        nMsecOffset = 0;
      }
      var offset = Math.min(_t.duration, Math.max(nMsecOffset, 0)); // position >= 0 and <= current available (loaded) duration
      _t._iO.position = offset;
      if (!bNoDebug) {
        // _s._wD('SMSound.setPosition('+nMsecOffset+')'+(nMsecOffset != offset?', corrected value: '+offset:''));
      }
      _s.o._setPosition(_t.sID, (_s.flashVersion == 9?_t._iO.position:_t._iO.position / 1000), (_t.paused || !_t.playState)); // if paused or not playing, will not resume (by playing)
    };

    this.pause = function() {
      if (_t.paused || _t.playState === 0) {
        return false;
      }
      _s._wD('SMSound.pause()');
      _t.paused = true;
      _s.o._pause(_t.sID);
      if (_t._iO.onpause) {
        _t._iO.onpause.apply(_t);
      }
    };

    this.resume = function() {
      if (!_t.paused || _t.playState === 0) {
        return false;
      }
      _s._wD('SMSound.resume()');
      _t.paused = false;
      _s.o._pause(_t.sID); // flash method is toggle-based (pause/resume)
      if (_t._iO.onresume) {
        _t._iO.onresume.apply(_t);
      }
    };

    this.togglePause = function() {
      _s._wD('SMSound.togglePause()');
      if (_t.playState === 0) {
        _t.play({
          position: (_s.flashVersion == 9?_t.position:_t.position / 1000)
        });
        return false;
      }
      if (_t.paused) {
        _t.resume();
      } else {
        _t.pause();
      }
    };

    this.setPan = function(nPan, bInstanceOnly) {
      if (typeof nPan == 'undefined') {
        nPan = 0;
      }
      if (typeof bInstanceOnly == 'undefined') {
        bInstanceOnly = false;
      }
      _s.o._setPan(_t.sID, nPan);
      _t._iO.pan = nPan;
      if (!bInstanceOnly) {
        _t.pan = nPan;
      }
    };

    this.setVolume = function(nVol, bInstanceOnly) {
      if (typeof nVol == 'undefined') {
        nVol = 100;
      }
      if (typeof bInstanceOnly == 'undefined') {
        bInstanceOnly = false;
      }
      _s.o._setVolume(_t.sID, (_s.muted && !_t.muted) || _t.muted?0:nVol);
      _t._iO.volume = nVol;
      if (!bInstanceOnly) {
        _t.volume = nVol;
      }
    };

    this.mute = function() {
      _t.muted = true;
      _s.o._setVolume(_t.sID, 0);
    };

    this.unmute = function() {
      _t.muted = false;
      var hasIO = typeof _t._iO.volume != 'undefined';
      _s.o._setVolume(_t.sID, hasIO?_t._iO.volume:_t.options.volume);
    };

    this.toggleMute = function() {
      if (_t.muted) {
        _t.unmute();
      } else {
        _t.mute();
      }
    };

    // --- "private" methods called by Flash ---

    this._whileloading = function(nBytesLoaded, nBytesTotal, nDuration) {
      if (!_t._iO.isMovieStar) {
        _t.bytesLoaded = nBytesLoaded;
        _t.bytesTotal = nBytesTotal;
        _t.duration = Math.floor(nDuration);
        _t.durationEstimate = parseInt((_t.bytesTotal / _t.bytesLoaded) * _t.duration, 10);
        if (_t.durationEstimate === undefined) {
          // reported bug?
          _t.durationEstimate = _t.duration;
        }
        if (_t.readyState != 3 && _t._iO.whileloading) {
          _t._iO.whileloading.apply(_t);
        }
      } else {
        _t.bytesLoaded = nBytesLoaded;
        _t.bytesTotal = nBytesTotal;
        _t.duration = Math.floor(nDuration);
        _t.durationEstimate = _t.duration;
        if (_t.readyState != 3 && _t._iO.whileloading) {
          _t._iO.whileloading.apply(_t);
        }
      }
    };

    this._onid3 = function(oID3PropNames, oID3Data) {
      // oID3PropNames: string array (names)
      // ID3Data: string array (data)
      _s._wD('SMSound._onid3(): "'+this.sID+'" ID3 data received.');
      var oData = [];
      for (var i=0, j = oID3PropNames.length; i<j; i++) {
        oData[oID3PropNames[i]] = oID3Data[i];
        // _s._wD(oID3PropNames[i]+': '+oID3Data[i]);
      }
      _t.id3 = _s._mergeObjects(_t.id3, oData);
      if (_t._iO.onid3) {
        _t._iO.onid3.apply(_t);
      }
    };

    this._whileplaying = function(nPosition, oPeakData, oWaveformDataLeft, oWaveformDataRight, oEQData) {

      if (isNaN(nPosition) || nPosition === null) {
        return false; // Flash may return NaN at times
      }
      if (_t.playState === 0 && nPosition > 0) {
        // can happen at the end of a video where nPosition == 33 for some reason, after finishing.???
        // can also happen with a normal stop operation. This resets the position to 0.
        // _s._writeDebug('Note: Not playing, but position = '+nPosition);
        nPosition = 0;
      }
      _t.position = nPosition;

	  if (_s.flashVersion > 8) {
        if (_t._iO.usePeakData && typeof oPeakData != 'undefined' && oPeakData) {
          _t.peakData = {
            left: oPeakData.leftPeak,
            right: oPeakData.rightPeak
          };
        }
        if (_t._iO.useWaveformData && typeof oWaveformDataLeft != 'undefined' && oWaveformDataLeft) {
          _t.waveformData = {
            left: oWaveformDataLeft.split(','),
            right: oWaveformDataRight.split(',')
          };
        }
        if (_t._iO.useEQData) {
          if (typeof oEQData != 'undefined' && oEQData.leftEQ) {
            var eqLeft = oEQData.leftEQ.split(',');
            _t.eqData = eqLeft;
            _t.eqData.left = eqLeft;
            if (typeof oEQData.rightEQ != 'undefined' && oEQData.rightEQ) {
              _t.eqData.right = oEQData.rightEQ.split(',');
            }
          }
        }
	  }

      if (_t.playState == 1) {
        // special case/hack: ensure buffering is false (instant load from cache, thus buffering stuck at 1?)
        if (_t.isBuffering) {
          _t._onbufferchange(0);
        }
        if (_t._iO.whileplaying) {
          _t._iO.whileplaying.apply(_t); // flash may call after actual finish
        }
        if (_t.loaded && _t._iO.onbeforefinish && _t._iO.onbeforefinishtime && !_t.didBeforeFinish && _t.duration - _t.position <= _t._iO.onbeforefinishtime) {
          _s._wD('duration-position &lt;= onbeforefinishtime: '+_t.duration+' - '+_t.position+' &lt= '+_t._iO.onbeforefinishtime+' ('+(_t.duration - _t.position)+')');
          _t._onbeforefinish();
        }
      }
    };

    this._onload = function(bSuccess) {
	  var fN = 'SMSound._onload(): ';
      bSuccess = (bSuccess == 1?true:false);
      _s._wD(fN+'"'+_t.sID+'"'+(bSuccess?' loaded.':' failed to load? - '+_t.url), (bSuccess?1:2));
      if (!bSuccess) {
        if (_s.sandbox.noRemote === true) {
          _s._wD(fN+_s._str('noNet'), 1);
        }
        if (_s.sandbox.noLocal === true) {
          _s._wD(fN+_s._str('noLocal'), 1);
        }
      }
      _t.loaded = bSuccess;
      _t.readyState = bSuccess?3:2;
      if (_t._iO.onload) {
        _t._iO.onload.apply(_t);
      }
    };

    this._onbeforefinish = function() {
      if (!_t.didBeforeFinish) {
        _t.didBeforeFinish = true;
        if (_t._iO.onbeforefinish) {
          _s._wD('SMSound._onbeforefinish(): "'+_t.sID+'"');
          _t._iO.onbeforefinish.apply(_t);
        }
      }
    };

    this._onjustbeforefinish = function(msOffset) {
      // msOffset: "end of sound" delay actual value (eg. 200 msec, value at event fire time was 187)
      if (!_t.didJustBeforeFinish) {
        _t.didJustBeforeFinish = true;
        if (_t._iO.onjustbeforefinish) {
          _s._wD('SMSound._onjustbeforefinish(): "'+_t.sID+'"');
          _t._iO.onjustbeforefinish.apply(_t);
        }
      }
    };

    this._onfinish = function() {
      // sound has finished playing
      // TODO: calling user-defined onfinish() should happen after setPosition(0)
      // OR: onfinish() and then setPosition(0) is bad.
      if (_t._iO.onbeforefinishcomplete) {
        _t._iO.onbeforefinishcomplete.apply(_t);
      }
      // reset some state items
      _t.didBeforeFinish = false;
      _t.didJustBeforeFinish = false;
      if (_t.instanceCount) {
        _t.instanceCount--;
        if (!_t.instanceCount) {
          // reset instance options
          // _t.setPosition(0);
          _t.playState = 0;
          _t.paused = false;
          _t.instanceCount = 0;
          _t.instanceOptions = {};
        }
        if (!_t.instanceCount || _t._iO.multiShotEvents) {
          // fire onfinish for last, or every instance
          if (_t._iO.onfinish) {
            _s._wD('SMSound._onfinish(): "'+_t.sID+'"');
            _t._iO.onfinish.apply(_t);
          }
        }
      } else {
        if (_t.useVideo) {
          // video has finished
          // may need to reset position for next play call, "rewind"
          // _t.setPosition(0);
        }
        // _t.setPosition(0);
      }

    };

    this._onmetadata = function(oMetaData) {
      // movieStar mode only
      var fN = 'SMSound.onmetadata()';
      _s._wD(fN);
      // Contains a subset of metadata. Note that files may have their own unique metadata.
      // http://livedocs.adobe.com/flash/9.0/main/wwhelp/wwhimpl/common/html/wwhelp.htm?context=LiveDocs_Parts&file=00000267.html
      if (!oMetaData.width && !oMetaData.height) {
        _s._wDS('noWH');
        oMetaData.width = 320;
        oMetaData.height = 240;
      }
      _t.metadata = oMetaData; // potentially-large object from flash
      _t.width = oMetaData.width;
      _t.height = oMetaData.height;
      if (_t._iO.onmetadata) {
        _s._wD(fN+': "'+_t.sID+'"');
        _t._iO.onmetadata.apply(_t);
      }
      _s._wD(fN+' complete');
    };

    this._onbufferchange = function(bIsBuffering) {
	  var fN = 'SMSound._onbufferchange()';
      if (_t.playState === 0) {
        // ignore if not playing
        return false;
      }
      if (bIsBuffering == _t.isBuffering) {
        // ignore initial "false" default, if matching
        _s._wD(fN+': ignoring false default / loaded sound');
        return false;
      }
      _t.isBuffering = (bIsBuffering == 1?true:false);
      if (_t._iO.onbufferchange) {
        _s._wD(fN+': '+bIsBuffering);
        _t._iO.onbufferchange.apply(_t);
      }
    };

    this._ondataerror = function(sError) {
      // flash 9 wave/eq data handler
      if (_t.playState > 0) { // hack: called at start, and end from flash at/after onfinish().
        _s._wD('SMSound._ondataerror(): '+sError);
        if (_t._iO.ondataerror) {
          _t._iO.ondataerror.apply(_t);
        }
      } else {
        // _s._wD('SMSound._ondataerror(): ignoring');
      }
    };

  }; // SMSound()

  this._onfullscreenchange = function(bFullScreen) {
    _s._wD('onfullscreenchange(): '+bFullScreen);
    _s.isFullScreen = (bFullScreen == 1?true:false);
    if (!_s.isFullScreen) {
      // attempt to restore window focus after leaving full-screen
      try {
        window.focus();
        _s._wD('window.focus()');
      } catch(e) {
        // oh well
      }
    }
  };

  // register a few event handlers
  if (window.addEventListener) {
    window.addEventListener('focus', _s.handleFocus, false);
    window.addEventListener('load', _s.beginDelayedInit, false);
    window.addEventListener('unload', _s.destruct, false);
    if (_s._tryInitOnFocus) {
      window.addEventListener('mousemove', _s.handleFocus, false); // massive Safari focus hack
    }
  } else if (window.attachEvent) {
    window.attachEvent('onfocus', _s.handleFocus);
    window.attachEvent('onload', _s.beginDelayedInit);
    window.attachEvent('unload', _s.destruct);
  } else {
    // no add/attachevent support - safe to assume no JS -> Flash either.
    _s._debugTS('onload', false);
    soundManager.onerror();
    soundManager.disable();
  }

  if (document.addEventListener) {
    document.addEventListener('DOMContentLoaded', _s.domContentLoaded, false);
  }

} // SoundManager()

// var SM2_DEFER = true; // un-comment or define in your own script to prevent immediate SoundManager() constructor call+start-up.
// if deferring, construct later with window.soundManager = new SoundManager(); followed by soundManager.beginDelayedInit();

if (typeof SM2_DEFER == 'undefined' || !SM2_DEFER) {
  soundManager = new SoundManager();
}


/*** jbolo_chat.js ***/

function gsCookie(name, value, options) {
    if (typeof value != 'undefined') { // name and value given, set cookie
        options = options || {};
        if (value === null) {
            value = '';
            options.expires = -1;
        }
        var expires = '';
        if (options.expires && (typeof options.expires == 'number' || options.expires.toUTCString)) {
            var date;
            if (typeof options.expires == 'number') {
                date = new Date();
                date.setTime(date.getTime() + (options.expires * 24 * 60 * 60 * 1000));
            } else {
                date = options.expires;
            }
            expires = '; expires=' + date.toUTCString(); // use expires attribute, max-age is not supported by IE
        }
        // CAUTION: Needed to parenthesize options.path and options.domain
        // in the following expressions, otherwise they evaluate to undefined
        // in the packed version for some reason...
        var path = options.path ? '; path=' + (options.path) : '';
        var domain = options.domain ? '; domain=' + (options.domain) : '';
        var secure = options.secure ? '; secure' : '';
        document.cookie = [name, '=', encodeURIComponent(value), expires, path, domain, secure].join('');
    } else { // only name given, get cookie
        var cookieValue = null;
        if (document.cookie.length>0 && document.cookie != '') {
            var cookies = document.cookie.split(';');
            for (var i = 0; i < cookies.length; i++) {  
                var cookie = jQuery.trim(cookies[i]);
                // Does this cookie string begin with the name we want?
                if (cookie.substring(0, name.length + 1) == (name + '=')) {
                    cookieValue = decodeURIComponent(cookie.substring(name.length + 1));
                    break;
                }
            }
        }
        return cookieValue;
    }
};




function callbackFn(status) {
	if (status.success) {
		var obj = status.ref;
		window.onload = function() {
			if (obj && typeof obj.loadsndfx != "undefined") {
				//LOAD MP3'S
				obj.loadsndfx('doh.mp3');
				//ATTACH SNDFX TO BUTTONS
				
				//ONLOAD EVENT
				
			}
		};
	}
};

/*

Copyright (c) 2009 Anant Garg (anantgarg.com | inscripts.com)

This script may be used for non-commercial purposes only. For any
commercial purposes, please contact the author at 
anant.garg@inscripts.com

THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES
OF MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT
HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY,
WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING
FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR
OTHER DEALINGS IN THE SOFTWARE.

*/


var jb_windowFocus = true;
var jb_username;
var jb_chatHeartbeatCount = 0;
var jb_minChatHeartbeat = 1000;
var jb_maxChatHeartbeat = 33000;
var jb_chatHeartbeatTime = jb_minChatHeartbeat;
var jb_originalTitle;
var jb_blinkOrder = 0;

var jb_chatboxFocus = new Array();
var jb_newMessages = new Array();
var jb_newMessagesWin = new Array();
var jb_chatBoxes = new Array();
var chattile='';

soundManager.url = jb_abs_link+'/components/com_jbolo/sound/';
soundManager.onload = function() {
soundManager.createSound('newmsg',jb_abs_link+'/components/com_jbolo/sound/newmsg.mp3');
};

jQuery(document).ready(function(){

	jb_originalTitle = document.title;
	startChatSession();

	jQuery([window, document]).blur(function(){
		jb_windowFocus = false;
	}).focus(function(){
		jb_windowFocus = true;
		document.title = jb_originalTitle;
	});
	for (x in jb_newMessagesWin) { 
			
			jb_newMessagesWin[x] = false;
		}
});

function strstr( haystack, needle ,bool) {
    var pos = 0;
     
    haystack += '';
    pos = haystack.indexOf( needle );
    if (pos == -1) {
        return false;
    } else{
        if( bool ){
            return haystack.substr( 0, pos );
        } else{
            return haystack.slice( pos );
        }
    }
}



function restructureChatBoxes(){
	var align = 0;
	for (x in jb_chatBoxes) {
		if (jb_chatBoxes) {
			chatboxtitle = jb_chatBoxes[x];
			if ((strstr(jb_chatBoxes[x], 'function')) == false) {
				if (jQuery("#chatbox_" + chatboxtitle).css('display') != 'none') {
					if (align == 0) {
						jQuery("#chatbox_" + chatboxtitle).css('right', '20px');
					}
					else {
						var width = (align) * (225 + 7) + 20;
						jQuery("#chatbox_" + chatboxtitle).css('right', width + 'px');
					}
					align++;
				}
			}
		}	
	}
}

function chatWith(chatuser) {  
	createChatBox(chatuser); 
	jQuery("#chatbox_"+chatuser+" .chatboxtextarea").focus();
}

function createChatBox(chatboxtitle,minimizeChatBox) {
	if (jQuery("#chatbox_"+chatboxtitle).length > 0) { 
		if (jQuery("#chatbox_"+chatboxtitle).css('display') == 'none') {
			jQuery("#chatbox_"+chatboxtitle).css('display','block');
			restructureChatBoxes();
		}
		// Module Click Fixed
		jQuery("#chatbox_"+chatboxtitle+" .chatboxcontent").css('display','block');
		jQuery("#chatbox_"+chatboxtitle+" .chatboxinput").css('display','block');
		jQuery('#'+chatboxtitle+'_thumb').css('display','block');  
		// IE positioning hack
		if (jQuery.browser.msie && jQuery.browser.version.substr(0,1)<8) {
		jQuery('#chatbox_'+chatboxtitle).removeClass('chatbox_m');
		}

		jQuery("#chatbox_"+chatboxtitle+" .chatboxtextarea").focus();
		return;
	}
	

	jQuery(" <div />" ).attr("id","chatbox_"+chatboxtitle)
	.addClass("chatbox")
	.html('<div class="chatboxhead" onclick="toggleChatBoxGrowth(\''+chatboxtitle+'\')"><div class="chatboxtitle"></div><div class="chatboxoptions"><span class="minimize">_</span> <span onclick="closeChatBox(\''+chatboxtitle+'\')" class="minimize">X</span></div><br clear="all"/></div><div id='+chatboxtitle+'_thumb class="chatboxistatus"></div><div class="chatboxcontent"></div><div class="chatboxoffline">'+jb_offlinemsg+'</div><div class="chatboxinput"><textarea class="chatboxtextarea" onkeydown="javascript:return checkChatBoxInputKey(event,this,\''+chatboxtitle+'\');"></textarea></div>')
	.appendTo(jQuery( "body" ));

	jQuery("#chatbox_"+chatboxtitle).css('bottom', '0px');
	jQuery("#chatbox_"+chatboxtitle).css('z-index', 1000);

	chattitle = chatboxtitle;
	jQuery.ajax({
	  url: jb_abs_link+"index.php?option=com_jbolo&action=getinfo&uid="+chatboxtitle,
	  cache: false,
	  dataType: "json",
	  success: function(udetails) { 
	   	chattitle = udetails.name;
			//jQuery("#chatbox_"+chatboxtitle+" .chatboxtitle").html(chattitle.substr(0,25));
	/* Changes for status icons */
			
			if(udetails.thumb != '')
			{
				var newHTML = "<div class=jfb_insideimage><img class=timgidclass src="+udetails.thumb+" /></div>";
				document.getElementById(chatboxtitle+"_thumb").innerHTML = newHTML;
			}
				
			if(udetails.status == '1')
			{	
				jQuery("#chatbox_"+chatboxtitle+" .chatboxtitle").html(chattitle.substr(0,25));
				jQuery("#chatbox_"+chatboxtitle+" .chatboxtitle").css({'padding-left':
'16px','width':'178px','height': '13px', 'margin-top':'1px', 'background':'url(components/com_jbolo/img/icon-lightblue.gif) no-repeat 0px 2px'});
			}
			else if(udetails.status == '2')
			{
				jQuery("#chatbox_"+chatboxtitle+" .chatboxtitle").html(chattitle.substr(0,25));
				jQuery("#chatbox_"+chatboxtitle+" .chatboxtitle").css({'padding-left':
'16px','height':'13px','margin-top':'1px', 'width':'178px','background':'url(components/com_jbolo/img/icon-lightblue.gif) no-repeat 0px -24px'});
			}
			else
			{
				jQuery("#chatbox_"+chatboxtitle+" .chatboxtitle").html(chattitle.substr(0,25));
				jQuery("#chatbox_"+chatboxtitle+" .chatboxtitle").css({'padding-left':
'16px','height':'13px','margin-top':'1px', 'width':'178px','background':'url(components/com_jbolo/img/icon-lightblue.gif) no-repeat 0px -37px'});
			}
			/* END Changes for status icons */
		}
	});
    
	chatBoxeslength = 0;
	
	for (x in jb_chatBoxes) {
		if (jb_chatBoxes) {
			if ((strstr(jb_chatBoxes[x], 'function')) == false) {
				if (jQuery("#chatbox_" + jb_chatBoxes[x]).css('display') != 'none') {
					chatBoxeslength++;
				}
			}
		}	
	}


	if (chatBoxeslength == 0) {
		jQuery("#chatbox_"+chatboxtitle).css('right', '20px');
	} else {
		width = (chatBoxeslength)*(225+7)+20;
		jQuery("#chatbox_"+chatboxtitle).css('right', width+'px');
	}
	
	jb_chatBoxes.push(chatboxtitle);

	if (minimizeChatBox == 1) {
		minimizedChatBoxes = new Array();

		if (gsCookie('chatbox_minimized')) {
			minimizedChatBoxes = gsCookie('chatbox_minimized').split(/\|/);
		}
		minimize = 0;
		for (j=0;j<minimizedChatBoxes.length;j++) { 
			if (minimizedChatBoxes[j]) {
				if (minimizedChatBoxes[j] == chatboxtitle) {
					minimize = 1;
				}
			}	
		}

		if (minimize == 1) {
			jQuery('#chatbox_'+chatboxtitle+' .chatboxcontent').css('display','none');
			jQuery('#chatbox_'+chatboxtitle+' .chatboxinput').css('display','none'); 
			jQuery('#'+chatboxtitle+'_thumb').css('display','none');    
			jQuery('#chatbox_'+chatboxtitle+' .chatboxoffline').css('display','none'); 
		}
	}

	jb_chatboxFocus[chatboxtitle] = false;

	jQuery("#chatbox_"+chatboxtitle+" .chatboxtextarea").blur(function(){
		jb_chatboxFocus[chatboxtitle] = false;
		jQuery("#chatbox_"+chatboxtitle+" .chatboxtextarea").removeClass('chatboxtextareaselected');
	}).focus(function(){
		jb_chatboxFocus[chatboxtitle] = true;
		jb_newMessages[chatboxtitle] = false;
		jQuery('#chatbox_'+chatboxtitle+' .chatboxhead').removeClass('chatboxblink');
		jQuery("#chatbox_"+chatboxtitle+" .chatboxtextarea").addClass('chatboxtextareaselected');
	});

	jQuery("#chatbox_"+chatboxtitle).click(function() {
		if (jQuery('#chatbox_'+chatboxtitle+' .chatboxcontent').css('display') != 'none') {
			jQuery("#chatbox_"+chatboxtitle+" .chatboxtextarea").focus();
		}
	});

	jQuery("#chatbox_"+chatboxtitle).show();
}


function chatHeartbeat(){ 

	var itemsfound = 0;
	
	if (jb_windowFocus == false) {
 		
		var blinkNumber = 0;
		var titleChanged = 0;
		for (x in jb_newMessagesWin) {
			if (jb_newMessagesWin[x]) {
				
				if (jb_newMessagesWin[x]!=''&& jb_newMessagesWin[x]!='undefined') {
					
					++blinkNumber;
					if (blinkNumber >= jb_blinkOrder) {
						
						document.title = jb_newMessagesWin[x];
						titleChanged = 1;
						break;
					}
				}
			}	
		}
		
		if (titleChanged == 0) {
			document.title = jb_originalTitle;
			jb_blinkOrder = 0;
		} else {
			++jb_blinkOrder;
			
		}

	} else {
		for (x in jb_newMessagesWin) { 
			
			jb_newMessagesWin[x] = false;
		}
	}

	for (x in jb_newMessages) { 
		if (jb_newMessages[x] == true) {
			if (jb_chatboxFocus[x] == false) {
				//FIXME: add toggle all or none policy, otherwise it looks funny
				
				jQuery('#chatbox_'+x+' .chatboxhead').toggleClass('chatboxblink');
			}
		}
	}
	var jb_usrno = jQuery("#jbusers>li").length;
	jQuery.ajax({
	  url: jb_abs_link+"index.php?option=com_jbolo&action=chatheartbeat&userno="+jb_usrno,
	  cache: false,
	  dataType: "json",
	  success: function(data) { 

		jQuery.each(data.l, function(i,item){

			if (item)	{ // fix strange ie bug
				if(this.m!=null && this.show!=null)
				{
					var chatboxtitle = this.f;
					
					thismessage = jb_doReplace(this.m);
					
					if (jQuery("#chatbox_"+chatboxtitle).length <= 0) {
						createChatBox(chatboxtitle);
					}
					if (jQuery("#chatbox_"+chatboxtitle).css('display') == 'none') {
						jQuery("#chatbox_"+chatboxtitle).css('display','block');
						restructureChatBoxes();
					}
					
					if (this.s == 1) {
						this.f = trans_me;//jb_username;
					} else if (this.s == 0) {
						this.f = this.show;
					}
					if(this.lst!=null)
					{
						jQuery("#jbusers").html(this.lst);
					}
					jQuery('#chatbox_'+chatboxtitle+' .chatboxcontent').css('height','200px');
					jQuery('#jb_user_'+chatboxtitle).css('display','block');
	
					if (this.s == 2) {
						jQuery("#chatbox_"+chatboxtitle+" .chatboxcontent").append('<div class="chatboxmessage"><span class="chatboxinfo">'+thismessage+'</span></div>');
					} else {
	
						jb_newMessages[chatboxtitle] = true;
						if(jb_windowFocus == false)
						{
							soundManager.play('newmsg');
						}
						jb_newMessagesWin[chatboxtitle] = this.show + " " + jb_says;
						jQuery("#chatbox_"+chatboxtitle+" .chatboxcontent").append('<div class="chatboxmessage"><span class="chatboxmessagefrom">'+this.f+':&nbsp;&nbsp;</span><span class="chatboxmessagecontent">'+thismessage+'</span></div>');
					}
					jQuery("#chatbox_"+chatboxtitle+" .chatboxcontent").scrollTop(jQuery("#chatbox_"+chatboxtitle+" .chatboxcontent")[0].scrollHeight);
					itemsfound += 1;
					chatboxtitle= null;
				}
				else
				{
					jQuery("#jbusers").html(this.lst);
					//jQuery('#chatbox_'+chatboxtitle+' .chatboxoffline').css('display','none');
					jQuery('#chatbox_'+chatboxtitle+' .chatboxcontent').css('height','200px');
				}
				
			} 
		});

		jb_chatHeartbeatCount++;

		if (itemsfound > 0) {
			jb_chatHeartbeatTime = jb_minChatHeartbeat;
			jb_chatHeartbeatCount = 1;
		} else if (jb_chatHeartbeatCount >= 10) {
			jb_chatHeartbeatTime *= 2;
			jb_chatHeartbeatCount = 1;
			if (jb_chatHeartbeatTime > jb_maxChatHeartbeat) {
				jb_chatHeartbeatTime = jb_maxChatHeartbeat;
			}
		}

		setTimeout('chatHeartbeat();',jb_chatHeartbeatTime);
	}});

}

function closeChatBox(chatboxtitle) {
	jQuery('#chatbox_'+chatboxtitle).css('display','none');
	restructureChatBoxes();

	jQuery.post(jb_abs_link+"index.php?option=com_jbolo&action=closechat", { chatbox: chatboxtitle} , function(data){	
	});

}

function toggleChatBoxGrowth(chatboxtitle) {
	if (jQuery('#chatbox_'+chatboxtitle+' .chatboxcontent').css('display') == 'none') {  
		
		var minimizedChatBoxes = new Array();
		
		if (gsCookie('chatbox_minimized')) {
			minimizedChatBoxes = gsCookie('chatbox_minimized').split(/\|/);
		}

		var newCookie = '';

		for (i=0;i<minimizedChatBoxes.length;i++) { 
			if (minimizedChatBoxes[i] != chatboxtitle) {
				newCookie += chatboxtitle+'|';
			}
		}

		newCookie = newCookie.slice(0, -1)
	

		gsCookie('chatbox_minimized', newCookie);
		jQuery('#chatbox_'+chatboxtitle+' .chatboxcontent').css('display','block');
		jQuery('#chatbox_'+chatboxtitle+' .chatboxinput').css('display','block');
		jQuery('#'+chatboxtitle+'_thumb').css('display','block');              ///**** Added for Thumbnails ***///
		jQuery("#chatbox_"+chatboxtitle+" .chatboxcontent").scrollTop(jQuery("#chatbox_"+chatboxtitle+" .chatboxcontent")[0].scrollHeight);

		// IE positioning hack
		if (jQuery.browser.msie && jQuery.browser.version.substr(0,1)<8) {
			jQuery('#chatbox_'+chatboxtitle).removeClass('chatbox_m');
		}
	} else {
		
		var newCookie = chatboxtitle;

		if (gsCookie('chatbox_minimized')) {
			newCookie += '|'+gsCookie('chatbox_minimized');
		}


		gsCookie('chatbox_minimized',newCookie);
		jQuery('#chatbox_'+chatboxtitle+' .chatboxcontent').css('display','none');
		jQuery('#chatbox_'+chatboxtitle+' .chatboxinput').css('display','none');
		jQuery('#'+chatboxtitle+'_thumb').css('display','none');             ///**** Added for Thumbnails ***///

		// IE positioning hack
		if (jQuery.browser.msie && jQuery.browser.version.substr(0,1)<8) {
			jQuery('#chatbox_'+chatboxtitle).addClass('chatbox_m');
		}
	}
	
}

var jb_message=" ";

	var maxHeight = 94;

function checkChatBoxInputKey(event,chatboxtextarea,chatboxtitle) {  
 //alert(jQuery(chatboxtextarea).val());

	if(event.keyCode == 13 && event.shiftKey == 0)  {
		jb_message = jQuery(chatboxtextarea).val();
		msg = jb_message.replace(/^\s+|\s+$/g,"");

		jQuery(chatboxtextarea).val('');
		jQuery(chatboxtextarea).focus();
		jQuery(chatboxtextarea).css('height','44px');
		if (msg != '') {
			jQuery.post(jb_abs_link+"index.php?option=com_jbolo&action=sendchat", {to: chatboxtitle, message: msg} , function(sendop){
				jb_message = msg.replace(/</g,"&lt;").replace(/>/g,"&gt;").replace(/\"/g,"&quot;");
				nmessage = jb_doReplace(jb_message);

				var the_length=sendop.length;
				var last_char=sendop.charAt(the_length-1);
				if(last_char=='0')
				{
					sendop = sendop.substring(0, sendop.length-1);
					jQuery("#chatbox_"+chatboxtitle+" .chatboxoffline").html(jb_offlinemsg);
					jQuery('#chatbox_'+chatboxtitle+' .chatboxoffline').css('display','block');
					jQuery('#chatbox_'+chatboxtitle+' .chatboxcontent').css('height','184px');
					jQuery('#jb_user_'+chatboxtitle).css('display','none');
				}
				else if(last_char=='2')
				{
					sendop = sendop.substring(0, sendop.length-1);
					jQuery("#chatbox_"+chatboxtitle+" .chatboxoffline").html(jb_awaymsg);
					jQuery('#chatbox_'+chatboxtitle+' .chatboxoffline').css('display','block');
					jQuery('#chatbox_'+chatboxtitle+' .chatboxcontent').css('height','184px');
				}
				else
				{
					jQuery('#chatbox_'+chatboxtitle+' .chatboxoffline').css('display','none');
					jQuery('#chatbox_'+chatboxtitle+' .chatboxcontent').css('height','200px');
					jQuery('#jb_user_'+chatboxtitle).css('display','block');
				}
				jQuery("#chatbox_"+chatboxtitle+" .chatboxcontent").append('<div class="chatboxmessage"><span class="chatboxmessagefrom">'+sendop+':&nbsp;&nbsp;</span><span class="chatboxmessagecontent">'+nmessage+'</span></div>');
				jQuery("#chatbox_"+chatboxtitle+" .chatboxcontent").scrollTop(jQuery("#chatbox_"+chatboxtitle+" .chatboxcontent")[0].scrollHeight);
			});
		}
		jb_chatHeartbeatTime = jb_minChatHeartbeat;
		jb_chatHeartbeatCount = 1;

		return false;
	}

	var adjustedHeight = chatboxtextarea.clientHeight;
//	alert(adjustedHeight);
	if(adjustedHeight)
	{
	if (maxHeight > adjustedHeight) {
		adjustedHeight = Math.max(chatboxtextarea.scrollHeight, adjustedHeight);
		if (maxHeight)
			adjustedHeight = Math.min(maxHeight, adjustedHeight);
		if (adjustedHeight > chatboxtextarea.clientHeight)
			jQuery(chatboxtextarea).css('height',adjustedHeight+8 +'px');
	}
	}	
	 else {
		jQuery(chatboxtextarea).css('overflow','auto');
	}
	
}

function startChatSession(){  
	jQuery.ajax({
	  url: jb_abs_link+"index.php?option=com_jbolo&action=startchatsession",
	  cache: false,
	  dataType: "json",
	  success: function(data) {  
		
		 jb_username = data.jb_username;
		if (jb_username == "undefined") { jb_username = "Guest"; }

		jQuery.each(data.items, function(i,item){ 
			if (this)	{ // fix strange ie bug
				//alert(this.f);
				var chatboxtitle = this.f;
				thismessage = jb_doReplace(this.m);
				
				if (jQuery("#chatbox_"+chatboxtitle).length <= 0) {
					createChatBox(chatboxtitle,1);
				}
				
				if (this.s == 1) {
					this.f = data.me;
				} else if (this.s == 0) {
					this.f = this.show;
				}

				if (this.s == 2) {
					jQuery("#chatbox_"+chatboxtitle+" .chatboxcontent").append('<div class="chatboxmessage"><span class="chatboxinfo">'+thismessage+'</span></div>');
				} else {
					jQuery("#chatbox_"+chatboxtitle+" .chatboxcontent").append('<div class="chatboxmessage"><span class="chatboxmessagefrom">'+this.f+':&nbsp;&nbsp;</span><span class="chatboxmessagecontent">'+thismessage+'</span></div>');
				}
			}
		});
		
		for (i=0;i<jb_chatBoxes.length;i++) { 
			chatboxtitle = jb_chatBoxes[i];
			jQuery("#chatbox_"+chatboxtitle+" .chatboxcontent").scrollTop(jQuery("#chatbox_"+chatboxtitle+" .chatboxcontent")[0].scrollHeight);
			setTimeout('jQuery("#chatbox_"+chatboxtitle+" .chatboxcontent").scrollTop(jQuery("#chatbox_"+chatboxtitle+" .chatboxcontent")[0].scrollHeight);', 100); // yet another strange ie bug
		}
	
	setTimeout('chatHeartbeat();',jb_chatHeartbeatTime);
		
	}});
}

function chat_status(currentstatus) {
	var insidetext;
	if(currentstatus==0)
	{
		insidetext='(Invisible)';
	}
	else if(currentstatus==1)
	{
		insidetext='(Available)';
	}
	else if(currentstatus==2)
	{
		insidetext='(Away)';
	}
	document.getElementById("inside-ch-box-tl").innerHTML = insidetext;
jQuery.post(jb_abs_link+"index2.php?option=com_jbolo&action=chat_status", { stats: currentstatus} , function(data){	
	});
	jQuery("#ch_box_status").toggle();
}

