PS.com.AnimateMulti = function (framerate)
{
	this.mm = new BS.com.Delete;
	this.animateCE = this.mm.ceNew('animate', this);
	this.animateCE.addCB(this._animate);

	if (!framerate) framerate = 30; //fps
	this.T_RATE = Math.round(1000/framerate);

	this._animations = [];
};

PS.com.AnimateMulti.prototype = {
	F_ANIMATING: false,
	STYLE_EASE: 'STYLE_E',
	STYLE_LINEAR: 'STYLE_L',

	_delete: function ()
	{
		this.mm.delArr(this._animations);
		this.mm._delete();
	},

	_animate: function ()
	{
		var a, v;
		for (var i = 0, l = this._animations.length; i < l; i++) {
			a = this._animations[i];
			switch (a.style) {
			case this.STYLE_LINEAR:
				v = this._stepLinear(a);
				a.cur += v;
				break;
			case this.STYLE_EASE:
				v = this._stepEase(a);
				a.cur = v;
				break;
			}
			a.vel = v;
			if (a.units == 'px') a.cur = Math.round(a.cur);
			//console.log(v);
 

			_bsDom.setStyle(a.el, a.prop, a.cur + a.units);
			a.steps--;
			if (a.steps == 0) {
				//animation complete?
				_bsDom.setStyle(a.el, a.prop, a.end + a.units)
				this._animations.splice(i,1);
				i--; //repeat idx with newly shifted data
				l--;
				//console.log(a);
			}
		}

		if (!this._animations.length) {
			this.animateCE.clearInterval();	
			this.F_ANIMATING = false;
		}
	},

	_stepLinear: function (a)
	{
		return (a.end - a.cur)/a.steps;
	},

	_stepEase: function (a)
	{
		var t = a.tsteps - a.steps;
		return  a.start + (a.end - a.start)*(1-Math.pow(2, -10*((t/a.tsteps))));
	},

	endAndClearAnims: function ()
	{
		var a;
		for (var i = 0, l = this._animations.length; i < l; i++) {
			a = this._animations[i];
			_bsDom.setStyle(a.el, a.prop, a.end + a.units);
		}

		this.animateCE.clearInterval();	
		this.F_ANIMATING = false;
		this._animations = [];
	},

	addAnim: function (anim)
	{
		//check to see if we're already animating this element, end if so
		var a;
		for (var i = 0, l = this._animations.length; i < l; i++) {
			a = this._animations[i];
			if (a.el == anim.el) {
				_bsDom.setStyle(a.el, a.prop, a.end + a.units);
				this._animations[i] = anim;
				break;
			}
		}

		this._animations.push(anim);

		if (!this.F_ANIMATING) {
			this.animateCE.setInterval(this.T_RATE);
			this.F_ANIMATING = true;
		}
	},

	makeAnim: function (el, prop, start, end, duration, units, style)
	{
		var a = {};
		a.el = el;
		a.prop = prop;
		a.start = start;
		a.end = end;
		a.dur = duration;
		a.style = style;
		if (!units) units = 'px';
		a.units = units;
		//local vars
		a.vel = 0;
		a.cur = start;
		a.tsteps = a.steps = Math.round(duration*1000/this.T_RATE);

		return a;
	}
};

PS.com.Portfolio = function (parent, prepop, cfg) 
{
	this.mm = new BS.com.Delete;
	this.titleH1 = this.mm.domNew(parent, "h1", "ps_port_title");
	this.rootDIV = this.mm.domNew(parent, "div", "PSPortfolio");

	this.spinnerDIV = this.mm.domNew(this.rootDIV, "div", "psfs_spinner psfs_adv_spinner");
	this.spinnerDIV.innerHTML = '<div class="psfs_spinner"><div></div><img src="/img/BS.com/spinner-big.gif"/></div>';	
	_bsDom.setDisplay(this.spinnerDIV, false);

	this.prevA = this.mm.domNew(this.rootDIV, "a", "psport_prev");
	this.prevA.href = 'javascript:void(0)';
	this.prevA.innerHTML = '<span></span>';
	this.windowDIV = this.mm.domNew(this.rootDIV, "div", "psport_thumbs");
	this.animm = this.mm.oNew(PS.com.AnimateMulti, 30);

	if (cfg) {
		if (cfg.BLOCK_SIZE) this.BLOCK_SIZE = parseInt(cfg.BLOCK_SIZE);
		if (cfg.THUMB_PAD) this.THMB_PAD = parseInt(cfg.THUMB_PAD);
		if (cfg.WINDOW_WIDTH) {
			this.WINDOW_WIDTH = parseInt(cfg.WINDOW_WIDTH);	
			this.WINDOW_HEIGHT = parseInt(cfg.WINDOW_HEIGHT);	
		}
		if (isset(cfg.F_2UP)) this.F_2UP = cfg.F_2UP; 
		if (isset(cfg.F_CAPTION)) this.F_CAPTION = cfg.F_CAPTION; 
		if (isset(cfg.F_MOREINFO)) this.F_MOREINFO = cfg.F_MOREINFO;
		if (isset(cfg.F_INDEX)) this.F_INDEX = cfg.F_INDEX;
		if (isset(cfg.TRANSITION)) this.transition = cfg.TRANSITION;
		if (isset(cfg.F_NAV_HOVER)) this.F_NAV_HOVER = cfg.F_NAV_HOVER;
		if (isset(cfg.F_IMAGE_TITLE)) this.F_IMAGE_TITLE = cfg.F_IMAGE_TITLE;
	}
	
	this.sliderDIV = this.mm.domNew(this.windowDIV, "div", "psport_slider");
	this.nextA = this.mm.domNew(this.rootDIV, "a", "psport_next");
	this.nextA.href = 'javascript:void(0)';
	this.nextA.innerHTML = '<span></span>'

	if (!this.F_NAV_HOVER) {
		_bsDom.setVis(this.nextA.firstChild, true);
		_bsDom.setVis(this.prevA.firstChild, true);
	}

	var tdiv = this.mm.domNew(this.rootDIV, "div", "");
	this.showCapA = this.mm.domNew(tdiv, "a", "psport_cap f_left");
	this.showCapA.href = 'javascript:void(0)';
	this.showCapA.innerHTML = 'Show Caption';
	_bsDom.setDisplay(this.showCapA, this.F_CAPTION);

	this.indexSPAN = this.mm.domNew(tdiv, "span", "psport_index");
	_bsDom.setDisplay(this.indexSPAN, this.F_INDEX);

	this.moreInfoA = this.mm.domNew(this.rootDIV, "a", "psport_info");
	this.moreInfoA.href = 'javascript:void(0)';
	this.moreInfoA.innerHTML = 'More Info';
	var mis = _bsDom.size(this.moreInfoA);
	if (mis[1] && (this.F_MOREINFO || this.F_IMAGE_TITLE)) this.MORE_INFO_H = mis[1];
	else this.MORE_INFO_H = 0;
	this.rootDIV.removeChild(this.moreInfoA);

	this.protectDIV = this.mm.domNew(this.rootDIV, "div", "psport_block");

	_bsDom.setSize(this.protectDIV, [this.WINDOW_WIDTH, this.WINDOW_HEIGHT]);
	_bsDom.setSize(this.windowDIV, [this.WINDOW_WIDTH, this.WINDOW_HEIGHT +  this.MORE_INFO_H]);
	_bsDom.setPos(this.spinnerDIV, [ Math.round(this.WINDOW_WIDTH/2 - this.SPINDIM[0]/2) , Math.round(this.WINDOW_HEIGHT/2 - this.SPINDIM[1]/2)]);


	var bw = Math.floor(this.WINDOW_WIDTH/2);
	_bsDom.setSize(this.prevA, [bw, this.WINDOW_HEIGHT]);
	_bsDom.setStyle(this.prevA, "left", '0px');
	_bsDom.setSize(this.nextA, [bw, this.WINDOW_HEIGHT]);
	_bsDom.setStyle(this.nextA, "left", bw + 'px');

	var clicksz = _bsDom.size(this.prevA.firstChild);
	var spanpos = [Math.round(bw/8 - clicksz[0]/2), Math.floor(this.WINDOW_HEIGHT/2 - clicksz[1]/2)];
	_bsDom.setPos(this.prevA.firstChild, spanpos);
	_bsDom.setPos(this.nextA.firstChild, [bw - spanpos[0] - clicksz[0], spanpos[1]]);

	this.bsapiCE = this.mm.ceNew('bsapi', this);
	this.bsapiCE.addCB(this._bsapiCB);

	this.clickCE = this.mm.ceNew('click', this);
	this.clickCE.addCB(this._clickCB);
	this.clickCE.attach(this.prevA, 'click');
	this.clickCE.attach(this.nextA, 'click');
	this.clickCE.attach(this.showCapA, 'click');

	this.clickCE = this.mm.ceNew('hover', this);
	this.clickCE.addCB(this._hoverCB);
	this.clickCE.attach(this.showCapA, 'mouseover');
	this.clickCE.attach(this.showCapA, 'mouseout');

	if (_bsBrowser.isIE && this.F_NAV_HOVER) {
		this.ieHoverCE = this.mm.ceNew('hover', this);
		this.ieHoverCE.addCB(this._iehoverCB);
		this.ieHoverCE.attach(this.nextA, 'mouseover');
		this.ieHoverCE.attach(this.nextA, 'mouseout');	
		this.ieHoverCE.attach(this.prevA, 'mouseover');
		this.ieHoverCE.attach(this.prevA, 'mouseout');	
	}

	this.loadCE = this.mm.ceNew('load', this);
	this.loadCE.addCB(this._loadCB);

	this.f_loading = [];
	this.f_loading[-1] = this.f_loading[1] = false;

	this.pagNextE = this.mm.ceNew('n', this);
	this.pagNextE.addCB(this._keyCB);
	this.pagPrevE = this.mm.ceNew('p', this);
	this.pagPrevE.addCB(this._keyCB);

	this.key = this.mm.oNew(BS.com.Keypress);
	this.key.add(37, this.pagPrevE);
	this.key.add(39, this.pagNextE);

	if (prepop) this.initWData(prepop);

};

PS.com.Portfolio.prototype = {
	AJAX: '/ajax/fsAct',
	BLOCK_SIZE: 50,
	THMB_SIZE: 75,
	THMB_PAD: 8,
	WINDOW_CNT: 5,
	OFSC_BUFFER: 2,
	LOAD_LOOKAHEAD: 5,
	TYPE: 'galPag',
	IESUX: 0,
	F_2UP: false,
	F_CAPTION: true,
	F_MOREINFO: true,
	F_INDEX: false,
	F_NAN_HOVER: true,
	F_IMAGE_TITLE: false,
	LOADING_PREDICT: 1,
	LOADING_REQD: 2,
	SPINDIM: [74,74],
	SPIN_SRC: '/img/BS.com/spinner-big.gif',
	MORE_INFO_H: 14,
	transition: 'SLIDE',
	

	_delete: function () 
	{
		this.pagData = this.imgData = null;
		this.mm._delete();
	},

	init: function (gid)
	{
		var p = {};
		p.FS_BS = this.BLOCK_SIZE;
		p.FS_G_ID = gid;
		p.FS_I_ID = BS.utl.location.getHash();
		p.FS_SRC_TYPE = this.TYPE;
		//lock UI here?
		_bsBsapi.post(this.AJAX, p, this.bsapiCE);	
	},

	initWData: function (data)
	{
		var hid = BS.utl.location.getHash(), ffound = false;
		/* needed for dynamic loading, currently disabled
		for (var i = 0; i < data.images.length; i++) 
				if (hid == data.images[i].I_ID) ffound = true;
		if (!ffound) return this.init(data.pag.g.G_ID);
		*/

		try { this.initWDataInt(data); } 
		catch (e) { 
			if (e.type)	throw e;	
			this.getDataIfNotAlready(e); 
		}
	},

	initWDataInt: function (data)
	{
	   	//is first run?
		if (!this.imgData) {
			this.pagData = data.pag;
			this.titleH1.innerHTML = this.pagData.g.G_NAME;
			this.imgData = [] ;//data.images;
			this.idMap = [];
			var hid = BS.utl.location.getHash();
			this.imgSel = 0;

			for (var i = 0; i < data.images.length; i++) {
				var idx = this.pagData.o + i;	
				this.imgData[idx] = data.images[i];
				this.idMap[data.images[i].I_ID] = idx;
				if (hid == data.images[i].I_ID) this.imgSel = idx;
			}

			this.maxCached = parseInt(this.pagData.o) + data.images.length;
			this.minCached = parseInt(this.pagData.o);
		}

		//shift selection backwards if that's the only workable 2up
		if (this.imgSel > 0 && this.F_2UP && !this.canNup(this.imgSel, this.imgSel + 1) && this.canNup(this.imgSel, this.imgSel - 1))
				this.imgSel--;	

		this.winSel = this.imgSel;
		this.winpos = 0;

		var t;
		if (!this.freeThumbA) {
			var freeThumbA = this.freeThumbA = [];

			var thmCnt = this.OFSC_BUFFER*2 + 1;
			for (var i = 0; i < thmCnt; i++) {
				t = this.mm.domNew(null, "div", "psport_thumbox");
				t.innerHTML = '';
				//this.loadCE.attach(t.firstChild.firstChild.firstChild, 'load');
				_bsDom.setSize(t, [this.WINDOW_WIDTH, this.WINDOW_HEIGHT]);
				freeThumbA.push(t);
			} 
		} else var freeThumbA = this.freeThumbA;

		if (!this.slideA) this.slideA = [];
		if (empty(this.slideA)) {
				t = freeThumbA.pop();
				this.addSlide(0, t);
		}

		for (var i = 1; i <= this.OFSC_BUFFER; i++) {

			   	t = freeThumbA.pop();
				this.addSlide(-1, t);

			   	t = freeThumbA.pop();
				this.addSlide(1, t);
		}

		/*
		_bsDom.setStyle(this.sliderDIV, 'left', this.getSlideOfsForIdx(this.winSel)+'px');
		var hw = Math.floor(this.WINDOW_CNT/2);
		*/
		var sdc = this.sliderDIV.childNodes;
		_bsDom.setDisplay(this.nextA, !_bsDom.hasClass(sdc[this.OFSC_BUFFER+1], 'psport_empty'));
		_bsDom.setDisplay(this.prevA, !_bsDom.hasClass(sdc[this.OFSC_BUFFER-1], 'psport_empty'));
		this.drawIndex();
	},

	canNup: function ()
	{
	   	var idxs = arguments;	

		var d = this.imgData;
		for (var i = 0, l = idxs.length; i < l; i++) {
		   	this.checkload(idxs[i]);
			if (!isset(d[idxs[i]])) return false;
		}

		var dim, dimsum = 0, di;

		for (var i = 0, l = idxs.length; i < l; i++) {
			di = d[idxs[i]];
		   	dim = PS.app.imgSzCalc([parseInt(di.I_SCREEN_WIDTH), parseInt(di.I_SCREEN_HEIGHT)], [this.WINDOW_WIDTH, this.WINDOW_HEIGHT]);
			dimsum += dim[0];
		}
		//console.log(dimsum);
		return (dimsum < this.WINDOW_WIDTH);
	},

	addSlide: function (end, div)
	{
		var f_rem = !div;
		var imgA = null;

		//are we waiting on data?
		//if (this.f_loading[end] == this.LOADING_REQD) return;
				

		/*
		var la = this.LOAD_LOOKAHEAD*end + this.imgSel;
		if ( (la > this.maxCached) && (la < this.pagData.t)) {
			this.getDataBlock(this.maxCached + 1);
			this.f_loading[end] = this.LOADING_PREDICT;
		} else if ( la < this.minCached && la > 0) {
			this.getDataBlock(this.minCached - this.BLOCK_SIZE);
			this.f_loading[end] = this.LOADING_PREDICT;	
		}
		*/

		if (end == 0) {
		   	//2up?
			if (!div) throw "Div needed for central slide";
		   	if (this.F_2UP && this.canNup(this.imgSel, this.imgSel + 1)) 	{
			   	this.slideA[0] = imgA = [this.imgSel, this.imgSel + 1];
				this.lmost = this.imgSel;
				this.rmost = this.imgSel + 1;
			} else {
				this.slideA[0] = this.rmost = this.lmost = this.imgSel;
				imgA = [this.imgSel];				
			}
			this.makeSlideWithData(imgA, div);
			_bsDom.setStyle(div,'left', '0px');
			this.sliderDIV.appendChild(div);
		} else {
			//blech, need to refactor and collapse these directional branches
			var idx, szp, posp, refdiv;	
			//right
		   	if (end > 0) {
				if (!div) div = this.sliderDIV.firstChild;
				refdiv = this.sliderDIV.lastChild;
				_bsDom.setClass(div, 'psport_empty', !isset(this.imgData[this.rmost + 1]));
				if (this.rmost + 1 >= this.imgData.length /*this.pagData.t*/) { 
					this.slideA[this.slideA.length] = null; 
			    } else if (this.F_2UP && this.canNup(this.rmost + 1, this.rmost + 2)) 	{
				   	this.slideA[this.slideA.length] = imgA = [this.rmost + 1, this.rmost + 2];
					this.rmost = this.rmost + 2;
				} else {
					this.checkload(this.rmost + 1);
				   	this.slideA[this.slideA.length] = this.rmost = this.rmost + 1;									  imgA = [this.rmost];
				}
				if (f_rem) {
					this.slideA.shift();
					this.lmost = this.slideA[0];
					if (is_array(this.lmost)) this.lmost = this.lmost[0];	
				}
				
				if (imgA) this.makeSlideWithData(imgA, div);
				this.sliderDIV.appendChild(div);
			} else if (end < 0) { //left
				if (!div) div = this.sliderDIV.lastChild;	
				refdiv = this.sliderDIV.firstChild;
				_bsDom.setClass(div, 'psport_empty', !isset(this.imgData[this.lmost - 1]));
				if (this.lmost - 1 < 0) { 
					this.slideA.unshift(null); 
				} else if (this.F_2UP && this.canNup(this.lmost - 2, this.lmost - 1)) {
					this.slideA.unshift(imgA = [this.lmost - 2, this.lmost - 1]);
					this.lmost =  this.lmost - 2;
				} else {
					this.checkload(this.lmost - 1);	
					this.slideA.unshift(this.lmost = this.lmost - 1);
					imgA = [this.lmost];
				}	

				if (f_rem) {
					this.slideA.pop();
					this.rmost = this.slideA[this.slideA.length-1];
					if (is_array(this.rmost)) this.rmost = this.rmost[this.rmost.length-1];	
				}

				if (imgA) this.makeSlideWithData(imgA, div);
				this.sliderDIV.insertBefore(div, this.sliderDIV.firstChild);
			} 

			switch (this.transition) {
			case 'SLIDE': 
				szp = _bsDom.size(refdiv);
				posp = _bsDom.pos(refdiv);   
				var npos = end*szp[0]+posp[0];	
				_bsDom.setStyle(div, 'left', npos + 'px');
				break;
			case 'XFADE':
				_bsDom.setStyle(div, 'left', '-4000px');
				break;
			}

		}
		//_bsDom.setStyle(div, 'left', idx*(this.THMB_SIZE + this.THMB_PAD)+'px');
		//_bsDom.setClass(div, 'psport_sel', (this.imgSel == idx));
	},

	makeSlideWithData: function (idxs, div)
	{
		var sz, szstr, sw, sh, slidestr = '', capstr = '', linkstr = '', hlstr = '', d;
		var dA = [], dwsum = 0, dim;
		for (var i = 0, l = idxs.length; i < l; i++) {

			d = this.imgData[idxs[i]];
			sw = parseInt(d.I_SCREEN_WIDTH);
			sh = parseInt(d.I_SCREEN_HEIGHT);
			
			dim = PS.app.imgSzCalc([sw, sh], [this.WINDOW_WIDTH, this.WINDOW_HEIGHT]);
			dA[i] = dim;
			dwsum += dim[0];
		}

		var mg, caph, posl = 0, cposl, maxtop = 0, maxh = 0, spinloc = [], hlesc;
		var pad = Math.round((this.WINDOW_WIDTH - dwsum)/(l+1));
		for (var i = 0, l = idxs.length; i < l; i++) {

			d = this.imgData[idxs[i]];
			sw = parseInt(d.I_SCREEN_WIDTH);
			sh = parseInt(d.I_SCREEN_HEIGHT);
			
			dim = dA[i];
			mg = Math.round((this.WINDOW_HEIGHT - dim[1])/2);
			posl += pad;
			caph = Math.round(dim[1]/4);
			maxtop = Math.max(maxtop, mg+dim[1]-caph);
			maxh =  Math.max(maxh, caph);
			cposl = ( idxs.length == 1 ? 0 : posl); //make singletons span entire width
			cwidth = ( idxs.length == 1 ? this.WINDOW_WIDTH : dim[0]);

			spinloc[0] = posl + Math.round(dim[0]/2 - this.SPINDIM[0]/2);
			spinloc[1] = mg + Math.round(dim[1]/2 - this.SPINDIM[1]/2);

			slidestr += '<div class="psfs_spinner" style="top:'+spinloc[1]+'px; left:'+spinloc[0]+'px;"><div></div><img src="/img/BS.com/spinner-big.gif"/></div>';

			slidestr += '<img src="'+d.src+'" style="top:'+mg+'px; left:'+posl+'px;">';			

			capstr += '<div style="width:'+cwidth+';height:'+caph+'; left:'+cposl+'px">'+(d.II_CAPTION ? d.II_CAPTION : '')+'</div>';

			linkstr += '<a href="'+this.getImageLink(d.I_ID)+'" class="psfs_moreinfo" style="left:'+cposl+'px; top:'+this.WINDOW_HEIGHT+'px">More Info</a>';

			if (!d.II_HEADLINE_CASC) hlesc = '';
			else hlesc = _bsStr.truncate(d.II_HEADLINE_CASC.replace('<', '&lt;').replace('>', '&gt;'));

			//insert truncation code herez
			hlstr += '<span class="psport_headline" style="left:'+cposl+'px; top:'+this.WINDOW_HEIGHT+'px; width: '+cwidth+'px">'+hlesc+'</span>';

			posl += dim[0];
		}

		slidestr += '<div class="psport_cap" style="width:'+this.WINDOW_WIDTH+'px; top:'+maxtop+'px; height: '+caph+'px;">' + capstr + '</div>';


		slidestr += (this.F_IMAGE_TITLE ? hlstr : '') + (this.F_MOREINFO ? linkstr : '');

		//cleanup old nodes
		var imgs;
		if (!_bsBrowser.isIE) {
		   	imgs = div.getElementsByTagName('img');
			for (var i = 0, l = imgs.length; i < l; i++) {
					if (imgs.src == this.SPIN_SRC) continue;
					this.loadCE.detach(imgs[i], 'load');			 
			}
		} ///else log('IEEEEE');
		
		div.innerHTML = slidestr;
		
		var cap = this._getCaptionDIV(div);
		_bsDom.setStyle(cap, 'opacity', 0);

		if (this.F_IMAGE_TITLE) _bsEvt.setTimeout(0, this._truncTO, this, div);		
		
		imgs = div.getElementsByTagName('img');
		for (var i = 0, l = imgs.length; i < l; i++) {
				if (_bsDom.hasClass(imgs[i], 'psfs_spinner')) {
					 _bsDom.setStyle(imgs[i], 'opacity', 0.5);
					 continue;
			 }
			if (!_bsBrowser.isIE) {	
			   	_bsDom.setStyle(imgs[i], 'opacity', 0);
				this.loadCE.attach(imgs[i], 'load');
			} else {
				_bsEvt.setTimeout(0, this._ieSetSrc, this, [imgs[i], imgs[i].src]);	
			}
			 
		}
		
		return slidestr;
	},

	_truncToWidth: function (str, w, target)
	{
			
	   mel = this.mm.domNew(target.parentNode, target.tagName, target.className);
	   _bsDom.setStyle(mel, 'position', 'absolute');
	   _bsDom.setStyle(mel, 'left', '-4000px');
	   _bsDom.setStyle(mel, 'display', 'block');
	   _bsDom.setStyle(mel, 'whiteSpace', 'nobreak');
	   mel.innerHTML = str;
	   var sz = _bsDom.size(mel);
	   //console.log(mel);
	   //console.log(sz);
	   if (sz[0] > w) {
		 var ppc = sz[0]/str.length;
		 tstr = BS.utl.string.truncate(str, Math.floor(w/ppc));
	   } else tstr = str;
	   mel.parentNode.removeChild(mel);
	   return tstr;
	},

	_truncTO: function (div)
	{
		var misz, tstr, hl = div.getElementsByTagName("a");
		for (var i = 0, l = hl.length; i < l; i++) 
			if (_bsDom.hasClass(hl[i], 'psfs_moreinfo')) {
				misz = _bsDom.size(hl[i]);
				break;
			}
		
		misz = (misz ? misz[0] : 0);
		//console.log(misz);

		var sz, tstr, hlspan, hl = div.getElementsByTagName("span");
		for (var i = 0, l = hl.length; i < l; i++) {
			hlspan = hl[i];
			if (!_bsDom.hasClass(hlspan, 'psport_headline')) continue;
			sz = _bsDom.size(hlspan);
			tstr = this._truncToWidth(hlspan.innerHTML, sz[0] - misz, hlspan);
			//console.log(tstr);
			hlspan.innerHTML = tstr;
		}
	},

	_ieSetSrc: function (args)
	{
		args[0].src = args[1];
		//failsafe damn you IE6
		//_bsEvt.setTimeout(200, this._fadeThumbIn, this, args[0]);
	},

	getImageLink: function (id) 
	{ 
		return PS.app.pvGet('server.web') + '/gallery-image/'+this.pagData.g.G_NAME_DASH+'/' + this.pagData.g.G_ID+'/' + id;
	},

	_slideRetry: function (data)
	{
			//console.log(data);
			var n_try = (isset(data[1]) ? data[1] : 0) + 1;
			this.slide(data[0], n_try);
	},

	slide: function (dir, n_tries)
	{
		var sdc = this.sliderDIV.childNodes;
		if (_bsDom.hasClass(sdc[this.OFSC_BUFFER+dir], 'psport_empty')) 
				return;

		if (this.f_loading[end] == this.LOADING_REQD) return;

		//clear queued slide action if any
		clearTimeout(this.slideTO);

		var imgs = sdc[this.OFSC_BUFFER+dir].getElementsByTagName('img');
		for (var i = 0, l = imgs.length; i < l; i++) {
			if (_bsDom.hasClass(imgs[i], 'psfs_spinner')) {
				continue;
			}
			//log("IMG "+imgs[i].complete+"  "+  +" "+imgs[i].readyState);
			if (imgs[i].complete || imgs[i].readyState === 'complete' || (_bsBrowser.isIE && _bsBrowser.version < 7)) continue;
			else {
					//log("IMG "+imgs[i].src+"  "+  +" "+imgs[i].readyState+"NOT READY YET");
				_bsDom.setDisplay(this.spinnerDIV, true);
				this.slideTO = _bsEvt.setTimeout(200, this._slideRetry, this, [dir, n_tries]);	
				return false;
			}			 
		}

		//hide spinner
		_bsDom.setDisplay(this.spinnerDIV, false);
		var szdx = _bsDom.size(sdc[this.OFSC_BUFFER+dir]);

		try { this.addSlide(dir); }
		catch (e) {
		   	if (e.type)	throw e;
		   	this.getDataIfNotAlready(e);
			return;
		}
		this.imgSel = this.slideA[this.OFSC_BUFFER];
		if (is_array(this.imgSel)) this.imgSel = this.imgSel[0];
		var iid = this.imgData[this.imgSel].I_ID;
		location.hash = iid;
		//this.setImageLink();

		//do transitions
		
		this.animm.endAndClearAnims();

		var spos = _bsDom.pos(this.sliderDIV);
		var start = spos[0];
		var end = start + -1*dir*szdx[0];
		
		switch (this.transition) {
		case 'SLIDE': 
			var a = this.animm.makeAnim(this.sliderDIV, 'left', start, end, 0.5, 'px', this.animm.STYLE_EASE);
			this.animm.addAnim(a);
			break;
		case 'XFADE':
			if (_bsBrowser.isIE) {
				_bsDom.setStyle(sdc[this.OFSC_BUFFER], 'left', 0);
				_bsDom.setStyle(sdc[this.OFSC_BUFFER-dir], 'left', '-4000px');
			} else {
				_bsDom.setStyle(sdc[this.OFSC_BUFFER], 'opacity', 0);
				_bsDom.setStyle(sdc[this.OFSC_BUFFER], 'left', 0);
				var a = this.animm.makeAnim(sdc[this.OFSC_BUFFER], 'opacity', 0, 1, 0.5, ' ', this.animm.STYLE_EASE);
				var b = this.animm.makeAnim(sdc[this.OFSC_BUFFER-dir], 'opacity', 1, 0, 0.5, ' ', this.animm.STYLE_EASE);
				this.animm.addAnim(a);
				this.animm.addAnim(b);
			}
			break;
		}
		

		_bsDom.setDisplay(this.nextA, !_bsDom.hasClass(sdc[this.OFSC_BUFFER+1], 'psport_empty'));
		_bsDom.setDisplay(this.prevA, !_bsDom.hasClass(sdc[this.OFSC_BUFFER-1], 'psport_empty'));

		this.drawIndex();

		//animate/setstyle
		//_bsDom.setStyle(this.sliderDIV, 'left', end);		
	},

	drawIndex: function ()
	{
		//need to centralize in a single function and add hook to initWData
		var curslide = this.slideA[this.OFSC_BUFFER];
		var curIdx = (isset(curslide[0]) ? ((curslide[0]+1) + '-' +  (curslide[curslide.length-1]+1)) : curslide + 1);
		this.indexSPAN.innerHTML =  curIdx + '/' + this.imgData.length;
	},

	_clickCB: function (type, data, args)
	{
		var t = _bsEvt.getTarget(args[0]);

		switch (t) {
		case this.prevA:
		case this.prevA.firstChild:
				this.slide(-1);
				break;
		case this.nextA:
		case this.nextA.firstChild:
				this.slide(1);
				break;
		}
	},

	_keyCB: function (type, data, args)
	{
		switch (type) {
		case 'p':
				this.slide(-1);
				break;
		case 'n':
				this.slide(1);
				break;
		}
	},

	_getCaptionDIV: function (el) 
	{
		var e, els = el.getElementsByTagName('div');
		for (var i = 0, l = els.length; i < l; i++ ) 
		   	if (_bsDom.hasClass(els[i], 'psport_cap')) { 
					e = els[i];
					break;
			}

		return e;
	},

	_hoverCB: function (type, data, args)
	{
		var e = args[0];
		var a;
		var el = this.sliderDIV.childNodes[this.OFSC_BUFFER];
		el = this._getCaptionDIV(el);

		switch (e.type) {
		case 'mouseover':
		   	a = this.animm.makeAnim(el, 'opacity', 0, 0.5, 0.2, ' ', this.animm.STYLE_LINEAR);
			this.animm.endAndClearAnims();
			this.animm.addAnim(a);
			break;
		case 'mouseout':
			a = this.animm.makeAnim(el, 'opacity', 0.5, 0, 0.2, ' ', this.animm.STYLE_LINEAR);
			this.animm.endAndClearAnims();
			this.animm.addAnim(a);	
			break;
		}
	},

	_iehoverCB: function (type, data, args)
	{
		var e = args[0];
		var a;
		var el = _bsEvt.getTarget(e);
		var elr;
		_bsEvt.stopPropagation(e);
		if (el.nodeName.toLowerCase() == 'span') el = el.parentNode;
		

		switch (e.type) {
		case 'mouseover':
			elr = e.relatedTarget || e.fromElement;
			if (elr && (elr == el || elr.parentNode == el)) return;
		   	//a = this.animm.makeAnim(el, 'opacity', 0, 1, 0.2, ' ', this.animm.STYLE_LINEAR);
			//this.animm.addAnim(a);
			_bsDom.setVis(el.firstChild, true);
			break;
		case 'mouseout':
			elr = e.relatedTarget || e.toElement;
			if (elr && (elr == el || elr.parentNode == el)) return;	
			//a = this.animm.makeAnim(el, 'opacity', 1, 0, 0.2, ' ', this.animm.STYLE_LINEAR);
			//this.animm.addAnim(a);
			_bsDom.setVis(el.firstChild, false);
			break;
		}
	},

	checkload: function (idx, f_noerr) 
	{
			/*
		if (!isset(this.imgData[idx]) && (idx < this.pagData.t && idx > 0))	{
				if (f_noerr) return true;
				else throw idx;
		}
			*/
		return false;
	},

   	getDataIfNotAlready: function (ofs)	
   	{
			//console.log('getting datat for: ' + ofs);	
		if ( ofs >= this.maxCached) {
			if (!this.f_loading[1])	this.getDataBlock(this.maxCached + 1);
			this.f_loading[1] = this.LOADING_REQD;
			//todo: right spinner
		} else if ( ofs < this.minCached) {
			if (!this.f_loading[-1]) this.getDataBlock(this.minCached - this.BLOCK_SIZE);
			this.f_loading[-1] = this.LOADING_REQD;	
			//todo: left spinner
		}	
	},

	getDataBlock: function (ofs, iid)
	{
		var p = {};
		p.FS_BS = this.BLOCK_SIZE;

		//futz with the boundary to prevent unecc data calls
		/*
		if (ofs < 0 || ofs < this.WINDOW_CNT*(this.OFSC_BUFFER*2+1)) {
			p.FS_BS = this.BLOCK_SIZE + ofs;
			ofs = 0;
		}
		*/
		p.FS_OFS = Math.floor(ofs/this.BLOCK_SIZE)*this.BLOCK_SIZE;
		p.FS_G_ID = this.pagData.g.G_ID;
		p.FS_SRC_TYPE = this.TYPE;
		//lock UI here?
		_bsBsapi.post(this.AJAX, p, this.bsapiCE);
	},
	
	_loadCB: function (type, data, args)
	{
		var t = _bsEvt.getTarget(args[0]);
		this._fadeThumbIn(t);
	},

	_fadeThumbIn: function (t)
	{			
		var a = this.animm.makeAnim(t, 'opacity', 0, 1, 0.3, ' ', this.animm.STYLE_LINEAR);
		this.animm.addAnim(a);
	},

	_bsapiCB: function (type, data, args)
	{
		try {
			var d = _bsBsapi.responseParse(args[0]);
		}
		catch (e) {
			_bsAlert.show('Oops!', e);
		}

		//no data! init
		if (!this.imgData) return this.initWData(d);

		//if init cb save pag data here
		d.pag.o = parseInt(d.pag.o);

		for (var i = 0; i < d.images.length; i++) {
			this.imgData[d.pag.o + i] = d.images[i];
		}

		var oldMax = this.maxCached;
		var oldMin = this.minCached;

		this.maxCached = Math.max(this.maxCached, d.pag.o + d.images.length);
		this.minCached = Math.min(this.minCached, d.pag.o);
		
		//console.log([d.pag.o, d.images.length, oldMax]);
		//console.log(this.f_loading);

		if (d.pag.o + d.images.length < oldMin) {
		   	if (this.f_loading[-1] == this.LOADING_REQD) {
			   	this.f_loading[-1] = false;	
				//todo: hide left spinner
				this.addSlide(-1);
			} else this.f_loading[-1] = false;
		} else if (d.pag.o > oldMax) {
		   	if (this.f_loading[1] == this.LOADING_REQD) {
			   	this.f_loading[1] = false;	
				//todo: hide left spinner
				this.addSlide(1);
			} else this.f_loading[1] = false;
		}
	}
};


