﻿/*
* Author: Cuong Tham
* You must not remove the following information:
* YUI Lightbox Beta
* From TheCodeCentral.com
* 1/1/2007
*
* For installation instruction, bug report and feature suggestion,
* please visit http://thecodecentral.com/2008/01/01/yui-based-lightbox-final
*
* Licensed under the Creative Commons Attribution-ShareAlike License, Version 3.0 (the "License")
* You may obtain a copy of the License at
* http://creativecommons.org/licenses/by-sa/3.0/
*/
LOOT.namespace(["widget.lightbox"]);

LOOT.widget.lightbox.LoadingPanel = function(conf){
	if(conf == undefined){
		conf = new Array();
	}
	if(conf.id == undefined){
		conf.id = 'loadingPanel';
	}
	if(conf.header == undefined){
		conf.header = 'Loading, please wait...';
	}
	if(conf.width == undefined){
	  conf.width = "240px";
	}

	this.conf = conf;
	this.init();
	
};

LOOT.widget.lightbox.LoadingPanel.prototype = {
	init:function(){
		this.loadingPanel =
		new YAHOO.widget.Panel(this.conf.id,{
			width:this.conf.width,
			fixedcenter:true,
			close:false,
			draggable:false,
			modal:true,
			visible:false,
			zindex: "150"
		});

		
		this.loadingPanel.setBody(this.conf.header + '<img src="http://us.i1.yimg.com/us.yimg.com/i/us/per/gr/gp/rel_interstitial_loading.gif" />');
		this.loadingPanel.render(document.body);
		Dom.addClass(this.loadingPanel.id, 'lui_lightboxLoader');
		
		var cancelLink = document.createElement('a');
		Dom.setStyle(cancelLink, 'cursor', 'pointer');
		cancelLink.appendChild(document.createTextNode('Cancel'));
		Event.on(cancelLink, 'click', function(e, o){
		    o.self.hide();
		}, {self:this.loadingPanel});
		this.loadingPanel.appendToBody(document.createElement('br'));
		this.loadingPanel.appendToBody(cancelLink);
		Dom.setStyle(this.loadingPanel.body, 'text-align', 'center');
	},
	show:function(text){
	    if(text != undefined){
	        this.loadingPanel.setHeader(text);
	    }else{
	        this.loadingPanel.setHeader(this.conf.header);
	    }
		this.loadingPanel.show();
	},
	hide:function(){
		this.loadingPanel.hide();
	},
	getInstance: function(){
	    return this.loadingPanel;	
	}
};
/**
* A class preload image of the given URL
* @param url location of the image to preload
* @param conf.onLoad the event handler called when the image is loaded
* @param conf.param an optional parameter pass to onLoad halder
*/
LOOT.widget.lightbox.ImageLoader = function(url){
	this.url = url;
	this.image = null;
	this.loadEvent = new YAHOO.util.CustomEvent("onLoad", this);
};

LOOT.widget.lightbox.ImageLoader.prototype = {
	load:function(){
		this.image = document.createElement('img');
		Event.on(this.image, 'load', function(e, o){
			//fire this.loadEvent
			o.fire();
			}, this.loadEvent);
		this.image.src = this.url;
	},
	getImage:function(){
		return this.image;
	}
};
/**
* A class preload image of the given URL
* @param url location of the image to preload
* @param conf.onLoad the event handler called when the image is loaded
* @param conf.param an optional parameter pass to onLoad halder
*/
LOOT.widget.lightbox.ImageGallery = function(dataSource, lightboxPanel){
	this.dataSource = dataSource;
	this.lightboxPanel = lightboxPanel;
	this.init();
	this.lightboxPanel.gallery = this;
	this.initKeyboardShortcut();
};


LOOT.widget.lightbox.ImageGallery.prototype = {
	init:function(){
		var galleryList = new LOOT.widget.lightbox.ImageGalleryList(this.dataSource, true);
		
		var nextImgDiv = document.createElement('div');
		nextImgDiv.title = 'Forward';
		Dom.addClass(nextImgDiv, 'lui-lb-ctrl lui-lb-next');
		
		var prevImgDiv = document.createElement('div');
		prevImgDiv.title = "Backward";
		Dom.addClass(prevImgDiv, 'lui-lb-ctrl lui-lb-prev');
		
		var closeDiv = document.createElement('div');
		closeDiv.title = "Close this gallery";
		Dom.addClass(closeDiv, 'lui-lb-ctrl lui-lb-close');
		
		var resizeDiv = document.createElement('div');
		resizeDiv.title = "Resize";
		Dom.addClass(resizeDiv, 'lui-lb-ctrl lui-lb-resize');
		
		var infoDiv = document.createElement('div');
		infoDiv.title = "Toggle tooltip";
		Dom.addClass(infoDiv, 'lui-lb-ctrl lui-lb-info');
		
		var helpDiv = document.createElement('div');
		helpDiv.title = "Toggle Help";
		Dom.addClass(helpDiv, 'lui-lb-ctrl lui-lb-help');
		
		var dragDiv = document.createElement('div');
		dragDiv.title = "Move toolbar";
		dragDiv.id = this.lightboxPanel.showImgPanel.id + "Dragger";
		Dom.addClass(dragDiv, 'lui-lb-ctrl lui-lb-drag');
		
		var navClickHandler = function(e, o){
			 if(o.dir == 'next'){
			 	 o.self.forward();
			 }else{
			 	 o.self.backward();
			 }
		};
		
		Event.on(nextImgDiv, 'click', navClickHandler, {self:this, dir:'next'});
		Event.on(prevImgDiv, 'click', navClickHandler, {self:this, dir:'prev'});
		Event.on(closeDiv, 'click', function(e, o){o.self.lightboxPanel.showImgPanel.hide();}, {self:this});
		Event.on(resizeDiv, 'click', function(e, o){o.self.lightboxPanel.switchSize();}, {self:this});
		Event.on(helpDiv, 'click', function(e, o){o.self.lightboxPanel.toggleHelpPanel();}, {self:this});
		Event.on(infoDiv, 'click', function(e, o){o.self.lightboxPanel.toggleTooltip();}, {self:this});
		
		var slideShowCtrl =  new YAHOO.widget.Panel(this.lightboxPanel.showImgPanel.id + '_ctrlpanel',
		{
			visible : false,
			close: false,
			draggable: false,
			underlay: "none"
		});
		
		slideShowCtrl.appendToBody(prevImgDiv);
		slideShowCtrl.appendToBody(nextImgDiv);
		slideShowCtrl.appendToBody(closeDiv);
		//slideShowCtrl.appendToBody(infoDiv);
		slideShowCtrl.appendToBody(helpDiv);
		slideShowCtrl.appendToBody(resizeDiv);
		slideShowCtrl.appendToBody(dragDiv);
		//make slideShowCtrl movable
		var ctrlDragger = new YAHOO.util.DD(slideShowCtrl.id + "_c");
		var showImgPanel = this.lightboxPanel.showImgPanel;
		ctrlDragger.endDrag = function(e){
    		showImgPanel.sizeMask();
    	};
	    ctrlDragger.setHandleElId (this.lightboxPanel.showImgPanel.id + "Dragger");
		
		slideShowCtrl.render(document.body);
		
		Dom.addClass(slideShowCtrl.id, 'lui-lb-ctrl-panel');
		Dom.setStyle(slideShowCtrl.id + '_c', 'opacity', this.lightboxPanel.conf.ctrlOpacity);
				
		slideShowCtrl.bringToTop();
		this.slideShowCtrl = slideShowCtrl;
		this.dockToolbar(true);

		this.lightboxPanel.loadingPanel.getInstance().showEvent.subscribe(function(t, a, o){
			o.slideShowCtrl.hide();
		}, this);
		this.lightboxPanel.loadingPanel.getInstance().hideEvent.subscribe(function(t, a, o){
			if(o.lightboxPanel.conf.ctrlVisible){
			  o.slideShowCtrl.show();
			}
		}, this);
		
		this.lightboxPanel.showImgPanel.showEvent.subscribe(function(t, a, o){
			if(o.lightboxPanel.conf.ctrlVisible){
				slideShowCtrl.show();
				slideShowCtrl.bringToTop();
			}
		}, this);
		this.lightboxPanel.showImgPanel.hideEvent.subscribe(function(t, a, o){
			slideShowCtrl.hide();
		});
		this.galleryList = galleryList;
		
		if(this.lightboxPanel.conf.ctrlVisible){
		Event.on(window, 'scroll', function(e){
			var r = Dom.getRegion(document.body);
			slideShowCtrl.moveTo(Dom.getDocumentScrollLeft() + Dom.getClientWidth()/2 - 100
			, Dom.getDocumentScrollTop() + Dom.getClientHeight() - 75);
		});
		}
	},
	forward:function(){	
		this.lightboxPanel.placeImage(this.galleryList.forward());
	},
	backward:function(){
	    this.lightboxPanel.placeImage(this.galleryList.backward());
	},

	initKeyboardShortcut:function(){
		var showImgPanel = this.lightboxPanel.showImgPanel;
		var keys = {};
		//add keyboard shortcut
		//add escape
		keys.escapeKey = new YAHOO.util.KeyListener(document, { keys:27 },                               
	                                              { fn:this.lightboxPanel.showImgPanel.hide, 
	                                                scope:this.lightboxPanel.showImgPanel, 
	                                                correctScope:true } ); 
	 
    	showImgPanel.cfg.queueProperty("keylisteners", keys.escapeKey); 
    	
    	keys.leftKey = new YAHOO.util.KeyListener(document, { keys:37 },                               
	                                              { fn:this.backward, 
	                                                scope:this, 
	                                                correctScope:true } ); 
	 
    	showImgPanel.cfg.queueProperty("keylisteners", keys.leftKey); 
    	
    	keys.upKey = new YAHOO.util.KeyListener(document, { keys:[38,32] },                               
	                                              { fn:this.lightboxPanel.switchSize, 
	                                                scope:this.lightboxPanel, 
	                                                correctScope:true } ); 
	 
    	showImgPanel.cfg.queueProperty("keylisteners", keys.upKey); 

    	
    	keys.rightKey = new YAHOO.util.KeyListener(document, { keys:39 },                               
		                                              { fn:this.forward, 
		                                                scope:this, 
		                                                correctScope:true } ); 
		 
	    showImgPanel.cfg.queueProperty("keylisteners", keys.rightKey); 
    	
    	keys.downKey = new YAHOO.util.KeyListener(document, { keys:40 },                               
	                                              { fn:this.lightboxPanel.toggleTooltip, 
	                                                scope:this.lightboxPanel, 
	                                                correctScope:true } ); 
	 
    	showImgPanel.cfg.queueProperty("keylisteners", keys.downKey);
    	
    	keys.f1Key = new YAHOO.util.KeyListener(document, { keys:112 },                               
	                                              { fn:this.lightboxPanel.toggleHelpPanel, 
	                                                scope:this.lightboxPanel, 
	                                                correctScope:true } ); 
	                                          
    	this.navKeys = keys; 
    	
    	//enable keyboard shortcuts only when lightbox panel is shown
    	showImgPanel.showEvent.subscribe(function(e, a, o){
    		o.self.setKeyboardEnabled(true);
    		//disable keyboard default behavior
    		Event.on(document, 'keydown', function(e, o){
    			Event.preventDefault(e);
    		});
    	}, {self:this});
    	showImgPanel.hideEvent.subscribe(function(e, a, o){
    		o.self.setKeyboardEnabled(false);
    		Event.purgeElement(document, false, 'keydown');	
    	}, {self:this});
    	
    	
	},
	/**
	 * Bring control panel into the current viewport
	 * @param force if this is set to true, move the control panel regardless where it is 
	 */
	dockToolbar:function(force){
		if(!this.lightboxPanel.conf.ctrlVisible){
			return;
		}
		
		force = force == undefined ? false: force;
		var ctrlRegion = Dom.getRegion(this.slideShowCtrl.id);
		
		if(!force && (( this.lightboxPanel.pageScrollTopValue + Dom.getClientHeight() > ctrlRegion.bottom + 5) &&
		   ( this.lightboxPanel.pagepageScrollLeftValue + Dom.getClientWidth() > ctrlRegion.right + 5))
		 ){
			return;
		}
		window.scroll(0, this.lightboxPanel.pageScrollTopValue);
		this.slideShowCtrl.cfg.setProperty("x",
			Dom.getViewportWidth()/2 - (ctrlRegion.right - ctrlRegion.left)/2);
		this.slideShowCtrl.center();
		this.slideShowCtrl.cfg.setProperty("y",
			Dom.getViewportHeight() + Dom.getDocumentScrollTop() - 75);
	},
	/**
	 * Disable/enable keyboard shortcuts on navigation
	 */
    setKeyboardEnabled:function(state){
		if(state == true){
			for(var i in this.navKeys){
				this.navKeys[i].enable();
			}
		}else{
			for(var i in this.navKeys){
				this.navKeys[i].disable();
			}
		}
	},
	getList:function(){
		return this.galleryList;
	}
	
};


/**
 * A data structure emulating a gallery
 */
LOOT.widget.lightbox.ImageGalleryList = function(dataSource, isCircular){
	this.list = new Array();
	this.curIndex = 0;
	this.isCircular = isCircular == undefined ? false : isCircular;
	this.dataSource = dataSource;
	this.doIndex();
};

LOOT.widget.lightbox.ImageGalleryList.prototype = {
	/**
	* Create an index for a give data source for sequential access
	* @private
	*/
	doIndex:function(){
		for(var i in this.dataSource){
			this.list.push(i);
		}
	},
	getFirst:function(){
		return this.list[0];
	},
	getLast:function(){
		return this.list[this.getSize() - 1];
	},
	//return id of the image
	getCurrent:function(){
		return this.list[this.curIndex];
	},
	//return index of this list structure
	getCurrentIndex:function(){
		return this.curIndex;
	},
	setCurrentIndex:function(index){
		index = parseInt(index);
		if(index > this.getSize()){
			this.curIndex = this.getSize() - 1;
		}else if(index < 0){
			this.curIndex = 0;
		}else{
			this.curIndex = index;
		}
	},
	/**
	 * Supply id of an image, will return index of this list
	 */
	getIndexByImageId:function(imgId){
		for(var i in this.list){
			if(this.list[i] == imgId){
				return i;
			}
		}
		return -1;
	},

	getNextIndex:function(){
		var i;
		if(this.curIndex + 1 < this.getSize()){
			i = this.curIndex + 1;
		}else{
			if(this.isCircular){
				i = 0;
			}else{
			    i = this.curIndex;
			}
		}

		return i;
	},
	getNext:function(){
		return this.list[this.getNextIndex()];
	},
	getPreviousIndex:function(){
		var i;
		if(this.curIndex > 0){
			i = this.curIndex - 1;
		}else{
			if(this.isCircular){
			    i = this.getSize() - 1;
			  
			}else{
				i = 0;
			}
		}
		
		return i;
		
	},
	getPrevious:function(){
		return this.list[this.getPreviousIndex()];
	},
	forward:function(){
		this.curIndex = this.getNextIndex();
		return this.getCurrent();
	},
	backward:function(){
		this.curIndex = this.getPreviousIndex();
	    return this.getCurrent();
	},
	getSize:function(){
		return this.list.length;
	},
	toString:function(){
		var s = '';
		for(var i in this.list){
			s += i + ':' + this.list[i] + ' ';
		}
		return s;
	}
};
LOOT.widget.lightbox.LightboxPanel = function(conf){
	this.STATE_MAX = 0;
	this.STATE_FIT = 1;
	this.conf = conf == null ? {} : conf;
	this.conf.hasThumbnails = conf.hasThumbnails == null ? true: conf.hasThumbnails;
	this.conf.effect = conf.effect == null ? true:  conf.effect;
	this.conf.effectDuration = conf.effectDuration == null ? 1 : conf.effectDuration;
	this.conf.ctrlVisible = conf.ctrlVisible == null ? true : conf.ctrlVisible;
	this.conf.ctrlOpacity = conf.ctrlOpacity == null ? .5 : conf.ctrlOpacity;
	this.conf.id = conf.id == null ? 'lui_lightbox' : conf.id;
	this.conf.tooltip = conf.tooltip == null ? true : conf.tooltip;
	this.conf.tooltipOpacity = conf.tooltipOpacity == null ? .9 : conf.tooltipOpacity;
	this.imgCache = {};
	//this will be set after gallery has been created
	this.gallery = null;
	this.init();
};

LOOT.widget.lightbox.LightboxPanel.prototype = {
	init:function(){
		//create custom events
		//event fired when preload image starts
		this.preloadStartEvent = new YAHOO.util.CustomEvent("preloadStartEvent", this);
		//event fired whe preload image complete
		this.preloadCompleteEvent = new YAHOO.util.CustomEvent("preloadCompleteEvent", this);
		//After all images are preloaded, this event will be fired
		this.preloadAllCompleteEvent = new YAHOO.util.CustomEvent("preloadAllCompleteEvent", this);
		
		this.loadingPanel = new LOOT.widget.lightbox.LoadingPanel();
		this.initLightbox();
		if(this.conf.hasThumbnails){
		  this.prepareThumbnails();
		}
		this.pageScrollTopValue = 0;
		this.pageScrollLeftValue = 0;
		
		if(this.conf.effect == true){
			//+ 'ImgHolder'
			this.imgPanelFadeIn = new YAHOO.util.Anim(this.showImgPanel.id , { 
	    	opacity: {from: 0, to: 1 }  
	    	}, this.conf.effectDuration, YAHOO.util.Easing.easeOut); 
		} 
		
		//init image state
		for(var i in this.conf.dataSource){
			if(this.conf.dataSource[i].state == undefined){
				this.conf.dataSource[i].state = this.STATE_FIT;
			}
		}
		
		Dom.addClass(document.body, 'yui-skin-sam');
	},
	/**
	* Load data source and add click event to image thumbnails
	* @private
	*/
	prepareThumbnails:function(){
		var r = this.conf.dataSource

		//for each image ID in the data source
		for(var i in r){

			//event handler fired when the thumbnail is clicked
			var onImgClick = function(e, o){
				o.self.show(o.imgId);
			};//end of onImgClick
			var imgSmall = Dom.get(i); //get element by image ID
			Dom.setStyle(imgSmall, 'cursor', 'pointer');
			//add click handler to this thumbnail image
			Event.on(imgSmall, 'click', onImgClick, {self: this, imgId: i});
		}
	},
	/**
	* Preload an image, and store it in the imgCache
	* @param imgId Image ID in dataSource
	* @param boolean conf.progressBar Set to false to hide progress bar. Default true.
	*        function conf.callback   Event handler fired when the image is loaded
	*        function conf.param      Parameters passed to the callback function
	* @param preloadOnly if set to true, don't the lightbox after finishing preloading and hide loading panel
	*/
	preloadImage:function(imgId, conf, preloadOnly){
		preloadOnly = preloadOnly == null ? false : preloadOnly;
		this.preloadStartEvent.fire({imageId:imgId, ds:this.conf.dataSource[imgId]});
		if(conf == undefined){conf = {};}
		if(conf.progressBar == undefined){conf.progressBar = true;}
		var imgLoader = new LOOT.widget.lightbox.ImageLoader(this.conf.dataSource[imgId].url);
		imgLoader.loadEvent.subscribe(function(e, a, o){
		    o.self.loadingPanel.hide();
			//save this image to cache, along image width and height
			var img = this.getImage();
			o.self.imgCache[o.imgId] = img;
			o.self.conf.dataSource[o.imgId].width = img.width;
			o.self.conf.dataSource[o.imgId].height = img.height;
			if(!preloadOnly){
			  o.self.show(o.imgId);
			}
			//notify subscribers that this image has been preloaded
			o.self.preloadCompleteEvent.fire({imageId:o.imgId, ds:o.self.conf.dataSource[o.imgId]});
			//if number of elements in the cache is equal to the number in the data source,
			// then all images have been loaded
		    if(LOOT.util.countAsc(o.self.conf.dataSource) == LOOT.util.countAsc(o.self.imgCache)){
		    	o.self.preloadAllCompleteEvent.fire(LOOT.util.countAsc(o.self.conf.dataSource));
		    }
		}, {self:this, imgId: imgId, conf:conf});
		if(conf.callback != undefined){
			imgLoader.loadEvent.subscribe(conf.callback, conf.param);
		}
		if(conf.progressBar && !preloadOnly){
			this.loadingPanel.show("Loading image ...");
		}
		imgLoader.load();
	},
	/**
	 * Preload all images from dataSource. To monitor the status of preloading,
	 * You can subscribe to these events:
	 * this.preloadStartEvent
	 * this.preloadCompleteEvent
	 * this.preloadAllCompleteEvent
	 */
	 preloadAll:function(){
	 	var queue = new Array();
	    for(var i in this.conf.dataSource){
	 		queue.push(i);
	 	}
	 	queue.reverse();
	 	
	 	this.preloadImage(queue.pop(), null, true);
	 	this.preloadCompleteEvent.subscribe(function(e, a, o){
	 		if(queue.length > 0){
	 		  o.self.preloadImage(o.queue.pop(), null, true);
	 		}
	 	}, {self:this, queue:queue});
	 },
	setOpacity:function(percent){
		//+ 'ImgHolder'
		  Dom.setStyle(this.showImgPanel.id , 'opacity', percent);
	},
	savePageScrollPosition:function(){
		this.pageScrollLeftValue = Dom.getDocumentScrollLeft();
		this.pageScrollTopValue =  Dom.getDocumentScrollTop();		
	},
	restorePageScrollPosition:function(){
		window.scroll(this.pageScrollLeftValue, this.pageScrollTopValue);
	},
	/**
	 * Save page scroll location and call placeImage
	 * Use this function only to show the lightbox
	 */
	show:function(imgId){
        this.savePageScrollPosition();
		if(imgId == null){
			imgId = this.gallery.galleryList.getFirst();
		}
		this.placeImage(imgId);
	},
	/**
	* Place an given image to the image panel
	* @param imgId ID of the image
	* @private
	*/
	placeImage:function(imgId){
		
		this.gallery.dockToolbar();
		
		//update index of galleryList structure
		this.gallery.galleryList.setCurrentIndex(this.gallery.galleryList.getIndexByImageId(imgId));
		
		//check if the image is already cached
		var image = this.imgCache[imgId];
		this.gallery.setKeyboardEnabled(false); //disable keyboard shortcuts when loading
		
		if(image == undefined){
			this.preloadImage(imgId);
			return;
		}
		this.gallery.setKeyboardEnabled(true);
		if(this.conf.effect == true){
			this.imgPanelFadeIn.stop();
			this.setOpacity(0);
			this.imgPanelFadeIn.animate();
		}
		LOOT.util.empty(this._imgHolder);
		
		
		this.restorePageScrollPosition();
		
		//attach double click handler on image
		Event.purgeElement(this.showImgPanel.body, false, 'dblclick');
		Event.on(this.showImgPanel.body, 'dblclick', function(e, o){
		    o.self.restorePageScrollPosition(); 
		    o.self.switchSize();
			
		}, {imgId:imgId, self:this, image: image});
		
		//setting up tooltip
		var title;
		var text;
		var toolTipText = "";
		if(this.conf.dataSource[imgId].title == null ||
		this.conf.dataSource[imgId].title.length == 0){
			title = '&nbsp;';
		}else{
			title = this.conf.dataSource[imgId].title;
		}
		
		if(this.conf.dataSource[imgId].text == null ||
		this.conf.dataSource[imgId].text.length == 0){
			text = '&nbsp;';
		}else{
			text = this.conf.dataSource[imgId].text;
		}
		this.setTooltipText(title, text);
		

		this.showImgPanel.show();
		
		//the following two lines provide fix for opera
		var imageNode = document.createElement('img');
		imageNode.src = image.src;
		this._imgHolder.appendChild(imageNode);
		
		this._autoFit(image, imgId);
		this.sizeMask();
	},
	sizeMask:function(){
		Dom.setStyle(this.showImgPanel.id + '_mask', 'width', Dom.getClientWidth() + 'px');
		Dom.setStyle(this.showImgPanel.id + '_mask', 'height', Dom.getClientHeight() + 'px');
		this.showImgPanel.sizeMask();
	},
	/**
	 * if the lightbox is minimized, maximize it, reverse otherwise
	 */
	switchSize:function(){
		this.gallery.dockToolbar();
		var imgId = this.gallery.getList().getCurrent();
		var image =  Dom.get(this._imgHolder.id).getElementsByTagName('img')[0];
		if(this.conf.dataSource[imgId].state == this.STATE_MAX){
			this._autoFit(image, imgId);
		}else{
			this._maximize(image, imgId);
		}
		this.sizeMask();
	},
	_autoFit:function(){
		var imgId = this.gallery.getList().getCurrent();
		this.conf.dataSource[imgId].state = this.STATE_FIT;
		var image =  Dom.get(this._imgHolder.id).getElementsByTagName('img')[0];
		var iw = this.conf.dataSource[imgId].width;
		var ih = this.conf.dataSource[imgId].height;
		var vw = Dom.getViewportWidth() - 50;
		var vh = Dom.getViewportHeight() - 50;
	
			if(iw > vw || ih > vh){
				var ratioi = iw/ih;
				var ratiow = vw/vh;
				if(ratioi <= ratiow){
					image.height = vh;
					image.width = iw * (vh / ih);
				}else{
					image.width = vw;
					image.height = ih * (vw / iw);
				}
			}
		this.showImgPanel.cfg.setProperty('width', (image.width + 20)  + 'px');
		this.showImgPanel.center();
	},
	//DOM image instance to maximize its size
	_maximize:function(){
		var imgId = this.gallery.getList().getCurrent();
		var image =  Dom.get(this._imgHolder.id).getElementsByTagName('img')[0];
		this.conf.dataSource[imgId].state = this.STATE_MAX;
		image.width = this.conf.dataSource[imgId].width;
		image.height = this.conf.dataSource[imgId].height;
		this.showImgPanel.cfg.setProperty('width',
		(parseInt(this.conf.dataSource[imgId].width) + 20)+ 'px');
		this.showImgPanel.cfg.setProperty('x', 5);
		this.showImgPanel.center();
	},
	initLightbox:function(){
		var panelConf = {
			width: '100px',
			visible : false,
			draggable:false,
			modal: true,
			close:false
			//constraintoviewport: true
		};
		if(this.conf.modal != undefined && this.conf.modal == false){
			panelConf.modal = false;
		}
		var showImgPanel = new YAHOO.widget.Panel(this.conf.id, panelConf);

		var imgHolder = document.createElement('div');
		imgHolder.id = showImgPanel.id + 'ImgHolder';
		Dom.setStyle(imgHolder, 'text-align', 'center');
		showImgPanel.setBody(imgHolder);
		showImgPanel.render(document.body);
		Dom.addClass(showImgPanel.id, 'lui-lightbox');

		var isDragged = false;
		Event.on(showImgPanel.body, 'click', function(e, o){
		    if(!isDragged){
				showImgPanel.hide();
			}
			isDragged = false;
		}, {self:this});
		
        var imgPanelDragger = new YAHOO.util.DD(showImgPanel.id + "_c");
        
    	imgPanelDragger.startDrag = function(e){
    		isDragged = true;
    	};
         
    	imgPanelDragger.endDrag = function(e){
    		showImgPanel.sizeMask();
    	};
    	
        //add behavior that when mask is clicked, close the panel
		Event.on(showImgPanel.id + '_mask', 'click', function(e, o){
			o.self.showImgPanel.hide();
		}, {self:this});


		showImgPanel.beforeShowEvent.subscribe(function(){
			this.sizeMask();
		});
		showImgPanel.moveEvent.subscribe(function(){
			this.sizeMask();
		});

		//set mask opacity and color
		var maskHandler = function(t, a, o){
			o.self.imageTooltip.bringToTop();
			if(o.self.conf.maskOpacity != undefined){
				Dom.setStyle(this.id + '_mask', 'opacity', o.self.conf.maskOpacity);
			}
			if(o.self.conf.maskBgColor != undefined){
				Dom.setStyle(this.id + '_mask', 'background-color', o.self.conf.maskBgColor);
			}
		};
		showImgPanel.showEvent.subscribe(maskHandler, {self:this});

		this.loadingPanel.getInstance().showEvent.subscribe(maskHandler, {self:this});

		showImgPanel.beforeHideEvent.subscribe(function(t, a, o){
		  //shrink image so it won't create a scroll bar after hiding the panel
		    o.self.restorePageScrollPosition();
			o.self._autoFit();
		}, {self:this});
		showImgPanel.hideEvent.subscribe(function(t, a, o){
			o.self.imageTooltip.hide();
			o.self.helpPanel.hide();
		}, {self:this});
		

		this._imgHolder = imgHolder;
		this.showImgPanel = showImgPanel;
		
		//init tooltip
		var imageTooltip = new YAHOO.widget.Dialog( this.showImgPanel.id + "_infopanel", {
		        xy: [ 15 , 15 ], 
                width: "250px",
                close: false,
                draggable: false,
                visible: false
	    } );
	    
	    imageTooltip.setBody('&nbsp;');
	    imageTooltip.render(document.body);
	    Dom.addClass(imageTooltip.id, 'lui-lightbox-infopanel');
	    Dom.setStyle(imageTooltip.id, 'opacity', this.conf.tooltipOpacity);
	    
	    //pin tooltip to top left screen
	     Event.on(window, 'scroll', function(e){
		    var r = Dom.getRegion(document.body);
		    imageTooltip.moveTo(Dom.getDocumentScrollLeft() + 15, 
		    Dom.getDocumentScrollTop()+ 15);
		});
	    
	    var imgTooltipDragger = new YAHOO.util.DD(imageTooltip.id + "_c"); 
	    
    	imgTooltipDragger.endDrag = function(e){
    		showImgPanel.sizeMask();
    	};
    	
        imgTooltipDragger.endDrag = function(e){
    		showImgPanel.sizeMask();
    	};
	    
	    this.imageTooltip = imageTooltip;
	    
	    //init help panel
	    var helpPanel = new YAHOO.widget.Panel( this.showImgPanel.id + "_helppanel", {  
			  width: "250px",
			  close: false,
			  draggable: false,
			  visible: false,
			  fixedcenter: true,
			  effect:{effect:YAHOO.widget.ContainerEffect.FADE,duration:0.10} 
	    } );
	    helpPanel.setBody(' ');
	    helpPanel.render(document.body);
	    Dom.addClass(helpPanel.id, 'lui-lightbox-helppanel');
    	Event.on(helpPanel.body, 'click', function(){
    		helpPanel.hide();
    	});
    	
    	this.helpPanel = helpPanel;
    	this._setHelpPanelBody();
    	
    	
	},
	_setHelpPanelBody:function(){
		this.helpPanel.setBody(
		'<div class="lui-lb-helppanel-title">Basic Operations:</div>' +
		'<strong>Click</strong> to close the lightbox<br/>' + 
		'<strong>Drag</strong> to move the lightbox<br/>'+
		'<br/>' +   
		'<div class="lui-lb-helppanel-title">Keyboard Shortcuts:</div>' + 
		'<strong>Arrow Left</strong> - Previous photo<br/>' +
		'<strong>Arrow Up/Space bar</strong> - Toggle maximize/restore<br/>' + 
		'<strong>Arrow Right</strong> - Next photo<br/>' + 
		'<strong>Arrow Down</strong> - Toggle ad description<br/>' + 
		'<strong>Escape</strong> - Close gallery<br/>' + 
		'<strong>F1</strong> - Show help<br/>' + 
		'<br/>Click this panel to close<br/>');
	},
	toggleTooltip:function(){
		this.conf.tooltip = !this.conf.tooltip;
		if(this.imageTooltip.cfg.getProperty('visible') == true && !this.conf.tooltip){
			this.imageTooltip.hide();
		}else{
			this.imageTooltip.show();
			this.imageTooltip.bringToTop();
		}
	},
	toggleHelpPanel:function(){
		if(this.helpPanel.cfg.getProperty('visible') == true){
			this.helpPanel.hide();
		}else{
			this.helpPanel.show();
			this.helpPanel.bringToTop();
		}
	},
	setTooltipText:function(title, text){
		title = (title == null || title == '&nbsp;') ? '':title;
		text = (text == null || text == '&nbsp;') ? '':text;
		
		if(title.length == 0 && text.length == 0 ){
			this.imageTooltip.hide();
		  
		}else{
			if(this.conf.tooltip){
				this.imageTooltip.show();
			}
			
			this.imageTooltip.setBody('<div class="lui-lb-infopanel-title" id="' + this.imageTooltip.id + '_title">' + title + '</div>' + 
		    '<div class="lui-lb-infopanel-desc" id="' + this.imageTooltip.id + '_desc">' + text + '</div>');
		    
		}
	}
};
LOOT.widget.lightbox.Lightbox = function(dataSource, conf){
	this.init(dataSource, conf);
};

LOOT.widget.lightbox.Lightbox.prototype = {
	init:function(dataSource, conf){
		conf = conf == null ? {} : conf;
		conf.dataSource = dataSource;
		this.conf = conf;
		this.lightboxPanel = new LOOT.widget.lightbox.LightboxPanel(conf);
		this.imageGallery = new LOOT.widget.lightbox.ImageGallery(conf.dataSource, this.lightboxPanel);
	},
	show:function(imgId){
	    try {
		    this.lightboxPanel.show(imgId);
		} catch (ex) {
		    console.log(ex);
		    // TODO: work out why firebug causes an issue where the image doesnt get placed into the centre
		    // of the screen and doesnt throw an error. Using a try / catch block seems to fix the problem.
		};
	},
	preloadAll:function(){
		this.lightboxPanel.preloadAll();
	},
	setDataSource:function(dataSource){
		this.lightboxPanel.conf.dataSource = dataSource;
	    this.lightboxPanel.imgCache = {};
		this.imageGallery.dataSource = dataSource;
		this.imageGallery.galleryList = new LOOT.widget.lightbox.ImageGalleryList(dataSource, true);
	},
	dispose:function(){
		this.lightboxPanel.showImgPanel.destroy();
		this.lightboxPanel.imageTooltip.destroy();
		this.imageGallery.slideShowCtrl.destroy();
		this.lightboxPanel.loadingPanel.loadingPanel.destroy();
		this.lightboxPanel.helpPanel.destroy();
	}
};

(function() {
    var build_skyScraper = {
        init: function() {
            if (Dom.getViewportWidth() > LOOT.constant.skyscraper_screen_size) {
                var _parent = Selector.query("#bd > .yui-b", document, true),
                    _skyScraper = new LOOT.widget.banner(_parent);

                _skyScraper.show();
            };
        }
    }
    Event.onDOMReady(build_skyScraper.init, build_skyScraper, true);

    var star_ad = {
        config: {
            trigger_id: 'sub_details',
            saved_container: 'save',
            saved_class: 'starred',
            starred_ad_count_class: 'starred-ad-count'
        },
        init: function() {
            this.timer = [];
            this.star = Dom.getElementsByClassName(this.config.saved_container)[0];

            Event.addListener(this.star, "click", star_ad.handle_click, star_ad, true);
            this.counters = Dom.getElementsByClassName(this.config.starred_ad_count_class);
        },
        handle_click: function(ev) {
            var _tar = Event.getTarget(ev);
            var _message_box;

            if (_message_box) {
                _message_box.hide();
            };
            if (star_ad.timer[0]) {
                clearTimeout(star_ad.timer[0]);
            };
            star_ad.timer[0] = setTimeout(function() {
                _message_box = LOOT.widget.showInfoMessage;
                _message_box.show(LOOT.constant.timeout_message);
            }, LOOT.constant.timeout);

            try {
                this.set_class_name(_tar);
                this.call_ajax(_tar);
                this.clicked = _tar;
            } catch (ex) {
                console.log(ex);
            };
        },
        set_class_name: function(tar) {
            if (tar.className == this.config.saved_class) {
                Dom.removeClass(tar, this.config.saved_class);
            } else {
                Dom.addClass(tar, this.config.saved_class);
            };
        },
        call_ajax: function(tar) {
            try {
                var _servicePath = LOOT.constant.path.webservice + LOOT.constant.webservice.advert;
                var _methodName = "UpdateSavedAd";
                var _params = { savedAdvertId: tar.id, visitorExternalId: EXTERNAL_VISITOR_KEY };
                var _webServiceProxy = new Sys.Net.WebServiceProxy();
                _webServiceProxy.set_timeout(0);

                var _request = _webServiceProxy._invoke(_servicePath,   // the webservice to be called
                                                        _methodName,    // the method to call in the webservice
                                                        false,          // get (true) or post (false)
                                                        _params,        // parameteres expected by the method
                                                        this.handle_success,    // callback function for success
                                                        this.handle_failure);   // callback function for failure
            } catch (ex) {
                star_ad.set_class_name(tar);
            };
        },
        handle_success: function(objJSON) {
            if (star_ad.timer[0]) {
                clearTimeout(star_ad.timer[0]);
            };

            LOOT.widget.showInfoMessage.hide();

            for (var i = 0; i < star_ad.counters.length; i++) {
                var _c = star_ad.counters[i];
                _c.innerHTML = '(' + objJSON + ')';
            };

        },
        handle_failure: function() {
            var _m;

            star_ad.set_class_name(star_ad.clicked);

            if (star_ad.timer[0]) {
                clearTimeout(star_ad.timer[0]);
            };
            if (LOOT.widget.showInfoMessage.hidden) {
                _m = 'Sorry, we encountered a problem, please try again.';
                LOOT.widget.showInfoMessage.show(_m);
            } else {
                _m = 'Sorry, we still appear to have a problem, please try again.';
                LOOT.widget.showInfoMessage.update(_m);
            };
            star_ad.timer[0] = setTimeout(function() {
                LOOT.widget.showInfoMessage.hide();
            }, LOOT.constant.timeout);
        }
    };
    Event.onAvailable(star_ad.config.trigger_id, star_ad.init, star_ad, true);

    var image_gallery = {
        config: {
            gallery_wrapper_id: 'photos',
            gallery_main: {
                id: 'gallery_main',
                height: 200,
                width: 300,
                scaling: 'FitPad'
            },
            gallery_thumb: {
                cssClass: 'gallery_thumb',
                height: 50,
                width: 75,
                scaling: 'FitPad'
            },
            lightbox_settings: {
                ctrlOpacity: 1
            }
        },
        init: function() {
            var _thumbs = Dom.getElementsByClassName(this.config.gallery_thumb.cssClass),
                _dataSource = {},
                _title = Dom.get('advert_title').innerHTML,
                _text = Dom.get('advert_description').innerHTML;

            for (var i = 0; i < _thumbs.length; i++) {
                var _src = _thumbs[i].src.split('?')[0];
                _dataSource[_thumbs[i].id] = { url: _src, title: _title, text: _text };
            };

            this.lightbox = new LOOT.widget.lightbox.Lightbox(_dataSource, this.config.lightbox_settings);

            Event.addListener(_thumbs, "click", this.handle_click, this, true);
        },
        handle_click: function(ev) {
            var _tar = Event.getTarget(ev);
            var _main = Dom.get(this.config.gallery_main.id);

            _srcArray = new Array();
            _srcArray = _tar.src.split('?');
            _main.src = _srcArray[0] + '?t=tr/w:' + this.config.gallery_main.width + '/h:' + this.config.gallery_main.height + '/m:' + this.config.gallery_main.scaling;
        }
    };
    Event.onAvailable(image_gallery.config.gallery_wrapper_id, image_gallery.init, image_gallery, true);

    var location_map = {
        config: {
            maps_wrapper_id: 'gMap'
        },
        init: function() {
            try {
                this.latLong = new Array();
                this.latLong = Dom.get(this.config.maps_wrapper_id).className.split(' ');

                Event.addListener(window, "unload", location_map.destroy_gMap);

                this.create_gMap();
            } catch (e) {
                // Do Nothing
            };
        },
        create_gMap: function() {
            if (GBrowserIsCompatible()) {
                var _point = new GLatLng(parseFloat(this.latLong[0]), parseFloat(this.latLong[1]))
                var _marker = new GMarker(_point);
                var _showAccurate = this.latLong[2];

                // Create Map
                this.gMap = new GMap2(Dom.get(this.config.maps_wrapper_id));
                // Center map on uk
                this.gMap.setCenter(_point, 14);
                this.gMap.addControl(new GSmallZoomControl());
                // Add marker
                if (_showAccurate == "1")
                    this.gMap.addOverlay(_marker);
            };
        },
        destroy_gMap: function() {
            GUnload();
        }
    };
    Event.onAvailable(location_map.config.maps_wrapper_id, location_map.init, location_map, true);


    var message_seller = {
        config: {
            id: 'contact-seller',
            disabled_classname: 'disabled',
            modal_box_title: 'Contact Seller',
            email_input_id: 'txtAdAbuseInfo_email',
            comment_input_id: 'txtAdAbuseInfo_description',
            post_url: 'http://' + window.location.host + '/advert/report-abuse.aspx'
        },
        init: function() {
            try {
                // gather elements required to build new panel
                this.message_box = {
                    link: Dom.get(this.config.id + '-link'),
                    container: Dom.get(this.config.id),
                    content: Selector.query('.message-seller #details', this.message_box, true),
                    button: Selector.query('.message-seller #controls input', this.message_box, true)
                }
                this.messagePanel = null;
                this._innerHTML = null;
                //remove the other contact seller box from the page
                this.message_box.container.parentNode.removeChild(this.message_box.container);
                // add click event to open new contact seller panel
                Event.addListener(this.message_box.link, "click", this.handle_click, this, true);
            } catch (ex) {
                LOOT.util.log(ex);
            };
        },
        handle_click: function(ev) {
            Event.stopEvent(ev);

            var _self = this;

            try {
                if (_self.messagePanel == null) {
                    _self.messagePanel = new LOOT.panel.ModalDialogRounded(this.config.modal_box_title, {
                        close: true,
                        render: 'bd',
                        modal: false
                    });
                    _self.messagePanel._buttons = [];

                    _self.messagePanel.showEvent.subscribe(function() {
                        if (this._buttons.length == 0) {
                            var _complete = false;
                            // Create a cancel button
                            this._buttons[0] = new YAHOO.widget.Button({
                                id: 'lui_cancel_button',
                                type: 'push',
                                label: 'cancel',
                                container: 'footer_buttons'
                            });
                            // Create a submit button from existing markup
                            this._buttons[1] = new YAHOO.widget.Button(
                                _self.message_box.button,
                                {
                                    label: 'Send <img id="waiting_message" src="/content/images/trans.gif" />',
                                    container: 'footer_buttons'
                                }
                            );
                            // Assign a click handler for cancel button
                            this._buttons[0].on('click', function() {
                                _self._innerHTML = Dom.get(_self.message_box.content.id).innerHTML;
                                _self.message_box.content = Dom.get(_self.message_box.content.id);
                                _self.messagePanel.hide();
                            });
                            // Assign a click handler for submit button
                            this._buttons[1].on('click', function(ev) {
                                var _button = this._button;
                                if (!_button.disabled) {
                                    Dom.addClass(_button, 'waiting');
                                };
                            }, this._buttons[1], true);
                            // Set the submit button to disabled
                            this._buttons[1].set('disabled', true);
                            // Create a keyup listener on the input fields to ensure a user has filled in all inputs
                            Event.on(_self.message_box.content, 'keyup', _self.send_message, this, true);
                            Event.on(_self.message_box.content, 'blur', _self.send_message, this, true);
                        };
                    }, _self.messagePanel, true);
                };

                _self.messagePanel.setBody(_self.message_box.content);
                // In certain browsers the message_boc loses its child elements so we save them to another variable,
                // If needed they are added back into the html.
                if (_self.message_box.content.childNodes.length == 0) {
                    Dom.get(_self.message_box.content.id).innerHTML = _self._innerHTML;
                };
                _self.messagePanel.show();
            }
            catch (ex) {
                LOOT.util.log('message_seller.messagePanel: ', ex);
            };
        },
        send_message: function(ev) {
            var _self = message_seller,
                _tar = Event.getTarget(ev),
                _email = Selector.query('input', _self.message_box.content, true),
                _message = Selector.query('textarea', _self.message_box.content, true),
                _re = new RegExp(LOOT.constant.regex.email);

            _complete = (!_re.test(_email.value)) || (_message.value == '');

            this._buttons[1].set('disabled', _complete);
        },
        show_message: function(msg) {
            var _self = this,
                _msg = msg;

            try {
                if (_self.timer) {
                    clearTimeout(_self.timer);
                };
                if (LOOT.widget.showInfoMessage.hidden) {
                    LOOT.widget.showInfoMessage.show(_msg);
                } else {
                    _msg = 'Sorry, we still appear to have a problem, please try again, or call ' + LOOT.constant.customer_services_number;
                    LOOT.widget.showInfoMessage.show(_msg);
                };
                _self.timer = setTimeout(function() {
                    LOOT.widget.showInfoMessage.hide();
                }, LOOT.constant.timeout);
            } catch (ex) {
                LOOT.util.log('message_seller.show_message: ', ex);
            };
        }
    };
    Event.onDOMReady(message_seller.init, message_seller, true);


    var report_abuse = {
        config: {
            id: 'report_abuse',
            disabled_classname: 'disabled',
            modal_box_title: 'Report This Advert',
            email_input_id: 'txtAdAbuseInfo_email',
            comment_input_id: 'txtAdAbuseInfo_description',
            post_url: 'http://' + window.location.host + '/advert/report-abuse.aspx'
        },
        init: function() {
            var _report_link = Dom.get(this.config.id),
                _link_classnames = _report_link.className.split(' ');
            this.report_link = _report_link;
            this.ad_id = _link_classnames[_link_classnames.length - 1];
            this.ReportAbusePanel = null;

            Dom.addClass(Selector.query('body'), 'yui-skin-sam');
            Dom.removeClass(this.report_link, this.config.disabled_classname);

            Event.addListener(this.report_link, "click", this.handle_click, this, true);
        },
        handle_click: function() {
            var _self = this,
                _HTMLContent = 'Please enter your contact email and your comment:';
            _HTMLContent += '<p id="report_ad_email" class="message-email"><label for="' + this.config.email_input_id + '">Your email:</label><input id="' + this.config.email_input_id + '" value="" size="40" /></p>';
            _HTMLContent += '<p id="report_ad_message" class="message-content"><label for="' + this.config.comment_input_id + '">Your comment on this listing:</label><textarea cols="37"  rows="5" id="' + this.config.comment_input_id + '"></textarea></p>';

            try {
                _self.ReportAbusePanel = new LOOT.panel.ModalDialogRounded(this.config.modal_box_title, {
                    close: true
                });
                _self.ReportAbusePanel._buttons = [];

                _self.ReportAbusePanel.showEvent.subscribe(function() {
                    if (this._buttons.length == 0) {
                        this._buttons[0] = new YAHOO.widget.Button({
                            id: 'lui_cancel_button',
                            type: 'push',
                            label: 'cancel',
                            container: 'footer_buttons'
                        });
                        this._buttons[1] = new YAHOO.widget.Button({
                            type: 'push',
                            label: 'Ok',
                            container: 'footer_buttons'
                        });

                        this._buttons[0].on('click', function() {
                            _self.ReportAbusePanel.hide();
                        });
                        this._buttons[1].on('click', function() {
                            _self.log_abuse();
                        });
                    };
                }, _self.ReportAbusePanel, true);

                _self.ReportAbusePanel.setBody(_HTMLContent);
                _self.ReportAbusePanel.show();
            }
            catch (ex) {
                LOOT.util.log('report_abuse.ReportAbusePanel: ', ex);
            };
        },
        log_abuse: function() {
            var _self = this,
                _advert = _self.ad_id,
                _email = Dom.get(_self.config.email_input_id).value,
                _comment = Dom.get(_self.config.comment_input_id).value,
                _hasComment = _email != '' && _comment != '',
                _re = new RegExp(LOOT.constant.regex.email);

            var _url = _self.config.post_url,
                _params = 'advert=' + _advert + '&email=' + _email + '&comment=' + _comment,
                _callback = {
                    success: function(o) {
                        Dom.addClass(_self.report_link, _self.config.disabled_classname);
                        _self.report_link.src = 'javascript: void(0);';
                        Event.removeListener(_self.report_link, 'click');

                        _self.show_message(o.responseText);

                        _self.timer = setTimeout(function() {
                            _self.ReportAbusePanel.hide();
                            _self.ReportAbusePanel.setBody('');
                        }, 2000);
                    },
                    failure: function(o) {
                        _self.show_message(o.responseText);
                    },
                    scope: this
                };

            if (!_re.test(_email)) {
                _self.show_message('Please enter a valid email address');
            } else if (_hasComment) {
                Connect.asyncRequest('POST', _url, _callback, _params);
            } else {
                _self.show_message('Please fill in all sections to report abuse.');
            };
        },
        show_message: function(msg) {
            var _self = this,
                _msg = msg;

            try {
                if (_self.timer) {
                    clearTimeout(_self.timer);
                };
                if (LOOT.widget.showInfoMessage.hidden) {
                    LOOT.widget.showInfoMessage.show(_msg);
                } else {
                    _msg = 'Sorry, we still appear to have a problem, please try again, or call ' + LOOT.constant.customer_services_number;
                    LOOT.widget.showInfoMessage.show(_msg);
                };
                _self.timer = setTimeout(function() {
                    LOOT.widget.showInfoMessage.hide();
                }, LOOT.constant.timeout);
            } catch (ex) {
                LOOT.util.log('report_abuse.show_message: ', ex);
            };
        }
    };
    Event.onDOMReady(report_abuse.init, report_abuse, true);

})();