diff --git a/css/wah.css b/css/wah.css
index 3524c57..d02a1e0 100644
--- a/css/wah.css
+++ b/css/wah.css
@@ -188,3 +188,24 @@ table.current-conditions tr:last-child td:nth-child(3) {
font-weight: normal;
font-style: italic;
}
+
+/* -------------------------------------------------------------------------- */
+
+div.gauge-grid {
+ padding: 20px !important;
+ display: flex;
+ flex-flow: row wrap;
+ justify-content: space-evenly;
+}
+
+div.gauge-header {
+ display: grid;
+ grid-template-columns: auto auto 1fr;
+ grid-template-rows: 1fr;
+ grid-column-gap: 10px;
+ grid-row-gap: 0px;
+}
+
+canvas#canvas_led {
+ margin-bottom: -7px;
+}
diff --git a/gauges/index.php b/gauges/index.php
index 7421aa1..747f6e9 100644
--- a/gauges/index.php
+++ b/gauges/index.php
@@ -3,26 +3,91 @@
-
+
+
-
-
- Status:
+
+
-
Page data updated
+
+
+
+
+
+
+
diff --git a/lib/steelseries/scripts/gauges.js b/lib/steelseries/scripts/gauges.js
index 38f1994..a8a647a 100644
--- a/lib/steelseries/scripts/gauges.js
+++ b/lib/steelseries/scripts/gauges.js
@@ -1,4377 +1,4377 @@
-/*!
- * THIS VERSION CUSTOMISED FROM CUMULUS MX DEFAULT WEB SITE
- * Last Modified: 2023/09/02 17:15:14
- *
- * A starter gauges page for Cumulus and Weather Display, based
- * on the JavaScript SteelSeries gauges by Gerrit Grunwald.
- *
- * Created by Mark Crossley, July 2011
- * see scriptVer below for latest release
- *
- * Released under GNU GENERAL PUBLIC LICENSE, Version 2, June 1991
- * See the enclosed License file
- *
- * File encoding = UTF-8
- *
- */
-
-/* exported gauges */
-
-/*!
-* Tiny Pub/Sub - v0.7.0 - 2013-01-29
-* https://github.com/cowboy/jquery-tiny-pubsub
-* Copyright (c) 2013 "Cowboy" Ben Alman; Licensed MIT
-*/
-(function ($) {
- 'use strict';
- var o = $({});
- $.subscribe = function () { o.on.apply(o, arguments); };
- $.unsubscribe = function () { o.off.apply(o, arguments); };
- $.publish = function () { o.trigger.apply(o, arguments); };
-}(jQuery));
-
-var gauges;
-gauges = (function () {
- 'use strict';
- var strings = LANG.EN, // Set to your default language. Store all the strings in one object
- config = {
- // Script configuration parameters you may want to 'tweak'
- scriptVer: '2.7.7',
- weatherProgram: 0, // Set 0=Cumulus, 1=Weather Display, 2=VWS, 3=WeatherCat, 4=Meteobridge, 5=WView, 6=WeeWX, 7=WLCOM
- imgPathURL: './/images/', // *** Change this to the relative path for your 'Trend' graph /images
- oldGauges: 'gauges.htm', // *** Change this to the relative path for your 'old' gauges page.
- realtimeInterval: 15, // *** Download data interval, set to your realtime data update interval in seconds
- longPoll: false, // if enabled, use long polling and PHP generated data !!only enable if you understand how this is implemented!!
- gaugeMobileScaling: 0.85, // scaling factor to apply when displaying the gauges mobile devices, set to 1 to disable (default 0.85)
- graphUpdateTime: 15, // period of pop-up data graph refresh, in minutes (default 15)
- stationTimeout: 3, // period of no data change before we declare the station off-line, in minutes (default 3)
- pageUpdateLimit: 20, // period after which the page stops automatically updating, in minutes (default 20),
- // - set to 0 (zero) to disable this feature
- pageUpdatePswd: 'its-me', // password to over ride the page updates time-out, do not set to blank even if you do not use a password - http://&pageUpdate=its-me
- digitalFont: false, // Font control for the gauges & timer
- digitalForecast: false, // Font control for the status display, set this to false for languages that use accented characters in the forecasts
- showPopupData: true, // Pop-up data displayed
- showPopupGraphs: false, // If pop-up data is displayed, show the graphs?
- mobileShowGraphs: false, // If false, on a mobile/narrow display, always disable the graphs
- showWindVariation: true, // Show variation in wind direction over the last 10 minutes on the direction gauge
- showWindMetar: false, // Show the METAR substring for wind speed/direction over the last 10 minutes on the direction gauge popup
- showIndoorTempHum: true, // Show the indoor temperature/humidity options
- showCloudGauge: true, // Display the Cloud Base gauge
- showUvGauge: true, // Display the UV Index gauge
- showSolarGauge: true, // Display the Solar gauge
- showSunshineLed: true, // Show 'sun shining now' LED on solar gauge
- showRoseGauge: true, // Show the optional Wind Rose gauge
- showRoseGaugeOdo: true, // Show the optional Wind Rose gauge wind run Odometer
- showRoseOnDirGauge: true, // Show the rose data as sectors on the direction gauge
- showGaugeShadow: true, // Show a drop shadow outside the gauges
- roundCloudbaseVal: true, // Round the value shown on the cloud base gauge to make it easier to read
- // The realtime files should be absolute paths, "/xxx.txt" refers to the public root of your web server
- realTimeUrlLongPoll: 'realtimegauges-longpoll.php', // *** ALL Users: If using long polling, change to your location of the PHP long poll realtime file ***
- // *** the supplied file is for Cumulus only
- realTimeUrlCumulus: 'realtimegauges.txt', // *** Cumulus Users: Change to your location of the realtime file ***
- realTimeUrlWD: 'customclientraw.txt', // *** WD Users: Change to your location of the ccr file ***
- realTimeUrlVWS: 'steelseriesVWSjson.php', // *** VWS Users: Change to your location of the JSON script generator ***
- realTimeUrlWC: 'realtimegaugesWC.txt', // *** WeatherCat Users: Change to your location of the JSON script generator ***
- realTimeUrlMB: 'MBrealtimegauges.txt', // *** Meteobridge Users: Change to the location of the JSON file
- realTimeUrlWView: 'customclientraw.txt', // *** WView Users: Change to your location of the customclientraw.txt file ***
- realTimeUrlWeewx: 'gauge-data.txt', // *** WeeWX Users: Change to your location of the gauge data file ***
- realTimeUrlWLCOM: 'WLrealtimegauges.php', // *** WLCOM Users: change to location of WLCOMtags.php file ***
- useCookies: true, // Persistently store user preferences in a cookie?
- tip/ images : [],
- dashboardMode: false, // Used by Cumulus MX dashboard - SET TO FALSE OTHERWISE
- dewDisplayType: 'dew' // Initial 'scale' to display on the 'dew point' gauge.
- // 'dew' - Dewpoint
- // 'app' - Apparent temperature
- // 'wnd' - Wind Chill
- // 'feel' - Feels Like
- // 'hea' - Heat Index
- // 'hum' - Humidex
-},
-
- // Gauge global look'n'feel settings
- gaugeGlobals = {
- minMaxArea: 'rgba(212,132,134,0.3)', // area sector for today's max/min. (red, green, blue, transparency)
- windAvgArea: 'rgba(132,212,134,0.3)',
- windVariationSector: 'rgba(120,200,120,0.7)', // only used when rose data is shown on direction gauge
- frameDesign: steelseries.FrameDesign.TILTED_GRAY,
- background: steelseries.BackgroundColor.BEIGE,
- foreground: steelseries.ForegroundType.TYPE1,
- pointer: steelseries.PointerType.TYPE8,
- pointerColour: steelseries.ColorDef.RED,
- dirAvgPointer: steelseries.PointerType.TYPE8,
- dirAvgPointerColour: steelseries.ColorDef.BLUE,
- gaugeType: steelseries.GaugeType.TYPE4,
- lcdColour: steelseries.LcdColor.STANDARD,
- knob: steelseries.KnobType.STANDARD_KNOB,
- knobStyle: steelseries.KnobStyle.SILVER,
- labelFormat: steelseries.LabelNumberFormat.STANDARD,
- tickLabelOrientation: steelseries.TickLabelOrientation.HORIZONTAL, // was .NORMAL up to v1.6.4
- rainUseSectionColours: false, // Only one of these colour options should be true
- rainUseGradientColours: false, // Set both to false to use the pointer colour
- tempTrendVisible: true,
- pressureTrendVisible: true,
- uvLcdDecimals: 1,
- // sunshine threshold values
- sunshineThreshold: 50, // the value in W/m² above which we can consider the Sun to be shining, *if* the current value exceeds...
- sunshineThresholdPct: 75, // the percentage of theoretical solar irradiance above which we consider the Sun to be shining
- // default gauge ranges - before auto-scaling/ranging
- tempScaleDefMinC: -20,
- tempScaleDefMaxC: 40,
- tempScaleDefMinF: 0,
- tempScaleDefMaxF: 100,
- baroScaleDefMinhPa: 990,
- baroScaleDefMaxhPa: 1030,
- baroScaleDefMinkPa: 99,
- baroScaleDefMaxkPa: 103,
- baroScaleDefMininHg: 29.2,
- baroScaleDefMaxinHg: 30.4,
- windScaleDefMaxMph: 20,
- windScaleDefMaxKts: 20,
- windScaleDefMaxMs: 10,
- windScaleDefMaxKmh: 30,
- rainScaleDefMaxmm: 10,
- rainScaleDefMaxIn: 0.5,
- rainRateScaleDefMaxmm: 10,
- rainRateScaleDefMaxIn: 0.5,
- uvScaleDefMax: 10, // Northern Europe may be lower - max. value recorded in the UK is 8, so use a scale of 10 for UK
- solarGaugeScaleMax: 1000, // Max value to be shown on the solar gauge - theoretical max without atmosphere ~ 1374 W/m²
- // - but Davis stations can read up to 1800, use 1000 for Northern Europe?
- cloudScaleDefMaxft: 3000,
- cloudScaleDefMaxm: 1000,
- shadowColour: 'rgba(0,0,0,0.3)' // Colour to use for gauge shadows - default 30% transparent black
- },
-
- commonParams = {
- // Common parameters for all the SteelSeries gauges
- fullScaleDeflectionTime: 4, // Bigger numbers (seconds) slow the gauge pointer movements more
- gaugeType: gaugeGlobals.gaugeType,
- minValue: 0,
- niceScale: true,
- ledVisible: false,
- frameDesign: gaugeGlobals.frameDesign,
- backgroundColor: gaugeGlobals.background,
- foregroundType: gaugeGlobals.foreground,
- pointerType: gaugeGlobals.pointer,
- pointerColor: gaugeGlobals.pointerColour,
- knobType: gaugeGlobals.knob,
- knobStyle: gaugeGlobals.knobStyle,
- lcdColor: gaugeGlobals.lcdColour,
- lcdDecimals: 1,
- digitalFont: config.digitalFont,
- tickLabelOrientation: gaugeGlobals.tickLabelOrientation,
- labelNumberFormat: gaugeGlobals.labelFormat
- },
- firstRun = true, // Used to set-up units & scales etc
- userUnitsSet = false, // Tracks if the display units have been set by a user preference
- data = {}, // Stores all the values from realtime.txt
- tickTockInterval, // The 1s clock interval timer
-
- // ajaxDelay, used by long polling, the delay between getting a response and queueing the next request, as the default PHP
- // script runtime timout is 30 seconds, we do not want the PHP task to run for more than 20 seconds. So queue the next
- // request half of the realtime interval, or 20 seconds before it is due, which ever is the larger.
- ajaxDelay = config.longPoll ? Math.max(config.realtimeInterval - 20, 0) : config.realtimeInterval,
- downloadTimer, // Stores a reference to the ajax download setTimout() timer
- timestamp = 0, // the timestamp of last data update on the server.
- jqXHR = null, // handle to the jQuery web request
- displayUnits = null, // Stores the display units cookie settings
- sampleDate,
- realtimeVer, // minimum version of the realtime JSON file required
- programLink = [
- 'Cumulus',
- 'Weather Display',
- 'Virtual Weather Station',
- 'WeatherCat',
- 'Meteobridge',
- 'Wview',
- 'weewx',
- 'Weatherlink.com'
- ],
-
- ledIndicator, statusScroller, statusTimer,
-
- gaugeTemp, gaugeDew, gaugeRain, gaugeRRate,
- gaugeHum, gaugeBaro, gaugeWind, gaugeDir,
- gaugeUV, gaugeSolar, gaugeCloud, gaugeRose,
-
- /* _imgBackground, // Uncomment if using a background image on the gauges */
-
- // ==================================================================================================================
- // Nothing below this line needs to be modified for the gauges as supplied
- // - unless you really know what you are doing
- // - but remember, if you break it, it's up to you to fix it ;-)
- // ==================================================================================================================
-
- //
- // init() Called when the document is ready, pre-draws the Status Display then calls
- // the first Ajax fetch of realtimegauges.txt. First draw of the gauges now deferred until
- // the Ajax data is available as a 'speed up'.
- //
- init = function (dashboard) {
- // Cumulus, Weather Display, VWS, WeatherCat?
- switch (config.weatherProgram) {
- case 0:
- // Cumulus
- realtimeVer = 12; // minimum version of the realtime JSON file required
- config.realTimeURL = config.longPoll ? config.realTimeUrlLongPoll : config.realTimeUrlCumulus;
- // the trend /images to be used for the pop-up data, used in conjunction with config.imgPathURL
- // by default this is configured for the Cumulus 'standard' web site
- // ** If you specify one image in a sub-array, then you MUST provide /images for all the other sub-elements
- config.tipImgs = [ // config.tipImgs for Cumulus users using the 'default' weather site
- ['temp.png', 'intemp.png'], // Temperature: outdoor, indoor
- // Temperature: dewpoint, apparent, windChill, heatIndex, humidex
- ['temp.png', 'temp.png', 'temp.png', 'temp.png', 'temp.png'],
- 'raint.png', // Rainfall
- 'rain.png', // Rainfall rate
- ['hum.png', 'hum.png'], // Humidity: outdoor, indoor
- 'press.png', // Pressure
- 'wind.png', // Wind speed
- 'windd.png', // Wind direction
- (config.showUvGauge ? 'uv.png' : null), // UV graph if UV sensor is present | =null if no UV sensor
- (config.showSolarGauge ? 'solar.png' : null), // Solar rad graph if Solar sensor is present | Solar =null if no Solar sensor
- (config.showRoseGauge ? 'windd.png' : null), // Wind direction if Rose is enabled | =null if Rose is disabled
- (config.showCloudGauge ? 'press.png' : null) // Pressure for cloud height | =null if Cloud Height is disabled
- ];
- break;
- case 1:
- // Weather Display
- realtimeVer = 14; // minimum version of the realtime JSON file required
- config.realTimeURL = config.longPoll ? config.realTimeUrlLongPoll : config.realTimeUrlWD;
- config.tipImgs = [ // config.tipImgs for Weather Display users with wxgraph
- ['temp+hum_24hr.php', 'indoor_temp_24hr.php'], // Temperature: outdoor, indoor
- // Temperature: dewpnt, apparent, windChill, HeatIndx, humidex
- ['temp+dew+hum_1hr.php', 'temp+dew+hum_1hr.php', 'temp+dew+hum_1hr.php', 'temp+dew+hum_1hr.php', 'temp+dew+hum_1hr.php'],
- 'rain_24hr.php', // Rainfall
- 'rain_1hr.php', // Rainfall rate
- ['humidity_1hr.php', 'humidity_7days.php'], // Humidity: outdoor, indoor
- 'baro_24hr.php', // Pressure
- 'windgust_1hr.php', // Wind speed
- 'winddir_24hr.php', // Wind direction
- (config.showUvGauge ? 'uv_24hr.php' : null), // UV graph if UV sensor is present | =null if no UV sensor
- (config.showSolarGauge ? 'solar_24hr.php' : null), // Solar rad graph if Solar sensor is present | Solar =null if no Solar sensor
- (config.showRoseGauge ? 'winddir_24hr.php' : null), // Wind direction if Rose is enabled | =null if Rose is disabled
- (config.showCloudGauge ? 'baro_24hr.php' : null) // Pressure for cloud height | =null if Cloud Height is disabled
- ];
- // WD useer generally use wxgraphs - tweak the CSS to accomadate the different aspect ratio
- $('.tipimg').css({
- width: '360px',
- height: '260px'
- });
- break;
- case 2:
- // WVS
- realtimeVer = 11; // minimum version of the realtime JSON file required
- config.realTimeURL = config.longPoll ? config.realTimeUrlLongPoll : config.realTimeUrlVWS;
- config.showRoseGauge = false; // no wind rose data from VWS
- config.showCloudGauge = false;
- config.tipImgs = [ // config.tipImgs for VWS users
- ['vws742.jpg', 'vws741.jpg'], // Temperature: outdoor, indoor
- // Temperature: dewpnt, apparent, windChill, HeatIndx, humidex
- ['vws757.jpg', 'vws762.jpg', 'vws754.jpg', 'vws756.jpg', null],
- 'vws744.jpg', // Rainfall
- 'vws859.jpg', // Rainfall rate
- ['vws740.jpg', 'vws739.jpg'], // Humidity: outdoor, indoor
- 'vws758.jpg', // Pressure
- 'vws737.jpg', // Wind speed
- 'vws736.jpg', // Wind direction
- (config.showUvGauge ? 'vws752.jpg' : null), // UV graph if UV sensor is present | =null if no UV sensor
- (config.showSolarGauge ? 'vws753.jpg' : null), // Solar rad graph if Solar sensor is present | Solar =null if no Solar sensor
- (config.showRoseGauge ? 'vws736.jpg' : null), // Wind direction if Rose is enabled | =null if Rose is disabled
- (config.showCloudGauge ? 'vws758.jpg' : null) // Pressure for cloud height | =null if Cloud Height is disabled
- ];
- break;
- case 3:
- // WeatherCat
- realtimeVer = 14; // minimum version of the realtime JSON file required
- config.realTimeURL = config.longPoll ? config.realTimeUrlLongPoll : config.realTimeUrlWC;
- config.tipImgs = [ // config.tipImgs - WeatherCat users using the 'default' weather site
- ['temperature1.jpg', 'tempin1.jpg'], // Temperature: outdoor, indoor
- // Temperature: dewpoint, apparent, windChill, heatIndex, humidex
- ['dewpoint1.jpg', 'temperature1.jpg', 'windchill1.jpg', 'heatindex1.jpg', 'temperature1.jpg'],
- 'precipitationc1.jpg', // Rainfall
- 'precipitation1.jpg', // Rainfall rate
- ['rh1.jpg', 'rhin1.jpg'], // Humidity: outdoor, indoor
- 'pressure1.jpg', // Pressure
- 'windspeed1.jpg', // Wind speed
- 'winddirection1.jpg', // Wind direction
- (config.showUvGauge ? 'uv1.jpg' : null), // UV graph if UV sensor is present | =null if no UV sensor
- (config.showSolarGauge ? 'solarrad1.jpg' : null), // Solar rad graph if Solar sensor is present | Solar =null if no Solar sensor
- (config.showRoseGauge ? 'winddirection1.jpg' : null), // Wind direction if Rose is enabled | =null if Rose is disabled
- (config.showCloudGauge ? 'cloudbase1.jpg' : null) // Pressure for cloud height | =null if Cloud Height is disabled
- ];
- break;
- case 4:
- // Meteobridge
- realtimeVer = 10; // minimum version of the realtime JSON file required
- config.realTimeURL = config.longPoll ? config.realTimeUrlLongPoll : config.realTimeUrlMB;
- config.showPopupGraphs = false; // config.tipImgs - no Meteobridge /images available
- config.showRoseGauge = false; // no windrose data from MB
- config.showCloudGauge = false;
- config.tipImgs = null; // config.tipImgs - no Meteobridge /images available
- config.showWindVariation = false; // no wind variation data from MB
- break;
- case 5:
- // WView
- realtimeVer = 11; // minimum version of the realtime JSON file required
- config.realTimeURL = config.longPoll ? config.realTimeUrlLongPoll : config.realTimeUrlWView;
- config.showSunshineLed = false; // WView does not provide the current theoretical solar max required to determine sunshine
- config.showWindVariation = false; // no wind variation from WView
- config.showRoseGauge = false; // No wind rose array from WView by default - there is a user supplied modification to enable it though.
- config.showCloudGauge = false;
- config.tipImgs = [ // config.tipImgs for WView users
- ['tempdaycomp.png', 'indoor_temp.png'], // Temperature: outdoor, indoor
- // Temperature: dewpnt, apparent, windChill, HeatIndx, humidex
- ['tempdaycomp.png', 'tempdaycomp.png', 'heatchillcomp.png', 'heatchillcomp.png', 'tempdaycomp.png'],
- 'rainday.png', // Rainfall
- 'rainrate.png', // Rainfall rate
- ['humidday.png', 'humidday.png'], // Humidity: outdoor, indoor
- 'baromday.png', // Pressure
- 'wspeeddaycomp.png', // Wind speed
- 'wdirday.png', // Wind direction
- (config.showUvGauge ? 'uvday.png' : null), // UV graph if UV sensor is present | =null if no UV sensor
- (config.showSolarGauge ? 'solarday.png' : null), // Solar rad graph if Solar sensor is present | Solar =null if no Solar sensor
- (config.showRoseGauge ? 'windroseday.png' : null), // Wind direction if Rose is enabled | =null if Rose is disabled
- (config.showCloudGauge ? 'baromday.png' : null) // Pressure for cloud height | =null if Cloud Height is disabled
- ];
- break;
- case 6:
- // weewx
- realtimeVer = 14; // minimum version of the realtime JSON file required
- config.realTimeURL = config.longPoll ? config.realTimeUrlLongPoll : config.realTimeUrlWeewx;
- config.showSunshineLed = true;
- config.showWindVariation = true;
- config.tipImgs = [ // config.tipImgs for weewx
- ['dayinouttemp.png', 'dayinouttemp.png'], // Temperature: outdoor, indoor
- // Temperature: dewpnt, apparent, windChill, HeatIndx, humidex
- ['dayouttemphum.png', 'dayouttemphum.png', 'dayouttemphum.png', 'dayouttemphum.png', 'dayouttemphum.png'],
- 'dayrain.png', // Rainfall
- 'dayrainrate.png', // Rainfall rate
- ['dayinouthum.png', 'dayinouthum.png'], // Humidity: outdoor, indoor
- 'daybarometer.png', // Pressure
- 'daywind.png', // Wind speed
- 'daywinddir.png', // Wind direction
- (config.showUvGauge ? 'dayuv.png' : null), // UV graph if UV sensor is present | =null if no UV sensor
- (config.showSolarGauge ? 'dayradiation.png' : null), // Solar rad graph if Solar sensor is present | Solar =null if no Solar sensor
- (config.showRoseGauge ? 'daywindvec.png' : null), // Wind direction if Rose is enabled | =null if Rose is disabled
- (config.showCloudGauge ? 'daybarometer.png' : null) // Pressure for cloud height | =null if Cloud Height is disabled
- ];
- break;
- case 7:
- // WLCOM
- realtimeVer = 10; // minimum version of the realtime JSON file required
- config.realTimeURL = config.realTimeUrlWLCOM;
- config.showPopupGraphs = false; // config.tipImgs - no WL /images available
- config.showRoseGauge = false; // no windrose data from WL
- config.showCloudGauge = false;
- config.tipImgs = null; // config.tipImgs - no WL /images available
- config.showWindVariation = false; // no wind variation data from WL
- break;
- default:
- // Who knows!
- realtimeVer = 0; // minimum version of the realtime JSON file required
- config.realtimeURL = null;
- config.showPopupGraphs = false;
- config.tipImgs = null; // config.tipImgs - unknown
- }
-
- // Are we running on a phone device (or really low res screen)?
- if ($(window).width() < 480) {
- // Change the gauge scaling
- config.gaugeScaling = config.gaugeMobileScaling;
- // Switch off graphs?
- config.showPopupGraphs = config.mobileShowGraphs;
- } else {
- config.gaugeScaling = 1;
- }
-
- // Logo /images are used to 'personalise' the gauge backgrounds
- // To add a logo to a gauge, add the parameter:
- // params.customLayer = _imgBackground;
- // to the corresponding drawXxxx() function below.
- //
- // These are for demo only, to add them remove the comments around the following lines, and
- // the _imgBackground definition line above...
- /*
- _imgBackground = document.createElement('img'); // small logo
- $(_imgBackground).attr('src', config.imgPathURL + 'logoSmall.png');
- */
- // End of logo /images
-
- // Get the display units the user last used when they visited before - if present
- displayUnits = getCookie('units');
- // Set 'units' radio buttons to match preferred units
- if (displayUnits !== null) {
- // User wants specific units
- userUnitsSet = true;
-
- // temperature
- setRadioCheck('rad_unitsTemp', displayUnits.temp);
- data.tempunit = '°' + displayUnits.temp;
- // rain
- setRadioCheck('rad_unitsRain', displayUnits.rain);
- data.rainunit = displayUnits.rain;
- // pressure
- setRadioCheck('rad_unitsPress', displayUnits.press);
- data.pressunit = displayUnits.press;
- // wind
- setRadioCheck('rad_unitsWind', displayUnits.wind);
- data.windunit = displayUnits.wind;
- displayUnits.windrun = getWindrunUnits(data.windunit);
- // cloud base
- setRadioCheck('rad_unitsCloud', displayUnits.cloud);
- data.cloudunit = displayUnits.cloud;
- } else {
- // Set the defaults to metric )
- // DO NOT CHANGE THESE - THE SCRIPT DEPENDS ON THESE DEFAULTS
- // The units actually displayed will be read from the realtime.txt file, or from the users last visit cookie
- displayUnits = {
- temp: 'C',
- rain: 'mm',
- press: 'hPa',
- wind: 'km/h',
- windrun: 'km',
- cloud: 'm'
- };
-
- data.tempunit = '°C';
- data.rainunit = 'mm';
- data.pressunit = 'hPa';
- data.windunit = 'km/h';
- data.cloudunit = 'm';
- }
-
- // enable popup data
- if (config.showPopupData) {
- ddimgtooltip.showTips = config.showPopupData;
- }
-
- if (config.showPopupGraphs) {
- // Note the number of array elements must match 'i' in ddimgtooltip.tiparray()
- ddimgtooltip.tiparray[0][0] = (config.tipImgs[0][0] === null ? null : '');
- ddimgtooltip.tiparray[1][0] = (config.tipImgs[1][0] === null ? null : '');
- ddimgtooltip.tiparray[2][0] = (config.tipImgs[2] === null ? null : '');
- ddimgtooltip.tiparray[3][0] = (config.tipImgs[3] === null ? null : '');
- ddimgtooltip.tiparray[4][0] = (config.tipImgs[4][0] === null ? null : '');
- ddimgtooltip.tiparray[5][0] = (config.tipImgs[5] === null ? null : '');
- ddimgtooltip.tiparray[6][0] = (config.tipImgs[6] === null ? null : '');
- ddimgtooltip.tiparray[7][0] = (config.tipImgs[7] === null ? null : '');
- ddimgtooltip.tiparray[8][0] = (config.tipImgs[8] === null ? null : '');
- ddimgtooltip.tiparray[9][0] = (config.tipImgs[9] === null ? null : '');
- ddimgtooltip.tiparray[10][0] = (config.tipImgs[10] === null ? null : '');
- ddimgtooltip.tiparray[11][0] = (config.tipImgs[11] === null ? null : '');
- }
-
- // draw the status gadgets first, they will display any errors in the initial set-up
- ledIndicator = singleLed.getInstance();
- statusScroller = singleStatus.getInstance();
- statusTimer = singleTimer.getInstance();
-
- gaugeTemp = singleTemp.getInstance();
- // Export gaugeTemp.update() so it can be called from the HTML code
- if (gaugeTemp) { gauges.doTemp = gaugeTemp.update; }
-
- gaugeDew = singleDew.getInstance();
- // Export gaugeDew.update() so it can be called from the HTML code
- if (gaugeDew) { gauges.doDew = gaugeDew.update; }
-
- gaugeHum = singleHum.getInstance();
- // Export gaugeHum.update() so it can be called from the HTML code
- if (gaugeHum) { gauges.doHum = gaugeHum.update; }
-
- gaugeBaro = singleBaro.getInstance();
-
- gaugeWind = singleWind.getInstance();
- gaugeDir = singleDir.getInstance();
-
- gaugeRain = singleRain.getInstance();
- gaugeRRate = singleRRate.getInstance();
-
- // remove the UV gauge?
- if (!config.showUvGauge) {
- $('#canvas_uv').parent().remove();
- } else {
- gaugeUV = singleUV.getInstance();
- }
-
- // remove the Solar gauge?
- if (!config.showSolarGauge) {
- $('#canvas_solar').parent().remove();
- } else {
- gaugeSolar = singleSolar.getInstance();
- }
-
- // remove the Wind Rose?
- if (!config.showRoseGauge) {
- $('#canvas_rose').parent().remove();
- } else {
- gaugeRose = singleRose.getInstance();
- }
-
- // remove the cloud base gauge?
- if (!config.showCloudGauge) {
- $('#canvas_cloud').parent().remove();
- // and remove cloudbase unit selection options
- $('#cloud').parent().remove();
- } else {
- gaugeCloud = singleCloudBase.getInstance();
- }
-
- // Set the language
- changeLang(strings, false);
-
- if (!dashboard) {
- // Go do get the data!
- getRealtime();
-
- // start a timer to update the status time
- tickTockInterval = setInterval(
- function () {
- $.publish('gauges.clockTick', null);
- },
- 1000);
-
- // start a timer to stop the page updates after the timeout period
- if (config.pageUpdateLimit > 0 && getUrlParam('pageUpdate') !== config.pageUpdatePswd) {
- setTimeout(pageTimeout, config.pageUpdateLimit * 60 * 1000);
- }
- }
- },
-
- //
- // singleXXXX functions define a singleton for each of the gauges
- //
-
- //
- // Singleton for the LED Indicator
- //
- singleLed = (function () {
- var instance; // Stores a reference to the Singleton
- var led; // Stores a reference to the SS LED
-
- function init() {
- // create led indicator
- if ($('#canvas_led').length) {
- led = new steelseries.Led(
- 'canvas_led', {
- ledColor: steelseries.LedColor.GREEN_LED,
- size: $('#canvas_led').width()
- });
-
- setTitle(strings.led_title);
- }
-
- function setTitle(newTitle) {
- $('#canvas_led').attr('title', newTitle);
- }
-
- function setLedColor(newColour) {
- if (led) {
- led.setLedColor(newColour);
- }
- }
-
- function setLedOnOff(onState) {
- if (led) {
- led.setLedOnOff(onState);
- }
- }
-
- function blink(blinkState) {
- if (led) {
- led.blink(blinkState);
- }
- }
-
- return {
- setTitle: setTitle,
- setLedColor: setLedColor,
- setLedOnOff: setLedOnOff,
- blink: blink
- };
- }
-
- return {
- // Get the Singleton instance if one exists
- // or create one if it doesn't
- getInstance: function () {
- if (!instance) {
- instance = init();
- }
- return instance;
- }
- };
- })(),
-
- //
- // Singleton for the Status Scroller
- //
- singleStatus = (function () {
- var instance; // Stores a reference to the Singleton
- var scroller; // Stores a reference to the SS scrolling display
-
- function init() {
- // create forecast display
- if ($('#canvas_status').length) {
- scroller = new steelseries.DisplaySingle(
- 'canvas_status', {
- width: $('#canvas_status').width(),
- height: $('#canvas_status').height(),
- lcdColor: gaugeGlobals.lcdColour,
- unitStringVisible: false,
- value: strings.statusStr,
- digitalFont: config.digitalForecast,
- valuesNumeric: false,
- autoScroll: true,
- alwaysScroll: false
- });
- }
-
- function setValue(newTxt) {
- if (scroller) {
- scroller.setValue(newTxt);
- }
- }
-
- return { setText: setValue };
- }
-
- return {
- // Get the Singleton instance if one exists
- // or create one if it doesn't
- getInstance: function () {
- if (!instance) {
- instance = init();
- }
- return instance;
- }
- };
- })(),
-
- //
- // Singleton for the Status Timer
- //
- singleTimer = (function () {
- var instance, // Stores a reference to the Singleton
- lcd, // Stores a reference to the SS LED
- count = 1;
-
- function init() {
- function tick() {
- if (lcd) {
- lcd.setValue(count);
- count += config.longPoll ? 1 : -1;
- }
- }
-
- function reset(val) {
- count = val;
- }
-
- function setValue(newVal) {
- if (lcd) {
- lcd.setValue(newVal);
- }
- }
-
- // create timer display
- if ($('#canvas_timer').length) {
- lcd = new steelseries.DisplaySingle(
- 'canvas_timer', {
- width: $('#canvas_timer').width(),
- height: $('#canvas_timer').height(),
- lcdColor: gaugeGlobals.lcdColour,
- lcdDecimals: 0,
- unitString: strings.timer,
- unitStringVisible: true,
- digitalFont: config.digitalFont,
- value: count
- });
- // subscribe to data updates
- $.subscribe('gauges.clockTick', tick);
- }
-
- return {
- reset: reset,
- setValue: setValue
- };
- }
-
- return {
- // Get the Singleton instance if one exists
- // or create one if it doesn't
- getInstance: function () {
- if (!instance) {
- instance = init();
- }
- return instance;
- }
- };
- })(),
-
- //
- // Singleton for the Temperature Gauge
- //
- singleTemp = (function () {
- var instance; // Stores a reference to the Singleton
- var ssGauge; // Stores a reference to the SS Gauge
- var cache = {}; // Stores various config values and parameters
-
- function init() {
- var params = $.extend(true, {}, commonParams);
-
- // define temperature gauge start values
- cache.sections = createTempSections(true);
- cache.areas = [];
- cache.minValue = gaugeGlobals.tempScaleDefMinC;
- cache.maxValue = gaugeGlobals.tempScaleDefMaxC;
- cache.title = strings.temp_title_out;
- cache.value = gaugeGlobals.tempScaleDefMinC + 0.0001;
- cache.maxMinVisible = false;
- cache.selected = 'out';
-
- // create temperature radial gauge
- if ($('#canvas_temp').length) {
- params.size = Math.ceil($('#canvas_temp').width() * config.gaugeScaling);
- params.section = cache.sections;
- params.area = cache.areas;
- params.minValue = cache.minValue;
- params.maxValue = cache.maxValue;
- params.thresholdVisible = false;
- params.minMeasuredValueVisible = cache.maxMinVisible;
- params.maxMeasuredValueVisible = cache.maxMinVisible;
- params.titleString = cache.title;
- params.unitString = data.tempunit;
- params.trendVisible = gaugeGlobals.tempTrendVisible;
- // params.customLayer = _imgBackground; // uncomment to add a background image - See Logo /images above
-
- ssGauge = new steelseries.Radial('canvas_temp', params);
- ssGauge.setValue(cache.value);
-
- // over-ride CSS applied size?
- if (config.gaugeScaling !== 1) {
- $('#canvas_temp').css({ width: params.size + 'px', height: params.size + 'px' });
- }
-
- // add a shadow to the gauge
- if (config.showGaugeShadow) {
- $('#canvas_temp').css(gaugeShadow(params.size));
- }
-
- // remove indoor temperature/humidity options?
- if (!config.showIndoorTempHum) {
- $('#rad_temp1').remove();
- $('#lab_temp1').remove();
- $('#rad_temp2').remove();
- $('#lab_temp2').remove();
- $('#rad_hum1').remove();
- $('#lab_hum1').remove();
- $('#rad_hum2').remove();
- $('#lab_hum2').remove();
- }
-
- // subscribe to data updates
- $.subscribe('gauges.dataUpdated', update);
- $.subscribe('gauges.graphUpdate', updateGraph);
- } else {
- // cannot draw gauge, return null
- return null;
- }
-
- function update() {
- var sel = cache.selected;
-
- // Argument length === 1 when called from radio input
- // Argument length === 2 when called from event handler
- if (arguments.length === 1) {
- sel = arguments[0].value;
- }
-
- // if rad isn't specified, just use existing value
- var t1, scaleStep, tip;
-
- cache.minValue = data.tempunit[1] === 'C' ? gaugeGlobals.tempScaleDefMinC : gaugeGlobals.tempScaleDefMinF;
- cache.maxValue = data.tempunit[1] === 'C' ? gaugeGlobals.tempScaleDefMaxC : gaugeGlobals.tempScaleDefMaxF;
-
- if (sel === 'out') {
- cache.low = extractDecimal(data.tempTL);
- cache.high = extractDecimal(data.tempTH);
- cache.lowScale = getMinTemp(cache.minValue);
- cache.highScale = getMaxTemp(cache.maxValue);
- cache.value = extractDecimal(data.temp);
- cache.title = strings.temp_title_out;
- cache.loc = strings.temp_out_info;
- cache.trendVal = extractDecimal(data.temptrend);
- cache.popupImg = 0;
- if (gaugeGlobals.tempTrendVisible) {
- t1 = tempTrend(+cache.trendVal, data.tempunit, false);
- if (t1 === -9999) {
- // trend value isn't currently available
- cache.trend = steelseries.TrendState.OFF;
- } else if (t1 > 0) {
- cache.trend = steelseries.TrendState.UP;
- } else if (t1 < 0) {
- cache.trend = steelseries.TrendState.DOWN;
- } else {
- cache.trend = steelseries.TrendState.STEADY;
- }
- }
- } else {
- // Indoor
- cache.title = strings.temp_title_in;
- cache.loc = strings.temp_in_info;
- cache.value = extractDecimal(data.intemp);
- cache.popupImg = 1;
- if (data.intempTL && data.intempTH) {
- // Indoor - and Max/Min values supplied
- cache.low = extractDecimal(data.intempTL);
- cache.high = extractDecimal(data.intempTH);
- cache.lowScale = getMinTemp(cache.minValue);
- cache.highScale = getMaxTemp(cache.maxValue);
- } else {
- // Indoor - no Max/Min values supplied
- cache.low = cache.value;
- cache.lowScale = cache.value;
- cache.high = cache.value;
- cache.highScale = cache.value;
- }
- if (gaugeGlobals.tempTrendVisible) {
- cache.trend = steelseries.TrendState.OFF;
- }
- }
-
- // has the gauge type changed?
- if (cache.selected !== sel) {
- cache.selected = sel;
- // Change gauge title
- ssGauge.setTitleString(cache.title);
- ssGauge.setMaxMeasuredValueVisible(cache.maxMinVisible);
- ssGauge.setMinMeasuredValueVisible(cache.maxMinVisible);
- if (config.showPopupGraphs && config.tipImgs[0][cache.popupImg] !== null) {
- var cacheDefeat = '?' + $('#imgtip0_img').attr('src').split('?')[1];
- $('#imgtip0_img').attr('src', config.imgPathURL + config.tipImgs[0][cache.popupImg] + cacheDefeat);
- }
- }
-
- // auto scale the ranges
- scaleStep = data.tempunit[1] === 'C' ? 10 : 20;
- while (cache.lowScale < cache.minValue) {
- cache.minValue -= scaleStep;
- if (cache.highScale <= cache.maxValue - scaleStep) {
- cache.maxValue -= scaleStep;
- }
- }
- while (cache.highScale > cache.maxValue) {
- cache.maxValue += scaleStep;
- if (cache.minValue >= cache.minValue + scaleStep) {
- cache.minValue += scaleStep;
- }
- }
-
- if (cache.minValue !== ssGauge.getMinValue() || cache.maxValue !== ssGauge.getMaxValue()) {
- ssGauge.setMinValue(cache.minValue);
- ssGauge.setMaxValue(cache.maxValue);
- ssGauge.setValue(cache.minValue);
- }
- if (cache.selected === 'out') {
- cache.areas = [steelseries.Section(+cache.low, +cache.high, gaugeGlobals.minMaxArea)];
- } else if (data.intempTL && data.intempTH) {
- // Indoor and min/max avaiable
- cache.areas = [steelseries.Section(+cache.low, +cache.high, gaugeGlobals.minMaxArea)];
- } else {
- // Indoor no min/max avaiable
- cache.areas = [];
- }
-
- if (gaugeGlobals.tempTrendVisible) {
- ssGauge.setTrend(cache.trend);
- }
- ssGauge.setArea(cache.areas);
- ssGauge.setValueAnimated(+cache.value);
-
- if (ddimgtooltip.showTips) {
- // update tooltip
- if (cache.selected === 'out') {
- tip = cache.loc + ' - ' + strings.lowestF_info + ': ' + cache.low + data.tempunit + ' ' + strings.at + ' ' + data.TtempTL +
- ' | ' +
- strings.highestF_info + ': ' + cache.high + data.tempunit + ' ' + strings.at + ' ' + data.TtempTH;
- if (cache.trendVal !== -9999) {
- tip += '
' +
- strings.temp_trend_info + ': ' + tempTrend(cache.trendVal, data.tempunit, true) +
- ' ' + cache.trendVal + data.tempunit + '/h';
- }
- } else if (data.TintempTL && data.TintempTH) {
- // Indoor and min/max available
- tip = cache.loc + ' - ' + strings.lowestF_info + ': ' + cache.low + data.tempunit + ' ' + strings.at + ' ' + data.TintempTL +
- ' | ' +
- strings.highestF_info + ': ' + cache.high + data.tempunit + ' ' + strings.at + ' ' + data.TintempTH;
- } else {
- // Indoor no min/max
- tip = cache.loc + ': ' + data.intemp + data.tempunit;
- }
- $('#imgtip0_txt').html(tip);
- }
- } // End of update()
-
- function updateGraph(evnt, cacheDefeat) {
- if (config.tipImgs[0][cache.popupImg] !== null) {
- $('#imgtip0_img').attr('src', config.imgPathURL + config.tipImgs[0][cache.popupImg] + cacheDefeat);
- }
- }
-
- return {
- data: cache,
- update: update,
- gauge: ssGauge
- };
- } // End of init()
-
- return {
- // Get the Singleton instance if one exists
- // or create one if it doesn't
- getInstance: function () {
- if (!instance) {
- instance = init();
- }
- return instance;
- }
- };
- })(), // End singleTemp()
-
- //
- // Singleton for the Dewpoint Gauge
- //
- singleDew = (function () {
- var instance; // Stores a reference to the Singleton
- var ssGauge; // Stores a reference to the SS Gauge
- var cache = {}; // Stores various config values and parameters
-
- function init() {
- var params = $.extend(true, {}, commonParams);
- var tmp;
-
- // define dew point gauge start values
- cache.sections = createTempSections(true);
- cache.areas = [];
- cache.minValue = gaugeGlobals.tempScaleDefMinC;
- cache.maxValue = gaugeGlobals.tempScaleDefMaxC;
- cache.value = gaugeGlobals.tempScaleDefMinC + 0.0001;
- // Has the end user selected a preferred 'scale' before
- tmp = getCookie('dewGauge');
- cache.selected = tmp !== null ? tmp : config.dewDisplayType;
- setRadioCheck('rad_dew', cache.selected);
- switch (cache.selected) {
- case 'dew':
- cache.title = strings.dew_title;
- cache.popupImg = 0;
- break;
- case 'app':
- cache.title = strings.apptemp_title;
- cache.popupImg = 1;
- break;
- case 'feel':
- cache.title = strings.feel_title;
- cache.popupImg = 1;
- break;
- case 'wnd':
- cache.title = strings.chill_title;
- cache.popupImg = 2;
- break;
- case 'hea':
- cache.title = strings.heat_title;
- cache.popupImg = 3;
- break;
- case 'hum':
- cache.title = strings.humdx_title;
- cache.popupImg = 4;
- // no default
- }
- cache.minMeasuredVisible = false;
- cache.maxMeasuredVisible = false;
-
- // create dew point radial gauge
- if ($('#canvas_dew').length) {
- params.size = Math.ceil($('#canvas_dew').width() * config.gaugeScaling);
- params.section = cache.sections;
- params.area = cache.areas;
- params.minValue = cache.minValue;
- params.maxValue = cache.maxValue;
- params.thresholdVisible = false;
- params.titleString = cache.title;
- params.unitString = data.tempunit;
-
- ssGauge = new steelseries.Radial('canvas_dew', params);
- ssGauge.setValue(cache.value);
-
- // over-ride CSS applied size?
- if (config.gaugeScaling !== 1) {
- $('#canvas_dew').css({ width: params.size + 'px', height: params.size + 'px' });
- }
-
- // add a shadow to the gauge
- if (config.showGaugeShadow) {
- $('#canvas_dew').css(gaugeShadow(params.size));
- }
-
- // subscribe to data updates
- $.subscribe('gauges.dataUpdated', update);
- $.subscribe('gauges.graphUpdate', updateGraph);
- } else {
- // cannot draw gauge, return null
- return null;
- }
-
- function update() {
- // if rad isn't specified, just use existing value
- var sel = cache.selected;
-
- // Argument length === 2 when called from event handler
- if (arguments.length === 1) {
- sel = arguments[0].value;
- // save the choice in a cookie
- setCookie('dewGauge', sel);
- }
-
- var tip, scaleStep;
-
- cache.minValue = data.tempunit[1] === 'C' ? gaugeGlobals.tempScaleDefMinC : gaugeGlobals.tempScaleDefMinF;
- cache.maxValue = data.tempunit[1] === 'C' ? gaugeGlobals.tempScaleDefMaxC : gaugeGlobals.tempScaleDefMaxF;
-
- cache.lowScale = getMinTemp(cache.minValue);
- cache.highScale = getMaxTemp(cache.maxValue);
-
- switch (sel) {
- case 'dew': // dew point
- cache.low = extractDecimal(data.dewpointTL);
- cache.high = extractDecimal(data.dewpointTH);
- cache.value = extractDecimal(data.dew);
- cache.areas = [steelseries.Section(+cache.low, +cache.high, gaugeGlobals.minMaxArea)];
- cache.title = strings.dew_title;
- cache.minMeasuredVisible = false;
- cache.maxMeasuredVisible = false;
- cache.popupImg = 0;
- tip = strings.dew_info + ':' +
- '
' +
- '- ' + strings.lowest_info + ': ' + cache.low + data.tempunit + ' ' + strings.at + ' ' + data.TdewpointTL +
- ' | ' + strings.highest_info + ': ' + cache.high + data.tempunit + ' ' + strings.at + ' ' + data.TdewpointTH;
- break;
- case 'app': // apparent temperature
- cache.low = extractDecimal(data.apptempTL);
- cache.high = extractDecimal(data.apptempTH);
- cache.value = extractDecimal(data.apptemp);
- cache.areas = [steelseries.Section(+cache.low, +cache.high, gaugeGlobals.minMaxArea)];
- cache.title = strings.apptemp_title;
- cache.minMeasuredVisible = false;
- cache.maxMeasuredVisible = false;
- cache.popupImg = 1;
- tip = tip = strings.apptemp_info + ':' +
- '
' +
- '- ' + strings.lowestF_info + ': ' + cache.low + data.tempunit + ' ' + strings.at + ' ' + data.TapptempTL +
- ' | ' + strings.highestF_info + ': ' + cache.high + data.tempunit + ' ' + strings.at + ' ' + data.TapptempTH;
- break;
- case 'feel': // feels like
- cache.low = extractDecimal(data.feelslikeTL);
- cache.high = extractDecimal(data.feelslikeTH);
- cache.value = extractDecimal(data.feelslike);
- cache.areas = [steelseries.Section(+cache.low, +cache.high, gaugeGlobals.minMaxArea)];
- cache.title = strings.feel_title;
- cache.minMeasuredVisible = false;
- cache.maxMeasuredVisible = false;
- cache.popupImg = 1;
- tip = tip = strings.feel_info + ':' +
- '
' +
- '- ' + strings.lowestF_info + ': ' + cache.low + data.tempunit + ' ' + strings.at + ' ' + data.TfeelslikeTL +
- ' | ' + strings.highestF_info + ': ' + cache.high + data.tempunit + ' ' + strings.at + ' ' + data.TfeelslikeTH;
- break;
- case 'wnd': // wind chill
- cache.low = extractDecimal(data.wchillTL);
- cache.high = extractDecimal(data.wchill);
- cache.value = extractDecimal(data.wchill);
- cache.areas = [];
- cache.title = strings.chill_title;
- cache.minMeasuredVisible = true;
- cache.maxMeasuredVisible = false;
- cache.popupImg = 2;
- tip = strings.chill_info + ':' +
- '
' +
- '- ' + strings.lowest_info + ': ' + cache.low + data.tempunit + ' ' + strings.at + ' ' + data.TwchillTL;
- break;
- case 'hea': // heat index
- cache.low = extractDecimal(data.heatindex);
- cache.high = extractDecimal(data.heatindexTH);
- cache.value = extractDecimal(data.heatindex);
- cache.areas = [];
- cache.title = strings.heat_title;
- cache.minMeasuredVisible = false;
- cache.maxMeasuredVisible = true;
- cache.popupImg = 3;
- tip = strings.heat_info + ':' +
- '
' +
- '- ' + strings.highest_info + ': ' + cache.high + data.tempunit + ' ' + strings.at + ' ' + data.TheatindexTH;
- break;
- case 'hum': // humidex
- cache.low = extractDecimal(data.humidex);
- cache.high = extractDecimal(data.humidex);
- cache.value = extractDecimal(data.humidex);
- cache.areas = [];
- cache.title = strings.humdx_title;
- cache.minMeasuredVisible = false;
- cache.maxMeasuredVisible = false;
- cache.popupImg = 4;
- tip = strings.humdx_info + ': ' + cache.value + data.tempunit;
- break;
- // no default
- }
-
- if (cache.selected !== sel) {
- cache.selected = sel;
- // change gauge title
- ssGauge.setTitleString(cache.title);
- // and graph image
- if (config.showPopupGraphs && config.tipImgs[1][cache.popupImg] !== null) {
- var cacheDefeat = '?' + $('#imgtip1_img').attr('src').split('?')[1];
- $('#imgtip1_img').attr('src', config.imgPathURL + config.tipImgs[1][cache.popupImg] + cacheDefeat);
- }
- }
-
- // auto scale the ranges
- scaleStep = data.tempunit[1] === 'C' ? 10 : 20;
- while (cache.lowScale < cache.minValue) {
- cache.minValue -= scaleStep;
- if (cache.highScale <= cache.maxValue - scaleStep) {
- cache.maxValue -= scaleStep;
- }
- }
- while (cache.highScale > cache.maxValue) {
- cache.maxValue += scaleStep;
- if (cache.minValue >= cache.minValue + scaleStep) {
- cache.minValue += scaleStep;
- }
- }
-
- if (cache.minValue !== ssGauge.getMinValue() || cache.maxValue !== ssGauge.getMaxValue()) {
- ssGauge.setMinValue(cache.minValue);
- ssGauge.setMaxValue(cache.maxValue);
- ssGauge.setValue(cache.minValue);
- }
- ssGauge.setMinMeasuredValueVisible(cache.minMeasuredVisible);
- ssGauge.setMaxMeasuredValueVisible(cache.maxMeasuredVisible);
- ssGauge.setMinMeasuredValue(+cache.low);
- ssGauge.setMaxMeasuredValue(+cache.high);
- ssGauge.setArea(cache.areas);
- ssGauge.setValueAnimated(+cache.value);
-
- if (ddimgtooltip.showTips) {
- // update tooltip
- $('#imgtip1_txt').html(tip);
- }
- }
-
- function updateGraph(evnt, cacheDefeat) {
- if (config.tipImgs[1][cache.popupImg] !== null) {
- $('#imgtip1_img').attr('src', config.imgPathURL + config.tipImgs[1][cache.popupImg] + cacheDefeat);
- }
- }
-
- return {
- data: cache,
- update: update,
- gauge: ssGauge
- };
- } // End of init()
-
- return {
- // Get the Singleton instance if one exists
- // or create one if it doesn't
- getInstance: function () {
- if (!instance) {
- instance = init();
- }
- return instance;
- }
- };
- })(), // End of singleDew()
-
- //
- // Singleton for the Rainfall Gauge
- //
- singleRain = (function () {
- var instance; // Stores a reference to the Singleton
- var ssGauge; // Stores a reference to the SS Gauge
- var cache = {}; // Stores various config values and parameters
-
- function init() {
- var params = $.extend(true, {}, commonParams);
-
- // define rain gauge start values
- cache.maxValue = gaugeGlobals.rainScaleDefMaxmm;
- cache.value = 0.0001;
- cache.title = strings.rain_title;
- cache.lcdDecimals = 1;
- cache.scaleDecimals = 1;
- cache.labelNumberFormat = gaugeGlobals.labelFormat;
- cache.sections = (gaugeGlobals.rainUseSectionColours ? createRainfallSections(true) : []);
- cache.valGrad = (gaugeGlobals.rainUseGradientColours ? createRainfallGradient(true) : null);
-
- // create rain radial bargraph gauge
- if ($('#canvas_rain').length) {
- params.size = Math.ceil($('#canvas_rain').width() * config.gaugeScaling);
- params.maxValue = cache.maxValue;
- params.thresholdVisible = false;
- params.titleString = cache.title;
- params.unitString = data.rainunit;
- params.valueColor = steelseries.ColorDef.BLUE;
- params.valueGradient = cache.valGrad;
- params.useValueGradient = gaugeGlobals.rainUseGradientColours;
- params.useSectionColors = gaugeGlobals.rainUseSectionColour;
- params.useSectionColors = gaugeGlobals.rainUseSectionColours;
- params.labelNumberFormat = cache.labelNumberFormat;
- params.fractionalScaleDecimals = cache.scaleDecimals;
- params.niceScale = false;
-
- ssGauge = new steelseries.RadialBargraph('canvas_rain', params);
- ssGauge.setValue(cache.value);
-
- // over-ride CSS applied size?
- if (config.gaugeScaling !== 1) {
- $('#canvas_rain').css({ width: params.size + 'px', height: params.size + 'px' });
- }
-
- // add a shadow to the gauge
- if (config.showGaugeShadow) {
- $('#canvas_rain').css(gaugeShadow(params.size));
- }
-
- // subscribe to data updates
- $.subscribe('gauges.dataUpdated', update);
- $.subscribe('gauges.graphUpdate', updateGraph);
- } else {
- // cannot draw gauge, return null
- return null;
- }
-
- function update() {
- cache.value = extractDecimal(data.rfall);
- if (data.rainunit === 'mm') { // 10, 20, 30...
- cache.maxValue = Math.max(nextHighest(cache.value, 10), gaugeGlobals.rainScaleDefMaxmm);
- } else {
- // inches 0.5, 1.0, 2.0, 3.0 ... 10.0, 12.0, 14.0
- if (cache.value <= 1) {
- cache.maxValue = Math.max(nextHighest(cache.value, 0.5), gaugeGlobals.rainScaleDefMaxIn);
- } else if (cache.value <= 6) {
- cache.maxValue = Math.max(nextHighest(cache.value, 1), gaugeGlobals.rainScaleDefMaxIn);
- } else {
- cache.maxValue = Math.max(nextHighest(cache.value, 2), gaugeGlobals.rainScaleDefMaxIn);
- }
- cache.scaleDecimals = cache.maxValue < 1 ? 2 : 1;
- }
-
- if (cache.maxValue !== ssGauge.getMaxValue()) {
- // Gauge scale is too low, increase it.
- // First set the pointer back to zero so we get a nice animation
- ssGauge.setValue(0);
- // and redraw the gauge with the new scale
- ssGauge.setFractionalScaleDecimals(cache.scaleDecimals);
- ssGauge.setMaxValue(cache.maxValue);
- }
- ssGauge.setValueAnimated(cache.value);
-
- if (ddimgtooltip.showTips) {
- // update tooltip
- $('#imgtip2_txt').html(strings.LastRain_info + ': ' + data.LastRained);
- }
- } // End of update()
-
- function updateGraph(evnt, cacheDefeat) {
- if (config.tipImgs[2] !== null) {
- $('#imgtip2_img').attr('src', config.imgPathURL + config.tipImgs[2] + cacheDefeat);
- }
- }
-
- return {
- data: cache,
- update: update,
- gauge: ssGauge
- };
- } // End of init()
-
- return {
- // Get the Singleton instance if one exists
- // or create one if it doesn't
- getInstance: function () {
- if (!instance) {
- instance = init();
- }
- return instance;
- }
- };
- })(),
-
- //
- // Singleton for the Rainfall Rate Gauge
- //
- singleRRate = (function () {
- var instance; // Stores a reference to the Singleton
- var ssGauge; // Stores a reference to the SS Gauge
- var cache = {}; // Stores various config values and parameters
-
- function init() {
- var params = $.extend(true, {}, commonParams);
-
- // define rain rate gauge start values
- cache.maxMeasured = 0;
- cache.maxValue = gaugeGlobals.rainRateScaleDefMaxmm;
- cache.value = 0.0001;
- cache.title = strings.rrate_title;
- cache.lcdDecimals = 1;
- cache.scaleDecimals = 0;
- cache.labelNumberFormat = gaugeGlobals.labelFormat;
- cache.sections = createRainRateSections(true);
-
- // create rain rate radial gauge
- if ($('#canvas_rrate').length) {
- params.size = Math.ceil($('#canvas_rrate').width() * config.gaugeScaling);
- params.section = cache.sections;
- params.maxValue = cache.maxValue;
- params.thresholdVisible = false;
- params.maxMeasuredValueVisible = true;
- params.titleString = cache.title;
- params.unitString = data.rainunit + '/h';
- params.lcdDecimals = cache.lcdDecimals;
- params.labelNumberFormat = cache.labelNumberFormat;
- params.fractionalScaleDecimals = cache.scaleDecimals;
- params.niceScale = false;
-
- ssGauge = new steelseries.Radial('canvas_rrate', params);
- ssGauge.setMaxMeasuredValue(cache.maxMeasured);
- ssGauge.setValue(cache.value);
-
- // over-ride CSS applied size?
- if (config.gaugeScaling !== 1) {
- $('#canvas_rrate').css({ width: params.size + 'px', height: params.size + 'px' });
- }
-
- // add a shadow to the gauge
- if (config.showGaugeShadow) {
- $('#canvas_rrate').css(gaugeShadow(params.size));
- }
-
- // subscribe to data updates
- $.subscribe('gauges.dataUpdated', update);
- $.subscribe('gauges.graphUpdate', updateGraph);
- } else {
- // cannot draw gauge, return null
- return null;
- }
-
- function update() {
- var tip;
-
- cache.value = extractDecimal(data.rrate);
- cache.maxMeasured = extractDecimal(data.rrateTM);
- cache.overallMax = Math.max(cache.maxMeasured, cache.value); // workaround for VWS bug, not supplying correct max value today
-
- if (data.rainunit === 'mm') { // 10, 20, 30...
- cache.maxValue = nextHighest(cache.overallMax, 10);
- } else {
- // inches 0.5, 1.0, 2.0, 3.0 ... 10, 20, 30...
- if (cache.overallMax <= 0.5) {
- cache.maxValue = 0.5;
- } else if (cache.overallMax <= 10) {
- cache.maxValue = nextHighest(cache.overallMax, 1);
- } else {
- cache.maxValue = nextHighest(cache.overallMax, 10);
- }
- cache.scaleDecimals = cache.maxValue < 1 ? 2 : (cache.maxValue < 7 ? 1 : 0);
- }
-
- if (cache.maxValue !== ssGauge.getMaxValue()) {
- ssGauge.setValue(0);
- ssGauge.setFractionalScaleDecimals(cache.scaleDecimals);
- ssGauge.setMaxValue(cache.maxValue);
- }
-
- ssGauge.setValueAnimated(cache.value);
- ssGauge.setMaxMeasuredValue(cache.maxMeasured);
-
- if (ddimgtooltip.showTips) {
- // update tooltip
- tip = strings.rrate_info + ':
' +
- '- ' + strings.maximum_info + ': ' + data.rrateTM + ' ' + data.rainunit + '/h ' + strings.at + ' ' + data.TrrateTM +
- ' | ' + strings.max_hour_info + ': ' + extractDecimal(data.hourlyrainTH) + ' ' + data.rainunit + ' ' +
- strings.at + ' ' + data.ThourlyrainTH;
- $('#imgtip3_txt').html(tip);
- }
- } // End of update()
-
- function updateGraph(evnt, cacheDefeat) {
- if (config.tipImgs[3] !== null) {
- $('#imgtip3_img').attr('src', config.imgPathURL + config.tipImgs[3] + cacheDefeat);
- }
- }
- return {
- data: cache,
- update: update,
- gauge: ssGauge
- };
- } // End of init()
-
- return {
- // Get the Singleton instance if one exists
- // or create one if it doesn't
- getInstance: function () {
- if (!instance) {
- instance = init();
- }
- return instance;
- }
- };
- })(),
-
- //
- // Singleton for the Humidity Gauge
- //
- singleHum = (function () {
- var instance; // Stores a reference to the Singleton
- var ssGauge; // Stores a reference to the SS Gauge
- var cache = {}; // Stores various config values and parameters
-
- function init() {
- var params = $.extend(true, {}, commonParams);
-
- // define humidity gauge start values
- cache.areas = [];
- cache.value = 0.0001;
- cache.title = strings.hum_title_out;
- cache.selected = 'out';
-
- // create humidity radial gauge
- if ($('#canvas_hum').length) {
- params.size = Math.ceil($('#canvas_hum').width() * config.gaugeScaling);
- params.section = [
- steelseries.Section(0, 20, 'rgba(255,255,0,0.3)'),
- steelseries.Section(20, 80, 'rgba(0,255,0,0.3)'),
- steelseries.Section(80, 100, 'rgba(255,0,0,0.3)')
- ];
- params.area = cache.areas;
- params.maxValue = 100;
- params.thresholdVisible = false;
- params.titleString = cache.title;
- params.unitString = 'RH%';
-
- ssGauge = new steelseries.Radial('canvas_hum', params);
- ssGauge.setValue(cache.value);
-
- // over-ride CSS applied size?
- if (config.gaugeScaling !== 1) {
- $('#canvas_hum').css({ width: params.size + 'px', height: params.size + 'px' });
- }
-
- // add a shadow to the gauge
- if (config.showGaugeShadow) {
- $('#canvas_hum').css(gaugeShadow(params.size));
- }
-
- // subscribe to data updates
- $.subscribe('gauges.dataUpdated', update);
- $.subscribe('gauges.graphUpdate', updateGraph);
- } else {
- // cannot draw gauge, return null
- return null;
- }
-
- function update() {
- var radio;
- // Argument length === 2 when called from event handler
- if (arguments.length === 1) {
- radio = arguments[0];
- }
-
- // if rad isn't specified, just use existing value
- var sel = (typeof radio === 'undefined' ? cache.selected : radio.value),
- tip;
-
- if (sel === 'out') {
- cache.value = extractDecimal(data.hum);
- cache.areas = [steelseries.Section(+extractDecimal(data.humTL), +extractDecimal(data.humTH), gaugeGlobals.minMaxArea)];
- cache.title = strings.hum_title_out;
- cache.popupImg = 0;
- } else {
- cache.value = extractDecimal(data.inhum);
- if (data.inhumTL && data.inhumTH) {
- cache.areas = [steelseries.Section(+extractDecimal(data.inhumTL), +extractDecimal(data.inhumTH), gaugeGlobals.minMaxArea)];
- } else {
- cache.areas = [];
- }
- cache.title = strings.hum_title_in;
- cache.popupImg = 1;
- }
-
- if (cache.selected !== sel) {
- cache.selected = sel;
- // Change gauge title
- ssGauge.setTitleString(cache.title);
- if (config.showPopupGraphs && config.tipImgs[4][cache.popupImg] !== null) {
- var cacheDefeat = '?' + $('#imgtip4_img').attr('src').split('?')[1];
- $('#imgtip4_img').attr('src', config.imgPathURL + config.tipImgs[4][cache.popupImg] + cacheDefeat);
- }
- }
-
- ssGauge.setArea(cache.areas);
- ssGauge.setValueAnimated(cache.value);
-
- if (ddimgtooltip.showTips) {
- // update tooltip
- if (cache.selected === 'out') {
- tip = strings.hum_out_info + ':' +
- '
' +
- '- ' + strings.minimum_info + ': ' + extractDecimal(data.humTL) + '% ' + strings.at + ' ' + data.ThumTL +
- ' | ' + strings.maximum_info + ': ' + extractDecimal(data.humTH) + '% ' + strings.at + ' ' + data.ThumTH;
- } else if (data.inhumTL && data.inhumTH) {
- // we have indoor high/low data
- tip = strings.hum_in_info + ':' +
- '
' +
- '- ' + strings.minimum_info + ': ' + extractDecimal(data.inhumTL) + '% ' + strings.at + ' ' + data.TinhumTL +
- ' | ' + strings.maximum_info + ': ' + extractDecimal(data.inhumTH) + '% ' + strings.at + ' ' + data.TinhumTH;
- } else {
- // no indoor high/low data
- tip = strings.hum_in_info + ': ' + extractDecimal(data.inhum) + '%';
- }
- $('#imgtip4_txt').html(tip);
- }
- } // End of update()
-
- function updateGraph(evnt, cacheDefeat) {
- if (config.tipImgs[4][cache.popupImg] !== null) {
- $('#imgtip4_img').attr('src', config.imgPathURL + config.tipImgs[4][cache.popupImg] + cacheDefeat);
- }
- }
-
- return {
- data: cache,
- update: update,
- gauge: ssGauge
- };
- } // End of init()
-
- return {
- // Get the Singleton instance if one exists
- // or create one if it doesn't
- getInstance: function () {
- if (!instance) {
- instance = init();
- }
- return instance;
- }
- };
- })(),
-
- //
- // Singleton for the Barometer Gauge
- //
- singleBaro = (function () {
- var instance; // Stores a reference to the Singleton
- var ssGauge; // Stores a reference to the SS Gauge
- var cache = {}; // Stores various config values and parameters
-
- function init() {
- var params = $.extend(true, {}, commonParams);
-
- // define pressure/barometer gauge start values
- cache.sections = [];
- cache.areas = [];
- cache.minValue = gaugeGlobals.baroScaleDefMinhPa;
- cache.maxValue = gaugeGlobals.baroScaleDefMaxhPa;
- cache.value = cache.minValue + 0.0001;
- cache.title = strings.baro_title;
- cache.lcdDecimals = 1;
- cache.scaleDecimals = 0;
- cache.labelNumberFormat = gaugeGlobals.labelFormat;
-
- // create pressure/barometric radial gauge
- if ($('#canvas_baro').length) {
- params.size = Math.ceil($('#canvas_baro').width() * config.gaugeScaling);
- params.section = cache.sections;
- params.area = cache.areas;
- params.minValue = cache.minValue;
- params.maxValue = cache.maxValue;
- params.niceScale = false;
- params.thresholdVisible = false;
- params.titleString = cache.title;
- params.unitString = data.pressunit;
- params.lcdDecimals = cache.lcdDecimals;
- params.trendVisible = gaugeGlobals.pressureTrendVisible;
- params.labelNumberFormat = cache.labelNumberFormat;
- params.fractionalScaleDecimals = cache.scaleDecimals;
-
- ssGauge = new steelseries.Radial('canvas_baro', params);
- ssGauge.setValue(cache.value);
-
- // over-ride CSS applied size?
- if (config.gaugeScaling !== 1) {
- $('#canvas_baro').css({ width: params.size + 'px', height: params.size + 'px' });
- }
-
- // add a shadow to the gauge
- if (config.showGaugeShadow) {
- $('#canvas_baro').css(gaugeShadow(params.size));
- }
-
- // subscribe to data updates
- $.subscribe('gauges.dataUpdated', update);
- $.subscribe('gauges.graphUpdate', updateGraph);
- } else {
- // cannot draw gauge, return null
- return null;
- }
-
- function update() {
- var tip, t1, dps;
-
- cache.recLow = +extractDecimal(data.pressL);
- cache.recHigh = +extractDecimal(data.pressH);
- cache.todayLow = +extractDecimal(data.pressTL);
- cache.todayHigh = +extractDecimal(data.pressTH);
- cache.value = +extractDecimal(data.press);
- // Convert the WD change over 3 hours to an hourly rate
- cache.trendVal = +extractDecimal(data.presstrendval) / (config.weatherProgram === 2 ? 3 : 1);
-
- if (data.pressunit === 'hPa' || data.pressunit === 'mb') {
- // default min range 990-1030 - steps of 10 hPa
- cache.minValue = Math.min(nextLowest(cache.recLow - 2, 10), gaugeGlobals.baroScaleDefMinhPa);
- cache.maxValue = Math.max(nextHighest(cache.recHigh + 2, 10), gaugeGlobals.baroScaleDefMaxhPa);
- dps = 1; // 1 decimal place
- } else if (data.pressunit === 'kPa') {
- // default min range 99-105 - steps of 1 kPa
- cache.minValue = Math.min(nextLowest(cache.recLow - 0.2, 1), gaugeGlobals.baroScaleDefMinkPa);
- cache.maxValue = Math.max(nextHighest(cache.recHigh + 0.2, 1), gaugeGlobals.baroScaleDefMaxkPa);
- dps = 2;
- } else {
- // inHg: default min range 29.5-30.5 - steps of 0.5 inHg
- cache.minValue = Math.min(nextLowest(cache.recLow - 0.1, 0.5), gaugeGlobals.baroScaleDefMininHg);
- cache.maxValue = Math.max(nextHighest(cache.recHigh + 0.1, 0.5), gaugeGlobals.baroScaleDefMaxinHg);
- dps = 3;
- }
- cache.trendValRnd = cache.trendVal.toFixed(dps);
- cache.todayLowRnd = cache.todayLow.toFixed(dps);
- cache.todayHighRnd = cache.todayHigh.toFixed(dps);
-
- if (cache.minValue !== ssGauge.getMinValue() || cache.maxValue !== ssGauge.getMaxValue()) {
- ssGauge.setMinValue(cache.minValue);
- ssGauge.setMaxValue(cache.maxValue);
- ssGauge.setValue(cache.minValue);
- }
- if (cache.recHigh === cache.todayHigh && cache.recLow === cache.todayLow) {
- // VWS does not provide record hi/lo values
- cache.sections = [];
- cache.areas = [steelseries.Section(cache.todayLow, cache.todayHigh, gaugeGlobals.minMaxArea)];
- } else {
- cache.sections = [
- steelseries.Section(cache.minValue, cache.recLow, 'rgba(255,0,0,0.5)'),
- steelseries.Section(cache.recHigh, cache.maxValue, 'rgba(255,0,0,0.5)')
- ];
- cache.areas = [
- steelseries.Section(cache.minValue, cache.recLow, 'rgba(255,0,0,0.5)'),
- steelseries.Section(cache.recHigh, cache.maxValue, 'rgba(255,0,0,0.5)'),
- steelseries.Section(cache.todayLow, cache.todayHigh, gaugeGlobals.minMaxArea)
- ];
- }
-
- if (gaugeGlobals.pressureTrendVisible) {
- // Use the baroTrend rather than simple arithmetic test - steady is more/less than zero!
- t1 = baroTrend(cache.trendVal, data.pressunit, false);
- if (t1 === -9999) {
- // trend value isn't currently available
- cache.trend = steelseries.TrendState.OFF;
- } else if (t1 > 0) {
- cache.trend = steelseries.TrendState.UP;
- } else if (t1 < 0) {
- cache.trend = steelseries.TrendState.DOWN;
- } else {
- cache.trend = steelseries.TrendState.STEADY;
- }
- ssGauge.setTrend(cache.trend);
- }
-
- ssGauge.setArea(cache.areas);
- ssGauge.setSection(cache.sections);
- ssGauge.setValueAnimated(cache.value);
-
- if (ddimgtooltip.showTips) {
- // update tooltip
- tip = strings.baro_info + ':' +
- '
' +
- '- ' + strings.minimum_info + ': ' + cache.todayLowRnd + ' ' + data.pressunit + ' ' + strings.at + ' ' + data.TpressTL +
- ' | ' + strings.maximum_info + ': ' + cache.todayHighRnd + ' ' + data.pressunit + ' ' + strings.at + ' ' + data.TpressTH;
- if (cache.trendVal !== -9999) {
- tip += '
' +
- '- ' + strings.baro_trend_info + ': ' + baroTrend(cache.trendVal, data.pressunit, true) + ' ' +
- (cache.trendValRnd > 0 ? '+' : '') + cache.trendValRnd + ' ' + data.pressunit + '/h';
- }
- $('#imgtip5_txt').html(tip);
- }
- } // End of update()
-
- function updateGraph(evnt, cacheDefeat) {
- if (config.tipImgs[5] !== null) {
- $('#imgtip5_img').attr('src', config.imgPathURL + config.tipImgs[5] + cacheDefeat);
- }
- }
-
- return {
- data: cache,
- update: update,
- gauge: ssGauge
- };
- } // End of init()
-
- return {
- // Get the Singleton instance if one exists
- // or create one if it doesn't
- getInstance: function () {
- if (!instance) {
- instance = init();
- }
- return instance;
- }
- };
- })(),
-
- //
- // Singleton for the Wind Speed Gauge
- //
- singleWind = (function () {
- var instance; // Stores a reference to the Singleton
- var ssGauge; // Stores a reference to the SS Gauge
- var cache = {}; // Stores various config values and parameters
-
- function init() {
- var params = $.extend(true, {}, commonParams);
-
- // define wind gauge start values
- cache.maxValue = gaugeGlobals.windScaleDefMaxKph;
- cache.areas = [];
- cache.maxMeasured = 0;
- cache.value = 0.0001;
- cache.title = strings.wind_title;
-
- // create wind speed radial gauge
- if ($('#canvas_wind').length) {
- params.size = Math.ceil($('#canvas_wind').width() * config.gaugeScaling);
- params.area = cache.areas;
- params.maxValue = cache.maxValue;
- params.niceScale = false;
- params.thresholdVisible = false;
- params.maxMeasuredValueVisible = true;
- params.titleString = cache.title;
- params.unitString = data.windunit;
-
- ssGauge = new steelseries.Radial('canvas_wind', params);
- ssGauge.setMaxMeasuredValue(cache.maxMeasured);
- ssGauge.setValue(cache.value);
-
- // over-ride CSS applied size?
- if (config.gaugeScaling !== 1) {
- $('#canvas_wind').css({ width: params.size + 'px', height: params.size + 'px' });
- }
-
- // add a shadow to the gauge
- if (config.showGaugeShadow) {
- $('#canvas_wind').css(gaugeShadow(params.size));
- }
-
- // subscribe to data updates
- $.subscribe('gauges.dataUpdated', update);
- $.subscribe('gauges.graphUpdate', updateGraph);
- } else {
- // cannot draw gauge, return null
- return null;
- }
-
- function update() {
- var tip;
-
- cache.value = extractDecimal(data.wlatest);
- cache.average = extractDecimal(data.wspeed);
- cache.gust = extractDecimal(data.wgust);
- cache.maxGustToday = extractDecimal(data.wgustTM);
- cache.maxAvgToday = extractDecimal(data.windTM);
-
- switch (data.windunit) {
- case 'mph':
- case 'kts':
- cache.maxValue = Math.max(nextHighest(cache.maxGustToday, 10), gaugeGlobals.windScaleDefMaxMph);
- break;
- case 'm/s':
- cache.maxValue = Math.max(nextHighest(cache.maxGustToday, 5), gaugeGlobals.windScaleDefMaxMs);
- break;
- default:
- cache.maxValue = Math.max(nextHighest(cache.maxGustToday, 20), gaugeGlobals.windScaleDefMaxKmh);
- }
- cache.areas = [
- steelseries.Section(0, +cache.average, gaugeGlobals.windAvgArea),
- steelseries.Section(+cache.average, +cache.gust, gaugeGlobals.minMaxArea)
- ];
- if (cache.maxValue !== ssGauge.getMaxValue()) {
- ssGauge.setValue(0);
- ssGauge.setMaxValue(cache.maxValue);
- }
-
- ssGauge.setArea(cache.areas);
- ssGauge.setMaxMeasuredValue(cache.maxGustToday);
- ssGauge.setValueAnimated(cache.value);
-
- if (ddimgtooltip.showTips) {
- // update tooltip
- tip = strings.tenminavgwind_info + ': ' + cache.average + ' ' + data.windunit + ' | ' +
- strings.maxavgwind_info + ': ' + cache.maxAvgToday + ' ' + data.windunit + '
' +
- strings.tenmingust_info + ': ' + cache.gust + ' ' + data.windunit + ' | ' +
- strings.maxgust_info + ': ' + cache.maxGustToday + ' ' + data.windunit + ' ' +
- strings.at + ' ' + data.TwgustTM + ' ' + strings.bearing_info + ': ' + data.bearingTM +
- (isNaN(parseFloat(data.bearingTM)) ? '' : '° (' + getord(+data.bearingTM) + ')');
- $('#imgtip6_txt').html(tip);
- }
- } // End of update()
-
- function updateGraph(evnt, cacheDefeat) {
- if (config.tipImgs[6] !== null) {
- $('#imgtip6_img').attr('src', config.imgPathURL + config.tipImgs[6] + cacheDefeat);
- }
- }
-
- return {
- data: cache,
- update: update,
- gauge: ssGauge
- };
- } // End of init()
-
- return {
- // Get the Singleton instance if one exists
- // or create one if it doesn't
- getInstance: function () {
- if (!instance) {
- instance = init();
- }
- return instance;
- }
- };
- })(), // End of singleWind()
-
- //
- // Singleton for the Wind Direction Gauge
- //
- singleDir = (function () {
- var instance; // Stores a reference to the Singleton
- var ssGauge; // Stores a reference to the SS Gauge
- var cache = {}; // Stores various config values and parameters
-
- function init() {
- var params = $.extend(true, {}, commonParams);
-
- // define wind direction gauge start values
- cache.valueLatest = 0;
- cache.valueAverage = 0;
- cache.titles = [strings.latest_web, strings.tenminavg_web];
-
- // create wind direction/compass radial gauge
- if ($('#canvas_dir').length) {
- params.size = Math.ceil($('#canvas_dir').width() * config.gaugeScaling);
- params.pointerTypeLatest = gaugeGlobals.pointer; // default TYPE8,
- params.pointerTypeAverage = gaugeGlobals.dirAvgPointer; // default TYPE8
- params.pointerColorAverage = gaugeGlobals.dirAvgPointerColour;
- params.degreeScale = true; // Show degree scale rather than ordinal directions
- params.pointSymbols = strings.compass;
- params.roseVisible = false;
- params.lcdTitleStrings = cache.titles;
- params.useColorLabels = false;
-
- ssGauge = new steelseries.WindDirection('canvas_dir', params);
- ssGauge.setValueAverage(+cache.valueAverage);
- ssGauge.setValueLatest(+cache.valueLatest);
-
- // over-ride CSS applied size?
- if (config.gaugeScaling !== 1) {
- $('#canvas_dir').css({ width: params.size + 'px', height: params.size + 'px' });
- }
-
- // add a shadow to the gauge
- if (config.showGaugeShadow) {
- $('#canvas_dir').css(gaugeShadow(params.size));
- }
-
- // subscribe to data updates
- $.subscribe('gauges.dataUpdated', update);
- $.subscribe('gauges.graphUpdate', updateGraph);
- } else {
- // cannot draw gauge, return null
- return null;
- }
-
- function update() {
- var windSpd, windGst, range, tip, i,
- rosePoints = 0,
- roseMax = 0,
- roseSectionAngle = 0,
- roseAreas = [];
-
- cache.valueLatest = extractInteger(data.bearing);
- cache.valueAverage = extractInteger(data.avgbearing);
- cache.bearingFrom = extractInteger(data.BearingRangeFrom10);
- cache.bearingTo = extractInteger(data.BearingRangeTo10);
-
- ssGauge.setValueAnimatedAverage(+cache.valueAverage);
- if (cache.valueAverage === 0) {
- cache.valueLatest = 0;
- }
- ssGauge.setValueAnimatedLatest(+cache.valueLatest);
-
- if (config.showWindVariation) {
- windSpd = +extractDecimal(data.wspeed);
- windGst = +extractDecimal(data.wgust);
- switch (data.windunit.toLowerCase()) {
- case 'mph':
- cache.avgKnots = 0.868976242 * windSpd;
- cache.gstKnots = 0.868976242 * windGst;
- break;
- case 'kts':
- cache.avgKnots = windSpd;
- cache.gstKnots = windGst;
- break;
- case 'm/s':
- cache.avgKnots = 1.94384449 * windSpd;
- cache.gstKnots = 1.94384449 * windGst;
- break;
- case 'km/h':
- cache.avgKnots = 0.539956803 * windSpd;
- cache.gstKnots = 0.539956803 * windGst;
- break;
- // no default
- }
- cache.avgKnots = Math.round(cache.avgKnots);
- cache.gstKnots = Math.round(cache.gstKnots);
- if (config.showWindMetar) {
- ssGauge.VRB = ' - METAR: ' + ('0' + data.avgbearing).slice(-3) + ('0' + cache.avgKnots).slice(-2) +
- 'G' + ('0' + cache.gstKnots).slice(-2) + 'KT ';
- } else {
- ssGauge.VRB = '';
- }
- if (windSpd > 0) {
- // If variation less than 60 degrees, then METAR = Steady
- // Unless range = 0 and from/to direction = avg + 180
- range = (+cache.bearingTo < +cache.bearingFrom ? 360 + (+cache.bearingTo) : +cache.bearingTo) - (+cache.bearingFrom);
-
- if (cache.avgKnots < 3) { // Europe uses 3kts, USA 6kts as the threshold
- if (config.showRoseOnDirGauge) {
- ssGauge.setSection([steelseries.Section(cache.bearingFrom, cache.bearingTo, gaugeGlobals.windVariationSector)]);
- ssGauge.setSection([]);
- } else {
- ssGauge.setSection([steelseries.Section(cache.bearingFrom, cache.bearingTo, gaugeGlobals.minMaxArea)]);
- ssGauge.setArea([]);
- }
- } else if (config.showRoseOnDirGauge) {
- ssGauge.setSection([steelseries.Section(cache.bearingFrom, cache.bearingTo, gaugeGlobals.windVariationSector)]);
- } else {
- ssGauge.setSection([]);
- ssGauge.setArea([steelseries.Section(cache.bearingFrom, cache.bearingTo, gaugeGlobals.minMaxArea)]);
- }
- if (config.showWindMetar) {
- if ((range < 60 && range > 0) || range === 0 && cache.bearingFrom === cache.valueAverage) {
- ssGauge.VRB += ' STDY';
- } else if (cache.avgKnots < 3) { // Europe uses 3kts, USA 6kts as the threshold
- ssGauge.VRB += ' VRB';
- } else {
- ssGauge.VRB += ' ' + cache.bearingFrom + 'V' + cache.bearingTo;
- }
- }
- } else {
- // Zero wind speed, calm
- if (config.showWindMetar) {
- ssGauge.VRB = ' - METAR: 00000KT';
- }
- ssGauge.setSection([]);
- if (!config.showRoseOnDirGauge) {
- ssGauge.setArea([]);
- }
- }
- } else {
- ssGauge.VRB = '';
- }
-
- // optional rose data on direction gauge
- if (config.showRoseOnDirGauge && data.WindRoseData) {
- // Process rose data
- rosePoints = data.WindRoseData.length;
- roseSectionAngle = 360 / rosePoints;
- // Find total for all directions
- for (i = 0; i < rosePoints; i++) {
- roseMax = Math.max(roseMax, data.WindRoseData[i]);
- }
- // Check we actually have some data, bad things happen if roseMax=0!
- if (roseMax > 0) {
- // Find relative value for each point, and create a gauge area for it
- for (i = 0; i < rosePoints; i++) {
- roseAreas[i] = steelseries.Section(
- i * roseSectionAngle - roseSectionAngle / 2,
- (i + 1) * roseSectionAngle - roseSectionAngle / 2,
- 'rgba(' + gradient('2020D0', 'D04040', data.WindRoseData[i] / roseMax) + ',' +
- (data.WindRoseData[i] / roseMax).toFixed(2) + ')'
- );
- }
- }
- ssGauge.setArea(roseAreas);
- }
-
- if (ddimgtooltip.showTips) {
- // update tooltip
- tip = strings.latest_title + ' ' + strings.bearing_info + ': ' + cache.valueLatest + '° (' + getord(+cache.valueLatest) + ')' +
- ssGauge.VRB + '
' + strings.tenminavg_web + ' ' + strings.bearing_info + ': ' + cache.valueAverage + '° (' +
- getord(+cache.valueAverage) + '), ' + strings.dominant_bearing + ': ' + data.domwinddir;
- if (!config.showRoseGauge) {
- // Wind run is shown on the wind rose if it is available
- tip += '
' + strings.windruntoday + ': ' + data.windrun + ' ' + displayUnits.windrun;
- }
- $('#imgtip7_txt').html(tip);
- }
- } // End of update()
-
- function updateGraph(evnt, cacheDefeat) {
- if (config.tipImgs[7] !== null) {
- $('#imgtip7_img').attr('src', config.imgPathURL + config.tipImgs[7] + cacheDefeat);
- }
- }
-
- return {
- data: cache,
- update: update,
- gauge: ssGauge
- };
- } // End of init()
-
- return {
- // Get the Singleton instance if one exists
- // or create one if it doesn't
- getInstance: function () {
- if (!instance) {
- instance = init();
- }
- return instance;
- }
- };
- })(),
-
- //
- // Singleton for the Wind Rose Gauge
- //
- singleRose = (function () {
- var instance; // Stores a reference to the Singleton
- var ssGauge; // Stores a reference to the SS Gauge
-
- var buffers = {}; // Stores references to the various canvas buffers
- var cache = {}; // various parameters to store for the life time of gauge
- var ctxRoseCanvas; // 2D context for the plotted gauge
-
- cache.firstRun = true;
- cache.odoDigits = 5; // Total number of odometer digits including the decimal
-
- function init() {
- var div, roseCanvas;
- // Get the context of the gauge canvas on the HTML page
- if ($('#canvas_rose').length) {
- cache.gaugeSize = Math.ceil($('#canvas_rose').width() * config.gaugeScaling);
- cache.gaugeSize2 = cache.gaugeSize / 2;
- cache.showOdo = config.showRoseGaugeOdo || false;
-
- cache.compassStrings = strings.compass;
- cache.titleString = strings.windrose;
- cache.gaugeOdoTitle = strings.km;
-
- // Create a hidden div to host the Rose plot
- div = document.createElement('div');
- div.style.display = 'none';
- document.body.appendChild(div);
-
- // Calcuate the size of the gauge background and so the size of rose plot required
- cache.plotSize = Math.floor(cache.gaugeSize * 0.68);
- cache.plotSize2 = cache.plotSize / 2;
-
- // rose plot canvas buffer
- buffers.plot = document.createElement('canvas');
- buffers.plot.width = cache.plotSize;
- buffers.plot.height = cache.plotSize;
- buffers.plot.id = 'rosePlot';
- buffers.ctxPlot = buffers.plot.getContext('2d');
- div.appendChild(buffers.plot);
-
- // Create a steelseries gauge frame
- buffers.frame = document.createElement('canvas');
- buffers.frame.width = cache.gaugeSize;
- buffers.frame.height = cache.gaugeSize;
- buffers.ctxFrame = buffers.frame.getContext('2d');
- steelseries.drawFrame(
- buffers.ctxFrame,
- gaugeGlobals.frameDesign,
- cache.gaugeSize2,
- cache.gaugeSize2,
- cache.gaugeSize,
- cache.gaugeSize
- );
-
- // Create a steelseries gauge background
- buffers.background = document.createElement('canvas');
- buffers.background.width = cache.gaugeSize;
- buffers.background.height = cache.gaugeSize;
- buffers.ctxBackground = buffers.background.getContext('2d');
- steelseries.drawBackground(
- buffers.ctxBackground,
- gaugeGlobals.background,
- cache.gaugeSize2,
- cache.gaugeSize2,
- cache.gaugeSize,
- cache.gaugeSize
- );
-
- // Optional - add a background image
- /*
- if (g_imgSmall !== null) {
- var drawSize = g_size * 0.831775;
- var x = (g_size - drawSize) / 2;
- buffers.ctxBackground.drawImage(g_imgSmall, x, x, cache.gaugeSize, cache.gaugeSize);
- }
- */
- // Add the compass points
- drawCompassPoints(buffers.ctxBackground, cache.gaugeSize);
-
- // Create a steelseries gauge foreground
- buffers.foreground = document.createElement('canvas');
- buffers.foreground.width = cache.gaugeSize;
- buffers.foreground.height = cache.gaugeSize;
- buffers.ctxForeground = buffers.foreground.getContext('2d');
- steelseries.drawForeground(
- buffers.ctxForeground,
- gaugeGlobals.foreground,
- cache.gaugeSize,
- cache.gaugeSize,
- false
- );
-
- roseCanvas = document.getElementById('canvas_rose');
- ctxRoseCanvas = roseCanvas.getContext('2d');
- // over-ride CSS applied size?
- if (config.gaugeScaling !== 1) {
- $('#canvas_rose').css({ width: cache.gaugeSize + 'px', height: cache.gaugeSize + 'px' });
- }
- // resize canvas on main page
- roseCanvas.width = cache.gaugeSize;
- roseCanvas.height = cache.gaugeSize;
- // add a shadow to the gauge
- if (config.showGaugeShadow) {
- $('#canvas_rose').css(gaugeShadow(cache.gaugeSize));
- }
-
- // Render an empty gauge, looks better than just the shadow background and odometer ;)
- // Paint the gauge frame
- ctxRoseCanvas.drawImage(buffers.frame, 0, 0);
-
- // Paint the gauge background
- ctxRoseCanvas.drawImage(buffers.background, 0, 0);
-
- // Paint the gauge foreground
- ctxRoseCanvas.drawImage(buffers.foreground, 0, 0);
-
- // Create an odometer
- if (cache.showOdo) {
- cache.odoHeight = Math.ceil(cache.gaugeSize * 0.08); // Sets the size of the odometer
- cache.odoWidth = Math.ceil(Math.floor(cache.odoHeight * 0.68) * cache.odoDigits); // 'Magic' number, do not alter
- // Create a new canvas for the oodometer
- buffers.Odo = document.createElement('canvas');
- $(buffers.Odo).attr({
- id: 'canvas_odo',
- width: cache.odoWidth,
- height: cache.odoHeight
- });
- // Position it
- $(buffers.Odo).attr('class', 'odo');
- // Insert it into the DOM before the Rose gauge
- $(buffers.Odo).insertBefore('#canvas_rose');
- // Create the odometer
- ssGauge = new steelseries.Odometer('canvas_odo', {
- height: cache.odoHeight,
- digits: cache.odoDigits - 1,
- decimals: 1
- });
- }
- // subscribe to data updates
- $.subscribe('gauges.dataUpdated', update);
- $.subscribe('gauges.graphUpdate', updateGraph);
- } else {
- // cannot draw gauge, return null
- return null;
- }
-
- cache.firstRun = false;
-
- function update() {
- var rose, offset;
-
- if (ctxRoseCanvas && !cache.firstRun) {
- // Clear the gauge
- ctxRoseCanvas.clearRect(0, 0, cache.gaugeSize, cache.gaugeSize);
-
- // Clear the existing rose plot
- buffers.ctxPlot.clearRect(0, 0, cache.plotSize, cache.plotSize);
-
- // Create a new rose plot
- rose = new RGraph.Rose('rosePlot', data.WindRoseData);
- rose.Set('chart.strokestyle', 'black');
- rose.Set('chart.background.axes.color', 'gray');
- rose.Set('chart.colors.alpha', 0.5);
- rose.Set('chart.colors', ['Gradient(#408040:red:#7070A0)']);
- rose.Set('chart.margin', Math.ceil(40 / data.WindRoseData.length));
-
- rose.Set('chart.title', cache.titleString);
- rose.Set('chart.title.size', Math.ceil(0.05 * cache.plotSize));
- rose.Set('chart.title.bold', false);
- rose.Set('chart.title.color', gaugeGlobals.background.labelColor.getRgbColor());
- rose.Set('chart.gutter.top', 0.2 * cache.plotSize);
- rose.Set('chart.gutter.bottom', 0.2 * cache.plotSize);
-
- rose.Set('chart.tooltips.effect', 'snap');
- rose.Set('chart.labels.axes', '');
- rose.Set('chart.background.circles', true);
- rose.Set('chart.background.grid.spokes', 16);
- rose.Set('chart.radius', cache.plotSize2);
- rose.Draw();
-
- // Add title to windrun odometer to the plot
- if (cache.showOdo) {
- drawOdoTitle(buffers.ctxPlot);
- }
-
- // Paint the gauge frame
- ctxRoseCanvas.drawImage(buffers.frame, 0, 0);
-
- // Paint the gauge background
- ctxRoseCanvas.drawImage(buffers.background, 0, 0);
-
- // Paint the rose plot
- offset = Math.floor(cache.gaugeSize2 - cache.plotSize2);
- ctxRoseCanvas.drawImage(buffers.plot, offset, offset);
-
- // Paint the gauge foreground
- ctxRoseCanvas.drawImage(buffers.foreground, 0, 0);
-
- // update the odometer
- if (cache.showOdo) {
- ssGauge.setValueAnimated(extractDecimal(data.windrun));
- }
-
- // update tooltip
- if (ddimgtooltip.showTips) {
- $('#imgtip10_txt').html(
- strings.dominant_bearing + ': ' + data.domwinddir + '
' +
- strings.windruntoday + ': ' + data.windrun + ' ' + displayUnits.windrun
- );
- }
- }
- } // End of update()
-
- function updateGraph(evnt, cacheDefeat) {
- if (config.tipImgs[10] !== null) {
- $('#imgtip10_img').attr('src', config.imgPathURL + config.tipImgs[10] + cacheDefeat);
- }
- }
-
- // Helper function to put the compass points on the background
- function drawCompassPoints(ctx, size) {
- ctx.save();
- // set the font
- ctx.font = 0.08 * size + 'px serif';
- ctx.strokeStyle = gaugeGlobals.background.labelColor.getRgbaColor();
- ctx.fillStyle = gaugeGlobals.background.labelColor.getRgbColor();
- ctx.textAlign = 'center';
- ctx.textBaseline = 'middle';
-
- // Draw the compass points
- for (var i = 0; i < 4; i++) {
- ctx.translate(size / 2, size * 0.125);
- ctx.fillText(cache.compassStrings[i * 2], 0, 0, size);
- ctx.translate(-size / 2, -size * 0.125);
- // Move to center
- ctx.translate(size / 2, size / 2);
- ctx.rotate(Math.PI / 2);
- ctx.translate(-size / 2, -size / 2);
- }
- ctx.restore();
- }
-
- function drawOdoTitle(ctx) {
- ctx.save();
- ctx.textAlign = 'center';
- ctx.textBaseline = 'middle';
- ctx.font = 0.05 * cache.gaugeSize + 'px Arial,Verdana,sans-serif';
- ctx.strokeStyle = gaugeGlobals.background.labelColor.getRgbaColor();
- ctx.fillStyle = gaugeGlobals.background.labelColor.getRgbaColor();
- ctx.fillText(cache.gaugeOdoTitle, cache.plotSize2, cache.plotSize * 0.75, cache.plotSize * 0.5);
- ctx.restore();
- }
-
- function setTitle(newTitle) {
- cache.titleString = newTitle;
- }
-
- function setOdoTitle(newTitle) {
- cache.gaugeOdoTitle = newTitle;
- }
-
- function setCompassStrings(newArray) {
- cache.compassStrings = newArray;
- if (!cache.firstRun) {
- // Redraw the background
- steelseries.drawBackground(
- buffers.ctxBackground,
- gaugeGlobals.background,
- cache.gaugeSize2,
- cache.gaugeSize2,
- cache.gaugeSize,
- cache.gaugeSize
- );
- // Add the compass points
- drawCompassPoints(buffers.ctxBackground, cache.gaugeSize);
- }
- }
-
- return {
- update: update,
- gauge: ssGauge,
- drawCompassPoints: drawCompassPoints,
- setTitle: setTitle,
- setCompassStrings: setCompassStrings,
- setOdoTitle: setOdoTitle
- };
- } // End of init()
-
- return {
- // Get the Singleton instance if one exists
- // or create one if it doesn't
- getInstance: function () {
- if (!instance) {
- instance = init();
- }
- return instance;
- }
- };
- })(),
-
- //
- // Singleton for the UV-Index Gauge
- //
- singleUV = (function () {
- var instance; // Stores a reference to the Singleton
- var ssGauge; // Stores a reference to the SS Gauge
- var cache = {}; // Stores various config values and parameters
-
- function init() {
- var params = $.extend(true, {}, commonParams);
-
- // define UV start values
- cache.value = 0.0001;
- cache.sections = [
- steelseries.Section(0, 2.9, '#289500'),
- steelseries.Section(2.9, 5.8, '#f7e400'),
- steelseries.Section(5.8, 7.8, '#f85900'),
- steelseries.Section(7.8, 10.9, '#d8001d'),
- steelseries.Section(10.9, 20, '#6b49c8')
- ];
- // Define value gradient for UV
- cache.gradient = new steelseries.gradientWrapper(0, 16,
- [0, 0.1, 0.19, 0.31, 0.45, 0.625, 1],
- [
- new steelseries.rgbaColor(0, 200, 0, 1),
- new steelseries.rgbaColor(0, 200, 0, 1),
- new steelseries.rgbaColor(255, 255, 0, 1),
- new steelseries.rgbaColor(248, 89, 0, 1),
- new steelseries.rgbaColor(255, 0, 0, 1),
- new steelseries.rgbaColor(255, 0, 144, 1),
- new steelseries.rgbaColor(153, 140, 255, 1)
- ]
- );
- cache.useSections = false;
- cache.useValueGradient = true;
-
- // create UV bargraph gauge
- if ($('#canvas_uv').length) {
- params.size = Math.ceil($('#canvas_uv').width() * config.gaugeScaling);
- params.gaugeType = steelseries.GaugeType.TYPE3;
- params.maxValue = gaugeGlobals.uvScaleDefMax;
- params.titleString = strings.uv_title;
- params.niceScale = false;
- params.section = cache.sections;
- params.useSectionColors = cache.useSections;
- params.valueGradient = cache.gradient;
- params.useValueGradient = cache.useValueGradient;
- params.lcdDecimals = gaugeGlobals.uvLcdDecimals;
-
- ssGauge = new steelseries.RadialBargraph('canvas_uv', params);
- ssGauge.setValue(cache.value);
-
- // over-ride CSS applied size?
- if (config.gaugeScaling !== 1) {
- $('#canvas_uv').css({ width: params.size + 'px', height: params.size + 'px' });
- }
-
- // add a shadow to the gauge
- if (config.showGaugeShadow) {
- $('#canvas_uv').css(gaugeShadow(params.size));
- }
-
- // subscribe to data updates
- $.subscribe('gauges.dataUpdated', update);
- $.subscribe('gauges.graphUpdate', updateGraph);
- } else {
- // cannot draw gauge, return null
- return null;
- }
-
- function update() {
- var tip, indx;
-
- cache.value = extractDecimal(data.UV);
-
- if (+cache.value === 0) {
- indx = 0;
- } else if (cache.value < 2.5) {
- indx = 1;
- } else if (cache.value < 5.5) {
- indx = 2;
- } else if (cache.value < 7.5) {
- indx = 3;
- } else if (cache.value < 10.5) {
- indx = 4;
- } else {
- indx = 5;
- }
-
- cache.maxValue = Math.max(nextHighest(cache.value, 2), gaugeGlobals.uvScaleDefMax);
- if (cache.maxValue !== ssGauge.getMaxValue()) {
- ssGauge.setValue(0);
- ssGauge.setMaxValue(cache.maxValue);
- }
-
- cache.risk = strings.uv_levels[indx];
- cache.headLine = strings.uv_headlines[indx];
- cache.detail = strings.uv_details[indx];
- ssGauge.setUnitString(cache.risk);
- ssGauge.setValueAnimated(cache.value);
-
- if (ddimgtooltip.showTips) {
- // update tooltip
- tip = '' + strings.uv_title + ': ' + cache.value + ' - ' + strings.solar_maxToday + ': ' + data.UVTH + '
';
- tip += '' + cache.headLine + '
';
- tip += cache.detail;
- $('#imgtip8_txt').html(tip);
- }
- } // End of update()
-
- function updateGraph(evnt, cacheDefeat) {
- if (config.tipImgs[8] !== null) {
- $('#imgtip8_img').attr('src', config.imgPathURL + config.tipImgs[8] + cacheDefeat);
- }
- }
-
- return {
- update: update,
- gauge: ssGauge
- };
- } // End of init()
-
- return {
- // Get the Singleton instance if one exists
- // or create one if it doesn't
- getInstance: function () {
- if (!instance) {
- instance = init();
- }
- return instance;
- }
- };
- })(),
-
- //
- // Singleton for the Solar Irradiation Gauge
- //
- singleSolar = (function () {
- var instance; // Stores a reference to the Singleton
- var ssGauge; // Stores a reference to the SS Gauge
- var cache = {}; // Stores various config values and parameters
-
- function init() {
- var params = $.extend(true, {}, commonParams);
-
- // define Solar start values
- cache.value = 0.0001;
- cache.sections = [
- steelseries.Section(0, 600, 'rgba(40,149,0,0.3)'),
- steelseries.Section(600, 800, 'rgba(248,89,0,0.3)'),
- steelseries.Section(800, 1000, 'rgba(216,0,29,0.3)'),
- steelseries.Section(1000, 1800, 'rgba(107,73,200,0.3)')
- ];
-
- // create Solar gauge
- if ($('#canvas_solar').length) {
- params.size = Math.ceil($('#canvas_solar').width() * config.gaugeScaling);
- params.section = cache.sections;
- params.maxValue = gaugeGlobals.solarGaugeScaleMax;
- params.titleString = strings.solar_title;
- params.unitString = 'W/m\u00B2';
- params.niceScale = false;
- params.thresholdVisible = false;
- params.lcdDecimals = 0;
-
- if (config.showSunshineLed) {
- params.userLedVisible = true;
- params.userLedColor = steelseries.LedColor.YELLOW_LED;
- }
-
- ssGauge = new steelseries.Radial('canvas_solar', params);
- ssGauge.setValue(cache.value);
-
- // over-ride CSS applied size?
- if (config.gaugeScaling !== 1) {
- $('#canvas_solar').css({ width: params.size + 'px', height: params.size + 'px' });
- }
-
- // add a shadow to the gauge
- if (config.showGaugeShadow) {
- $('#canvas_solar').css(gaugeShadow(params.size));
- }
- // subscribe to data updates
- $.subscribe('gauges.dataUpdated', update);
- $.subscribe('gauges.graphUpdate', updateGraph);
- } else {
- // cannot draw gauge, return null
- return null;
- }
-
- function update() {
- var tip, percent;
-
- cache.value = +extractInteger(data.SolarRad);
- cache.maxToday = extractInteger(data.SolarTM);
- cache.currMaxValue = +extractInteger(data.CurrentSolarMax);
- percent = (+cache.currMaxValue === 0 ? '--' : Math.round(+cache.value / +cache.currMaxValue * 100));
-
- // Need to rescale the gauge?
- cache.maxValue = Math.max(cache.value, cache.currMaxValue, cache.maxToday, gaugeGlobals.solarGaugeScaleMax);
- cache.maxValue = nextHighest(cache.maxValue, 100);
- if (cache.maxValue !== ssGauge.getMaxValue()) {
- ssGauge.setValue(0);
- ssGauge.setMaxValue(cache.maxValue);
- }
-
- // Set a section (15% of maxScale wide) to show current theoretical max value
- if (data.CurrentSolarMax !== 'N/A') {
- ssGauge.setArea([
- // Sunshine threshold
- steelseries.Section(
- Math.max(cache.currMaxValue * gaugeGlobals.sunshineThresholdPct / 100, gaugeGlobals.sunshineThreshold),
- cache.currMaxValue,
- 'rgba(255,255,50,0.4)'
- ),
- // Over max threshold
- steelseries.Section(
- cache.currMaxValue,
- Math.min(cache.currMaxValue + cache.maxValue * 0.15, cache.maxValue),
- 'rgba(220,0,0,0.5)'
- )
- ]);
- }
-
- // Set the values
- ssGauge.setMaxMeasuredValue(cache.maxToday);
- ssGauge.setValueAnimated(cache.value);
-
- if (config.showSunshineLed) {
- ssGauge.setUserLedOnOff(
- percent !== '--' &&
- percent >= gaugeGlobals.sunshineThresholdPct &&
- +cache.value >= gaugeGlobals.sunshineThreshold
- );
- }
-
- if (ddimgtooltip.showTips) {
- // update tooltip
- tip = '' + strings.solar_title + ': ' + cache.value + ' W/m² - ' +
- '' + percent + '% ' + strings.solar_ofMax + '
' +
- strings.solar_currentMax + ': ' + cache.currMaxValue + ' W/m²';
- if (typeof data.SolarTM !== 'undefined') {
- tip += '
' + strings.solar_maxToday + ': ' + cache.maxToday + ' W/m²';
- }
- $('#imgtip9_txt').html(tip);
- }
- } // End of update()
-
- function updateGraph(evnt, cacheDefeat) {
- if (config.tipImgs[9] !== null) {
- $('#imgtip9_img').attr('src', config.imgPathURL + config.tipImgs[9] + cacheDefeat);
- }
- }
-
- return {
- update: update,
- gauge: ssGauge
- };
- } // End of init()
-
- return {
- // Get the Singleton instance if one exists
- // or create one if it doesn't
- getInstance: function () {
- if (!instance) {
- instance = init();
- }
- return instance;
- }
- };
- })(),
-
- //
- // Singleton for the Cloudbase Gauge
- //
- singleCloudBase = (function () {
- var instance; // Stores a reference to the Singleton
- var ssGauge; // Stores a reference to the SS Gauge
- var cache = {}; // Stores various config values and parameters
-
- function init() {
- var params = $.extend(true, {}, commonParams);
-
- cache.sections = createCloudBaseSections(true);
- cache.value = 0.0001;
- cache.maxValue = gaugeGlobals.cloudScaleDefMaxm;
-
- // create Cloud base radial gauge
- if ($('#canvas_cloud').length) {
- params.size = Math.ceil($('#canvas_cloud').width() * config.gaugeScaling);
- params.section = cache.sections;
- params.maxValue = cache.maxValue;
- params.titleString = strings.cloudbase_title;
- params.unitString = strings.metres;
- params.thresholdVisible = false;
- params.lcdDecimals = 0;
-
- ssGauge = new steelseries.Radial('canvas_cloud', params);
- ssGauge.setValue(cache.value);
-
- // over-ride CSS applied size?
- if (config.gaugeScaling !== 1) {
- $('#canvas_cloud').css({ width: params.size + 'px', height: params.size + 'px' });
- }
-
- // add a shadow to the gauge
- if (config.showGaugeShadow) {
- $('#canvas_cloud').css(gaugeShadow(params.size));
- }
- // subscribe to data updates
- $.subscribe('gauges.dataUpdated', update);
- $.subscribe('gauges.graphUpdate', updateGraph);
- } else {
- // cannot draw gauge, return null
- return null;
- }
-
- function update() {
- cache.value = extractInteger(data.cloudbasevalue);
-
- if (data.cloudbaseunit === 'm') {
- // adjust metre gauge in jumps of 1000 metres, don't downscale during the session
- cache.maxValue = Math.max(nextHighest(cache.value, 1000), gaugeGlobals.cloudScaleDefMaxm, cache.maxValue);
- if (cache.value <= 1000 && config.roundCloudbaseVal) {
- // and round the value to the nearest 10 m
- cache.value = Math.round(cache.value / 10) * 10;
- } else if (config.roundCloudbaseVal) {
- // and round the value to the nearest 50 m
- cache.value = Math.round(cache.value / 50) * 50;
- }
- } else {
- // adjust feet gauge in jumps of 2000 ft, don't downscale during the session
- cache.maxValue = Math.max(nextHighest(cache.value, 2000), gaugeGlobals.cloudScaleDefMaxft, cache.maxValue);
- if (cache.value <= 2000 && config.roundCloudbaseVal) {
- // and round the value to the nearest 50 ft
- cache.value = Math.round(cache.value / 50) * 50;
- } else if (config.roundCloudbaseVal) {
- // and round the value to the nearest 100 ft
- cache.value = Math.round(cache.value / 100) * 100;
- }
- }
-
- if (cache.maxValue !== ssGauge.getMaxValue()) {
- if (ssGauge.getMaxValue() > cache.maxValue) {
- // Gauge currently showing more than our max (nice scale effct),
- // so reset our max to match
- cache.maxValue = ssGauge.getMaxValue();
- } else {
- // Gauge scale is too low, increase it.
- // First set the pointer back to zero so we get a nice animation
- ssGauge.setValue(0);
- // and redraw the gauge with teh new scale
- ssGauge.setMaxValue(cache.maxValue);
- }
- }
- ssGauge.setValueAnimated(cache.value);
-
- if (config.showPopupData) {
- // static tooltip on cloud gauge
- $('#imgtip11_txt').html('' + strings.cloudbase_popup_title + '
' + strings.cloudbase_popup_text);
- }
- } // End of update()
-
- function updateGraph(evnt, cacheDefeat) {
- if (config.tipImgs[11] !== null) {
- $('#imgtip11_img').attr('src', config.imgPathURL + config.tipImgs[11] + cacheDefeat);
- }
- }
-
- return {
- data: cache,
- update: update,
- gauge: ssGauge
- };
- } // End of init()
-
- return {
- // Get the Singleton instance if one exists
- // or create one if it doesn't
- getInstance: function () {
- if (!instance) {
- instance = init();
- }
- return instance;
- }
- };
- })(),
-
- //
- // getRealtime() fetches the realtimegauges JSON data from the server
- //
- getRealtime = function () {
- var url = config.realTimeURL;
- if ($.active > 0 && undefined != jqXHR) {
- // kill any outstanding requests
- jqXHR.abort();
- }
- if (config.longPoll) {
- url += '?timestamp=' + timestamp;
- }
- jqXHR = $.ajax({
- url: url,
- cache: (config.longPoll),
- dataType: 'json',
- timeout: config.longPoll ? (Math.min(config.realtimeInterval, 20) + 21) * 1000 : 21000 // 21 second time-out by default
- }).done(function (data) {
- checkRtResp(data);
- }).fail(function (xhr, status, err) {
- checkRtError(xhr, status, err);
- });
- },
-
- //
- // checkRtResp() called by the Ajax fetch once data has been downloaded
- //
- checkRtResp = function (response) {
- var delay;
- statusTimer.reset(config.longPoll ? 1 : config.realtimeInterval);
- if (config.longPoll && response.status !== 'OK') {
- checkRtError(null, 'PHP Error', response.status);
- } else {
- if (processData(response)) {
- delay = ajaxDelay;
- } else {
- delay = 5;
- }
- if (delay > 0) {
- downloadTimer = setTimeout(getRealtime, delay * 1000);
- } else {
- getRealtime();
- }
- }
- },
-
- //
- // checkRtError() called by the Ajax fetch if an error occurs during the fetching realtimegauges.txt
- //
- checkRtError = function (xhr, status, error) {
- if (xhr == null || xhr.statusText !== 'abort') {
- // Clear any existing download timer
- clearTimeout(downloadTimer);
- // Set the status LED to off
- ledIndicator.setLedOnOff(false);
- ledIndicator.setTitle(strings.led_title_unknown);
- statusScroller.setText(status + ': ' + error);
- // wait 5 seconds, then try again...
- downloadTimer = setTimeout(getRealtime, 5000);
- }
- },
-
- //
- // processData() massages the data returned in realtimegauges.txt, and posts a gauges.dataUpdated event to update the page
- //
- processData = function (dataObj) {
- var str, dt, tm, today, now, then, tmp, elapsedMins, retVal;
- // copy the realtime fields into the global 'data' object
- if (config.longPoll) {
- timestamp = dataObj.timestamp;
- data = dataObj.data;
- } else {
- // normal polling
- data = dataObj;
- }
-
- // and check we have the expected version number
- if (typeof data.ver !== 'undefined' && data.ver >= realtimeVer) {
- // manpulate the last rain time into something more friendly
- try {
- str = data.LastRainTipISO.split(' ');
- dt = str[0].replace(/\//g, '-').split('-'); // WD uses dd/mm/yyyy, we use a '-'
- tm = str[1].split(':');
- today = new Date();
- today.setHours(0, 0, 0, 0);
- if (typeof data.dateFormat === 'undefined') {
- data.dateFormat = 'y/m/d';
- } else {
- // frig for WD bug which leaves a trailing % character from the tag
- data.dateFormat = data.dateFormat.replace('%', '');
- }
- if (data.dateFormat === 'y/m/d') {
- // ISO/Cumulus format
- then = new Date(dt[0], dt[1] - 1, dt[2], tm[0], tm[1], 0, 0);
- } else if (data.dateFormat === 'd/m/y') {
- then = new Date(dt[2], dt[1] - 1, dt[0], tm[0], tm[1], 0, 0);
- } else { // m/d/y
- then = new Date(dt[2], dt[0] - 1, dt[1], tm[0], tm[1], 0, 0);
- }
- if (then.getTime() >= today.getTime()) {
- data.LastRained = strings.LastRainedT_info + ' ' + str[1];
- } else if (then.getTime() + 86400000 >= today.getTime()) {
- data.LastRained = strings.LastRainedY_info + ' ' + str[1];
- } else {
- data.LastRained = then.getDate().toString() + ' ' + strings.months[then.getMonth()] + ' ' + strings.at + ' ' + str[1];
- }
- } catch (e) {
- data.LastRained = data.LastRainTipISO;
- }
- if (data.tempunit.length > 1) {
- // clean up temperature units - remove html encoded degree symbols
- data.tempunit = data.tempunit.replace(/&\S*;/, '°'); // old Cumulus versions uses °, WeatherCat uses °
- } else {
- // using new realtimegaugesT.txt with Cumulus > 1.9.2
- data.tempunit = '°' + data.tempunit;
- }
-
- // Check for station off-line
- now = Date.now();
- tmp = data.timeUTC.split(',');
- sampleDate = Date.UTC(tmp[0], tmp[1] - 1, tmp[2], tmp[3], tmp[4], tmp[5]);
- if (now - sampleDate > config.stationTimeout * 60 * 1000) {
- elapsedMins = Math.floor((now - sampleDate) / (1000 * 60));
- // the realtimegauges.txt file isn't being updated
- ledIndicator.setLedColor(steelseries.LedColor.RED_LED);
- ledIndicator.setTitle(strings.led_title_offline);
- ledIndicator.blink(true);
- if (elapsedMins < 120) {
- // up to 2 hours ago
- tm = elapsedMins.toString() + ' ' + strings.StatusMinsAgo;
- } else if (elapsedMins < 2 * 24 * 60) {
- // up to 48 hours ago
- tm = Math.floor(elapsedMins / 60).toString() + ' ' + strings.StatusHoursAgo;
- } else {
- // days ago!
- tm = Math.floor(elapsedMins / (60 * 24)).toString() + ' ' + strings.StatusDaysAgo;
- }
- data.forecast = strings.led_title_offline + ' ' + strings.StatusLastUpdate + ' ' + tm;
- } else if (+data.SensorContactLost === 1) {
- // Fine Offset sensor status
- ledIndicator.setLedColor(steelseries.LedColor.RED_LED);
- ledIndicator.setTitle(strings.led_title_lost);
- ledIndicator.blink(true);
- data.forecast = strings.led_title_lost;
- } else {
- ledIndicator.setLedColor(steelseries.LedColor.GREEN_LED);
- ledIndicator.setTitle(strings.led_title_ok + '. ' + strings.StatusLastUpdate + ': ' + data.date);
- ledIndicator.blink(false);
- ledIndicator.setLedOnOff(true);
- }
-
- // de-encode the forecast string if required (Cumulus support for extended characters)
- data.forecast = $('').html(data.forecast).text();
- data.forecast = data.forecast.trim();
-
- data.pressunit = data.pressunit.trim(); // WView sends ' in', ' mb', or ' hPa'
- if (data.pressunit === 'in') { // Cumulus and WView send 'in'
- data.pressunit = 'inHg';
- }
-
- data.windunit = data.windunit.trim(); // WView sends ' kmh' etc
- data.windunit = data.windunit.toLowerCase(); // WeatherCat sends "MPH"
- if (data.windunit === 'knots') { // WeatherCat/weewx send "Knots", we use "kts"
- data.windunit = 'kts';
- }
-
- if (data.windunit === 'kmh' || data.windunit === 'kph') { // WD wind unit omits '/', weewx sends 'kph'
- data.windunit = 'km/h';
- }
-
- data.rainunit = data.rainunit.trim(); // WView sends ' mm' etc
-
- // take a look at the cloud base data...
- // change WeatherCat units from Metres/Feet to m/ft
- try {
- if (data.cloudbaseunit.toLowerCase() === 'metres') {
- data.cloudbaseunit = 'm';
- } else if (data.cloudbaseunit.toLowerCase() === 'feet') {
- data.cloudbaseunit = 'ft';
- }
- } catch (e) {
- data.cloudbaseunit = '';
- }
- if (config.showCloudGauge && (
- (config.weatherProgram === 4 || config.weatherProgram === 5) ||
- data.cloudbasevalue === '')) {
- // WeatherCat and VWS (and WView?) do not provide a cloud base value, so we have to calculate it...
- // assume if the station uses an imperial wind speed they want cloud base in feet, otherwise metres
- data.cloudbaseunit = (data.windunit === 'mph' || data.windunit === 'kts') ? 'ft' : 'm';
- data.cloudbasevalue = calcCloudbase(data.temp, data.tempunit, data.dew, data.cloudbaseunit);
- }
-
- // Temperature data conversion for display required?
- if (data.tempunit[1] !== displayUnits.temp && userUnitsSet) {
- // temp needs converting
- if (data.tempunit[1] === 'C') {
- convTempData(c2f);
- } else {
- convTempData(f2c);
- }
- } else if (firstRun) {
- displayUnits.temp = data.tempunit[1];
- setRadioCheck('rad_unitsTemp', displayUnits.temp);
- }
-
- // Rain data conversion for display required?
- if (data.rainunit !== displayUnits.rain && userUnitsSet) {
- // rain needs converting
- convRainData(displayUnits.rain === 'mm' ? in2mm : mm2in);
- } else if (firstRun) {
- displayUnits.rain = data.rainunit;
- setRadioCheck('rad_unitsRain', displayUnits.rain);
- }
-
- // Wind data conversion for display required?
- if (data.windunit !== displayUnits.wind && userUnitsSet) {
- // wind needs converting
- convWindData(data.windunit, displayUnits.wind);
- } else if (firstRun) {
- displayUnits.wind = data.windunit;
- displayUnits.windrun = getWindrunUnits(data.windunit);
- setRadioCheck('rad_unitsWind', displayUnits.wind);
- }
-
- // Pressure data conversion for display required?
- if (data.pressunit !== displayUnits.press && userUnitsSet) {
- convBaroData(data.pressunit, displayUnits.press);
- } else if (firstRun) {
- displayUnits.press = data.pressunit;
- setRadioCheck('rad_unitsPress', displayUnits.press);
- }
-
- // Cloud height data conversion for display required?
- if (data.cloudbaseunit !== displayUnits.cloud && userUnitsSet) {
- // Cloud height needs converting
- convCloudBaseData(displayUnits.cloud === 'm' ? ft2m : m2ft);
- } else if (firstRun) {
- displayUnits.cloud = data.cloudbaseunit;
- setRadioCheck('rad_unitsCloud', displayUnits.cloud);
- }
-
- statusScroller.setText(data.forecast);
-
- // first time only, setup units etc
- if (firstRun) {
- doFirst();
- }
-
- // publish the update, use the shared data object rather than transferring it
- $.publish('gauges.dataUpdated', {});
-
- retVal = true;
- } else {
- // set an error message
- if (data.ver < realtimeVer) {
- statusTimer.setValue(0);
- statusScroller.setText('Your ' + config.realTimeURL.substr(config.realTimeURL.lastIndexOf('/') + 1) + ' file template needs updating!');
- return false;
- } else {
- // oh-oh! The number of data fields isn't what we expected
- statusScroller.setText(strings.realtimeCorrupt);
- }
- ledIndicator.setLedOnOff(false);
- ledIndicator.setTitle(strings.led_title_unknown);
-
- retVal = false;
- }
- return retVal;
- },
-
- //
- // pagetimeout() called once every config.pageUpdateLimit minutes to stop updates and prevent page 'sitters'
- //
- pageTimeout = function () {
- statusScroller.setText(strings.StatusPageLimit);
- ledIndicator.setLedColor(steelseries.LedColor.RED_LED);
- ledIndicator.setTitle(strings.StatusPageLimit);
- ledIndicator.blink(true);
- ledIndicator.setTitle(strings.StatusTimeout);
-
- // stop any pending download
- clearTimeout(downloadTimer);
-
- // stop any long polling in progress
- if ($.active > 0) {
- jqXHR.abort();
- }
-
- // stop the clock
- clearInterval(tickTockInterval);
-
- // clear the timer display
- statusTimer.setValue(0);
-
- // set an onclick event on the LED to restart everything
- $('#canvas_led').click(
- function click() {
- // disable the onClick event again
- $('#canvas_led').unbind('click');
- // reset the timer count to 1
- statusTimer.reset(1);
- // restart the timer to update the status time
- tickTockInterval = setInterval(
- function tick() {
- $.publish('gauges.clockTick', null);
- },
- 1000
- );
-
- // restart the page timeout timer, so we hit this code again
- setTimeout(pageTimeout, config.pageUpdateLimit * 60 * 1000);
-
- // refresh the page data
- getRealtime();
- }
- );
- },
-
- //
- // doFirst() called by doUpdate() the first time the page is updated to set-up various things that are
- // only known when the realtimegauges.txt data is available
- //
- doFirst = function () {
- var cacheDefeat = '?' + (new Date()).getTime().toString();
-
- if (data.tempunit[1] === 'F') {
- displayUnits.temp = 'F';
- setRadioCheck('rad_unitsTemp', 'F');
- setTempUnits(false);
- }
-
- if (data.pressunit !== 'hPa') {
- displayUnits.press = data.pressunit;
- setRadioCheck('rad_unitsPress', data.pressunit);
- setBaroUnits(data.pressunit);
- }
-
- if (data.windunit !== 'km/h') {
- displayUnits.wind = data.windunit;
- setRadioCheck('rad_unitsWind', data.windunit);
- setWindUnits(data.windunit);
- }
-
- if (data.rainunit !== 'mm') {
- displayUnits.rain = data.rainunit;
- setRadioCheck('rad_unitsRain', data.rainunit);
- setRainUnits(false);
- }
-
- if (config.showSolarGauge && typeof data.SolarTM !== 'undefined' && gaugeSolar) {
- gaugeSolar.gauge.setMaxMeasuredValueVisible(true);
- }
-
- if (config.showCloudGauge && data.cloudbaseunit !== 'm') {
- displayUnits.cloud = data.cloudbaseunit;
- setRadioCheck('rad_unitsCloud', data.cloudbaseunit);
- setCloudBaseUnits(false);
- }
-
- // set the script version on the page
- $('#scriptVer').html(config.scriptVer);
- // set the version information from the station
- $('#programVersion').html(data.version);
- $('#programBuild').html(data.build);
- $('#programName').html(programLink[config.weatherProgram]);
-
- if (config.showPopupData) {
- // now initialise the pop-up script and download the trend /images
- // - has to be done here as doFirst may remove elements from the page
- // - and we delay the download of the /images speeding up page display
- ddimgtooltip.init('[id^="tip_"]');
- // Are we running on a phone device (or really low res screen)?
- if ($(window).width() < 480) {
- $('.ddimgtooltip').filter(':hidden').width('200px');
- }
- }
-
- if (config.showPopupData && config.showPopupGraphs) {
- // now download the trend /images
- // - has to be done here as doFirst may remove elements from the page
- // - and we delay the download of the /images speeding up page display
- //
- $('#imgtip0_img').attr('src', config.imgPathURL + config.tipImgs[0][0] + cacheDefeat);
- if (gaugeDew) {
- $('#imgtip1_img').attr('src', config.imgPathURL + config.tipImgs[1][gaugeDew.data.popupImg] + cacheDefeat);
- }
- $('#imgtip2_img').attr('src', config.imgPathURL + config.tipImgs[2] + cacheDefeat);
- $('#imgtip3_img').attr('src', config.imgPathURL + config.tipImgs[3] + cacheDefeat);
- $('#imgtip4_img').attr('src', config.imgPathURL + config.tipImgs[4][0] + cacheDefeat);
- $('#imgtip5_img').attr('src', config.imgPathURL + config.tipImgs[5] + cacheDefeat);
- $('#imgtip6_img').attr('src', config.imgPathURL + config.tipImgs[6] + cacheDefeat);
- $('#imgtip7_img').attr('src', config.imgPathURL + config.tipImgs[7] + cacheDefeat);
- $('#imgtip8_img').attr('src', config.imgPathURL + config.tipImgs[8] + cacheDefeat);
- $('#imgtip9_img').attr('src', config.imgPathURL + config.tipImgs[9] + cacheDefeat);
- $('#imgtip10_img').attr('src', config.imgPathURL + config.tipImgs[10] + cacheDefeat);
- $('#imgtip11_img').attr('src', config.imgPathURL + config.tipImgs[11] + cacheDefeat);
- // start a timer for popup graphic updates
- setInterval(
- function timeout() {
- $.publish('gauges.graphUpdate', '?' + (new Date()).getTime().toString());
- },
- config.graphUpdateTime * 60 * 1000
- );
- }
-
- firstRun = false;
- },
-
- //
- // createTempSections() creates an array of gauge sections appropriate for Celsius or Fahrenheit scales
- //
- createTempSections = function (celsius) {
- var section;
- if (celsius) {
- section = [
- steelseries.Section(-100, -35, 'rgba(195, 92, 211, 0.4)'),
- steelseries.Section(-35, -30, 'rgba(139, 74, 197, 0.4)'),
- steelseries.Section(-30, -25, 'rgba(98, 65, 188, 0.4)'),
- steelseries.Section(-25, -20, 'rgba(62, 66, 185, 0.4)'),
- steelseries.Section(-20, -15, 'rgba(42, 84, 194, 0.4)'),
- steelseries.Section(-15, -10, 'rgba(25, 112, 210, 0.4)'),
- steelseries.Section(-10, -5, 'rgba(9, 150, 224, 0.4)'),
- steelseries.Section(-5, 0, 'rgba(2, 170, 209, 0.4)'),
- steelseries.Section(0, 5, 'rgba(0, 162, 145, 0.4)'),
- steelseries.Section(5, 10, 'rgba(0, 158, 122, 0.4)'),
- steelseries.Section(10, 15, 'rgba(54, 177, 56, 0.4)'),
- steelseries.Section(15, 20, 'rgba(111, 202, 56, 0.4)'),
- steelseries.Section(20, 25, 'rgba(248, 233, 45, 0.4)'),
- steelseries.Section(25, 30, 'rgba(253, 142, 42, 0.4)'),
- steelseries.Section(30, 40, 'rgba(236, 45, 45, 0.4)'),
- steelseries.Section(40, 100, 'rgba(245, 109, 205, 0.4)')
- ];
- } else {
- section = [
- steelseries.Section(-200, -30, 'rgba(195, 92, 211, 0.4)'),
- steelseries.Section(-30, -25, 'rgba(139, 74, 197, 0.4)'),
- steelseries.Section(-25, -15, 'rgba(98, 65, 188, 0.4)'),
- steelseries.Section(-15, -5, 'rgba(62, 66, 185, 0.4)'),
- steelseries.Section(-5, 5, 'rgba(42, 84, 194, 0.4)'),
- steelseries.Section(5, 15, 'rgba(25, 112, 210, 0.4)'),
- steelseries.Section(15, 25, 'rgba(9, 150, 224, 0.4)'),
- steelseries.Section(25, 32, 'rgba(2, 170, 209, 0.4)'),
- steelseries.Section(32, 40, 'rgba(0, 162, 145, 0.4)'),
- steelseries.Section(40, 50, 'rgba(0, 158, 122, 0.4)'),
- steelseries.Section(50, 60, 'rgba(54, 177, 56, 0.4)'),
- steelseries.Section(60, 70, 'rgba(111, 202, 56, 0.4)'),
- steelseries.Section(70, 80, 'rgba(248, 233, 45, 0.4)'),
- steelseries.Section(80, 90, 'rgba(253, 142, 42, 0.4)'),
- steelseries.Section(90, 110, 'rgba(236, 45, 45, 0.4)'),
- steelseries.Section(110, 200, 'rgba(245, 109, 205, 0.4)')
- ];
- }
- return section;
- },
-
- //
- // createRainSections() returns an array of section highlights for the Rain Rate gauge
- //
- /*
- Assumes 'standard' descriptive limits from UK met office:
- < 0.25 mm/hr - Very light rain
- 0.25mm/hr to 1.0mm/hr - Light rain
- 1.0 mm/hr to 4.0 mm/hr - Moderate rain
- 4.0 mm/hr to 16.0 mm/hr - Heavy rain
- 16.0 mm/hr to 50 mm/hr - Very heavy rain
- > 50.0 mm/hour - Extreme rain
-
- Roughly translated to the corresponding Inch rates
- < 0.001
- 0.001 to 0.05
- 0.05 to 0.20
- 0.20 to 0.60
- 0.60 to 2.0
- > 2.0
- */
- createRainRateSections = function (metric) {
- var factor = metric ? 1 : 1 / 25;
- return [
- steelseries.Section(0, 0.25 * factor, 'rgba(0, 140, 0, 0.5)'),
- steelseries.Section(0.25 * factor, 1 * factor, 'rgba(80, 192, 80, 0.5)'),
- steelseries.Section(1 * factor, 4 * factor, 'rgba(150, 203, 150, 0.5)'),
- steelseries.Section(4 * factor, 16 * factor, 'rgba(212, 203, 109, 0.5)'),
- steelseries.Section(16 * factor, 50 * factor, 'rgba(225, 155, 105, 0.5)'),
- steelseries.Section(50 * factor, 1000 * factor, 'rgba(245, 86, 59, 0.5)')
- ];
- },
-
- //
- // createRainFallSections()returns an array of section highlights for total rainfall in mm or inches
- //
- createRainfallSections = function (metric) {
- var factor = metric ? 1 : 1 / 25;
- return [
- steelseries.Section(0, 5 * factor, 'rgba(0, 250, 0, 1)'),
- steelseries.Section(5 * factor, 10 * factor, 'rgba(0, 250, 117, 1)'),
- steelseries.Section(10 * factor, 25 * factor, 'rgba(218, 246, 0, 1)'),
- steelseries.Section(25 * factor, 40 * factor, 'rgba(250, 186, 0, 1)'),
- steelseries.Section(40 * factor, 50 * factor, 'rgba(250, 95, 0, 1)'),
- steelseries.Section(50 * factor, 65 * factor, 'rgba(250, 0, 0, 1)'),
- steelseries.Section(65 * factor, 75 * factor, 'rgba(250, 6, 80, 1)'),
- steelseries.Section(75 * factor, 100 * factor, 'rgba(205, 18, 158, 1)'),
- steelseries.Section(100 * factor, 125 * factor, 'rgba(0, 0, 250, 1)'),
- steelseries.Section(125 * factor, 500 * factor, 'rgba(0, 219, 212, 1)')
- ];
- },
-
- //
- // createRainfallGradient() returns an array of SS colours for continuous gradient colouring of the total rainfall LED gauge
- //
- createRainfallGradient = function (metric) {
- var grad = new steelseries.gradientWrapper(
- 0,
- (metric ? 100 : 4),
- [0, 0.1, 0.62, 1],
- [
- new steelseries.rgbaColor(15, 148, 0, 1),
- new steelseries.rgbaColor(213, 213, 0, 1),
- new steelseries.rgbaColor(213, 0, 25, 1),
- new steelseries.rgbaColor(250, 0, 0, 1)
- ]
- );
- return grad;
- },
-
- //
- // createClousBaseSections() returns an array of section highlights for the Cloud Base gauge
- //
- createCloudBaseSections = function (metric) {
- var section;
- if (metric) {
- section = [
- steelseries.Section(0, 150, 'rgba(245, 86, 59, 0.5)'),
- steelseries.Section(150, 300, 'rgba(225, 155, 105, 0.5)'),
- steelseries.Section(300, 750, 'rgba(212, 203, 109, 0.5)'),
- steelseries.Section(750, 1000, 'rgba(150, 203, 150, 0.5)'),
- steelseries.Section(1000, 1500, 'rgba(80, 192, 80, 0.5)'),
- steelseries.Section(1500, 2500, 'rgba(0, 140, 0, 0.5)'),
- steelseries.Section(2500, 5500, 'rgba(19, 103, 186, 0.5)')
- ];
- } else {
- section = [
- steelseries.Section(0, 500, 'rgba(245, 86, 59, 0.5)'),
- steelseries.Section(500, 1000, 'rgba(225, 155, 105, 0.5)'),
- steelseries.Section(1000, 2500, 'rgba(212, 203, 109, 0.5)'),
- steelseries.Section(2500, 3500, 'rgba(150, 203, 150, 0.5)'),
- steelseries.Section(3500, 5500, 'rgba(80, 192, 80, 0.5)'),
- steelseries.Section(5500, 8500, 'rgba(0, 140, 0, 0.5)'),
- steelseries.Section(8500, 18000, 'rgba(19, 103, 186, 0.5)')
- ];
- }
- return section;
- },
-
- //
- // --------------- Helper functions ------------------
- //
-
- //
- // getord() converts a value in degrees (0-360) into a localised compass point (N, ENE, NE, etc)
- //
- getord = function (deg) {
- if (deg === 0) {
- // Special case, 0=No wind, 360=North
- return strings.calm;
- } else {
- return (strings.coords[Math.floor((deg + 11.25) / 22.5) % 16]);
- }
- },
-
- //
- // getUrlParam() extracts the named parameter from the current page URL
- //
- getUrlParam = function (paramName) {
- var name, regexS, regex, results;
- name = paramName.replace(/(\[|\])/g, '\\$1');
- regexS = '[\\?&]' + name + '=([^]*)';
- regex = new RegExp(regexS);
- results = regex.exec(window.location.href);
- if (results === null) {
- return '';
- } else {
- return results[1];
- }
- },
-
- //
- // extractDecimal() returns a decimal number from a string, the decimal point can be either a dot or a comma
- // it ignores any text such as pre/appended units
- //
- extractDecimal = function (str, errVal) {
- try {
- return (/[-+]?[0-9]+\.?[0-9]*/).exec(str.replace(',', '.'))[0];
- } catch (e) {
- // error condition
- return errVal || -9999;
- }
- },
-
- //
- // extractInteger() returns an integer from a string
- // it ignores any text such as pre/appended units
- //
- extractInteger = function (str, errVal) {
- try {
- return (/[-+]?[0-9]+/).exec(str)[0];
- } catch (e) {
- // error condition
- return errVal || -9999;
- }
- },
-
- //
- // tempTrend() converts a temperature trend value into a localised string, or +1, 0, -1 depending on the value of bTxt
- //
- tempTrend = function (trend, units, bTxt) {
- // Scale is over 3 hours, in Celsius
- var val = trend * 3 * (units[1] === 'C' ? 1 : (5 / 9)),
- ret;
- if (trend === -9999) {
- ret = (bTxt ? '--' : trend);
- } else if (val > 5) {
- ret = (bTxt ? strings.RisingVeryRapidly : 1);
- } else if (val > 3) {
- ret = (bTxt ? strings.RisingQuickly : 1);
- } else if (val > 1) {
- ret = (bTxt ? strings.Rising : 1);
- } else if (val > 0.5) {
- ret = (bTxt ? strings.RisingSlowly : 1);
- } else if (val >= -0.5) {
- ret = (bTxt ? strings.Steady : 0);
- } else if (val >= -1) {
- ret = (bTxt ? strings.FallingSlowly : -1);
- } else if (val >= -3) {
- ret = (bTxt ? strings.Falling : -1);
- } else if (val >= -5) {
- ret = (bTxt ? strings.FallingQuickly : -1);
- } else {
- ret = (bTxt ? strings.FallingVeryRapidly : -1);
- }
- return ret;
- },
-
- //
- // baroTrend() converts a pressure trend value into a localised string, or +1, 0, -1 depending on the value of bTxt
- //
- baroTrend = function (trend, units, bTxt) {
- var val = trend * 3,
- ret;
- // The terms below are the UK Met Office terms for a 3 hour change in hPa
- // trend is supplied as an hourly change, so multiply by 3
- if (units === 'inHg') {
- val *= 33.8639;
- } else if (units === 'kPa') {
- val *= 10;
- // assume everything else is hPa or mb, could be dangerous!
- }
- if (trend === -9999) {
- ret = (bTxt ? '--' : trend);
- } else if (val > 6.0) {
- ret = (bTxt ? strings.RisingVeryRapidly : 1);
- } else if (val > 3.5) {
- ret = (bTxt ? strings.RisingQuickly : 1);
- } else if (val > 1.5) {
- ret = (bTxt ? strings.Rising : 1);
- } else if (val > 0.1) {
- ret = (bTxt ? strings.RisingSlowly : 1);
- } else if (val >= -0.1) {
- ret = (bTxt ? strings.Steady : 0);
- } else if (val >= -1.5) {
- ret = (bTxt ? strings.FallingSlowly : -1);
- } else if (val >= -3.5) {
- ret = (bTxt ? strings.Falling : -1);
- } else if (val >= -6.0) {
- ret = (bTxt ? strings.FallingQuickly : -1);
- } else {
- ret = (bTxt ? strings.FallingVeryRapidly : -1);
- }
- return ret;
- },
-
- //
- // getMinTemp() returns the lowest temperature today for gauge scaling
- //
- getMinTemp = function (deflt) {
- return Math.min(
- extractDecimal(data.tempTL, deflt),
- extractDecimal(data.dewpointTL, deflt),
- extractDecimal(data.apptempTL, deflt),
- extractDecimal(data.feelslikeTL, deflt),
- extractDecimal(data.wchillTL, deflt));
- },
-
- //
- // getMaxTemp() returns the highest temperature today for gauge scaling
- //
- getMaxTemp = function (deflt) {
- return Math.max(
- extractDecimal(data.tempTH, deflt),
- extractDecimal(data.apptempTH, deflt),
- extractDecimal(data.feelslikeTH, deflt),
- extractDecimal(data.heatindexTH, deflt),
- extractDecimal(data.humidex, deflt));
- },
-
- // Celsius to Fahrenheit
- c2f = function (val) {
- return (extractDecimal(val) * 9 / 5 + 32).toFixed(1);
- },
- // Fahrenheit to Celsius
- f2c = function (val) {
- return ((extractDecimal(val) - 32) * 5 / 9).toFixed(1);
- },
- // kph to ms
- kmh2ms = function (val) {
- return (extractDecimal(val) * 0.2778).toFixed(1);
- },
- // ms to kph
- ms2kmh = function (val) {
- return (extractDecimal(val) * 3.6).toFixed(1);
- },
- kmh2ms = function (val) {
- return (extractDecimal(val) / 3.6).toFixed(1);
- },
- // mm to inches
- mm2in = function (val) {
- return (extractDecimal(val) / 25.4).toFixed(2);
- },
- // inches to mm
- in2mm = function (val) {
- return (extractDecimal(val) * 25.4).toFixed(1);
- },
- // miles to km
- miles2km = function (val) {
- return (extractDecimal(val) * 1.609344).toFixed(1);
- },
- // nautical miles to km
- nmiles2km = function (val) {
- return (extractDecimal(val) * 1.85200).toFixed(1);
- },
- // km to miles
- km2miles = function (val) {
- return (extractDecimal(val) / 1.609344).toFixed(1);
- },
- // km to nautical miles
- km2nmiles = function (val) {
- return (extractDecimal(val) / 1.85200).toFixed(1);
- },
- // hPa to inHg (@0°C)
- hpa2inhg = function (val, decimals) {
- return (extractDecimal(val) * 0.029528744).toFixed(decimals || 3);
- },
- // inHg to hPa (@0°C)
- inhg2hpa = function (val) {
- return (extractDecimal(val) / 0.029528744).toFixed(1);
- },
- // kPa to hPa
- kpa2hpa = function (val) {
- return (extractDecimal(val) * 10).toFixed(1);
- },
- // hPa to kPa
- hpa2kpa = function (val, decimals) {
- return (extractDecimal(val) / 10).toFixed(decimals || 2);
- },
- // m to ft
- m2ft = function (val) {
- return (val * 3.2808399).toFixed(0);
- },
- // ft to m
- ft2m = function (val) {
- return (val / 3.2808399).toFixed(0);
- },
-
- //
- // setCookie() writes the 'obj' in cookie 'name' for persistent storage
- //
- setCookie = function (name, obj) {
- var date = new Date(),
- expires;
- // cookies valid for 1 year
- date.setYear(date.getFullYear() + 1);
- expires = '; expires=' + date.toGMTString();
- document.cookie = name + '=' + encodeURIComponent(JSON.stringify(obj)) + expires;
- },
-
- //
- // getCookie() reads the value of cookie 'name' from persistent storage
- //
- getCookie = function (name) {
- var i, x, y,
- ret = null,
- arrCookies = document.cookie.split(';');
-
- for (i = arrCookies.length; i--;) {
- x = arrCookies[i].split('=');
- if (x[0].trim() === name) {
- try {
- y = decodeURIComponent(x[1]);
- } catch (e) {
- y = x[1];
- }
- ret = JSON.parse(unescape(y));
- break;
- }
- }
- return ret;
- },
-
- //
- // setRadioCheck() sets the desired value of the HTML radio buttons to be selected
- //
- setRadioCheck = function (obj, val) {
- $('input:radio[name="' + obj + '"]').filter('[value="' + val + '"]').prop('checked', true);
- },
-
- //
- // convTempData() converts all the temperature values using the supplied conversion function
- //
- convTempData = function (convFunc) {
- data.apptemp = convFunc(data.apptemp);
- data.apptempTH = convFunc(data.apptempTH);
- data.apptempTL = convFunc(data.apptempTL);
- data.feelslike = convFunc(data.feelslike);
- data.feelslikeTH = convFunc(data.feelslikeTH);
- data.feelslikeTL = convFunc(data.feelslikeTL);
- data.dew = convFunc(data.dew);
- data.dewpointTH = convFunc(data.dewpointTH);
- data.dewpointTL = convFunc(data.dewpointTL);
- data.heatindex = convFunc(data.heatindex);
- data.heatindexTH = convFunc(data.heatindexTH);
- data.humidex = convFunc(data.humidex);
- data.intemp = convFunc(data.intemp);
- if (data.intempTL && data.intempTH) {
- data.intempTL = convFunc(data.intempTL);
- data.intempTH = convFunc(data.intempTH);
- }
- data.temp = convFunc(data.temp);
- data.tempTH = convFunc(data.tempTH);
- data.tempTL = convFunc(data.tempTL);
- data.wchill = convFunc(data.wchill);
- data.wchillTL = convFunc(data.wchillTL);
- if (convFunc === c2f) {
- data.temptrend = (+extractDecimal(data.temptrend) * 9 / 5).toFixed(1);
- data.tempunit = '°F';
- } else {
- data.temptrend = (+extractDecimal(data.temptrend) * 5 / 9).toFixed(1);
- data.tempunit = '°C';
- }
- },
-
- //
- // convRainData() converts all the rain data units using the supplied conversion function
- //
- convRainData = function (convFunc) {
- data.rfall = convFunc(data.rfall);
- data.rrate = convFunc(data.rrate);
- data.rrateTM = convFunc(data.rrateTM);
- data.hourlyrainTH = convFunc(data.hourlyrainTH);
- data.rainunit = convFunc === mm2in ? 'in' : 'mm';
- },
-
- //
- // convWindData() converts all the wind values using the supplied conversion function
- //
- convWindData = function (from, to) {
- var fromFunc1, toFunc1,
- fromFunc2, toFunc2,
- dummy = function (val) {
- return val;
- };
-
- // convert to km/h & km
- switch (from) {
- case 'mph':
- fromFunc1 = miles2km;
- fromFunc2 = miles2km;
- break;
- case 'kts':
- fromFunc1 = nmiles2km;
- fromFunc2 = nmiles2km;
- break;
- case 'm/s':
- fromFunc1 = ms2kmh;
- fromFunc2 = dummy;
- break;
- case 'km/h':
- // falls through
- default:
- fromFunc1 = dummy;
- fromFunc2 = dummy;
- }
- // conversion function from km to required units
- switch (to) {
- case 'mph':
- toFunc1 = km2miles;
- toFunc2 = km2miles;
- displayUnits.windrun = 'miles';
- break;
- case 'kts':
- toFunc1 = km2nmiles;
- toFunc2 = km2nmiles;
- displayUnits.windrun = 'n.miles';
- break;
- case 'm/s':
- toFunc1 = kmh2ms;
- toFunc2 = dummy;
- displayUnits.windrun = 'km';
- break;
- case 'km/h':
- // falls through
- default:
- toFunc1 = dummy;
- toFunc2 = dummy;
- displayUnits.windrun = 'km';
- }
- // do the conversions
- data.wgust = toFunc1(fromFunc1(data.wgust));
- data.wgustTM = toFunc1(fromFunc1(data.wgustTM));
- data.windTM = toFunc1(fromFunc1(data.windTM));
- data.windrun = toFunc2(fromFunc2(data.windrun));
- data.wlatest = toFunc1(fromFunc1(data.wlatest));
- data.wspeed = toFunc1(fromFunc1(data.wspeed));
- data.windunit = to;
- },
-
- //
- // convBaroData() converts all the pressure values using the supplied conversion function
- //
- convBaroData = function (from, to) {
- var fromFunc, toFunc,
- dummy = function (val) {
- return val;
- };
-
- // convert to hPa
- switch (from) {
- case 'hPa':
- // falls through
- case 'mb':
- fromFunc = dummy;
- break;
- case 'inHg':
- fromFunc = inhg2hpa;
- break;
- case 'kPa':
- fromFunc = kpa2hpa;
- break;
- // no default
- }
- // convert to required units
- switch (to) {
- case 'hPa':
- // falls through
- case 'mb':
- toFunc = dummy;
- break;
- case 'inHg':
- toFunc = hpa2inhg;
- break;
- case 'kPa':
- toFunc = hpa2kpa;
- break;
- // no default
- }
-
- data.press = toFunc(fromFunc(data.press));
- data.pressH = toFunc(fromFunc(data.pressH));
- data.pressL = toFunc(fromFunc(data.pressL));
- data.pressTH = toFunc(fromFunc(data.pressTH));
- data.pressTL = toFunc(fromFunc(data.pressTL));
- data.presstrendval = toFunc(fromFunc(data.presstrendval), 3);
- data.pressunit = to;
- },
-
- //
- // convCloudBaseData() converts all the cloud base data units using the supplied conversion function
- //
- convCloudBaseData = function (convFunc) {
- data.cloudbasevalue = convFunc(data.cloudbasevalue);
- data.cloudbaseunit = convFunc === m2ft ? 'ft' : 'm';
- },
-
- //
- // setUnits() Main data conversion routine, calls all the setXXXX() sub-routines
- //
- setUnits = function (radio) {
- var sel = radio.value;
-
- userUnitsSet = true;
-
- switch (sel) {
- // == Temperature ==
- case 'C':
- displayUnits.temp = sel;
- if (data.tempunit[1] !== sel) {
- setTempUnits(true);
- convTempData(f2c);
- if (gaugeTemp) { gaugeTemp.update(); }
- if (gaugeDew) { gaugeDew.update(); }
- }
- break;
- case 'F':
- displayUnits.temp = sel;
- if (data.tempunit[1] !== sel) {
- setTempUnits(false);
- convTempData(c2f);
- if (gaugeTemp) { gaugeTemp.update(); }
- if (gaugeDew) { gaugeDew.update(); }
- }
- break;
- // == Rainfall ==
- case 'mm':
- displayUnits.rain = sel;
- if (data.rainunit !== sel) {
- setRainUnits(true);
- convRainData(in2mm);
- if (gaugeRain) { gaugeRain.update(); }
- if (gaugeRRate) { gaugeRRate.update(); }
- }
- break;
- case 'in':
- displayUnits.rain = sel;
- if (data.rainunit !== sel) {
- setRainUnits(false);
- convRainData(mm2in);
- if (gaugeRain) { gaugeRain.update(); }
- if (gaugeRRate) { gaugeRRate.update(); }
- }
- break;
- // == Pressure ==
- case 'hPa':
- // falls through
- case 'inHg':
- // falls through
- case 'mb':
- // falls through
- case 'kPa':
- displayUnits.press = sel;
- if (data.pressunit !== sel) {
- convBaroData(data.pressunit, sel);
- setBaroUnits(sel);
- if (gaugeBaro) { gaugeBaro.update(); }
- }
- break;
- // == Wind speed ==
- case 'mph':
- // falls through
- case 'kts':
- // falls through
- case 'm/s':
- // falls through
- case 'km/h':
- displayUnits.wind = sel;
- if (data.windunit !== sel) {
- convWindData(data.windunit, sel);
- setWindUnits(sel);
- if (gaugeWind) { gaugeWind.update(); }
- if (gaugeDir) { gaugeDir.update(); }
- if (gaugeRose) { gaugeRose.update(); }
- }
- break;
- // == CloudBase ==
- case 'm':
- displayUnits.cloud = sel;
- if (data.cloudbaseunit !== sel) {
- setCloudBaseUnits(true);
- convCloudBaseData(ft2m);
- if (gaugeCloud) { gaugeCloud.update(); }
- }
- break;
- case 'ft':
- displayUnits.cloud = sel;
- if (data.cloudbaseunit !== sel) {
- setCloudBaseUnits(false);
- convCloudBaseData(m2ft);
- if (gaugeCloud) { gaugeCloud.update(); }
- }
- break;
- // no default
- }
- if (config.useCookies) {
- setCookie('units', displayUnits);
- }
- },
-
- setTempUnits = function (celsius) {
- if (celsius) {
- data.tempunit = '°C';
- if (gaugeTemp) {
- gaugeTemp.data.sections = createTempSections(true);
- gaugeTemp.data.minValue = gaugeGlobals.tempScaleDefMinC;
- gaugeTemp.data.maxValue = gaugeGlobals.tempScaleDefMaxC;
- }
- if (gaugeDew) {
- gaugeDew.data.sections = createTempSections(true);
- gaugeDew.data.minValue = gaugeGlobals.tempScaleDefMinC;
- gaugeDew.data.maxValue = gaugeGlobals.tempScaleDefMaxC;
- }
- } else {
- data.tempunit = '°F';
- if (gaugeTemp) {
- gaugeTemp.data.sections = createTempSections(false);
- gaugeTemp.data.minValue = gaugeGlobals.tempScaleDefMinF;
- gaugeTemp.data.maxValue = gaugeGlobals.tempScaleDefMaxF;
- }
- if (gaugeDew) {
- gaugeDew.data.sections = createTempSections(false);
- gaugeDew.data.minValue = gaugeGlobals.tempScaleDefMinF;
- gaugeDew.data.maxValue = gaugeGlobals.tempScaleDefMaxF;
- }
- }
- if (gaugeTemp) {
- gaugeTemp.gauge.setUnitString(data.tempunit);
- gaugeTemp.gauge.setSection(gaugeTemp.data.sections);
- }
- if (gaugeDew) {
- gaugeDew.gauge.setUnitString(data.tempunit);
- gaugeDew.gauge.setSection(gaugeTemp.data.sections);
- }
- },
-
- setRainUnits = function (mm) {
- if (mm) {
- data.rainunit = 'mm';
- if (gaugeRain) {
- gaugeRain.data.lcdDecimals = 1;
- gaugeRain.data.scaleDecimals = 1;
- gaugeRain.data.labelNumberFormat = gaugeGlobals.labelFormat;
- gaugeRain.data.sections = (gaugeGlobals.rainUseSectionColours ? createRainfallSections(true) : []);
- gaugeRain.data.maxValue = gaugeGlobals.rainScaleDefMaxmm;
- gaugeRain.data.grad = (gaugeGlobals.rainUseGradientColours ? createRainfallGradient(true) : null);
- }
- if (gaugeRRate) {
- gaugeRRate.data.lcdDecimals = 1;
- gaugeRRate.data.scaleDecimals = 0;
- gaugeRRate.data.labelNumberFormat = gaugeGlobals.labelFormat;
- gaugeRRate.data.sections = createRainRateSections(true);
- gaugeRRate.data.maxValue = gaugeGlobals.rainRateScaleDefMaxmm;
- }
- } else {
- data.rainunit = 'in';
- if (gaugeRain) {
- gaugeRain.data.lcdDecimals = 2;
- gaugeRain.data.scaleDecimals = gaugeGlobals.rainScaleDefMaxIn < 1 ? 2 : 1;
- gaugeRain.data.labelNumberFormat = steelseries.LabelNumberFormat.FRACTIONAL;
- gaugeRain.data.sections = (gaugeGlobals.rainUseSectionColours ? createRainfallSections(false) : []);
- gaugeRain.data.maxValue = gaugeGlobals.rainScaleDefMaxIn;
- gaugeRain.data.grad = (gaugeGlobals.rainUseGradientColours ? createRainfallGradient(false) : null);
- }
- if (gaugeRRate) {
- gaugeRRate.data.lcdDecimals = 2;
- gaugeRRate.data.scaleDecimals = gaugeGlobals.rainRateScaleDefMaxIn < 1 ? 2 : 1;
- gaugeRRate.data.labelNumberFormat = steelseries.LabelNumberFormat.FRACTIONAL;
- gaugeRRate.data.sections = createRainRateSections(false);
- gaugeRRate.data.maxValue = gaugeGlobals.rainRateScaleDefMaxIn;
- }
- }
- if (gaugeRain) {
- gaugeRain.data.value = 0;
- gaugeRain.gauge.setUnitString(data.rainunit);
- gaugeRain.gauge.setSection(gaugeRain.data.sections);
- gaugeRain.gauge.setGradient(gaugeRain.data.grad);
- gaugeRain.gauge.setFractionalScaleDecimals(gaugeRain.data.scaleDecimals);
- gaugeRain.gauge.setLabelNumberFormat(gaugeRain.data.labelNumberFormat);
- gaugeRain.gauge.setLcdDecimals(gaugeRain.data.lcdDecimals);
- gaugeRain.gauge.setValue(0);
- gaugeRain.gauge.setMaxValue(gaugeRain.data.maxValue);
- }
- if (gaugeRRate) {
- gaugeRRate.data.value = 0;
- gaugeRRate.gauge.setUnitString(data.rainunit + '/h');
- gaugeRRate.gauge.setSection(gaugeRRate.data.sections);
- gaugeRRate.gauge.setFractionalScaleDecimals(gaugeRRate.data.scaleDecimals);
- gaugeRRate.gauge.setLabelNumberFormat(gaugeRRate.data.labelNumberFormat);
- gaugeRRate.gauge.setLcdDecimals(gaugeRRate.data.lcdDecimals);
- gaugeRRate.gauge.setValue(0);
- gaugeRRate.gauge.setMaxValue(gaugeRRate.data.maxValue);
- }
- },
-
- setWindUnits = function (to) {
- var maxVal;
- data.windunit = to;
- if (gaugeWind) {
- // conversion function to required units
- switch (to) {
- case 'mph':
- maxVal = gaugeGlobals.windScaleDefMaxMph;
- break;
- case 'kts':
- maxVal = gaugeGlobals.windScaleDefMaxKts;
- break;
- case 'km/h':
- maxVal = gaugeGlobals.windScaleDefMaxKmh;
- break;
- case 'm/s':
- maxVal = gaugeGlobals.windScaleDefMaxMs;
- break;
- // no default
- }
- // set the gauges
- gaugeWind.data.maxValue = maxVal;
- gaugeWind.gauge.setUnitString(data.windunit);
- gaugeWind.gauge.setValue(0);
- }
- if (gaugeRose) {
- gaugeRose.setOdoTitle(strings[getWindrunUnits(data.windunit)]);
- }
- },
-
- setBaroUnits = function (to) {
- var minVal, maxVal;
-
- if (!gaugeBaro) { return; }
-
- // set to the required units
- switch (to) {
- case 'hPa':
- // falls through
- case 'mb':
- minVal = gaugeGlobals.baroScaleDefMinhPa;
- maxVal = gaugeGlobals.baroScaleDefMaxhPa;
- gaugeBaro.data.lcdDecimals = 1;
- gaugeBaro.data.scaleDecimals = 0;
- gaugeBaro.data.labelNumberFormat = gaugeGlobals.labelFormat;
- break;
- case 'inHg':
- minVal = gaugeGlobals.baroScaleDefMininHg;
- maxVal = gaugeGlobals.baroScaleDefMaxinHg;
- gaugeBaro.data.lcdDecimals = 2;
- gaugeBaro.data.scaleDecimals = 1;
- gaugeBaro.data.labelNumberFormat = steelseries.LabelNumberFormat.FRACTIONAL;
- break;
- case 'kPa':
- minVal = gaugeGlobals.baroScaleDefMinkPa;
- maxVal = gaugeGlobals.baroScaleDefMaxkPa;
- gaugeBaro.data.lcdDecimals = 2;
- gaugeBaro.data.scaleDecimals = 1;
- gaugeBaro.data.labelNumberFormat = steelseries.LabelNumberFormat.FRACTIONAL;
- break;
- // no default
- }
-
- data.pressunit = to;
- gaugeBaro.gauge.setUnitString(to);
- gaugeBaro.gauge.setLcdDecimals(gaugeBaro.data.lcdDecimals);
- gaugeBaro.gauge.setFractionalScaleDecimals(gaugeBaro.data.scaleDecimals);
- gaugeBaro.gauge.setLabelNumberFormat(gaugeBaro.data.labelNumberFormat);
- gaugeBaro.data.minValue = minVal;
- gaugeBaro.data.maxValue = maxVal;
- gaugeBaro.data.value = gaugeBaro.data.minValue;
- },
-
- setCloudBaseUnits = function (m) {
- if (!gaugeCloud) { return; }
-
- if (m) {
- gaugeCloud.data.sections = createCloudBaseSections(true);
- gaugeCloud.data.maxValue = gaugeGlobals.cloudScaleDefMaxm;
- } else {
- gaugeCloud.data.sections = createCloudBaseSections(false);
- gaugeCloud.data.maxValue = gaugeGlobals.cloudScaleDefMaxft;
- }
- gaugeCloud.data.value = 0;
- gaugeCloud.gauge.setUnitString(m ? strings.metres : strings.feet);
- gaugeCloud.gauge.setSection(gaugeCloud.data.sections);
- },
-
- //
- // setLang() switches the HTML page language set, called by changeLang() in language.js
- //
- setLang = function (newLang) {
- // reset to the new language
- strings = newLang;
-
- // temperature
- if (gaugeTemp) {
- if (config.showIndoorTempHum) {
- if ($('#rad_temp1').is(':checked')) {
- gaugeTemp.data.title = strings.temp_title_out;
- } else {
- gaugeTemp.data.title = strings.temp_title_in;
- }
- } else {
- gaugeTemp.data.title = strings.temp_title_out;
- }
- gaugeTemp.gauge.setTitleString(gaugeTemp.data.title);
- if (data.ver) { gaugeTemp.update(); }
- }
- if (gaugeDew) {
- switch ($('input[name="rad_dew"]:checked').val()) {
- case 'dew':
- gaugeDew.data.title = strings.dew_title;
- break;
- case 'app':
- gaugeDew.data.title = strings.apptemp_title;
- break;
- case 'feel':
- gaugeDew.data.title = strings.feel_title;
- break;
- case 'wnd':
- gaugeDew.data.title = strings.chill_title;
- break;
- case 'hea':
- gaugeDew.data.title = strings.heat_title;
- break;
- case 'hum':
- gaugeDew.data.title = strings.humdx_title;
- break;
- // no default
- }
- gaugeDew.gauge.setTitleString(gaugeDew.data.title);
- if (data.ver) { gaugeDew.update(); }
- }
- // rain
- if (gaugeRain) {
- gaugeRain.data.title = strings.rain_title;
- gaugeRain.gauge.setTitleString(gaugeRain.data.title);
- if (data.ver) { gaugeRain.update(); }
- }
- // rrate
- if (gaugeRRate) {
- gaugeRRate.data.title = strings.rrate_title;
- gaugeRRate.gauge.setTitleString(gaugeRRate.data.title);
- if (data.ver) { gaugeRRate.update(); }
- }
- // humidity
- if (gaugeHum) {
- if (config.showIndoorTempHum) {
- if ($('#rad_hum1').is(':checked')) {
- gaugeHum.data.title = strings.hum_title_out;
- } else {
- gaugeHum.data.title = strings.hum_title_in;
- }
- } else {
- gaugeHum.data.title = strings.hum_title_out;
- }
- gaugeHum.gauge.setTitleString(gaugeHum.data.title);
- if (data.ver) { gaugeHum.update(); }
- }
- // barometer
- if (gaugeBaro) {
- gaugeBaro.data.title = strings.baro_title;
- gaugeBaro.gauge.setTitleString(gaugeBaro.data.title);
- if (data.ver) { gaugeBaro.update(); }
- }
- // wind
- if (gaugeWind) {
- gaugeWind.data.title = strings.wind_title;
- gaugeWind.gauge.setTitleString(gaugeWind.data.title);
- if (data.ver) { gaugeWind.update(); }
- }
- if (gaugeDir) {
- gaugeDir.gauge.setPointSymbols(strings.compass);
- gaugeDir.data.titles = [strings.latest_web, strings.tenminavg_web];
- gaugeDir.gauge.setLcdTitleStrings(gaugeDir.data.titles);
- if (data.ver) { gaugeDir.update(); }
- }
- if (gaugeUV) {
- gaugeUV.gauge.setTitleString(strings.uv_title);
- if (data.ver) { gaugeUV.update(); }
- }
- if (gaugeSolar) {
- gaugeSolar.gauge.setTitleString(strings.solar_title);
- if (data.ver) { gaugeSolar.update(); }
- }
- if (gaugeRose) {
- gaugeRose.setTitle(strings.windrose);
- gaugeRose.setCompassStrings(strings.compass);
- gaugeRose.setOdoTitle(strings[getWindrunUnits(displayUnits.wind)]);
- if (data.ver) { gaugeRose.update(); }
- }
- if (gaugeCloud) {
- // Cloudbase
- gaugeCloud.data.units = data.cloudunit === 'm' ? strings.metres : strings.feet;
- gaugeCloud.gauge.setTitleString(strings.cloudbase_title);
- gaugeCloud.gauge.setUnitString(gaugeCloud.data.units);
- if (data.ver) { gaugeCloud.update(); }
- }
- },
-
- //
- // return windrun units based on the windspeed units
- //
- getWindrunUnits = function (spdUnits) {
- var retVal;
- switch (spdUnits) {
- case 'mph':
- retVal = 'miles';
- break;
- case 'kts':
- retVal = 'n_miles';
- break;
- case 'km/h':
- // falls through
- case 'm/s':
- // falls through
- default:
- retVal = 'km';
- break;
- }
- return retVal;
- },
-
- //
- // performs a simple cloudbase calculation for those weather programs that don't supply it
- //
- calcCloudbase = function (temp, tempunit, dew, cloudbaseunit) {
- var sprd = temp - dew;
- var cb = sprd * (tempunit[1] === 'C' ? 400 : 227.3); // cloud base in feet
- if (cloudbaseunit === 'm') {
- cb = ft2m(cb);
- }
- return cb;
- },
-
- //
- // create a shadow effect for the gauge using CSS
- //
- gaugeShadow = function (size) {
- var offset = Math.floor(size * 0.015);
- return {
- 'box-shadow': offset + 'px ' + offset + 'px ' + offset + 'px ' + gaugeGlobals.shadowColour,
- 'border-radius': Math.floor(size / 2) + 'px'
- };
- },
-
- //
- // generate a colour gradient based on start and end values
- //
- gradient = function (startCol, endCol, fraction) {
- var redOrigin, grnOrigin, bluOrigin,
- gradientSizeRed, gradientSizeGrn, gradientSizeBlu;
-
- redOrigin = parseInt(startCol.substr(0, 2), 16);
- grnOrigin = parseInt(startCol.substr(2, 2), 16);
- bluOrigin = parseInt(startCol.substr(4, 2), 16);
-
- gradientSizeRed = parseInt(endCol.substr(0, 2), 16) - redOrigin; // Graduation Size Red
- gradientSizeGrn = parseInt(endCol.substr(2, 2), 16) - grnOrigin;
- gradientSizeBlu = parseInt(endCol.substr(4, 2), 16) - bluOrigin;
-
- return (redOrigin + (gradientSizeRed * fraction)).toFixed(0) + ',' +
- (grnOrigin + (gradientSizeGrn * fraction)).toFixed(0) + ',' +
- (bluOrigin + (gradientSizeBlu * fraction)).toFixed(0);
- },
- //
- // returns the next highest number in the step sequence
- //
- nextHighest = function (value, step) {
- return +value == 0 ? step : Math.ceil(+value / step) * step;
- },
- //
- // returns the next lowest number in the step sequence
- //
- nextLowest = function (value, step) {
- return +value == 0 ? -step : Math.floor(+value / step) * step;
- };
-// ########################################################
-// End of gauges() var declarations
-// ########################################################
-
-//
-// Execution starts here
-//
-
-// test for canvas support before we do anything else, especially reference steelseries which will cause the script to abort!
-if (!document.createElement('canvas').getContext) {
- // failed, no canvas support detected
- $('body').html(strings.canvasnosupport);
- setTimeout(function () {
- window.location = config.oldGauges;
- }, 3000);
- return false;
-} else {
- //
- // Called when the document object has loaded
- // This starts the whole script.
- //
- $(document).ready(function () {
- // Kick it all off - false for web page, true for dashboard
- init(config.dashboardMode);
- });
-}
-
-return {
- setLang: setLang,
- setUnits: setUnits,
- processData: processData,
- config: config,
- init: init
-};
-}());
-
-// ===============================================================================================================================
-// ===============================================================================================================================
-// ===============================================================================================================================
-
-/*!
-* Image w/ description tooltip v2.0 - For FF1+ IE6+ Opr8+
-* Created: April 23rd, 2010. This notice must stay intact for usage
-* Author: Dynamic Drive at http://www.dynamicdrive.com/
-* Visit http://www.dynamicdrive.com/ for full source code
-* Modified: M Crossley June 2011, January 2012
-* v2.-
-*/
-var ddimgtooltip;
-ddimgtooltip = {
- tiparray: (function () {
- var style = { background: '#FFFFFF', color: 'black', border: '2px ridge darkblue' },
- i = 12, // set to number of tooltips required
- tooltips = [];
- for (; i--;) {
- tooltips[i] = [null, ' ', style];
- }
- return tooltips;
- }()),
-
- tooltipoffsets: [20, -30], // additional x and y offset from mouse cursor for tooltips
-
- tipDelay: 1000,
-
- delayTimer: 0,
-
- tipprefix: 'imgtip', // tooltip DOM ID prefixes
-
- createtip: function ($, tipid, tipinfo) {
- if ($('#' + tipid).length === 0) { // if this tooltip doesn't exist yet
- return $('')
- .html(
- ((tipinfo[1]) ? '' + tipinfo[1] + '
' : '') +
- (tipinfo[0] !== null ? '' : '')
- )
- .css(tipinfo[2] || {})
- .appendTo(document.body);
- }
- return null;
- },
-
- positiontooltip: function ($, $tooltip, e) {
- var x = e.pageX + this.tooltipoffsets[0],
- y = e.pageY + this.tooltipoffsets[1],
- tipw = $tooltip.outerWidth(),
- tiph = $tooltip.outerHeight(),
- wWidth = $(window).width(),
- wHght = $(window).height(),
- dTop = $(document).scrollTop();
-
- x = (x + tipw > $(document).scrollLeft() + wWidth) ? x - tipw - (ddimgtooltip.tooltipoffsets[0] * 2) : x;
- y = (y + tiph > dTop + wHght) ? dTop + wHght - tiph - 10 : y;
- // last ditch attempt to keep the graphs 'on page'
- x = Math.max(x, 0);
- if (tipw >= wWidth) {
- $($tooltip.attr('id') + '_img').css({ width: wWidth - 20 });
- $('#' + $tooltip.attr('id') + '_img').css({ width: wWidth - 20 });
- y = e.pageY + 5;
- }
- $tooltip.css({ left: x, top: y });
- },
-
- delaybox: function ($, $tooltip) {
- if (this.showTips) {
- ddimgtooltip.delayTimer = setTimeout(
- function () {
- ddimgtooltip.showbox($tooltip);
- }, ddimgtooltip.tipDelay);
- }
- },
-
- showbox: function (tooltip) {
- if (this.showTips) {
- // $(tooltip).show();
- $(tooltip).fadeIn();
- }
- },
-
- hidebox: function ($, $tooltip) {
- clearTimeout(ddimgtooltip.delayTimer);
- // $tooltip.hide();
- $tooltip.fadeOut();
- },
-
- showTips: false,
-
- init: function (targetselector) {
- var tiparray = ddimgtooltip.tiparray,
- $targets = $(targetselector);
-
- if ($targets.length === 0) {
- return;
- }
- $targets.each(function () {
- var $target = $(this),
- tipsuffix, tipid,
- $tooltip;
- var ind = ($target.attr('id').match(/_(\d+)/) || [])[1] || ''; // match d of attribute id='tip_d'
- tipsuffix = parseInt(ind, 10); // get d as integer
- tipid = this.tipid = ddimgtooltip.tipprefix + tipsuffix; // construct this tip's ID value and remember it
- $tooltip = ddimgtooltip.createtip($, tipid, tiparray[tipsuffix]);
-
- $target.mouseenter(function (e) {
- var $tooltip = $('#' + this.tipid);
- // ddimgtooltip.showbox($, $tooltip, e);
- ddimgtooltip.delaybox($, $tooltip, e);
- });
- $target.mouseleave(function () {
- var $tooltip = $('#' + this.tipid);
- ddimgtooltip.hidebox($, $tooltip);
- });
- $target.mousemove(function (e) {
- var $tooltip = $('#' + this.tipid);
- ddimgtooltip.positiontooltip($, $tooltip, e);
- });
- if ($tooltip) { // add mouseenter to this tooltip (only if event hasn't already been added)
- $tooltip.mouseenter(function () {
- ddimgtooltip.hidebox($, $(this));
- });
- }
- });
- }
-};
-
-// if String doesn't offer a .trim() method, add it
-String.prototype.trim = String.prototype.trim || function trim() {
- return this.replace(/^\s+|\s+$/g, '');
-};
+/*!
+ * THIS VERSION CUSTOMISED FROM CUMULUS MX DEFAULT WEB SITE
+ * Last Modified: 2023/09/02 17:15:14
+ *
+ * A starter gauges page for Cumulus and Weather Display, based
+ * on the JavaScript SteelSeries gauges by Gerrit Grunwald.
+ *
+ * Created by Mark Crossley, July 2011
+ * see scriptVer below for latest release
+ *
+ * Released under GNU GENERAL PUBLIC LICENSE, Version 2, June 1991
+ * See the enclosed License file
+ *
+ * File encoding = UTF-8
+ *
+ */
+
+/* exported gauges */
+
+/*!
+* Tiny Pub/Sub - v0.7.0 - 2013-01-29
+* https://github.com/cowboy/jquery-tiny-pubsub
+* Copyright (c) 2013 "Cowboy" Ben Alman; Licensed MIT
+*/
+(function ($) {
+ 'use strict';
+ var o = $({});
+ $.subscribe = function () { o.on.apply(o, arguments); };
+ $.unsubscribe = function () { o.off.apply(o, arguments); };
+ $.publish = function () { o.trigger.apply(o, arguments); };
+}(jQuery));
+
+var gauges;
+gauges = (function () {
+ 'use strict';
+ var strings = LANG.EN, // Set to your default language. Store all the strings in one object
+ config = {
+ // Script configuration parameters you may want to 'tweak'
+ scriptVer: '2.7.7',
+ weatherProgram: 0, // Set 0=Cumulus, 1=Weather Display, 2=VWS, 3=WeatherCat, 4=Meteobridge, 5=WView, 6=WeeWX, 7=WLCOM
+ imgPathURL: './/images/', // *** Change this to the relative path for your 'Trend' graph /images
+ oldGauges: 'gauges.htm', // *** Change this to the relative path for your 'old' gauges page.
+ realtimeInterval: 15, // *** Download data interval, set to your realtime data update interval in seconds
+ longPoll: false, // if enabled, use long polling and PHP generated data !!only enable if you understand how this is implemented!!
+ gaugeMobileScaling: 0.85, // scaling factor to apply when displaying the gauges mobile devices, set to 1 to disable (default 0.85)
+ graphUpdateTime: 15, // period of pop-up data graph refresh, in minutes (default 15)
+ stationTimeout: 3, // period of no data change before we declare the station off-line, in minutes (default 3)
+ pageUpdateLimit: 20, // period after which the page stops automatically updating, in minutes (default 20),
+ // - set to 0 (zero) to disable this feature
+ pageUpdatePswd: 'its-me', // password to over ride the page updates time-out, do not set to blank even if you do not use a password - http://&pageUpdate=its-me
+ digitalFont: false, // Font control for the gauges & timer
+ digitalForecast: false, // Font control for the status display, set this to false for languages that use accented characters in the forecasts
+ showPopupData: true, // Pop-up data displayed
+ showPopupGraphs: false, // If pop-up data is displayed, show the graphs?
+ mobileShowGraphs: false, // If false, on a mobile/narrow display, always disable the graphs
+ showWindVariation: true, // Show variation in wind direction over the last 10 minutes on the direction gauge
+ showWindMetar: false, // Show the METAR substring for wind speed/direction over the last 10 minutes on the direction gauge popup
+ showIndoorTempHum: true, // Show the indoor temperature/humidity options
+ showCloudGauge: true, // Display the Cloud Base gauge
+ showUvGauge: true, // Display the UV Index gauge
+ showSolarGauge: true, // Display the Solar gauge
+ showSunshineLed: true, // Show 'sun shining now' LED on solar gauge
+ showRoseGauge: true, // Show the optional Wind Rose gauge
+ showRoseGaugeOdo: true, // Show the optional Wind Rose gauge wind run Odometer
+ showRoseOnDirGauge: true, // Show the rose data as sectors on the direction gauge
+ showGaugeShadow: true, // Show a drop shadow outside the gauges
+ roundCloudbaseVal: true, // Round the value shown on the cloud base gauge to make it easier to read
+ // The realtime files should be absolute paths, "/xxx.txt" refers to the public root of your web server
+ realTimeUrlLongPoll: 'realtimegauges-longpoll.php', // *** ALL Users: If using long polling, change to your location of the PHP long poll realtime file ***
+ // *** the supplied file is for Cumulus only
+ realTimeUrlCumulus: '/data/realtimegauges.txt', // *** Cumulus Users: Change to your location of the realtime file ***
+ realTimeUrlWD: 'customclientraw.txt', // *** WD Users: Change to your location of the ccr file ***
+ realTimeUrlVWS: 'steelseriesVWSjson.php', // *** VWS Users: Change to your location of the JSON script generator ***
+ realTimeUrlWC: 'realtimegaugesWC.txt', // *** WeatherCat Users: Change to your location of the JSON script generator ***
+ realTimeUrlMB: 'MBrealtimegauges.txt', // *** Meteobridge Users: Change to the location of the JSON file
+ realTimeUrlWView: 'customclientraw.txt', // *** WView Users: Change to your location of the customclientraw.txt file ***
+ realTimeUrlWeewx: 'gauge-data.txt', // *** WeeWX Users: Change to your location of the gauge data file ***
+ realTimeUrlWLCOM: 'WLrealtimegauges.php', // *** WLCOM Users: change to location of WLCOMtags.php file ***
+ useCookies: true, // Persistently store user preferences in a cookie?
+ tipImages: [],
+ dashboardMode: false, // Used by Cumulus MX dashboard - SET TO FALSE OTHERWISE
+ dewDisplayType: 'dew' // Initial 'scale' to display on the 'dew point' gauge.
+ // 'dew' - Dewpoint
+ // 'app' - Apparent temperature
+ // 'wnd' - Wind Chill
+ // 'feel' - Feels Like
+ // 'hea' - Heat Index
+ // 'hum' - Humidex
+ },
+
+ // Gauge global look'n'feel settings
+ gaugeGlobals = {
+ minMaxArea: 'rgba(212,132,134,0.3)', // area sector for today's max/min. (red, green, blue, transparency)
+ windAvgArea: 'rgba(132,212,134,0.3)',
+ windVariationSector: 'rgba(120,200,120,0.7)', // only used when rose data is shown on direction gauge
+ frameDesign: steelseries.FrameDesign.TILTED_GRAY,
+ background: steelseries.BackgroundColor.BEIGE,
+ foreground: steelseries.ForegroundType.TYPE1,
+ pointer: steelseries.PointerType.TYPE8,
+ pointerColour: steelseries.ColorDef.RED,
+ dirAvgPointer: steelseries.PointerType.TYPE8,
+ dirAvgPointerColour: steelseries.ColorDef.BLUE,
+ gaugeType: steelseries.GaugeType.TYPE4,
+ lcdColour: steelseries.LcdColor.STANDARD,
+ knob: steelseries.KnobType.STANDARD_KNOB,
+ knobStyle: steelseries.KnobStyle.SILVER,
+ labelFormat: steelseries.LabelNumberFormat.STANDARD,
+ tickLabelOrientation: steelseries.TickLabelOrientation.HORIZONTAL, // was .NORMAL up to v1.6.4
+ rainUseSectionColours: false, // Only one of these colour options should be true
+ rainUseGradientColours: false, // Set both to false to use the pointer colour
+ tempTrendVisible: true,
+ pressureTrendVisible: true,
+ uvLcdDecimals: 1,
+ // sunshine threshold values
+ sunshineThreshold: 50, // the value in W/m² above which we can consider the Sun to be shining, *if* the current value exceeds...
+ sunshineThresholdPct: 75, // the percentage of theoretical solar irradiance above which we consider the Sun to be shining
+ // default gauge ranges - before auto-scaling/ranging
+ tempScaleDefMinC: -20,
+ tempScaleDefMaxC: 40,
+ tempScaleDefMinF: 0,
+ tempScaleDefMaxF: 100,
+ baroScaleDefMinhPa: 990,
+ baroScaleDefMaxhPa: 1030,
+ baroScaleDefMinkPa: 99,
+ baroScaleDefMaxkPa: 103,
+ baroScaleDefMininHg: 29.2,
+ baroScaleDefMaxinHg: 30.4,
+ windScaleDefMaxMph: 20,
+ windScaleDefMaxKts: 20,
+ windScaleDefMaxMs: 10,
+ windScaleDefMaxKmh: 30,
+ rainScaleDefMaxmm: 10,
+ rainScaleDefMaxIn: 0.5,
+ rainRateScaleDefMaxmm: 10,
+ rainRateScaleDefMaxIn: 0.5,
+ uvScaleDefMax: 10, // Northern Europe may be lower - max. value recorded in the UK is 8, so use a scale of 10 for UK
+ solarGaugeScaleMax: 1000, // Max value to be shown on the solar gauge - theoretical max without atmosphere ~ 1374 W/m²
+ // - but Davis stations can read up to 1800, use 1000 for Northern Europe?
+ cloudScaleDefMaxft: 3000,
+ cloudScaleDefMaxm: 1000,
+ shadowColour: 'rgba(0,0,0,0.3)' // Colour to use for gauge shadows - default 30% transparent black
+ },
+
+ commonParams = {
+ // Common parameters for all the SteelSeries gauges
+ fullScaleDeflectionTime: 4, // Bigger numbers (seconds) slow the gauge pointer movements more
+ gaugeType: gaugeGlobals.gaugeType,
+ minValue: 0,
+ niceScale: true,
+ ledVisible: false,
+ frameDesign: gaugeGlobals.frameDesign,
+ backgroundColor: gaugeGlobals.background,
+ foregroundType: gaugeGlobals.foreground,
+ pointerType: gaugeGlobals.pointer,
+ pointerColor: gaugeGlobals.pointerColour,
+ knobType: gaugeGlobals.knob,
+ knobStyle: gaugeGlobals.knobStyle,
+ lcdColor: gaugeGlobals.lcdColour,
+ lcdDecimals: 1,
+ digitalFont: config.digitalFont,
+ tickLabelOrientation: gaugeGlobals.tickLabelOrientation,
+ labelNumberFormat: gaugeGlobals.labelFormat
+ },
+ firstRun = true, // Used to set-up units & scales etc
+ userUnitsSet = false, // Tracks if the display units have been set by a user preference
+ data = {}, // Stores all the values from realtime.txt
+ tickTockInterval, // The 1s clock interval timer
+
+ // ajaxDelay, used by long polling, the delay between getting a response and queueing the next request, as the default PHP
+ // script runtime timout is 30 seconds, we do not want the PHP task to run for more than 20 seconds. So queue the next
+ // request half of the realtime interval, or 20 seconds before it is due, which ever is the larger.
+ ajaxDelay = config.longPoll ? Math.max(config.realtimeInterval - 20, 0) : config.realtimeInterval,
+ downloadTimer, // Stores a reference to the ajax download setTimout() timer
+ timestamp = 0, // the timestamp of last data update on the server.
+ jqXHR = null, // handle to the jQuery web request
+ displayUnits = null, // Stores the display units cookie settings
+ sampleDate,
+ realtimeVer, // minimum version of the realtime JSON file required
+ programLink = [
+ 'Cumulus',
+ 'Weather Display',
+ 'Virtual Weather Station',
+ 'WeatherCat',
+ 'Meteobridge',
+ 'Wview',
+ 'weewx',
+ 'Weatherlink.com'
+ ],
+
+ ledIndicator, statusScroller, statusTimer,
+
+ gaugeTemp, gaugeDew, gaugeRain, gaugeRRate,
+ gaugeHum, gaugeBaro, gaugeWind, gaugeDir,
+ gaugeUV, gaugeSolar, gaugeCloud, gaugeRose,
+
+ /* _imgBackground, // Uncomment if using a background image on the gauges */
+
+ // ==================================================================================================================
+ // Nothing below this line needs to be modified for the gauges as supplied
+ // - unless you really know what you are doing
+ // - but remember, if you break it, it's up to you to fix it ;-)
+ // ==================================================================================================================
+
+ //
+ // init() Called when the document is ready, pre-draws the Status Display then calls
+ // the first Ajax fetch of /data/realtimegauges.txt. First draw of the gauges now deferred until
+ // the Ajax data is available as a 'speed up'.
+ //
+ init = function (dashboard) {
+ // Cumulus, Weather Display, VWS, WeatherCat?
+ switch (config.weatherProgram) {
+ case 0:
+ // Cumulus
+ realtimeVer = 12; // minimum version of the realtime JSON file required
+ config.realTimeURL = config.longPoll ? config.realTimeUrlLongPoll : config.realTimeUrlCumulus;
+ // the trend /images to be used for the pop-up data, used in conjunction with config.imgPathURL
+ // by default this is configured for the Cumulus 'standard' web site
+ // ** If you specify one image in a sub-array, then you MUST provide /images for all the other sub-elements
+ config.tipImgs = [ // config.tipImgs for Cumulus users using the 'default' weather site
+ ['temp.png', 'intemp.png'], // Temperature: outdoor, indoor
+ // Temperature: dewpoint, apparent, windChill, heatIndex, humidex
+ ['temp.png', 'temp.png', 'temp.png', 'temp.png', 'temp.png'],
+ 'raint.png', // Rainfall
+ 'rain.png', // Rainfall rate
+ ['hum.png', 'hum.png'], // Humidity: outdoor, indoor
+ 'press.png', // Pressure
+ 'wind.png', // Wind speed
+ 'windd.png', // Wind direction
+ (config.showUvGauge ? 'uv.png' : null), // UV graph if UV sensor is present | =null if no UV sensor
+ (config.showSolarGauge ? 'solar.png' : null), // Solar rad graph if Solar sensor is present | Solar =null if no Solar sensor
+ (config.showRoseGauge ? 'windd.png' : null), // Wind direction if Rose is enabled | =null if Rose is disabled
+ (config.showCloudGauge ? 'press.png' : null) // Pressure for cloud height | =null if Cloud Height is disabled
+ ];
+ break;
+ case 1:
+ // Weather Display
+ realtimeVer = 14; // minimum version of the realtime JSON file required
+ config.realTimeURL = config.longPoll ? config.realTimeUrlLongPoll : config.realTimeUrlWD;
+ config.tipImgs = [ // config.tipImgs for Weather Display users with wxgraph
+ ['temp+hum_24hr.php', 'indoor_temp_24hr.php'], // Temperature: outdoor, indoor
+ // Temperature: dewpnt, apparent, windChill, HeatIndx, humidex
+ ['temp+dew+hum_1hr.php', 'temp+dew+hum_1hr.php', 'temp+dew+hum_1hr.php', 'temp+dew+hum_1hr.php', 'temp+dew+hum_1hr.php'],
+ 'rain_24hr.php', // Rainfall
+ 'rain_1hr.php', // Rainfall rate
+ ['humidity_1hr.php', 'humidity_7days.php'], // Humidity: outdoor, indoor
+ 'baro_24hr.php', // Pressure
+ 'windgust_1hr.php', // Wind speed
+ 'winddir_24hr.php', // Wind direction
+ (config.showUvGauge ? 'uv_24hr.php' : null), // UV graph if UV sensor is present | =null if no UV sensor
+ (config.showSolarGauge ? 'solar_24hr.php' : null), // Solar rad graph if Solar sensor is present | Solar =null if no Solar sensor
+ (config.showRoseGauge ? 'winddir_24hr.php' : null), // Wind direction if Rose is enabled | =null if Rose is disabled
+ (config.showCloudGauge ? 'baro_24hr.php' : null) // Pressure for cloud height | =null if Cloud Height is disabled
+ ];
+ // WD useer generally use wxgraphs - tweak the CSS to accomadate the different aspect ratio
+ $('.tipimg').css({
+ width: '360px',
+ height: '260px'
+ });
+ break;
+ case 2:
+ // WVS
+ realtimeVer = 11; // minimum version of the realtime JSON file required
+ config.realTimeURL = config.longPoll ? config.realTimeUrlLongPoll : config.realTimeUrlVWS;
+ config.showRoseGauge = false; // no wind rose data from VWS
+ config.showCloudGauge = false;
+ config.tipImgs = [ // config.tipImgs for VWS users
+ ['vws742.jpg', 'vws741.jpg'], // Temperature: outdoor, indoor
+ // Temperature: dewpnt, apparent, windChill, HeatIndx, humidex
+ ['vws757.jpg', 'vws762.jpg', 'vws754.jpg', 'vws756.jpg', null],
+ 'vws744.jpg', // Rainfall
+ 'vws859.jpg', // Rainfall rate
+ ['vws740.jpg', 'vws739.jpg'], // Humidity: outdoor, indoor
+ 'vws758.jpg', // Pressure
+ 'vws737.jpg', // Wind speed
+ 'vws736.jpg', // Wind direction
+ (config.showUvGauge ? 'vws752.jpg' : null), // UV graph if UV sensor is present | =null if no UV sensor
+ (config.showSolarGauge ? 'vws753.jpg' : null), // Solar rad graph if Solar sensor is present | Solar =null if no Solar sensor
+ (config.showRoseGauge ? 'vws736.jpg' : null), // Wind direction if Rose is enabled | =null if Rose is disabled
+ (config.showCloudGauge ? 'vws758.jpg' : null) // Pressure for cloud height | =null if Cloud Height is disabled
+ ];
+ break;
+ case 3:
+ // WeatherCat
+ realtimeVer = 14; // minimum version of the realtime JSON file required
+ config.realTimeURL = config.longPoll ? config.realTimeUrlLongPoll : config.realTimeUrlWC;
+ config.tipImgs = [ // config.tipImgs - WeatherCat users using the 'default' weather site
+ ['temperature1.jpg', 'tempin1.jpg'], // Temperature: outdoor, indoor
+ // Temperature: dewpoint, apparent, windChill, heatIndex, humidex
+ ['dewpoint1.jpg', 'temperature1.jpg', 'windchill1.jpg', 'heatindex1.jpg', 'temperature1.jpg'],
+ 'precipitationc1.jpg', // Rainfall
+ 'precipitation1.jpg', // Rainfall rate
+ ['rh1.jpg', 'rhin1.jpg'], // Humidity: outdoor, indoor
+ 'pressure1.jpg', // Pressure
+ 'windspeed1.jpg', // Wind speed
+ 'winddirection1.jpg', // Wind direction
+ (config.showUvGauge ? 'uv1.jpg' : null), // UV graph if UV sensor is present | =null if no UV sensor
+ (config.showSolarGauge ? 'solarrad1.jpg' : null), // Solar rad graph if Solar sensor is present | Solar =null if no Solar sensor
+ (config.showRoseGauge ? 'winddirection1.jpg' : null), // Wind direction if Rose is enabled | =null if Rose is disabled
+ (config.showCloudGauge ? 'cloudbase1.jpg' : null) // Pressure for cloud height | =null if Cloud Height is disabled
+ ];
+ break;
+ case 4:
+ // Meteobridge
+ realtimeVer = 10; // minimum version of the realtime JSON file required
+ config.realTimeURL = config.longPoll ? config.realTimeUrlLongPoll : config.realTimeUrlMB;
+ config.showPopupGraphs = false; // config.tipImgs - no Meteobridge /images available
+ config.showRoseGauge = false; // no windrose data from MB
+ config.showCloudGauge = false;
+ config.tipImgs = null; // config.tipImgs - no Meteobridge /images available
+ config.showWindVariation = false; // no wind variation data from MB
+ break;
+ case 5:
+ // WView
+ realtimeVer = 11; // minimum version of the realtime JSON file required
+ config.realTimeURL = config.longPoll ? config.realTimeUrlLongPoll : config.realTimeUrlWView;
+ config.showSunshineLed = false; // WView does not provide the current theoretical solar max required to determine sunshine
+ config.showWindVariation = false; // no wind variation from WView
+ config.showRoseGauge = false; // No wind rose array from WView by default - there is a user supplied modification to enable it though.
+ config.showCloudGauge = false;
+ config.tipImgs = [ // config.tipImgs for WView users
+ ['tempdaycomp.png', 'indoor_temp.png'], // Temperature: outdoor, indoor
+ // Temperature: dewpnt, apparent, windChill, HeatIndx, humidex
+ ['tempdaycomp.png', 'tempdaycomp.png', 'heatchillcomp.png', 'heatchillcomp.png', 'tempdaycomp.png'],
+ 'rainday.png', // Rainfall
+ 'rainrate.png', // Rainfall rate
+ ['humidday.png', 'humidday.png'], // Humidity: outdoor, indoor
+ 'baromday.png', // Pressure
+ 'wspeeddaycomp.png', // Wind speed
+ 'wdirday.png', // Wind direction
+ (config.showUvGauge ? 'uvday.png' : null), // UV graph if UV sensor is present | =null if no UV sensor
+ (config.showSolarGauge ? 'solarday.png' : null), // Solar rad graph if Solar sensor is present | Solar =null if no Solar sensor
+ (config.showRoseGauge ? 'windroseday.png' : null), // Wind direction if Rose is enabled | =null if Rose is disabled
+ (config.showCloudGauge ? 'baromday.png' : null) // Pressure for cloud height | =null if Cloud Height is disabled
+ ];
+ break;
+ case 6:
+ // weewx
+ realtimeVer = 14; // minimum version of the realtime JSON file required
+ config.realTimeURL = config.longPoll ? config.realTimeUrlLongPoll : config.realTimeUrlWeewx;
+ config.showSunshineLed = true;
+ config.showWindVariation = true;
+ config.tipImgs = [ // config.tipImgs for weewx
+ ['dayinouttemp.png', 'dayinouttemp.png'], // Temperature: outdoor, indoor
+ // Temperature: dewpnt, apparent, windChill, HeatIndx, humidex
+ ['dayouttemphum.png', 'dayouttemphum.png', 'dayouttemphum.png', 'dayouttemphum.png', 'dayouttemphum.png'],
+ 'dayrain.png', // Rainfall
+ 'dayrainrate.png', // Rainfall rate
+ ['dayinouthum.png', 'dayinouthum.png'], // Humidity: outdoor, indoor
+ 'daybarometer.png', // Pressure
+ 'daywind.png', // Wind speed
+ 'daywinddir.png', // Wind direction
+ (config.showUvGauge ? 'dayuv.png' : null), // UV graph if UV sensor is present | =null if no UV sensor
+ (config.showSolarGauge ? 'dayradiation.png' : null), // Solar rad graph if Solar sensor is present | Solar =null if no Solar sensor
+ (config.showRoseGauge ? 'daywindvec.png' : null), // Wind direction if Rose is enabled | =null if Rose is disabled
+ (config.showCloudGauge ? 'daybarometer.png' : null) // Pressure for cloud height | =null if Cloud Height is disabled
+ ];
+ break;
+ case 7:
+ // WLCOM
+ realtimeVer = 10; // minimum version of the realtime JSON file required
+ config.realTimeURL = config.realTimeUrlWLCOM;
+ config.showPopupGraphs = false; // config.tipImgs - no WL /images available
+ config.showRoseGauge = false; // no windrose data from WL
+ config.showCloudGauge = false;
+ config.tipImgs = null; // config.tipImgs - no WL /images available
+ config.showWindVariation = false; // no wind variation data from WL
+ break;
+ default:
+ // Who knows!
+ realtimeVer = 0; // minimum version of the realtime JSON file required
+ config.realtimeURL = null;
+ config.showPopupGraphs = false;
+ config.tipImgs = null; // config.tipImgs - unknown
+ }
+
+ // Are we running on a phone device (or really low res screen)?
+ if ($(window).width() < 480) {
+ // Change the gauge scaling
+ config.gaugeScaling = config.gaugeMobileScaling;
+ // Switch off graphs?
+ config.showPopupGraphs = config.mobileShowGraphs;
+ } else {
+ config.gaugeScaling = 1;
+ }
+
+ // Logo /images are used to 'personalise' the gauge backgrounds
+ // To add a logo to a gauge, add the parameter:
+ // params.customLayer = _imgBackground;
+ // to the corresponding drawXxxx() function below.
+ //
+ // These are for demo only, to add them remove the comments around the following lines, and
+ // the _imgBackground definition line above...
+ /*
+ _imgBackground = document.createElement('img'); // small logo
+ $(_imgBackground).attr('src', config.imgPathURL + 'logoSmall.png');
+ */
+ // End of logo /images
+
+ // Get the display units the user last used when they visited before - if present
+ displayUnits = getCookie('units');
+ // Set 'units' radio buttons to match preferred units
+ if (displayUnits !== null) {
+ // User wants specific units
+ userUnitsSet = true;
+
+ // temperature
+ setRadioCheck('rad_unitsTemp', displayUnits.temp);
+ data.tempunit = '°' + displayUnits.temp;
+ // rain
+ setRadioCheck('rad_unitsRain', displayUnits.rain);
+ data.rainunit = displayUnits.rain;
+ // pressure
+ setRadioCheck('rad_unitsPress', displayUnits.press);
+ data.pressunit = displayUnits.press;
+ // wind
+ setRadioCheck('rad_unitsWind', displayUnits.wind);
+ data.windunit = displayUnits.wind;
+ displayUnits.windrun = getWindrunUnits(data.windunit);
+ // cloud base
+ setRadioCheck('rad_unitsCloud', displayUnits.cloud);
+ data.cloudunit = displayUnits.cloud;
+ } else {
+ // Set the defaults to metric )
+ // DO NOT CHANGE THESE - THE SCRIPT DEPENDS ON THESE DEFAULTS
+ // The units actually displayed will be read from the realtime.txt file, or from the users last visit cookie
+ displayUnits = {
+ temp: 'C',
+ rain: 'mm',
+ press: 'hPa',
+ wind: 'km/h',
+ windrun: 'km',
+ cloud: 'm'
+ };
+
+ data.tempunit = '°C';
+ data.rainunit = 'mm';
+ data.pressunit = 'hPa';
+ data.windunit = 'km/h';
+ data.cloudunit = 'm';
+ }
+
+ // enable popup data
+ if (config.showPopupData) {
+ ddimgtooltip.showTips = config.showPopupData;
+ }
+
+ if (config.showPopupGraphs) {
+ // Note the number of array elements must match 'i' in ddimgtooltip.tiparray()
+ ddimgtooltip.tiparray[0][0] = (config.tipImgs[0][0] === null ? null : '');
+ ddimgtooltip.tiparray[1][0] = (config.tipImgs[1][0] === null ? null : '');
+ ddimgtooltip.tiparray[2][0] = (config.tipImgs[2] === null ? null : '');
+ ddimgtooltip.tiparray[3][0] = (config.tipImgs[3] === null ? null : '');
+ ddimgtooltip.tiparray[4][0] = (config.tipImgs[4][0] === null ? null : '');
+ ddimgtooltip.tiparray[5][0] = (config.tipImgs[5] === null ? null : '');
+ ddimgtooltip.tiparray[6][0] = (config.tipImgs[6] === null ? null : '');
+ ddimgtooltip.tiparray[7][0] = (config.tipImgs[7] === null ? null : '');
+ ddimgtooltip.tiparray[8][0] = (config.tipImgs[8] === null ? null : '');
+ ddimgtooltip.tiparray[9][0] = (config.tipImgs[9] === null ? null : '');
+ ddimgtooltip.tiparray[10][0] = (config.tipImgs[10] === null ? null : '');
+ ddimgtooltip.tiparray[11][0] = (config.tipImgs[11] === null ? null : '');
+ }
+
+ // draw the status gadgets first, they will display any errors in the initial set-up
+ ledIndicator = singleLed.getInstance();
+ statusScroller = singleStatus.getInstance();
+ statusTimer = singleTimer.getInstance();
+
+ gaugeTemp = singleTemp.getInstance();
+ // Export gaugeTemp.update() so it can be called from the HTML code
+ if (gaugeTemp) { gauges.doTemp = gaugeTemp.update; }
+
+ gaugeDew = singleDew.getInstance();
+ // Export gaugeDew.update() so it can be called from the HTML code
+ if (gaugeDew) { gauges.doDew = gaugeDew.update; }
+
+ gaugeHum = singleHum.getInstance();
+ // Export gaugeHum.update() so it can be called from the HTML code
+ if (gaugeHum) { gauges.doHum = gaugeHum.update; }
+
+ gaugeBaro = singleBaro.getInstance();
+
+ gaugeWind = singleWind.getInstance();
+ gaugeDir = singleDir.getInstance();
+
+ gaugeRain = singleRain.getInstance();
+ gaugeRRate = singleRRate.getInstance();
+
+ // remove the UV gauge?
+ if (!config.showUvGauge) {
+ $('#canvas_uv').parent().remove();
+ } else {
+ gaugeUV = singleUV.getInstance();
+ }
+
+ // remove the Solar gauge?
+ if (!config.showSolarGauge) {
+ $('#canvas_solar').parent().remove();
+ } else {
+ gaugeSolar = singleSolar.getInstance();
+ }
+
+ // remove the Wind Rose?
+ if (!config.showRoseGauge) {
+ $('#canvas_rose').parent().remove();
+ } else {
+ gaugeRose = singleRose.getInstance();
+ }
+
+ // remove the cloud base gauge?
+ if (!config.showCloudGauge) {
+ $('#canvas_cloud').parent().remove();
+ // and remove cloudbase unit selection options
+ $('#cloud').parent().remove();
+ } else {
+ gaugeCloud = singleCloudBase.getInstance();
+ }
+
+ // Set the language
+ changeLang(strings, false);
+
+ if (!dashboard) {
+ // Go do get the data!
+ getRealtime();
+
+ // start a timer to update the status time
+ tickTockInterval = setInterval(
+ function () {
+ $.publish('gauges.clockTick', null);
+ },
+ 1000);
+
+ // start a timer to stop the page updates after the timeout period
+ if (config.pageUpdateLimit > 0 && getUrlParam('pageUpdate') !== config.pageUpdatePswd) {
+ setTimeout(pageTimeout, config.pageUpdateLimit * 60 * 1000);
+ }
+ }
+ },
+
+ //
+ // singleXXXX functions define a singleton for each of the gauges
+ //
+
+ //
+ // Singleton for the LED Indicator
+ //
+ singleLed = (function () {
+ var instance; // Stores a reference to the Singleton
+ var led; // Stores a reference to the SS LED
+
+ function init() {
+ // create led indicator
+ if ($('#canvas_led').length) {
+ led = new steelseries.Led(
+ 'canvas_led', {
+ ledColor: steelseries.LedColor.GREEN_LED,
+ size: $('#canvas_led').width()
+ });
+
+ setTitle(strings.led_title);
+ }
+
+ function setTitle(newTitle) {
+ $('#canvas_led').attr('title', newTitle);
+ }
+
+ function setLedColor(newColour) {
+ if (led) {
+ led.setLedColor(newColour);
+ }
+ }
+
+ function setLedOnOff(onState) {
+ if (led) {
+ led.setLedOnOff(onState);
+ }
+ }
+
+ function blink(blinkState) {
+ if (led) {
+ led.blink(blinkState);
+ }
+ }
+
+ return {
+ setTitle: setTitle,
+ setLedColor: setLedColor,
+ setLedOnOff: setLedOnOff,
+ blink: blink
+ };
+ }
+
+ return {
+ // Get the Singleton instance if one exists
+ // or create one if it doesn't
+ getInstance: function () {
+ if (!instance) {
+ instance = init();
+ }
+ return instance;
+ }
+ };
+ })(),
+
+ //
+ // Singleton for the Status Scroller
+ //
+ singleStatus = (function () {
+ var instance; // Stores a reference to the Singleton
+ var scroller; // Stores a reference to the SS scrolling display
+
+ function init() {
+ // create forecast display
+ if ($('#canvas_status').length) {
+ scroller = new steelseries.DisplaySingle(
+ 'canvas_status', {
+ width: $('#canvas_status').width(),
+ height: $('#canvas_status').height(),
+ lcdColor: gaugeGlobals.lcdColour,
+ unitStringVisible: false,
+ value: strings.statusStr,
+ digitalFont: config.digitalForecast,
+ valuesNumeric: false,
+ autoScroll: true,
+ alwaysScroll: false
+ });
+ }
+
+ function setValue(newTxt) {
+ if (scroller) {
+ scroller.setValue(newTxt);
+ }
+ }
+
+ return { setText: setValue };
+ }
+
+ return {
+ // Get the Singleton instance if one exists
+ // or create one if it doesn't
+ getInstance: function () {
+ if (!instance) {
+ instance = init();
+ }
+ return instance;
+ }
+ };
+ })(),
+
+ //
+ // Singleton for the Status Timer
+ //
+ singleTimer = (function () {
+ var instance, // Stores a reference to the Singleton
+ lcd, // Stores a reference to the SS LED
+ count = 1;
+
+ function init() {
+ function tick() {
+ if (lcd) {
+ lcd.setValue(count);
+ count += config.longPoll ? 1 : -1;
+ }
+ }
+
+ function reset(val) {
+ count = val;
+ }
+
+ function setValue(newVal) {
+ if (lcd) {
+ lcd.setValue(newVal);
+ }
+ }
+
+ // create timer display
+ if ($('#canvas_timer').length) {
+ lcd = new steelseries.DisplaySingle(
+ 'canvas_timer', {
+ width: $('#canvas_timer').width(),
+ height: $('#canvas_timer').height(),
+ lcdColor: gaugeGlobals.lcdColour,
+ lcdDecimals: 0,
+ unitString: strings.timer,
+ unitStringVisible: true,
+ digitalFont: config.digitalFont,
+ value: count
+ });
+ // subscribe to data updates
+ $.subscribe('gauges.clockTick', tick);
+ }
+
+ return {
+ reset: reset,
+ setValue: setValue
+ };
+ }
+
+ return {
+ // Get the Singleton instance if one exists
+ // or create one if it doesn't
+ getInstance: function () {
+ if (!instance) {
+ instance = init();
+ }
+ return instance;
+ }
+ };
+ })(),
+
+ //
+ // Singleton for the Temperature Gauge
+ //
+ singleTemp = (function () {
+ var instance; // Stores a reference to the Singleton
+ var ssGauge; // Stores a reference to the SS Gauge
+ var cache = {}; // Stores various config values and parameters
+
+ function init() {
+ var params = $.extend(true, {}, commonParams);
+
+ // define temperature gauge start values
+ cache.sections = createTempSections(true);
+ cache.areas = [];
+ cache.minValue = gaugeGlobals.tempScaleDefMinC;
+ cache.maxValue = gaugeGlobals.tempScaleDefMaxC;
+ cache.title = strings.temp_title_out;
+ cache.value = gaugeGlobals.tempScaleDefMinC + 0.0001;
+ cache.maxMinVisible = false;
+ cache.selected = 'out';
+
+ // create temperature radial gauge
+ if ($('#canvas_temp').length) {
+ params.size = Math.ceil($('#canvas_temp').width() * config.gaugeScaling);
+ params.section = cache.sections;
+ params.area = cache.areas;
+ params.minValue = cache.minValue;
+ params.maxValue = cache.maxValue;
+ params.thresholdVisible = false;
+ params.minMeasuredValueVisible = cache.maxMinVisible;
+ params.maxMeasuredValueVisible = cache.maxMinVisible;
+ params.titleString = cache.title;
+ params.unitString = data.tempunit;
+ params.trendVisible = gaugeGlobals.tempTrendVisible;
+ // params.customLayer = _imgBackground; // uncomment to add a background image - See Logo /images above
+
+ ssGauge = new steelseries.Radial('canvas_temp', params);
+ ssGauge.setValue(cache.value);
+
+ // over-ride CSS applied size?
+ if (config.gaugeScaling !== 1) {
+ $('#canvas_temp').css({ width: params.size + 'px', height: params.size + 'px' });
+ }
+
+ // add a shadow to the gauge
+ if (config.showGaugeShadow) {
+ $('#canvas_temp').css(gaugeShadow(params.size));
+ }
+
+ // remove indoor temperature/humidity options?
+ if (!config.showIndoorTempHum) {
+ $('#rad_temp1').remove();
+ $('#lab_temp1').remove();
+ $('#rad_temp2').remove();
+ $('#lab_temp2').remove();
+ $('#rad_hum1').remove();
+ $('#lab_hum1').remove();
+ $('#rad_hum2').remove();
+ $('#lab_hum2').remove();
+ }
+
+ // subscribe to data updates
+ $.subscribe('gauges.dataUpdated', update);
+ $.subscribe('gauges.graphUpdate', updateGraph);
+ } else {
+ // cannot draw gauge, return null
+ return null;
+ }
+
+ function update() {
+ var sel = cache.selected;
+
+ // Argument length === 1 when called from radio input
+ // Argument length === 2 when called from event handler
+ if (arguments.length === 1) {
+ sel = arguments[0].value;
+ }
+
+ // if rad isn't specified, just use existing value
+ var t1, scaleStep, tip;
+
+ cache.minValue = data.tempunit[1] === 'C' ? gaugeGlobals.tempScaleDefMinC : gaugeGlobals.tempScaleDefMinF;
+ cache.maxValue = data.tempunit[1] === 'C' ? gaugeGlobals.tempScaleDefMaxC : gaugeGlobals.tempScaleDefMaxF;
+
+ if (sel === 'out') {
+ cache.low = extractDecimal(data.tempTL);
+ cache.high = extractDecimal(data.tempTH);
+ cache.lowScale = getMinTemp(cache.minValue);
+ cache.highScale = getMaxTemp(cache.maxValue);
+ cache.value = extractDecimal(data.temp);
+ cache.title = strings.temp_title_out;
+ cache.loc = strings.temp_out_info;
+ cache.trendVal = extractDecimal(data.temptrend);
+ cache.popupImg = 0;
+ if (gaugeGlobals.tempTrendVisible) {
+ t1 = tempTrend(+cache.trendVal, data.tempunit, false);
+ if (t1 === -9999) {
+ // trend value isn't currently available
+ cache.trend = steelseries.TrendState.OFF;
+ } else if (t1 > 0) {
+ cache.trend = steelseries.TrendState.UP;
+ } else if (t1 < 0) {
+ cache.trend = steelseries.TrendState.DOWN;
+ } else {
+ cache.trend = steelseries.TrendState.STEADY;
+ }
+ }
+ } else {
+ // Indoor
+ cache.title = strings.temp_title_in;
+ cache.loc = strings.temp_in_info;
+ cache.value = extractDecimal(data.intemp);
+ cache.popupImg = 1;
+ if (data.intempTL && data.intempTH) {
+ // Indoor - and Max/Min values supplied
+ cache.low = extractDecimal(data.intempTL);
+ cache.high = extractDecimal(data.intempTH);
+ cache.lowScale = getMinTemp(cache.minValue);
+ cache.highScale = getMaxTemp(cache.maxValue);
+ } else {
+ // Indoor - no Max/Min values supplied
+ cache.low = cache.value;
+ cache.lowScale = cache.value;
+ cache.high = cache.value;
+ cache.highScale = cache.value;
+ }
+ if (gaugeGlobals.tempTrendVisible) {
+ cache.trend = steelseries.TrendState.OFF;
+ }
+ }
+
+ // has the gauge type changed?
+ if (cache.selected !== sel) {
+ cache.selected = sel;
+ // Change gauge title
+ ssGauge.setTitleString(cache.title);
+ ssGauge.setMaxMeasuredValueVisible(cache.maxMinVisible);
+ ssGauge.setMinMeasuredValueVisible(cache.maxMinVisible);
+ if (config.showPopupGraphs && config.tipImgs[0][cache.popupImg] !== null) {
+ var cacheDefeat = '?' + $('#imgtip0_img').attr('src').split('?')[1];
+ $('#imgtip0_img').attr('src', config.imgPathURL + config.tipImgs[0][cache.popupImg] + cacheDefeat);
+ }
+ }
+
+ // auto scale the ranges
+ scaleStep = data.tempunit[1] === 'C' ? 10 : 20;
+ while (cache.lowScale < cache.minValue) {
+ cache.minValue -= scaleStep;
+ if (cache.highScale <= cache.maxValue - scaleStep) {
+ cache.maxValue -= scaleStep;
+ }
+ }
+ while (cache.highScale > cache.maxValue) {
+ cache.maxValue += scaleStep;
+ if (cache.minValue >= cache.minValue + scaleStep) {
+ cache.minValue += scaleStep;
+ }
+ }
+
+ if (cache.minValue !== ssGauge.getMinValue() || cache.maxValue !== ssGauge.getMaxValue()) {
+ ssGauge.setMinValue(cache.minValue);
+ ssGauge.setMaxValue(cache.maxValue);
+ ssGauge.setValue(cache.minValue);
+ }
+ if (cache.selected === 'out') {
+ cache.areas = [steelseries.Section(+cache.low, +cache.high, gaugeGlobals.minMaxArea)];
+ } else if (data.intempTL && data.intempTH) {
+ // Indoor and min/max avaiable
+ cache.areas = [steelseries.Section(+cache.low, +cache.high, gaugeGlobals.minMaxArea)];
+ } else {
+ // Indoor no min/max avaiable
+ cache.areas = [];
+ }
+
+ if (gaugeGlobals.tempTrendVisible) {
+ ssGauge.setTrend(cache.trend);
+ }
+ ssGauge.setArea(cache.areas);
+ ssGauge.setValueAnimated(+cache.value);
+
+ if (ddimgtooltip.showTips) {
+ // update tooltip
+ if (cache.selected === 'out') {
+ tip = cache.loc + ' - ' + strings.lowestF_info + ': ' + cache.low + data.tempunit + ' ' + strings.at + ' ' + data.TtempTL +
+ ' | ' +
+ strings.highestF_info + ': ' + cache.high + data.tempunit + ' ' + strings.at + ' ' + data.TtempTH;
+ if (cache.trendVal !== -9999) {
+ tip += '
' +
+ strings.temp_trend_info + ': ' + tempTrend(cache.trendVal, data.tempunit, true) +
+ ' ' + cache.trendVal + data.tempunit + '/h';
+ }
+ } else if (data.TintempTL && data.TintempTH) {
+ // Indoor and min/max available
+ tip = cache.loc + ' - ' + strings.lowestF_info + ': ' + cache.low + data.tempunit + ' ' + strings.at + ' ' + data.TintempTL +
+ ' | ' +
+ strings.highestF_info + ': ' + cache.high + data.tempunit + ' ' + strings.at + ' ' + data.TintempTH;
+ } else {
+ // Indoor no min/max
+ tip = cache.loc + ': ' + data.intemp + data.tempunit;
+ }
+ $('#imgtip0_txt').html(tip);
+ }
+ } // End of update()
+
+ function updateGraph(evnt, cacheDefeat) {
+ if (config.tipImgs[0][cache.popupImg] !== null) {
+ $('#imgtip0_img').attr('src', config.imgPathURL + config.tipImgs[0][cache.popupImg] + cacheDefeat);
+ }
+ }
+
+ return {
+ data: cache,
+ update: update,
+ gauge: ssGauge
+ };
+ } // End of init()
+
+ return {
+ // Get the Singleton instance if one exists
+ // or create one if it doesn't
+ getInstance: function () {
+ if (!instance) {
+ instance = init();
+ }
+ return instance;
+ }
+ };
+ })(), // End singleTemp()
+
+ //
+ // Singleton for the Dewpoint Gauge
+ //
+ singleDew = (function () {
+ var instance; // Stores a reference to the Singleton
+ var ssGauge; // Stores a reference to the SS Gauge
+ var cache = {}; // Stores various config values and parameters
+
+ function init() {
+ var params = $.extend(true, {}, commonParams);
+ var tmp;
+
+ // define dew point gauge start values
+ cache.sections = createTempSections(true);
+ cache.areas = [];
+ cache.minValue = gaugeGlobals.tempScaleDefMinC;
+ cache.maxValue = gaugeGlobals.tempScaleDefMaxC;
+ cache.value = gaugeGlobals.tempScaleDefMinC + 0.0001;
+ // Has the end user selected a preferred 'scale' before
+ tmp = getCookie('dewGauge');
+ cache.selected = tmp !== null ? tmp : config.dewDisplayType;
+ setRadioCheck('rad_dew', cache.selected);
+ switch (cache.selected) {
+ case 'dew':
+ cache.title = strings.dew_title;
+ cache.popupImg = 0;
+ break;
+ case 'app':
+ cache.title = strings.apptemp_title;
+ cache.popupImg = 1;
+ break;
+ case 'feel':
+ cache.title = strings.feel_title;
+ cache.popupImg = 1;
+ break;
+ case 'wnd':
+ cache.title = strings.chill_title;
+ cache.popupImg = 2;
+ break;
+ case 'hea':
+ cache.title = strings.heat_title;
+ cache.popupImg = 3;
+ break;
+ case 'hum':
+ cache.title = strings.humdx_title;
+ cache.popupImg = 4;
+ // no default
+ }
+ cache.minMeasuredVisible = false;
+ cache.maxMeasuredVisible = false;
+
+ // create dew point radial gauge
+ if ($('#canvas_dew').length) {
+ params.size = Math.ceil($('#canvas_dew').width() * config.gaugeScaling);
+ params.section = cache.sections;
+ params.area = cache.areas;
+ params.minValue = cache.minValue;
+ params.maxValue = cache.maxValue;
+ params.thresholdVisible = false;
+ params.titleString = cache.title;
+ params.unitString = data.tempunit;
+
+ ssGauge = new steelseries.Radial('canvas_dew', params);
+ ssGauge.setValue(cache.value);
+
+ // over-ride CSS applied size?
+ if (config.gaugeScaling !== 1) {
+ $('#canvas_dew').css({ width: params.size + 'px', height: params.size + 'px' });
+ }
+
+ // add a shadow to the gauge
+ if (config.showGaugeShadow) {
+ $('#canvas_dew').css(gaugeShadow(params.size));
+ }
+
+ // subscribe to data updates
+ $.subscribe('gauges.dataUpdated', update);
+ $.subscribe('gauges.graphUpdate', updateGraph);
+ } else {
+ // cannot draw gauge, return null
+ return null;
+ }
+
+ function update() {
+ // if rad isn't specified, just use existing value
+ var sel = cache.selected;
+
+ // Argument length === 2 when called from event handler
+ if (arguments.length === 1) {
+ sel = arguments[0].value;
+ // save the choice in a cookie
+ setCookie('dewGauge', sel);
+ }
+
+ var tip, scaleStep;
+
+ cache.minValue = data.tempunit[1] === 'C' ? gaugeGlobals.tempScaleDefMinC : gaugeGlobals.tempScaleDefMinF;
+ cache.maxValue = data.tempunit[1] === 'C' ? gaugeGlobals.tempScaleDefMaxC : gaugeGlobals.tempScaleDefMaxF;
+
+ cache.lowScale = getMinTemp(cache.minValue);
+ cache.highScale = getMaxTemp(cache.maxValue);
+
+ switch (sel) {
+ case 'dew': // dew point
+ cache.low = extractDecimal(data.dewpointTL);
+ cache.high = extractDecimal(data.dewpointTH);
+ cache.value = extractDecimal(data.dew);
+ cache.areas = [steelseries.Section(+cache.low, +cache.high, gaugeGlobals.minMaxArea)];
+ cache.title = strings.dew_title;
+ cache.minMeasuredVisible = false;
+ cache.maxMeasuredVisible = false;
+ cache.popupImg = 0;
+ tip = strings.dew_info + ':' +
+ '
' +
+ '- ' + strings.lowest_info + ': ' + cache.low + data.tempunit + ' ' + strings.at + ' ' + data.TdewpointTL +
+ ' | ' + strings.highest_info + ': ' + cache.high + data.tempunit + ' ' + strings.at + ' ' + data.TdewpointTH;
+ break;
+ case 'app': // apparent temperature
+ cache.low = extractDecimal(data.apptempTL);
+ cache.high = extractDecimal(data.apptempTH);
+ cache.value = extractDecimal(data.apptemp);
+ cache.areas = [steelseries.Section(+cache.low, +cache.high, gaugeGlobals.minMaxArea)];
+ cache.title = strings.apptemp_title;
+ cache.minMeasuredVisible = false;
+ cache.maxMeasuredVisible = false;
+ cache.popupImg = 1;
+ tip = tip = strings.apptemp_info + ':' +
+ '
' +
+ '- ' + strings.lowestF_info + ': ' + cache.low + data.tempunit + ' ' + strings.at + ' ' + data.TapptempTL +
+ ' | ' + strings.highestF_info + ': ' + cache.high + data.tempunit + ' ' + strings.at + ' ' + data.TapptempTH;
+ break;
+ case 'feel': // feels like
+ cache.low = extractDecimal(data.feelslikeTL);
+ cache.high = extractDecimal(data.feelslikeTH);
+ cache.value = extractDecimal(data.feelslike);
+ cache.areas = [steelseries.Section(+cache.low, +cache.high, gaugeGlobals.minMaxArea)];
+ cache.title = strings.feel_title;
+ cache.minMeasuredVisible = false;
+ cache.maxMeasuredVisible = false;
+ cache.popupImg = 1;
+ tip = tip = strings.feel_info + ':' +
+ '
' +
+ '- ' + strings.lowestF_info + ': ' + cache.low + data.tempunit + ' ' + strings.at + ' ' + data.TfeelslikeTL +
+ ' | ' + strings.highestF_info + ': ' + cache.high + data.tempunit + ' ' + strings.at + ' ' + data.TfeelslikeTH;
+ break;
+ case 'wnd': // wind chill
+ cache.low = extractDecimal(data.wchillTL);
+ cache.high = extractDecimal(data.wchill);
+ cache.value = extractDecimal(data.wchill);
+ cache.areas = [];
+ cache.title = strings.chill_title;
+ cache.minMeasuredVisible = true;
+ cache.maxMeasuredVisible = false;
+ cache.popupImg = 2;
+ tip = strings.chill_info + ':' +
+ '
' +
+ '- ' + strings.lowest_info + ': ' + cache.low + data.tempunit + ' ' + strings.at + ' ' + data.TwchillTL;
+ break;
+ case 'hea': // heat index
+ cache.low = extractDecimal(data.heatindex);
+ cache.high = extractDecimal(data.heatindexTH);
+ cache.value = extractDecimal(data.heatindex);
+ cache.areas = [];
+ cache.title = strings.heat_title;
+ cache.minMeasuredVisible = false;
+ cache.maxMeasuredVisible = true;
+ cache.popupImg = 3;
+ tip = strings.heat_info + ':' +
+ '
' +
+ '- ' + strings.highest_info + ': ' + cache.high + data.tempunit + ' ' + strings.at + ' ' + data.TheatindexTH;
+ break;
+ case 'hum': // humidex
+ cache.low = extractDecimal(data.humidex);
+ cache.high = extractDecimal(data.humidex);
+ cache.value = extractDecimal(data.humidex);
+ cache.areas = [];
+ cache.title = strings.humdx_title;
+ cache.minMeasuredVisible = false;
+ cache.maxMeasuredVisible = false;
+ cache.popupImg = 4;
+ tip = strings.humdx_info + ': ' + cache.value + data.tempunit;
+ break;
+ // no default
+ }
+
+ if (cache.selected !== sel) {
+ cache.selected = sel;
+ // change gauge title
+ ssGauge.setTitleString(cache.title);
+ // and graph image
+ if (config.showPopupGraphs && config.tipImgs[1][cache.popupImg] !== null) {
+ var cacheDefeat = '?' + $('#imgtip1_img').attr('src').split('?')[1];
+ $('#imgtip1_img').attr('src', config.imgPathURL + config.tipImgs[1][cache.popupImg] + cacheDefeat);
+ }
+ }
+
+ // auto scale the ranges
+ scaleStep = data.tempunit[1] === 'C' ? 10 : 20;
+ while (cache.lowScale < cache.minValue) {
+ cache.minValue -= scaleStep;
+ if (cache.highScale <= cache.maxValue - scaleStep) {
+ cache.maxValue -= scaleStep;
+ }
+ }
+ while (cache.highScale > cache.maxValue) {
+ cache.maxValue += scaleStep;
+ if (cache.minValue >= cache.minValue + scaleStep) {
+ cache.minValue += scaleStep;
+ }
+ }
+
+ if (cache.minValue !== ssGauge.getMinValue() || cache.maxValue !== ssGauge.getMaxValue()) {
+ ssGauge.setMinValue(cache.minValue);
+ ssGauge.setMaxValue(cache.maxValue);
+ ssGauge.setValue(cache.minValue);
+ }
+ ssGauge.setMinMeasuredValueVisible(cache.minMeasuredVisible);
+ ssGauge.setMaxMeasuredValueVisible(cache.maxMeasuredVisible);
+ ssGauge.setMinMeasuredValue(+cache.low);
+ ssGauge.setMaxMeasuredValue(+cache.high);
+ ssGauge.setArea(cache.areas);
+ ssGauge.setValueAnimated(+cache.value);
+
+ if (ddimgtooltip.showTips) {
+ // update tooltip
+ $('#imgtip1_txt').html(tip);
+ }
+ }
+
+ function updateGraph(evnt, cacheDefeat) {
+ if (config.tipImgs[1][cache.popupImg] !== null) {
+ $('#imgtip1_img').attr('src', config.imgPathURL + config.tipImgs[1][cache.popupImg] + cacheDefeat);
+ }
+ }
+
+ return {
+ data: cache,
+ update: update,
+ gauge: ssGauge
+ };
+ } // End of init()
+
+ return {
+ // Get the Singleton instance if one exists
+ // or create one if it doesn't
+ getInstance: function () {
+ if (!instance) {
+ instance = init();
+ }
+ return instance;
+ }
+ };
+ })(), // End of singleDew()
+
+ //
+ // Singleton for the Rainfall Gauge
+ //
+ singleRain = (function () {
+ var instance; // Stores a reference to the Singleton
+ var ssGauge; // Stores a reference to the SS Gauge
+ var cache = {}; // Stores various config values and parameters
+
+ function init() {
+ var params = $.extend(true, {}, commonParams);
+
+ // define rain gauge start values
+ cache.maxValue = gaugeGlobals.rainScaleDefMaxmm;
+ cache.value = 0.0001;
+ cache.title = strings.rain_title;
+ cache.lcdDecimals = 1;
+ cache.scaleDecimals = 1;
+ cache.labelNumberFormat = gaugeGlobals.labelFormat;
+ cache.sections = (gaugeGlobals.rainUseSectionColours ? createRainfallSections(true) : []);
+ cache.valGrad = (gaugeGlobals.rainUseGradientColours ? createRainfallGradient(true) : null);
+
+ // create rain radial bargraph gauge
+ if ($('#canvas_rain').length) {
+ params.size = Math.ceil($('#canvas_rain').width() * config.gaugeScaling);
+ params.maxValue = cache.maxValue;
+ params.thresholdVisible = false;
+ params.titleString = cache.title;
+ params.unitString = data.rainunit;
+ params.valueColor = steelseries.ColorDef.BLUE;
+ params.valueGradient = cache.valGrad;
+ params.useValueGradient = gaugeGlobals.rainUseGradientColours;
+ params.useSectionColors = gaugeGlobals.rainUseSectionColour;
+ params.useSectionColors = gaugeGlobals.rainUseSectionColours;
+ params.labelNumberFormat = cache.labelNumberFormat;
+ params.fractionalScaleDecimals = cache.scaleDecimals;
+ params.niceScale = false;
+
+ ssGauge = new steelseries.RadialBargraph('canvas_rain', params);
+ ssGauge.setValue(cache.value);
+
+ // over-ride CSS applied size?
+ if (config.gaugeScaling !== 1) {
+ $('#canvas_rain').css({ width: params.size + 'px', height: params.size + 'px' });
+ }
+
+ // add a shadow to the gauge
+ if (config.showGaugeShadow) {
+ $('#canvas_rain').css(gaugeShadow(params.size));
+ }
+
+ // subscribe to data updates
+ $.subscribe('gauges.dataUpdated', update);
+ $.subscribe('gauges.graphUpdate', updateGraph);
+ } else {
+ // cannot draw gauge, return null
+ return null;
+ }
+
+ function update() {
+ cache.value = extractDecimal(data.rfall);
+ if (data.rainunit === 'mm') { // 10, 20, 30...
+ cache.maxValue = Math.max(nextHighest(cache.value, 10), gaugeGlobals.rainScaleDefMaxmm);
+ } else {
+ // inches 0.5, 1.0, 2.0, 3.0 ... 10.0, 12.0, 14.0
+ if (cache.value <= 1) {
+ cache.maxValue = Math.max(nextHighest(cache.value, 0.5), gaugeGlobals.rainScaleDefMaxIn);
+ } else if (cache.value <= 6) {
+ cache.maxValue = Math.max(nextHighest(cache.value, 1), gaugeGlobals.rainScaleDefMaxIn);
+ } else {
+ cache.maxValue = Math.max(nextHighest(cache.value, 2), gaugeGlobals.rainScaleDefMaxIn);
+ }
+ cache.scaleDecimals = cache.maxValue < 1 ? 2 : 1;
+ }
+
+ if (cache.maxValue !== ssGauge.getMaxValue()) {
+ // Gauge scale is too low, increase it.
+ // First set the pointer back to zero so we get a nice animation
+ ssGauge.setValue(0);
+ // and redraw the gauge with the new scale
+ ssGauge.setFractionalScaleDecimals(cache.scaleDecimals);
+ ssGauge.setMaxValue(cache.maxValue);
+ }
+ ssGauge.setValueAnimated(cache.value);
+
+ if (ddimgtooltip.showTips) {
+ // update tooltip
+ $('#imgtip2_txt').html(strings.LastRain_info + ': ' + data.LastRained);
+ }
+ } // End of update()
+
+ function updateGraph(evnt, cacheDefeat) {
+ if (config.tipImgs[2] !== null) {
+ $('#imgtip2_img').attr('src', config.imgPathURL + config.tipImgs[2] + cacheDefeat);
+ }
+ }
+
+ return {
+ data: cache,
+ update: update,
+ gauge: ssGauge
+ };
+ } // End of init()
+
+ return {
+ // Get the Singleton instance if one exists
+ // or create one if it doesn't
+ getInstance: function () {
+ if (!instance) {
+ instance = init();
+ }
+ return instance;
+ }
+ };
+ })(),
+
+ //
+ // Singleton for the Rainfall Rate Gauge
+ //
+ singleRRate = (function () {
+ var instance; // Stores a reference to the Singleton
+ var ssGauge; // Stores a reference to the SS Gauge
+ var cache = {}; // Stores various config values and parameters
+
+ function init() {
+ var params = $.extend(true, {}, commonParams);
+
+ // define rain rate gauge start values
+ cache.maxMeasured = 0;
+ cache.maxValue = gaugeGlobals.rainRateScaleDefMaxmm;
+ cache.value = 0.0001;
+ cache.title = strings.rrate_title;
+ cache.lcdDecimals = 1;
+ cache.scaleDecimals = 0;
+ cache.labelNumberFormat = gaugeGlobals.labelFormat;
+ cache.sections = createRainRateSections(true);
+
+ // create rain rate radial gauge
+ if ($('#canvas_rrate').length) {
+ params.size = Math.ceil($('#canvas_rrate').width() * config.gaugeScaling);
+ params.section = cache.sections;
+ params.maxValue = cache.maxValue;
+ params.thresholdVisible = false;
+ params.maxMeasuredValueVisible = true;
+ params.titleString = cache.title;
+ params.unitString = data.rainunit + '/h';
+ params.lcdDecimals = cache.lcdDecimals;
+ params.labelNumberFormat = cache.labelNumberFormat;
+ params.fractionalScaleDecimals = cache.scaleDecimals;
+ params.niceScale = false;
+
+ ssGauge = new steelseries.Radial('canvas_rrate', params);
+ ssGauge.setMaxMeasuredValue(cache.maxMeasured);
+ ssGauge.setValue(cache.value);
+
+ // over-ride CSS applied size?
+ if (config.gaugeScaling !== 1) {
+ $('#canvas_rrate').css({ width: params.size + 'px', height: params.size + 'px' });
+ }
+
+ // add a shadow to the gauge
+ if (config.showGaugeShadow) {
+ $('#canvas_rrate').css(gaugeShadow(params.size));
+ }
+
+ // subscribe to data updates
+ $.subscribe('gauges.dataUpdated', update);
+ $.subscribe('gauges.graphUpdate', updateGraph);
+ } else {
+ // cannot draw gauge, return null
+ return null;
+ }
+
+ function update() {
+ var tip;
+
+ cache.value = extractDecimal(data.rrate);
+ cache.maxMeasured = extractDecimal(data.rrateTM);
+ cache.overallMax = Math.max(cache.maxMeasured, cache.value); // workaround for VWS bug, not supplying correct max value today
+
+ if (data.rainunit === 'mm') { // 10, 20, 30...
+ cache.maxValue = nextHighest(cache.overallMax, 10);
+ } else {
+ // inches 0.5, 1.0, 2.0, 3.0 ... 10, 20, 30...
+ if (cache.overallMax <= 0.5) {
+ cache.maxValue = 0.5;
+ } else if (cache.overallMax <= 10) {
+ cache.maxValue = nextHighest(cache.overallMax, 1);
+ } else {
+ cache.maxValue = nextHighest(cache.overallMax, 10);
+ }
+ cache.scaleDecimals = cache.maxValue < 1 ? 2 : (cache.maxValue < 7 ? 1 : 0);
+ }
+
+ if (cache.maxValue !== ssGauge.getMaxValue()) {
+ ssGauge.setValue(0);
+ ssGauge.setFractionalScaleDecimals(cache.scaleDecimals);
+ ssGauge.setMaxValue(cache.maxValue);
+ }
+
+ ssGauge.setValueAnimated(cache.value);
+ ssGauge.setMaxMeasuredValue(cache.maxMeasured);
+
+ if (ddimgtooltip.showTips) {
+ // update tooltip
+ tip = strings.rrate_info + ':
' +
+ '- ' + strings.maximum_info + ': ' + data.rrateTM + ' ' + data.rainunit + '/h ' + strings.at + ' ' + data.TrrateTM +
+ ' | ' + strings.max_hour_info + ': ' + extractDecimal(data.hourlyrainTH) + ' ' + data.rainunit + ' ' +
+ strings.at + ' ' + data.ThourlyrainTH;
+ $('#imgtip3_txt').html(tip);
+ }
+ } // End of update()
+
+ function updateGraph(evnt, cacheDefeat) {
+ if (config.tipImgs[3] !== null) {
+ $('#imgtip3_img').attr('src', config.imgPathURL + config.tipImgs[3] + cacheDefeat);
+ }
+ }
+ return {
+ data: cache,
+ update: update,
+ gauge: ssGauge
+ };
+ } // End of init()
+
+ return {
+ // Get the Singleton instance if one exists
+ // or create one if it doesn't
+ getInstance: function () {
+ if (!instance) {
+ instance = init();
+ }
+ return instance;
+ }
+ };
+ })(),
+
+ //
+ // Singleton for the Humidity Gauge
+ //
+ singleHum = (function () {
+ var instance; // Stores a reference to the Singleton
+ var ssGauge; // Stores a reference to the SS Gauge
+ var cache = {}; // Stores various config values and parameters
+
+ function init() {
+ var params = $.extend(true, {}, commonParams);
+
+ // define humidity gauge start values
+ cache.areas = [];
+ cache.value = 0.0001;
+ cache.title = strings.hum_title_out;
+ cache.selected = 'out';
+
+ // create humidity radial gauge
+ if ($('#canvas_hum').length) {
+ params.size = Math.ceil($('#canvas_hum').width() * config.gaugeScaling);
+ params.section = [
+ steelseries.Section(0, 20, 'rgba(255,255,0,0.3)'),
+ steelseries.Section(20, 80, 'rgba(0,255,0,0.3)'),
+ steelseries.Section(80, 100, 'rgba(255,0,0,0.3)')
+ ];
+ params.area = cache.areas;
+ params.maxValue = 100;
+ params.thresholdVisible = false;
+ params.titleString = cache.title;
+ params.unitString = 'RH%';
+
+ ssGauge = new steelseries.Radial('canvas_hum', params);
+ ssGauge.setValue(cache.value);
+
+ // over-ride CSS applied size?
+ if (config.gaugeScaling !== 1) {
+ $('#canvas_hum').css({ width: params.size + 'px', height: params.size + 'px' });
+ }
+
+ // add a shadow to the gauge
+ if (config.showGaugeShadow) {
+ $('#canvas_hum').css(gaugeShadow(params.size));
+ }
+
+ // subscribe to data updates
+ $.subscribe('gauges.dataUpdated', update);
+ $.subscribe('gauges.graphUpdate', updateGraph);
+ } else {
+ // cannot draw gauge, return null
+ return null;
+ }
+
+ function update() {
+ var radio;
+ // Argument length === 2 when called from event handler
+ if (arguments.length === 1) {
+ radio = arguments[0];
+ }
+
+ // if rad isn't specified, just use existing value
+ var sel = (typeof radio === 'undefined' ? cache.selected : radio.value),
+ tip;
+
+ if (sel === 'out') {
+ cache.value = extractDecimal(data.hum);
+ cache.areas = [steelseries.Section(+extractDecimal(data.humTL), +extractDecimal(data.humTH), gaugeGlobals.minMaxArea)];
+ cache.title = strings.hum_title_out;
+ cache.popupImg = 0;
+ } else {
+ cache.value = extractDecimal(data.inhum);
+ if (data.inhumTL && data.inhumTH) {
+ cache.areas = [steelseries.Section(+extractDecimal(data.inhumTL), +extractDecimal(data.inhumTH), gaugeGlobals.minMaxArea)];
+ } else {
+ cache.areas = [];
+ }
+ cache.title = strings.hum_title_in;
+ cache.popupImg = 1;
+ }
+
+ if (cache.selected !== sel) {
+ cache.selected = sel;
+ // Change gauge title
+ ssGauge.setTitleString(cache.title);
+ if (config.showPopupGraphs && config.tipImgs[4][cache.popupImg] !== null) {
+ var cacheDefeat = '?' + $('#imgtip4_img').attr('src').split('?')[1];
+ $('#imgtip4_img').attr('src', config.imgPathURL + config.tipImgs[4][cache.popupImg] + cacheDefeat);
+ }
+ }
+
+ ssGauge.setArea(cache.areas);
+ ssGauge.setValueAnimated(cache.value);
+
+ if (ddimgtooltip.showTips) {
+ // update tooltip
+ if (cache.selected === 'out') {
+ tip = strings.hum_out_info + ':' +
+ '
' +
+ '- ' + strings.minimum_info + ': ' + extractDecimal(data.humTL) + '% ' + strings.at + ' ' + data.ThumTL +
+ ' | ' + strings.maximum_info + ': ' + extractDecimal(data.humTH) + '% ' + strings.at + ' ' + data.ThumTH;
+ } else if (data.inhumTL && data.inhumTH) {
+ // we have indoor high/low data
+ tip = strings.hum_in_info + ':' +
+ '
' +
+ '- ' + strings.minimum_info + ': ' + extractDecimal(data.inhumTL) + '% ' + strings.at + ' ' + data.TinhumTL +
+ ' | ' + strings.maximum_info + ': ' + extractDecimal(data.inhumTH) + '% ' + strings.at + ' ' + data.TinhumTH;
+ } else {
+ // no indoor high/low data
+ tip = strings.hum_in_info + ': ' + extractDecimal(data.inhum) + '%';
+ }
+ $('#imgtip4_txt').html(tip);
+ }
+ } // End of update()
+
+ function updateGraph(evnt, cacheDefeat) {
+ if (config.tipImgs[4][cache.popupImg] !== null) {
+ $('#imgtip4_img').attr('src', config.imgPathURL + config.tipImgs[4][cache.popupImg] + cacheDefeat);
+ }
+ }
+
+ return {
+ data: cache,
+ update: update,
+ gauge: ssGauge
+ };
+ } // End of init()
+
+ return {
+ // Get the Singleton instance if one exists
+ // or create one if it doesn't
+ getInstance: function () {
+ if (!instance) {
+ instance = init();
+ }
+ return instance;
+ }
+ };
+ })(),
+
+ //
+ // Singleton for the Barometer Gauge
+ //
+ singleBaro = (function () {
+ var instance; // Stores a reference to the Singleton
+ var ssGauge; // Stores a reference to the SS Gauge
+ var cache = {}; // Stores various config values and parameters
+
+ function init() {
+ var params = $.extend(true, {}, commonParams);
+
+ // define pressure/barometer gauge start values
+ cache.sections = [];
+ cache.areas = [];
+ cache.minValue = gaugeGlobals.baroScaleDefMinhPa;
+ cache.maxValue = gaugeGlobals.baroScaleDefMaxhPa;
+ cache.value = cache.minValue + 0.0001;
+ cache.title = strings.baro_title;
+ cache.lcdDecimals = 1;
+ cache.scaleDecimals = 0;
+ cache.labelNumberFormat = gaugeGlobals.labelFormat;
+
+ // create pressure/barometric radial gauge
+ if ($('#canvas_baro').length) {
+ params.size = Math.ceil($('#canvas_baro').width() * config.gaugeScaling);
+ params.section = cache.sections;
+ params.area = cache.areas;
+ params.minValue = cache.minValue;
+ params.maxValue = cache.maxValue;
+ params.niceScale = false;
+ params.thresholdVisible = false;
+ params.titleString = cache.title;
+ params.unitString = data.pressunit;
+ params.lcdDecimals = cache.lcdDecimals;
+ params.trendVisible = gaugeGlobals.pressureTrendVisible;
+ params.labelNumberFormat = cache.labelNumberFormat;
+ params.fractionalScaleDecimals = cache.scaleDecimals;
+
+ ssGauge = new steelseries.Radial('canvas_baro', params);
+ ssGauge.setValue(cache.value);
+
+ // over-ride CSS applied size?
+ if (config.gaugeScaling !== 1) {
+ $('#canvas_baro').css({ width: params.size + 'px', height: params.size + 'px' });
+ }
+
+ // add a shadow to the gauge
+ if (config.showGaugeShadow) {
+ $('#canvas_baro').css(gaugeShadow(params.size));
+ }
+
+ // subscribe to data updates
+ $.subscribe('gauges.dataUpdated', update);
+ $.subscribe('gauges.graphUpdate', updateGraph);
+ } else {
+ // cannot draw gauge, return null
+ return null;
+ }
+
+ function update() {
+ var tip, t1, dps;
+
+ cache.recLow = +extractDecimal(data.pressL);
+ cache.recHigh = +extractDecimal(data.pressH);
+ cache.todayLow = +extractDecimal(data.pressTL);
+ cache.todayHigh = +extractDecimal(data.pressTH);
+ cache.value = +extractDecimal(data.press);
+ // Convert the WD change over 3 hours to an hourly rate
+ cache.trendVal = +extractDecimal(data.presstrendval) / (config.weatherProgram === 2 ? 3 : 1);
+
+ if (data.pressunit === 'hPa' || data.pressunit === 'mb') {
+ // default min range 990-1030 - steps of 10 hPa
+ cache.minValue = Math.min(nextLowest(cache.recLow - 2, 10), gaugeGlobals.baroScaleDefMinhPa);
+ cache.maxValue = Math.max(nextHighest(cache.recHigh + 2, 10), gaugeGlobals.baroScaleDefMaxhPa);
+ dps = 1; // 1 decimal place
+ } else if (data.pressunit === 'kPa') {
+ // default min range 99-105 - steps of 1 kPa
+ cache.minValue = Math.min(nextLowest(cache.recLow - 0.2, 1), gaugeGlobals.baroScaleDefMinkPa);
+ cache.maxValue = Math.max(nextHighest(cache.recHigh + 0.2, 1), gaugeGlobals.baroScaleDefMaxkPa);
+ dps = 2;
+ } else {
+ // inHg: default min range 29.5-30.5 - steps of 0.5 inHg
+ cache.minValue = Math.min(nextLowest(cache.recLow - 0.1, 0.5), gaugeGlobals.baroScaleDefMininHg);
+ cache.maxValue = Math.max(nextHighest(cache.recHigh + 0.1, 0.5), gaugeGlobals.baroScaleDefMaxinHg);
+ dps = 3;
+ }
+ cache.trendValRnd = cache.trendVal.toFixed(dps);
+ cache.todayLowRnd = cache.todayLow.toFixed(dps);
+ cache.todayHighRnd = cache.todayHigh.toFixed(dps);
+
+ if (cache.minValue !== ssGauge.getMinValue() || cache.maxValue !== ssGauge.getMaxValue()) {
+ ssGauge.setMinValue(cache.minValue);
+ ssGauge.setMaxValue(cache.maxValue);
+ ssGauge.setValue(cache.minValue);
+ }
+ if (cache.recHigh === cache.todayHigh && cache.recLow === cache.todayLow) {
+ // VWS does not provide record hi/lo values
+ cache.sections = [];
+ cache.areas = [steelseries.Section(cache.todayLow, cache.todayHigh, gaugeGlobals.minMaxArea)];
+ } else {
+ cache.sections = [
+ steelseries.Section(cache.minValue, cache.recLow, 'rgba(255,0,0,0.5)'),
+ steelseries.Section(cache.recHigh, cache.maxValue, 'rgba(255,0,0,0.5)')
+ ];
+ cache.areas = [
+ steelseries.Section(cache.minValue, cache.recLow, 'rgba(255,0,0,0.5)'),
+ steelseries.Section(cache.recHigh, cache.maxValue, 'rgba(255,0,0,0.5)'),
+ steelseries.Section(cache.todayLow, cache.todayHigh, gaugeGlobals.minMaxArea)
+ ];
+ }
+
+ if (gaugeGlobals.pressureTrendVisible) {
+ // Use the baroTrend rather than simple arithmetic test - steady is more/less than zero!
+ t1 = baroTrend(cache.trendVal, data.pressunit, false);
+ if (t1 === -9999) {
+ // trend value isn't currently available
+ cache.trend = steelseries.TrendState.OFF;
+ } else if (t1 > 0) {
+ cache.trend = steelseries.TrendState.UP;
+ } else if (t1 < 0) {
+ cache.trend = steelseries.TrendState.DOWN;
+ } else {
+ cache.trend = steelseries.TrendState.STEADY;
+ }
+ ssGauge.setTrend(cache.trend);
+ }
+
+ ssGauge.setArea(cache.areas);
+ ssGauge.setSection(cache.sections);
+ ssGauge.setValueAnimated(cache.value);
+
+ if (ddimgtooltip.showTips) {
+ // update tooltip
+ tip = strings.baro_info + ':' +
+ '
' +
+ '- ' + strings.minimum_info + ': ' + cache.todayLowRnd + ' ' + data.pressunit + ' ' + strings.at + ' ' + data.TpressTL +
+ ' | ' + strings.maximum_info + ': ' + cache.todayHighRnd + ' ' + data.pressunit + ' ' + strings.at + ' ' + data.TpressTH;
+ if (cache.trendVal !== -9999) {
+ tip += '
' +
+ '- ' + strings.baro_trend_info + ': ' + baroTrend(cache.trendVal, data.pressunit, true) + ' ' +
+ (cache.trendValRnd > 0 ? '+' : '') + cache.trendValRnd + ' ' + data.pressunit + '/h';
+ }
+ $('#imgtip5_txt').html(tip);
+ }
+ } // End of update()
+
+ function updateGraph(evnt, cacheDefeat) {
+ if (config.tipImgs[5] !== null) {
+ $('#imgtip5_img').attr('src', config.imgPathURL + config.tipImgs[5] + cacheDefeat);
+ }
+ }
+
+ return {
+ data: cache,
+ update: update,
+ gauge: ssGauge
+ };
+ } // End of init()
+
+ return {
+ // Get the Singleton instance if one exists
+ // or create one if it doesn't
+ getInstance: function () {
+ if (!instance) {
+ instance = init();
+ }
+ return instance;
+ }
+ };
+ })(),
+
+ //
+ // Singleton for the Wind Speed Gauge
+ //
+ singleWind = (function () {
+ var instance; // Stores a reference to the Singleton
+ var ssGauge; // Stores a reference to the SS Gauge
+ var cache = {}; // Stores various config values and parameters
+
+ function init() {
+ var params = $.extend(true, {}, commonParams);
+
+ // define wind gauge start values
+ cache.maxValue = gaugeGlobals.windScaleDefMaxKph;
+ cache.areas = [];
+ cache.maxMeasured = 0;
+ cache.value = 0.0001;
+ cache.title = strings.wind_title;
+
+ // create wind speed radial gauge
+ if ($('#canvas_wind').length) {
+ params.size = Math.ceil($('#canvas_wind').width() * config.gaugeScaling);
+ params.area = cache.areas;
+ params.maxValue = cache.maxValue;
+ params.niceScale = false;
+ params.thresholdVisible = false;
+ params.maxMeasuredValueVisible = true;
+ params.titleString = cache.title;
+ params.unitString = data.windunit;
+
+ ssGauge = new steelseries.Radial('canvas_wind', params);
+ ssGauge.setMaxMeasuredValue(cache.maxMeasured);
+ ssGauge.setValue(cache.value);
+
+ // over-ride CSS applied size?
+ if (config.gaugeScaling !== 1) {
+ $('#canvas_wind').css({ width: params.size + 'px', height: params.size + 'px' });
+ }
+
+ // add a shadow to the gauge
+ if (config.showGaugeShadow) {
+ $('#canvas_wind').css(gaugeShadow(params.size));
+ }
+
+ // subscribe to data updates
+ $.subscribe('gauges.dataUpdated', update);
+ $.subscribe('gauges.graphUpdate', updateGraph);
+ } else {
+ // cannot draw gauge, return null
+ return null;
+ }
+
+ function update() {
+ var tip;
+
+ cache.value = extractDecimal(data.wlatest);
+ cache.average = extractDecimal(data.wspeed);
+ cache.gust = extractDecimal(data.wgust);
+ cache.maxGustToday = extractDecimal(data.wgustTM);
+ cache.maxAvgToday = extractDecimal(data.windTM);
+
+ switch (data.windunit) {
+ case 'mph':
+ case 'kts':
+ cache.maxValue = Math.max(nextHighest(cache.maxGustToday, 10), gaugeGlobals.windScaleDefMaxMph);
+ break;
+ case 'm/s':
+ cache.maxValue = Math.max(nextHighest(cache.maxGustToday, 5), gaugeGlobals.windScaleDefMaxMs);
+ break;
+ default:
+ cache.maxValue = Math.max(nextHighest(cache.maxGustToday, 20), gaugeGlobals.windScaleDefMaxKmh);
+ }
+ cache.areas = [
+ steelseries.Section(0, +cache.average, gaugeGlobals.windAvgArea),
+ steelseries.Section(+cache.average, +cache.gust, gaugeGlobals.minMaxArea)
+ ];
+ if (cache.maxValue !== ssGauge.getMaxValue()) {
+ ssGauge.setValue(0);
+ ssGauge.setMaxValue(cache.maxValue);
+ }
+
+ ssGauge.setArea(cache.areas);
+ ssGauge.setMaxMeasuredValue(cache.maxGustToday);
+ ssGauge.setValueAnimated(cache.value);
+
+ if (ddimgtooltip.showTips) {
+ // update tooltip
+ tip = strings.tenminavgwind_info + ': ' + cache.average + ' ' + data.windunit + ' | ' +
+ strings.maxavgwind_info + ': ' + cache.maxAvgToday + ' ' + data.windunit + '
' +
+ strings.tenmingust_info + ': ' + cache.gust + ' ' + data.windunit + ' | ' +
+ strings.maxgust_info + ': ' + cache.maxGustToday + ' ' + data.windunit + ' ' +
+ strings.at + ' ' + data.TwgustTM + ' ' + strings.bearing_info + ': ' + data.bearingTM +
+ (isNaN(parseFloat(data.bearingTM)) ? '' : '° (' + getord(+data.bearingTM) + ')');
+ $('#imgtip6_txt').html(tip);
+ }
+ } // End of update()
+
+ function updateGraph(evnt, cacheDefeat) {
+ if (config.tipImgs[6] !== null) {
+ $('#imgtip6_img').attr('src', config.imgPathURL + config.tipImgs[6] + cacheDefeat);
+ }
+ }
+
+ return {
+ data: cache,
+ update: update,
+ gauge: ssGauge
+ };
+ } // End of init()
+
+ return {
+ // Get the Singleton instance if one exists
+ // or create one if it doesn't
+ getInstance: function () {
+ if (!instance) {
+ instance = init();
+ }
+ return instance;
+ }
+ };
+ })(), // End of singleWind()
+
+ //
+ // Singleton for the Wind Direction Gauge
+ //
+ singleDir = (function () {
+ var instance; // Stores a reference to the Singleton
+ var ssGauge; // Stores a reference to the SS Gauge
+ var cache = {}; // Stores various config values and parameters
+
+ function init() {
+ var params = $.extend(true, {}, commonParams);
+
+ // define wind direction gauge start values
+ cache.valueLatest = 0;
+ cache.valueAverage = 0;
+ cache.titles = [strings.latest_web, strings.tenminavg_web];
+
+ // create wind direction/compass radial gauge
+ if ($('#canvas_dir').length) {
+ params.size = Math.ceil($('#canvas_dir').width() * config.gaugeScaling);
+ params.pointerTypeLatest = gaugeGlobals.pointer; // default TYPE8,
+ params.pointerTypeAverage = gaugeGlobals.dirAvgPointer; // default TYPE8
+ params.pointerColorAverage = gaugeGlobals.dirAvgPointerColour;
+ params.degreeScale = true; // Show degree scale rather than ordinal directions
+ params.pointSymbols = strings.compass;
+ params.roseVisible = false;
+ params.lcdTitleStrings = cache.titles;
+ params.useColorLabels = false;
+
+ ssGauge = new steelseries.WindDirection('canvas_dir', params);
+ ssGauge.setValueAverage(+cache.valueAverage);
+ ssGauge.setValueLatest(+cache.valueLatest);
+
+ // over-ride CSS applied size?
+ if (config.gaugeScaling !== 1) {
+ $('#canvas_dir').css({ width: params.size + 'px', height: params.size + 'px' });
+ }
+
+ // add a shadow to the gauge
+ if (config.showGaugeShadow) {
+ $('#canvas_dir').css(gaugeShadow(params.size));
+ }
+
+ // subscribe to data updates
+ $.subscribe('gauges.dataUpdated', update);
+ $.subscribe('gauges.graphUpdate', updateGraph);
+ } else {
+ // cannot draw gauge, return null
+ return null;
+ }
+
+ function update() {
+ var windSpd, windGst, range, tip, i,
+ rosePoints = 0,
+ roseMax = 0,
+ roseSectionAngle = 0,
+ roseAreas = [];
+
+ cache.valueLatest = extractInteger(data.bearing);
+ cache.valueAverage = extractInteger(data.avgbearing);
+ cache.bearingFrom = extractInteger(data.BearingRangeFrom10);
+ cache.bearingTo = extractInteger(data.BearingRangeTo10);
+
+ ssGauge.setValueAnimatedAverage(+cache.valueAverage);
+ if (cache.valueAverage === 0) {
+ cache.valueLatest = 0;
+ }
+ ssGauge.setValueAnimatedLatest(+cache.valueLatest);
+
+ if (config.showWindVariation) {
+ windSpd = +extractDecimal(data.wspeed);
+ windGst = +extractDecimal(data.wgust);
+ switch (data.windunit.toLowerCase()) {
+ case 'mph':
+ cache.avgKnots = 0.868976242 * windSpd;
+ cache.gstKnots = 0.868976242 * windGst;
+ break;
+ case 'kts':
+ cache.avgKnots = windSpd;
+ cache.gstKnots = windGst;
+ break;
+ case 'm/s':
+ cache.avgKnots = 1.94384449 * windSpd;
+ cache.gstKnots = 1.94384449 * windGst;
+ break;
+ case 'km/h':
+ cache.avgKnots = 0.539956803 * windSpd;
+ cache.gstKnots = 0.539956803 * windGst;
+ break;
+ // no default
+ }
+ cache.avgKnots = Math.round(cache.avgKnots);
+ cache.gstKnots = Math.round(cache.gstKnots);
+ if (config.showWindMetar) {
+ ssGauge.VRB = ' - METAR: ' + ('0' + data.avgbearing).slice(-3) + ('0' + cache.avgKnots).slice(-2) +
+ 'G' + ('0' + cache.gstKnots).slice(-2) + 'KT ';
+ } else {
+ ssGauge.VRB = '';
+ }
+ if (windSpd > 0) {
+ // If variation less than 60 degrees, then METAR = Steady
+ // Unless range = 0 and from/to direction = avg + 180
+ range = (+cache.bearingTo < +cache.bearingFrom ? 360 + (+cache.bearingTo) : +cache.bearingTo) - (+cache.bearingFrom);
+
+ if (cache.avgKnots < 3) { // Europe uses 3kts, USA 6kts as the threshold
+ if (config.showRoseOnDirGauge) {
+ ssGauge.setSection([steelseries.Section(cache.bearingFrom, cache.bearingTo, gaugeGlobals.windVariationSector)]);
+ ssGauge.setSection([]);
+ } else {
+ ssGauge.setSection([steelseries.Section(cache.bearingFrom, cache.bearingTo, gaugeGlobals.minMaxArea)]);
+ ssGauge.setArea([]);
+ }
+ } else if (config.showRoseOnDirGauge) {
+ ssGauge.setSection([steelseries.Section(cache.bearingFrom, cache.bearingTo, gaugeGlobals.windVariationSector)]);
+ } else {
+ ssGauge.setSection([]);
+ ssGauge.setArea([steelseries.Section(cache.bearingFrom, cache.bearingTo, gaugeGlobals.minMaxArea)]);
+ }
+ if (config.showWindMetar) {
+ if ((range < 60 && range > 0) || range === 0 && cache.bearingFrom === cache.valueAverage) {
+ ssGauge.VRB += ' STDY';
+ } else if (cache.avgKnots < 3) { // Europe uses 3kts, USA 6kts as the threshold
+ ssGauge.VRB += ' VRB';
+ } else {
+ ssGauge.VRB += ' ' + cache.bearingFrom + 'V' + cache.bearingTo;
+ }
+ }
+ } else {
+ // Zero wind speed, calm
+ if (config.showWindMetar) {
+ ssGauge.VRB = ' - METAR: 00000KT';
+ }
+ ssGauge.setSection([]);
+ if (!config.showRoseOnDirGauge) {
+ ssGauge.setArea([]);
+ }
+ }
+ } else {
+ ssGauge.VRB = '';
+ }
+
+ // optional rose data on direction gauge
+ if (config.showRoseOnDirGauge && data.WindRoseData) {
+ // Process rose data
+ rosePoints = data.WindRoseData.length;
+ roseSectionAngle = 360 / rosePoints;
+ // Find total for all directions
+ for (i = 0; i < rosePoints; i++) {
+ roseMax = Math.max(roseMax, data.WindRoseData[i]);
+ }
+ // Check we actually have some data, bad things happen if roseMax=0!
+ if (roseMax > 0) {
+ // Find relative value for each point, and create a gauge area for it
+ for (i = 0; i < rosePoints; i++) {
+ roseAreas[i] = steelseries.Section(
+ i * roseSectionAngle - roseSectionAngle / 2,
+ (i + 1) * roseSectionAngle - roseSectionAngle / 2,
+ 'rgba(' + gradient('2020D0', 'D04040', data.WindRoseData[i] / roseMax) + ',' +
+ (data.WindRoseData[i] / roseMax).toFixed(2) + ')'
+ );
+ }
+ }
+ ssGauge.setArea(roseAreas);
+ }
+
+ if (ddimgtooltip.showTips) {
+ // update tooltip
+ tip = strings.latest_title + ' ' + strings.bearing_info + ': ' + cache.valueLatest + '° (' + getord(+cache.valueLatest) + ')' +
+ ssGauge.VRB + '
' + strings.tenminavg_web + ' ' + strings.bearing_info + ': ' + cache.valueAverage + '° (' +
+ getord(+cache.valueAverage) + '), ' + strings.dominant_bearing + ': ' + data.domwinddir;
+ if (!config.showRoseGauge) {
+ // Wind run is shown on the wind rose if it is available
+ tip += '
' + strings.windruntoday + ': ' + data.windrun + ' ' + displayUnits.windrun;
+ }
+ $('#imgtip7_txt').html(tip);
+ }
+ } // End of update()
+
+ function updateGraph(evnt, cacheDefeat) {
+ if (config.tipImgs[7] !== null) {
+ $('#imgtip7_img').attr('src', config.imgPathURL + config.tipImgs[7] + cacheDefeat);
+ }
+ }
+
+ return {
+ data: cache,
+ update: update,
+ gauge: ssGauge
+ };
+ } // End of init()
+
+ return {
+ // Get the Singleton instance if one exists
+ // or create one if it doesn't
+ getInstance: function () {
+ if (!instance) {
+ instance = init();
+ }
+ return instance;
+ }
+ };
+ })(),
+
+ //
+ // Singleton for the Wind Rose Gauge
+ //
+ singleRose = (function () {
+ var instance; // Stores a reference to the Singleton
+ var ssGauge; // Stores a reference to the SS Gauge
+
+ var buffers = {}; // Stores references to the various canvas buffers
+ var cache = {}; // various parameters to store for the life time of gauge
+ var ctxRoseCanvas; // 2D context for the plotted gauge
+
+ cache.firstRun = true;
+ cache.odoDigits = 5; // Total number of odometer digits including the decimal
+
+ function init() {
+ var div, roseCanvas;
+ // Get the context of the gauge canvas on the HTML page
+ if ($('#canvas_rose').length) {
+ cache.gaugeSize = Math.ceil($('#canvas_rose').width() * config.gaugeScaling);
+ cache.gaugeSize2 = cache.gaugeSize / 2;
+ cache.showOdo = config.showRoseGaugeOdo || false;
+
+ cache.compassStrings = strings.compass;
+ cache.titleString = strings.windrose;
+ cache.gaugeOdoTitle = strings.km;
+
+ // Create a hidden div to host the Rose plot
+ div = document.createElement('div');
+ div.style.display = 'none';
+ document.body.appendChild(div);
+
+ // Calcuate the size of the gauge background and so the size of rose plot required
+ cache.plotSize = Math.floor(cache.gaugeSize * 0.68);
+ cache.plotSize2 = cache.plotSize / 2;
+
+ // rose plot canvas buffer
+ buffers.plot = document.createElement('canvas');
+ buffers.plot.width = cache.plotSize;
+ buffers.plot.height = cache.plotSize;
+ buffers.plot.id = 'rosePlot';
+ buffers.ctxPlot = buffers.plot.getContext('2d');
+ div.appendChild(buffers.plot);
+
+ // Create a steelseries gauge frame
+ buffers.frame = document.createElement('canvas');
+ buffers.frame.width = cache.gaugeSize;
+ buffers.frame.height = cache.gaugeSize;
+ buffers.ctxFrame = buffers.frame.getContext('2d');
+ steelseries.drawFrame(
+ buffers.ctxFrame,
+ gaugeGlobals.frameDesign,
+ cache.gaugeSize2,
+ cache.gaugeSize2,
+ cache.gaugeSize,
+ cache.gaugeSize
+ );
+
+ // Create a steelseries gauge background
+ buffers.background = document.createElement('canvas');
+ buffers.background.width = cache.gaugeSize;
+ buffers.background.height = cache.gaugeSize;
+ buffers.ctxBackground = buffers.background.getContext('2d');
+ steelseries.drawBackground(
+ buffers.ctxBackground,
+ gaugeGlobals.background,
+ cache.gaugeSize2,
+ cache.gaugeSize2,
+ cache.gaugeSize,
+ cache.gaugeSize
+ );
+
+ // Optional - add a background image
+ /*
+ if (g_imgSmall !== null) {
+ var drawSize = g_size * 0.831775;
+ var x = (g_size - drawSize) / 2;
+ buffers.ctxBackground.drawImage(g_imgSmall, x, x, cache.gaugeSize, cache.gaugeSize);
+ }
+ */
+ // Add the compass points
+ drawCompassPoints(buffers.ctxBackground, cache.gaugeSize);
+
+ // Create a steelseries gauge foreground
+ buffers.foreground = document.createElement('canvas');
+ buffers.foreground.width = cache.gaugeSize;
+ buffers.foreground.height = cache.gaugeSize;
+ buffers.ctxForeground = buffers.foreground.getContext('2d');
+ steelseries.drawForeground(
+ buffers.ctxForeground,
+ gaugeGlobals.foreground,
+ cache.gaugeSize,
+ cache.gaugeSize,
+ false
+ );
+
+ roseCanvas = document.getElementById('canvas_rose');
+ ctxRoseCanvas = roseCanvas.getContext('2d');
+ // over-ride CSS applied size?
+ if (config.gaugeScaling !== 1) {
+ $('#canvas_rose').css({ width: cache.gaugeSize + 'px', height: cache.gaugeSize + 'px' });
+ }
+ // resize canvas on main page
+ roseCanvas.width = cache.gaugeSize;
+ roseCanvas.height = cache.gaugeSize;
+ // add a shadow to the gauge
+ if (config.showGaugeShadow) {
+ $('#canvas_rose').css(gaugeShadow(cache.gaugeSize));
+ }
+
+ // Render an empty gauge, looks better than just the shadow background and odometer ;)
+ // Paint the gauge frame
+ ctxRoseCanvas.drawImage(buffers.frame, 0, 0);
+
+ // Paint the gauge background
+ ctxRoseCanvas.drawImage(buffers.background, 0, 0);
+
+ // Paint the gauge foreground
+ ctxRoseCanvas.drawImage(buffers.foreground, 0, 0);
+
+ // Create an odometer
+ if (cache.showOdo) {
+ cache.odoHeight = Math.ceil(cache.gaugeSize * 0.08); // Sets the size of the odometer
+ cache.odoWidth = Math.ceil(Math.floor(cache.odoHeight * 0.68) * cache.odoDigits); // 'Magic' number, do not alter
+ // Create a new canvas for the oodometer
+ buffers.Odo = document.createElement('canvas');
+ $(buffers.Odo).attr({
+ id: 'canvas_odo',
+ width: cache.odoWidth,
+ height: cache.odoHeight
+ });
+ // Position it
+ $(buffers.Odo).attr('class', 'odo');
+ // Insert it into the DOM before the Rose gauge
+ $(buffers.Odo).insertBefore('#canvas_rose');
+ // Create the odometer
+ ssGauge = new steelseries.Odometer('canvas_odo', {
+ height: cache.odoHeight,
+ digits: cache.odoDigits - 1,
+ decimals: 1
+ });
+ }
+ // subscribe to data updates
+ $.subscribe('gauges.dataUpdated', update);
+ $.subscribe('gauges.graphUpdate', updateGraph);
+ } else {
+ // cannot draw gauge, return null
+ return null;
+ }
+
+ cache.firstRun = false;
+
+ function update() {
+ var rose, offset;
+
+ if (ctxRoseCanvas && !cache.firstRun) {
+ // Clear the gauge
+ ctxRoseCanvas.clearRect(0, 0, cache.gaugeSize, cache.gaugeSize);
+
+ // Clear the existing rose plot
+ buffers.ctxPlot.clearRect(0, 0, cache.plotSize, cache.plotSize);
+
+ // Create a new rose plot
+ rose = new RGraph.Rose('rosePlot', data.WindRoseData);
+ rose.Set('chart.strokestyle', 'black');
+ rose.Set('chart.background.axes.color', 'gray');
+ rose.Set('chart.colors.alpha', 0.5);
+ rose.Set('chart.colors', ['Gradient(#408040:red:#7070A0)']);
+ rose.Set('chart.margin', Math.ceil(40 / data.WindRoseData.length));
+
+ rose.Set('chart.title', cache.titleString);
+ rose.Set('chart.title.size', Math.ceil(0.05 * cache.plotSize));
+ rose.Set('chart.title.bold', false);
+ rose.Set('chart.title.color', gaugeGlobals.background.labelColor.getRgbColor());
+ rose.Set('chart.gutter.top', 0.2 * cache.plotSize);
+ rose.Set('chart.gutter.bottom', 0.2 * cache.plotSize);
+
+ rose.Set('chart.tooltips.effect', 'snap');
+ rose.Set('chart.labels.axes', '');
+ rose.Set('chart.background.circles', true);
+ rose.Set('chart.background.grid.spokes', 16);
+ rose.Set('chart.radius', cache.plotSize2);
+ rose.Draw();
+
+ // Add title to windrun odometer to the plot
+ if (cache.showOdo) {
+ drawOdoTitle(buffers.ctxPlot);
+ }
+
+ // Paint the gauge frame
+ ctxRoseCanvas.drawImage(buffers.frame, 0, 0);
+
+ // Paint the gauge background
+ ctxRoseCanvas.drawImage(buffers.background, 0, 0);
+
+ // Paint the rose plot
+ offset = Math.floor(cache.gaugeSize2 - cache.plotSize2);
+ ctxRoseCanvas.drawImage(buffers.plot, offset, offset);
+
+ // Paint the gauge foreground
+ ctxRoseCanvas.drawImage(buffers.foreground, 0, 0);
+
+ // update the odometer
+ if (cache.showOdo) {
+ ssGauge.setValueAnimated(extractDecimal(data.windrun));
+ }
+
+ // update tooltip
+ if (ddimgtooltip.showTips) {
+ $('#imgtip10_txt').html(
+ strings.dominant_bearing + ': ' + data.domwinddir + '
' +
+ strings.windruntoday + ': ' + data.windrun + ' ' + displayUnits.windrun
+ );
+ }
+ }
+ } // End of update()
+
+ function updateGraph(evnt, cacheDefeat) {
+ if (config.tipImgs[10] !== null) {
+ $('#imgtip10_img').attr('src', config.imgPathURL + config.tipImgs[10] + cacheDefeat);
+ }
+ }
+
+ // Helper function to put the compass points on the background
+ function drawCompassPoints(ctx, size) {
+ ctx.save();
+ // set the font
+ ctx.font = 0.08 * size + 'px serif';
+ ctx.strokeStyle = gaugeGlobals.background.labelColor.getRgbaColor();
+ ctx.fillStyle = gaugeGlobals.background.labelColor.getRgbColor();
+ ctx.textAlign = 'center';
+ ctx.textBaseline = 'middle';
+
+ // Draw the compass points
+ for (var i = 0; i < 4; i++) {
+ ctx.translate(size / 2, size * 0.125);
+ ctx.fillText(cache.compassStrings[i * 2], 0, 0, size);
+ ctx.translate(-size / 2, -size * 0.125);
+ // Move to center
+ ctx.translate(size / 2, size / 2);
+ ctx.rotate(Math.PI / 2);
+ ctx.translate(-size / 2, -size / 2);
+ }
+ ctx.restore();
+ }
+
+ function drawOdoTitle(ctx) {
+ ctx.save();
+ ctx.textAlign = 'center';
+ ctx.textBaseline = 'middle';
+ ctx.font = 0.05 * cache.gaugeSize + 'px Arial,Verdana,sans-serif';
+ ctx.strokeStyle = gaugeGlobals.background.labelColor.getRgbaColor();
+ ctx.fillStyle = gaugeGlobals.background.labelColor.getRgbaColor();
+ ctx.fillText(cache.gaugeOdoTitle, cache.plotSize2, cache.plotSize * 0.75, cache.plotSize * 0.5);
+ ctx.restore();
+ }
+
+ function setTitle(newTitle) {
+ cache.titleString = newTitle;
+ }
+
+ function setOdoTitle(newTitle) {
+ cache.gaugeOdoTitle = newTitle;
+ }
+
+ function setCompassStrings(newArray) {
+ cache.compassStrings = newArray;
+ if (!cache.firstRun) {
+ // Redraw the background
+ steelseries.drawBackground(
+ buffers.ctxBackground,
+ gaugeGlobals.background,
+ cache.gaugeSize2,
+ cache.gaugeSize2,
+ cache.gaugeSize,
+ cache.gaugeSize
+ );
+ // Add the compass points
+ drawCompassPoints(buffers.ctxBackground, cache.gaugeSize);
+ }
+ }
+
+ return {
+ update: update,
+ gauge: ssGauge,
+ drawCompassPoints: drawCompassPoints,
+ setTitle: setTitle,
+ setCompassStrings: setCompassStrings,
+ setOdoTitle: setOdoTitle
+ };
+ } // End of init()
+
+ return {
+ // Get the Singleton instance if one exists
+ // or create one if it doesn't
+ getInstance: function () {
+ if (!instance) {
+ instance = init();
+ }
+ return instance;
+ }
+ };
+ })(),
+
+ //
+ // Singleton for the UV-Index Gauge
+ //
+ singleUV = (function () {
+ var instance; // Stores a reference to the Singleton
+ var ssGauge; // Stores a reference to the SS Gauge
+ var cache = {}; // Stores various config values and parameters
+
+ function init() {
+ var params = $.extend(true, {}, commonParams);
+
+ // define UV start values
+ cache.value = 0.0001;
+ cache.sections = [
+ steelseries.Section(0, 2.9, '#289500'),
+ steelseries.Section(2.9, 5.8, '#f7e400'),
+ steelseries.Section(5.8, 7.8, '#f85900'),
+ steelseries.Section(7.8, 10.9, '#d8001d'),
+ steelseries.Section(10.9, 20, '#6b49c8')
+ ];
+ // Define value gradient for UV
+ cache.gradient = new steelseries.gradientWrapper(0, 16,
+ [0, 0.1, 0.19, 0.31, 0.45, 0.625, 1],
+ [
+ new steelseries.rgbaColor(0, 200, 0, 1),
+ new steelseries.rgbaColor(0, 200, 0, 1),
+ new steelseries.rgbaColor(255, 255, 0, 1),
+ new steelseries.rgbaColor(248, 89, 0, 1),
+ new steelseries.rgbaColor(255, 0, 0, 1),
+ new steelseries.rgbaColor(255, 0, 144, 1),
+ new steelseries.rgbaColor(153, 140, 255, 1)
+ ]
+ );
+ cache.useSections = false;
+ cache.useValueGradient = true;
+
+ // create UV bargraph gauge
+ if ($('#canvas_uv').length) {
+ params.size = Math.ceil($('#canvas_uv').width() * config.gaugeScaling);
+ params.gaugeType = steelseries.GaugeType.TYPE3;
+ params.maxValue = gaugeGlobals.uvScaleDefMax;
+ params.titleString = strings.uv_title;
+ params.niceScale = false;
+ params.section = cache.sections;
+ params.useSectionColors = cache.useSections;
+ params.valueGradient = cache.gradient;
+ params.useValueGradient = cache.useValueGradient;
+ params.lcdDecimals = gaugeGlobals.uvLcdDecimals;
+
+ ssGauge = new steelseries.RadialBargraph('canvas_uv', params);
+ ssGauge.setValue(cache.value);
+
+ // over-ride CSS applied size?
+ if (config.gaugeScaling !== 1) {
+ $('#canvas_uv').css({ width: params.size + 'px', height: params.size + 'px' });
+ }
+
+ // add a shadow to the gauge
+ if (config.showGaugeShadow) {
+ $('#canvas_uv').css(gaugeShadow(params.size));
+ }
+
+ // subscribe to data updates
+ $.subscribe('gauges.dataUpdated', update);
+ $.subscribe('gauges.graphUpdate', updateGraph);
+ } else {
+ // cannot draw gauge, return null
+ return null;
+ }
+
+ function update() {
+ var tip, indx;
+
+ cache.value = extractDecimal(data.UV);
+
+ if (+cache.value === 0) {
+ indx = 0;
+ } else if (cache.value < 2.5) {
+ indx = 1;
+ } else if (cache.value < 5.5) {
+ indx = 2;
+ } else if (cache.value < 7.5) {
+ indx = 3;
+ } else if (cache.value < 10.5) {
+ indx = 4;
+ } else {
+ indx = 5;
+ }
+
+ cache.maxValue = Math.max(nextHighest(cache.value, 2), gaugeGlobals.uvScaleDefMax);
+ if (cache.maxValue !== ssGauge.getMaxValue()) {
+ ssGauge.setValue(0);
+ ssGauge.setMaxValue(cache.maxValue);
+ }
+
+ cache.risk = strings.uv_levels[indx];
+ cache.headLine = strings.uv_headlines[indx];
+ cache.detail = strings.uv_details[indx];
+ ssGauge.setUnitString(cache.risk);
+ ssGauge.setValueAnimated(cache.value);
+
+ if (ddimgtooltip.showTips) {
+ // update tooltip
+ tip = '' + strings.uv_title + ': ' + cache.value + ' - ' + strings.solar_maxToday + ': ' + data.UVTH + '
';
+ tip += '' + cache.headLine + '
';
+ tip += cache.detail;
+ $('#imgtip8_txt').html(tip);
+ }
+ } // End of update()
+
+ function updateGraph(evnt, cacheDefeat) {
+ if (config.tipImgs[8] !== null) {
+ $('#imgtip8_img').attr('src', config.imgPathURL + config.tipImgs[8] + cacheDefeat);
+ }
+ }
+
+ return {
+ update: update,
+ gauge: ssGauge
+ };
+ } // End of init()
+
+ return {
+ // Get the Singleton instance if one exists
+ // or create one if it doesn't
+ getInstance: function () {
+ if (!instance) {
+ instance = init();
+ }
+ return instance;
+ }
+ };
+ })(),
+
+ //
+ // Singleton for the Solar Irradiation Gauge
+ //
+ singleSolar = (function () {
+ var instance; // Stores a reference to the Singleton
+ var ssGauge; // Stores a reference to the SS Gauge
+ var cache = {}; // Stores various config values and parameters
+
+ function init() {
+ var params = $.extend(true, {}, commonParams);
+
+ // define Solar start values
+ cache.value = 0.0001;
+ cache.sections = [
+ steelseries.Section(0, 600, 'rgba(40,149,0,0.3)'),
+ steelseries.Section(600, 800, 'rgba(248,89,0,0.3)'),
+ steelseries.Section(800, 1000, 'rgba(216,0,29,0.3)'),
+ steelseries.Section(1000, 1800, 'rgba(107,73,200,0.3)')
+ ];
+
+ // create Solar gauge
+ if ($('#canvas_solar').length) {
+ params.size = Math.ceil($('#canvas_solar').width() * config.gaugeScaling);
+ params.section = cache.sections;
+ params.maxValue = gaugeGlobals.solarGaugeScaleMax;
+ params.titleString = strings.solar_title;
+ params.unitString = 'W/m\u00B2';
+ params.niceScale = false;
+ params.thresholdVisible = false;
+ params.lcdDecimals = 0;
+
+ if (config.showSunshineLed) {
+ params.userLedVisible = true;
+ params.userLedColor = steelseries.LedColor.YELLOW_LED;
+ }
+
+ ssGauge = new steelseries.Radial('canvas_solar', params);
+ ssGauge.setValue(cache.value);
+
+ // over-ride CSS applied size?
+ if (config.gaugeScaling !== 1) {
+ $('#canvas_solar').css({ width: params.size + 'px', height: params.size + 'px' });
+ }
+
+ // add a shadow to the gauge
+ if (config.showGaugeShadow) {
+ $('#canvas_solar').css(gaugeShadow(params.size));
+ }
+ // subscribe to data updates
+ $.subscribe('gauges.dataUpdated', update);
+ $.subscribe('gauges.graphUpdate', updateGraph);
+ } else {
+ // cannot draw gauge, return null
+ return null;
+ }
+
+ function update() {
+ var tip, percent;
+
+ cache.value = +extractInteger(data.SolarRad);
+ cache.maxToday = extractInteger(data.SolarTM);
+ cache.currMaxValue = +extractInteger(data.CurrentSolarMax);
+ percent = (+cache.currMaxValue === 0 ? '--' : Math.round(+cache.value / +cache.currMaxValue * 100));
+
+ // Need to rescale the gauge?
+ cache.maxValue = Math.max(cache.value, cache.currMaxValue, cache.maxToday, gaugeGlobals.solarGaugeScaleMax);
+ cache.maxValue = nextHighest(cache.maxValue, 100);
+ if (cache.maxValue !== ssGauge.getMaxValue()) {
+ ssGauge.setValue(0);
+ ssGauge.setMaxValue(cache.maxValue);
+ }
+
+ // Set a section (15% of maxScale wide) to show current theoretical max value
+ if (data.CurrentSolarMax !== 'N/A') {
+ ssGauge.setArea([
+ // Sunshine threshold
+ steelseries.Section(
+ Math.max(cache.currMaxValue * gaugeGlobals.sunshineThresholdPct / 100, gaugeGlobals.sunshineThreshold),
+ cache.currMaxValue,
+ 'rgba(255,255,50,0.4)'
+ ),
+ // Over max threshold
+ steelseries.Section(
+ cache.currMaxValue,
+ Math.min(cache.currMaxValue + cache.maxValue * 0.15, cache.maxValue),
+ 'rgba(220,0,0,0.5)'
+ )
+ ]);
+ }
+
+ // Set the values
+ ssGauge.setMaxMeasuredValue(cache.maxToday);
+ ssGauge.setValueAnimated(cache.value);
+
+ if (config.showSunshineLed) {
+ ssGauge.setUserLedOnOff(
+ percent !== '--' &&
+ percent >= gaugeGlobals.sunshineThresholdPct &&
+ +cache.value >= gaugeGlobals.sunshineThreshold
+ );
+ }
+
+ if (ddimgtooltip.showTips) {
+ // update tooltip
+ tip = '' + strings.solar_title + ': ' + cache.value + ' W/m² - ' +
+ '' + percent + '% ' + strings.solar_ofMax + '
' +
+ strings.solar_currentMax + ': ' + cache.currMaxValue + ' W/m²';
+ if (typeof data.SolarTM !== 'undefined') {
+ tip += '
' + strings.solar_maxToday + ': ' + cache.maxToday + ' W/m²';
+ }
+ $('#imgtip9_txt').html(tip);
+ }
+ } // End of update()
+
+ function updateGraph(evnt, cacheDefeat) {
+ if (config.tipImgs[9] !== null) {
+ $('#imgtip9_img').attr('src', config.imgPathURL + config.tipImgs[9] + cacheDefeat);
+ }
+ }
+
+ return {
+ update: update,
+ gauge: ssGauge
+ };
+ } // End of init()
+
+ return {
+ // Get the Singleton instance if one exists
+ // or create one if it doesn't
+ getInstance: function () {
+ if (!instance) {
+ instance = init();
+ }
+ return instance;
+ }
+ };
+ })(),
+
+ //
+ // Singleton for the Cloudbase Gauge
+ //
+ singleCloudBase = (function () {
+ var instance; // Stores a reference to the Singleton
+ var ssGauge; // Stores a reference to the SS Gauge
+ var cache = {}; // Stores various config values and parameters
+
+ function init() {
+ var params = $.extend(true, {}, commonParams);
+
+ cache.sections = createCloudBaseSections(true);
+ cache.value = 0.0001;
+ cache.maxValue = gaugeGlobals.cloudScaleDefMaxm;
+
+ // create Cloud base radial gauge
+ if ($('#canvas_cloud').length) {
+ params.size = Math.ceil($('#canvas_cloud').width() * config.gaugeScaling);
+ params.section = cache.sections;
+ params.maxValue = cache.maxValue;
+ params.titleString = strings.cloudbase_title;
+ params.unitString = strings.metres;
+ params.thresholdVisible = false;
+ params.lcdDecimals = 0;
+
+ ssGauge = new steelseries.Radial('canvas_cloud', params);
+ ssGauge.setValue(cache.value);
+
+ // over-ride CSS applied size?
+ if (config.gaugeScaling !== 1) {
+ $('#canvas_cloud').css({ width: params.size + 'px', height: params.size + 'px' });
+ }
+
+ // add a shadow to the gauge
+ if (config.showGaugeShadow) {
+ $('#canvas_cloud').css(gaugeShadow(params.size));
+ }
+ // subscribe to data updates
+ $.subscribe('gauges.dataUpdated', update);
+ $.subscribe('gauges.graphUpdate', updateGraph);
+ } else {
+ // cannot draw gauge, return null
+ return null;
+ }
+
+ function update() {
+ cache.value = extractInteger(data.cloudbasevalue);
+
+ if (data.cloudbaseunit === 'm') {
+ // adjust metre gauge in jumps of 1000 metres, don't downscale during the session
+ cache.maxValue = Math.max(nextHighest(cache.value, 1000), gaugeGlobals.cloudScaleDefMaxm, cache.maxValue);
+ if (cache.value <= 1000 && config.roundCloudbaseVal) {
+ // and round the value to the nearest 10 m
+ cache.value = Math.round(cache.value / 10) * 10;
+ } else if (config.roundCloudbaseVal) {
+ // and round the value to the nearest 50 m
+ cache.value = Math.round(cache.value / 50) * 50;
+ }
+ } else {
+ // adjust feet gauge in jumps of 2000 ft, don't downscale during the session
+ cache.maxValue = Math.max(nextHighest(cache.value, 2000), gaugeGlobals.cloudScaleDefMaxft, cache.maxValue);
+ if (cache.value <= 2000 && config.roundCloudbaseVal) {
+ // and round the value to the nearest 50 ft
+ cache.value = Math.round(cache.value / 50) * 50;
+ } else if (config.roundCloudbaseVal) {
+ // and round the value to the nearest 100 ft
+ cache.value = Math.round(cache.value / 100) * 100;
+ }
+ }
+
+ if (cache.maxValue !== ssGauge.getMaxValue()) {
+ if (ssGauge.getMaxValue() > cache.maxValue) {
+ // Gauge currently showing more than our max (nice scale effct),
+ // so reset our max to match
+ cache.maxValue = ssGauge.getMaxValue();
+ } else {
+ // Gauge scale is too low, increase it.
+ // First set the pointer back to zero so we get a nice animation
+ ssGauge.setValue(0);
+ // and redraw the gauge with teh new scale
+ ssGauge.setMaxValue(cache.maxValue);
+ }
+ }
+ ssGauge.setValueAnimated(cache.value);
+
+ if (config.showPopupData) {
+ // static tooltip on cloud gauge
+ $('#imgtip11_txt').html('' + strings.cloudbase_popup_title + '
' + strings.cloudbase_popup_text);
+ }
+ } // End of update()
+
+ function updateGraph(evnt, cacheDefeat) {
+ if (config.tipImgs[11] !== null) {
+ $('#imgtip11_img').attr('src', config.imgPathURL + config.tipImgs[11] + cacheDefeat);
+ }
+ }
+
+ return {
+ data: cache,
+ update: update,
+ gauge: ssGauge
+ };
+ } // End of init()
+
+ return {
+ // Get the Singleton instance if one exists
+ // or create one if it doesn't
+ getInstance: function () {
+ if (!instance) {
+ instance = init();
+ }
+ return instance;
+ }
+ };
+ })(),
+
+ //
+ // getRealtime() fetches the realtimegauges JSON data from the server
+ //
+ getRealtime = function () {
+ var url = config.realTimeURL;
+ if ($.active > 0 && undefined != jqXHR) {
+ // kill any outstanding requests
+ jqXHR.abort();
+ }
+ if (config.longPoll) {
+ url += '?timestamp=' + timestamp;
+ }
+ jqXHR = $.ajax({
+ url: url,
+ cache: (config.longPoll),
+ dataType: 'json',
+ timeout: config.longPoll ? (Math.min(config.realtimeInterval, 20) + 21) * 1000 : 21000 // 21 second time-out by default
+ }).done(function (data) {
+ checkRtResp(data);
+ }).fail(function (xhr, status, err) {
+ checkRtError(xhr, status, err);
+ });
+ },
+
+ //
+ // checkRtResp() called by the Ajax fetch once data has been downloaded
+ //
+ checkRtResp = function (response) {
+ var delay;
+ statusTimer.reset(config.longPoll ? 1 : config.realtimeInterval);
+ if (config.longPoll && response.status !== 'OK') {
+ checkRtError(null, 'PHP Error', response.status);
+ } else {
+ if (processData(response)) {
+ delay = ajaxDelay;
+ } else {
+ delay = 5;
+ }
+ if (delay > 0) {
+ downloadTimer = setTimeout(getRealtime, delay * 1000);
+ } else {
+ getRealtime();
+ }
+ }
+ },
+
+ //
+ // checkRtError() called by the Ajax fetch if an error occurs during the fetching /data/realtimegauges.txt
+ //
+ checkRtError = function (xhr, status, error) {
+ if (xhr == null || xhr.statusText !== 'abort') {
+ // Clear any existing download timer
+ clearTimeout(downloadTimer);
+ // Set the status LED to off
+ ledIndicator.setLedOnOff(false);
+ ledIndicator.setTitle(strings.led_title_unknown);
+ statusScroller.setText(status + ': ' + error);
+ // wait 5 seconds, then try again...
+ downloadTimer = setTimeout(getRealtime, 5000);
+ }
+ },
+
+ //
+ // processData() massages the data returned in /data/realtimegauges.txt, and posts a gauges.dataUpdated event to update the page
+ //
+ processData = function (dataObj) {
+ var str, dt, tm, today, now, then, tmp, elapsedMins, retVal;
+ // copy the realtime fields into the global 'data' object
+ if (config.longPoll) {
+ timestamp = dataObj.timestamp;
+ data = dataObj.data;
+ } else {
+ // normal polling
+ data = dataObj;
+ }
+
+ // and check we have the expected version number
+ if (typeof data.ver !== 'undefined' && data.ver >= realtimeVer) {
+ // manpulate the last rain time into something more friendly
+ try {
+ str = data.LastRainTipISO.split(' ');
+ dt = str[0].replace(/\//g, '-').split('-'); // WD uses dd/mm/yyyy, we use a '-'
+ tm = str[1].split(':');
+ today = new Date();
+ today.setHours(0, 0, 0, 0);
+ if (typeof data.dateFormat === 'undefined') {
+ data.dateFormat = 'y/m/d';
+ } else {
+ // frig for WD bug which leaves a trailing % character from the tag
+ data.dateFormat = data.dateFormat.replace('%', '');
+ }
+ if (data.dateFormat === 'y/m/d') {
+ // ISO/Cumulus format
+ then = new Date(dt[0], dt[1] - 1, dt[2], tm[0], tm[1], 0, 0);
+ } else if (data.dateFormat === 'd/m/y') {
+ then = new Date(dt[2], dt[1] - 1, dt[0], tm[0], tm[1], 0, 0);
+ } else { // m/d/y
+ then = new Date(dt[2], dt[0] - 1, dt[1], tm[0], tm[1], 0, 0);
+ }
+ if (then.getTime() >= today.getTime()) {
+ data.LastRained = strings.LastRainedT_info + ' ' + str[1];
+ } else if (then.getTime() + 86400000 >= today.getTime()) {
+ data.LastRained = strings.LastRainedY_info + ' ' + str[1];
+ } else {
+ data.LastRained = then.getDate().toString() + ' ' + strings.months[then.getMonth()] + ' ' + strings.at + ' ' + str[1];
+ }
+ } catch (e) {
+ data.LastRained = data.LastRainTipISO;
+ }
+ if (data.tempunit.length > 1) {
+ // clean up temperature units - remove html encoded degree symbols
+ data.tempunit = data.tempunit.replace(/&\S*;/, '°'); // old Cumulus versions uses °, WeatherCat uses °
+ } else {
+ // using new realtimegaugesT.txt with Cumulus > 1.9.2
+ data.tempunit = '°' + data.tempunit;
+ }
+
+ // Check for station off-line
+ now = Date.now();
+ tmp = data.timeUTC.split(',');
+ sampleDate = Date.UTC(tmp[0], tmp[1] - 1, tmp[2], tmp[3], tmp[4], tmp[5]);
+ if (now - sampleDate > config.stationTimeout * 60 * 1000) {
+ elapsedMins = Math.floor((now - sampleDate) / (1000 * 60));
+ // the /data/realtimegauges.txt file isn't being updated
+ ledIndicator.setLedColor(steelseries.LedColor.RED_LED);
+ ledIndicator.setTitle(strings.led_title_offline);
+ ledIndicator.blink(true);
+ if (elapsedMins < 120) {
+ // up to 2 hours ago
+ tm = elapsedMins.toString() + ' ' + strings.StatusMinsAgo;
+ } else if (elapsedMins < 2 * 24 * 60) {
+ // up to 48 hours ago
+ tm = Math.floor(elapsedMins / 60).toString() + ' ' + strings.StatusHoursAgo;
+ } else {
+ // days ago!
+ tm = Math.floor(elapsedMins / (60 * 24)).toString() + ' ' + strings.StatusDaysAgo;
+ }
+ data.forecast = strings.led_title_offline + ' ' + strings.StatusLastUpdate + ' ' + tm;
+ } else if (+data.SensorContactLost === 1) {
+ // Fine Offset sensor status
+ ledIndicator.setLedColor(steelseries.LedColor.RED_LED);
+ ledIndicator.setTitle(strings.led_title_lost);
+ ledIndicator.blink(true);
+ data.forecast = strings.led_title_lost;
+ } else {
+ ledIndicator.setLedColor(steelseries.LedColor.GREEN_LED);
+ ledIndicator.setTitle(strings.led_title_ok + '. ' + strings.StatusLastUpdate + ': ' + data.date);
+ ledIndicator.blink(false);
+ ledIndicator.setLedOnOff(true);
+ }
+
+ // de-encode the forecast string if required (Cumulus support for extended characters)
+ data.forecast = $('').html(data.forecast).text();
+ data.forecast = data.forecast.trim();
+
+ data.pressunit = data.pressunit.trim(); // WView sends ' in', ' mb', or ' hPa'
+ if (data.pressunit === 'in') { // Cumulus and WView send 'in'
+ data.pressunit = 'inHg';
+ }
+
+ data.windunit = data.windunit.trim(); // WView sends ' kmh' etc
+ data.windunit = data.windunit.toLowerCase(); // WeatherCat sends "MPH"
+ if (data.windunit === 'knots') { // WeatherCat/weewx send "Knots", we use "kts"
+ data.windunit = 'kts';
+ }
+
+ if (data.windunit === 'kmh' || data.windunit === 'kph') { // WD wind unit omits '/', weewx sends 'kph'
+ data.windunit = 'km/h';
+ }
+
+ data.rainunit = data.rainunit.trim(); // WView sends ' mm' etc
+
+ // take a look at the cloud base data...
+ // change WeatherCat units from Metres/Feet to m/ft
+ try {
+ if (data.cloudbaseunit.toLowerCase() === 'metres') {
+ data.cloudbaseunit = 'm';
+ } else if (data.cloudbaseunit.toLowerCase() === 'feet') {
+ data.cloudbaseunit = 'ft';
+ }
+ } catch (e) {
+ data.cloudbaseunit = '';
+ }
+ if (config.showCloudGauge && (
+ (config.weatherProgram === 4 || config.weatherProgram === 5) ||
+ data.cloudbasevalue === '')) {
+ // WeatherCat and VWS (and WView?) do not provide a cloud base value, so we have to calculate it...
+ // assume if the station uses an imperial wind speed they want cloud base in feet, otherwise metres
+ data.cloudbaseunit = (data.windunit === 'mph' || data.windunit === 'kts') ? 'ft' : 'm';
+ data.cloudbasevalue = calcCloudbase(data.temp, data.tempunit, data.dew, data.cloudbaseunit);
+ }
+
+ // Temperature data conversion for display required?
+ if (data.tempunit[1] !== displayUnits.temp && userUnitsSet) {
+ // temp needs converting
+ if (data.tempunit[1] === 'C') {
+ convTempData(c2f);
+ } else {
+ convTempData(f2c);
+ }
+ } else if (firstRun) {
+ displayUnits.temp = data.tempunit[1];
+ setRadioCheck('rad_unitsTemp', displayUnits.temp);
+ }
+
+ // Rain data conversion for display required?
+ if (data.rainunit !== displayUnits.rain && userUnitsSet) {
+ // rain needs converting
+ convRainData(displayUnits.rain === 'mm' ? in2mm : mm2in);
+ } else if (firstRun) {
+ displayUnits.rain = data.rainunit;
+ setRadioCheck('rad_unitsRain', displayUnits.rain);
+ }
+
+ // Wind data conversion for display required?
+ if (data.windunit !== displayUnits.wind && userUnitsSet) {
+ // wind needs converting
+ convWindData(data.windunit, displayUnits.wind);
+ } else if (firstRun) {
+ displayUnits.wind = data.windunit;
+ displayUnits.windrun = getWindrunUnits(data.windunit);
+ setRadioCheck('rad_unitsWind', displayUnits.wind);
+ }
+
+ // Pressure data conversion for display required?
+ if (data.pressunit !== displayUnits.press && userUnitsSet) {
+ convBaroData(data.pressunit, displayUnits.press);
+ } else if (firstRun) {
+ displayUnits.press = data.pressunit;
+ setRadioCheck('rad_unitsPress', displayUnits.press);
+ }
+
+ // Cloud height data conversion for display required?
+ if (data.cloudbaseunit !== displayUnits.cloud && userUnitsSet) {
+ // Cloud height needs converting
+ convCloudBaseData(displayUnits.cloud === 'm' ? ft2m : m2ft);
+ } else if (firstRun) {
+ displayUnits.cloud = data.cloudbaseunit;
+ setRadioCheck('rad_unitsCloud', displayUnits.cloud);
+ }
+
+ statusScroller.setText(data.forecast);
+
+ // first time only, setup units etc
+ if (firstRun) {
+ doFirst();
+ }
+
+ // publish the update, use the shared data object rather than transferring it
+ $.publish('gauges.dataUpdated', {});
+
+ retVal = true;
+ } else {
+ // set an error message
+ if (data.ver < realtimeVer) {
+ statusTimer.setValue(0);
+ statusScroller.setText('Your ' + config.realTimeURL.substr(config.realTimeURL.lastIndexOf('/') + 1) + ' file template needs updating!');
+ return false;
+ } else {
+ // oh-oh! The number of data fields isn't what we expected
+ statusScroller.setText(strings.realtimeCorrupt);
+ }
+ ledIndicator.setLedOnOff(false);
+ ledIndicator.setTitle(strings.led_title_unknown);
+
+ retVal = false;
+ }
+ return retVal;
+ },
+
+ //
+ // pagetimeout() called once every config.pageUpdateLimit minutes to stop updates and prevent page 'sitters'
+ //
+ pageTimeout = function () {
+ statusScroller.setText(strings.StatusPageLimit);
+ ledIndicator.setLedColor(steelseries.LedColor.RED_LED);
+ ledIndicator.setTitle(strings.StatusPageLimit);
+ ledIndicator.blink(true);
+ ledIndicator.setTitle(strings.StatusTimeout);
+
+ // stop any pending download
+ clearTimeout(downloadTimer);
+
+ // stop any long polling in progress
+ if ($.active > 0) {
+ jqXHR.abort();
+ }
+
+ // stop the clock
+ clearInterval(tickTockInterval);
+
+ // clear the timer display
+ statusTimer.setValue(0);
+
+ // set an onclick event on the LED to restart everything
+ $('#canvas_led').click(
+ function click() {
+ // disable the onClick event again
+ $('#canvas_led').unbind('click');
+ // reset the timer count to 1
+ statusTimer.reset(1);
+ // restart the timer to update the status time
+ tickTockInterval = setInterval(
+ function tick() {
+ $.publish('gauges.clockTick', null);
+ },
+ 1000
+ );
+
+ // restart the page timeout timer, so we hit this code again
+ setTimeout(pageTimeout, config.pageUpdateLimit * 60 * 1000);
+
+ // refresh the page data
+ getRealtime();
+ }
+ );
+ },
+
+ //
+ // doFirst() called by doUpdate() the first time the page is updated to set-up various things that are
+ // only known when the /data/realtimegauges.txt data is available
+ //
+ doFirst = function () {
+ var cacheDefeat = '?' + (new Date()).getTime().toString();
+
+ if (data.tempunit[1] === 'F') {
+ displayUnits.temp = 'F';
+ setRadioCheck('rad_unitsTemp', 'F');
+ setTempUnits(false);
+ }
+
+ if (data.pressunit !== 'hPa') {
+ displayUnits.press = data.pressunit;
+ setRadioCheck('rad_unitsPress', data.pressunit);
+ setBaroUnits(data.pressunit);
+ }
+
+ if (data.windunit !== 'km/h') {
+ displayUnits.wind = data.windunit;
+ setRadioCheck('rad_unitsWind', data.windunit);
+ setWindUnits(data.windunit);
+ }
+
+ if (data.rainunit !== 'mm') {
+ displayUnits.rain = data.rainunit;
+ setRadioCheck('rad_unitsRain', data.rainunit);
+ setRainUnits(false);
+ }
+
+ if (config.showSolarGauge && typeof data.SolarTM !== 'undefined' && gaugeSolar) {
+ gaugeSolar.gauge.setMaxMeasuredValueVisible(true);
+ }
+
+ if (config.showCloudGauge && data.cloudbaseunit !== 'm') {
+ displayUnits.cloud = data.cloudbaseunit;
+ setRadioCheck('rad_unitsCloud', data.cloudbaseunit);
+ setCloudBaseUnits(false);
+ }
+
+ // set the script version on the page
+ $('#scriptVer').html(config.scriptVer);
+ // set the version information from the station
+ $('#programVersion').html(data.version);
+ $('#programBuild').html(data.build);
+ $('#programName').html(programLink[config.weatherProgram]);
+
+ if (config.showPopupData) {
+ // now initialise the pop-up script and download the trend /images
+ // - has to be done here as doFirst may remove elements from the page
+ // - and we delay the download of the /images speeding up page display
+ ddimgtooltip.init('[id^="tip_"]');
+ // Are we running on a phone device (or really low res screen)?
+ if ($(window).width() < 480) {
+ $('.ddimgtooltip').filter(':hidden').width('200px');
+ }
+ }
+
+ if (config.showPopupData && config.showPopupGraphs) {
+ // now download the trend /images
+ // - has to be done here as doFirst may remove elements from the page
+ // - and we delay the download of the /images speeding up page display
+ //
+ $('#imgtip0_img').attr('src', config.imgPathURL + config.tipImgs[0][0] + cacheDefeat);
+ if (gaugeDew) {
+ $('#imgtip1_img').attr('src', config.imgPathURL + config.tipImgs[1][gaugeDew.data.popupImg] + cacheDefeat);
+ }
+ $('#imgtip2_img').attr('src', config.imgPathURL + config.tipImgs[2] + cacheDefeat);
+ $('#imgtip3_img').attr('src', config.imgPathURL + config.tipImgs[3] + cacheDefeat);
+ $('#imgtip4_img').attr('src', config.imgPathURL + config.tipImgs[4][0] + cacheDefeat);
+ $('#imgtip5_img').attr('src', config.imgPathURL + config.tipImgs[5] + cacheDefeat);
+ $('#imgtip6_img').attr('src', config.imgPathURL + config.tipImgs[6] + cacheDefeat);
+ $('#imgtip7_img').attr('src', config.imgPathURL + config.tipImgs[7] + cacheDefeat);
+ $('#imgtip8_img').attr('src', config.imgPathURL + config.tipImgs[8] + cacheDefeat);
+ $('#imgtip9_img').attr('src', config.imgPathURL + config.tipImgs[9] + cacheDefeat);
+ $('#imgtip10_img').attr('src', config.imgPathURL + config.tipImgs[10] + cacheDefeat);
+ $('#imgtip11_img').attr('src', config.imgPathURL + config.tipImgs[11] + cacheDefeat);
+ // start a timer for popup graphic updates
+ setInterval(
+ function timeout() {
+ $.publish('gauges.graphUpdate', '?' + (new Date()).getTime().toString());
+ },
+ config.graphUpdateTime * 60 * 1000
+ );
+ }
+
+ firstRun = false;
+ },
+
+ //
+ // createTempSections() creates an array of gauge sections appropriate for Celsius or Fahrenheit scales
+ //
+ createTempSections = function (celsius) {
+ var section;
+ if (celsius) {
+ section = [
+ steelseries.Section(-100, -35, 'rgba(195, 92, 211, 0.4)'),
+ steelseries.Section(-35, -30, 'rgba(139, 74, 197, 0.4)'),
+ steelseries.Section(-30, -25, 'rgba(98, 65, 188, 0.4)'),
+ steelseries.Section(-25, -20, 'rgba(62, 66, 185, 0.4)'),
+ steelseries.Section(-20, -15, 'rgba(42, 84, 194, 0.4)'),
+ steelseries.Section(-15, -10, 'rgba(25, 112, 210, 0.4)'),
+ steelseries.Section(-10, -5, 'rgba(9, 150, 224, 0.4)'),
+ steelseries.Section(-5, 0, 'rgba(2, 170, 209, 0.4)'),
+ steelseries.Section(0, 5, 'rgba(0, 162, 145, 0.4)'),
+ steelseries.Section(5, 10, 'rgba(0, 158, 122, 0.4)'),
+ steelseries.Section(10, 15, 'rgba(54, 177, 56, 0.4)'),
+ steelseries.Section(15, 20, 'rgba(111, 202, 56, 0.4)'),
+ steelseries.Section(20, 25, 'rgba(248, 233, 45, 0.4)'),
+ steelseries.Section(25, 30, 'rgba(253, 142, 42, 0.4)'),
+ steelseries.Section(30, 40, 'rgba(236, 45, 45, 0.4)'),
+ steelseries.Section(40, 100, 'rgba(245, 109, 205, 0.4)')
+ ];
+ } else {
+ section = [
+ steelseries.Section(-200, -30, 'rgba(195, 92, 211, 0.4)'),
+ steelseries.Section(-30, -25, 'rgba(139, 74, 197, 0.4)'),
+ steelseries.Section(-25, -15, 'rgba(98, 65, 188, 0.4)'),
+ steelseries.Section(-15, -5, 'rgba(62, 66, 185, 0.4)'),
+ steelseries.Section(-5, 5, 'rgba(42, 84, 194, 0.4)'),
+ steelseries.Section(5, 15, 'rgba(25, 112, 210, 0.4)'),
+ steelseries.Section(15, 25, 'rgba(9, 150, 224, 0.4)'),
+ steelseries.Section(25, 32, 'rgba(2, 170, 209, 0.4)'),
+ steelseries.Section(32, 40, 'rgba(0, 162, 145, 0.4)'),
+ steelseries.Section(40, 50, 'rgba(0, 158, 122, 0.4)'),
+ steelseries.Section(50, 60, 'rgba(54, 177, 56, 0.4)'),
+ steelseries.Section(60, 70, 'rgba(111, 202, 56, 0.4)'),
+ steelseries.Section(70, 80, 'rgba(248, 233, 45, 0.4)'),
+ steelseries.Section(80, 90, 'rgba(253, 142, 42, 0.4)'),
+ steelseries.Section(90, 110, 'rgba(236, 45, 45, 0.4)'),
+ steelseries.Section(110, 200, 'rgba(245, 109, 205, 0.4)')
+ ];
+ }
+ return section;
+ },
+
+ //
+ // createRainSections() returns an array of section highlights for the Rain Rate gauge
+ //
+ /*
+ Assumes 'standard' descriptive limits from UK met office:
+ < 0.25 mm/hr - Very light rain
+ 0.25mm/hr to 1.0mm/hr - Light rain
+ 1.0 mm/hr to 4.0 mm/hr - Moderate rain
+ 4.0 mm/hr to 16.0 mm/hr - Heavy rain
+ 16.0 mm/hr to 50 mm/hr - Very heavy rain
+ > 50.0 mm/hour - Extreme rain
+
+ Roughly translated to the corresponding Inch rates
+ < 0.001
+ 0.001 to 0.05
+ 0.05 to 0.20
+ 0.20 to 0.60
+ 0.60 to 2.0
+ > 2.0
+ */
+ createRainRateSections = function (metric) {
+ var factor = metric ? 1 : 1 / 25;
+ return [
+ steelseries.Section(0, 0.25 * factor, 'rgba(0, 140, 0, 0.5)'),
+ steelseries.Section(0.25 * factor, 1 * factor, 'rgba(80, 192, 80, 0.5)'),
+ steelseries.Section(1 * factor, 4 * factor, 'rgba(150, 203, 150, 0.5)'),
+ steelseries.Section(4 * factor, 16 * factor, 'rgba(212, 203, 109, 0.5)'),
+ steelseries.Section(16 * factor, 50 * factor, 'rgba(225, 155, 105, 0.5)'),
+ steelseries.Section(50 * factor, 1000 * factor, 'rgba(245, 86, 59, 0.5)')
+ ];
+ },
+
+ //
+ // createRainFallSections()returns an array of section highlights for total rainfall in mm or inches
+ //
+ createRainfallSections = function (metric) {
+ var factor = metric ? 1 : 1 / 25;
+ return [
+ steelseries.Section(0, 5 * factor, 'rgba(0, 250, 0, 1)'),
+ steelseries.Section(5 * factor, 10 * factor, 'rgba(0, 250, 117, 1)'),
+ steelseries.Section(10 * factor, 25 * factor, 'rgba(218, 246, 0, 1)'),
+ steelseries.Section(25 * factor, 40 * factor, 'rgba(250, 186, 0, 1)'),
+ steelseries.Section(40 * factor, 50 * factor, 'rgba(250, 95, 0, 1)'),
+ steelseries.Section(50 * factor, 65 * factor, 'rgba(250, 0, 0, 1)'),
+ steelseries.Section(65 * factor, 75 * factor, 'rgba(250, 6, 80, 1)'),
+ steelseries.Section(75 * factor, 100 * factor, 'rgba(205, 18, 158, 1)'),
+ steelseries.Section(100 * factor, 125 * factor, 'rgba(0, 0, 250, 1)'),
+ steelseries.Section(125 * factor, 500 * factor, 'rgba(0, 219, 212, 1)')
+ ];
+ },
+
+ //
+ // createRainfallGradient() returns an array of SS colours for continuous gradient colouring of the total rainfall LED gauge
+ //
+ createRainfallGradient = function (metric) {
+ var grad = new steelseries.gradientWrapper(
+ 0,
+ (metric ? 100 : 4),
+ [0, 0.1, 0.62, 1],
+ [
+ new steelseries.rgbaColor(15, 148, 0, 1),
+ new steelseries.rgbaColor(213, 213, 0, 1),
+ new steelseries.rgbaColor(213, 0, 25, 1),
+ new steelseries.rgbaColor(250, 0, 0, 1)
+ ]
+ );
+ return grad;
+ },
+
+ //
+ // createClousBaseSections() returns an array of section highlights for the Cloud Base gauge
+ //
+ createCloudBaseSections = function (metric) {
+ var section;
+ if (metric) {
+ section = [
+ steelseries.Section(0, 150, 'rgba(245, 86, 59, 0.5)'),
+ steelseries.Section(150, 300, 'rgba(225, 155, 105, 0.5)'),
+ steelseries.Section(300, 750, 'rgba(212, 203, 109, 0.5)'),
+ steelseries.Section(750, 1000, 'rgba(150, 203, 150, 0.5)'),
+ steelseries.Section(1000, 1500, 'rgba(80, 192, 80, 0.5)'),
+ steelseries.Section(1500, 2500, 'rgba(0, 140, 0, 0.5)'),
+ steelseries.Section(2500, 5500, 'rgba(19, 103, 186, 0.5)')
+ ];
+ } else {
+ section = [
+ steelseries.Section(0, 500, 'rgba(245, 86, 59, 0.5)'),
+ steelseries.Section(500, 1000, 'rgba(225, 155, 105, 0.5)'),
+ steelseries.Section(1000, 2500, 'rgba(212, 203, 109, 0.5)'),
+ steelseries.Section(2500, 3500, 'rgba(150, 203, 150, 0.5)'),
+ steelseries.Section(3500, 5500, 'rgba(80, 192, 80, 0.5)'),
+ steelseries.Section(5500, 8500, 'rgba(0, 140, 0, 0.5)'),
+ steelseries.Section(8500, 18000, 'rgba(19, 103, 186, 0.5)')
+ ];
+ }
+ return section;
+ },
+
+ //
+ // --------------- Helper functions ------------------
+ //
+
+ //
+ // getord() converts a value in degrees (0-360) into a localised compass point (N, ENE, NE, etc)
+ //
+ getord = function (deg) {
+ if (deg === 0) {
+ // Special case, 0=No wind, 360=North
+ return strings.calm;
+ } else {
+ return (strings.coords[Math.floor((deg + 11.25) / 22.5) % 16]);
+ }
+ },
+
+ //
+ // getUrlParam() extracts the named parameter from the current page URL
+ //
+ getUrlParam = function (paramName) {
+ var name, regexS, regex, results;
+ name = paramName.replace(/(\[|\])/g, '\\$1');
+ regexS = '[\\?&]' + name + '=([^]*)';
+ regex = new RegExp(regexS);
+ results = regex.exec(window.location.href);
+ if (results === null) {
+ return '';
+ } else {
+ return results[1];
+ }
+ },
+
+ //
+ // extractDecimal() returns a decimal number from a string, the decimal point can be either a dot or a comma
+ // it ignores any text such as pre/appended units
+ //
+ extractDecimal = function (str, errVal) {
+ try {
+ return (/[-+]?[0-9]+\.?[0-9]*/).exec(str.replace(',', '.'))[0];
+ } catch (e) {
+ // error condition
+ return errVal || -9999;
+ }
+ },
+
+ //
+ // extractInteger() returns an integer from a string
+ // it ignores any text such as pre/appended units
+ //
+ extractInteger = function (str, errVal) {
+ try {
+ return (/[-+]?[0-9]+/).exec(str)[0];
+ } catch (e) {
+ // error condition
+ return errVal || -9999;
+ }
+ },
+
+ //
+ // tempTrend() converts a temperature trend value into a localised string, or +1, 0, -1 depending on the value of bTxt
+ //
+ tempTrend = function (trend, units, bTxt) {
+ // Scale is over 3 hours, in Celsius
+ var val = trend * 3 * (units[1] === 'C' ? 1 : (5 / 9)),
+ ret;
+ if (trend === -9999) {
+ ret = (bTxt ? '--' : trend);
+ } else if (val > 5) {
+ ret = (bTxt ? strings.RisingVeryRapidly : 1);
+ } else if (val > 3) {
+ ret = (bTxt ? strings.RisingQuickly : 1);
+ } else if (val > 1) {
+ ret = (bTxt ? strings.Rising : 1);
+ } else if (val > 0.5) {
+ ret = (bTxt ? strings.RisingSlowly : 1);
+ } else if (val >= -0.5) {
+ ret = (bTxt ? strings.Steady : 0);
+ } else if (val >= -1) {
+ ret = (bTxt ? strings.FallingSlowly : -1);
+ } else if (val >= -3) {
+ ret = (bTxt ? strings.Falling : -1);
+ } else if (val >= -5) {
+ ret = (bTxt ? strings.FallingQuickly : -1);
+ } else {
+ ret = (bTxt ? strings.FallingVeryRapidly : -1);
+ }
+ return ret;
+ },
+
+ //
+ // baroTrend() converts a pressure trend value into a localised string, or +1, 0, -1 depending on the value of bTxt
+ //
+ baroTrend = function (trend, units, bTxt) {
+ var val = trend * 3,
+ ret;
+ // The terms below are the UK Met Office terms for a 3 hour change in hPa
+ // trend is supplied as an hourly change, so multiply by 3
+ if (units === 'inHg') {
+ val *= 33.8639;
+ } else if (units === 'kPa') {
+ val *= 10;
+ // assume everything else is hPa or mb, could be dangerous!
+ }
+ if (trend === -9999) {
+ ret = (bTxt ? '--' : trend);
+ } else if (val > 6.0) {
+ ret = (bTxt ? strings.RisingVeryRapidly : 1);
+ } else if (val > 3.5) {
+ ret = (bTxt ? strings.RisingQuickly : 1);
+ } else if (val > 1.5) {
+ ret = (bTxt ? strings.Rising : 1);
+ } else if (val > 0.1) {
+ ret = (bTxt ? strings.RisingSlowly : 1);
+ } else if (val >= -0.1) {
+ ret = (bTxt ? strings.Steady : 0);
+ } else if (val >= -1.5) {
+ ret = (bTxt ? strings.FallingSlowly : -1);
+ } else if (val >= -3.5) {
+ ret = (bTxt ? strings.Falling : -1);
+ } else if (val >= -6.0) {
+ ret = (bTxt ? strings.FallingQuickly : -1);
+ } else {
+ ret = (bTxt ? strings.FallingVeryRapidly : -1);
+ }
+ return ret;
+ },
+
+ //
+ // getMinTemp() returns the lowest temperature today for gauge scaling
+ //
+ getMinTemp = function (deflt) {
+ return Math.min(
+ extractDecimal(data.tempTL, deflt),
+ extractDecimal(data.dewpointTL, deflt),
+ extractDecimal(data.apptempTL, deflt),
+ extractDecimal(data.feelslikeTL, deflt),
+ extractDecimal(data.wchillTL, deflt));
+ },
+
+ //
+ // getMaxTemp() returns the highest temperature today for gauge scaling
+ //
+ getMaxTemp = function (deflt) {
+ return Math.max(
+ extractDecimal(data.tempTH, deflt),
+ extractDecimal(data.apptempTH, deflt),
+ extractDecimal(data.feelslikeTH, deflt),
+ extractDecimal(data.heatindexTH, deflt),
+ extractDecimal(data.humidex, deflt));
+ },
+
+ // Celsius to Fahrenheit
+ c2f = function (val) {
+ return (extractDecimal(val) * 9 / 5 + 32).toFixed(1);
+ },
+ // Fahrenheit to Celsius
+ f2c = function (val) {
+ return ((extractDecimal(val) - 32) * 5 / 9).toFixed(1);
+ },
+ // kph to ms
+ kmh2ms = function (val) {
+ return (extractDecimal(val) * 0.2778).toFixed(1);
+ },
+ // ms to kph
+ ms2kmh = function (val) {
+ return (extractDecimal(val) * 3.6).toFixed(1);
+ },
+ kmh2ms = function (val) {
+ return (extractDecimal(val) / 3.6).toFixed(1);
+ },
+ // mm to inches
+ mm2in = function (val) {
+ return (extractDecimal(val) / 25.4).toFixed(2);
+ },
+ // inches to mm
+ in2mm = function (val) {
+ return (extractDecimal(val) * 25.4).toFixed(1);
+ },
+ // miles to km
+ miles2km = function (val) {
+ return (extractDecimal(val) * 1.609344).toFixed(1);
+ },
+ // nautical miles to km
+ nmiles2km = function (val) {
+ return (extractDecimal(val) * 1.85200).toFixed(1);
+ },
+ // km to miles
+ km2miles = function (val) {
+ return (extractDecimal(val) / 1.609344).toFixed(1);
+ },
+ // km to nautical miles
+ km2nmiles = function (val) {
+ return (extractDecimal(val) / 1.85200).toFixed(1);
+ },
+ // hPa to inHg (@0°C)
+ hpa2inhg = function (val, decimals) {
+ return (extractDecimal(val) * 0.029528744).toFixed(decimals || 3);
+ },
+ // inHg to hPa (@0°C)
+ inhg2hpa = function (val) {
+ return (extractDecimal(val) / 0.029528744).toFixed(1);
+ },
+ // kPa to hPa
+ kpa2hpa = function (val) {
+ return (extractDecimal(val) * 10).toFixed(1);
+ },
+ // hPa to kPa
+ hpa2kpa = function (val, decimals) {
+ return (extractDecimal(val) / 10).toFixed(decimals || 2);
+ },
+ // m to ft
+ m2ft = function (val) {
+ return (val * 3.2808399).toFixed(0);
+ },
+ // ft to m
+ ft2m = function (val) {
+ return (val / 3.2808399).toFixed(0);
+ },
+
+ //
+ // setCookie() writes the 'obj' in cookie 'name' for persistent storage
+ //
+ setCookie = function (name, obj) {
+ var date = new Date(),
+ expires;
+ // cookies valid for 1 year
+ date.setYear(date.getFullYear() + 1);
+ expires = '; expires=' + date.toGMTString();
+ document.cookie = name + '=' + encodeURIComponent(JSON.stringify(obj)) + expires;
+ },
+
+ //
+ // getCookie() reads the value of cookie 'name' from persistent storage
+ //
+ getCookie = function (name) {
+ var i, x, y,
+ ret = null,
+ arrCookies = document.cookie.split(';');
+
+ for (i = arrCookies.length; i--;) {
+ x = arrCookies[i].split('=');
+ if (x[0].trim() === name) {
+ try {
+ y = decodeURIComponent(x[1]);
+ } catch (e) {
+ y = x[1];
+ }
+ ret = JSON.parse(unescape(y));
+ break;
+ }
+ }
+ return ret;
+ },
+
+ //
+ // setRadioCheck() sets the desired value of the HTML radio buttons to be selected
+ //
+ setRadioCheck = function (obj, val) {
+ $('input:radio[name="' + obj + '"]').filter('[value="' + val + '"]').prop('checked', true);
+ },
+
+ //
+ // convTempData() converts all the temperature values using the supplied conversion function
+ //
+ convTempData = function (convFunc) {
+ data.apptemp = convFunc(data.apptemp);
+ data.apptempTH = convFunc(data.apptempTH);
+ data.apptempTL = convFunc(data.apptempTL);
+ data.feelslike = convFunc(data.feelslike);
+ data.feelslikeTH = convFunc(data.feelslikeTH);
+ data.feelslikeTL = convFunc(data.feelslikeTL);
+ data.dew = convFunc(data.dew);
+ data.dewpointTH = convFunc(data.dewpointTH);
+ data.dewpointTL = convFunc(data.dewpointTL);
+ data.heatindex = convFunc(data.heatindex);
+ data.heatindexTH = convFunc(data.heatindexTH);
+ data.humidex = convFunc(data.humidex);
+ data.intemp = convFunc(data.intemp);
+ if (data.intempTL && data.intempTH) {
+ data.intempTL = convFunc(data.intempTL);
+ data.intempTH = convFunc(data.intempTH);
+ }
+ data.temp = convFunc(data.temp);
+ data.tempTH = convFunc(data.tempTH);
+ data.tempTL = convFunc(data.tempTL);
+ data.wchill = convFunc(data.wchill);
+ data.wchillTL = convFunc(data.wchillTL);
+ if (convFunc === c2f) {
+ data.temptrend = (+extractDecimal(data.temptrend) * 9 / 5).toFixed(1);
+ data.tempunit = '°F';
+ } else {
+ data.temptrend = (+extractDecimal(data.temptrend) * 5 / 9).toFixed(1);
+ data.tempunit = '°C';
+ }
+ },
+
+ //
+ // convRainData() converts all the rain data units using the supplied conversion function
+ //
+ convRainData = function (convFunc) {
+ data.rfall = convFunc(data.rfall);
+ data.rrate = convFunc(data.rrate);
+ data.rrateTM = convFunc(data.rrateTM);
+ data.hourlyrainTH = convFunc(data.hourlyrainTH);
+ data.rainunit = convFunc === mm2in ? 'in' : 'mm';
+ },
+
+ //
+ // convWindData() converts all the wind values using the supplied conversion function
+ //
+ convWindData = function (from, to) {
+ var fromFunc1, toFunc1,
+ fromFunc2, toFunc2,
+ dummy = function (val) {
+ return val;
+ };
+
+ // convert to km/h & km
+ switch (from) {
+ case 'mph':
+ fromFunc1 = miles2km;
+ fromFunc2 = miles2km;
+ break;
+ case 'kts':
+ fromFunc1 = nmiles2km;
+ fromFunc2 = nmiles2km;
+ break;
+ case 'm/s':
+ fromFunc1 = ms2kmh;
+ fromFunc2 = dummy;
+ break;
+ case 'km/h':
+ // falls through
+ default:
+ fromFunc1 = dummy;
+ fromFunc2 = dummy;
+ }
+ // conversion function from km to required units
+ switch (to) {
+ case 'mph':
+ toFunc1 = km2miles;
+ toFunc2 = km2miles;
+ displayUnits.windrun = 'miles';
+ break;
+ case 'kts':
+ toFunc1 = km2nmiles;
+ toFunc2 = km2nmiles;
+ displayUnits.windrun = 'n.miles';
+ break;
+ case 'm/s':
+ toFunc1 = kmh2ms;
+ toFunc2 = dummy;
+ displayUnits.windrun = 'km';
+ break;
+ case 'km/h':
+ // falls through
+ default:
+ toFunc1 = dummy;
+ toFunc2 = dummy;
+ displayUnits.windrun = 'km';
+ }
+ // do the conversions
+ data.wgust = toFunc1(fromFunc1(data.wgust));
+ data.wgustTM = toFunc1(fromFunc1(data.wgustTM));
+ data.windTM = toFunc1(fromFunc1(data.windTM));
+ data.windrun = toFunc2(fromFunc2(data.windrun));
+ data.wlatest = toFunc1(fromFunc1(data.wlatest));
+ data.wspeed = toFunc1(fromFunc1(data.wspeed));
+ data.windunit = to;
+ },
+
+ //
+ // convBaroData() converts all the pressure values using the supplied conversion function
+ //
+ convBaroData = function (from, to) {
+ var fromFunc, toFunc,
+ dummy = function (val) {
+ return val;
+ };
+
+ // convert to hPa
+ switch (from) {
+ case 'hPa':
+ // falls through
+ case 'mb':
+ fromFunc = dummy;
+ break;
+ case 'inHg':
+ fromFunc = inhg2hpa;
+ break;
+ case 'kPa':
+ fromFunc = kpa2hpa;
+ break;
+ // no default
+ }
+ // convert to required units
+ switch (to) {
+ case 'hPa':
+ // falls through
+ case 'mb':
+ toFunc = dummy;
+ break;
+ case 'inHg':
+ toFunc = hpa2inhg;
+ break;
+ case 'kPa':
+ toFunc = hpa2kpa;
+ break;
+ // no default
+ }
+
+ data.press = toFunc(fromFunc(data.press));
+ data.pressH = toFunc(fromFunc(data.pressH));
+ data.pressL = toFunc(fromFunc(data.pressL));
+ data.pressTH = toFunc(fromFunc(data.pressTH));
+ data.pressTL = toFunc(fromFunc(data.pressTL));
+ data.presstrendval = toFunc(fromFunc(data.presstrendval), 3);
+ data.pressunit = to;
+ },
+
+ //
+ // convCloudBaseData() converts all the cloud base data units using the supplied conversion function
+ //
+ convCloudBaseData = function (convFunc) {
+ data.cloudbasevalue = convFunc(data.cloudbasevalue);
+ data.cloudbaseunit = convFunc === m2ft ? 'ft' : 'm';
+ },
+
+ //
+ // setUnits() Main data conversion routine, calls all the setXXXX() sub-routines
+ //
+ setUnits = function (radio) {
+ var sel = radio.value;
+
+ userUnitsSet = true;
+
+ switch (sel) {
+ // == Temperature ==
+ case 'C':
+ displayUnits.temp = sel;
+ if (data.tempunit[1] !== sel) {
+ setTempUnits(true);
+ convTempData(f2c);
+ if (gaugeTemp) { gaugeTemp.update(); }
+ if (gaugeDew) { gaugeDew.update(); }
+ }
+ break;
+ case 'F':
+ displayUnits.temp = sel;
+ if (data.tempunit[1] !== sel) {
+ setTempUnits(false);
+ convTempData(c2f);
+ if (gaugeTemp) { gaugeTemp.update(); }
+ if (gaugeDew) { gaugeDew.update(); }
+ }
+ break;
+ // == Rainfall ==
+ case 'mm':
+ displayUnits.rain = sel;
+ if (data.rainunit !== sel) {
+ setRainUnits(true);
+ convRainData(in2mm);
+ if (gaugeRain) { gaugeRain.update(); }
+ if (gaugeRRate) { gaugeRRate.update(); }
+ }
+ break;
+ case 'in':
+ displayUnits.rain = sel;
+ if (data.rainunit !== sel) {
+ setRainUnits(false);
+ convRainData(mm2in);
+ if (gaugeRain) { gaugeRain.update(); }
+ if (gaugeRRate) { gaugeRRate.update(); }
+ }
+ break;
+ // == Pressure ==
+ case 'hPa':
+ // falls through
+ case 'inHg':
+ // falls through
+ case 'mb':
+ // falls through
+ case 'kPa':
+ displayUnits.press = sel;
+ if (data.pressunit !== sel) {
+ convBaroData(data.pressunit, sel);
+ setBaroUnits(sel);
+ if (gaugeBaro) { gaugeBaro.update(); }
+ }
+ break;
+ // == Wind speed ==
+ case 'mph':
+ // falls through
+ case 'kts':
+ // falls through
+ case 'm/s':
+ // falls through
+ case 'km/h':
+ displayUnits.wind = sel;
+ if (data.windunit !== sel) {
+ convWindData(data.windunit, sel);
+ setWindUnits(sel);
+ if (gaugeWind) { gaugeWind.update(); }
+ if (gaugeDir) { gaugeDir.update(); }
+ if (gaugeRose) { gaugeRose.update(); }
+ }
+ break;
+ // == CloudBase ==
+ case 'm':
+ displayUnits.cloud = sel;
+ if (data.cloudbaseunit !== sel) {
+ setCloudBaseUnits(true);
+ convCloudBaseData(ft2m);
+ if (gaugeCloud) { gaugeCloud.update(); }
+ }
+ break;
+ case 'ft':
+ displayUnits.cloud = sel;
+ if (data.cloudbaseunit !== sel) {
+ setCloudBaseUnits(false);
+ convCloudBaseData(m2ft);
+ if (gaugeCloud) { gaugeCloud.update(); }
+ }
+ break;
+ // no default
+ }
+ if (config.useCookies) {
+ setCookie('units', displayUnits);
+ }
+ },
+
+ setTempUnits = function (celsius) {
+ if (celsius) {
+ data.tempunit = '°C';
+ if (gaugeTemp) {
+ gaugeTemp.data.sections = createTempSections(true);
+ gaugeTemp.data.minValue = gaugeGlobals.tempScaleDefMinC;
+ gaugeTemp.data.maxValue = gaugeGlobals.tempScaleDefMaxC;
+ }
+ if (gaugeDew) {
+ gaugeDew.data.sections = createTempSections(true);
+ gaugeDew.data.minValue = gaugeGlobals.tempScaleDefMinC;
+ gaugeDew.data.maxValue = gaugeGlobals.tempScaleDefMaxC;
+ }
+ } else {
+ data.tempunit = '°F';
+ if (gaugeTemp) {
+ gaugeTemp.data.sections = createTempSections(false);
+ gaugeTemp.data.minValue = gaugeGlobals.tempScaleDefMinF;
+ gaugeTemp.data.maxValue = gaugeGlobals.tempScaleDefMaxF;
+ }
+ if (gaugeDew) {
+ gaugeDew.data.sections = createTempSections(false);
+ gaugeDew.data.minValue = gaugeGlobals.tempScaleDefMinF;
+ gaugeDew.data.maxValue = gaugeGlobals.tempScaleDefMaxF;
+ }
+ }
+ if (gaugeTemp) {
+ gaugeTemp.gauge.setUnitString(data.tempunit);
+ gaugeTemp.gauge.setSection(gaugeTemp.data.sections);
+ }
+ if (gaugeDew) {
+ gaugeDew.gauge.setUnitString(data.tempunit);
+ gaugeDew.gauge.setSection(gaugeTemp.data.sections);
+ }
+ },
+
+ setRainUnits = function (mm) {
+ if (mm) {
+ data.rainunit = 'mm';
+ if (gaugeRain) {
+ gaugeRain.data.lcdDecimals = 1;
+ gaugeRain.data.scaleDecimals = 1;
+ gaugeRain.data.labelNumberFormat = gaugeGlobals.labelFormat;
+ gaugeRain.data.sections = (gaugeGlobals.rainUseSectionColours ? createRainfallSections(true) : []);
+ gaugeRain.data.maxValue = gaugeGlobals.rainScaleDefMaxmm;
+ gaugeRain.data.grad = (gaugeGlobals.rainUseGradientColours ? createRainfallGradient(true) : null);
+ }
+ if (gaugeRRate) {
+ gaugeRRate.data.lcdDecimals = 1;
+ gaugeRRate.data.scaleDecimals = 0;
+ gaugeRRate.data.labelNumberFormat = gaugeGlobals.labelFormat;
+ gaugeRRate.data.sections = createRainRateSections(true);
+ gaugeRRate.data.maxValue = gaugeGlobals.rainRateScaleDefMaxmm;
+ }
+ } else {
+ data.rainunit = 'in';
+ if (gaugeRain) {
+ gaugeRain.data.lcdDecimals = 2;
+ gaugeRain.data.scaleDecimals = gaugeGlobals.rainScaleDefMaxIn < 1 ? 2 : 1;
+ gaugeRain.data.labelNumberFormat = steelseries.LabelNumberFormat.FRACTIONAL;
+ gaugeRain.data.sections = (gaugeGlobals.rainUseSectionColours ? createRainfallSections(false) : []);
+ gaugeRain.data.maxValue = gaugeGlobals.rainScaleDefMaxIn;
+ gaugeRain.data.grad = (gaugeGlobals.rainUseGradientColours ? createRainfallGradient(false) : null);
+ }
+ if (gaugeRRate) {
+ gaugeRRate.data.lcdDecimals = 2;
+ gaugeRRate.data.scaleDecimals = gaugeGlobals.rainRateScaleDefMaxIn < 1 ? 2 : 1;
+ gaugeRRate.data.labelNumberFormat = steelseries.LabelNumberFormat.FRACTIONAL;
+ gaugeRRate.data.sections = createRainRateSections(false);
+ gaugeRRate.data.maxValue = gaugeGlobals.rainRateScaleDefMaxIn;
+ }
+ }
+ if (gaugeRain) {
+ gaugeRain.data.value = 0;
+ gaugeRain.gauge.setUnitString(data.rainunit);
+ gaugeRain.gauge.setSection(gaugeRain.data.sections);
+ gaugeRain.gauge.setGradient(gaugeRain.data.grad);
+ gaugeRain.gauge.setFractionalScaleDecimals(gaugeRain.data.scaleDecimals);
+ gaugeRain.gauge.setLabelNumberFormat(gaugeRain.data.labelNumberFormat);
+ gaugeRain.gauge.setLcdDecimals(gaugeRain.data.lcdDecimals);
+ gaugeRain.gauge.setValue(0);
+ gaugeRain.gauge.setMaxValue(gaugeRain.data.maxValue);
+ }
+ if (gaugeRRate) {
+ gaugeRRate.data.value = 0;
+ gaugeRRate.gauge.setUnitString(data.rainunit + '/h');
+ gaugeRRate.gauge.setSection(gaugeRRate.data.sections);
+ gaugeRRate.gauge.setFractionalScaleDecimals(gaugeRRate.data.scaleDecimals);
+ gaugeRRate.gauge.setLabelNumberFormat(gaugeRRate.data.labelNumberFormat);
+ gaugeRRate.gauge.setLcdDecimals(gaugeRRate.data.lcdDecimals);
+ gaugeRRate.gauge.setValue(0);
+ gaugeRRate.gauge.setMaxValue(gaugeRRate.data.maxValue);
+ }
+ },
+
+ setWindUnits = function (to) {
+ var maxVal;
+ data.windunit = to;
+ if (gaugeWind) {
+ // conversion function to required units
+ switch (to) {
+ case 'mph':
+ maxVal = gaugeGlobals.windScaleDefMaxMph;
+ break;
+ case 'kts':
+ maxVal = gaugeGlobals.windScaleDefMaxKts;
+ break;
+ case 'km/h':
+ maxVal = gaugeGlobals.windScaleDefMaxKmh;
+ break;
+ case 'm/s':
+ maxVal = gaugeGlobals.windScaleDefMaxMs;
+ break;
+ // no default
+ }
+ // set the gauges
+ gaugeWind.data.maxValue = maxVal;
+ gaugeWind.gauge.setUnitString(data.windunit);
+ gaugeWind.gauge.setValue(0);
+ }
+ if (gaugeRose) {
+ gaugeRose.setOdoTitle(strings[getWindrunUnits(data.windunit)]);
+ }
+ },
+
+ setBaroUnits = function (to) {
+ var minVal, maxVal;
+
+ if (!gaugeBaro) { return; }
+
+ // set to the required units
+ switch (to) {
+ case 'hPa':
+ // falls through
+ case 'mb':
+ minVal = gaugeGlobals.baroScaleDefMinhPa;
+ maxVal = gaugeGlobals.baroScaleDefMaxhPa;
+ gaugeBaro.data.lcdDecimals = 1;
+ gaugeBaro.data.scaleDecimals = 0;
+ gaugeBaro.data.labelNumberFormat = gaugeGlobals.labelFormat;
+ break;
+ case 'inHg':
+ minVal = gaugeGlobals.baroScaleDefMininHg;
+ maxVal = gaugeGlobals.baroScaleDefMaxinHg;
+ gaugeBaro.data.lcdDecimals = 2;
+ gaugeBaro.data.scaleDecimals = 1;
+ gaugeBaro.data.labelNumberFormat = steelseries.LabelNumberFormat.FRACTIONAL;
+ break;
+ case 'kPa':
+ minVal = gaugeGlobals.baroScaleDefMinkPa;
+ maxVal = gaugeGlobals.baroScaleDefMaxkPa;
+ gaugeBaro.data.lcdDecimals = 2;
+ gaugeBaro.data.scaleDecimals = 1;
+ gaugeBaro.data.labelNumberFormat = steelseries.LabelNumberFormat.FRACTIONAL;
+ break;
+ // no default
+ }
+
+ data.pressunit = to;
+ gaugeBaro.gauge.setUnitString(to);
+ gaugeBaro.gauge.setLcdDecimals(gaugeBaro.data.lcdDecimals);
+ gaugeBaro.gauge.setFractionalScaleDecimals(gaugeBaro.data.scaleDecimals);
+ gaugeBaro.gauge.setLabelNumberFormat(gaugeBaro.data.labelNumberFormat);
+ gaugeBaro.data.minValue = minVal;
+ gaugeBaro.data.maxValue = maxVal;
+ gaugeBaro.data.value = gaugeBaro.data.minValue;
+ },
+
+ setCloudBaseUnits = function (m) {
+ if (!gaugeCloud) { return; }
+
+ if (m) {
+ gaugeCloud.data.sections = createCloudBaseSections(true);
+ gaugeCloud.data.maxValue = gaugeGlobals.cloudScaleDefMaxm;
+ } else {
+ gaugeCloud.data.sections = createCloudBaseSections(false);
+ gaugeCloud.data.maxValue = gaugeGlobals.cloudScaleDefMaxft;
+ }
+ gaugeCloud.data.value = 0;
+ gaugeCloud.gauge.setUnitString(m ? strings.metres : strings.feet);
+ gaugeCloud.gauge.setSection(gaugeCloud.data.sections);
+ },
+
+ //
+ // setLang() switches the HTML page language set, called by changeLang() in language.js
+ //
+ setLang = function (newLang) {
+ // reset to the new language
+ strings = newLang;
+
+ // temperature
+ if (gaugeTemp) {
+ if (config.showIndoorTempHum) {
+ if ($('#rad_temp1').is(':checked')) {
+ gaugeTemp.data.title = strings.temp_title_out;
+ } else {
+ gaugeTemp.data.title = strings.temp_title_in;
+ }
+ } else {
+ gaugeTemp.data.title = strings.temp_title_out;
+ }
+ gaugeTemp.gauge.setTitleString(gaugeTemp.data.title);
+ if (data.ver) { gaugeTemp.update(); }
+ }
+ if (gaugeDew) {
+ switch ($('input[name="rad_dew"]:checked').val()) {
+ case 'dew':
+ gaugeDew.data.title = strings.dew_title;
+ break;
+ case 'app':
+ gaugeDew.data.title = strings.apptemp_title;
+ break;
+ case 'feel':
+ gaugeDew.data.title = strings.feel_title;
+ break;
+ case 'wnd':
+ gaugeDew.data.title = strings.chill_title;
+ break;
+ case 'hea':
+ gaugeDew.data.title = strings.heat_title;
+ break;
+ case 'hum':
+ gaugeDew.data.title = strings.humdx_title;
+ break;
+ // no default
+ }
+ gaugeDew.gauge.setTitleString(gaugeDew.data.title);
+ if (data.ver) { gaugeDew.update(); }
+ }
+ // rain
+ if (gaugeRain) {
+ gaugeRain.data.title = strings.rain_title;
+ gaugeRain.gauge.setTitleString(gaugeRain.data.title);
+ if (data.ver) { gaugeRain.update(); }
+ }
+ // rrate
+ if (gaugeRRate) {
+ gaugeRRate.data.title = strings.rrate_title;
+ gaugeRRate.gauge.setTitleString(gaugeRRate.data.title);
+ if (data.ver) { gaugeRRate.update(); }
+ }
+ // humidity
+ if (gaugeHum) {
+ if (config.showIndoorTempHum) {
+ if ($('#rad_hum1').is(':checked')) {
+ gaugeHum.data.title = strings.hum_title_out;
+ } else {
+ gaugeHum.data.title = strings.hum_title_in;
+ }
+ } else {
+ gaugeHum.data.title = strings.hum_title_out;
+ }
+ gaugeHum.gauge.setTitleString(gaugeHum.data.title);
+ if (data.ver) { gaugeHum.update(); }
+ }
+ // barometer
+ if (gaugeBaro) {
+ gaugeBaro.data.title = strings.baro_title;
+ gaugeBaro.gauge.setTitleString(gaugeBaro.data.title);
+ if (data.ver) { gaugeBaro.update(); }
+ }
+ // wind
+ if (gaugeWind) {
+ gaugeWind.data.title = strings.wind_title;
+ gaugeWind.gauge.setTitleString(gaugeWind.data.title);
+ if (data.ver) { gaugeWind.update(); }
+ }
+ if (gaugeDir) {
+ gaugeDir.gauge.setPointSymbols(strings.compass);
+ gaugeDir.data.titles = [strings.latest_web, strings.tenminavg_web];
+ gaugeDir.gauge.setLcdTitleStrings(gaugeDir.data.titles);
+ if (data.ver) { gaugeDir.update(); }
+ }
+ if (gaugeUV) {
+ gaugeUV.gauge.setTitleString(strings.uv_title);
+ if (data.ver) { gaugeUV.update(); }
+ }
+ if (gaugeSolar) {
+ gaugeSolar.gauge.setTitleString(strings.solar_title);
+ if (data.ver) { gaugeSolar.update(); }
+ }
+ if (gaugeRose) {
+ gaugeRose.setTitle(strings.windrose);
+ gaugeRose.setCompassStrings(strings.compass);
+ gaugeRose.setOdoTitle(strings[getWindrunUnits(displayUnits.wind)]);
+ if (data.ver) { gaugeRose.update(); }
+ }
+ if (gaugeCloud) {
+ // Cloudbase
+ gaugeCloud.data.units = data.cloudunit === 'm' ? strings.metres : strings.feet;
+ gaugeCloud.gauge.setTitleString(strings.cloudbase_title);
+ gaugeCloud.gauge.setUnitString(gaugeCloud.data.units);
+ if (data.ver) { gaugeCloud.update(); }
+ }
+ },
+
+ //
+ // return windrun units based on the windspeed units
+ //
+ getWindrunUnits = function (spdUnits) {
+ var retVal;
+ switch (spdUnits) {
+ case 'mph':
+ retVal = 'miles';
+ break;
+ case 'kts':
+ retVal = 'n_miles';
+ break;
+ case 'km/h':
+ // falls through
+ case 'm/s':
+ // falls through
+ default:
+ retVal = 'km';
+ break;
+ }
+ return retVal;
+ },
+
+ //
+ // performs a simple cloudbase calculation for those weather programs that don't supply it
+ //
+ calcCloudbase = function (temp, tempunit, dew, cloudbaseunit) {
+ var sprd = temp - dew;
+ var cb = sprd * (tempunit[1] === 'C' ? 400 : 227.3); // cloud base in feet
+ if (cloudbaseunit === 'm') {
+ cb = ft2m(cb);
+ }
+ return cb;
+ },
+
+ //
+ // create a shadow effect for the gauge using CSS
+ //
+ gaugeShadow = function (size) {
+ var offset = Math.floor(size * 0.015);
+ return {
+ 'box-shadow': offset + 'px ' + offset + 'px ' + offset + 'px ' + gaugeGlobals.shadowColour,
+ 'border-radius': Math.floor(size / 2) + 'px'
+ };
+ },
+
+ //
+ // generate a colour gradient based on start and end values
+ //
+ gradient = function (startCol, endCol, fraction) {
+ var redOrigin, grnOrigin, bluOrigin,
+ gradientSizeRed, gradientSizeGrn, gradientSizeBlu;
+
+ redOrigin = parseInt(startCol.substr(0, 2), 16);
+ grnOrigin = parseInt(startCol.substr(2, 2), 16);
+ bluOrigin = parseInt(startCol.substr(4, 2), 16);
+
+ gradientSizeRed = parseInt(endCol.substr(0, 2), 16) - redOrigin; // Graduation Size Red
+ gradientSizeGrn = parseInt(endCol.substr(2, 2), 16) - grnOrigin;
+ gradientSizeBlu = parseInt(endCol.substr(4, 2), 16) - bluOrigin;
+
+ return (redOrigin + (gradientSizeRed * fraction)).toFixed(0) + ',' +
+ (grnOrigin + (gradientSizeGrn * fraction)).toFixed(0) + ',' +
+ (bluOrigin + (gradientSizeBlu * fraction)).toFixed(0);
+ },
+ //
+ // returns the next highest number in the step sequence
+ //
+ nextHighest = function (value, step) {
+ return +value == 0 ? step : Math.ceil(+value / step) * step;
+ },
+ //
+ // returns the next lowest number in the step sequence
+ //
+ nextLowest = function (value, step) {
+ return +value == 0 ? -step : Math.floor(+value / step) * step;
+ };
+ // ########################################################
+ // End of gauges() var declarations
+ // ########################################################
+
+ //
+ // Execution starts here
+ //
+
+ // test for canvas support before we do anything else, especially reference steelseries which will cause the script to abort!
+ if (!document.createElement('canvas').getContext) {
+ // failed, no canvas support detected
+ $('body').html(strings.canvasnosupport);
+ setTimeout(function () {
+ window.location = config.oldGauges;
+ }, 3000);
+ return false;
+ } else {
+ //
+ // Called when the document object has loaded
+ // This starts the whole script.
+ //
+ $(document).ready(function () {
+ // Kick it all off - false for web page, true for dashboard
+ init(config.dashboardMode);
+ });
+ }
+
+ return {
+ setLang: setLang,
+ setUnits: setUnits,
+ processData: processData,
+ config: config,
+ init: init
+ };
+}());
+
+// ===============================================================================================================================
+// ===============================================================================================================================
+// ===============================================================================================================================
+
+/*!
+* Image w/ description tooltip v2.0 - For FF1+ IE6+ Opr8+
+* Created: April 23rd, 2010. This notice must stay intact for usage
+* Author: Dynamic Drive at http://www.dynamicdrive.com/
+* Visit http://www.dynamicdrive.com/ for full source code
+* Modified: M Crossley June 2011, January 2012
+* v2.-
+*/
+var ddimgtooltip;
+ddimgtooltip = {
+ tiparray: (function () {
+ var style = { background: '#FFFFFF', color: 'black', border: '2px ridge darkblue' },
+ i = 12, // set to number of tooltips required
+ tooltips = [];
+ for (; i--;) {
+ tooltips[i] = [null, ' ', style];
+ }
+ return tooltips;
+ }()),
+
+ tooltipoffsets: [20, -30], // additional x and y offset from mouse cursor for tooltips
+
+ tipDelay: 1000,
+
+ delayTimer: 0,
+
+ tipprefix: 'imgtip', // tooltip DOM ID prefixes
+
+ createtip: function ($, tipid, tipinfo) {
+ if ($('#' + tipid).length === 0) { // if this tooltip doesn't exist yet
+ return $('')
+ .html(
+ ((tipinfo[1]) ? '' + tipinfo[1] + '
' : '') +
+ (tipinfo[0] !== null ? '' : '')
+ )
+ .css(tipinfo[2] || {})
+ .appendTo(document.body);
+ }
+ return null;
+ },
+
+ positiontooltip: function ($, $tooltip, e) {
+ var x = e.pageX + this.tooltipoffsets[0],
+ y = e.pageY + this.tooltipoffsets[1],
+ tipw = $tooltip.outerWidth(),
+ tiph = $tooltip.outerHeight(),
+ wWidth = $(window).width(),
+ wHght = $(window).height(),
+ dTop = $(document).scrollTop();
+
+ x = (x + tipw > $(document).scrollLeft() + wWidth) ? x - tipw - (ddimgtooltip.tooltipoffsets[0] * 2) : x;
+ y = (y + tiph > dTop + wHght) ? dTop + wHght - tiph - 10 : y;
+ // last ditch attempt to keep the graphs 'on page'
+ x = Math.max(x, 0);
+ if (tipw >= wWidth) {
+ $($tooltip.attr('id') + '_img').css({ width: wWidth - 20 });
+ $('#' + $tooltip.attr('id') + '_img').css({ width: wWidth - 20 });
+ y = e.pageY + 5;
+ }
+ $tooltip.css({ left: x, top: y });
+ },
+
+ delaybox: function ($, $tooltip) {
+ if (this.showTips) {
+ ddimgtooltip.delayTimer = setTimeout(
+ function () {
+ ddimgtooltip.showbox($tooltip);
+ }, ddimgtooltip.tipDelay);
+ }
+ },
+
+ showbox: function (tooltip) {
+ if (this.showTips) {
+ // $(tooltip).show();
+ $(tooltip).fadeIn();
+ }
+ },
+
+ hidebox: function ($, $tooltip) {
+ clearTimeout(ddimgtooltip.delayTimer);
+ // $tooltip.hide();
+ $tooltip.fadeOut();
+ },
+
+ showTips: false,
+
+ init: function (targetselector) {
+ var tiparray = ddimgtooltip.tiparray,
+ $targets = $(targetselector);
+
+ if ($targets.length === 0) {
+ return;
+ }
+ $targets.each(function () {
+ var $target = $(this),
+ tipsuffix, tipid,
+ $tooltip;
+ var ind = ($target.attr('id').match(/_(\d+)/) || [])[1] || ''; // match d of attribute id='tip_d'
+ tipsuffix = parseInt(ind, 10); // get d as integer
+ tipid = this.tipid = ddimgtooltip.tipprefix + tipsuffix; // construct this tip's ID value and remember it
+ $tooltip = ddimgtooltip.createtip($, tipid, tiparray[tipsuffix]);
+
+ $target.mouseenter(function (e) {
+ var $tooltip = $('#' + this.tipid);
+ // ddimgtooltip.showbox($, $tooltip, e);
+ ddimgtooltip.delaybox($, $tooltip, e);
+ });
+ $target.mouseleave(function () {
+ var $tooltip = $('#' + this.tipid);
+ ddimgtooltip.hidebox($, $tooltip);
+ });
+ $target.mousemove(function (e) {
+ var $tooltip = $('#' + this.tipid);
+ ddimgtooltip.positiontooltip($, $tooltip, e);
+ });
+ if ($tooltip) { // add mouseenter to this tooltip (only if event hasn't already been added)
+ $tooltip.mouseenter(function () {
+ ddimgtooltip.hidebox($, $(this));
+ });
+ }
+ });
+ }
+};
+
+// if String doesn't offer a .trim() method, add it
+String.prototype.trim = String.prototype.trim || function trim() {
+ return this.replace(/^\s+|\s+$/g, '');
+};