var pages = ["graphs", "records", "reports", "about"]; // If this page we're on now is listed as a subpage, use ".." to get to the relative root function get_relative_url() { var sPath = window.location.pathname.replace(/\/$/, ""); var pageName = sPath.substring(sPath.lastIndexOf('/') + 1); if ( pages.includes( pageName ) ) { var relative_url = ".."; } else { var relative_url = "."; } belchertown_debug("URL: Relative URL is: " + relative_url); return relative_url; } // Determine if debug is on via URL var or config setting if ( getURLvar("debug") && ( getURLvar("debug") == "true" || getURLvar("debug") == "1" ) ) { var belchertown_debug_config = true; belchertown_debug("Debug: URL debug variable enabled"); } else { var belchertown_debug_config = 0; belchertown_debug("Debug: skin.conf belchertown_debug enabled"); } var moment_locale = "en-US"; moment.locale(moment_locale); var graphgroups_raw = {"homepage": ["chart1", "chart2", "chart3", "chart4"], "day": ["chart1", "chart2", "chart3", "chart4"], "week": ["chart1", "chart2", "chart3", "chart4"], "month": ["chart1", "chart2", "chart3", "chart4"], "year": ["chart1", "chart2", "chart3", "chart4"]}; var graphgroups_titles = {"homepage": "Homepage", "day": "Today", "week": "This Week", "month": "This Month", "year": "This Year"}; var graphpage_content = {}; function belchertown_debug(message) { if (belchertown_debug_config > 0) { console.log(message); } } jQuery(document).ready(function() { // Bootstrap hover tooltips jQuery(function () { jQuery('[data-toggle="tooltip"]').tooltip() }) // If the visitor has overridden the theme, keep that theme going throughout the full site and their visit. if ( sessionStorage.getItem('theme') == "toggleOverride" ) { belchertown_debug("Theme: sessionStorage override in place."); changeTheme( sessionStorage.getItem('currentTheme') ); } // Change theme if a URL variable is set if ( window.location.search.indexOf('theme') ) { if (window.location.search.indexOf('?theme=dark') === 0) { belchertown_debug("Theme: Setting dark theme because of URL override"); changeTheme("dark", true); } else if (window.location.search.indexOf('?theme=light') === 0) { belchertown_debug("Theme: Setting light theme because of URL override"); changeTheme("light", true); } else if (window.location.search.indexOf('?theme=auto') === 0) { belchertown_debug("Theme: Setting auto theme because of URL override"); sessionStorage.setItem('theme', 'auto') autoTheme(20, 33, 05, 41) } } // Dark mode checkbox toggle switcher try { document.getElementById('themeSwitch').addEventListener('change', function(event) { belchertown_debug("Theme: Toggle button changed"); (event.target.checked) ? changeTheme("dark", true) : changeTheme("light", true); }); } catch(err) { // Silently exit } // After charts are loaded, if an anchor tag is in the URL, let's scroll to it jQuery(window).on('load', function() { var anchor_tag = location.hash.replace('#',''); if ( anchor_tag != '' ) { // Scroll the webpage to the chart. The timeout is to let jQuery finish appending the outer div so the height of the page is completed. setTimeout(function() { jQuery('html, body').animate({ scrollTop: jQuery('#'+anchor_tag).offset().top }, 500); }, 500); } }); }); // Run this on every page for dark mode if skin theme is auto ajaxweewx(); // Disable AJAX caching jQuery.ajaxSetup({ cache:false }); // Get the URL variables. Source: https://stackoverflow.com/a/26744533/1177153 function getURLvar(k) { var p={}; location.search.replace(/[?&]+([^=&]+)=([^&]*)/gi,function(s,k,v){p[k]=v}); return k?p[k]:p; } // https://stackoverflow.com/a/53387532/1177153 // Archived: https://stackoverflow.com/a/52059759/1177153 (also https://helloacm.com/the-javascript-function-to-compare-version-number-strings/) function check_for_updates(oldVer, newVer) { // Treat non-numerical characters as lower version // Replacing them with a negative number based on charcode of each character function fix(s) { return "." + (s.toLowerCase().charCodeAt(0) - 99999) + "."; } oldVer = ("" + oldVer).replace(/[^0-9\.]/g, fix).split('.'); newVer = ("" + newVer).replace(/[^0-9\.]/g, fix).split('.'); var c = Math.max(newVer.length, oldVer.length); for (var i = 0; i < c; i++) { //convert to integer the most efficient way oldVer[i] = ~~oldVer[i]; newVer[i] = ~~newVer[i]; if (oldVer[i] < newVer[i]) return true; else if (oldVer[i] > newVer[i]) return false; } return false; } // http://stackoverflow.com/a/14887961/1177153 var weatherdirection = { 0: "N", 90: "E", 180: "S", 270: "W", 360: "N" }; // Change the color of the outTemp_F variable function get_outTemp_color( unit, outTemp, returnColor=false ) { outTemp = parseFloat( outTemp ).toFixed(0); // Convert back to decimal literal if ( unit == "degree_F" ) { if ( outTemp <= 0 ) { var outTemp_color = "#1278c8"; } else if ( outTemp <= 25 ) { var outTemp_color = "#30bfef"; } else if ( outTemp <= 32 ) { var outTemp_color = "#1fafdd"; } else if ( outTemp <= 40 ) { var outTemp_color = "rgba(0,172,223,1)"; } else if ( outTemp <= 50 ) { var outTemp_color = "#71bc3c"; } else if ( outTemp <= 55 ) { var outTemp_color = "rgba(90,179,41,0.8)"; } else if ( outTemp <= 65 ) { var outTemp_color = "rgba(131,173,45,1)"; } else if ( outTemp <= 70 ) { var outTemp_color = "rgba(206,184,98,1)"; } else if ( outTemp <= 75 ) { var outTemp_color = "rgba(255,174,0,0.9)"; } else if ( outTemp <= 80 ) { var outTemp_color = "rgba(255,153,0,0.9)"; } else if ( outTemp <= 85 ) { var outTemp_color = "rgba(255,127,0,1)"; } else if ( outTemp <= 90 ) { var outTemp_color = "rgba(255,79,0,0.9)"; } else if ( outTemp <= 95 ) { var outTemp_color = "rgba(255,69,69,1)"; } else if ( outTemp <= 110 ) { var outTemp_color = "rgba(255,104,104,1)"; } else if ( outTemp >= 111 ) { var outTemp_color = "rgba(218,113,113,1)"; } } else if ( unit == "degree_C" ) { if ( outTemp <= 0 ) { var outTemp_color = "#1278c8"; } else if ( outTemp <= -3.8 ) { var outTemp_color = "#30bfef"; } else if ( outTemp <= 0 ) { var outTemp_color = "#1fafdd"; } else if ( outTemp <= 4.4 ) { var outTemp_color = "rgba(0,172,223,1)"; } else if ( outTemp <= 10 ) { var outTemp_color = "#71bc3c"; } else if ( outTemp <= 12.7 ) { var outTemp_color = "rgba(90,179,41,0.8)"; } else if ( outTemp <= 18.3 ) { var outTemp_color = "rgba(131,173,45,1)"; } else if ( outTemp <= 21.1 ) { var outTemp_color = "rgba(206,184,98,1)"; } else if ( outTemp <= 23.8 ) { var outTemp_color = "rgba(255,174,0,0.9)"; } else if ( outTemp <= 26.6 ) { var outTemp_color = "rgba(255,153,0,0.9)"; } else if ( outTemp <= 29.4 ) { var outTemp_color = "rgba(255,127,0,1)"; } else if ( outTemp <= 32.2 ) { var outTemp_color = "rgba(255,79,0,0.9)"; } else if ( outTemp <= 35 ) { var outTemp_color = "rgba(255,69,69,1)"; } else if ( outTemp <= 43.3 ) { var outTemp_color = "rgba(255,104,104,1)"; } else if ( outTemp >= 43.4 ) { var outTemp_color = "rgba(218,113,113,1)"; } } // Return the color value if requested, otherwise just set the div color if ( returnColor ) { return outTemp_color; } else { jQuery(".outtemp_outer").css( "color", outTemp_color ); } } function highcharts_tooltip_factory(obsvalue, point_obsType, highchartsReturn=false, rounding, mirrored=false, numberFormat) { // Mirrored values have the negative sign removed if ( mirrored ) { obsvalue = Math.abs( obsvalue ); } if ( point_obsType == "windDir" ) { if (obsvalue >= 0 && obsvalue <= 11.25) { ordinal = "N"; // N } else if (obsvalue >= 11.26 && obsvalue <= 33.75) { ordinal = "NNE"; // NNE } else if (obsvalue >= 33.76 && obsvalue <= 56.25) { ordinal = "NE"; // NE } else if (obsvalue >= 56.26 && obsvalue <= 78.75) { ordinal = "ENE"; // ENE } else if (obsvalue >= 78.76 && obsvalue <= 101.25) { ordinal = "E"; // E } else if (obsvalue >= 101.26 && obsvalue <= 123.75) { ordinal = "ESE"; // ESE } else if (obsvalue >= 123.76 && obsvalue <= 146.25) { ordinal = "SE"; // SE } else if (obsvalue >= 146.26 && obsvalue <= 168.75) { ordinal = "SSE"; // SSE } else if (obsvalue >= 168.76 && obsvalue <= 191.25) { ordinal = "S"; // S } else if (obsvalue >= 191.26 && obsvalue <= 213.75) { ordinal = "SSW"; // SSW } else if (obsvalue >= 213.76 && obsvalue <= 236.25) { ordinal = "SW"; // SW } else if (obsvalue >= 236.26 && obsvalue <= 258.75) { ordinal = "WSW"; // WSW } else if (obsvalue >= 258.76 && obsvalue <= 281.25) { ordinal = "W"; // W } else if (obsvalue >= 281.26 && obsvalue <= 303.75) { ordinal = "WNW"; // WNW } else if (obsvalue >= 303.76 && obsvalue <= 326.25) { ordinal = "NW"; // NW } else if (obsvalue >= 326.26 && obsvalue <= 348.75) { ordinal = "NNW"; // NNW } else if (obsvalue >= 348.76 && obsvalue <= 360) { ordinal = "N"; // N } // highchartsReturn returns the full wind direction string for highcharts tooltips. e.g "NNW (337)" if ( highchartsReturn ) { output = ordinal + " ("+ Math.round(obsvalue) + "\xBA)"; } else { output = ordinal; } } else { try { // Setup any graphs.conf overrides on formatting var { decimals, decimalPoint, thousandsSep } = numberFormat; // Try to apply the highcharts numberFormat for locale awareness. Use rounding from weewx.conf StringFormats. // -1 is set from Python to notate no rounding data available and decimals from graphs.conf is undefined. if ( rounding == "-1" && typeof decimals === "undefined" ) { output = Highcharts.numberFormat(obsvalue); } else { // If the amount of decimal is defined, use that instead since rounding is provided to the function. if ( typeof decimals !== "undefined" ) { rounding = decimals; } // If decimalPoint is undefined, use the auto detect from the skin since this comes from the skin. if ( typeof decimalPoint === "undefined" ) { decimalPoint = "."; } // If thousandsSep is undefined, use the auto detect from the skin since this comes from the skin. if ( typeof thousandsSep === "undefined" ) { thousandsSep = ","; } output = Highcharts.numberFormat(obsvalue, rounding, decimalPoint, thousandsSep); } } catch(err) { // Fall back to just returning the highcharts point number value, which is a best guess. output = Highcharts.numberFormat(obsvalue); } } return output; } // Handle wind arrow rotation with the ability to "rollover" past 0 // without spinning back around. e.g 350 to 3 would spin back around // https://stackoverflow.com/a/19872672/1177153 function rotateThis(newRotation) { if ( newRotation == "N/A") { return; } var currentRotation; finalRotation = finalRotation || 0; // if finalRotation undefined or 0, make 0, else finalRotation currentRotation = finalRotation % 360; if ( currentRotation < 0 ) { currentRotation += 360; } if ( currentRotation < 180 && (newRotation > (currentRotation + 180)) ) { finalRotation -= 360; } if ( currentRotation >= 180 && (newRotation <= (currentRotation - 180)) ) { finalRotation += 360; } finalRotation += (newRotation - currentRotation); jQuery(".wind-arrow").css( "transform", "rotate(" + finalRotation + "deg)" ); jQuery(".arrow").css( "transform", "rotate(" + finalRotation + "deg)" ); } // Title case strings. https://stackoverflow.com/a/45253072/1177153 function titleCase(str) { return str.toLowerCase().split(' ').map(function(word) { return word.replace(word[0], word[0].toUpperCase()); }).join(' '); } function autoTheme(sunset_hour, sunset_min, sunrise_hour, sunrise_min) { // First check if ?theme= is in URL. If so, bail out and do not change anything. if ( getURLvar("theme") && getURLvar("theme") != "auto" ) { belchertown_debug("Auto theme: theme override detected in URL. Skipping auto theme"); return true; } belchertown_debug("Auto theme: checking to see if theme needs to be switched"); var d = new Date(); var nowHour = d.getHours(); var nowMinutes = d.getMinutes(); nowHour = nowHour; sunrise_hour = sunrise_hour; sunset_hour = sunset_hour; // Determine if it's day time. https://stackoverflow.com/a/14718577/1177153 if ( sunrise_hour <= nowHour && nowHour < sunset_hour ) { dayTime = true; } else { dayTime = false; } belchertown_debug("Auto theme: sunrise: " + sunrise_hour); belchertown_debug("Auto theme: now: " + nowHour); belchertown_debug("Auto theme: sunset: " + sunset_hour); belchertown_debug("Auto theme: are we in daylight hours: " + dayTime); belchertown_debug("Auto theme: sessionStorage.getItem('theme') = " + sessionStorage.getItem('theme')); if ( dayTime ) { // Day time, set light if needed if ( document.body.classList.contains("dark") ) { if ( sessionStorage.getItem('theme') == "auto" ) { belchertown_debug("Auto theme: setting light theme since dayTime variable is true (day)"); } else { belchertown_debug("Auto theme: cannot set light theme since visitor used toggle to override theme. Refresh to reset the override."); } // Only change theme if user has not overridden the auto option with the toggle if ( sessionStorage.getItem('theme') == "auto" ) { changeTheme("light"); } } } else { // Night time, set dark if needed if ( document.body.classList.contains("light") ) { if ( sessionStorage.getItem('theme') == "auto" ) { belchertown_debug("Auto theme: setting dark theme since dayTime variable is false (night)"); } else { belchertown_debug("Auto theme: cannot set dark theme since visitor used toggle to override theme. Refresh to reset the override."); } // Only change theme if user has not overridden the auto option with the toggle if ( sessionStorage.getItem('theme') == "auto" ) { changeTheme("dark"); } } } } function changeTheme(themeName, toggleOverride=false) { belchertown_debug("Theme: Changing to " + themeName); // If the configured theme is auto, but the user toggles light/dark, remove the auto option. if ( toggleOverride ) { belchertown_debug("Theme: toggle override clicked."); belchertown_debug("Theme: sessionStorage.getItem('theme') was previously: " + sessionStorage.getItem('theme') ); // This was applied only to auto theme config, but now it's applied to all themes so visitor has full control on light/dark mode //if ( sessionStorage.getItem('theme') == "auto" ) { } sessionStorage.setItem('theme', 'toggleOverride'); belchertown_debug("Theme: sessionStorage.getItem('theme') is now: " + sessionStorage.getItem('theme') ); } if ( themeName == "dark" ) { // Apply dark theme jQuery('body').addClass("dark"); jQuery('body').removeClass("light"); jQuery("#themeSwitch").prop( "checked", true ); sessionStorage.setItem('currentTheme', 'dark'); } else if ( themeName == "light" ) { // Apply light theme jQuery('body').addClass("light"); jQuery('body').removeClass("dark"); jQuery("#themeSwitch").prop( "checked", false ); sessionStorage.setItem('currentTheme', 'light'); } } function ajaxweewx() { // Relative URL jQuery.getJSON(get_relative_url() + "/json/weewx_data.json", update_weewx_data); }; // Update weewx data elements //var station_obs_array = ""; var unit_rounding_array = ""; var unit_label_array = ""; function update_weewx_data( data ) { belchertown_debug("Updating weewx data"); // Check for updates var update_available = check_for_updates("1.1", data["version"]["github_version"]); belchertown_debug("Checking Update: update available: " + update_available + " (installed: 1.1 - new version: "+data["version"]["github_version"]+")"); if ( update_available ) { jQuery(".updateavailable").show(); } // Auto theme if enabled autoTheme(data["almanac"]["sunset_hour"], data["almanac"]["sunset_minute"], data["almanac"]["sunrise_hour"], data["almanac"]["sunrise_minute"], ); //station_obs_array = data["station_observations"]; unit_rounding_array = data["unit_rounding"]; unit_label_array = data["unit_label"]; // Daily High Low high = data["day"]["outTemp"]["max"]; low = data["day"]["outTemp"]["min"]; jQuery(".high").html( high ); jQuery(".low").html( low ); // Barometer trending by finding a negative number count = ( data["current"]["barometer_trend"].match(/-/g) || [] ).length if ( count >= 1 ) { jQuery(".pressure-trend").html( '' ); } else { jQuery(".pressure-trend").html( '' ); } // Daily max gust span jQuery(".dailymaxgust").html( parseFloat( data["day"]["wind"]["max"] ).toFixed(1) ); // Daily Snapshot Stats Section jQuery(".snapshot-records-today-header").html( moment.unix( data["current"]["epoch"] ).utcOffset(-240.0).format( 'dddd, LL' ) ); jQuery(".snapshot-records-month-header").html( moment.unix( data["current"]["epoch"] ).utcOffset(-240.0).format( 'MMMM YYYY' ) ); jQuery(".dailystatshigh").html( data["day"]["outTemp"]["max"] ); jQuery(".dailystatslow").html( data["day"]["outTemp"]["min"] ); jQuery(".dailystatswindavg").html( data["day"]["wind"]["average"] ); jQuery(".dailystatswindmax").html( data["day"]["wind"]["max"] ); jQuery(".dailystatsrain").html( data["day"]["rain"]["sum"] ); jQuery(".dailystatsrainrate").html( data["day"]["rain"]["max"] ); // Month Snapshot Stats Section jQuery(".monthstatshigh").html( data["month"]["outTemp"]["max"] ); jQuery(".monthstatslow").html( data["month"]["outTemp"]["min"] ); jQuery(".monthstatswindavg").html( data["month"]["wind"]["average"] ); jQuery(".monthstatswindmax").html( data["month"]["wind"]["max"] ); jQuery(".monthstatsrain").html( data["month"]["rain"]["sum"] ); jQuery(".monthstatsrainrate").html( data["month"]["rain"]["max"] ); // Sunrise and Sunset jQuery(".sunrise-value").html( moment.unix( parseFloat(data["almanac"]["sunrise_epoch"]).toFixed(0) ).utcOffset(-240.0).format( "LT" ) ); jQuery(".sunset-value").html( moment.unix( parseFloat(data["almanac"]["sunset_epoch"]).toFixed(0) ).utcOffset(-240.0).format( "LT" ) ); // Moon icon, phase and illumination percent switch ( data["almanac"]["moon"]["moon_index"] ) { case "0": jQuery(".moon-icon").html( "
" ); break; case "1": jQuery(".moon-icon").html( "" ); break; case "2": jQuery(".moon-icon").html( "" ); break; case "3": jQuery(".moon-icon").html( "" ); break; case "4": jQuery(".moon-icon").html( "" ); break; case "5": jQuery(".moon-icon").html( "" ); break; case "6": jQuery(".moon-icon").html( "" ); break; case "7": jQuery(".moon-icon").html( "" ); break; } jQuery(".moon-phase").html( titleCase( data["almanac"]["moon"]["moon_phase"] ) ); // Javascript function above jQuery(".moon-visible").html( "" + data["almanac"]["moon"]["moon_fullness"] + "% visible" ); } Highcharts.setOptions({ global: { //useUTC: false timezoneOffset: 240.0 }, lang: { decimalPoint: '.', thousandsSep: ',' } }); function showChart(json_file, prepend_renderTo=false) { // Relative URL by finding what page we're on currently. jQuery.getJSON(get_relative_url() + '/json/' + json_file + '.json', function(data) { // Loop through each chart name (e.g. chart1, chart2, chart3) jQuery.each(data, function (plotname, obsname) { var observation_type = undefined; // Ignore the Belchertown Version since this "plot" has no other options if ( plotname == "belchertown_version" ) { return true; } // Ignore the generated timestamp since this "plot" has no other options if ( plotname == "generated_timestamp" ) { return true; } // Ignore the chartgroup_title since this "plot" has no other options if ( plotname == "chartgroup_title" ) { return true; } // Set the chart's tooltip date time format, then return since this "plot" has no other options if ( plotname == "tooltip_date_format" ) { tooltip_date_format = obsname; return true; } // Set the chart colors, then return right away since this "plot" has no other options if ( plotname == "colors" ) { colors = obsname.split(","); return true; } // Set the chart credits, then return right away since this "plot" has no other options if ( plotname == "credits" ) { credits = obsname.split(",")[0]; return true; } // Set the chart credits url, then return right away since this "plot" has no other options if ( plotname == "credits_url" ) { credits_url = obsname.split(",")[0]; return true; } // Set the chart credits position, then return right away since this "plot" has no other options if ( plotname == "credits_position" ) { credits_position = obsname; return true; } // Loop through each chart options jQuery.each(data[plotname]["options"], function (optionName, optionVal) { switch(optionName) { case "type": type = optionVal; break; case "renderTo": renderTo = optionVal; break; case "title": title = optionVal; break; case "subtitle": subtitle = optionVal; break; case "yAxis_label": yAxis_label = optionVal; break; case "chart_group": chart_group = optionVal; break; case "gapsize": gapsize = optionVal; break; case "connectNulls": connectNulls = optionVal; break; case "rounding": rounding = optionVal; break; case "xAxis_categories": xAxis_categories = optionVal; break; case "plot_tooltip_date_format": plot_tooltip_date_format = optionVal; break; case "css_class": css_class = optionVal; break; case "css_height": css_height = optionVal; break; case "css_width": css_width = optionVal; break; case "exporting": exporting_enabled = optionVal; break; } }); // Handle any per-chart date time format override if ( typeof plot_tooltip_date_format !== "undefined" ) { var tooltip_date_format = plot_tooltip_date_format; } var options = { chart: { renderTo: '', spacing: [5, 10, 10, 0], type: '', zoomType: 'x' }, exporting: { enabled: JSON.parse( String( exporting_enabled ) ) // Convert string to bool }, title: { useHTML: true, text: '' }, subtitle: { text: '' }, legend: { enabled: true }, xAxis: { dateTimeLabelFormats: { day: '%e %b', week: '%e %b', month: '%b %y', }, lineColor: '#555', minRange: 900000, minTickInterval: 900000, title: { style: { font: 'bold 12px Lucida Grande, Lucida Sans Unicode, Verdana, Arial, Helvetica, sans-serif' } }, ordinal: false, type: 'datetime' }, yAxis: [{ endOnTick: true, lineColor: '#555', minorGridLineWidth: 0, startOnTick: true, showLastLabel: true, title: { }, opposite: false }], plotOptions: { area: { lineWidth: 2, gapSize: '', gapUnit: 'value', marker: { enabled: false, radius: 2 }, threshold: null, softThreshold: true }, line: { lineWidth: 2, gapSize: '', gapUnit: 'value', marker: { enabled: false, radius: 2 }, }, spline: { lineWidth: 2, gapSize: '', gapUnit: 'value', marker: { enabled: false, radius: 2 }, }, areaspline: { lineWidth: 2, gapSize: '', gapUnit: 'value', marker: { enabled: false, radius: 2 }, threshold: null, softThreshold: true }, scatter: { gapSize: '', gapUnit: 'value', marker: { radius: 2 }, }, }, // Highstock is needed for gapsize. Disable these 3 to make it look like standard Highcharts scrollbar: { enabled: false }, navigator: { enabled: false }, rangeSelector: { enabled: false }, tooltip: { enabled: true, crosshairs: true, dateTimeLabelFormats: { hour: '%e %b %H:%M' }, // For locale control with moment.js formatter: function (tooltip) { try { // The first returned item is the header, subsequent items are the points. // Mostly applies to line style charts (line, spline, area) return [moment.unix( this.x / 1000).utcOffset(-240.0).format( tooltip_date_format )].concat( this.points.map(function (point) { // If observation_type is in the series array, use that otherwise use the obsType var point_obsType = point.series.userOptions.observation_type ? point.series.userOptions.observation_type : point.series.userOptions.obsType; var rounding = point.series.userOptions.rounding; var mirrored = point.series.userOptions.mirrored_value; var numberFormat = point.series.userOptions.numberFormat ? point.series.userOptions.numberFormat : ""; return "\u25CF " + point.series.name + ': ' + highcharts_tooltip_factory( point.y, point_obsType, true, rounding, mirrored, numberFormat ); }) ); } catch(e) { // There's an error so check if it's windDir to apply wind direction label, or if it's a scatter. If none of those revert back to default tooltip. if (this.series.userOptions.obsType == "windDir" || this.series.userOptions.observation_type == "windDir") { // If observation_type is in the series array, use that otherwise use the obsType var point_obsType = this.series.userOptions.observation_type ? this.series.userOptions.observation_type : this.series.userOptions.obsType; var rounding = this.series.userOptions.rounding; var mirrored = this.series.userOptions.mirrored_value; return moment.unix( this.x / 1000).utcOffset(-240.0).format( tooltip_date_format ) +'