thewisemonkey.net Open in urlscan Pro
91.238.165.233  Public Scan

URL: http://thewisemonkey.net/javascript/main.js
Submission: On July 10 via api from CH — Scanned from GB

Form analysis 0 forms found in the DOM

Text Content

/*jslint browser: true*/
/*  Compress: http://closure-compiler.appspot.com/home   */

//==================================  MAIN CONFIG =====================================
var wmconfig = {
	dev_mode : false,
	width_declared_desktop : 550,
	desktop_loaded : false,
	wguru_loaded : false,
	resizing : false,
	
	loadWindguru : function(){
		//return;
		if( !wmconfig.wguru_loaded ){
			var $load_area=$("#wg_load_area");
			$load_area.html("<h2>Loading...</h2>");		
			$.get("/windguru_js_loader.html", function(data){
				$load_area.html(data);
				wmconfig.wguru_loaded = true;
			});
		}	
	},
	wgInit : function(){
		//windguru manual loader - DIV using new way from windguru
		$("#wg_loader_button").click(function(e){
			e.preventDefault();
			wmconfig.loadWindguru();
		});		
	},
			
	mobileOrDesktopSet : function(){
		if (document.body.offsetWidth > wmconfig.width_declared_desktop) { 
			wmconfig.is_mobile=false; 
			wmconfig.is_desktop=true;
		} else { 
			wmconfig.is_mobile=true; 
			wmconfig.is_desktop=false;
		}
	},

	loadCssJs : function(type,filename){
		//load extra desktop stylesheet or js (if not already present)
		//BROWSERS ARE DEPRECATING THIS NOW - are no longer using.
		if(type==="css"){
			if(!$('link[rel*=style][href="'+filename+'"]').length) {
				$('head').append('<link rel="stylesheet" type="text/css" href="'+filename+'">');
			}
		} else if(type==="js"){
			if(!$('script[type*=javascript][href="'+filename+'"]').length) {
				$('head').append('<script type="text/javascript" src="'+filename+'"></script>');
			}
		}
	},

	desktopInit : function(){
		//return;	
		if(!wmconfig.desktop_loaded && wmconfig.is_desktop) {
			//load extra desktop stylesheet and js if not already present
			//wmconfig.loadCssJs("css","/css/extra_desktop.css");	
			//wmconfig.loadCssJs("js","/javascript/extra_desktop.js"); --had to stop this as it was coming up as deprecated in browsers. loading always now in header.
			//load extra desktop html if not there
			var $edt=$('#extra_desktop');
			if ($edt.is(':empty')){
				$edt.load("/x_extra_desktop.php",function(){
					extra_desktop.init();
				});
			}
			//fontface
			//$("head").append("<link href='http://fonts.googleapis.com/css?family=Play:400,700' rel='stylesheet' type='text/css'>");
			wmconfig.desktop_loaded=true;  //to prevent loading it more than once
		}
	},
	
	mobileInit : function(){
		// hides iphone nav bar- not sure why the 0 timeout is necessary
		if (navigator.userAgent.indexOf('iPhone') !== -1) { setTimeout(function(){ window.scrollTo(0, 1); }, 200); }
		//jsy met left right
		$("#object_jsymet").click(function(){
			var $src_trgt = $("#object_jsymet .w_inner");
			var width=$(this).width();
			if($src_trgt.scrollLeft() >= width) { width = -width; }
			$src_trgt.animate({scrollLeft: width}, 'fast');
		});		
	},

	init : function(){
		$.ajaxSetup({ cache:false });
		wmconfig.mobileOrDesktopSet();
		comments.init();
		obs.setVarsFromJsonHtml("1stload");
		sites.init();
		timeline.init();
		refresh.init();
		wmconfig.wgInit();

		if(wmconfig.is_desktop) {
			wmconfig.desktopInit();
		} else {
			wmconfig.mobileInit();
		}

		$(window).resize(function() {			
			//first time it's called will be the start of the resizing
			if(!wmconfig.resizing) {
				wmconfig.resizing = true;
				wmconfig.was_dt_b4_resize = wmconfig.is_desktop;
				//if the window is resized temp stop animating the sites otherwise there are clashes with the responsive css
				sites.pulseStop();
				sites.removeAllPopups();
				$("body").removeClass("anim");	//disable animation while resizing		
			}

			//if the timer is already running clear it
		    if(this.resizeTO) { clearTimeout(this.resizeTO); }
			//set a timer to restart animation after a short delay. As it is continuously being reset above when resizing it will only occur after resizing stops.
		    this.resizeTO = setTimeout(function() {
				wmconfig.resizing = false;
				sites.pulseStart();
				wmconfig.mobileOrDesktopSet();
				if (!wmconfig.was_dt_b4_resize && wmconfig.is_desktop) {
					wmconfig.desktopInit();
					timeline.winResized();	
				}
				$("body").addClass("anim");
		    }, 500);
		});
	
	}	
};


//==================================  COMMENTS =====================================
var comments = {
	init : function(){
		comments.$sc = $("#scene_comments");
		comments.$wm = $("#hdr_comments");
	},
	
	mkySet : function(text){
		comments.$wm.text(text);
	},
	
	mkyRevert : function(){
		//monkey comment revert
		comments.$wm.text(obs.monkey_comments);
	},
	
	
	chide : function(){
		//reset to current temporal also? but we'd see it change as it slides down
		comments.$sc.addClass("hidden");
	},

	sceneSet : function(this_text) {
		//assume we want to show it also.
		comments.$sc.text(this_text).removeClass("hidden");
	},

	countdown : function(narrative, counter, func){
		var sec_txt = "seconds";
		if (counter===1){ sec_txt = "second"; }
		comments.$sc.removeClass("hidden").text( narrative + " in " + counter+ " "+sec_txt );
		counter=counter-1;
		if (counter>-1){
			window.setTimeout(function(){ comments.countdown(narrative, counter, func); } ,1000);			
		} else {
			func.call();
		}
	}
};


//==================================  OBSERVATIONS =====================================
var obs = {
	ref_timer : false,
	
	setVarsFromJsonHtml : function(when){
		//DEV:HAVE JSON DATA AS A separate text load rather than stuffed in dummy div?
		var jdata = jQuery.parseJSON( $("#current_data").attr("json") );  //look for ajax json data in custom attribute of ajax div returned

		if(jdata) {
			if(jdata.temporal) { obs.temporal = jdata.temporal; }	
			if(jdata.wind_speed) { obs.wind_speed = jdata.wind_speed; }
			if(jdata.wind_direction) { obs.wind_direction = jdata.wind_direction; }
			if(jdata.swell_direction) { obs.swell_direction = jdata.swell_direction; }
			if(jdata.tide_height) { obs.tide_height = jdata.tide_height; }
			if(jdata.monkey_comments) { obs.monkey_comments = jdata.monkey_comments; }
			if(jdata.wind_comments) { obs.wind_comments = jdata.wind_comments; }
			
			//wind & swell arrows
			$("#arrow").css({"transform": "rotate("+obs.wind_direction+"deg)"});
			if(obs.swell_direction == "?"){
				$("#arrow_swell").hide();
			} else {
				$("#arrow_swell").show().css({"transform": "rotate("+obs.swell_direction+"deg)"});
			}
			
			
			//update monkey comments and time
			if(jdata.newtime) { $("#nav_now").text(jdata.newtime); }
			comments.sceneSet(obs.wind_comments);
			comments.mkySet(obs.monkey_comments);

			//SPORTS on/off
			if(wmconfig.is_desktop) {
				if( jdata.sport_SUP==="1" ) { $("#hdr_sport_sup").show(); } else { $("#hdr_sport_sup").hide(); }
				if( jdata.sport_PG==="1" ) { $("#hdr_sport_pg").show(); } else { $("#hdr_sport_pg").hide(); }
				if( jdata.sport_KS==="1" ) { $("#hdr_sport_ks").show(); } else { $("#hdr_sport_ks").hide(); }
				if( jdata.sport_WS==="1" ) { $("#hdr_sport_ws").show(); } else { $("#hdr_sport_ws").hide(); }	
			}
		
			//update daylight bodyclass
			if ( jdata.bodyclass) {
				$("body").removeClass("live history future dawn day dusk night");
				$("body").addClass(jdata.bodyclass);
			}
						
			$("#current_data").remove(); // get rid of DOM element containing json data so that if another is added there is no conflict
			//$("body").trigger("obs_updated"); //trigger custom event
		}
	},

	refresh : function(announce){
		//default announce var to yes (it just gives a visual cue that refesh is happening)
		announce = (announce == null) ? "yes" : announce;
		//if (announce == "options") { url += "?xoptions_refresh=true"; }  //options changed so show day!!
		if (announce==="yes") {
			obs.refreshAnounce(0,true);
		}
						
		//get updated data via ajax
		$.ajax({
			url: "/x_live_refresh.php",
			cache: false,
			success: function(html){
				//data is now loaded so add to page
				obs.refreshComplete();
				$("#refresh_area").html(html);
				obs.setVarsFromJsonHtml(); //get new data and update
				timeline.updateFromObs(); //update live timeline tile
				sites.pulseRefresh(); //pulse any sites which are active
				//if (announce==="options") {
				//	$(".spot.off").addClass("was_off").removeClass("off"); //show all sites	
				//}
			} //of success
		}); //of ajax		
	},

	refreshAnounce : function(stage,wipe_day) {
		stage = (stage == null) ? 0 : stage; //inital stage is zero when first run
		//start it off
		//comments.sceneSet("Stage "+stage);
		
		if(stage===0){
			clearTimeout(obs.ref_timer); 
			//refresh.pause(); 
			//DEV: pausing and then resuming mucks up timline click pause - if we need to reintroduce this we could do a check for temporal first
			
			if(wipe_day) {
				$("body").removeClass("dawn day dusk night");
				comments.sceneSet("Refreshing..");
			}
			$("#obs_time").html("Updating now...");
			$("#object_wind").fadeTo(3000,0.33);
			obs.ref_timer = window.setTimeout(function(){ obs.refreshAnounce(1,false); },6000);				
		} else if(stage===1){
			$("#wind_obs").html("<div id='obs_loading'>Still loading...</div>");
			$("#object_wind").fadeTo(3000,1);
			$("#obs_loading").fadeTo(3000,0.33);
			obs.ref_timer = window.setTimeout(function(){ obs.refreshAnounce(2); },6000);	
			
		} else if(stage===2){
			$("#wind_obs").html("<div id='obs_loading'>Network slow?</div>");
			$("#obs_loading").fadeTo(5000,1);
			obs.ref_timer = window.setTimeout(function(){ obs.refreshAnounce(3); },5000);
		} else if(stage===3){
			$("#wind_obs").html("<div id='obs_loading'><a href='/'>Try full reset?</a></div>");	
		}
				
	},

	refreshComplete : function() {
		clearTimeout(obs.ref_timer);  
		$("#object_wind, #obs_loading").stop().removeAttr('style');
		//refresh.resume();
		//DEV: pausing and then resuming mucks up timline click pause - if we need to reintroduce this we could do a check for temporal first
	}	
};


//==================================  SITES =====================================
var sites = {
	delay_timer : false,
	delay_ms : 200,
	pulsing : false,
	pulse_timer : false,	
	pulse_rate : 1000,
	
	init : function(){
		sites.addEvents();
		sites.pulseStart();
	},
	
	ensureOnScreen : function($site_obj){
	    var
			site_height = $site_obj.outerHeight(),
		    site_width = $site_obj.innerWidth(),
		    site_position = $site_obj.position(),   
		    site_top = site_position.top,       
		    site_left = site_position.left,
			window_height = $("#viewport").height(),
			window_width = $(window).width(),
		    site_bottom = window_height - (site_top+site_height),
			site_right = window_width - (site_left+site_width);

	    //is site too high and overlapping the header?    
	    if ( site_top < 0 ) { 
	    	$site_obj.css({'top':'0px'});    
	    //is site too low and therefore off the bottom of the screen?
	    } else if ( site_bottom < 0 ) {		
	    	var new_site_top = site_top + site_bottom; //yep so move it up 
	    	if (new_site_top < 0) { new_site_top=0; } //but make sure it's not off the top of the screen
//alert("window_height:"+window_height+", site_top:"+ site_top + ", site_height:"+ site_height + ", site_bottom:"+site_bottom + ", new_site_top:" +new_site_top );
	    	$site_obj.css({'top':new_site_top+'px'}); //move to new position
	    }

	    //is site too far right and therfore off the side of the screen?   
	    if ( site_right < 10 ) { 
	    	var new_site_left = site_left + site_right -10;  //yep so move it left (inc borders)
	    	if (new_site_left < 0) { new_site_left=0; }  //but make sure it's not off the left of the screen
	    	$site_obj.css({'left' : new_site_left+'px'});  //move to new position
		// too left?
	    } else if (site_left < 0) {
	    	$site_obj.css({'left' : '0px'});
	    }			
	},
	
	removeAllPopups : function() {
	  $(".site_popup").remove();
	},

	getPopup : function(site_code, e) {
		sites.removeAllPopups(); //get rid of any other popups that may be open
		//get popup info via ajax
		var url = "/x_site_popup.php?site_code="+site_code+"&wind_speed="+obs.wind_speed+"&wind_direction="+obs.wind_direction +"&tide_height="+obs.tide_height +"&is_desktop="+wmconfig.is_desktop;
			
		$.ajax({
			url: url,
			cache: false,
			success: function(html){
				//data is now loaded so add to page
				sites.hideThrobber();
				$("#panel_obs").append(html);
				var $site_obj = $("#site" + site_code); //the added popup
				//then fade in and move a bit 
				var offset = $(e.target).offset();
				$site_obj.fadeIn("fast")
					.css('left', offset.left+3).css('top', offset.top-$("#header").height()-15); 
				if (wmconfig.is_desktop) { sites.ensureOnScreen($site_obj); }
			} //of success
		});
	},
	
	showThrobber : function(e) {
		var offset = $(e.target).offset();
		$("#throbber").css('left', offset.left-15).css('top', offset.top-$("#header").height()-10).show();
	},
	
	hideThrobber : function() {
		$("#throbber").hide();
	},
	
	addEvents : function() {
		// popup on site on click
		$(".spot").live("click", function(e) {
			//get site code stored in attribute and the load it
			var site_code = $(this).attr('alt');
			if(site_code=="alert"){
				$.ajax({
					url: "misc/alert.html",
					cache: false,
					success: function(html){
						$("body").append(html);
					} //of success
				});				
			} else {
				sites.showThrobber(e);
				sites.getPopup(site_code,e); 
			}
		});

		//popup to fade out then remove from page when mouse out or click
		$(".site_popup").live("mouseleave click touchstart", function() {			
			$(this).fadeOut("fast", function() { 
				$(this).remove(); //when fade complete remove the popup from the DOM
			});
		}); //of bind
		
		//if wind arrow	id over a site it will block click inputs. we will inetrcept and move arrow underneath.
		$("#arrow").live("click touchstart", function() {
			$(this).css('z-index',0);
			window.setTimeout(function(){$("#arrow").css('z-index',2)},2000);
		});			
	},
	
	pulseStart : function(){
		//return;
		if(!sites.pulsing && !$("body").hasClass("night")) { 
			//if there are any active sites then animate a pulsing effect on them
			if( $(".spot.active:visible").length ) {
				//use flag to prevent multiple firings
				sites.pulsing = true;
				$(".spot.active:visible .rating").fadeOut("slow").fadeIn("fast",function(){
					sites.pulsing = false;
					sites.pulse_timer = setTimeout(function() { sites.pulseStart(); }, sites.pulse_rate);
				});

			}
		}
	},

	pulseStop : function() {
		if (sites.pulsing) {
			//site_remove_all_popups();
			clearTimeout(sites.pulse_timer); //stop any previous animation
			$(".spot.active:visible .rating").stop(true, true).css('opacity',1).show();  //clear any previous fading	
			sites.pulsing = false;
		}
	},

	pulseRefresh : function(){
		sites.pulseStop();
		sites.pulseStart();
	}
};


//====================================  TIMELINE ==========================================
var timeline = {
	boxGoto : function($box){
		//use url found in timeline box passed to refresh the area for that time
		var url = $box.attr("href");
		if(!url) {
			return;
		} else if (url==="/") {
			url="/x_live_refresh.php"; //NOW link clicked
		}
		
		$("#timeline a.active").removeClass("active");
		$box.addClass("active");
		sites.removeAllPopups();
		obs.refreshAnounce(0,false);  //stage start, don't flash day style
		$("#refresh_area").load(url, function(){
			obs.refreshComplete();				
			obs.setVarsFromJsonHtml(); //update obs variables from returned data in json div
			sites.pulseRefresh(); //show sites that are on
		});		
	},

	boxRefresh : function(){
		//rerun current box - used for settings update
		timeline.boxGoto( $("#timeline a.active") );
	},
		
	init : function() {
		$("#timeline").html("<h2>Timeline browser loading..</h2>");
		timeline.detail = timeline.calcDetail();
		timeline.refresh(); //won't be loaded yet.

		$("#timeline a").live("click",function(e){
			e.preventDefault();

			//if live clicked resume refeshing
			if( $(this).hasClass("current") ) {
				//obs.refresh();
				refresh.resume(); //resume refreshing if live then selected
							
			//if current active click then go back to live
			} else if( $(this).hasClass("active") ) {
				timeline.jump_live();	
				return;	
			
			//otherwise must be unselected history or future-
			} else {
				refresh.pause(); //to prevent auto refreshing when browsing
			}
			
			//pass jquery reference to this box on
			timeline.boxGoto($(this));
		});
		
		//Header navigation
		$("#nav_back").click(function(e){
			e.preventDefault();
			timeline.jump_back();
		});
		$("#nav_fwd").click(function(e){
			e.preventDefault();
			timeline.jump_fwd();
		});
		$("#nav_now, #scene_comments").click(function(e){
			e.preventDefault();
			timeline.jump_live();
		});		
	},
	
	jump_fwd : function(dtype) {
		dtype = (dtype == null) ? "any" : dtype;
		var search_for = "a.tl_box";
		if (dtype==="day_only") {
			search_for = "a.tl_box.day, a.tl_box.dusk";
		}		
		//move to next timeline by finding the next box after the active one-that natches the criteria. use All and return only 1 element
		$("#timeline a.active").nextAll(search_for)[0].click();
	},
	jump_back : function() {
		$("#timeline a.active").prevAll("a.tl_box")[0].click();
	},
	jump_live : function() {
		$("#timeline a.current").click();
	},	

	refresh : function() {
		//work out from browser width how much detail to show
		//if( !this.current_detail || this.current_detail <> this.calcDetail() )
		//timeline.detail is set via timeline.calcDetail. called on init and when window resized
		$.getJSON("/x_timeline.php?detail="+timeline.detail+ "&output_type=json", function(data){
			timeline.createFromJson(data);
	    });	
	},
	
	createFromJson : function(json_array) {
		var html="<div class='scroller cf'>";

		$.each(json_array, function(i, json) {
			if(json.newday !== undefined) {
				html+="<div class='newday'>" +json.newday+ "</div>"; //NEW day

			} else {
				//BOX
				html+="<a class='tl_box " +json.c+ "' href='" +json.l+ "'>";
					html+="<div class='info'>" +json.t+ "</div>";
					html+="<div class='reading'>";
						html+="<div class='tlarrow' data-d='" +json.d+ "'></div>";
						html+="<div class='wind'>" +json.s+ "</div>";
					html+="</div>";
				html+="</a>";
			}
		});

		html+="</div>";	//of .scroller cf
		$("#timeline").html(html);

		//rotate arrows
		$(".tlarrow").each( function(){
			$(this).css({"transform": "rotate("+$(this).data("d")+"deg)"});
		});		
	},
		
	winResized : function(){
		//after window has been resized update the timeline if the detail required has changed
		var new_detail = timeline.calcDetail();
		if( timeline.detail !== new_detail ){
			timeline.detail = new_detail;
			timeline.refresh();
		}
	},
	
	calcDetail : function(){
		//work out from browser width how much detail to show
		var browser_width = document.body.offsetWidth;
		var tl_detail = "full";
		if (browser_width < 550 ) {
			tl_detail="minimum";
		}
		return tl_detail;	
	},

	updateFromObs : function () {
		//update live timeline tile from obs details - used after an obs refresh
		var $cbox = $("#timeline .current");
		$cbox.find(".wind").text(obs.wind_speed);
		//Update arrow image - remove "0" prefix if present e.g. "010" to "10"
		var windir = obs.wind_direction;
		if( windir.substr(0,1) === "0" ) {
			windir = windir.substr(1,3);
		}
		$cbox.find(".tlarrow").css({"transform": "rotate("+windir+"deg)"});
	}
};


//=================================== REFRESH =================================== 
var refresh = {
	paused : false,
	sec_counter : 0,
	ticker_timer : null,
	autoresume_timer : null,
	main_refresh : null,
	autoplay : true,
	autoplay_count : 0,
	
	curTime : function(){
		return Math.round(+new Date()/1000);  //in seconds
	},
	tickerRepeat : function(){
		refresh.ticker_timer = window.setTimeout('refresh.ticker()',1000); //every second
	},
	pause : function(){
		if(!refresh.paused) {
			refresh.paused=true;
			//used while browsing the timeline
			if(refresh.ticker_timer !== null) {
				clearTimeout(refresh.ticker_timer);
				refresh.ticker_timer = null;
				//refresh.secondCounterReset();
			}	
			//auto resume after 30 seconds after last tl use
			//clearTimeout(refresh.autoresume_timer);
			//refresh.autoresume_timer = window.setTimeout('refresh.autoresume()',30000); //30 sec
		}
	},
	resume : function(){
		if(refresh.paused) {
			refresh.paused=false;
			//comments.mkyRevert();
			//fired when 'current' selected in timeline
			clearTimeout(refresh.autoresume_timer); //stop auto refresh adding to a manual refresh
			refresh.main_refresh.resetTime(); //reset main refresh
			refresh.ticker();
		}
	},
	autoresume : function(){
		refresh.paused=false;
		$("#timeline .current").click(); //resume by using the current tl box.
	},

	ticker : function(){
		var now_time = refresh.curTime();
		refresh.secondCounter(now_time);
		//run thorugh all repeaters to check if any are overdue
		for (var i = 0; i < refresh.repeaterArray.length; i++){
			if( now_time > refresh.repeaterArray[i].refresh_time ) {
				refresh.repeaterArray[i].fireRefresh(now_time);
			}
		}	
		refresh.tickerRepeat();
	},
	secondCounter : function(now_time){		
		refresh.sec_counter = now_time-refresh.main_refresh.refresh_time +60; //use main refresh to calc seconds since last refresh	
		$("#seconds").text(refresh.sec_counter);
	},
	//REPEATERS
	repeaterArray : [],
	repeater : function(data) {
		this.desc = data.desc;
		this.interval = data.interval;
		this.script = data.script;
		this.refresh_time = refresh.curTime()+data.interval; //initital
	    refresh.repeaterArray.push(this);

		this.fireRefresh = function(now_time) {
			this.refresh_time = now_time + this.interval;
			refresh[this.script](); //call script within this object - tried to pass other object's functions as a parameter but could only do it for window scope
		};
		this.resetTime = function() {
			this.refresh_time = refresh.curTime() + this.interval;
		};		
	},

	init : function(){
		//list of items to repeat with duration and script to fire
		refresh.main_refresh = new refresh.repeater( {"desc":"main_refresh", "interval":60, "script":"run_mainDisplay" } ); //60 - every minute. assign it to a var so we can call resetTime on it in resume
		refresh.timeline_repeater = new refresh.repeater( {"desc":"timeline", "interval":300, "script":"run_timeline" } ); //300 - 5mins
		refresh.qf_repeater = new refresh.repeater( {"desc":"quick_forecasts", "interval":900, "script":"run_quickForcasts" } ); //900 - 15mins
		refresh.autoplay_repeater = new refresh.repeater( {"desc":"auto_play", "interval":1, "script":"run_autoplay" } ); //every second
		//
		refresh.ticker();
	},
	
		
	run_mainDisplay : function(){
		obs.refresh();	
	},
	run_timeline : function(){
		timeline.refresh();		
	},
	run_quickForcasts : function(){
		wmconfig.wguru_loaded = false; //it won't be soon
		$("#quick_forecast_area").load("x_quickforecasts.php", function(){
			if(wmconfig.is_desktop) { wmconfig.loadWindguru(); } //auto load windguru if desktop class
		});
	},
	run_autoplay : function(){
		if(wmconfig.is_mobile || !refresh.autoplay) { return; }
		//new version just running off seconds and firing custom body events so extra.js can see it
		$("body").trigger("autoplay"); //trigger custom event
	}
}

//====================================  ON LOAD ==========================================
$(document).ready(function (){
	wmconfig.init();
});