var cb = {

expandDuration : 150, 
restoreDuration : 0,
marginLeft : 15,
marginRight : 15,
marginTop : 15,
marginBottom : 15,
zIndexCounter : 1001, 
loadingOpacity : 0.75,
minWidth: 200,
minHeight: 200,

expanders : [],
overrides : [
	
	'minWidth',
	'minHeight',
	'maxWidth',
	'maxHeight',
	'slideshowGroup',
	'easing',
	'easingClose',
	'fadeInOut',
	'src'
],
clones : {},
ie : (document.all && !window.opera),
safari : /Safari/.test(navigator.userAgent),

$ : 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) cb.setAttribs(el, attribs);
	if (nopad) cb.setStyles(el, {padding: 0, border: 'none', margin: 0});
	if (styles) cb.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) {
		if (cb.ie && x == 'opacity') {
			if (styles[x] > 0.99) el.style.removeAttribute('filter');
			else el.style.filter = 'alpha(opacity='+ (styles[x] * 100) +')';
		}
		else el.style[x] = styles[x];
	}
},

ieVersion : function () {
	var arr = navigator.appVersion.split("MSIE");
	return arr[1] ? parseFloat(arr[1]) : null;
},

getPageSize : function () {
	var d = document, w = window, iebody = d.compatMode && d.compatMode != 'BackCompat' 
		? d.documentElement : d.body;
	
	var width = cb.ie ? iebody.clientWidth : 
			(d.documentElement.clientWidth || self.innerWidth),
		height = cb.ie ? iebody.clientHeight : self.innerHeight;
	
	return {
		width: width,
		height: height,		
		scrollLeft: cb.ie ? iebody.scrollLeft : pageXOffset,
		scrollTop: cb.ie ? iebody.scrollTop : pageYOffset
	}
},

getPosition : function(el)	{
	var p = { x: el.offsetLeft, y: el.offsetTop };
	while (el.offsetParent)	{
		el = el.offsetParent;
		p.x += el.offsetLeft;
		p.y += el.offsetTop;
		if (el != document.body && el != document.documentElement) {
			p.x -= el.scrollLeft;
			p.y -= el.scrollTop;
		}
	}
	return p;
},

expand : function(a, params, custom, type) {
    if (!a) a = cb.createElement('a', null, { display: 'none' }, cb.container);
	if (typeof a.getParams == 'function') return params;	
	try {	
		new cb.Expander(a, params, custom);
		return false;
	} catch (e) { return true; }
},

getParam : function (a, param) {
	a.getParams = a.onclick;
	var p = a.getParams ? a.getParams() : null;
	a.getParams = null;
	
	return (p && typeof p[param] != 'undefined') ? p[param] : 
		(typeof cb[param] != 'undefined' ? cb[param] : null);
},

getSrc : function (a) {
	var src = cb.getParam(a, 'src');
	if (src) return src;
	return a.href;
},

discardElement : function(d) {
	cb.garbageBin.appendChild(d);
	cb.garbageBin.innerHTML = '';
},

getWrapperKey : function (element, expOnly) {
	var el, re = /^cb-wrapper-([0-9]+)$/;
	el = element;
	while (el.parentNode)	{
		if (el.id && re.test(el.id)) return el.id.replace(re, "$1");
		el = el.parentNode;
	}
	if (!expOnly) {
		el = element;
		while (el.parentNode)	{
			if (el.tagName && cb.isHsAnchor(el)) {
				for (var key = 0; key < cb.expanders.length; key++) {
					var exp = cb.expanders[key];
					if (exp && exp.a == el) return key;
				}
			}
			el = el.parentNode;
		}
	}
	return null; 
},

getExpander : function (el, expOnly) {
	if (typeof el == 'undefined') return cb.expanders[cb.focusKey] || null;
	if (typeof el == 'number') return cb.expanders[el] || null;
	if (typeof el == 'string') el = cb.$(el);
	return cb.expanders[cb.getWrapperKey(el, expOnly)] || null;
},

isHsAnchor : function (a) {
	return (a.onclick && a.onclick.toString().replace(/\s/g, ' ').match(/cb.(htmlE|e)xpand/));
},

mouseClickHandler : function(e) 
{	
	if (!e) e = window.event;
	if (e.button > 1) return true;
	if (!e.target) e.target = e.srcElement;
	
	var el = e.target;
	while (el.parentNode
		&& !(/cb-(image|move|html|resize)/.test(el.className)))
	{
		el = el.parentNode;
	}
	var exp = cb.getExpander(el);
	if (exp && (exp.isClosing || !exp.isExpanded)) return true;
		
	if (exp && e.type == 'mousedown') {
		if (e.target.form) return true;
		var match = el.className.match(/cb-(image|move|resize)/);
		if (match) {
			cb.dragArgs = { exp: exp };
			
			if (/cb-(image|html)-blur/.test(exp.content.className)) {
				exp.focus();
				cb.hasFocused = true;
			}
			return false;
		}
	} else if (e.type == 'mouseup') {
		
		if (cb.dragArgs) {
			
			if (!cb.hasFocused && !/(move|resize)/.test(cb.dragArgs.type)) {
				exp.close();
			}
			
			cb.hasFocused = false;
			cb.dragArgs = null;
		
		} 
	}
	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;
		}
	}
},

init : function () {
	if (!cb.container) {
		cb.container = cb.createElement('div', { }, {
				position: 'absolute', 
				left: 0, 
				top: 0, 
				width: '100%', 
				zIndex: cb.zIndexCounter,
				direction: 'ltr'
			}, 
			document.body,
			true
		);
		
		cb.garbageBin = cb.createElement('div', null, { display: 'none' }, cb.container);
		
		Math.linearTween = function (t, b, c, d) {
			return c*t/d + b;
		};
		Math.easeInQuad = function (t, b, c, d) {
			return c*(t/=d)*t + b;
		};
	}
},

domReady : function() {
	cb.isDomReady = true;
	if (cb.onDomReady) cb.onDomReady();
},

close : function(el) {
	var exp = cb.getExpander(el);
	if (exp) exp.close();
	return false;
}
};

cb.Dimension = function(exp, dim) {
	this.exp = exp;
	this.dim = dim;
	this.ucwh = dim == 'x' ? 'Width' : 'Height';
	this.wh = this.ucwh.toLowerCase();
	this.uclt = dim == 'x' ? 'Left' : 'Top';
	this.lt = this.uclt.toLowerCase();
	this.ucrb = dim == 'x' ? 'Right' : 'Bottom';
	this.rb = this.ucrb.toLowerCase();
};

cb.Dimension.prototype = {
get : function(key) {
	switch (key) {
		case 'wsize':
			return this.size + 2 * this.cb;
		case 'fitsize':
			return this.clientSize - this.marginMin - this.marginMax;
		case 'opos':
			return this.pos;
		case 'osize':
			return this.get('wsize');
		
	}
},
calcBorders: function() {
	this.cb = (this.exp.content['offset'+ this.ucwh] - this.t) / 2;
	this.marginMax = cb['margin'+ this.ucrb] + 2 * this.cb;
},
calcThumb: function() {
	this.t = this.exp.el[this.wh] ? parseInt(this.exp.el[this.wh]) : 
		this.exp.el['offset'+ this.ucwh];
	this.tpos = this.exp.tpos[this.dim];
	this.tb = (this.exp.el['offset'+ this.ucwh] - this.t) / 2;
	if (this.tpos == 0) {
		this.tpos = (cb.page[this.wh] / 2) + cb.page['scroll'+ this.uclt];		
	};
},
calcExpanded: function() {
	this.justify = 'auto';
	this.pos = this.tpos - this.cb + this.tb;
	this.size = Math.min(this.full, this.exp['max'+ this.ucwh] || this.full);
	this.minSize =  this.full;
	this.marginMin = cb['margin'+ this.uclt];
	this.scroll = cb.page['scroll'+ this.uclt];
	this.clientSize = cb.page[this.wh];
},
setSize: function(i) {
	this.size = i;
	this.exp.content.style[this.wh] = i +'px';
	this.exp.wrapper.style[this.wh] = this.get('wsize') +'px';
},
setPos: function(i) {
	this.pos = i;
	this.exp.wrapper.style[this.lt] = i +'px';	
	
}
};

cb.Expander = function(a, params, custom, contentType) {
	if (document.readyState && cb.ie && !cb.isDomReady) {
		cb.onDomReady = function() {
			new cb.Expander(a, params, custom, contentType);
		};
		return;
	} 
	this.a = a;
	this.custom = custom;
	this.contentType = contentType || 'image';
	this.isImage = !this.isHtml;
	cb.init();
	var key = this.key = cb.expanders.length;
	for (var i = 0; i < cb.overrides.length; i++) {
		var name = cb.overrides[i];
		this[name] = params && typeof params[name] != 'undefined' ?
			params[name] : cb[name];
	}
	if (!this.src) this.src = a.href;
	var el = (params && params.thumbnailId) ? cb.$(params.thumbnailId) : a;
	el = this.thumb = el.getElementsByTagName('img')[0] || el;
	this.thumbsUserSetId = el.id || a.id;
	
	for (var i = 0; i < cb.expanders.length; i++) {
		if (cb.expanders[i] && cb.expanders[i].a == a) {
			cb.expanders[i].focus();
			return false;
		}
	}	
	for (var i = 0; i < cb.expanders.length; i++) {
		if (cb.expanders[i] && cb.expanders[i].thumb != el && !cb.expanders[i].onLoadStarted) {
			cb.expanders[i].cancelLoading();
		}
	}
	cb.expanders[this.key] = this;
	
	this.el = el;
	this.tpos = cb.getPosition(el);
	cb.page = cb.getPageSize();
	var x = this.x = new cb.Dimension(this, 'x');
	x.calcThumb();
	var y = this.y = new cb.Dimension(this, 'y');
	y.calcThumb();
	
	this.wrapper = cb.createElement(
		'div', {
			id: 'cb-wrapper-'+ this.key
		}, {
			visibility: 'hidden',
			position: 'absolute',
			zIndex: cb.zIndexCounter++
		}, null, true );
		this[this.contentType +'Create']();
	return true;
};

cb.Expander.prototype = {

imageCreate : function() {
	var exp = this;
	
	var img = document.createElement('img');
    this.content = img;
    img.onload = function () {
    	if (cb.expanders[exp.key]) exp.contentLoaded(); 
	};
    if (cb.blockRightClick) img.oncontextmenu = function() { return false; };
    cb.setStyles(img, {
    	visibility: 'hidden',
    	display: 'block',
    	position: 'absolute',
		maxWidth: '9999px',
		zIndex: 3
	});
    
    if (cb.safari) cb.container.appendChild(img);
    if (cb.ie && cb.flushImgSize) img.src = null;
	img.src = this.src;
	img.alt = this.thumb.alt;
	img.className = "thumb_large";
	img.exp = this;
	img.onmouseover = function () {this.style.cursor = 'pointer'};
	img.onmouseout = function () {setTimeout(function(){img.exp.close();}, 250);};
	
	this.showLoading();
},

contentLoaded : function() {
	try {	
		if (!this.content) return;
		this.content.onload = null;
		if (this.onLoadStarted) return;
		else this.onLoadStarted = true;
		
		var x = this.x, y = this.y;
		
		x.full = this.content.width;
		y.full = this.content.height;
		
		cb.setStyles(this.content, {
			width: this.x.t +'px',
			height: this.y.t +'px'
		});
		
		this.wrapper.appendChild(this.content);
		cb.setStyles (this.wrapper, {
			left: this.x.tpos +'px',
			top: this.y.tpos +'px'
		});
		cb.container.appendChild(this.wrapper);
		
		x.calcBorders();
		y.calcBorders();
		
		var ratio = x.full / y.full;
		
		x.calcExpanded();
		this.justify(x);
		
		y.calcExpanded();
		this.justify(y);
		this.show();
		
	} catch (e) {
		window.location.href = this.src;
	}
},

justify : function (p, moveOnly) {
	var tgtArr, tgt = p.target, dim = p == this.x ? 'x' : 'y';
	
		var hasMovedMin = false;
			p.pos = Math.round(p.pos - ((p.get('wsize') - p.t) / 2));
		if (p.pos < p.scroll + p.marginMin) {
			p.pos = p.scroll + p.marginMin;
			hasMovedMin = true;		
		}
		if (p.pos + p.get('wsize') > p.scroll + p.clientSize - p.marginMax) {
			if (!moveOnly && hasMovedMin) {
			} else if (p.get('wsize') < p.get('fitsize')) {
				p.pos = p.scroll + p.clientSize - p.marginMax - p.get('wsize');
			} else { 
				p.pos = p.scroll + p.marginMin;
			}			
		}
		
	
		
	if (p.pos < p.marginMin) {
		var tmpMin = p.pos;
		p.pos = p.marginMin; 
		
	}
},

show : function () {
	this.changeSize(
		1,
		{ 
			xpos: this.x.tpos + this.x.tb - this.x.cb,
			ypos: this.y.tpos + this.y.tb - this.y.cb,
			xsize: this.x.t,
			ysize: this.y.t
		},
		{
			xpos: this.x.pos,
			ypos: this.y.pos,
			xsize: this.x.size,
			ysize: this.y.size
		},
		cb.expandDuration
	);
},

changeSize : function(up, from, to, dur) {
	if (this.fadeInOut) {
		from.op = up ? 0 : 1;
		to.op = up;
	}
	var t,
		exp = this,
		easing = Math[this.easing] || Math.easeInQuad,
		steps = (up ? cb.expandSteps : cb.restoreSteps) || parseInt(dur / 25) || 1;
	if (!up) easing = Math[this.easingClose] || easing;
	for (var i = 1; i <= steps ; i++) {
		t = Math.round(i * (dur / steps));
		
		(function(){
			var pI = i, size = {};
			
			for (var x in from) {
				size[x] = easing(t, from[x], to[x] - from[x], dur);
				if (isNaN(size[x])) size[x] = to[x];
				if (!/^op$/.test(x)) size[x] = Math.round(size[x]);
			}
			setTimeout ( function() {
				if (up && pI == 1) {
					exp.content.style.visibility = 'visible';
				}
				exp.setSize(size);
			}, t);				
		})();
	}
	
	if (up) {
		setTimeout(function() {
			exp.afterExpand();
		}, t + 50);
	}
	else setTimeout(function() { exp.afterClose(); }, t);
},

setSize : function (to) {
	try {		
		if (to.op) cb.setStyles(this.wrapper, { opacity: to.op });
		cb.setStyles ( this.wrapper, {
			width : (to.xsize +
				2 * this.x.cb) +'px',
			height : (to.ysize +
				2 * this.y.cb) +'px',
			left: to.xpos +'px',
			top: to.ypos +'px'
		});
		cb.setStyles(this.content, {
			width: (to.xsize) +'px',
			height: to.ysize +'px'
		});
			
		this.wrapper.style.visibility = 'visible';
		
	} catch (e) {
		window.location.href = this.src;	
	}
},


afterExpand : function() {
	this.isExpanded = true;	
	this.focus();
},

focus : function() {
	this.wrapper.style.zIndex = cb.zIndexCounter++;
	for (var i = 0; i < cb.expanders.length; i++) {
		if (cb.expanders[i] && i == cb.focusKey) {
			var blurExp = cb.expanders[i];
			blurExp.content.style.cursor = cb.ie ? 'hand' : 'pointer';
		}
	}
		
	cb.focusKey = this.key;	
},

close : function() {
    if (this.isClosing || !this.isExpanded) return;
	this.isClosing = true;
	try {
		this.content.style.cursor = 'default';
		this.changeSize(
			0, {
				xpos: this.x.pos,
				ypos: this.y.pos,
				xsize: this.x.size,
				ysize: this.y.size
			}, {
				xpos: this.x.tpos - this.x.cb + this.x.tb,
				ypos: this.y.tpos - this.y.cb + this.y.tb,
				xsize: this.x.t,
				ysize: this.y.t
			},
			cb.restoreDuration
		);
		
	} catch (e) { this.afterClose(); } 
},

afterClose : function () {
	cb.discardElement(this.wrapper);
	cb.expanders[this.key] = null;		
}

};
if (document.readyState && cb.ie) {
	(function () {
		try {
			document.documentElement.doScroll('left');
		} catch (e) {
			setTimeout(arguments.callee, 50);
			return;
		}
		cb.domReady();
	})();
}
var cbExpander = cb.Expander;

cb.addEventListener(window, 'load', function() {
	var sel = '.cb img', 
		dec = 'cursor: pointer !important;';
		
	var style = cb.createElement('style', { type: 'text/css' }, null, 
		document.getElementsByTagName('HEAD')[0]);

	if (!cb.ie) {
		style.appendChild(document.createTextNode(sel + " {" + dec + "}"));
	} else {
		var last = document.styleSheets[document.styleSheets.length - 1];
		if (typeof(last.addRule) == "object") last.addRule(sel, dec);
	}
});