Introduction

Feels Like is a concept often quoted in weather forecasts, as the name suggests it attempts to quantify what a human detects as the warming or cooling effect. A number of formulae are used, all involve the air temperature and at least one of the following:

  • (relative) humidity
  • wind (speed)
  • sunshine (radiation)

Look up Apparent_temperature, Heat_index, Humidex, or Wind_chill. Davis stations also provide THW index and THWS index

Web implementation

Ever thought that you want to display a 'Feels Like' temperature?

  1. Would you like to display Wind chill when it is cold and windy, Heat index when it is hot and humid, and Apparent temperature at other times?
  2. Do you understand how to call JavaScript code from HTML?
  3. Can you modify a Cascading Stylesheets (CSS) file to include new classes to define the appearance of various items?

If you can answer yes to all these questions, the following JavaScript code may be useful to you. Depending on the element id that it finds on your HTML page, it either inserts an appropriate 'Feels Like temperature' as a figure, or it draws up a temperature bar graph in the standard Cumulus style, but shows the current value for a parameter selected depending on the current conditions (although it also draws any maximum and/or minimum values of that parameter that are available).

If you can understand the standard Cumulus gaugesT.htm template, then you can use that as a starting point. You might want to modify that template page, or you might want to modify (or create) another template page.

You need to include something like the script that appears at the bottom of the standard gaugesT.htm in respect of defining temperature, humidity and wind speed:

HTML code to translate web tags to JavaScript variables (as modified for additional parameters)

This is needed on any web page if you want to use the new script.

<script>/* -------------------------------- Convert Cumulus tags into Javascript variables for selecting 'Feels Like' parameter------------------------------------- */
 var tempscale= "<#tempunitnodeg>"; // This is temperature unit, it contains F or C (without the HTML code for degree because JavaScript cannot understand it)
 var tempos = new Array("<#temp>","<#tempTL>","<#tempTH>","<#temptrendtext>","<#temptrendenglish>");/* OUTSIDE TEMPERATURE (current, today low, today high, trend description to display on mouseover, trend value to determine image to show) */
 var ExtraSensor1Name = ""; /* Extra temperature/humidity sensor one name prefix */
 var tempex1 = new Array("","","","");/* EXTRA TEMPERATURE ONE parameters		(required even if not used) */
 var ExtraSensor2Name = ""; /* Extra temperature/humidity sensor two name prefix */
 var tempex2 = new Array("","","","");/* EXTRA TEMPERATURE TWO parameters		(required even if not used) */
 var TempColor = ""; // If set defines the bar chart column colour for standard Cumulus charts like dewpoint
 var tempdp = new Array("<#dew>","<#dewpointTL>","<#dewpointTH>","","");/* DEW POINT (current, today low, today high) */
 var tempapp = new Array("<#apptemp>","<#apptempTL>","<#apptempTH>","","");/* APPARENT TEMPERATURE (current, today low, today high)*/
 var temphi = new Array("<#heatindex>","unavailable","<#heatindexTH>","","");/* HEAT INDEX (current, - , today high)  */
 var tempwc = new Array("<#wchill>","<#wchillTL>","unavailable","","");/* WIND CHILL (current, today low) */
 var tempis = new Array("not used","","","");/* INDOOR TEMPERATURE 		(not used by feels like routine) */
 var humos = new Array("<#hum>","<#humTL>","<#ThumTL>","<#humTH>", "<#ThumTH>");/* OUTSIDE HUMIDITY latest, minimum, time of minimum, maximum, time of maximum*/
// Wind histogram data (Modified from Cumulus original - needs more work as degree symbol giving warning messages on validation for HTML5)
 var winddata = new Array("<#wgust>","<#bearing>","<#wspeed>","<#avgbearing>","<#wgustTM>", "<#windunit>", "<#bearingTM>° at <#TwgustTM>");/* WIND SPEEDS (latest gust, its bearing, average wind speed, average bearing, maximum gust today, unit for wind speeds, bearing of maximum gust today with symbol for degrees, time of maximum gust) */
 </script>

HTML amendment to call new script

Supposing you stored the new script below in a file called "temperature.js" in the same directory as the calling html, then the HTML needs a call to the new script (insert just before the end of the HTML body) like this:

<script src="temperature.js"></script>
</body>

Defining HTML insert position

The HTML needs an element id for determining where the script inserts the Feels Like data.

Option 1 - Modifying a table to display a figure

 
set of values

The element id shown below would result in the numerical value being inserted as per screen image on left. Moving your mouse over the figure would display the information about the parameter being shown. This could be suitable for your 'now' page (the standard Cumulus indexT.htm displays wind chill, heat index and apparent temperature, but maybe you want to alter that? (Note this element id is not relevant to the gauges page, unless you want to display numerical values without a graphic).

HTML table rows to replace

<tr class="td_temperature_data">
    <td>Windchill</td>
    <td><#wchill> <#tempunit></td>
    <td>Humidity</td>
    <td><#hum>%</td>
  </tr>
  <tr class="td_temperature_data">
    <td>Heat Index</td>
    <td><#heatindex> <#tempunit></td>
    <td>Apparent Temperature</td>
    <td><#apptemp> <#tempunit></td>
  </tr>

HTML code required for inserting figure

<tr class="td_temperature_data"><td colspan="4" id="variable_figure" title="'Feels Like' - need to have JavaScript enabled for automatic selection of parameter to show here">
 					<small>Feels Like (title varies)</small> <br><!-- insert position for variable numerical value --></td></tr>

Option 2 - Modifying the Gauges page to display a different bar chart

Perhaps you use the standard gaugesT.htm template, but want to change it so it displays an appropriate Feels Like graphic (see screen shot)?

 
bar chart

Then you need to note the differences between the temperature and wind histogram data transfer shown above and that appearing at the foot of the standard Cumulus page. If you are able to cope with the necessary coding changes, you could replace the following code with the code that follows it (but there may be sizing issues to sort out).

HTML code for Inside Temperature can be replaced

<td width="33%" align="center" bgcolor="#EFEFEF"><div id="insidetemp">small</div></td>

HTML code required for varying chart

<td class="plots"><div id="feels_like"></div></td>

The class plots will need adding to the CSS, it could contain the width and align clauses that you removed or any other formatting you require.

New JavaScript Code required

This script introduces a number of new classes, to move styling that in the standard Cumulus dashboard.js is defined inside the script, out to an external CSS. For brevity, the list of new classes is not listed here, it is assumed you know enough to work out the list yourself, and you will probably want to use your own styling anyway.

/* ----------------------Apparent Temperature, Wind Chill or Heat Index-------------------*/
// --- variables required ---
var gauges_images=”dbimages”; // directory where temperature scale image is stored
var divid = new Array("outsidetemp","apptemp","dewpoint","heatindex","windchill","windchill/heatindex");var ddata = new Array(tempos, tempapp, tempdp, temphi, tempwc);var dColour = new Array("#c60","#f90","sienna","purple","cyan");var esn1 = "Extra Temperature 1";var esn2 = "Extra Temperature 2";if(ExtraSensor1Name) esn1 = ExtraSensor1Name + " Temperature";if(ExtraSensor2Name) esn2 = ExtraSensor2Name + " Temperature";var divti = new Array("Outside Temperature","Apparent Temperature",esn1,esn2,"Dew Point","Heat Index","Wind Chill");
var dtext =new Array("This routine automatically decides which parameter best represents the 'Feels Like' temperature by checking the maximum wind gust speed and the minimum and maximum temperature for this meteorological day.: These are used to pick between 'Wind Chill' (low minimum temperature, high wind gust), 'Heat Index' (high maximum temperature, ) and 'Apparent Temperature' (all other cases).",

"Apparent Temperature (AT) is displayed when minimum temperature is not low enough (or wind not strong enough) to show 'Wind Chill' and maximum temperature (and/or humidity) not high enough to show 'Heat Index'. The AT is defined (in Australia) as; the temperature, at the reference humidity level, producing the same amount of discomfort as that experienced under the current ambient temperature and humidity: The (Australian) Apparent Temperature (AT) is calculated from a formula combining measurements of air temperature (Ta), wind speed (ws) and relative humidity (rh).   AT = Ta + 0.33×rh / 100 × 6.105 × exp ( 17.27 × Ta / ( 237.7 + Ta ) ) - 1.57×ws - 4.0 Taking account of temperature, wind and humidity and using a dewpoint of 14°C as a reference comfort level makes this a better indication of what your body feels than the other measures listed, but strictly it only applies in the shade.",

"The (USA) Heat Index only applies if the actual temperature is at or above 27 °C (80 °F) and relative humidity peaks above 40% .: The index modifies air temperature using relative humidity in an attempt to determine the human-perceived equivalent temperature (how hot it feels).",

"Wind Chill Temperature only applies for temperatures at or below 10 °C (50 °F) and wind speeds above 3.0 mph (4.8 kilometres per hour, 1.34 metres per second, or 2.6 knots) (it is selected if the outdoor temperature today is or has fallen below 10.5, 51 respectively and today's maximum measured gust has exceeded quoted figure).: Wind Chill modifies air temperature using wind speed in an attempt to determine the exposed skin-perceived equivalent temperature (how cold it feels).");
//---------------------------------------------------------------
function dovariablebarchart(eidh){
var m, n, mo=[], tu = "°" + tempscale;
/*-- some javascript code that inserts 'Apparent Temperature' normally; but replaces that with 'Wind Chill' if minimum temperature is below 12 degrees Celsius, or replaces it with 'Heat Index' if maximum temperature is above 24 degrees Celsius */
/* are units Celsius or Fahrenheit? */
if(tempscale=="C"){ // Celsius
n= 10.5; // wind chill
m = 27; // heat index
}else{ // Fahrenheit
n = 51; // wind chill
m = 80; // heat index
}
var gust;
switch(winddata[5]){
case "mph" : gust=3.0; break;
case "km/h" : gust=4.8; break;
case "m/s" : gust= 1.34; break;
case "kts" : gust=2.6 ; break;
default : gust=0.0;
}
var motext = dtext[1];var modata = ddata[1];var selectid = divid[1];var selectColour = dColour[1];var tit=divti[1];// apparent is default plot
if((tempos[2] > m) && (humos[3] > 40)) { // check maximum
motext = dtext[2];modata = ddata[3];selectid = divid[3];selectColour = dColour[3];tit=divti[5]; //heat index plot
} else if ((tempos[1] <n) && (gust < winddata[4])) { // check minimum temp and maximum wind gust 
motext = dtext[3];modata = ddata[4];selectid = divid[4];selectColour = dColour[4];tit=divti[6]; // wind chill plot
}// end of if else group checking minimum and maximum temperatures
mo[0]=dtext[0];eidh.title ="header=["+'<img class="vam" src="'+gauges_images+'/information.png" alt=" graphic with little i representing information">'+"Feels Like ("+tu+")] body=["+getmo(mo)+"]";eidh.innerHTML += tit;// variable title written, check if summary page, if so appropriate figure is required and heading box requires a title
if(document.getElementById("variable_figure")){eidw=document.getElementById("variable_figure");n=modata[1];if(!isNaN(n)){ // check if minimum measurement is available
n =", "+"Min="+modata[1] + " °" + tempscale;} else {n="";}m=modata[2];if(!isNaN(m)){ // check if maximum measurement is available
m =", "+"Max="+modata[2] + " °" + tempscale;} else {m="";}eidw.innerHTML=("Latest="+modata[0] + " °" + tempscale+n+m);mo[0]=motext;eidw.title="header=["+'<img class="vam" src="'+gauges_images+'/information.png" alt=" graphic with little i representing information">'+tit+" ("+tu+")] body=["+getmo(mo)+"]";} // end of summary page coding
// rest of function only followed if bar chart to be drawn
if(document.getElementById("windchill/heatindex")){eidw=document.getElementById("windchill/heatindex");var size=eidw.innerHTMLdotemps(tit,selectid,eidw,size,modata, motext, selectColour);}} // end of function
//------------------------------------------------------------------------------
//variables for mouseover popup
var mod =0;//mouseover popup delay (msecs))
var fst = "position:relative; cursor:pointer; ";
var tds = "font-family: Verdana,Arial,Helvetica; font-size: 9px; color: #000055; "
//------------------------------------------------------------------------------
/* COMMON SUBROUTINE used by ALL CALLS FOR MOUSE OVER TEXT to create body table when using BOXOVER script */
function getmo(mot){
// Based on script included with Cumulus, but modified to use classes to refer to external Cascading Style Sheet instead of style attributes embedded in script – see comments that follow
var st = " ";
st += "<table class='b_green cmo'>"; // defines a background colour
for (var j=0;j<mot.length;j++){
st += "<tr><td class='labels'>"; // for example labels could be bold and have a background colour
st += mot[j].substring(0,mot[j].indexOf(":")+1); // Extract string up to colon into first cell of row
st += "</td><td class='site-data'>";// numbers are centered or whatever suits you
st += mot[j].substring(mot[j].indexOf(":")+1); // Extract string after colon into second cell of row
st += "</td></tr>";
}
st += "</table>";
return st;
}
/* ------------------------ ALL TEMPERATURE BASED BAR CHARTS ------------------ */
function dotemps(tit,id,eid,size,data, text, nowColour){
var tgd,factor, bottom, scale, maxm, t, h, l, r, tu, val, fst= "position:relative; cursor:pointer; ";
if(size=="small"){ 
tgd="<div id='"+id+"' style='"+fst+"width:90px;'><img 
src='”+gauges_images+”/thermos.gif''></div>”;
factor=2;
bottom=195;
}else{ 
tgd="<div id='"+id+"' style='"+fst+"width:90px;'><img src='”+gauges_images+”/thermol.gif'></div>";
factor=1;
bottom=375;
}
eid.parentNode.innerHTML=tgd;
eid=document.getElementById(id);
tu = "°" + tempscale;
if(tempscale=="C"){ // Celsius
scale=3.6/factor;
maxm=60;
}else{ // Fahrenheit
scale=2/factor;
maxm=140;
}
var valnow= parseFloat(data[0]);
t=parseInt(((maxm - valnow) * scale)+16);
h=(bottom-t)+1;// calculate length of column (origin is top left, so draw downwards)
l=25; // left hand end of horizontal lines for maximum
r=66; // right hand end of horizontal lines for minimum
// Other end of horizontal lines for maximum and minimum set at 45 - Modified so lines do not overlap and always show
var jg=new jsGraphics(id);
jg.setColor(nowColour || "#cc9"); // column fill colour taken from either calling code or default here
var mo = new Array()
var c = 0;
mo[c]=text; // descriptive text re observation or calculation
c++; // increment array index
if(!isNaN(t)){ // check if measurement is numerical
jg.fillEllipse(36,(bottom-16),20,20); // bulb of thermonmeter added by SFWS
jg.fillRect(41,t,9,h); // left and width of column plot are constants
mo[c]="<span class='sienna'>Current:</span>"+valnow+" "+tu; // semi-colon separates cells of table
} else mo[c]="Current temperature: Not Available"; // colon separates cells of table
c++;
if(data[1]){ // if minimum available
jg.setColor("navy");
jg.setStroke(2);
val= parseFloat(data[1]);
t=parseInt(((maxm - val)*scale)+16);
if(!isNaN(t))jg.drawLine(45,t,r,t);
mo[c]="<span class='navy'>Minimum This Meteorological Day:</span>"+val+" "+tu;
c++;
}
if(data[2]){ // if maximum available
jg.setColor("red");
jg.setStroke(2);
val=parseFloat(data[2]);
t=parseInt(((maxm - val)*scale)+16);
if(!isNaN(t))jg.drawLine(l,t,45,t);
mo[c]="<span class='red'>Maximum This Meteorological Day:</span>"+val+" "+tu;
c++;
if(tempscale=="C"){
val=Math.round((parseFloat(data[2])*1.8)+32)
mo[c]="<span class='red'>Maximum after conversion:</span>"+val+" "+"°" +"Farenheit";
c++;
}
}
if(data[3]){ // if trend available
jg.drawImage('gauges_images/'+data[4]+'.gif',41,8,9,29);// Modified (different rising/falling images and different position so trend visible at top!) data[4] is fixed text to determine filename
mo[c]="Trend:"+data[3];// data[3] uses text that can be set in 'samplestrings.ini'
}
jg.paint();
eid.title="header=["+'<img class="vam" src="'+gauges_images+'/information.png" alt=" graphic with little i representing information">'+tit+" ("+tu+")] body=["+getmo(mo)+"]";
}
/* -------------------------------------------------------------------------------------------
Note that the code works for all temperature and wind speed units permitted by Cumulus, 'variable_figure' is id for HTML where numbers to be written (perhaps on indexT.htm template page) and "feels_like" is id for HTML element where graphic to be drawn (normally on gaugesT.htm template page) 
------------------------------------------------------ */
// --- tabular display ---
if(document.getElementById("variable_figure")){
eidh=document.getElementById("variable_figure");
// call subroutine that determines which figures are to be displayed
dovariablebarchart(eidh)
}
// --- multipurpose bar chart ---
if(document.getElementById("feels_like")){
eidh=document.getElementById("feels_like");
// call subroutine that determines which bar chart is to be plotted
dovariablebarchart(eidh)
}

Sfws 18:53, 27 December 2012 (UTC)