/* 	VMM.Timeline.TimeNav.js
    TimeNav
	This class handles the bottom timeline navigation.
	It requires the VMM.Util class and VMM.Date class
================================================== */

if(typeof VMM.Timeline != 'undefined' && typeof VMM.Timeline.TimeNav == 'undefined') {
	
	VMM.Timeline.TimeNav = function(parent, content_width, content_height) {
		trace("VMM.Timeline.TimeNav");
		
		var $timenav, $content, $time, $timeintervalminor, $timeinterval, $timeintervalmajor, $timebackground, 
			$timeintervalbackground, $timenavline, $timenavindicator, $timeintervalminor_minor, $toolbar, $zoomin, $zoomout, $dragslide,
			config					= VMM.Timeline.Config,
			row_height,
			events					= {},
			timespan				= {},
			layout					= parent,
			data					= [],
			era_markers				= [],
			markers					= [],
			interval_array			= [],
			interval_major_array	= [],
			tags					= [],
			current_marker			= 0,
			_active					= false,
			eras,
			content,
			timeouts = {
				interval_position:	""
			},
			timenav_pos = {
				left:				"",
				visible: {
					left:			"",
					right:			""
				}
			},
			timelookup = {
				day:			24,
				month:			12,
				year:			10,
				hour:			60,
				minute:			60,
				second:			1000,
				decade:			10,
				century:		100,
				millenium:		1000,
				age:			1000000,
				epoch:			10000000,
				era:			100000000,
				eon:			500000000,
				week:			4.34812141,
				days_in_month:	30.4368499,
				days_in_week:	7,
				weeks_in_month:	4.34812141,
				weeks_in_year:	52.177457,
				days_in_year:	365.242199,
				hours_in_day:	24
			},
			dateFractionBrowser = {
				day:			86400000,
				week:			7,
				month:			30.4166666667,
				year:			12,
				hour:			24,
				minute:			1440,
				second:			86400,
				decade:			10,
				century:		100,
				millenium:		1000,
				age:			1000000,
				epoch:			10000000,
				era:			100000000,
				eon:			500000000
			},
			interval = {
				type:			"year",
				number:			10,
				first:			1970,
				last:			2011,
				multiplier:		100,
				classname:		"_idd",
				interval_type:	"interval"
			},
			interval_major = {
				type:			"year",
				number:			10,
				first:			1970,
				last:			2011,
				multiplier:		100,
				classname:		"major",
				interval_type:	"interval major"
			},
			interval_macro = {
				type:			"year",
				number:			10,
				first:			1970,
				last:			2011,
				multiplier:		100,
				classname:		"_dd_minor",
				interval_type:	"interval minor"
			},
			interval_calc = {
				day: {},
				month: {},
				year: {},
				hour: {},
				minute: {},
				second: {},
				decade: {},
				century: {},
				millenium: {},
				week: {},
				age: {},
				epoch: {},
				era: {},
				eon: {}
			};
		
		
		/* ADD to Config
		================================================== */
		row_height			=	config.nav.marker.height/2;
		config.nav.rows = {
			full:				['0px', row_height*2, row_height*4],
			half:				['0px', row_height*2, row_height*4],
			current:			[]
		}
		
		if (content_width != null && content_width != "") {
			config.nav.width	= 	content_width;
		} 
		if (content_height != null && content_height != "") {
			config.nav.height	= 	content_height;
		}
		
		/* INIT
		================================================== */
		this.init = function(d,e) {
			trace('VMM.Timeline.TimeNav init');
			// need to evaluate d
			// some function to determine type of data and prepare it
			if(typeof d != 'undefined') {
				this.setData(d, e);
			} else {
				trace("WAITING ON DATA");
			}
		};
		
		/* GETTERS AND SETTERS
		================================================== */
		this.setData = function(d,e) {
			if(typeof d != 'undefined') {
				data = {};
				data = d;
				eras = e;
				build();
			} else{
				trace("NO DATA");
			}
		};
		
		this.setSize = function(w, h) {
			if (w != null) {config.width = w};
			if (h != null) {config.height = h};
			if (_active) {
				reSize();
			}

			
		}
		
		this.setMarker = function(n, ease, duration, fast) {
			goToMarker(n, ease, duration);
		}
		
		this.getCurrentNumber = function() {
			return current_marker;
		}
		
		/* ON EVENT
		================================================== */
		
		function onConfigSet() {
			trace("onConfigSet");
		};
		
		function reSize(firstrun) {
			config.nav.constraint.left = (config.width/2);
			config.nav.constraint.right = config.nav.constraint.right_min - (config.width/2);
			$dragslide.updateConstraint(config.nav.constraint);
			
			VMM.Lib.css($timenavline, "left", Math.round(config.width/2)+2);
			VMM.Lib.css($timenavindicator, "left", Math.round(config.width/2)-8);
			goToMarker(config.current_slide, config.ease, config.duration, true, firstrun);
		};
		
		function upDate() {
			VMM.fireEvent(layout, "UPDATE");
		}
		
		function onZoomIn() {
			
			$dragslide.cancelSlide();
			if (config.nav.multiplier.current > config.nav.multiplier.min) {
				if (config.nav.multiplier.current <= 1) {
					config.nav.multiplier.current = config.nav.multiplier.current - .25;
				} else {
					if (config.nav.multiplier.current > 5) {
						if (config.nav.multiplier.current > 16) {
							config.nav.multiplier.current = Math.round(config.nav.multiplier.current - 10);
						} else {
							config.nav.multiplier.current = Math.round(config.nav.multiplier.current - 4);
						}
					} else {
						config.nav.multiplier.current = Math.round(config.nav.multiplier.current - 1);
					}
					
				}
				if (config.nav.multiplier.current <= 0) {
					config.nav.multiplier.current = config.nav.multiplier.min;
				}
				refreshTimeline();
			}
		}
		
		function onZoomOut() {
			$dragslide.cancelSlide();
			if (config.nav.multiplier.current < config.nav.multiplier.max) {
				if (config.nav.multiplier.current > 4) {
					if (config.nav.multiplier.current > 16) {
						config.nav.multiplier.current = Math.round(config.nav.multiplier.current + 10);
					} else {
						config.nav.multiplier.current = Math.round(config.nav.multiplier.current + 4);
					}
				} else {
					config.nav.multiplier.current = Math.round(config.nav.multiplier.current + 1);
				}
				
				if (config.nav.multiplier.current >= config.nav.multiplier.max) {
					config.nav.multiplier.current = config.nav.multiplier.max;
				}
				refreshTimeline();
			}
		}
		
		function onBackHome(e) {
			$dragslide.cancelSlide();
			goToMarker(0);
			upDate();
		}
		
		function onMouseScroll(e) {
			var delta		= 0,
				scroll_to	= 0;
			if (!e) {
				e = window.event;
			}
			if (e.originalEvent) {
				e = e.originalEvent;
			}
			
			// Browsers unable to differntiate between up/down and left/right scrolling
			/*
			if (e.wheelDelta) {
				delta = e.wheelDelta/6;
			} else if (e.detail) {
				delta = -e.detail*12;
			}
			*/
			
			// Webkit and browsers able to differntiate between up/down and left/right scrolling
			if (typeof e.wheelDeltaX != 'undefined' ) {
				delta = e.wheelDeltaY/6;
				if (Math.abs(e.wheelDeltaX) > Math.abs(e.wheelDeltaY)) {
					delta = e.wheelDeltaX/6;
				} else {
					//delta = e.wheelDeltaY/6;
					delta = 0;
				}
			}
			if (delta) {
				if (e.preventDefault) {
					 e.preventDefault();
				}
				e.returnValue = false;
			}
			// Stop from scrolling too far
			scroll_to = VMM.Lib.position($timenav).left + delta;
			
			if (scroll_to > config.nav.constraint.left) {
				scroll_to = config.width/2;
			} else if (scroll_to < config.nav.constraint.right) {
				scroll_to = config.nav.constraint.right;
			}
			
			//VMM.Lib.stop($timenav);
			//VMM.Lib.animate($timenav, config.duration/2, "linear", {"left": scroll_to});
			VMM.Lib.css($timenav, "left", scroll_to);	
		}
		
		function refreshTimeline() {
			trace("config.nav.multiplier " + config.nav.multiplier.current);
			positionMarkers(true);
			positionEras(true);
			positionInterval($timeinterval, interval_array, true, true);
			positionInterval($timeintervalmajor, interval_major_array, true);
			config.nav.constraint.left = (config.width/2);
			config.nav.constraint.right = config.nav.constraint.right_min - (config.width/2);
			$dragslide.updateConstraint(config.nav.constraint);
		};
		
		/* MARKER EVENTS
		================================================== */
		function onMarkerClick(e) {
			$dragslide.cancelSlide();
			goToMarker(e.data.number);
			upDate();
		};
		
		function onMarkerHover(e) {
			VMM.Lib.toggleClass(e.data.elem, "zFront");
		};
		
		function goToMarker(n, ease, duration, fast, firstrun) {
			trace("GO TO MARKER");
			var _ease		= config.ease,
				_duration	= config.duration,
				is_last		= false,
				is_first	= false;
			
			current_marker = 	n;
			
			timenav_pos.left			= (config.width/2) - markers[current_marker].pos_left
			timenav_pos.visible.left	= Math.abs(timenav_pos.left) - 100;
			timenav_pos.visible.right	= Math.abs(timenav_pos.left) + config.width + 100;
			
			if (current_marker == 0) {
				is_first = true;
			}
			if (current_marker +1 == markers.length) {
				is_last = true
			}
			if (ease != null && ease != "") {_ease = ease};
			if (duration != null && duration != "") {_duration = duration};
			
			// set marker style
			for(var i = 0; i < markers.length; i++) {
				VMM.Lib.removeClass(markers[i].marker, "selected");
				if (data[i].selection){
					data[i].selection.selected = false;
				}
			}
			
			if (config.start_page && markers[0].type == "start") {
				VMM.Lib.visible(markers[0].marker, false);
				VMM.Lib.addClass(markers[0].marker, "start");
			}
			
			VMM.Lib.addClass(markers[current_marker].marker, "selected");
			if (data[current_marker].selection){
				data[current_marker].selection.selected = true;
			}
			if (config.scope){
				config.scope.$apply();
			}
			
			// ANIMATE MARKER
			VMM.Lib.stop($timenav);
			VMM.Lib.animate($timenav, _duration, _ease, {"left": timenav_pos.left});
			
		}
		
		/* TOUCH EVENTS
		================================================== */
		function onTouchUpdate(e, b) {
			VMM.Lib.animate($timenav, b.time/2, config.ease, {"left": b.left});
		};
		
		/* CALCULATIONS
		================================================== */
		function averageMarkerPositionDistance() {
			var last_pos	= 0,
				pos			= 0,
				pos_dif		= 0,
				mp_diff		= [],
				i			= 0;
			
			for(i = 0; i < markers.length; i++) {
				if (data[i].type == "start") {
					
				} else {
					var _pos = positionOnTimeline(interval, markers[i].relative_pos),
					last_pos = pos;
					pos = _pos.begin;
					pos_dif = pos - last_pos;
					mp_diff.push(pos_dif);
				}
			}
			return VMM.Util.average(mp_diff).mean;
		}
		
		function averageDateDistance() {
			var last_dd			= 0,
				dd				= 0,
				_dd				= "",
				date_dif		= 0,
				date_diffs		= [],
				is_first_date	= true,
				i				= 0;
			
			for(i = 0; i < data.length; i++) {
				if (data[i].type == "start") {
					trace("DATA DATE IS START")
				} else {
					_dd			= data[i].startdate;
					last_dd		= dd;
					dd			= _dd;
					date_dif	= dd - last_dd;
					date_diffs.push(date_dif);
				}
			}
			
			return VMM.Util.average(date_diffs);
		}
		
		function calculateMultiplier() {
			var temp_multiplier	= config.nav.multiplier.current,
				i				= 0;
				
			for(i = 0; i < temp_multiplier; i++) {
				if (averageMarkerPositionDistance() < 75) {
					if (config.nav.multiplier.current > 1) {
						config.nav.multiplier.current = (config.nav.multiplier.current - 1);
					}
				}
			}
			
		}
		
		function calculateInterval() {
			// NEED TO REWRITE ALL OF THIS
			var _first								= getDateFractions(data[0].startdate),
				_last								= getDateFractions(data[data.length - 1].enddate);
			
			// EON
			interval_calc.eon.type					=	"eon";
			interval_calc.eon.first					=	_first.eons;
			interval_calc.eon.base					=	Math.floor(_first.eons);
			interval_calc.eon.last					=	_last.eons;
			interval_calc.eon.number				=	timespan.eons;
			interval_calc.eon.multiplier		 	=	timelookup.eons;
			interval_calc.eon.minor					=	timelookup.eons;
			
			// ERA
			interval_calc.era.type					=	"era";
			interval_calc.era.first					=	_first.eras;
			interval_calc.era.base					=	Math.floor(_first.eras);
			interval_calc.era.last					=	_last.eras;
			interval_calc.era.number				=	timespan.eras;
			interval_calc.era.multiplier		 	=	timelookup.eras;
			interval_calc.era.minor					=	timelookup.eras;
			
			// EPOCH
			interval_calc.epoch.type				=	"epoch";
			interval_calc.epoch.first				=	_first.epochs;
			interval_calc.epoch.base				=	Math.floor(_first.epochs);
			interval_calc.epoch.last				=	_last.epochs;
			interval_calc.epoch.number				=	timespan.epochs;
			interval_calc.epoch.multiplier		 	=	timelookup.epochs;
			interval_calc.epoch.minor				=	timelookup.epochs;
			
			// AGE
			interval_calc.age.type					=	"age";
			interval_calc.age.first					=	_first.ages;
			interval_calc.age.base					=	Math.floor(_first.ages);
			interval_calc.age.last					=	_last.ages;
			interval_calc.age.number				=	timespan.ages;
			interval_calc.age.multiplier		 	=	timelookup.ages;
			interval_calc.age.minor					=	timelookup.ages;
			
			// MILLENIUM
			interval_calc.millenium.type 			=	"millenium";
			interval_calc.millenium.first			=	_first.milleniums;
			interval_calc.millenium.base			=	Math.floor(_first.milleniums);
			interval_calc.millenium.last			=	_last.milleniums;
			interval_calc.millenium.number			=	timespan.milleniums;
			interval_calc.millenium.multiplier	 	=	timelookup.millenium;
			interval_calc.millenium.minor			=	timelookup.millenium;
			
			// CENTURY
			interval_calc.century.type 				= "century";
			interval_calc.century.first 			= _first.centuries;
			interval_calc.century.base 				= Math.floor(_first.centuries);
			interval_calc.century.last 				= _last.centuries;
			interval_calc.century.number 			= timespan.centuries;
			interval_calc.century.multiplier	 	= timelookup.century;
			interval_calc.century.minor 			= timelookup.century;
			
			// DECADE
			interval_calc.decade.type 				= "decade";
			interval_calc.decade.first 				= _first.decades;
			interval_calc.decade.base 				= Math.floor(_first.decades);
			interval_calc.decade.last 				= _last.decades;
			interval_calc.decade.number 			= timespan.decades;
			interval_calc.decade.multiplier 		= timelookup.decade;
			interval_calc.decade.minor 				= timelookup.decade;
			
			// YEAR
			interval_calc.year.type					= "year";
			interval_calc.year.first 				= _first.years;
			interval_calc.year.base 				= Math.floor(_first.years);
			interval_calc.year.last					= _last.years;
			interval_calc.year.number 				= timespan.years;
			interval_calc.year.multiplier 			= 1;
			interval_calc.year.minor 				= timelookup.month;
			
			// MONTH
			interval_calc.month.type 				= "month";
			interval_calc.month.first 				= _first.months;
			interval_calc.month.base 				= Math.floor(_first.months);
			interval_calc.month.last 				= _last.months;
			interval_calc.month.number 				= timespan.months;
			interval_calc.month.multiplier 			= 1;
			interval_calc.month.minor 				= Math.round(timelookup.week);
			
			// WEEK
			// NOT DONE
			interval_calc.week.type 				= "week";
			interval_calc.week.first 				= _first.weeks;
			interval_calc.week.base 				= Math.floor(_first.weeks);
			interval_calc.week.last 				= _last.weeks;
			interval_calc.week.number 				= timespan.weeks;
			interval_calc.week.multiplier 			= 1;
			interval_calc.week.minor 				= 7;
			
			// DAY
			interval_calc.day.type 					= "day";
			interval_calc.day.first 				= _first.days;
			interval_calc.day.base	 				= Math.floor(_first.days);
			interval_calc.day.last 					= _last.days;
			interval_calc.day.number 				= timespan.days;
			interval_calc.day.multiplier 			= 1;
			interval_calc.day.minor 				= 24;
			
			// HOUR
			interval_calc.hour.type 				= "hour";
			interval_calc.hour.first 				= _first.hours;
			interval_calc.hour.base 				= Math.floor(_first.hours);
			interval_calc.hour.last 				= _last.hours;
			interval_calc.hour.number 				= timespan.hours;
			interval_calc.hour.multiplier 			= 1;
			interval_calc.hour.minor 				= 60;
			
			// MINUTE
			interval_calc.minute.type 				= "minute";
			interval_calc.minute.first 				= _first.minutes;
			interval_calc.minute.base 				= Math.floor(_first.minutes);
			interval_calc.minute.last 				= _last.minutes;
			interval_calc.minute.number 			= timespan.minutes;
			interval_calc.minute.multiplier 		= 1;
			interval_calc.minute.minor 				= 60;
			
			// SECOND
			interval_calc.second.type 				= "decade";
			interval_calc.second.first 				= _first.seconds;
			interval_calc.second.base 				= Math.floor(_first.seconds);
			interval_calc.second.last 				= _last.seconds;
			interval_calc.second.number 			= timespan.seconds;
			interval_calc.second.multiplier 		= 1;
			interval_calc.second.minor 				= 10;
		}
		
		function getDateFractions(the_date, is_utc) {
			
			var _time = {};
			_time.days			=		the_date		/	dateFractionBrowser.day;
			_time.weeks 		=		_time.days		/	dateFractionBrowser.week;
			_time.months 		=		_time.days		/	dateFractionBrowser.month;
			_time.years 		=		_time.months 	/	dateFractionBrowser.year;
			_time.hours 		=		_time.days		*	dateFractionBrowser.hour;
			_time.minutes 		=		_time.days		*	dateFractionBrowser.minute;
			_time.seconds 		=		_time.days		*	dateFractionBrowser.second;
			_time.decades 		=		_time.years		/	dateFractionBrowser.decade;
			_time.centuries 	=		_time.years		/	dateFractionBrowser.century;
			_time.milleniums 	=		_time.years		/	dateFractionBrowser.millenium;
			_time.ages			=		_time.years		/	dateFractionBrowser.age;
			_time.epochs		=		_time.years		/	dateFractionBrowser.epoch;
			_time.eras			=		_time.years		/	dateFractionBrowser.era;
			_time.eons			=		_time.years		/	dateFractionBrowser.eon;
			
			/*
			trace("AGES "		 + 		_time.ages);
			trace("EPOCHS "		 + 		_time.epochs);
			trace("MILLENIUMS "  + 		_time.milleniums);
			trace("CENTURIES "	 + 		_time.centuries);
			trace("DECADES "	 + 		_time.decades);
			trace("YEARS "		 + 		_time.years);
			trace("MONTHS "		 + 		_time.months);
			trace("WEEKS "		 + 		_time.weeks);
			trace("DAYS "		 + 		_time.days);
			trace("HOURS "		 + 		_time.hours);
			trace("MINUTES "	 + 		_time.minutes);
			trace("SECONDS "	 + 		_time.seconds);
			*/
			return _time;
		}
		
		/*	POSITION
			Positions elements on the timeline based on date
			relative to the calculated interval
		================================================== */
		function positionRelative(_interval, first, last) {
			var _first,
				_last,
				_type			= _interval.type,
				timerelative = {
					start:		"",
					end:		"",
					type:		_type
				};
			
			/* FIRST
			================================================== */
			_first					= getDateFractions(first);
			timerelative.start		= first.months;
			
			if (_type == "eon") {
				timerelative.start	= _first.eons;
			} else if (_type == "era") {
				timerelative.start	= _first.eras;
			} else if (_type == "epoch") {
				timerelative.start	= _first.epochs;
			} else if (_type == "age") {
				timerelative.start	= _first.ages;
			} else if (_type == "millenium") {
				timerelative.start	= first.milleniums;
			} else if (_type == "century") {
				timerelative.start	= _first.centuries;
			} else if (_type == "decade") {
				timerelative.start	= _first.decades;
			} else if (_type == "year") {
				timerelative.start	= _first.years;
			} else if (_type == "month") {
				timerelative.start	= _first.months;
			} else if (_type == "week") {
				timerelative.start	= _first.weeks;
			} else if (_type == "day") {
				timerelative.start	= _first.days;
			} else if (_type == "hour") {
				timerelative.start	= _first.hours;
			} else if (_type == "minute") {
				timerelative.start	= _first.minutes;
			}
			
			/* LAST
			================================================== */
			if (type.of(last) == "date") {
				
				_last					= getDateFractions(last);
				timerelative.end		= last.months;
				
				if (_type == "eon") {
					timerelative.end	= _last.eons;
				} else if (_type == "era") {
					timerelative.end	= _last.eras;
				} else if (_type == "epoch") {
					timerelative.end	= _last.epochs;
				} else if (_type == "age") {
					timerelative.end	= _last.ages;
				} else if (_type == "millenium") {
					timerelative.end	= last.milleniums;
				} else if (_type == "century") {
					timerelative.end	= _last.centuries;
				} else if (_type == "decade") {
					timerelative.end	= _last.decades;
				} else if (_type == "year") {
					timerelative.end	= _last.years;
				} else if (_type == "month") {
					timerelative.end	= _last.months;
				} else if (_type == "week") {
					timerelative.end	= _last.weeks;
				} else if (_type == "day") {
					timerelative.end	= _last.days;
				} else if (_type == "hour") {
					timerelative.end	= _last.hours;
				} else if (_type == "minute") {
					timerelative.end	= _last.minutes;
				}
				
			} else {
				
				timerelative.end		= timerelative.start;
				
			}
			
			return timerelative
		}
		
		function positionOnTimeline(the_interval, timerelative) {
			return {
				begin:	(timerelative.start	-	interval.base) * (config.nav.interval_width / config.nav.multiplier.current), 
				end:	(timerelative.end	-	interval.base) * (config.nav.interval_width / config.nav.multiplier.current)
			};
		}
		
		function positionMarkers(is_animated) {
			
			var row						= 2,
				previous_pos			= 0,
				pos_offset				= -2,
				row_depth				= 0,
				row_depth_sub			= 0,
				line_last_height_pos	= 150,
				line_height				= 6,
				cur_mark				= 0,
				in_view_margin			= config.width,
				pos_cache_array			= [],
				pos_cache_max			= 6,
				in_view = {
					left:				timenav_pos.visible.left - in_view_margin,
					right:				timenav_pos.visible.right + in_view_margin
				},
				i						= 0,
				k						= 0;
				
			config.nav.minor_width = config.width;
			
			VMM.Lib.removeClass(".flag", "row1");
			VMM.Lib.removeClass(".flag", "row2");
			VMM.Lib.removeClass(".flag", "row3");
			
			for(i = 0; i < markers.length; i++) {
				
				var line,
					marker				= markers[i],
					pos					= positionOnTimeline(interval, markers[i].relative_pos),
					row_pos				= 0,
					is_in_view			= false,
					pos_cache_obj		= {id: i, pos: 0, row: 0},
					pos_cache_close		= 0;
				
				
				// COMPENSATE FOR DATES BEING POITIONED IN THE MIDDLE
				pos.begin				= Math.round(pos.begin +  pos_offset);
				pos.end					= Math.round(pos.end + pos_offset);
				line					= Math.round(pos.end - pos.begin);
				marker.pos_left			= pos.begin;
				
				if (current_marker == i) {
					timenav_pos.left			= (config.width/2) - pos;
					timenav_pos.visible.left	= Math.abs(timenav_pos.left);
					timenav_pos.visible.right	= Math.abs(timenav_pos.left) + config.width;
					in_view.left				= timenav_pos.visible.left - in_view_margin;
					in_view.right				= timenav_pos.visible.right + in_view_margin;
				}
				
				if (Math.abs(pos.begin) >= in_view.left && Math.abs(pos.begin) <= in_view.right ) {
					is_in_view = true;
				}
				
				// APPLY POSITION TO MARKER
				if (is_animated) {
					VMM.Lib.stop(marker.marker);
					VMM.Lib.animate(marker.marker, config.duration/2, config.ease, {"left": pos.begin});
				} else {
					VMM.Lib.stop(marker.marker);
					VMM.Lib.css(marker.marker, "left", pos.begin);
				}
				
				if (i == current_marker) {
					cur_mark = pos.begin;
				}
				
				// EVENT LENGTH LINE
				if (line > 5) {
					VMM.Lib.css(marker.lineevent, "height", line_height);
					VMM.Lib.css(marker.lineevent, "top", line_last_height_pos);
					if (is_animated) {
						VMM.Lib.animate(marker.lineevent, config.duration/2, config.ease, {"width": line});
					} else {
						VMM.Lib.css(marker.lineevent, "width", line);
					}
				}
				
				// CONTROL ROW POSITION
				if (tags.length > 0) {
					
					for (k = 0; k < tags.length; k++) {
						if (k < config.nav.rows.current.length) {
							if (marker.tag == tags[k]) {
								row = k;
								if (k == config.nav.rows.current.length - 1) {
									trace("ON LAST ROW");
									VMM.Lib.addClass(marker.flag, "flag-small-last");
								}
							}
						}
					}
					row_pos = config.nav.rows.current[row];
				} else {
					
					if (pos.begin - previous_pos.begin < (config.nav.marker.width + config.spacing)) {
						if (row < config.nav.rows.current.length - 1) {
							row ++;
						
						} else {
							row = 0;
							row_depth ++;
						}
					} else {
						row_depth = 1;
						row = 1;
					}
					row_pos = config.nav.rows.current[row];
					
				}
				
				// SET LAST MARKER POSITION
				previous_pos = pos;
				
				// POSITION CACHE
				pos_cache_obj.pos = pos;
				pos_cache_obj.row = row;
				pos_cache_array.push(pos_cache_obj);
				if (pos_cache_array.length > pos_cache_max) {
					VMM.Util.removeRange(pos_cache_array,0);
				}
				
				//if (is_animated && is_in_view) {
				if (is_animated) {
					VMM.Lib.stop(marker.flag);
					VMM.Lib.animate(marker.flag, config.duration, config.ease, {"top": row_pos});
				} else {
					VMM.Lib.stop(marker.flag);
					VMM.Lib.css(marker.flag, "top", row_pos);
				}
				VMM.Lib.css(marker.dot, "top", row_pos);
				VMM.Lib.css(marker.line, "top", row_pos);
				VMM.Lib.css(marker.line, "height", config.nav.rows.current[config.nav.rows.current.length-1] + config.nav.rows.current[1] - row_pos);
				if (data[i].color){
					VMM.Lib.css(marker.dot, "background", data[i].color);
					VMM.Lib.css(marker.line, "background", data[i].color);
				}
				
				// IS THE MARKER A REPRESENTATION OF A START SCREEN?
				if (config.start_page && markers[i].type == "start") {
					VMM.Lib.visible(marker.marker, false);
					
				}
				
				if (pos > config.nav.minor_width) {
					config.nav.minor_width = pos;
				}
				
				if (pos < config.nav.minor_left) {
					config.nav.minor_left = pos;
				}
				
			}
			
			// ANIMATE THE TIMELINE TO ADJUST TO CHANGES
			if (is_animated) {
				VMM.Lib.stop($timenav);
				VMM.Lib.animate($timenav, config.duration/2, config.ease, {"left": (config.width/2) - (cur_mark)});
			} else {
				
			}
			
			//VMM.Lib.delay_animate(config.duration, $timenav, config.duration/2, config.ease, {"left": (config.width/2) - (cur_mark)});
			
		
		}
		
		function positionEras(is_animated) {
			var i	= 0,
				p	= 0;
				
			for(i = 0; i < era_markers.length; i++) {
				var era			= era_markers[i],
					pos			= positionOnTimeline(interval, era.relative_pos),
					row_pos		= 0,
					row			= 0,
					era_height	= config.nav.marker.height * config.nav.rows.full.length,
					era_length	= pos.end - pos.begin;
					
				// CONTROL ROW POSITION
				if (era.tag != "") {
					era_height = (config.nav.marker.height * config.nav.rows.full.length) / config.nav.rows.current.length;
					for (p = 0; p < tags.length; p++) {
						if (p < config.nav.rows.current.length) {
							if (era.tag == tags[p]) {
								row = p;
							}
						}
					}
					row_pos = config.nav.rows.current[row];
					
				} else {
					row_pos = -1;
				}
				
				// APPLY POSITION TO MARKER
				if (is_animated) {
					VMM.Lib.stop(era.content);
					VMM.Lib.stop(era.text_content);
					VMM.Lib.animate(era.content, config.duration/2, config.ease, {"top": row_pos, "left": pos.begin, "width": era_length, "height":era_height});
					VMM.Lib.animate(era.text_content, config.duration/2, config.ease, {"left": pos.begin});
				} else {
					VMM.Lib.stop(era.content);
					VMM.Lib.stop(era.text_content);
					VMM.Lib.css(era.content, "left", pos.begin);
					VMM.Lib.css(era.content, "width", era_length);
					VMM.Lib.css(era.content, "height", era_height);
					VMM.Lib.css(era.content, "top", row_pos);
					VMM.Lib.css(era.text_content, "left", pos.begin);
					
				}

			}
		}
		
		function positionInterval(the_main_element, the_intervals, is_animated, is_minor) {
			
			var last_position		= 0,
				last_position_major	= 0,
				//in_view_margin		= (config.nav.minor_width/config.nav.multiplier.current)/2,
				in_view_margin		= config.width,
				in_view = {
					left:			timenav_pos.visible.left - in_view_margin,
					right:			timenav_pos.visible.right + in_view_margin
				}
				not_too_many		= true,
				i					= 0;
			
			config.nav.minor_left = 0;
				
			if (the_intervals.length > 100) {
				not_too_many = false;
				trace("TOO MANY " + the_intervals.length);
			}
			
			
			for(i = 0; i < the_intervals.length; i++) {
				var _interval			= the_intervals[i].element,
					_interval_date		= the_intervals[i].date,
					_interval_visible	= the_intervals[i].visible,
					_pos				= positionOnTimeline(interval, the_intervals[i].relative_pos),
					pos					= _pos.begin,
					_animation			= the_intervals[i].animation,
					is_visible			= true,
					is_in_view			= false,
					pos_offset			= 50;
				
				
				_animation.pos			= pos;
				_animation.animate		= false;
				
				if (Math.abs(pos) >= in_view.left && Math.abs(pos) <= in_view.right ) {
					is_in_view = true;
				}
				
				if (true) {
					
					// CONDENSE WHAT IS DISPLAYED
					if (config.nav.multiplier.current > 16 && is_minor) {
						is_visible = false;
					} else {
						if ((pos - last_position) < 65 ) {
							if ((pos - last_position) < 35 ) {
								if (i%4 == 0) {
									if (pos == 0) {
										is_visible = false;
									}
								} else {
									is_visible = false;
								}
							} else {
								if (!VMM.Util.isEven(i)) {
									is_visible = false;
								}
							}
						}
					}
					
					if (is_visible) {
						if (the_intervals[i].is_detached) {
							VMM.Lib.append(the_main_element, _interval);
							the_intervals[i].is_detached = false;
						}
					} else {
						the_intervals[i].is_detached = true;
						VMM.Lib.detach(_interval);
					}
					
					
					if (_interval_visible) {
						if (!is_visible) {
							_animation.opacity	= "0";
							if (is_animated && not_too_many) {
								_animation.animate	= true;
							}
							the_intervals[i].interval_visible = false;
						} else {
							_animation.opacity	= "100";
							if (is_animated && is_in_view) {
								_animation.animate	= true;
							}
						}
					} else {
						_animation.opacity	= "100";
						if (is_visible) {
							if (is_animated && not_too_many) {
								_animation.animate	= true;
							} else {
								if (is_animated && is_in_view) {
									_animation.animate	= true;
								}
							}
							the_intervals[i].interval_visible = true;
						} else {
							if (is_animated && not_too_many) {
								_animation.animate	= true;
							}
						}
					}
				
					last_position = pos;
				
					if (pos > config.nav.minor_width) {
						config.nav.minor_width = pos;
					}
					
					if (pos < config.nav.minor_left) {
						config.nav.minor_left = pos;
					}
					
				}
				
				if (_animation.animate) {
					VMM.Lib.animate(_interval, config.duration/2, config.ease, {opacity: _animation.opacity, left: _animation.pos});
				} else {
					VMM.Lib.css(_interval, "opacity", _animation.opacity);
					VMM.Lib.css(_interval, "left", pos);
				}
			}
			
			config.nav.constraint.right_min = -(config.nav.minor_width)+(config.width);
			config.nav.constraint.right = config.nav.constraint.right_min + (config.width/2);
			
			VMM.Lib.css($timeintervalminor_minor, "left", config.nav.minor_left - (config.width)/2);
			VMM.Lib.width($timeintervalminor_minor, (config.nav.minor_width)+(config.width) + Math.abs(config.nav.minor_left) );
			
		}
		
		/* Interval Elements
		================================================== */
		function createIntervalElements(_interval, _array, _element_parent) {
			
			var inc_time			= 0,
				_first_run			= true,
				_last_pos			= 0,
				_largest_pos		= 0,
				_timezone_offset,
				_first_date,
				_last_date,
				int_number			= Math.ceil(_interval.number) + 2,
				firefox = {
					flag:			false,
					offset:			0
				},
				i					= 0;
			
			VMM.attachElement(_element_parent, "");
			
			_interval.date = new Date(data[0].startdate.getFullYear(), 0, 1, 0,0,0);
			_timezone_offset = _interval.date.getTimezoneOffset();
			
			for(i = 0; i < int_number; i++) {
				trace(_interval.type);
				var _is_year			= false,
					int_obj = {
						element: 		VMM.appendAndGetElement(_element_parent, "<div>", _interval.classname),
						date: 			new Date(data[0].startdate.getFullYear(), 0, 1, 0,0,0),
						visible: 		false,
						date_string:	"",
						type: 			_interval.interval_type,
						relative_pos:	0,
						is_detached:	false,
						animation: {
							animate:	false,
							pos:		"",
							opacity:	"100"
						
						}
					};
				
				if (_interval.type == "eon") {
					if (_first_run) {
						_first_date = Math.floor(data[0].startdate.getFullYear() / 500000000) * 500000000;
					}
					int_obj.date.setFullYear(_first_date + (inc_time * 500000000));
					_is_year = true;
				} else if (_interval.type == "era") {
					if (_first_run) {
						_first_date = Math.floor(data[0].startdate.getFullYear() / 100000000) * 100000000;
					}
					int_obj.date.setFullYear(_first_date + (inc_time * 100000000));
					_is_year = true;
				} else if (_interval.type == "epoch") {
					if (_first_run) {
						_first_date = Math.floor(data[0].startdate.getFullYear() / 10000000) * 10000000
					}
					int_obj.date.setFullYear(_first_date + (inc_time * 10000000));
					_is_year = true;
				} else if (_interval.type == "age") {
					if (_first_run) {
						_first_date = Math.floor(data[0].startdate.getFullYear() / 1000000) * 1000000
					}
					int_obj.date.setFullYear(_first_date + (inc_time * 1000000));
					_is_year = true;
				} else if (_interval.type == "millenium") {
					if (_first_run) {
						_first_date = Math.floor(data[0].startdate.getFullYear() / 1000) * 1000;
					}
					int_obj.date.setFullYear(_first_date + (inc_time * 1000));
					_is_year = true;
				} else if (_interval.type == "century") {
					if (_first_run) {
						_first_date = Math.floor(data[0].startdate.getFullYear() / 100) * 100
					}
					int_obj.date.setFullYear(_first_date + (inc_time * 100));
					_is_year = true;
				} else if (_interval.type == "decade") {
					if (_first_run) {
						_first_date = Math.floor(data[0].startdate.getFullYear() / 10) * 10;
					}
					int_obj.date.setFullYear(_first_date + (inc_time * 10));
					_is_year = true;
				} else if (_interval.type == "year") {
					if (_first_run) {
						_first_date = data[0].startdate.getFullYear();
					}
					int_obj.date.setFullYear(_first_date + inc_time);
					_is_year = true;
				} else if (_interval.type == "month") {
					if (_first_run) {
						_first_date = data[0].startdate.getMonth();
					}
					int_obj.date.setMonth(_first_date + inc_time);
				} else if (_interval.type == "week") {
					if (_first_run) {
						_first_date = data[0].startdate.getMonth();
					}
					int_obj.date.setMonth(data[0].startdate.getMonth());
					int_obj.date.setDate(_first_date + (inc_time * 7) );
				} else if (_interval.type == "day") {
					if (_first_run) {
						_first_date = data[0].startdate.getDate();
					}
					int_obj.date.setMonth(data[0].startdate.getMonth());
					int_obj.date.setDate(_first_date + inc_time);
				} else if (_interval.type == "hour") {
					if (_first_run) {
						_first_date = data[0].startdate.getHours();
					}
					int_obj.date.setMonth(data[0].startdate.getMonth());
					int_obj.date.setDate(data[0].startdate.getDate());
					int_obj.date.setHours(_first_date + inc_time);
				} else if (_interval.type == "minute") {
					if (_first_run) {
						_first_date = data[0].startdate.getMinutes();
					}
					int_obj.date.setMonth(data[0].startdate.getMonth());
					int_obj.date.setDate(data[0].startdate.getDate());
					int_obj.date.setHours(data[0].startdate.getHours());
					int_obj.date.setMinutes(_first_date + inc_time);
				} else if (_interval.type == "second") {
					if (_first_run) {
						_first_date = data[0].startdate.getSeconds();
					}
					int_obj.date.setMonth(data[0].startdate.getMonth());
					int_obj.date.setDate(data[0].startdate.getDate());
					int_obj.date.setHours(data[0].startdate.getHours());
					int_obj.date.setMinutes(data[0].startdate.getMinutes());
					int_obj.date.setSeconds(_first_date + inc_time);
				}	else if (_interval.type == "millisecond") {
					if (_first_run) {
						_first_date = data[0].startdate.getMilliseconds();
					}
					int_obj.date.setMonth(data[0].startdate.getMonth());
					int_obj.date.setDate(data[0].startdate.getDate());
					int_obj.date.setHours(data[0].startdate.getHours());
					int_obj.date.setMinutes(data[0].startdate.getMinutes());
					int_obj.date.setSeconds(data[0].startdate.getSeconds());
					int_obj.date.setMilliseconds(_first_date + inc_time);
				}
				
				// FIX WEIRD FIREFOX BUG FOR GMT TIME FORMATTING
				if (VMM.Browser.browser == "Firefox") {
					if (int_obj.date.getFullYear() == "1970" && int_obj.date.getTimezoneOffset() != _timezone_offset) {
						
						trace("FIREFOX 1970 TIMEZONE OFFSET " + int_obj.date.getTimezoneOffset() + " SHOULD BE " + _timezone_offset);
						trace(_interval.type + " " + _interval.date);
						
						// try and fix firefox bug, if not the flag will catch it
						firefox.offset = (int_obj.date.getTimezoneOffset()/60);
						firefox.flag = true;
						int_obj.date.setHours(int_obj.date.getHours() + firefox.offset );
						
					} else if (firefox.flag) {
						// catch the bug the second time around
						firefox.flag = false;
						int_obj.date.setHours(int_obj.date.getHours() + firefox.offset );
						if (_is_year) {
							firefox.flag = true;
						}
					}
					
				}
				
				if (_is_year) {
					if ( int_obj.date.getFullYear() < 0 ) {
						int_obj.date_string = 	Math.abs( int_obj.date.getFullYear() ).toString() + " B.C.";
					} else {
						int_obj.date_string = int_obj.date.getFullYear();
					}
				} else {
					int_obj.date_string = VMM.Date.prettyDate(int_obj.date, true);
				}
				
				// Increment Time
				inc_time = inc_time + 1;
				
				// No longer first run
				_first_run = false;
				
				int_obj.relative_pos = positionRelative(interval, int_obj.date);
				_last_pos = int_obj.relative_pos.begin;
				if (int_obj.relative_pos.begin > _largest_pos) {
					_largest_pos = int_obj.relative_pos.begin;
				}
				
				// Add the time string to the element and position it.
				VMM.appendElement(int_obj.element, int_obj.date_string);
				VMM.Lib.css(int_obj.element, "text-indent", -(VMM.Lib.width(int_obj.element)/2));
				VMM.Lib.css(int_obj.element, "opacity", "0");
				
				// add the interval element to the array
				_array.push(int_obj);
				
			}
			
			VMM.Lib.width($timeintervalminor_minor, _largest_pos);
			
			positionInterval(_element_parent, _array);
			
			
			
		}
		
		/* BUILD
		================================================== */
		function build() {
			var i	= 0,
				j	= 0;
				
			VMM.attachElement(layout, "");
			
			$timenav					= VMM.appendAndGetElement(layout, "<div>", "timenav");
			$content					= VMM.appendAndGetElement($timenav, "<div>", "content");
			$time						= VMM.appendAndGetElement($timenav, "<div>", "time");
			$timeintervalminor			= VMM.appendAndGetElement($time, "<div>", "time-interval-minor");
			$timeintervalminor_minor	= VMM.appendAndGetElement($timeintervalminor, "<div>", "minor");
			$timeintervalmajor			= VMM.appendAndGetElement($time, "<div>", "time-interval-major");
			$timeinterval				= VMM.appendAndGetElement($time, "<div>", "time-interval");
			$timebackground				= VMM.appendAndGetElement(layout, "<div>", "timenav-background");
			$timenavline				= VMM.appendAndGetElement($timebackground, "<div>", "timenav-line");
			$timenavindicator			= VMM.appendAndGetElement($timebackground, "<div>", "timenav-indicator");
			$timeintervalbackground		= VMM.appendAndGetElement($timebackground, "<div>", "timenav-interval-background", "<div class='top-highlight'></div>");
			$toolbar					= VMM.appendAndGetElement(layout, "<div>", "vco-toolbar");
			
			
			buildInterval();
			buildMarkers();
			buildEras();
			calculateMultiplier();
			positionMarkers(false);
			positionEras();
			
			positionInterval($timeinterval, interval_array, false, true);
			positionInterval($timeintervalmajor, interval_major_array);
			
			
			if (config.start_page) {
				$backhome = VMM.appendAndGetElement($toolbar, "<div>", "fonticon icon-timeline back-home");
				VMM.bindEvent(".back-home", onBackHome, "click");
				VMM.Lib.attribute($backhome, "title", VMM.master_config.language.messages.return_to_title);
				VMM.Lib.attribute($backhome, "rel", "timeline-tooltip");
				
			}
			
			
			// MAKE TIMELINE DRAGGABLE/TOUCHABLE
			$dragslide = new VMM.DragSlider;
			$dragslide.createPanel(layout, $timenav, config.nav.constraint, config.touch);
			
			
			
			if (config.touch && config.start_page) {
				VMM.Lib.addClass($toolbar, "touch");
				VMM.Lib.css($toolbar, "top", 55);
				VMM.Lib.css($toolbar, "left", 10);
			} else {
				if (config.start_page) {
					VMM.Lib.css($toolbar, "top", 27);
				}
				$zoomin		= VMM.appendAndGetElement($toolbar, "<div>", "fonticon icon-zoom-in zoom-in");
				$zoomout	= VMM.appendAndGetElement($toolbar, "<div>", "fonticon icon-zoom-out zoom-out");
				// ZOOM EVENTS
				VMM.bindEvent($zoomin, onZoomIn, "click");
				VMM.bindEvent($zoomout, onZoomOut, "click");
				// TOOLTIP
				VMM.Lib.attribute($zoomin, "title", VMM.master_config.language.messages.expand_timeline);
				VMM.Lib.attribute($zoomin, "rel", "timeline-tooltip");
				VMM.Lib.attribute($zoomout, "title", VMM.master_config.language.messages.contract_timeline);
				VMM.Lib.attribute($zoomout, "rel", "timeline-tooltip");
				$toolbar.tooltip({selector: "div[rel=timeline-tooltip]", placement: "right"});
				
				
				// MOUSE EVENTS
				VMM.bindEvent(layout, onMouseScroll, 'DOMMouseScroll');
				VMM.bindEvent(layout, onMouseScroll, 'mousewheel');
			}
			
			
			
			// USER CONFIGURABLE ADJUSTMENT TO DEFAULT ZOOM
			if (config.nav.zoom.adjust != 0) {
				if (config.nav.zoom.adjust < 0) {
					for(i = 0; i < Math.abs(config.nav.zoom.adjust); i++) {
						onZoomOut();
					}
				} else {
					for(j = 0; j < config.nav.zoom.adjust; j++) {
						onZoomIn();
					}
				}
			}
			
			//VMM.fireEvent(layout, "LOADED");
			_active = true;
			
			reSize(true);
			VMM.fireEvent(layout, "LOADED");
			
		};
		
		function buildInterval() {
			var i	= 0,
				j	= 0;
			// CALCULATE INTERVAL
			timespan = getDateFractions((data[data.length - 1].enddate) - (data[0].startdate), true);
			trace(timespan);
			calculateInterval();

			/* DETERMINE DEFAULT INTERVAL TYPE
				millenium, ages, epoch, era and eon are not optimized yet. They may never be.
			================================================== */
			/*
			if (timespan.eons				>		data.length / config.nav.density) {
				interval					=		interval_calc.eon;
				interval_major				=		interval_calc.eon;
				interval_macro				=		interval_calc.era;
			} else if (timespan.eras		>		data.length / config.nav.density) {
				interval					=		interval_calc.era;
				interval_major				=		interval_calc.eon;
				interval_macro				=		interval_calc.epoch;
			} else if (timespan.epochs		>		data.length / config.nav.density) {
				interval					=		interval_calc.epoch;
				interval_major				=		interval_calc.era;
				interval_macro				=		interval_calc.age;
			} else if (timespan.ages		>		data.length / config.nav.density) {
				interval					=		interval_calc.ages;
				interval_major				=		interval_calc.epoch;
				interval_macro				=		interval_calc.millenium;
			} else if (timespan.milleniums			>		data.length / config.nav.density) {
				interval					=		interval_calc.millenium;
				interval_major				=		interval_calc.age;
				interval_macro				=		interval_calc.century;
			} else 
			*/
			if (timespan.centuries			>		data.length / config.nav.density) {
				interval					=		interval_calc.century;
				interval_major				=		interval_calc.millenium;
				interval_macro				=		interval_calc.decade;
			} else if (timespan.decades		>		data.length / config.nav.density) {
				interval					=		interval_calc.decade;
				interval_major				=		interval_calc.century;
				interval_macro				=		interval_calc.year;
			} else if (timespan.years		>		data.length / config.nav.density) {	
				interval					=		interval_calc.year;
				interval_major				=		interval_calc.decade;
				interval_macro				=		interval_calc.month;
			} else if (timespan.months		>		data.length / config.nav.density) {
				interval					=		interval_calc.month;
				interval_major				=		interval_calc.year;
				interval_macro				=		interval_calc.day;
			} else if (timespan.days		>		data.length / config.nav.density) {
				interval					=		interval_calc.day;
				interval_major				=		interval_calc.month;
				interval_macro				=		interval_calc.hour;
			} else if (timespan.hours		>		data.length / config.nav.density) {
				interval					=		interval_calc.hour;
				interval_major				=		interval_calc.day;
				interval_macro				=		interval_calc.minute;
			} else if (timespan.minutes		>		data.length / config.nav.density) {
				interval					=		interval_calc.minute;
				interval_major				=		interval_calc.hour;
				interval_macro				=		interval_calc.second;
			} else if (timespan.seconds		>		data.length / config.nav.density) {
				interval					=		interval_calc.second;
				interval_major				=		interval_calc.minute;
				interval_macro				=		interval_calc.second;
			} else {
				trace("NO IDEA WHAT THE TYPE SHOULD BE");
				interval					=		interval_calc.day;
				interval_major				=		interval_calc.month;
				interval_macro				=		interval_calc.hour;
			}
			
			trace("INTERVAL TYPE: " + interval.type);
			trace("INTERVAL MAJOR TYPE: " + interval_major.type);
			
			createIntervalElements(interval, interval_array, $timeinterval);
			createIntervalElements(interval_major, interval_major_array, $timeintervalmajor);
			
			// Cleanup duplicate interval elements between normal and major
			for(i = 0; i < interval_array.length; i++) {
				for(j = 0; j < interval_major_array.length; j++) {
					if (interval_array[i].date_string == interval_major_array[j].date_string) {
						VMM.attachElement(interval_array[i].element, "");
					}
				}
			}
		}
		
		function buildMarkers() {
			
			var row			= 2,
				lpos		= 0,
				row_depth	= 0,
				i			= 0,
				k			= 0,
				l			= 0;
				
				
			markers			= [];
			era_markers		= [];
			
			for(i = 0; i < data.length; i++) {
				
				var _marker,
					_marker_flag,
					_marker_content,
					_marker_dot,
					_marker_line,
					_marker_line_event,
					_marker_obj,
					_marker_title		= "",
					has_title			= false;
				
				//Popover text
				if (data[i].startdate){
					var startDate = new Date(data[i].startdate).toDateString();
					var popoverText = 'Date:\t' + startDate;
					if (data[i].status){
						popoverText = popoverText + '\nStatus:\t' + data[i].status;
					}
					if (data[i].timeFrame){
						popoverText = popoverText + '\nTimeframe:\t' + data[i].timeFrame;
					}
					VMM.Lib.css(_marker_flag, "popover", popoverText);
				}
				
				_marker					= VMM.appendAndGetElement($content, "<div>", "marker");
				_marker_flag			= VMM.appendAndGetElement(_marker, "<div popover='" + (popoverText ? popoverText : "") + "' popover-trigger='mouseenter'>", "flag");				_marker_content			= VMM.appendAndGetElement(_marker_flag, "<div>", "flag-content");
				_marker_dot				= VMM.appendAndGetElement(_marker, "<div>", "dot");
				_marker_line			= VMM.appendAndGetElement(_marker, "<div>", "line");
				_marker_line_event		= VMM.appendAndGetElement(_marker_line, "<div>", "event-line");
				_marker_relative_pos	= positionRelative(interval, data[i].startdate, data[i].enddate);
				_marker_thumb			= "";
				
				// THUMBNAIL
				if (data[i].asset != null && data[i].asset != "") {
					VMM.appendElement(_marker_content, VMM.MediaElement.thumbnail(data[i].asset, 24, 24, data[i].uniqueid));
				} else {
					VMM.appendElement(_marker_content, "<div style='margin-right:7px;height:auto;width:2px;float:left;'></div>");
				}
				
				// ADD DATE AND TITLE
				if (data[i].title == "" || data[i].title == " " ) {
					trace("TITLE NOTHING")
					if (typeof data[i].slug != 'undefined' && data[i].slug != "") {
						trace("SLUG")
						_marker_title = VMM.Util.untagify(data[i].slug);
						has_title = true;
					} else {
						var m = VMM.MediaType(data[i].asset.media);
						if (m.type == "quote" || m.type == "unknown") {
							_marker_title = VMM.Util.untagify(m.id);
							has_title = true;
						} else {
							has_title = false;
						}
					}
				} else if (data[i].title != "" || data[i].title != " ") {
					trace(data[i].title)
					_marker_title = VMM.Util.untagify(data[i].title);
					has_title = true;
				} else {
					trace("TITLE SLUG NOT FOUND " + data[i].slug)
				}
				
				if (has_title) {
					VMM.appendElement(_marker_content, "<h3>" + _marker_title + "</h3>");
				} else {
					VMM.appendElement(_marker_content, "<h3>" + _marker_title + "</h3>");
					VMM.appendElement(_marker_content, "<h3 id='marker_content_" + data[i].uniqueid + "'>" + _marker_title + "</h3>");
				}
				
				if(data[i].status === "Completed") {
					VMM.appendElement(_marker_content, '<span class="icon-small-checkmark"></span>');
				}

				// ADD ID
				VMM.Lib.attr(_marker, "id", ( "marker_" + data[i].uniqueid).toString() );
				
				// MARKER CLICK
				VMM.bindEvent(_marker_flag, onMarkerClick, "", {number: i});
				VMM.bindEvent(_marker_flag, onMarkerHover, "mouseenter mouseleave", {number: i, elem:_marker_flag});
				
				_marker_obj = {
					marker: 			_marker,
					flag: 				_marker_flag,
					lineevent: 			_marker_line_event,
					type: 				"marker",
					full:				true,
					relative_pos:		_marker_relative_pos,
					tag:				data[i].tag,
					pos_left:			0,
					line:				_marker_line,
					dot:				_marker_dot
				};
				
				
				if (data[i].type == "start") {
					trace("BUILD MARKER HAS START PAGE");
					config.start_page = true;
					_marker_obj.type = "start";
				}
				
				if (data[i].type == "storify") {
					_marker_obj.type = "storify";
				}
				
				
				if (data[i].tag) {
					tags.push(data[i].tag);
				}
				
				markers.push(_marker_obj);
				
				
				
			}
			
			// CREATE TAGS
			tags = VMM.Util.deDupeArray(tags);
			if (tags.length > 3) {
				config.nav.rows.current = config.nav.rows.half;
			} else {
				config.nav.rows.current = config.nav.rows.full;
			}
			for(k = 0; k < tags.length; k++) {
				if (k < config.nav.rows.current.length) {
					var tag_element = VMM.appendAndGetElement($timebackground, "<div>", "timenav-tag");
					VMM.Lib.addClass(tag_element, "timenav-tag-row-" + (k+1));
					if (tags.length > 3) {
						VMM.Lib.addClass(tag_element, "timenav-tag-size-half");
					} else {
						VMM.Lib.addClass(tag_element, "timenav-tag-size-full");
					}
					VMM.appendElement(tag_element, "<div><h3>" + tags[k] + "</h3></div>");
				}
				
			}
			
			// RESIZE FLAGS IF NEEDED
			if (tags.length > 3) {
				for(l = 0; l < markers.length; l++) {
					VMM.Lib.addClass(markers[l].flag, "flag-small");
					markers[l].full = false;
				}
			}

			
		}
		
		function buildEras() {
			var number_of_colors	= 6,
				current_color		= 0,
				j					= 0;
			// CREATE ERAS
			for(j = 0; j < eras.length; j++) {
				var era = {
						content: 			VMM.appendAndGetElement($content, "<div>", "era"),
						text_content: 		VMM.appendAndGetElement($timeinterval, "<div>", "era"),
						startdate: 			VMM.Date.parse(eras[j].startDate),
						enddate: 			VMM.Date.parse(eras[j].endDate),
						title: 				eras[j].headline,
						uniqueid: 			VMM.Util.unique_ID(6),
						tag:				"",
						relative_pos:	 	""
					},
					st						= VMM.Date.prettyDate(era.startdate),
					en						= VMM.Date.prettyDate(era.enddate),
					era_text				= "<div>&nbsp;</div>";
					
				if (typeof eras[j].tag != "undefined") {
					era.tag = eras[j].tag;
				}
				
				era.relative_pos = positionRelative(interval, era.startdate, era.enddate);
				
				VMM.Lib.attr(era.content, "id", era.uniqueid);
				VMM.Lib.attr(era.text_content, "id", era.uniqueid + "_text");
				
				// Background Color
				VMM.Lib.addClass(era.content, "era"+(current_color+1));
				VMM.Lib.addClass(era.text_content, "era"+(current_color+1));
				
				if (current_color < number_of_colors) {
					current_color++;
				} else {
					current_color = 0;
				}
				
				VMM.appendElement(era.content, era_text);
				VMM.appendElement(era.text_content, VMM.Util.unlinkify(era.title));
				
				era_markers.push(era);
				
			}
			
		}
		
	};
	
}
