MDVToolTipBubble.prototype.createBubble = function () {
		
	var that = this;
	
	// save iPath as property
	// method 'update' uses this as well
	this.iPath = 'images/';
	if (this.mdvMap.config.get('imagePath')) {
  		this.iPath = this.mdvMap.config.get('imagePath');
	}
	this.iPath += 'tt_bg/';
	
	this.tt = {};
	
	// POINTER TOP
	var tmp = document.createElement('img');
		tmp.src = this.iPath + 'tt_ptl.png';
		tmp.width = 35;
		tmp.height = 26;
		tmp.onload = correctPNG;
	this.tt.ptl = document.createElement('div');
	this.tt.ptl.appendChild(tmp);
	this.div.appendChild(this.tt.ptl);
	
	var tmp = document.createElement('img');
		tmp.src = this.iPath + 'tt_ptr.png';
		tmp.width = 40;
		tmp.height = 27;
		tmp.onload = correctPNG;
	this.tt.ptr = document.createElement('div');
	this.tt.ptr.appendChild(tmp);
	this.div.appendChild(this.tt.ptr);
	
	// TOP 
	var tmp = document.createElement('img');
		tmp.src = this.iPath + 'tt_ctl.png';
		tmp.width = 7;
		tmp.height = 11;
		tmp.onload = correctPNG;
	this.tt.ctl = document.createElement('div');
	this.tt.ctl.appendChild(tmp);
	this.div.appendChild(this.tt.ctl);
	
	var tmp = document.createElement('img');
		tmp.src = this.iPath + 'tt_bgt.png';
		tmp.style.width = '100%';
		tmp.height = 11;
		tmp.onload = correctPNG;
	this.tt.bgt = document.createElement('div');
	this.tt.bgt.appendChild(tmp);
	this.div.appendChild(this.tt.bgt);
	
	var tmp = document.createElement('img');
		tmp.src = this.iPath + 'tt_ctr.png';
		tmp.width = 11;
		tmp.height = 12;
		tmp.onload = correctPNG;
	this.tt.ctr = document.createElement('div');
	this.tt.ctr.appendChild(tmp);
	this.div.appendChild(this.tt.ctr);
	
	// CENTER 
	var tmp = document.createElement('img');
		tmp.src = this.iPath + 'tt_bgl.png';
		tmp.width = 7;
		tmp.style.height = '100%';
		tmp.onload = correctPNG;
	this.tt.bgl = document.createElement('div');
	this.tt.bgl.appendChild(tmp);
	this.div.appendChild(this.tt.bgl);
	
	this.tt.bgbody = document.createElement('div');
	this.div.appendChild(this.tt.bgbody);
	
	this.tt.content = document.createElement('div');
	this.tt.bgbody.appendChild(this.tt.content);
	
	var tmp = document.createElement('img');
		tmp.src = this.iPath + 'tt_bgr.png';
		tmp.width = 12;
		tmp.style.height = '100%';
		tmp.onload = correctPNG;
	this.tt.bgr = document.createElement('div');
	this.tt.bgr.appendChild(tmp);
	this.div.appendChild(this.tt.bgr);
	
	// BOTTOM 
	var tmp = document.createElement('img');
		tmp.src = this.iPath + 'tt_cbl.png';
		tmp.width = 11;
		tmp.height = 11;
		tmp.onload = correctPNG;
	this.tt.cbl = document.createElement('div');
	this.tt.cbl.appendChild(tmp);
	this.div.appendChild(this.tt.cbl);
	
	var tmp = document.createElement('img');
		tmp.src = this.iPath + 'tt_bgb.png';
		tmp.style.width = '100%';
		tmp.height = 11;
		tmp.onload = correctPNG;
	this.tt.bgb = document.createElement('div');
	this.tt.bgb.appendChild(tmp);
	this.div.appendChild(this.tt.bgb);
	
	var tmp = document.createElement('img');
		tmp.src = this.iPath + 'tt_cbr.png';
		tmp.width = 11;
		tmp.height = 11;
		tmp.onload = correctPNG;
	this.tt.cbr = document.createElement('div');
	this.tt.cbr.appendChild(tmp);
	this.div.appendChild(this.tt.cbr);
	
	// POINTER BOTTOM
	var tmp = document.createElement('img');
		tmp.src = this.iPath + 'tt_pbl.png';
		tmp.width = 38;
		tmp.height = 34;
		tmp.onload = correctPNG;
	this.tt.pbl = document.createElement('div');
	this.tt.pbl.appendChild(tmp);
	this.div.appendChild(this.tt.pbl);
	
	var tmp = document.createElement('img');
		tmp.src = this.iPath + 'tt_pbr.png';
		tmp.width = 39;
		tmp.height = 34;
		tmp.onload = correctPNG;
	this.tt.pbr = document.createElement('div');
	this.tt.pbr.appendChild(tmp);
	this.div.appendChild(this.tt.pbr);
	
	// use pointerState as array index 
	this.tt.pointer  = [this.tt.pbl, this.tt.pbr, this.tt.ptr, this.tt.ptl];
	// memorize current pointer
	this.tt.actPointer = this.pointerState;
	
	function correctPNG(e) {
		mdvLib.correctPNG(that.mdvMap, this);
	}
	
	this.wasWrap = null;
	
};
    
	
MDVToolTipBubble.prototype.update = function () {   		
	
	var that = this;
	var point = this.mdvMap.getPoint(this.getParent().getCoords());
	
	var markerObj = this.getParent();
	
	
	
	if(!point) {
		this.mdvMap.events.triggerEvent(MDVEvent_ERROR, 'MDVMap wasn\'t able to get px coordinates for marker.');
   		return false;
	}
	
	// create pin ... 
	if (this.getParent() && this.getParent().toolTip
		&& this.getParent().toolTip.hasPin()
		&& typeof this.tt.pin === 'undefined') {
		
		var tmp = document.createElement('img');
			tmp.src = this.iPath + 'bubble.png';
			tmp.style.position = 'relative';
			tmp.style.left = -662 + 'px';
			tmp.style.top = -701 + 'px';
			tmp.bubble = this;
			tmp.onclick = MDVToolTipBubble_OnPinClick.bind(that);
			
		this.tt.pin = document.createElement('div');
		this.tt.pin.appendChild(tmp);
		this.tt.bgbody.appendChild(this.tt.pin);
		mdvLib.style([this.tt.pin], {
			position: 'absolute',
			top: '0px',
			right: '5px',
			width: '19px',
			height: '18px',
			zIndex: 201,
			overflow: 'hidden'
		});
	}
	
	// ... or close icon
	else if (this.mdvMap.config.get('tooltipHandler')
   		 && this.mdvMap.config.get('tooltipHandler').indexOf('click') !== -1
   		 && typeof this.tt.imgClose === 'undefined') {
		
		var tmp = document.createElement('img');
			tmp.src = this.iPath + 'btn_X.gif';
			tmp.style.position = 'relative';
			tmp.style.top = '2px',
			tmp.style.left = '4px',
			tmp.bubble = this;
			
		this.tt.imgClose = document.createElement('div');
		this.tt.imgClose.appendChild(tmp);
		this.tt.bgbody.appendChild(this.tt.imgClose);
		mdvLib.style([this.tt.imgClose], {
			position: 'absolute',
			top: '-2px',
			right: '0px',
			cursor: 'pointer',
			width: '20px',
			height: '20px',
			zIndex: 999,
			overflow: 'hidden'
		});
	}
	
	if( typeof this.tt.imgClose !== 'undefined') {
		this.tt.imgClose.onclick = MDVMarker_hideToolTip.bind(markerObj);
	}
	
	var parent = this.getParent();
	
	var margin = new MDVPoint(0, 0);
	var iwidth = 0;
	var iheight = 0;
	
	if (parent && parent.img) {
		margin.x = parent.img.width * parent.getXFactor();			
		margin.y = parent.img.height * parent.getYFactor();
		iwidth = parent.img.width;
		iheight = parent.img.height;
	}

	if (parent.img 
		&& (this.margins == null 
		|| (this.getLastParent()
		&& this.getLastParent().id != this.getParent().id))) {
   		var tempPos = new MDVPoint(parseInt(this.div.style.left),
			parseInt(this.div.style.top));
			
		// Not for the first time.
		if (this.margins) {
			this.div.style.left = (tempPos.x - this.margins.x) + 'px';
   			this.div.style.top	= (tempPos.y - this.margins.y) + 'px';
		}

		// Reset margin on marker turnover			
		switch (this.pointerState) {
			case 0:
				this.margins = new MDVPoint(iwidth - margin.x, 0 - margin.y);
				
			break;
			
			case 1:
				this.margins = new MDVPoint(0 - margin.x, 0 - margin.y);
			break;
			
			case 2:
				this.margins = new MDVPoint(0 - margin.x, iheight - margin.y);
			break;
			
			case 3:
				this.margins = new MDVPoint(iwidth - margin.x, iheight - margin.y);
			break;
		}			
		
		this.setLastParent(this.getParent());
	} else if (parent.img == null) {
		this.margins = null;
		this.setLastParent(null);
	}

	var viewport = this.mdvMap.getViewportExtends();
	
	if (!this.offset) {
		this.offset = new MDVPoint(0 + this.delta.x - this.pointerBorder.x, 0);
	} else {
		this.offset.x += this.delta.x;
		this.offset.y += this.delta.y;
	}
	
	this.delta.x = 0;
	this.delta.y = 0;
	
	// We need to move the tool tip first in order to check whether it is crossing a border...
	var xMargin = this.margins ? this.margins.x : 0;
	var yMargin = this.margins ? this.margins.y : 0;
	
	
	// assign correct offset.x if we touched a border before
	if(this.wasWrap && this.wasWrap==='right') {
		this.offset.x = this.size.x * -1 + 34;
		this.pointerBorder.x = this.size.x - this.pointerSize.x - 34;
		if (this.margins) {
   			this.margins.x = 0 - margin.x;
		}	
	} else if(this.wasWrap && this.wasWrap==='left') {
		this.pointerBorder.x = 34;
		this.offset.x = 0 - 34;
		if (this.margins) {
   			this.margins.x = iwidth - margin.x;
		}
	}
	
	this.div.style.left     = (point.x + this.offset.x + xMargin) + 'px';
	this.div.style.top 		= (point.y + this.offset.y + yMargin) + 'px';
	
	var pos = new MDVPoint(parseInt(this.div.style.left) + parseInt(this.mdvMap.mapper.style.left),
		parseInt(this.div.style.top) + parseInt(this.mdvMap.mapper.style.top));
	
	var update = false;
	var wrap = { upper: true, lower: false, left: true, right: false };
	
	// Crossing upper view port border
	if (pos.y <= 25) {
		this.innerOffset.y = this.pointerSize.y-1;
		this.offset.y = 0;
		
		if (this.margins)
   			this.margins.y = (iheight - margin.y);

			wrap.upper = true;
 
   			update = true;
   		} else {
   			wrap.upper = false;
   		}

	// Crossing lower view port border   		
	if (pos.y + this.size.y + 20 >= viewport.height) {
		this.innerOffset.y = 0;   			
		this.offset.y = this.size.y * -1;

		if (this.margins)
   			this.margins.y = 0 - margin.y;

		wrap.lower = true;

		update = true;
	} else {
		wrap.lower = false;
	}
		
	// Crossing left hand view port border 
	if (pos.x < 14) {
		this.pointerBorder.x = 34;
		this.offset.x = 0 - 34;

		if (this.margins)
   			this.margins.x = iwidth - margin.x;

		wrap.left = true;
		this.wasWrap = 'left';
		update = true;
	} else {
		wrap.left = false;
	}

	// Crossing right hand view port border
	if (pos.x + this.size.x + 8 + margin.x > viewport.width) {
		this.offset.x = this.size.x * -1 + 34;
		this.pointerBorder.x = this.size.x - this.pointerSize.x - 34;
		
		if (this.margins)
   			this.margins.x = 0 - margin.x;
		
		wrap.right = true;
		this.wasWrap = 'right';
		update = true;   			
	} else {
		wrap.right = false;
	}
	
	if (update) {
		var xMargin = this.margins ? this.margins.x : 0;
		var yMargin = this.margins ? this.margins.y : 0;
		this.div.style.left     = (point.x + this.offset.x + xMargin) + 'px';
   		this.div.style.top 		= (point.y + this.offset.y + yMargin) + 'px';
	}

	this.pointerState = this.wrapPointer(wrap);   		
	
	this.updateBubble();
	
	return true;
};	

MDVToolTipBubble.prototype.setPointer = function(updatePos) {
	
	this.tt.pointer[this.tt.actPointer].style.visibility = 'hidden';	
		this.tt.pointer[this.pointerState].style.visibility = 'visible';
		this.tt.actPointer = this.pointerState;
		
		if(!updatePos) {
			return true;
		}
		
		switch (this.pointerState) {
			case 0:	this.div.style.top = parseInt(this.div.style.top, 10) - 50 + 'px';
					this.div.style.left = parseInt(this.div.style.left, 10) + 15 + 'px';
					break;
			case 1:	this.div.style.top = parseInt(this.div.style.top, 10) - 48 + 'px';
					this.div.style.left = parseInt(this.div.style.left, 10) - 17 + 'px';
					break;
			case 2:	this.div.style.top = parseInt(this.div.style.top, 10) + 3 + 'px';
					this.div.style.left = parseInt(this.div.style.left, 10) - 17 + 'px';
					break;
			case 3:	this.div.style.top = parseInt(this.div.style.top, 10) + 3 + 'px';
					this.div.style.left = parseInt(this.div.style.left, 10) + 15 + 'px';
					break;
		}
		return true;
};  

MDVToolTipBubble.prototype.setVisibility = function (visible) {
    	this.visibility = visible;
    	var flow = false;
    	var parent = this.getParent();
    	if (parent && parent.toolTip && parent.toolTip.isOverflow())
    		flow = true;
//    	if (this.complex['body'] && flow)
//	    	this.complex['body'].style.overflow = visible ? 'auto' : 'hidden';
		if (this.tt && visible === false) {
			this.tt.pointer[this.tt.actPointer].style.visibility =  'hidden';	
    	}
		this.div.style.visibility = visible ? 'visible' : 'hidden';
    };	
	
	
MDVToolTipBubble.prototype.updateBubble = function () {
		
	/*  POINTER TOP LEFT / RIGHT */
	
	
	mdvLib.style([this.tt.ptl], {
		position: 'absolute',
		top: '1px',
		width: '35px',
		height: '26px',
		zIndex: 101,
		overflow: 'hidden',
		visibility: 'hidden'
	});
	
	mdvLib.style([this.tt.ptr], {
		position: 'absolute',
		top: '0px',
		width: '40px',
		height: '27px',
		left: this.size.x - 41 + 'px',
		zIndex: 101,
		overflow: 'hidden',
		visibility: 'hidden'
	}); 
	
	/* TOP */
	
	mdvLib.style([this.tt.ctl], {
		position: 'absolute',
		top: '23px',
		width: '7px',
		height: '11px',
		overflow: 'hidden'
	});
	
	mdvLib.style([this.tt.bgt], {
		position: 'absolute',
		top: '23px',
		left: '7px',
		width: this.size.x - 18 + 'px',
		height: '11px',
		overflow: 'hidden'
	});
	
	mdvLib.style([this.tt.ctr], {
		position: 'absolute',
		top: '23px',
		left: this.size.x - 11 + 'px',
		width: '11px',
		height: '12px',
		overflow: 'hidden'
	});
	
	/* CENTER */ 

	mdvLib.style([this.tt.bgl], {
		position: 'absolute',
		top: '34px',
		left: '0px',
		width: '7px',
		height: this.size.y - 11 + 'px',
		overflow: 'hidden'
	});
	
	mdvLib.style([this.tt.bgbody], {
		position: 'absolute',
		top: '30px',
		left: '6px',
		width: this.size.x - 16 + 'px', 
		height: this.size.y - 7 + 'px',
		backgroundColor: '#fff',
		overflow: 'hidden'
	});
	
	mdvLib.style([this.tt.content], {
		margin: '0px 0px 0px 0px'		
	});
	
	
	// correct bgr offset in IE
	var topPos = (document.all) ? '34px' : '35px';
	var heightCorr = (document.all) ? 11 : 12;
	
	mdvLib.style([this.tt.bgr], {
		position: 'absolute',
		top: topPos,
		left: this.size.x - 11 + 'px',
		width: '12px',
		height: this.size.y - heightCorr + 'px',
		overflow: 'hidden'
	});
	
	/* BOTTOM */ 
	
	mdvLib.style([this.tt.cbl], {
		position: 'absolute',
		top: this.size.y + 23 + 'px',
		width: '11px',
		height: '11px',
		overflow: 'hidden'
	});
	
	mdvLib.style([this.tt.bgb], {
		position: 'absolute',
		top: this.size.y + 23 + 'px', 
		left: '11px',
		width: this.size.x - 21 + 'px',
		height: '11px',
		overflow: 'hidden'
	});
	
	mdvLib.style([this.tt.cbr], {
		position: 'absolute',
		top: this.size.y + 23 + 'px',
		left: this.size.x - 10 + 'px', 
		width: '11px',
		height: '11px',
		overflow: 'hidden'
	});
	
	/*  POINTER BOTTOM LEFT / RIGHT */
	
	mdvLib.style([this.tt.pbl], {
		position: 'absolute',
		top: this.size.y + 23 + 'px',
		width: '38px',
		height: '34px',
		overflow: 'hidden',
		visibility: 'hidden'
	});
	
	mdvLib.style([this.tt.pbr], {
		position: 'absolute',
		top: this.size.y + 23 + 'px',
		left: this.size.x - 38 + 'px',
		width: '39px',
		height: '34px',
		overflow: 'hidden',
		visibility: 'hidden'
	}); 
	
	this.setPointer(true);
};

MDVToolTipBubble.prototype.setInnerHTML = function (innerHTML) {
	this.tt.content.innerHTML = innerHTML;
};


function MDVToolTipBubble_OnPinClick(e) {
	
	var pinImg = this.tt.pin.firstChild;
	
	if (pinImg.bubble && pinImg.bubble.getParent() && pinImg.bubble.getParent().toolTip) {
		var fixed = pinImg.bubble.getParent().toolTip.isFixed();
		pinImg.style.left = (fixed ? -662 : -681) + 'px';
   		pinImg.bubble.getParent().toolTip.setFixed(!fixed);
   	}
}

