2024-12-12 22:39:43 +00:00
/ * !
* 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://<URL>&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 = [
'<a href="https://cumuluswiki.wxforum.net/a/Software" target="_blank" rel="noopener">Cumulus</a>' ,
'<a href="//www.weather-display.com/" target="_blank" rel="noopener">Weather Display</a>' ,
'<a href="//www.ambientweather.com/virtualstation.html" target="_blank" rel="noopener">Virtual Weather Station</a>' ,
'<a href="//trixology.com/weathercat/" target="_blank" rel="noopener">WeatherCat</a>' ,
'<a href="//www.meteobridge.com/" target="_blank rel="noopener"">Meteobridge</a>' ,
'<a href="//www.wviewweather.com/" target="_blank" rel="noopener">Wview</a>' ,
'<a href="//www.weewx.com/" target="_blank" rel="noopener">weewx</a>' ,
'<a href="//weatherlink.com/" target="_blank" rel="noopener">Weatherlink.com</a>'
] ,
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 += '<br>' +
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 + ':' +
'<br>' +
'- ' + 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 + ':' +
'<br>' +
'- ' + 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 + ':' +
'<br>' +
'- ' + 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 + ':' +
'<br>' +
'- ' + 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 + ':' +
'<br>' +
'- ' + 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 + ':<br>' +
'- ' + 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 + ':' +
'<br>' +
'- ' + 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 + ':' +
'<br>' +
'- ' + 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 + ':' +
'<br>' +
'- ' + 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 += '<br>' +
'- ' + 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 + '<br>' +
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 + '<br>' + 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 += '<br>' + 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 + '<br>' +
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 = '<b>' + strings . uv _title + ': ' + cache . value + '</b> - <i>' + strings . solar _maxToday + ': ' + data . UVTH + '</i><br>' ;
tip += '<i>' + cache . headLine + '</i><br>' ;
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 = '<b>' + strings . solar _title + ': ' + cache . value + ' W/m²</b> - ' +
'<i>' + percent + '% ' + strings . solar _ofMax + '</i><br>' +
strings . solar _currentMax + ': ' + cache . currMaxValue + ' W/m²' ;
if ( typeof data . SolarTM !== 'undefined' ) {
tip += '<br>' + 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 ( '<strong>' + strings . cloudbase _popup _title + '</strong><br>' + 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 = $ ( '<div/>' ) . 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.25 mm / hr to 1.0 mm / 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 23 rd , 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 $ ( '<div id="' + tipid + '" class="ddimgtooltip" />' )
. html (
( ( tipinfo [ 1 ] ) ? '<div class="tipinfo" id="' + tipid + '_txt">' + tipinfo [ 1 ] + '</div>' : '' ) +
( tipinfo [ 0 ] !== null ? '<div style="text-align:center"><img class="tipimg" id="' + tipid +
'_img" src="' + tipinfo [ 0 ] + '" /></div>' : '' )
)
. 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 , '' ) ;
} ;