// 
//  movideo.tooltips.js
//  Movideo ToolTips
//  
//  Copyright 2009 mcm technial services. All rights reserved.
// 
//movideo_agent.swf and movideo_mediagallery.swf urls need to bee changed as appropriate

/**
	@ BEGIN MOVIDEO.AUTOLINKER
*/
if (typeof Movideo == "undefined") { var Movideo = {}; }

Movideo.AutoLinker = {
	
	Settings: {
		// These vars are set with scriptsrc query string
		autolink: 'on', // optional
		config: '',
		content_id: '',
		domain:'',
		path:'autolinker',
		url:'',
		//storage for the sessiontoken once authenticated
		sessionToken:'',
		counter: 0,
		
		AGENT_URL: '',
		AGENT_ID: 'agent-obj',
		AGENT_HOLDER_ID: 'agent-holder'
	},
	
	setup: function () {		
	
		this.setupCustomOptions();
		if (!document.getElementById(this.Settings.content_id)) { return; }
		this.embedAgent();
	},
	
	setupCustomOptions: function () 
	{
		Movideo.AutoLinker.Settings.domain = _getDomain (MovideoAutoLinkerScriptObj);
		Movideo.AutoLinker.Settings.url = Movideo.AutoLinker.Settings.domain  +'/'+Movideo.AutoLinker.Settings.path; 
		Movideo.AutoLinker.Settings.AGENT_URL = 'http://'+ Movideo.AutoLinker.Settings.url +'/flash/movideo_agent.swf';
		var query_string = _getQueryString(MovideoAutoLinkerScriptObj);
		_applyCustomSettings(_parseQuery(query_string));
		
		
		function _getQueryString (scriptobj) {
			return scriptobj.src.replace(/^[^\?]+\??/,'');
		}
		
		function _getDomain (scriptobj) {
		var pathExtract = /^(?:(?![^:@]+:[^:@\/]*@)([^:\/?#.]+):)?(?:\/\/)?((?:(([^:@]*)(?::([^:@]*))?)?@)?([^:\/?#]*)(?::(\d*))?)(((\/(?:[^?#](?![^?#\/]*\.[^?#\/.]+(?:[?#]|$)))*\/?)?([^?#\/]*))(?:\?([^#]*))?(?:#(.*))?)/;
		return (pathExtract.exec(scriptobj.src))[2];
		}
		
		function _parseQuery (query) {
		   var Params = new Object();
		   if (!query) return Params; // return empty object
		   var Pairs = query.split(/[;&]/);
		   for (var i=0; i < Pairs.length; i++) {
		      var KeyVal = Pairs[i].split('=');
		      if (!KeyVal || KeyVal.length != 2) continue;
		      var key = unescape(KeyVal[0]);
		      var val = unescape(KeyVal[1]);
		      val = val.replace(/\+/g, ' ');
		      Params[key] = val;
		   }
		   return Params;
		}
		
		function _applyCustomSettings (custom_settings) {
			for (var key in custom_settings) {
				Movideo.AutoLinker.Settings[key] = custom_settings[key];
			}
			
		// apply sitename
		if (!Movideo.AutoLinker.Settings.config || Movideo.AutoLinker.Settings.config.length<=0) 
		{
			Movideo.AutoLinker.Settings.config = Movideo.AutoLinker.Settings.url+'/demo/config';
		}
        
		}
	},
	
	embedAgent: function () {
		var div = document.createElement('div');
		div.setAttribute('id', Movideo.AutoLinker.Settings.AGENT_HOLDER_ID);
		div.style.width = '1';
		div.style.height = '1';
		div.style.overflow = 'hidden';
		div.style.position = 'fixed';
		div.style.top = '0';
		div.style.left = '0';

		var embed_target = document.createElement('div');
		embed_target.setAttribute('id', Movideo.AutoLinker.Settings.AGENT_ID);
		
		div.appendChild(embed_target);
		document.body.appendChild(div);
		
		var params = {
		  menu: "false",
		  allowScriptAccess: "always",
		  wmode: "transparent",
		  quality: "low"
		};
		
		var flashvars={
			config:'http://'+this.Settings.config
			
		};
		
		swfobject.embedSWF(Movideo.AutoLinker.Settings.AGENT_URL, Movideo.AutoLinker.Settings.AGENT_ID, 1, 1, "9.0.0", null, flashvars, params, null);
	},
	
	agentReady: function (sessionToken) {
		this.Settings.sessionToken=sessionToken;
		if (Movideo.AutoLinker.Settings.autolink == 'on') {
			var agent = document.getElementById(Movideo.AutoLinker.Settings.AGENT_ID);
			agent.scan(Movideo.AutoLinker.getCleanCopy(Movideo.AutoLinker.Settings.content_id));
		} else {		
		

		Movideo.ToolTips.setup(this.Settings.config, sessionToken);
		}
	},
	
	autoLink: function (data) {
		if (!data) { return; }

		var copy = this.getCopy(this.Settings.content_id);
	
		//finding all flashvars and storing their values because they will be stripped by 'innerHTML' on IE
		var fv = this.getFlashVars(document.getElementById(this.Settings.content_id), new Array());
		
		for (var i=0; i < data.length; i++) {
			copy = this.updateCopy(data[i], copy);
		};
		
		//restoring flashvars that were stripped by 'innerHTML' in IE
		copy = this.resetFlashVars(copy,fv);
		
		document.getElementById(this.Settings.content_id).innerHTML = copy;
		
		Movideo.ToolTips.setup(this.Settings.config, this.Settings.sessionToken);
	},
	
	getCopy: function (area_id) {
		var copy = document.getElementById(area_id).innerHTML;
		return copy;
	},
	
	getFlashVars: function (domNode, fv) {
		for(var i=0; i<domNode.childNodes.length; i++){
			var childNode = domNode.childNodes[i];
		
			if(childNode.childNodes.length > 0)
			{
				var results = this.getFlashVars(childNode, fv);
				if(results.length > 0)
					fv.concat(results);
			}
			else if(childNode.nodeName.toLowerCase() == "param" && childNode.attributes.getNamedItem('name').value.toLowerCase() == "flashvars")
			{
			var temp = childNode.attributes.getNamedItem('value').value;
			if(childNode.attributes.getNamedItem('value').value == "undefined")//no value
				fv.push("undefined");//placing 'undefined' here because the regex used to update the flashvars look for empty vars, undefined marks it as updated but empty.
			else
				fv.push(childNode.attributes.getNamedItem('value').value);
			}
		}
		return fv;
	},
	
	resetFlashVars: function (copy, fv) {

		for(var i=0;i<fv.length;i++)
		{
			copy = copy.replace(/("?flashvars"?[\s]*)(value="?\s?"?(?=>))/im, "\"flashvars\" value=\""+fv[i]+"\"");
		}
		
		return copy;
	},
	
	//return the copy minus any <object> or <script> tags because these can cause issues with the URLRequest in the ActiveX Flash plugin
	getCleanCopy: function (area_id) {
		var copy = document.getElementById(area_id).innerHTML;
		return copy.replace(/(<script[\s\S]*?<\/\s*script\s*>|<object[\s\S]*?<\/\s*object\s*>)/gim, '');
	},
	
	//return a tag array instead of targetContent
	updateCopy: function (targetContent, copy) {
		if(targetContent.related != null)
		{
			var regex = '\\b' + targetContent.primary.value + '\\b(?![^<]*>)(?![^<]*</a)';
			var regex_obj = new RegExp(regex, 'i');
			var key = Movideo.ToolTips.Settings.Triggers.ID_PREFIX+Movideo.AutoLinker.Settings.counter;
			Movideo.AutoLinker.Settings.counter++;
			Movideo.ToolTips.Settings.Table[key] = targetContent.primary.tag +','+ targetContent.related.tag;
			return copy.replace(regex_obj, '<a href="#" class="' + Movideo.ToolTips.Settings.Triggers.CLASS +'" id="' + key +'">$&</a>');
		}
		else
		{
			var key = Movideo.ToolTips.Settings.Triggers.ID_PREFIX+Movideo.AutoLinker.Settings.counter;
			Movideo.AutoLinker.Settings.counter++;
			Movideo.ToolTips.Settings.Table[key] = targetContent.primary.tag +',';
			var regex = '\\b' + targetContent.primary.value + '\\b(?![^<]*>)(?![^<]*</a)';
			var regex_obj = new RegExp(regex, 'i');
			return copy.replace(regex_obj, '<a href="#" class="' + Movideo.ToolTips.Settings.Triggers.CLASS +'" id="' + key +'">$&</a>');
		}	
	}
	
};



/**
	@ BEGIN MOVIDEO.TOOLTIPS
*/

Movideo.ToolTips = {
	
	Settings: {
		
		Table: {},
	
		Triggers: {
			CLASS: 'movideo-tooltip',
			ELEMENT: 'a',
			ID_PREFIX: 'movideo-searchtag-', // prefix before searchtag, e.g. for id="movideo-searchtag-0", prefix is 'movideo-searchtag-'
			open_in_new_window: false,
			styles: {
				color:  '#2badf3', // movideo blue
				font_weight: 'bold',
				border_bottom: '1px dotted #2badf3',
				cursor: 'pointer',
				Icon: {
					padding: '0 2px 0 4px',
					border: '0',
					display: 'inline'
				}
			}
		},
		
		Link: {
			onclick_link: ''//set by setTooltipProperties
		},
		
		Popup: {
			delay_disp: 200, // ms
			delay_hide: 800, // ms
			width_min: 213, // px
			width_max: 383, // px
			height: 120, // px
			padding: 1, // px
			offset_x: -50, // px
			offset_y: -118, // px
			border_color: '' // colour of tooltip border, set by setupTooltipProperties()
		},
		
		Flash: {
			config: '', // // passed in via Movideo.ToolTips.setup(), same as this.vars.config
		//	url: 'http://'+ Movideo.AutoLinker.Settings.url +'/flash/movideo_mediagallery.swf',
			url: '',
			vars: {
				adType: '', // defaults to toolip
				config: '', // passed in via Movideo.ToolTips.setup()
				tag: '',
				sessionToken: ''
			},
			width_min: 211, // px
			width_max: 383, // px
			height: 90, // px
			object_id: 'movideogalleryobject',
			embed_id: 'movideogalleryembed'
		},

		ImageAssets: {
			base_path: 'http://', // base path to images, sitename is appended to this by Movideo.ToolTips.prepareImages()
			bg_left: 'tooltip-bg-left.png',
			bg_right: 'tooltip-bg-right.png',
			bg_right_ie6_297: 'tooltip-bg-right-ie6-297px.png',
			bg_right_ie6_211: 'tooltip-bg-right-ie6-211px.png',
			ico_play: 'tooltip-play.gif'
		}
		
	},
	
	Objects: {
		TriggerActive: null, // active trigger link
		Popup: null, // the popup element if it exisits
		Timer: null // application timer
	},
	
	
	
	/**
		@ SETUP MOVIDEO.TOOLTIPS
		@ param classname [String (optional)] CSS class to setup Movideo.tooltips on
	*/
	setup: function (sitename,sessionToken) {

			// apply sitename
		if (!sitename || sitename.length<=0) 
		{
			var sitename = Movideo.AutoLinker.Settings.url+'/demo/config'
			this.Settings.Flash.vars.config =  Movideo.AutoLinker.Settings.domain;		
			this.Settings.Flash.vars.adType = Movideo.AutoLinker.Settings.domain;		
			this.setupTooltipProperties(sitename);
		}
		else
		{
			this.Settings.ImageAssets.base_path += sitename + '/';
			this.Settings.Flash.vars.config = sitename;		
			this.setupTooltipProperties(sitename);
		}
	
		this.Settings.Flash.url = 'http://'+ Movideo.AutoLinker.Settings.url +'/flash/movideo_mediagallery.swf'
	   
	
		if(sessionToken)
			this.Settings.Flash.vars.sessionToken = sessionToken;
		
		// prep and preload bg images
		this.prepareImages(this.Settings.ImageAssets);

		var triggers = this.Utils.getElementsByClass(this.Settings.Triggers.CLASS, null, this.Settings.Triggers.ELEMENT);
		if (triggers.length < 1) return;
		
		// assign trigger events
		for (var i=0; i < triggers.length; i++) {
			this.styleTriggers(triggers[i]);
			
			triggers[i].onmouseover = function (e) {
				if (!e) var e = window.event;
				Movideo.ToolTips.handleMouseOver(this, e);
			};

			triggers[i].onmouseout = function (e) {
				if (!e) var e = window.event;
				Movideo.ToolTips.handleMouseOut(this, e);
			};
			
			triggers[i].onclick = function () {
				if(Movideo.ToolTips.Settings.Link.onclick_link != '')
				{
			 	var tagArray = new Array(Movideo.ToolTips.getPrimaryTag(this),Movideo.ToolTips.getRelatedTag(this))
					Movideo.ToolTips.goToPage(Movideo.ToolTips.Settings.Triggers.open_in_new_window,tagArray);
				}
			 	return false;
			};

		};
		
		// assign document listener for cleanup
		// use movideo_addEvent to ensure existing document.onmouseover events aren't overwritten
		movideo_addEvent(document,"mouseover", function (e) {
			if (!e) var e = window.event;
			Movideo.ToolTips.handleDocumentOver(e);
		});
		
	},
	
	
	setupTooltipProperties: function (sitename) {
		Movideo.ToolTips.Settings.Popup.border_color = _getBorderColor(_getToolTipProperties(sitename));
		Movideo.ToolTips.Settings.Link.onclick_link = _getOnClickLink(_getToolTipProperties(sitename));
		
		// Don't override link color if not found
		var linkColor = _getTriggerColor(_getToolTipProperties(sitename));
		if (linkColor)
		{
			Movideo.ToolTips.Settings.Triggers.styles.color = linkColor;
			Movideo.ToolTips.Settings.Triggers.styles.border_bottom = '1px dotted ' + linkColor;
		}

		function _getToolTipProperties (sitename) {
			var agent = document.getElementById(Movideo.AutoLinker.Settings.AGENT_ID);
			if (agent) {
				var properties = agent.getTooltipProperties();		
				return properties;
			}
		}
		
		function _getBorderColor (properties) {
			var color = properties.match(/color\.border.*/);
			color = '#' + color[0].split('color.border=0x')[1];
			return color;
		}
		
		function _getOnClickLink (properties) {
			var onClickLink = properties.match(/onclick\.link.*/);
			if(onClickLink != undefined)
				onClickLink = onClickLink[0].split('onclick.link=')[1];
			else
				return;
			return onClickLink;
		}
		
		function _getTriggerColor(properties) {
			var color = properties.match(/[^#]color\.link\S*/);
			return color ? '#' + color[0].split('color.link=0x')[1] : null;
		}
	},
	
	
	/**
		@ TRIGGER MOUSEOVER: CREATE, POSITION, DISPLAY POPUP
		@ param trigger [HTML Element] HTML Element of activated trigger link
	*/
	handleMouseOver: function (trigger) {
		this.stopTimer();
		this.Objects.Timer = setTimeout(function(){ _displayPopup(trigger); trigger=null; }, Movideo.ToolTips.Settings.Popup.delay_disp);
		
		function _displayPopup (trigger) {
			// reset timer
			Movideo.ToolTips.stopTimer();

			// if trigger is active, its tooltip is already there, do nothing
			if (Movideo.ToolTips.Utils.hasClass(trigger, 'active')) { return false; }

			// if another tooltip exists, kill it
			if (Movideo.ToolTips.Objects.Popup) { Movideo.ToolTips.removePopup(); }

			// set active trigger and artist id
			Movideo.ToolTips.Utils.addClass(trigger, 'active');
			Movideo.ToolTips.Objects.TriggerActive = trigger;
			Movideo.ToolTips.Settings.Flash.vars.tag = Movideo.ToolTips.getPrimaryTag(trigger);

			// create, position and append popup
			_createPopup(trigger);
			Movideo.ToolTips.positionPopup(trigger);
			document.body.appendChild(Movideo.ToolTips.Objects.Popup);

			function _createPopup (trigger) {
				var popup = document.createElement('div');
			  popup.style.width = Movideo.ToolTips.Settings.Popup.width_min + 'px';
			 popup.style.height = Movideo.ToolTips.Settings.Popup.height + 'px';
			 popup.style.overflow = 'hidden';
			  popup.style.zIndex = '9999';
			  popup.style.backgroundColor = 'transparent';
			  popup.style.backgroundRepeat = 'no-repeat';
				popup.style.position = 'absolute';
				popup.setAttribute('rel', trigger.getAttribute('id')); // set id of tooltip to span[rel] of it's trigger
				
				// creating nested div for 1px border around swf
				var popup_inner = document.createElement('div');
				popup_inner.style.border = '1px solid ' + Movideo.ToolTips.Settings.Popup.border_color;
				popup_inner.style.height = Movideo.ToolTips.Settings.Flash.height + 'px';
				popup_inner.innerHTML = '<object id="' + Movideo.ToolTips.Settings.Flash.object_id + '" width="' + Movideo.ToolTips.Settings.Flash.width_min + '" height="' + 0 + '" classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000" codebase="http://download.macromedia.com/pub/shockwave/cabs/flash/swflash.cab#version=9,0,28,0"><param name="allowScriptAccess" value="always" /><param name="flashvars" value="' + _toFlashVarsString(Movideo.ToolTips.Settings.Flash.vars) + '" /><param name="movie" value="' + Movideo.ToolTips.Settings.Flash.url + '" /><param name="bgcolor" value="#ffff00" /><embed id="' + Movideo.ToolTips.Settings.Flash.embed_id + '" src="' + Movideo.ToolTips.Settings.Flash.url + '?' + _toFlashVarsString(Movideo.ToolTips.Settings.Flash.vars) + '" quality="high" bgcolor="#ffff00" width="' + Movideo.ToolTips.Settings.Flash.width_min + '" height="' + 0 + '" name="myMovieName" align="" type="application/x-shockwave-flash" pluginspage="http://www.macromedia.com/go/getflashplayer" allowscriptaccess="always" allowfullscreen="true" /></object>';
				
				popup.appendChild(popup_inner);

				popup.onmouseover = function (e) {
					Movideo.ToolTips.stopTimer();
				};

				popup.onmouseout = function (e) {
					if (!e) var e = window.event;
					Movideo.ToolTips.handleMouseOut(popup, e);
				};

				Movideo.ToolTips.Objects.Popup = popup;

				function _toFlashVarsString (hash) {
					var pairs = [], string;
					for (key in hash) {
						string = key + '=' + hash[key];
						pairs[pairs.length] = string;
					}
					return pairs.join('&');
				}	
			}
		}
		
	},
	
	
	
	/**
		@ POSITION POPUP
		@ param trigger [HTML Element] HTML Element of activated trigger link
		@ param popup_width [Integer (optional)] Popup width, otherwise it is Movideo.ToolTips.Settings.Popup.width_min
		Called twice during popup creation lifecycle:
		1. After popup is created handleMouseOver()
		2. After the Flash callback function setSize(), to reposition after swf width is known
	*/
	positionPopup: function (trigger, popup_width) {
		var popup = this.Objects.Popup;
		var viewport_width = _getViewportSize()[0];
		var trigger_x = _getPosition(trigger)[0];
		var trigger_y = _getPosition(trigger)[1];
		var gap = viewport_width - trigger_x; // width of gap from link position to right edge of viewport 
		if (!popup_width) {
			popup_width = this.Settings.Popup.width_min;
		} else {
			popup.style.width = popup_width + 'px';

	}
		
	  popup.style.top = (trigger_y + this.Settings.Popup.offset_y) + 'px';
		
		// if the RHS gap is smaller than the max width of the popup, right-align the popup
		if (gap < this.Settings.Popup.width_max) {
			popup.style.left = trigger_x - (popup_width + this.Settings.Popup.offset_x) + 'px';
			popup.style.backgroundPosition = 'right top';
			if (this.Utils.isIE6()) {
				bg_ie6 = _getBackgroundImageForIE6(popup_width);
				popup.style.filter = 'progid:DXImageTransform.Microsoft.AlphaImageLoader(src="' + bg_ie6 + '", sizingMethod="crop")';
			} else {
				popup.style.backgroundImage = 'url("' + this.Settings.ImageAssets.bg_right + '")';
			}
		// otherwise, there's enough room, left-align popup
		} else {
		  popup.style.left = trigger_x + 'px';
			popup.style.backgroundPosition = 'left top';
			if (this.Utils.isIE6()) {
				popup.style.filter = 'progid:DXImageTransform.Microsoft.AlphaImageLoader(src="' + this.Settings.ImageAssets.bg_left + '", sizingMethod="crop")';
			} else {
				popup.style.backgroundImage = 'url("' + this.Settings.ImageAssets.bg_left + '")';
			}
		}
		
		// In IE6, we cannot apply background-position background images applied with AlphaImageLoader
		// So we have to create background images sized to match all the possible tooltip widths
		// This function returns the appropriate image for the popup_width
		function _getBackgroundImageForIE6 (popup_width) {
			if (popup_width == Movideo.ToolTips.Settings.Popup.width_max) {
				return Movideo.ToolTips.Settings.ImageAssets.bg_right;
			} else if (popup_width == 299) {
				return Movideo.ToolTips.Settings.ImageAssets.bg_right_ie6_297;
			}	else if (popup_width == 213) {
				return Movideo.ToolTips.Settings.ImageAssets.bg_right_ie6_211;
			}
		}
		
		// returns position of element relative to document 
		function _getPosition (el) {
			var x = y = 0;
			do {
				x += el.offsetLeft;
				y += el.offsetTop;
			} while (el = el.offsetParent);
		  return [x, y];
		}
		
		// returns dimensions of document
		function _getViewportSize () {
			var x = y = 0;
			var de = document.documentElement;
			x = self.innerWidth || (de && de.clientWidth) || document.body.clientWidth;
			y = self.innerHeight || (de && de.clientHeight) || document.body.clientHeight;
			return [x, y];
		}
	},
	
	
	
	/**
		@ FLASH CALLBACK: SET SWF SIZE
		@ param swf_width [Interger] Calculated swf width
		It resizes the swf accordingly, aswell as resizing and repositioning the popup.
		Called when Flash has loaded media and is able to determine the swf width.
		swf height is initially set to 0 in _createPopup to hide flash until this callback.
	*/
	setSize: function (swf_width) {
		var swf_obj = document.getElementById(this.Settings.Flash.object_id);
		if (swf_obj) swf_obj.setAttribute('width', swf_width);
		if (swf_obj) swf_obj.setAttribute('height', this.Settings.Flash.height);
		var swf_emb = document.getElementById(this.Settings.Flash.embed_id);
		if (swf_emb) swf_emb.setAttribute('width', swf_width);
		if (swf_emb) swf_emb.setAttribute('height', this.Settings.Flash.height);
		
		this.Objects.Popup.style.width = swf_width + 'px';
		this.positionPopup(this.Objects.TriggerActive, (swf_width + 2));
		
		
	},
	
		
	
	/**
		@ TRIGGER/POPUP MOUSEOUT: REMOVE POPUP
		@ param el [HTML Element] HTML Element of mouseout listener (trigger or popup)
		@ param e [Object] Event object
		Called by the trigger and popup. Determines if mouse is has really left the tooltip
		area, then sets timeout to destroy popup.
	*/
	handleMouseOut: function (el, e) {	
		// if mouse has left tooltip, set a timer to destroy popup
		if (_hasMouseLeftToolTip(el, e)) {
			this.stopTimer();
			this.Objects.Timer = setTimeout(function(){ Movideo.ToolTips.removePopup(); }, Movideo.ToolTips.Settings.Popup.delay_hide);
		}
		
		function _hasMouseLeftToolTip (el, e) {
			// get element mouseout occured on
			var tg = e.srcElement || e.target;
			
			// if it wasn't the trigger/popout, return false
			if (tg != el) { return false; }

			// get related target (element moused-out to)
			var reltg = (e.relatedTarget) ? e.relatedTarget : e.toElement;
			
			// if it's null, something's gone wrong, kill popup immediate and return false
			if (reltg == null) {
				this.removePopup();
				return false;
			}
			
			// starting at related target, scale up DOM till it hits the trigger/popout, <body> or <html>
			while (reltg != tg && reltg.nodeName != 'BODY' && reltg.nodeName != 'HTML') {
				reltg = reltg.parentNode;
			};
			
			// if the moused-out-to element is a child of the the trigger/popout,
			// it's still on toolip territory, so won't remove the popup yet, return false
			if (reltg == tg) { return false; }
			
			// otherwise, the mouse has really left tooltip territory, return true
			return true;
		}
	},
	
	
	
	/**
		@ DOCUMENT MOUSEOVER: CLEAN UP ORPHAN TOOLTIPS
		@ param e [Object] Event object
			Destroys any orphan tooltips not destroyed by the mouseout events on triggers/tooltip
			(this happens sometimes when the cursor mouses out from the tooltip very fast, not firing
			the tooltip mouseout event in the process ... grrr)
	*/ 
	handleDocumentOver: function (e) {
		if (_isMouseAwayFromToolTip(e)) { _cleanUp(); }

		function _cleanUp () {
			// if tooltip is not active AND the timer is counting, do nothing
			if ((!Movideo.ToolTips.Objects.Popup) && (Movideo.ToolTips.Objects.Timer)) { return; }

			// if tooltip is on screen AND the timer is not counting, set timer to destroy tooltip
			if ((Movideo.ToolTips.Objects.Popup) && (Movideo.ToolTips.Objects.Timer == null)) {
				Movideo.ToolTips.stopTimer();
				Movideo.ToolTips.Objects.Timer = setTimeout(function(){ Movideo.ToolTips.removePopup(); }, Movideo.ToolTips.Settings.Popup.delay_hide);
			}
		}
		
		// checks if mouse is still over popup/link		
		function _isMouseAwayFromToolTip (e) {
			// get hovered el from event
			var tg = e.srcElement || e.target;
			
			// if the hovered el class matches trigger class, return false
			if (Movideo.ToolTips.Utils.hasClass(tg, Movideo.ToolTips.Settings.Triggers.CLASS)) { return false; }
			
			// take hovered el and step up thru DOM, stop if it's the tooltip, <body> or <html>
			while (tg != Movideo.ToolTips.Objects.Popup && tg.nodeName != 'BODY' && tg.nodeName != 'HTML') {
				tg = tg.parentNode;
			};
			
			// if the hovered el is a child of the ToolTip, return false
			if (tg == Movideo.ToolTips.Objects.Popup) return false;
			
			// it passes all checks! the mouse has moved away from the tooltip
			return true;
		}
	},

	
	
	/**
		@ MISC TOOLTIP FUNCTIONS
	*/
	removePopup: function () {
		this.stopTimer();
		if (!(this.Objects.Popup)) return;
		
		this.Utils.removeClass(this.Objects.TriggerActive, 'active');
		this.Objects.TriggerActive = null;
		
		this.Objects.Popup.parentNode.removeChild(this.Objects.Popup);
		this.Objects.Popup = null;
	},
	
	stopTimer: function () {
		clearTimeout(this.Objects.Timer);
		this.Objects.Timer = null;
	},

	getPrimaryTag: function (trigger) {
		var key = trigger.getAttribute('id').split(this.Settings.Triggers.ID_PREFIX)[1];	
		var tags = Movideo.ToolTips.Settings.Table[Movideo.ToolTips.Settings.Triggers.ID_PREFIX+key];
		return tags.split(',')[0];
	},
	
	getRelatedTag: function (trigger) {
		var key = trigger.getAttribute('id').split(this.Settings.Triggers.ID_PREFIX)[1];	
		var tags = Movideo.ToolTips.Settings.Table[Movideo.ToolTips.Settings.Triggers.ID_PREFIX+key];
		return tags.split(',')[1];
	},
	
	prepareImages: function (images) {
		for (key in images) {
			var regex = new RegExp('(' + Movideo.ToolTips.Settings.ImageAssets.base_path + ')');
			if (images[key].search(regex) == -1) {
				images[key] = this.Settings.ImageAssets.base_path + images[key];
				var img_obj = new Image;
				img_obj.src = images[key];
			}
		}
	},

	/* 
	 * Passed an array of tags and if the tag ns & predicate exist in the on_click url, then they are replaced
	 * with the tag value, i.e. http://test/{mcm:artistid}  becomes http://test/1234 if the tag 
	 * 'mcm:artistid=1234' exists in the array.
	 * */
	goToPage: function (new_window, tagArray) {
		var url = this.Settings.Link.onclick_link;
		for(var i in tagArray)
		{

			if(tagArray[i]!= undefined)
			{
				//splitting the tag into ns:predicate and value pair
				var tag = tagArray[i].split('=')

				//replace ns:predicate pattern with value
				var regex = '\{' + tag[0] + '\}';
				var regex_obj = new RegExp(regex, 'g');
				url = url.replace(regex_obj, tag[1]);
			}
		}

		if (new_window) {
			window.open(url);
		} else {
			window.location = url;
		}
	},
	
	styleTriggers: function (trigger) {
		trigger.style.color = this.Settings.Triggers.styles.color;
		trigger.style.fontWeight = this.Settings.Triggers.styles.font_weight;
		trigger.style.borderBottom = this.Settings.Triggers.styles.border_bottom;
		trigger.style.cursor = this.Settings.Triggers.styles.cursor;
		
		var img = document.createElement('img');
		img.setAttribute('border', '0');
		img.setAttribute('src', this.Settings.ImageAssets.ico_play);		
		img.style.padding = this.Settings.Triggers.styles.Icon.padding;
		img.style.display = this.Settings.Triggers.styles.Icon.display;
		trigger.appendChild(img);
	},
	
	/**
		@ UTILITY FUNCTIONS
	*/
	Utils: {
	
		hasClass: function (ele,cls) {
			return ele.className.match(new RegExp('(\\s|^)'+cls+'(\\s|$)'));
		},

		addClass: function (ele,cls) {
			if (!this.hasClass(ele,cls)) ele.className += " "+cls;
		},

		removeClass: function (ele,cls) {
			if (this.hasClass(ele,cls)) {
				var reg = new RegExp('(\\s|^)'+cls+'(\\s|$)');
				ele.className=ele.className.replace(reg,' ');
			}
		},

		// Dustin Diaz's getElementsByClass
		// http://www.dustindiaz.com/getelementsbyclass
		getElementsByClass: function (searchClass, node, tag) {
			var classElements = new Array();
			if (node == null) node = document;
			if (tag == null) tag = '*';
			var els = node.getElementsByTagName(tag);
			var elsLen = els.length;
			var pattern = new RegExp("(^|\\s)"+searchClass+"(\\s|$)");
			for (i = 0, j = 0; i < elsLen; i++) {
				if ( pattern.test(els[i].className) ) {
					classElements[j] = els[i];
					j++;
				}
			}
			return classElements;
		},

	  isIE6: function () {
			return ( document.all && (/msie 6./i).test(navigator.appVersion) && window.ActiveXObject ) ? true : false;
	  }
	
	}
	
};

// movideo_addEvent(element, type, handler)
// written by Dean Edwards, 2005
// with input from Tino Zijdel - crisp@xs4all.nl
// http://therealcrisp.xs4all.nl/upload/addEvent_dean.html
// Movideo.ToolTip changes:
// - added conditional wrapper
// - modified method names with 'movideo_' prefix to avoid conflicts
if (!window.movideo_addEvent || !movideo_addEvent.guid) {
	
	function movideo_addEvent (element, type, handler) {
		if (element.addEventListener) {
			element.addEventListener(type, handler, false);
		} else {
			if (!handler.$$guid) { handler.$$guid = movideo_addEvent.guid++; }
			if (!element.events) { element.events = {}; }
			var handlers = element.events[type];
			if (!handlers) {
				handlers = element.events[type] = {};
				if (element['on' + type]) { handlers[0] = element['on' + type]; }
				element['on' + type] = movideo_handleEvent;
			}
			handlers[handler.$$guid] = handler;
		}
	}
	
	movideo_addEvent.guid = 1;

	function movideo_removeEvent (element, type, handler) {
		if (element.removeEventListener) {
			element.removeEventListener(type, handler, false);
		} else if (element.events && element.events[type] && handler.$$guid) {
			delete element.events[type][handler.$$guid];
		}
	}

	function movideo_handleEvent (event) {
		event = event || movideo_fixEvent(window.event);
		var returnValue = true;
		var handlers = this.events[event.type];

		for (var i in handlers) {
			if (!Object.prototype[i]) {
				this.$$handler = handlers[i];
				if (this.$$handler(event) === false) { returnValue = false; }
			}
		}

		if (this.$$handler) { this.$$handler = null; }

		return returnValue;
	}

	function movideo_fixEvent (event) {
		event.preventDefault = movideo_fixEvent.preventDefault;
		event.stopPropagation = movideo_fixEvent.stopPropagation;
		return event;
	}
	
	movideo_fixEvent.preventDefault = function() {
		this.returnValue = false;
	};
	
	movideo_fixEvent.stopPropagation = function() {
		this.cancelBubble = true;
	};
	
}


// This little snippet fixes the problem that the onload attribute on the body-element will overwrite
// previous attached events on the window object for the onload event
if (!window.addEventListener) {
	document.onreadystatechange = function() {
		if (window.onload && window.onload != movideo_handleEvent) {
			movideo_addEvent(window, 'load', window.onload);
			window.onload = movideo_handleEvent;
		}
	};
}



/**
		SWFObject v2.2 <http://code.google.com/p/swfobject/> 
		is released under the MIT License <http://www.opensource.org/licenses/mit-license.php> 
*/
if (typeof swfobject == "undefined") var swfobject=function(){var D="undefined",r="object",S="Shockwave Flash",W="ShockwaveFlash.ShockwaveFlash",q="application/x-shockwave-flash",R="SWFObjectExprInst",x="onreadystatechange",O=window,j=document,t=navigator,T=false,U=[h],o=[],N=[],I=[],l,Q,E,B,J=false,a=false,n,G,m=true,M=function(){var aa=typeof j.getElementById!=D&&typeof j.getElementsByTagName!=D&&typeof j.createElement!=D,ah=t.userAgent.toLowerCase(),Y=t.platform.toLowerCase(),ae=Y?/win/.test(Y):/win/.test(ah),ac=Y?/mac/.test(Y):/mac/.test(ah),af=/webkit/.test(ah)?parseFloat(ah.replace(/^.*webkit\/(\d+(\.\d+)?).*$/,"$1")):false,X=!+"\v1",ag=[0,0,0],ab=null;if(typeof t.plugins!=D&&typeof t.plugins[S]==r){ab=t.plugins[S].description;if(ab&&!(typeof t.mimeTypes!=D&&t.mimeTypes[q]&&!t.mimeTypes[q].enabledPlugin)){T=true;X=false;ab=ab.replace(/^.*\s+(\S+\s+\S+$)/,"$1");ag[0]=parseInt(ab.replace(/^(.*)\..*$/,"$1"),10);ag[1]=parseInt(ab.replace(/^.*\.(.*)\s.*$/,"$1"),10);ag[2]=/[a-zA-Z]/.test(ab)?parseInt(ab.replace(/^.*[a-zA-Z]+(.*)$/,"$1"),10):0}}else{if(typeof O.ActiveXObject!=D){try{var ad=new ActiveXObject(W);if(ad){ab=ad.GetVariable("$version");if(ab){X=true;ab=ab.split(" ")[1].split(",");ag=[parseInt(ab[0],10),parseInt(ab[1],10),parseInt(ab[2],10)]}}}catch(Z){}}}return{w3:aa,pv:ag,wk:af,ie:X,win:ae,mac:ac}}(),k=function(){if(!M.w3){return}if((typeof j.readyState!=D&&j.readyState=="complete")||(typeof j.readyState==D&&(j.getElementsByTagName("body")[0]||j.body))){f()}if(!J){if(typeof j.addEventListener!=D){j.addEventListener("DOMContentLoaded",f,false)}if(M.ie&&M.win){j.attachEvent(x,function(){if(j.readyState=="complete"){j.detachEvent(x,arguments.callee);f()}});if(O==top){(function(){if(J){return}try{j.documentElement.doScroll("left")}catch(X){setTimeout(arguments.callee,0);return}f()})()}}if(M.wk){(function(){if(J){return}if(!/loaded|complete/.test(j.readyState)){setTimeout(arguments.callee,0);return}f()})()}s(f)}}();function f(){if(J){return}try{var Z=j.getElementsByTagName("body")[0].appendChild(C("span"));Z.parentNode.removeChild(Z)}catch(aa){return}J=true;var X=U.length;for(var Y=0;Y<X;Y++){U[Y]()}}function K(X){if(J){X()}else{U[U.length]=X}}function s(Y){if(typeof O.addEventListener!=D){O.addEventListener("load",Y,false)}else{if(typeof j.addEventListener!=D){j.addEventListener("load",Y,false)}else{if(typeof O.attachEvent!=D){i(O,"onload",Y)}else{if(typeof O.onload=="function"){var X=O.onload;O.onload=function(){X();Y()}}else{O.onload=Y}}}}}function h(){if(T){V()}else{H()}}function V(){var X=j.getElementsByTagName("body")[0];var aa=C(r);aa.setAttribute("type",q);var Z=X.appendChild(aa);if(Z){var Y=0;(function(){if(typeof Z.GetVariable!=D){var ab=Z.GetVariable("$version");if(ab){ab=ab.split(" ")[1].split(",");M.pv=[parseInt(ab[0],10),parseInt(ab[1],10),parseInt(ab[2],10)]}}else{if(Y<10){Y++;setTimeout(arguments.callee,10);return}}X.removeChild(aa);Z=null;H()})()}else{H()}}function H(){var ag=o.length;if(ag>0){for(var af=0;af<ag;af++){var Y=o[af].id;var ab=o[af].callbackFn;var aa={success:false,id:Y};if(M.pv[0]>0){var ae=c(Y);if(ae){if(F(o[af].swfVersion)&&!(M.wk&&M.wk<312)){w(Y,true);if(ab){aa.success=true;aa.ref=z(Y);ab(aa)}}else{if(o[af].expressInstall&&A()){var ai={};ai.data=o[af].expressInstall;ai.width=ae.getAttribute("width")||"0";ai.height=ae.getAttribute("height")||"0";if(ae.getAttribute("class")){ai.styleclass=ae.getAttribute("class")}if(ae.getAttribute("align")){ai.align=ae.getAttribute("align")}var ah={};var X=ae.getElementsByTagName("param");var ac=X.length;for(var ad=0;ad<ac;ad++){if(X[ad].getAttribute("name").toLowerCase()!="movie"){ah[X[ad].getAttribute("name")]=X[ad].getAttribute("value")}}P(ai,ah,Y,ab)}else{p(ae);if(ab){ab(aa)}}}}}else{w(Y,true);if(ab){var Z=z(Y);if(Z&&typeof Z.SetVariable!=D){aa.success=true;aa.ref=Z}ab(aa)}}}}}function z(aa){var X=null;var Y=c(aa);if(Y&&Y.nodeName=="OBJECT"){if(typeof Y.SetVariable!=D){X=Y}else{var Z=Y.getElementsByTagName(r)[0];if(Z){X=Z}}}return X}function A(){return !a&&F("6.0.65")&&(M.win||M.mac)&&!(M.wk&&M.wk<312)}function P(aa,ab,X,Z){a=true;E=Z||null;B={success:false,id:X};var ae=c(X);if(ae){if(ae.nodeName=="OBJECT"){l=g(ae);Q=null}else{l=ae;Q=X}aa.id=R;if(typeof aa.width==D||(!/%$/.test(aa.width)&&parseInt(aa.width,10)<310)){aa.width="310"}if(typeof aa.height==D||(!/%$/.test(aa.height)&&parseInt(aa.height,10)<137)){aa.height="137"}j.title=j.title.slice(0,47)+" - Flash Player Installation";var ad=M.ie&&M.win?"ActiveX":"PlugIn",ac="MMredirectURL="+O.location.toString().replace(/&/g,"%26")+"&MMplayerType="+ad+"&MMdoctitle="+j.title;if(typeof ab.flashvars!=D){ab.flashvars+="&"+ac}else{ab.flashvars=ac}if(M.ie&&M.win&&ae.readyState!=4){var Y=C("div");X+="SWFObjectNew";Y.setAttribute("id",X);ae.parentNode.insertBefore(Y,ae);ae.style.display="none";(function(){if(ae.readyState==4){ae.parentNode.removeChild(ae)}else{setTimeout(arguments.callee,10)}})()}u(aa,ab,X)}}function p(Y){if(M.ie&&M.win&&Y.readyState!=4){var X=C("div");Y.parentNode.insertBefore(X,Y);X.parentNode.replaceChild(g(Y),X);Y.style.display="none";(function(){if(Y.readyState==4){Y.parentNode.removeChild(Y)}else{setTimeout(arguments.callee,10)}})()}else{Y.parentNode.replaceChild(g(Y),Y)}}function g(ab){var aa=C("div");if(M.win&&M.ie){aa.innerHTML=ab.innerHTML}else{var Y=ab.getElementsByTagName(r)[0];if(Y){var ad=Y.childNodes;if(ad){var X=ad.length;for(var Z=0;Z<X;Z++){if(!(ad[Z].nodeType==1&&ad[Z].nodeName=="PARAM")&&!(ad[Z].nodeType==8)){aa.appendChild(ad[Z].cloneNode(true))}}}}}return aa}function u(ai,ag,Y){var X,aa=c(Y);if(M.wk&&M.wk<312){return X}if(aa){if(typeof ai.id==D){ai.id=Y}if(M.ie&&M.win){var ah="";for(var ae in ai){if(ai[ae]!=Object.prototype[ae]){if(ae.toLowerCase()=="data"){ag.movie=ai[ae]}else{if(ae.toLowerCase()=="styleclass"){ah+=' class="'+ai[ae]+'"'}else{if(ae.toLowerCase()!="classid"){ah+=" "+ae+'="'+ai[ae]+'"'}}}}}var af="";for(var ad in ag){if(ag[ad]!=Object.prototype[ad]){af+='<param name="'+ad+'" value="'+ag[ad]+'" />'}}aa.outerHTML='<object classid="clsid:D27CDB6E-AE6D-11cf-96B8-444553540000"'+ah+">"+af+"</object>";N[N.length]=ai.id;X=c(ai.id)}else{var Z=C(r);Z.setAttribute("type",q);for(var ac in ai){if(ai[ac]!=Object.prototype[ac]){if(ac.toLowerCase()=="styleclass"){Z.setAttribute("class",ai[ac])}else{if(ac.toLowerCase()!="classid"){Z.setAttribute(ac,ai[ac])}}}}for(var ab in ag){if(ag[ab]!=Object.prototype[ab]&&ab.toLowerCase()!="movie"){e(Z,ab,ag[ab])}}aa.parentNode.replaceChild(Z,aa);X=Z}}return X}function e(Z,X,Y){var aa=C("param");aa.setAttribute("name",X);aa.setAttribute("value",Y);Z.appendChild(aa)}function y(Y){var X=c(Y);if(X&&X.nodeName=="OBJECT"){if(M.ie&&M.win){X.style.display="none";(function(){if(X.readyState==4){b(Y)}else{setTimeout(arguments.callee,10)}})()}else{X.parentNode.removeChild(X)}}}function b(Z){var Y=c(Z);if(Y){for(var X in Y){if(typeof Y[X]=="function"){Y[X]=null}}Y.parentNode.removeChild(Y)}}function c(Z){var X=null;try{X=j.getElementById(Z)}catch(Y){}return X}function C(X){return j.createElement(X)}function i(Z,X,Y){Z.attachEvent(X,Y);I[I.length]=[Z,X,Y]}function F(Z){var Y=M.pv,X=Z.split(".");X[0]=parseInt(X[0],10);X[1]=parseInt(X[1],10)||0;X[2]=parseInt(X[2],10)||0;return(Y[0]>X[0]||(Y[0]==X[0]&&Y[1]>X[1])||(Y[0]==X[0]&&Y[1]==X[1]&&Y[2]>=X[2]))?true:false}function v(ac,Y,ad,ab){if(M.ie&&M.mac){return}var aa=j.getElementsByTagName("head")[0];if(!aa){return}var X=(ad&&typeof ad=="string")?ad:"screen";if(ab){n=null;G=null}if(!n||G!=X){var Z=C("style");Z.setAttribute("type","text/css");Z.setAttribute("media",X);n=aa.appendChild(Z);if(M.ie&&M.win&&typeof j.styleSheets!=D&&j.styleSheets.length>0){n=j.styleSheets[j.styleSheets.length-1]}G=X}if(M.ie&&M.win){if(n&&typeof n.addRule==r){n.addRule(ac,Y)}}else{if(n&&typeof j.createTextNode!=D){n.appendChild(j.createTextNode(ac+" {"+Y+"}"))}}}function w(Z,X){if(!m){return}var Y=X?"visible":"hidden";if(J&&c(Z)){c(Z).style.visibility=Y}else{v("#"+Z,"visibility:"+Y)}}function L(Y){var Z=/[\\\"<>\.;]/;var X=Z.exec(Y)!=null;return X&&typeof encodeURIComponent!=D?encodeURIComponent(Y):Y}var d=function(){if(M.ie&&M.win){window.attachEvent("onunload",function(){var ac=I.length;for(var ab=0;ab<ac;ab++){I[ab][0].detachEvent(I[ab][1],I[ab][2])}var Z=N.length;for(var aa=0;aa<Z;aa++){y(N[aa])}for(var Y in M){M[Y]=null}M=null;for(var X in swfobject){swfobject[X]=null}swfobject=null})}}();return{registerObject:function(ab,X,aa,Z){if(M.w3&&ab&&X){var Y={};Y.id=ab;Y.swfVersion=X;Y.expressInstall=aa;Y.callbackFn=Z;o[o.length]=Y;w(ab,false)}else{if(Z){Z({success:false,id:ab})}}},getObjectById:function(X){if(M.w3){return z(X)}},embedSWF:function(ab,ah,ae,ag,Y,aa,Z,ad,af,ac){var X={success:false,id:ah};if(M.w3&&!(M.wk&&M.wk<312)&&ab&&ah&&ae&&ag&&Y){w(ah,false);K(function(){ae+="";ag+="";var aj={};if(af&&typeof af===r){for(var al in af){aj[al]=af[al]}}aj.data=ab;aj.width=ae;aj.height=ag;var am={};if(ad&&typeof ad===r){for(var ak in ad){am[ak]=ad[ak]}}if(Z&&typeof Z===r){for(var ai in Z){if(typeof am.flashvars!=D){am.flashvars+="&"+ai+"="+Z[ai]}else{am.flashvars=ai+"="+Z[ai]}}}if(F(Y)){var an=u(aj,am,ah);if(aj.id==ah){w(ah,true)}X.success=true;X.ref=an}else{if(aa&&A()){aj.data=aa;P(aj,am,ah,ac);return}else{w(ah,true)}}if(ac){ac(X)}})}else{if(ac){ac(X)}}},switchOffAutoHideShow:function(){m=false},ua:M,getFlashPlayerVersion:function(){return{major:M.pv[0],minor:M.pv[1],release:M.pv[2]}},hasFlashPlayerVersion:F,createSWF:function(Z,Y,X){if(M.w3){return u(Z,Y,X)}else{return undefined}},showExpressInstall:function(Z,aa,X,Y){if(M.w3&&A()){P(Z,aa,X,Y)}},removeSWF:function(X){if(M.w3){y(X)}},createCSS:function(aa,Z,Y,X){if(M.w3){v(aa,Z,Y,X)}},addDomLoadEvent:K,addLoadEvent:s,getQueryParamValue:function(aa){var Z=j.location.search||j.location.hash;if(Z){if(/\?/.test(Z)){Z=Z.split("?")[1]}if(aa==null){return L(Z)}var Y=Z.split("&");for(var X=0;X<Y.length;X++){if(Y[X].substring(0,Y[X].indexOf("="))==aa){return L(Y[X].substring((Y[X].indexOf("=")+1)))}}}return""},expressInstallCallback:function(){if(a){var X=c(R);if(X&&l){X.parentNode.replaceChild(l,X);if(Q){w(Q,true);if(M.ie&&M.win){l.style.display="block"}}if(E){E(B)}}a=false}}}}();



/**
	@ CREATE SCRIPT OBJECT
		Creates and returns script object out of last known <script> element, this one.
		Run inline to ensure it gets the last known <script> el, which this one as this file is parsed.
		http://feather.elektrum.org/book/src.html
*/
function createScriptObj () {
	var scripts = document.getElementsByTagName('script');
	return scripts[scripts.length-1];
}
var MovideoAutoLinkerScriptObj = createScriptObj(); // assign script object to global var



/**
	@ SETUP AUTOLINKER & TOOLTIPS
		Adds onload event listener to run setup functions for Movideo.AutoLinker and Movideo.ToolTips
*/
movideo_addEvent(window,"load", function () {
	Movideo.AutoLinker.setup();
});
