
function pc3PopupManagement(){
	var self = this;
	
	this.designs = $H({});
	this.popups = $H({});
	this.hiddenSelects = new Array();
	this.triggers = $H({});
	this.openPopups = $H({});
	this.popup = $(pc3Widget.body);
	this.content = $(pc3Widget.body);
	this.id = 'management';
	this.parentNode	= '';
	
	this.init = function(){
		this.selects = this.content.select('select');
		this.initPopups();
	}

	this.initPopups = function(){
		var popupData = pc3PopupData;
		if ( !popupData.size() ) return;
		var popupDesignData = $H(pc3PopupDesignData);

		popupData.each(function(popup){
			var designId = popup.designId;
			if ( !self.designs.get(designId) && ( designId && $(designId) && popupDesignData.get(designId) )){
				self.designs.set(designId, new pc3PopupDesign(designId, popupDesignData.get(designId), self));
			}
			var trigger = $(popup.triggerId);
			if ( self.designs.get(designId) && trigger ){
				var popupId = popup.triggerId+"_"+designId;
				if ( !self.popups.get(popupId) ){
					self.popups.set(popupId, new pc3Popup(popupId, popup.triggerId, popup, self.designs.get(designId), self));
					self.triggers.set(popup.triggerId, self.popups.get(popupId));
				} else {
					self.popups.get(popupId).init();
				}
				self.popups.get(popupId).openInitially();
			}
		});
		pc3PopupData = new Array();
	}

	this.getParent = function(popup){
		if ( popup.parent ) return;
		var dataNode = $(popup.id+'Data');
		if ( !dataNode ) return;
		var parent = dataNode.up('.pc3popupdata');
		if ( parent ){
			parent = self.popups.get(parent.id.slice(0,(parent.id.length-4)));
		} else {
			parent = dataNode.up('[pc3popup]');
			if ( parent ) parent = parent.popup;
		}
		if ( !parent ) parent = this;
		return parent;
	}
		
	this.addOpenPopup = function(popup){
		if ( !this.openPopups.size() && Prototype.Browser.IE6 ) {
			this.selects.each(function(select){
				if ( select.visible() ){
					self.hiddenSelects.push(select);
					select.style.visibility = "hidden";
				}
			});
		}
		this.openPopups.set(popup.id, popup);
	}

	this.removeOpenPopup = function(popup){
		var zIndex = 1000;
		this.openPopups.unset(popup.id);
		this.openPopups.each(function(currentPopup){
			currentPopup.value.setZIndex(zIndex);
			zIndex++;
		});
		if ( !this.openPopups.size() && Prototype.Browser.IE6 ) {
			this.hiddenSelects.each(function(select){ select.style.visibility = "visible"; });
			this.hiddenSelects = new Array();
		}
	}

	this.removePopup = function(popupId){
		this.popups.unset(popupId);
	}

	this.removeAjaxPopups = function(ajaxContent){
		this.triggers.each(function(currentTrigger){
			var ancestors = currentTrigger.value.trigger.ancestors();
			if ( !ancestors.size() || ancestors.last().tagName != 'HTML' ){
				if ( currentTrigger.value.parent ) currentTrigger.value.parent.removePopup(currentTrigger.value.id);
				else self.popups.unset(currentTrigger.value.id);
			}
		});
	}

	this.closeOtherOpenPopups = function(popup){
		if ( popup.groupname == 'pc3DefaultPopupGroup' ) return;
		this.openPopups.each(function(currentPopup){ if ( popup.id != currentPopup.key && popup.groupname == currentPopup.value.groupname ) currentPopup.value.close(''); });		
	}

	this.addPopup = function(popup){ if ( !this.popups.get(popup.id) ) this.popups.set(popup.id, popup); }
	
	this.doForAllOpenPopups = function(func){ this.openPopups.each(function(currentPopup){ func.bind(currentPopup.value)(); }); }

	this.doForAllPopups = function(func){ this.popups.each(function(currentPopup){ func.bind(currentPopup.value)(); }); }
	
	this.getZIndex = function(){ return (1000 + this.openPopups.size()); }
		
	this.isOpen = function(){ return true; }
	
	this.close = function(){ return false; }


	this.closePopup = function(trigger){
		var element = $(trigger);
		if ( typeof(trigger) == 'string' ){
			if ( element && element.popup ) element.popup.close('');
		} else {		
			var parent = element.up('[pc3Popup]');
			if ( parent ) parent = parent.popup;
			if ( parent ) parent.close('');
		}
	}

	this.updatePopup = function(trigger){
		var element = $(trigger);
		if ( typeof(trigger) == 'string' ){
			if ( element && element.popup ) element.popup.update();
		} else {		
			var parent = element.up('[pc3Popup]');
			if ( parent ) parent = parent.popup;
			if ( parent ) parent.update();
		}
	}

	// Event handlers
		this.handleMouseMove = function(event){ this.doForAllOpenPopups(function(){ this.handleMouseMove(); }); }
	
		this.handleClick = function(event){ this.doForAllOpenPopups(function(){ this.handleClick(event); }); }
	
		this.handleResize = function(event){ this.doForAllOpenPopups(function(){ this.handleResize(); }); }
	
		this.handleScroll = function(event){ this.doForAllOpenPopups(function(){ this.handleScroll(); }); }
	//---------------
		
	this.init();
	
}


function pc3PopupDesign(designId, designData, management){
	var self = this;
	this.id = designId;
	this.management = management;
	
	//"behaviour","openTrigger","openTriggerDelay","openSizeAnimation","openAnimation","openPathAnimation",
	//"openEffect","openDuration","originPosition","closedPosition","closeTriggers","closeTriggerDelay","closeSizeAnimation","closeAnimation",
	//"closePathAnimation","closeEffect","closeDuration","endPosition","backgroundColor","backgroundOpacity","backgroundOpenAnimation",
	//"backgroundOpenEffect","backgroundCloseAnimation","backgroundCloseEffect","displayShadow","placeholders",
	//"cornerSize","shadowOffsetTop","shadowOffsetRight","shadowOffsetBottom","shadowOffsetLeft","shadowTop","shadowRight","shadowBottom","shadowLeft"

	this.init = function(designData){
		var designData = $H(designData);
		designData.each(function(attribute){ self[attribute.key] = attribute.value; });
		if ( this.shadow.enabled ){
			this.shadow.blurRadius = parseInt(this.shadow.blurRadius);
			this.shadow.marginLeft = parseInt(this.shadow.marginLeft);
			this.shadow.marginRight = parseInt(this.shadow.marginRight);
			this.shadow.marginTop = parseInt(this.shadow.marginTop);
			this.shadow.marginBottom = parseInt(this.shadow.marginBottom);
			this.shadow.cornerSize = parseInt(this.shadow.cornerSize);
			this.shadowImages = {};
			['Left','Top','Right','Bottom'].each(function(location){
				if ( !self.shadow['image'+location] ) return;
				self.shadowImages[location.toLowerCase()] = self.shadow['image'+location];
				var loader = new Image();
				loader.src = self.shadow['image'+location];
			});
		}
		this.template = $(this.id);
		this.template.id = '';
		this.width = this.template.getWidth();
		this.height = this.template.getHeight();
		this.opacity = pc3Widget.getOpacity(this.template) * 100;
		this.template.remove();
	}	

	this.init(designData);
}

function pc3Popup(popupId, triggerId, popupData, design, management){
	var self = this;
	this.id = popupId;
	this.design = design;
	
	this.management = management;
	this.popupData = $H(popupData);
	this.parent = '';
	this.waitingToOpen = '';
	this.waitingToClose = '';
	this.closeAfterOpen = '';
	this.openAfterClose = '';
	this.popup = '';
	this.hiddenSelects = new Array();
	
	this.openedPosition = {x:0,y:0,width:0,height:0,marginLeft:0,marginRight:0,marginTop:0,marginBottom:0,factorWidth:0,factorHeight:0};
	this.closedPosition = {x:0,y:0,width:0,height:0,marginLeft:0,marginRight:0,marginTop:0,marginBottom:0,factorWidth:0,factorHeight:0};
	this.currentPosition = {x:0,y:0,width:0,height:0};
	this.lastSize = {width:0,height:0};
	this.effects = $H({});
	this.shadow = '';
	this.shadowOffsets = {offsetLeft:0, offsetTop:0, offsetRight:0, offsetBottom:0, offsetsX:0, offsetsY:0};
	this.eventLayer = '';
	this.popups = $H({});
	this.openPopups = $H({});
	this.background = '';
	this.ajaxRequest = false;
	this.triggerId = triggerId;
	
	this.init = function(){
		this.trigger = $(this.triggerId);
		this.trigger[this.id] = 'closed';
		this.trigger.popup = this;
		this.groupname = this.popupData.get('groupName');
		if ( !this.groupname ) this.groupname = 'pc3DefaultPopupGroup';

		var openHandler = this.open.bindAsEventListener(this);
		if ( this.design.open.trigger == 'click' ) openHandler = this.handleClickOnTrigger.bindAsEventListener(this);
		Event.observe(this.trigger, this.design.open.trigger, openHandler);

		if ( this.design.close.trigger && this.design.close.trigger.indexOf('mouseout') >= 0 ) {
			Event.observe(this.trigger, 'mouseout', this.close.bindAsEventListener(this));
		}
		
		this.openTriggerDelay = parseFloat( this.design.open.delay ) || 0;
		this.closeTriggerDelay = parseFloat(this.design.close.delay) || 0;
		
		this.initialState = this.popupData.get('initialState');

	}

	this.bindToParent = function(){
		this.parent = this.management.getParent(this);
		this.parent.addPopup(this);
	}
	
	this.initPopup = function(){
		this.outerBox = new Element('div').setStyle({position:'absolute', overflow:'hidden'}).hide();
		this.outerBox.popup = this;
		this.outerBox.widget = this;
		this.outerBox.writeAttribute({pc3Popup:1});
		this.outerBox.writeAttribute({pc3Widget:1});
		this.innerBox = new Element('div').setStyle({position:'relative'});
		this.outerBox.appendChild(this.innerBox);
		this.popup = this.design.template.cloneNode(true).removeClassName('pc3popupdesign').setStyle({position:'absolute',zIndex:1});
		this.innerBox.appendChild(this.popup);
		this.popup.outerDimension = pc3Widget.getOuterDimension(this.popup, false);
		this.content = new Element('div').setStyle({position:'relative'});

		this.contentBox = this.content.wrap('div').setStyle({position:'absolute', overflow:'hidden',zIndex:2});
		this.innerBox.appendChild(this.contentBox);

		//transfer childs of pupup design to content
		this.popup.childElements().each( function(item) {
			Element.insert(self.content, item); 
		});

		if ( this.design.close.trigger && this.design.close.trigger.indexOf('mouseout') >= 0 ) {
			Event.observe(this.popup, 'mouseout', this.close.bindAsEventListener(this));
			Event.observe(this.content, 'mouseout', this.close.bindAsEventListener(this));
		}
		
		if ( this.design.close.trigger && this.design.close.trigger.indexOf('clickInsidePopup') >= 0 ) {
			this.eventLayer = new Element('div').setStyle({position:'absolute',zIndex:3});
			Event.observe(this.eventLayer, 'click', this.close.bindAsEventListener(this));
			this.innerBox.appendChild(this.eventLayer);
		}

		//populate popup
		var dataNode = $(this.id+'Data');
		var topDataNode = dataNode;
		
		if ( this.design.placeholders != null ){
			this.design.placeholders.each(function(name){ //loop through placeholders
				var dataElement = '';
				dataNode.childElements().each(function(child){ if ( child.className == name ) dataElement = child; });		
				var targetElement = self.content.down('.'+name);
				if ( targetElement ) targetElement.removeClassName(name);
				if ( targetElement && dataElement ) dataElement.childElements().each(function(child){ targetElement.appendChild(child); });
				else if ( targetElement ) targetElement.remove();
			});
		}
		
		if ( this.design.positionChilds == 'absolute' ){
			if ( this.parent.parentNode ){
				this.parentNode = this.parent.parentNode;
			} else {
				dataNode.ancestors().each(function(element){
					if ( element.className == 'pc3popupwrapper' ) topDataNode = element;
					else if ( !self.parentNode && element.tagName != 'TD' && element.tagName != 'TR' && element.tagName != 'TBODY' && element.tagName != 'TABLE' ) self.parentNode = element;
				});
			}
		} else {
			this.parentNode = this.parent.content;
		}

		topDataNode.remove();
		this.parentNode.appendChild(this.outerBox);

		this.settings = {};
		['origin','opened','closed'].each(function(state){
			var values = {};
			var definition = self.popupData.get(state);
			values['setting'] = definition.element;
			values['position'] = definition.position;
			values['margins'] = {x:(definition.marginLeft?parseInt(definition.marginLeft):0),y:(definition.marginTop?parseInt(definition.marginTop):0)};
			values['element'] = '';
			if ( values.setting == 'triggerElement' ) values['element'] = self.trigger;
			else if ( values.setting == 'parentElement' ) values['element'] = self.parent.popup;
			else if ( values.setting == 'customElement' && definition.custom && $(definition.custom) ) values['element'] = $(definition.custom);
			self.settings[state] = values;
			
			if ( values['setting'] == 'atMouse' || !values['element'] ){
				if ( !values['margins'].x ) values['margins'].x = 1;
				if ( !values['margins'].y ) values['margins'].y = 1;
			}
		});
	}
		
	this.openInitially = function(){
		if ( this.initialState == 'opened' ) this.open('', '');
	}
	
	this.open = function(event, delay){
		if ( event ) event.stop();
		if ( !this.parent ) this.bindToParent();
		
		if ( !this.parent.isOpen() ) return;
		if ( this.waitingToOpen ) return;
		if ( this.waitingForClose ) {
			window.clearTimeout(this.waitingForClose);		
			this.waitingForClose = '';
			return;
		}
		if ( this.state == 'opened' || this.state == 'opening' ) return;
		if ( this.state == 'closing' ){
			this.openAfterClose = this.open.bind(this);
			return;
		}

		if ( !this.popup ) {
			this.initPopup();
			if ( this.design.shadow.enabled ){
				this.shadow = new pc3Shadow(
					this.popup,
					{left:this.design.shadow.marginLeft,top:this.design.shadow.marginTop,right:this.design.shadow.marginRight,bottom:this.design.shadow.marginBottom},
					this.design.shadowImages,
					this.design.shadow.cornerSize,
					this.design.shadow.color,
					this.design.shadow.opacity,
					this.design.shadow.blurRadius,
					(this.settings.origin.setting != 'atEndPosition' || this.settings.closed.setting != 'atEndPosition' || this.design.open.animationSize != '' || this.design.close.animationSize != '' ),
					(this.design.open.effect == 'fadeIn' || this.design.close.effect == 'fadeOut' )
				);
			}
		}
		
		if ( this.design.ajaxContentId ){
			var ajaxContent = pc3Widget.findElementById(this.content, this.design.ajaxContentId);

			if ( ajaxContent && this.popupData.get('ajaxContentId') && window.pc3AjaxContentObjects && window.pc3AjaxContentObjects[this.design.ajaxContentId] && this.popupData.get('ajaxLink') ){
				this.ajaxRequest = new pc3PopupAjaxRequest(this.design.ajaxContentId, this.popupData.get('ajaxContentId'), this.popupData.get('ajaxLink'), ajaxContent, {width:parseInt(this.popupData.get('ajaxContentCustomWidth')),height:parseInt(this.popupData.get('ajaxContentCustomHeight'))});
				var duration = (this.design.open.duration?parseFloat(this.design.open.duration):0) + (this.openTriggerDelay?parseFloat(this.openTriggerDelay):0);
				this.ajaxRequest.open(duration);
			}
		}
		var dimension = pc3Widget.getElementDimension(this.content);
		this.openedPosition.width = (dimension.width>0?dimension.width:1);
		this.openedPosition.height = (dimension.height>0?dimension.height:1);
		this.openedPosition.factorWidth = 10000;
		this.openedPosition.factorHeight = 10000;
		if ( typeof( this.design.background ) != "undefined" && this.design.background.enabled ) this.background = pc3Widget.addBackground(this.parent.popup, this.design.background.color, this.design.background.opacity);
		if ( this.background ) this.background.open(this.design.background.openDelay, this.design.background.openEffect, this.design.background.openDuration);
		
		this.parent.closeOtherOpenPopups(this);
		this.trigger[this.id] = 'opened';
		
		if ( this.openTriggerDelay > 0 && (event || delay) ) this.waitingToOpen = this.openPopup.bind(this).delay(this.openTriggerDelay);
		else this.openPopup();
	}

	
	this.openPopup = function(){

		window.clearTimeout(this.waitingToOpen);
		this.waitingToOpen = '';
		this.state = 'opening';
		this.parent.addOpenPopup(this);

		this.setZIndex(this.management.getZIndex());
		this.setClosedDimension(this.design.open.animationSize, this.settings.origin.element, this.settings.origin.setting);

		if ( this.closedPosition.width != this.openedPosition.width || this.closedPosition.height != this.openedPosition.height ) this.setDimension({value:this.closedPosition});
		else this.setDimension({value:this.openedPosition});

		this.setPositions('opened', this.openedPosition);
		this.setPositions('origin', this.closedPosition);
		if ( this.closedPosition.x != this.openedPosition.x || this.closedPosition.y != this.openedPosition.y ) this.setPosition({value:this.closedPosition});
		else this.setPosition({value:this.openedPosition})

		this.boundingBox = this.getBoundingBox(this.design.open.animationType);	

		var duration = (this.design.open.duration?parseFloat(this.design.open.duration)*1000:0);
		
		// fadeIn
		if ( this.design.open.effect == 'fadeIn' ){
			this.setOpacity({value:0});
			this.effects.set('opacity', new pc3Tween('opacity', 0, 100, (duration*0.8).round(), 'EaseInQuad', this.setOpacity.bind(self), this.removeEffect.bind(self)));
		} else {
			this.setOpacity({value:100});
		}
		
		// pathAnimation
		var pathAnimationTransition = '';
		if ( this.closedPosition.x != this.openedPosition.x || this.closedPosition.y != this.openedPosition.y ){
			pathAnimationTransition = this.getPathAnimationTransition(this.design.open.animation, 'open');
			this.effects.set('path', new pc3PopupPathAnimation('path', this.getPath(this.design.open.animationPath, 'open'), 'open', (duration*1).round(), pathAnimationTransition, this.setPosition.bind(self), this.removeEffect.bind(self)));
		}
		
		// sizeAnimation
		if ( this.closedPosition.width != this.openedPosition.width || this.closedPosition.height != this.openedPosition.height ){
			this.effects.set('size', new pc3PopupSizeAnimation('size', 0, 10000, 'open', this.design.open.animationSize, pathAnimationTransition, duration, this.setDimension.bind(self), this.removeEffect.bind(self)));
		}
		
		this.outerBox.show();
		pc3Widget.updateScrollers();
		this.animate();
	}
	
	this.close = function(event){
		if ( !this.popup ) return;
		if ( this.waitingForClose ) return;
		if ( event && event.type == 'mouseout' ){
			event.stop();
			if ( this.mouseIsInside(event) ) return;
			this.parent.close(event);
		}
		if ( this.waitingToOpen ) {
			window.clearTimeout(this.waitingToOpen);		
			this.waitingToOpen = '';
			return;
		}
		if ( this.state == 'opening' ){
			this.closeAfterOpen = this.close.bind(this);
			return;
		}
		if ( this.state == 'closed' || this.state == 'closing' ) return;

		this.trigger[this.id] = 'closed';
		if ( this.background ) this.background.close(this.design.background.closeDelay, this.design.background.closeEffect, this.design.background.closeDuration);
		this.background = '';
		this.state = 'closing';

		if ( this.closeTriggerDelay > 0 && event ) this.waitingForClose = this.closeChildPopups.bind(this).delay(this.closeTriggerDelay);
		else this.closeChildPopups();
	
	}

	this.closeChildPopups = function(){
		window.clearTimeout(this.waitingForClose);
		this.waitingForClose = '';
		this.doForAllOpenPopups(function(){ this.close(''); });
		this.waitForChildsToClose();
	}

	this.waitForChildsToClose = function(){
		if ( this.openPopups.size() ){
			this.doForAllOpenPopups(function(){ this.close(''); });
			this.waitForChildsToClose.bind(this).delay(0.02);
		} else {
			this.closePopup();
		}
	}
	
	this.closePopup = function(){
		this.setClosedDimension(this.design.close.animationSize, this.settings.closed.element, this.settings.closed.setting);
		
		this.openedPosition.x = this.currentPosition.x;
		this.openedPosition.y = this.currentPosition.y;
		
		this.setPositions('closed', this.closedPosition);
		this.boundingBox = this.getBoundingBox(this.design.close.animationType);	
				
		var duration = (this.design.close.duration?parseFloat(this.design.close.duration)*1000:0);
		
		// fadeOut
		if ( this.design.close.effect == 'fadeOut' ){
			this.effects.set('opacity', new pc3Tween('opacity', 100, 0, (duration*1.1).round(), 'EaseOutQuad', this.setOpacity.bind(self), this.removeEffect.bind(self)));
		}
		
		// pathAnimation
		var pathAnimationTransition = '';
		if ( this.closedPosition.x != this.openedPosition.x || this.closedPosition.y != this.openedPosition.y ){
			pathAnimationTransition = this.getPathAnimationTransition(this.design.close.animation, 'close');
			this.effects.set('path', new pc3PopupPathAnimation('path', this.getPath(this.design.open.animationPath, 'close'), 'close', duration, pathAnimationTransition, this.setPosition.bind(self), this.removeEffect.bind(self)));
		}
		
		// sizeAnimation
		if ( this.closedPosition.width != this.openedPosition.width || this.closedPosition.height != this.openedPosition.height ){
			this.effects.set('size', new pc3PopupSizeAnimation('size', 1000, 0, 'close', this.design.close.animationSize, pathAnimationTransition, duration, this.setDimension.bind(self), this.removeEffect.bind(self)));
		}
		
		this.animate();
	}

	this.handleClick = function(event){
		if (!this.design.close.trigger) return;
		if ( this.design.close.trigger.indexOf('clickOutsidePopup') >= 0 && !this.mouseIsInside(event)){
			this.trigger[this.id] = 'closed';
			this.close('');
		}
		this.doForAllOpenPopups(function(){ this.handleClick(event)});
	}


	this.handleClickOnTrigger = function(event){
		if ( this.design.close.trigger && this.design.close.trigger.indexOf('clickOnTrigger') >= 0 ){
			if ( this.trigger[this.id] == 'opened' ){
				this.close(event);
			} else {
				this.open(event);
			}
		} else {
			this.open(event);
		}
	}

	this.handleMouseMove = function(){
		if ( this.design.behaviour == 'attachedToMouse' ){
			position = this.getPositionAt(this.currentPosition, this.settings.opened.margins, '');
			this.positionPopup(position);
		}
		this.doForAllOpenPopups(function(){ this.handleMouseMove()});
	}

	this.handleResize = function(){
		if ( this.design.behaviour == 'attachedToScreen' ){
			this.setPositions('opened', this.openedPosition);
			this.setCurrentPosition(this.openedPosition);
			this.boundingBox = this.getBoundingBox(this.design.open.animationType);
			this.positionPopup(this.openedPosition);
		}
		this.doForAllOpenPopups(function(){ this.handleResize()});
	}

	this.handleScroll = function(){
		if ( this.design.behaviour == 'attachedToScreen' ){
			this.setPositions('opened', this.openedPosition);
			this.setCurrentPosition(this.openedPosition);
			this.boundingBox = this.getBoundingBox(this.design.open.animationType);
			this.positionPopup(this.openedPosition);
		}
		this.doForAllOpenPopups(function(){ this.handleScroll()});
	}

	this.update = function(){
		var dimension = pc3Widget.getElementDimension(this.content);
		this.openedPosition.width = dimension.width;
		this.openedPosition.height = dimension.height;
		if ( this.state != 'opened' ) return;
		this.setPositions('opened', this.openedPosition);
		this.setDimension({value:this.openedPosition});
		this.setCurrentPosition(this.openedPosition);
		this.boundingBox = this.getBoundingBox(this.design.open.animationType);
		this.positionPopup(this.openedPosition);
	}

	this.setCurrentPosition = function(values){
		this.currentPosition.x = values.x;
		this.currentPosition.y = values.y;
	}
	
	
	this.mouseIsInside = function(event){
		var pointerX = event.pointerX();
		var pointerY = event.pointerY();
		if ( Prototype.Browser.IE ){
			pointerX = pointerX - 2;
			pointerY = pointerY - 2;
		}
		var position = this.trigger.cumulativeOffset();
		var triggerArea = {left:position.left,top:position.top,right:(position.left + this.trigger.getWidth()),bottom:(position.top + this.trigger.getHeight())};
		if ( (pointerX >= triggerArea.left && pointerX < triggerArea.right) && (pointerY >= triggerArea.top && pointerY < triggerArea.bottom) ) return true;
		if ( this.design.behaviour == 'attachedToMouse' ) return false;
		position = this.popup.cumulativeOffset();
		var popupArea = {left:position.left,top:position.top,right:(position.left + this.popup.getWidth()),bottom:(position.top + this.popup.getHeight())};
		if ( (pointerX >= popupArea.left && pointerX < popupArea.right) && (pointerY >= popupArea.top && pointerY < popupArea.bottom) ) return true;

		if ( this.design.close.trigger.indexOf('mouseout') >= 0 ){
			var connectingArea = {};
			if ( triggerArea.left > popupArea.left ){
				if ( popupArea.right > triggerArea.left ){
					connectingArea['left'] = triggerArea.left;
					connectingArea['right'] = popupArea.right;
				} else {
					connectingArea['left'] = popupArea.right;
					connectingArea['right'] = triggerArea.left;
				}
			} else {
				if ( triggerArea.right > popupArea.left ){
					connectingArea['left'] = popupArea.left;
					connectingArea['right'] = triggerArea.right;
				} else {
					connectingArea['left'] = triggerArea.right;
					connectingArea['right'] = popupArea.left;
				}
			}
			if ( triggerArea.top > popupArea.top ){
				if ( popupArea.bottom > triggerArea.top ){
					connectingArea['top'] = triggerArea.top;
					connectingArea['bottom'] = popupArea.bottom;
				} else {
					connectingArea['top'] = popupArea.bottom;
					connectingArea['bottom'] = triggerArea.top;
				}
			} else {
				if ( triggerArea.bottom > popupArea.top ){
					connectingArea['top'] = popupArea.top;
					connectingArea['bottom'] = triggerArea.bottom;
				} else {
					connectingArea['top'] = triggerArea.bottom;
					connectingArea['bottom'] = popupArea.top;
				}
			}
	
			if ( (pointerX >= connectingArea.left && pointerX < connectingArea.right) && (pointerY >= connectingArea.top && pointerY < connectingArea.bottom) ) return true;
		}

		if ( this.settings.opened.setting != 'triggerElement' ) return false;
		
		var mouseIsInside = false;
		this.openPopups.each(function(currentPopup){ if ( currentPopup.value.mouseIsInside(event) ) mouseIsInside = true; });		
		return mouseIsInside;
	}

	this.setClosedDimension = function(sizeAnimation, offsetElement, elementSetting){
		switch( sizeAnimation ){
			case 'zoomIn':
			case 'zoomOut':
			case 'bubble':
			case 'growBoth':
			case 'shrinkBoth':
				if ( (elementSetting == 'triggerElement' || elementSetting == 'customElement') && offsetElement ){
					this.closedPosition.width = offsetElement.getWidth() - this.popup.outerDimension.offsetsX;
					this.closedPosition.height = offsetElement.getHeight() - this.popup.outerDimension.offsetsY;
				} else {
					this.closedPosition.width = (this.popup.outerDimension.offsetsX?0:3);
					this.closedPosition.height = (this.popup.outerDimension.offsetsY?0:3);
				}
				break;
				
			case 'growHorizontal':
			case 'shrinkHorizontal':
				this.closedPosition.width = (this.popup.outerDimension.offsetsX?0:1);
				this.closedPosition.height = this.openedPosition.height;
				break;
				
			case 'growVertical':
			case 'shrinkVertical':
				this.closedPosition.width = this.openedPosition.width;
				this.closedPosition.height = (this.popup.outerDimension.offsetsY?0:1);
				break;
				
			default:
				this.closedPosition.width = this.openedPosition.width;
				this.closedPosition.height = this.openedPosition.height;
				break;
		}
		this.closedPosition.factorWidth = 0;
		this.closedPosition.factorHeight = 0;
	}

	this.setPositions = function(state, dimensions){
		var newPosition = $H({x:0,y:0,marginLeft:0,marginTop:0,marginRight:0,marginBottom:0});
		
		var offsetElement = this.settings[state].element;
		var elementSetting = this.settings[state].setting;
		var positionSetting = this.settings[state].position;
		var margins = this.settings[state].margins;
		if ( elementSetting == 'atEndPosition' ){
			newPosition.each(function(pair){ newPosition.set(pair.key, self.openedPosition[pair.key]) });
		} else if ( elementSetting == 'atMouse' || !offsetElement ){
			var position = self.getPositionAt(dimensions, margins, '');
			newPosition.each(function(pair){ newPosition.set(pair.key, position[pair.key]) });			
		} else if ( positionSetting == 'atElement' ){
			var boxDimension = { left:offsetElement.cumulativeOffset().left, top:offsetElement.cumulativeOffset().top, width:offsetElement.getWidth(), height:offsetElement.getHeight() };
			var position = self.getPositionAt(dimensions, margins, boxDimension);
			newPosition.each(function(pair){ newPosition.set(pair.key, position[pair.key]) });
		} else {
			var offsetLeft = document.viewport.getScrollOffsets().left;
			var offsetTop = document.viewport.getScrollOffsets().top;
			var screenWidth = document.viewport.getWidth();
			var screenHeight = document.viewport.getHeight();
			
			if ( offsetElement != pc3Widget.body ){
				if ( !this.positionIsRelative() ){
					offsetLeft = offsetElement.cumulativeOffset().left;
					offsetTop = offsetElement.cumulativeOffset().top;
					screenWidth = offsetElement.getWidth();
					screenHeight = offsetElement.getHeight();
				} else {
					if ( offsetElement != this.parent.popup ){
						offsetLeft = offsetElement.cumulativeOffset().left - this.parent.popup.cumulativeOffset().left;
						offsetTop = offsetElement.cumulativeOffset().top - this.parent.popup.cumulativeOffset().top;
						screenWidth = offsetElement.getWidth();
						screenHeight = offsetElement.getHeight();
					} else {
						offsetLeft = 0;
						offsetTop = 0;
						screenWidth = offsetElement.getWidth();
						screenHeight = offsetElement.getHeight();
					}
				}
			}
			
			
			
			var halfWidth = (dimensions.width / 2).round();
			var halfHeight = (dimensions.height / 2).round();
			switch( positionSetting ){
				case 'leftTopOutside':
				case 'leftCenterOutside':
				case 'leftBottomOutside':
					newPosition.set('marginLeft', 0);
					newPosition.set('marginRight', margins.x);
					newPosition.set('x', offsetLeft - halfWidth - this.popup.outerDimension.offsetRight - newPosition.get('marginRight'));
					break;

				case 'topLeftOutside':
				case 'topLeftInside':
				case 'leftTopInside':
				case 'leftCenterInside':
				case 'leftBottomInside':
				case 'bottomLeftInside':
				case 'bottomLeftOutside':
					newPosition.set('marginLeft', margins.x);
					newPosition.set('marginRight', 0);
					newPosition.set('x', offsetLeft + halfWidth + this.popup.outerDimension.offsetLeft + newPosition.get('marginLeft'));
					break;

				case 'centerCenter':
				case 'topCenterInside':
				case 'bottomCenterInside':
				case 'topCenterOutside':
				case 'bottomCenterOutside':
					newPosition.set('marginLeft', 0);
					newPosition.set('marginRight', 0);
					newPosition.set('x', (offsetLeft + (screenWidth / 2)).round());
					break;

				case 'topRightOutside':
				case 'topRightInside':
				case 'rightTopInside':
				case 'rightCenterInside':
				case 'rightBottomInside':
				case 'bottomRightInside':
				case 'bottomRightOutside':
					newPosition.set('marginLeft', 0);
					newPosition.set('marginRight', margins.x);
					newPosition.set('x', offsetLeft + screenWidth - halfWidth - this.popup.outerDimension.offsetRight - newPosition.get('marginRight'));
					break;
					
				case 'rightTopOutside':
				case 'rightCenterOutside':
				case 'rightBottomOutside':
					newPosition.set('marginLeft', margins.x);
					newPosition.set('marginRight', 0);
					newPosition.set('x', offsetLeft + screenWidth + halfWidth + this.popup.outerDimension.offsetLeft + newPosition.get('marginLeft'));
					break;
			}


			switch( positionSetting ){
				case 'topLeftOutside':
				case 'topCenterOutside':
				case 'topRightOutside':
					newPosition.set('marginTop', 0);
					newPosition.set('marginBottom', margins.y);
					newPosition.set('y', offsetTop - halfHeight - this.popup.outerDimension.offsetTop - newPosition.get('marginBottom'));
					break;

				case 'leftTopOutside':
				case 'leftTopInside':
				case 'topLeftInside':
				case 'topCenterInside':
				case 'topRightInside':
				case 'rightTopInside':
				case 'rightTopOutside':
					newPosition.set('marginTop', margins.y);
					newPosition.set('marginBottom', 0);
					newPosition.set('y', offsetTop + halfHeight + this.popup.outerDimension.offsetTop + newPosition.get('marginTop'));
					break;

				case 'leftCenterOutside':
				case 'leftCenterInside':
				case 'centerCenter':
				case 'rightCenterInside':
				case 'rightCenterOutside':
					newPosition.set('marginTop', 0);
					newPosition.set('marginBottom', 0);
					newPosition.set('y', (offsetTop + (screenHeight / 2)).round());
					break;

				case 'leftBottomOutside':
				case 'leftBottomInside':
				case 'bottomLeftInside':
				case 'bottomCenterInside':
				case 'bottomRightInside':
				case 'rightBottomInside':
				case 'rightBottomOutside':
					newPosition.set('marginTop', 0);
					newPosition.set('marginBottom', margins.y);
					newPosition.set('y', offsetTop + screenHeight - halfHeight - this.popup.outerDimension.offsetBottom - newPosition.get('marginBottom'));
					break;

				case 'bottomLeftOutside':
				case 'bottomCenterOutside':
				case 'bottomRightOutside':
					newPosition.set('marginTop', margins.y);
					newPosition.set('marginBottom', 0);
					newPosition.set('y', offsetTop + screenHeight + halfHeight + this.popup.outerDimension.offsetTop + newPosition.get('marginTop'));
					break;
			}
		}
		if ( state == 'opened' ) newPosition.each(function(pair){ self.openedPosition[pair.key] = pair.value });			
		else newPosition.each(function(pair){ self.closedPosition[pair.key] = pair.value });
		//console.log('setPositions '+(offsetElement?offsetElement.identify():'noOffsetElement')+" "+elementSetting+" "+positionSetting+" {"+dimensions.x+","+dimensions.y+"} {"+dimensions.width+","+dimensions.height+"} {"+margins.x+","+margins.y+"} "+state);
	}

	this.getPath = function(type, direction){
		var x = 0;
		var y = 0;
		var startX = (direction=='open'?this.closedPosition.x:this.openedPosition.x);
		var endX = (direction=='open'?this.openedPosition.x:this.closedPosition.x);
		var startY = (direction=='open'?this.closedPosition.y:this.openedPosition.y);
		var endY = (direction=='open'?this.openedPosition.y:this.closedPosition.y);
		
		switch( type ){
			case 'straight':
				x = (startX + ((endX - startX) / 2)).round();
				y = (startY + ((endY - startY) / 2)).round();
				break;
			
			case 'swish':
				if ( startX < endX ) x = (startX + ((((endX - startX) / 3)) * 2)).round();
				else x = (startX - ((((startX - endX) / 3)) * 2)).round();
				if ( startY < endY ) y = (endY + (((endY - startY) / 4) * 3)).round();
				else y = (endY - (((startY - endY) / 4) * 3)).round();
				break;
			
			case 'swishStrong':
				if ( startX < endX ) x = (startX + ((((endX - startX) / 2)) * 1)).round();
				else x = (startX - ((((startX - endX) / 2)) * 1)).round();
				if ( startY < endY ) y = (endY + ((endY - startY) * 2)).round();
				else y = (endY - ((startY - endY) * 2)).round();
				break;
		}

		return { start:{ x:startX, y:startY }, middle:{ x:x, y:y }, end:{ x:endX, y:endY } };
	}

	this.getPathAnimationTransition = function(type, direction){
		switch( type ){
			case 'easeOut':
				return 'EaseOutQuad';
				
			case 'easeIn':
				return 'EaseInQuad';

			case 'drop':
				if ( direction == 'open' ) return 'EaseOutBounce';
				return 'EaseOutBounce';
				
			case 'elastic':
				if ( direction == 'open' ) return 'EaseOutElastic';
				return 'EaseInElastic';
		}
		
		return 'EaseNone';
	}				

	this.setZIndex = function(zIndex){
		this.outerBox.setStyle({zIndex:zIndex});
	}
	
	this.setOpacity = function(effect){
		this.currentPosition.opacity = effect.value;
		this.innerBox.setOpacity(this.currentPosition.opacity/100);
	}

	this.setPosition = function(effect){
		this.currentPosition.x = (effect.value.x).round();
		this.currentPosition.y = (effect.value.y).round();
	}

	this.setDimension = function(effect){
		this.currentPosition.width = (((this.openedPosition.width - this.closedPosition.width) * effect.value.factorWidth) / this.openedPosition.factorWidth).round() + this.closedPosition.width;
		this.currentPosition.height = (((this.openedPosition.height - this.closedPosition.height) * effect.value.factorHeight) / this.openedPosition.factorHeight).round() + this.closedPosition.height;
	}

	this.positionIsRelative = function(){
		if ( this.design.positionChilds == 'absolute' || (this.design.positionChilds != 'absolute' && this.parent == this.management) ) return false;
		return true;
	}
	
	this.removeEffect = function(effect){ this.effects.unset(effect.name); }

	this.getBoundingBox = function(type){
		var outerBoundingBox = pc3Widget.getDocumentDimension();
		
		var offsetElement = this.settings.opened.element;
		var positionSetting = this.settings.opened.position;

		if (type == 'visible' || !offsetElement || positionSetting == 'atElement' ) return outerBoundingBox;
		
		var left = outerBoundingBox.left;
		var top = outerBoundingBox.top;
		var right = outerBoundingBox.right;
		var bottom = outerBoundingBox.bottom;
		
		if ( positionSetting.endsWith('Inside') || positionSetting == 'centerCenter' || positionSetting == 'atMouse' ){
		
			if ( this.design.positionChilds == 'absolute' || (this.design.positionChilds != 'absolute' && this.parent == this.management) ){
				if ( offsetElement != pc3Widget.body ){
					left = offsetElement.cumulativeOffset().left;
					top = offsetElement.cumulativeOffset().top;
					right = left + offsetElement.getWidth();
					bottom = top + offsetElement.getHeight();
				}
			} else {
				left = offsetElement.cumulativeOffset().left - this.parent.popup.cumulativeOffset().left;
				top = offsetElement.cumulativeOffset().top - this.parent.popup.cumulativeOffset().top;
				right = left + offsetElement.getWidth();
				bottom = top + offsetElement.getHeight();
			}

		} else {
			if ( positionSetting.startsWith('left') ){
				if ( this.positionIsRelative() ) right = offsetElement.cumulativeOffset().left - this.parent.popup.cumulativeOffset().left;
				else right = offsetElement.cumulativeOffset().left;
			} else if ( positionSetting.startsWith('right') ){
				if ( this.positionIsRelative() ) left = offsetElement.cumulativeOffset().left - this.parent.popup.cumulativeOffset().left + offsetElement.getWidth();
				else left = offsetElement.cumulativeOffset().left + offsetElement.getWidth();
			}
			if ( positionSetting.startsWith('top') ){
				if ( this.positionIsRelative() ) bottom = offsetElement.cumulativeOffset().top - this.parent.popup.cumulativeOffset().top;
				bottom = offsetElement.cumulativeOffset().top;
			} else if ( positionSetting.startsWith('bottom') ){
				if ( this.positionIsRelative() ) top = offsetElement.cumulativeOffset().top - this.parent.popup.cumulativeOffset().top + offsetElement.getHeight();
				top = offsetElement.cumulativeOffset().top + offsetElement.getHeight();
			}
		}
		return {left:left,top:top,right:right,bottom:bottom};
	}

	this.fitToBoundingBox = function(contentDimension, boundingBox){
		var offsetX = 0;
		var left = contentDimension.left;
		var width = contentDimension.width;
		if ( left < boundingBox.left ){
			offsetX = left - boundingBox.left;
			if ( (left + width) < boundingBox.left ){
				width = 0;
			} else {
				width = width + offsetX;
			}
			left = boundingBox.left;
		}
		
		if ( left + width > boundingBox.right ){
			if ( left > boundingBox.right ){
				left = boundingBox.right;
				width = 0;
			} else {
				width = boundingBox.right - left;
			}
		}

		var offsetY = 0;
		var top = contentDimension.top;
		var height = contentDimension.height;

		if ( top < boundingBox.top ){
			offsetY = top - boundingBox.top;
			if ( (top + height) < boundingBox.top ){
				height = 0;
			} else {
				height = height + offsetY;
			}
			top = boundingBox.top;
		}
		if ( top + height > boundingBox.bottom ){
			if ( top > boundingBox.bottom ){
				top = boundingBox.bottom;
				height = 0;
			} else {
				height = boundingBox.bottom - top;
			}
		}
		return {left:(left).round(), top:(top).round(), width:(width).round(), height:(height).round(), offsetX:(offsetX).round(), offsetY:(offsetY).round()};
	}

	this.getPositionAt = function(dimension, margins, box){
		if ( !box ) {
			box = {
				left:(pc3Widget.mousePosition.x?pc3Widget.mousePosition.x:0),
				top:(pc3Widget.mousePosition.y?pc3Widget.mousePosition.y:0),
				width:0,
				height:0
			}
		}
		
		if ( this.positionIsRelative() ){
			var offsetLeft = this.parent.popup.cumulativeOffset().left;
			var offsetTop = this.parent.popup.cumulativeOffset().top;
			var screenWidth = this.parent.popup.getWidth();
			var screenHeight = this.parent.popup.getHeight();
		} else {
			var offsetLeft = document.viewport.getScrollOffsets().left;
			var offsetTop = document.viewport.getScrollOffsets().top;
			var screenWidth = document.viewport.getWidth();
			var screenHeight = document.viewport.getHeight();
		}

		var shadowOffsets = this.getShadowOffsets(dimension);

		var width = dimension.width;
		var height = dimension.height;
		
		var position = {x:0, y:0, marginLeft:0, marginTop:0, marginRight:0, marginBottom:0};

		position.marginLeft = margins.x;

		position.x = ((box.left + box.width) + position.marginLeft + this.popup.outerDimension.offsetLeft + shadowOffsets.offsetLeft + (width/2)).ceil();
		var correction = (position.x + (width/2).ceil() + this.popup.outerDimension.offsetRight + shadowOffsets.offsetRight + 10) - (screenWidth + offsetLeft);
		if ( correction > 0 ) position.x = position.x - correction;
		
		if ( position.x - (position.marginLeft + this.popup.outerDimension.offsetLeft + shadowOffsets.offsetLeft + (width/2)).ceil() < offsetLeft ){
			position.x = (offsetLeft + position.marginLeft + this.popup.outerDimension.offsetLeft + shadowOffsets.offsetLeft + (width/2)).ceil();
		}

		position.marginTop = margins.y;
		position.y = ((box.top + box.height) + position.marginTop + this.popup.outerDimension.offsetTop + shadowOffsets.offsetTop + (height/2)).ceil();
		correction = (position.y + (height/2).ceil() + this.popup.outerDimension.offsetBottom + 2) - (screenHeight + offsetTop);
		if ( correction > 0 && box.top - offsetTop >= height + this.popup.outerDimension.offsetsY + shadowOffsets.offsetTop + shadowOffsets.offsetBottom){
			position.marginTop = 0;
			position.marginBottom = margins.y;
			position.y = (box.top - position.marginBottom - this.popup.outerDimension.offsetBottom - shadowOffsets.offsetBottom - (height/2)).ceil();
		}
		
		if ( this.positionIsRelative() ){
			position.x = position.x - this.parent.cumulativeOffset().left;
			position.y = position.y - this.parent.cumulativeOffset().top;
		}
		return position;
		
	}	


	this.animate = function(){
		var position = this.currentPosition;
		if ( this.design.behaviour == 'attachedToMouse' ) position = this.getPositionAt(this.currentPosition, this.settings.opened.margins, '');
		this.positionPopup(position);

		if ( this.effects.size() ){
			this.animate.bind(this).delay(0.02)
		} else {
			if ( this.state == 'closing' ){
				this.state = 'closed';
				if ( this.ajaxRequest ) this.removeAjaxPopups();
				this.parent.removeOpenPopup(this);
				this.outerBox.hide();
			} else {
				this.state = 'opened';
				this.doForAllPopups( function(){ this.openInitially(); });
			}
			if ( this.closeAfterOpen ){
				var closeAfterOpen = this.closeAfterOpen;
				this.closeAfterOpen = '';
				closeAfterOpen();
			}
			if ( this.openAfterClose ){
				var openAfterClose = this.openAfterClose;
				this.openAfterClose = '';
				openAfterClose();
			}
		}
	}

	this.positionPopup = function(position){
		var endLeft = (position.x - (this.openedPosition.width/2)).round();
		var left = endLeft + ((this.openedPosition.width - this.currentPosition.width)/2).round();

		var endTop = (position.y - (this.openedPosition.height/2)).round();
		var top = endTop + ((this.openedPosition.height - this.currentPosition.height)/2).round();

		var shadowOffsets = this.getShadowOffsets(this.currentPosition);
		
		var popupOffsetLeft = shadowOffsets.offsetLeft;
		var popupOffsetTop = shadowOffsets.offsetTop;

		var innerBoxDimension = {};

		innerBoxDimension['left'] = left - this.popup.outerDimension.offsetLeft - popupOffsetLeft;
		innerBoxDimension['top'] = top - this.popup.outerDimension.offsetTop - popupOffsetTop;
		innerBoxDimension['width'] = this.currentPosition.width + (left - innerBoxDimension.left) + this.popup.outerDimension.offsetRight + shadowOffsets.offsetRight;
		innerBoxDimension['height'] = this.currentPosition.height + (top - innerBoxDimension.top) + this.popup.outerDimension.offsetBottom + shadowOffsets.offsetBottom;

		var boxDimension = this.fitToBoundingBox(innerBoxDimension, this.boundingBox);
		
		

		this.outerBox.setStyle({
			left:boxDimension.left +'px',
			top:boxDimension.top +'px',
			width:boxDimension.width +'px',
			height:boxDimension.height +'px'
		});

		if ( boxDimension.offsetX != 0) popupOffsetLeft = popupOffsetLeft + boxDimension.offsetX;
		if ( boxDimension.offsetY != 0) popupOffsetTop = popupOffsetTop + boxDimension.offsetY;

		this.innerBox.setStyle({
			left:popupOffsetLeft +'px',
			top:popupOffsetTop +'px',
			width:innerBoxDimension.width +'px',
			height:innerBoxDimension.height +'px'
		});


		if ( (this.lastSize && this.lastSize.width != this.currentPosition.width) || (this.lastSize && this.lastSize.height != this.currentPosition.height) ){
			this.popup.setStyle({
				left:'0px',
				top:'0px',
				width:this.currentPosition.width +'px',
				height:this.currentPosition.height +'px'
			});
	
			this.contentBox.setStyle({
				left:this.popup.outerDimension.offsetLeft +'px',
				top:this.popup.outerDimension.offsetTop +'px',
				width:this.currentPosition.width +'px',
				height:this.currentPosition.height +'px'
			});
	
			this.content.setStyle({
				left:-(left - endLeft) +'px',
				top:-(top - endTop) +'px',
				width:this.openedPosition.width +'px',
				height:this.openedPosition.height +'px'
			});
	
			if ( this.eventLayer ){
				this.eventLayer.setStyle({
					left:shadowOffsets.offsetLeft +'px',
					top:shadowOffsets.offsetTop +'px',
					width:(this.currentPosition.width + shadowOffsets.offsetsX) +'px',
					height:(this.currentPosition.height + shadowOffsets.offsetsY) +'px'
				});
			}
			
			if ( this.shadow ){
				this.shadow.setZoomFactor(this.getShadowFactor(this.currentPosition));
				this.shadow.show();
			}
		}


		this.lastSize.width = this.currentPosition.width;
		this.lastSize.height = this.currentPosition.height;

	}

	this.getShadowFactor = function(position){
		if ( this.openedPosition.width < 1 || this.openedPosition.height < 1 ) return 0;
		var shadowFactor = position.width / this.openedPosition.width;
		if ( shadowFactor > position.height / this.openedPosition.height ) shadowFactor = position.height / this.openedPosition.height;
		return (shadowFactor * 100);
	}	
	
	this.getShadowOffsets = function(position){
		if ( this.shadowOffsets && (this.lastSize && this.lastSize.width == position.width) || (this.lastSize && this.lastSize.height == position.height) ) return this.shadowOffsets;
		if ( this.shadow ){
			this.shadow.setZoomFactor(this.getShadowFactor(position));
			this.shadowOffsets = this.shadow.getOuterDimension();
			['Left','Top','Right','Bottom'].each(function(location){ if ( self.shadowOffsets['offset'+location] < 0 ) self.shadowOffsets['offset'+location] = 0;});
		}
		return this.shadowOffsets;
	}
	
	this.addOpenPopup = function(popup){
		if ( !this.openPopups.size() && Prototype.Browser.IE6 ) {
			this.selects.each(function(select){
				if ( select.visible() ){
					self.hiddenSelects.push(select);
					select.style.visibility = "hidden";
				}
			});
		}
		this.openPopups.set(popup.id, popup);
	}

	this.removeOpenPopup = function(popup){
		this.openPopups.unset(popup.id);
		if ( !this.openPopups.size() && Prototype.Browser.IE6 ) {
			this.hiddenSelects.each(function(select){ select.style.visibility = "visible"; });
			this.hiddenSelects = new Array();
		}
	}


	this.removePopup = function(popupId){
		this.popups.unset(popupId);
		this.parent.removePopup(popupId);
	}

	this.closeOtherOpenPopups = function(popup){
		if ( popup.groupname == 'pc3DefaultPopupGroup' ) return;
		this.openPopups.each(function(currentPopup){ if ( popup.id != currentPopup.key && popup.groupname == currentPopup.value.groupname ) currentPopup.value.close(''); });		
	}

	this.removeChildPopups = function(){
		this.popups.each(function(currentPopup){
			if ( currentPopup.value.outerBox ) currentPopup.value.outerBox.remove();
			currentPopup.value.parent.removePopup(currentPopup.value.id);
			delete currentPopup;
		});
	}
	
	this.removeAjaxPopups = function(){
		this.ajaxRequest.resetAjaxContent();
		this.management.removeAjaxPopups(this.ajaxRequest.getAjaxContent());
	}

	this.doForAllOpenPopups = function(func){ this.openPopups.each(function(currentPopup){ func.bind(currentPopup.value)(); }); }

	this.doForAllPopups = function(func){ this.popups.each(function(currentPopup){ func.bind(currentPopup.value)(); }); }

	this.addPopup = function(popup){ this.popups.set(popup.id, popup); }

	this.isOpen = function(){ return (this.state == 'opened'); }
	
	this.init();
}



function pc3PopupSizeAnimation(name, startDimension, endDimension, direction, type, pathAnimationTransition, duration, onUpdate, onComplete){
	var self = this;
	this.name = name;
	this.direction = direction;
	
	this.onUpdateFunction = onUpdate;
	this.onCompleteFunction = onComplete;
	
	this.start = {
		factorWidth:startDimension,
		factorHeight:startDimension
	};
	
	this.end = {
		factorWidth:endDimension,
		factorHeight:endDimension
	};

	this.value = $H({
		factorWidth:startDimension,
		factorHeight:startDimension
	});
		
	this.onUpdate = function(effect){
		var factor = effect.value/10000;
		if ( effect.name == 'both' || effect.name == 'width' ) this.value.factorWidth = this.start.factorWidth + ((this.end.factorWidth - this.start.factorWidth) * factor);
 		if ( effect.name == 'both' || effect.name == 'height' ) this.value.factorHeight = this.start.factorHeight + ((this.end.factorHeight - this.start.factorHeight) * factor);
		this.onUpdateFunction(this);
	}

	this.extendEffect = function(name, start, end, duration, transition, onUpdate, onComplete, effect ){
		var nextEffect = new pc3Tween(name, start, end, duration, transition, onUpdate, onComplete);
		delete effect;
	};
	
	this.onComplete = function(effect){
		delete effect;
		this.value = this.end;
		this.onUpdateFunction(this);
		this.onCompleteFunction(this);
	};
	
	
	this.init = function(duration, type){
		var transition = '';
		switch( type ){
			case 'bubble':
				var effect = new pc3Tween('both', 0, 10000, (duration * 0.5).round(), (direction=='open'?'EaseOutBounce':'EaseOutBounce'), this.onUpdate.bind(self), this.onComplete.bind(self));
				break;

			case 'growBoth':
			case 'shrinkBoth':
				if ( pathAnimationTransition ){
					if ( pathAnimationTransition.startsWith('EaseIn') ) transition = 'EaseInQuad';
					else transition = 'EaseOutQuad';
				} else {
					transition = (direction=='open'?'EaseInQuad':'EaseOutQuad');
				}
				var nextEffect = this.extendEffect.bind(self, 'height', 0, 10000, (duration * 0.5).round(), transition, this.onUpdate.bind(self), this.onComplete.bind(self));
				var effect = new pc3Tween('width', 0, 10000, (duration * 0.5).round(), transition, this.onUpdate.bind(self), nextEffect);
				break;

			default:
				if ( pathAnimationTransition ){
					if ( pathAnimationTransition.startsWith('EaseIn') ) transition = 'EaseInQuad';
					else transition = 'EaseOutQuad';
				} else {
					transition = (direction=='open'?'EaseInQuad':'EaseOutQuad');
				}
				var effect = new pc3Tween('both', 0, 10000, (duration * 1).round(), transition, this.onUpdate.bind(self), this.onComplete.bind(self));
				break;		
		}

	}

	this.init(duration, type);
}

function pc3PopupPathAnimation(name, path, direction, duration, transition, onUpdate, onComplete){
	var self = this;
	this.name = name;
	this.path = path;
	this.onUpdateFunction = onUpdate;
	this.onCompleteFunction = onComplete;
	
	this.value = this.path.start;
	this.end = this.path.end;
	
	this.onUpdate = function(effect){
		this.value = this.getBezierPosition(effect.value, this.path);
		this.onUpdateFunction(this);
	}
	
	this.onComplete = function(effect){
		delete effect;
		this.value = this.end;
		this.onUpdateFunction(this);
		this.onCompleteFunction(this);
	};
	
	this.init = function(duration, transition, direction){
		var effect = new pc3Tween('position', 0.0, 1.0, duration, transition, this.onUpdate.bind(self), this.onComplete.bind(self));
	}

	this.getBezierPosition = function(time, path){
		return this.getIntermedianPosition(time, this.getIntermedianPosition(time, path.start, path.middle), this.getIntermedianPosition(time, path.middle, path.end));
	}
	
	this.getIntermedianPosition = function(time, start, end){
		return { x:start.x + (end.x-start.x)*time, y:start.y + (end.y-start.y)*time };
	}

	this.init(duration, transition, direction);
}

function pc3PopupAjaxRequest(originialId, newId, URL, ajaxContent, dimension){
	var self = this;
	this.url = URL;
	this.ajaxRequest = '';
	this.dimension = dimension;
	this.originialId = originialId;
	
	this.init = function(){
		ajaxContent.id = newId;
		this.ajaxRequest = new pc3AjaxContent('','', window.pc3AjaxContentObjects[originialId].onErrorHTML, '', ajaxContent);
		this.loadContent = window.pc3AjaxContentObjects[originialId].onRequestHTML;
	}
	
	this.getAjaxContent = function(){
		return this.ajaxContent;
	}

	this.resetAjaxContent = function(){
		this.ajaxRequest.replaceDefaultContent('');
		this.ajaxRequest.defaultContent.id = this.originialId;
	}

	this.open = function(delay){
		if ( !this.ajaxRequest ) return;
		this.ajaxRequest.replaceDefaultContent(this.loadContent);
		if ( this.dimension.width ) this.ajaxRequest.defaultContent.down().setStyle({width:this.dimension.width+'px'});
		if ( this.dimension.height ) this.ajaxRequest.defaultContent.down().setStyle({height:this.dimension.height+'px'});
		this.requestContent.bind(this).delay(delay);
	}

	this.requestContent = function(){
		this.ajaxRequest.requestContent(this.url);
	}
		
	this.init();
}