Added Extended Forecast, Daypart + general tweaks
This commit is contained in:
parent
99b802cc2a
commit
960ff44b72
|
@ -0,0 +1,231 @@
|
|||
function WeatherAudio() {
|
||||
|
||||
var musicarr = [],
|
||||
$players = $('<div id="players">'),
|
||||
that=this,
|
||||
mobilePlaying = false;
|
||||
|
||||
(function() {
|
||||
|
||||
$('body').append($players);
|
||||
|
||||
// start the music
|
||||
buildMusicArray(musicarr);
|
||||
shuffle(musicarr);
|
||||
|
||||
startPlaying(musicarr, true);
|
||||
|
||||
function buildMusicArray(arr) {
|
||||
|
||||
var musicpath = "music/";
|
||||
|
||||
// insert track names
|
||||
for (var i = 1; i<66; i++) {
|
||||
arr.push(musicpath + "Track " + String('0'+i).slice(-2) + '.mp3');
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
})();
|
||||
|
||||
|
||||
function startPlaying(arrPlayList, bLoop) {
|
||||
|
||||
|
||||
// only allow one set of players to be created
|
||||
var myclass = (bLoop ? 'music' : 'voice');
|
||||
if ($players.find('.' + myclass).length>0) {return}
|
||||
|
||||
var current=-1,
|
||||
len = arrPlayList.length,
|
||||
$player = initPlayer('p1'),
|
||||
$preloader = initPlayer('p2'),
|
||||
$myplayers = $players.find('.' + myclass);
|
||||
|
||||
// init the event to output ID3 track info if this is a music play
|
||||
if (myclass=='music') {
|
||||
$players.find('.music').bind($.jPlayer.event.play,
|
||||
function() { // event.jPlayer.status.media
|
||||
|
||||
if (that.playCallback) {
|
||||
|
||||
var mp3url = $(this).data('jPlayer').status.src,
|
||||
relativeUrl = mp3url.replace('%20',' ').slice(-arrPlayList[current].length);
|
||||
|
||||
// only trigger on current track, do not do on preload play/stop
|
||||
if (relativeUrl==arrPlayList[current]) {
|
||||
|
||||
ID3.loadTags(mp3url, function() {
|
||||
var tags = ID3.getAllTags(mp3url);
|
||||
that.playCallback(tags); //alert(tags.artist + " - " + tags.title + ", " + tags.album);
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
);
|
||||
} else {
|
||||
// duck the music if we're going to play a vocal
|
||||
$players.find('.music').jPlayer('volume', 0.30);
|
||||
}
|
||||
|
||||
// prime the preloader
|
||||
$preloader.jPlayer("setMedia", {mp3:arrPlayList[0]});
|
||||
|
||||
playNext();
|
||||
|
||||
|
||||
function playNext() {
|
||||
|
||||
current = nextIndex();
|
||||
|
||||
if (nextIndex()===null) {
|
||||
// nothing to preload so don't fire off a playNext after this play
|
||||
$preloader.unbind($.jPlayer.event.ended);
|
||||
$preloader.bind($.jPlayer.event.ended,
|
||||
function() {
|
||||
$players.find('.music').jPlayer('volume', 0.80); // bring music volume back up
|
||||
$player.remove();
|
||||
$preloader.remove();
|
||||
}
|
||||
);
|
||||
swapAndPlay();
|
||||
} else {
|
||||
swapAndPlay();
|
||||
|
||||
// preload the next track
|
||||
function doPreload(trackname) {
|
||||
try {
|
||||
$preloader.jPlayer("setMedia", {mp3:arrPlayList[nextIndex()]}).jPlayer("play").jPlayer("stop");
|
||||
} catch(e) {
|
||||
setTimeout( function() {doPreload(trackname)}, 500);
|
||||
}
|
||||
}
|
||||
doPreload( arrPlayList[nextIndex()] );
|
||||
|
||||
}
|
||||
|
||||
function nextIndex() {
|
||||
var nextI = current+1;
|
||||
if (nextI<len) {
|
||||
return nextI;
|
||||
} else {
|
||||
return (bLoop ? 0 : null);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
function initPlayer(id){
|
||||
var $div;
|
||||
$div = $('<div id=' + id + ' class="jplayer ' + myclass + '">');
|
||||
$div.jPlayer({
|
||||
swfPath: document.baseURI + "jplayer",
|
||||
preload: 'auto',
|
||||
ended: playNext
|
||||
});
|
||||
$players.append($div);
|
||||
return $div;
|
||||
}
|
||||
|
||||
|
||||
|
||||
function swapAndPlay() {
|
||||
// who would think swapping two vars would be so hard?
|
||||
var $temp1 = $player,
|
||||
$temp2 = $preloader;
|
||||
$player = null; $preloader = null;
|
||||
$player=$temp2; $preloader=$temp1;
|
||||
|
||||
$player.jPlayer("play");
|
||||
|
||||
$(document).mousedown( function() {
|
||||
if (!mobilePlaying) {
|
||||
$player.jPlayer("play");
|
||||
mobilePlaying = true;
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
// click for debugging or whater you want
|
||||
$('body').on('click', function(){
|
||||
//$player.jPlayer("playHead", 100);
|
||||
//getWeatherbyLocation();
|
||||
});
|
||||
|
||||
|
||||
this.playCallback = {};
|
||||
|
||||
|
||||
// plays the vocal current conditions announcement
|
||||
this.playCurrentConditions = function (currentConditions) {
|
||||
|
||||
var array2play = ['CC_INTRO' + (Math.floor(Math.random()*2)+1), currentConditions.temp.replace('-', 'M')],
|
||||
condfile = mapCurrentConditions(currentConditions.code);
|
||||
|
||||
if (condfile) { array2play.push(condfile); }
|
||||
|
||||
$.each(array2play, function(i,v){
|
||||
array2play[i] = '/localvocals/' + v + '.mp3';
|
||||
});
|
||||
|
||||
startPlaying(array2play, false);
|
||||
|
||||
function mapCurrentConditions(ccCode){
|
||||
return "CC" + {0:"422",1:"EF300",2:"EF300",3:"422",4:"400",5:"500",6:"600",7:"700",8:"800",9:"901",10:"1000",11:"1100",12:"2680",13:"1601",14:"1312",15:"1500",16:"1600",17:"1730",18:"1800",19:"1939",20:"2000",21:"2000",22:"2200",23:"2410",24:"2410",26:"2600",27:"2700",28:"2700",29:"2900",30:"2900",31:"3100",32:"3200",33:"3400",34:"3400",35:"1730",37:"429",38:"429",39:"429",40:"2680",41:"1402",42:"1312",43:"1402",44:"2900",45:"1100",46:"1312",47:"EF3900"}[ccCode];
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
this.playLocalRadar = function() {
|
||||
startPlaying(['/localvocals/RADAR.mp3'], false);
|
||||
}
|
||||
|
||||
|
||||
|
||||
}
|
||||
var weatherAudio = new WeatherAudio();
|
||||
|
||||
//ID3 Reader
|
||||
//https://github.com/aadsm/JavaScript-ID3-Reader
|
||||
(function(A){if("object"===typeof exports&&"undefined"!==typeof module)module.f=A();else if("function"===typeof define&&define.M)define([],A);else{var g;"undefined"!==typeof window?g=window:"undefined"!==typeof global?g=global:"undefined"!==typeof self?g=self:g=this;g.ID3=A()}})(function(){return function g(l,h,f){function c(b,d){if(!h[b]){if(!l[b]){var e="function"==typeof require&&require;if(!d&&e)return e(b,!0);if(a)return a(b,!0);e=Error("Cannot find module '"+b+"'");throw e.code="MODULE_NOT_FOUND",
|
||||
e;}e=h[b]={f:{}};l[b][0].call(e.f,function(a){var e=l[b][1][a];return c(e?e:a)},e,e.f,g,l,h,f)}return h[b].f}for(var a="function"==typeof require&&require,b=0;b<f.length;b++)c(f[b]);return c}({1:[function(g,l){var h=g("./stringutils");if("undefined"!==typeof document){var f=document.createElement("script");f.type="text/vbscript";f.textContent="Function IEBinary_getByteAt(strBinary, iOffset)\r\n\tIEBinary_getByteAt = AscB(MidB(strBinary,iOffset+1,1))\r\nEnd Function\r\nFunction IEBinary_getLength(strBinary)\r\n\tIEBinary_getLength = LenB(strBinary)\r\nEnd Function\r\n";
|
||||
document.getElementsByTagName("head")[0].appendChild(f)}else g("btoa"),g("atob");l.f=function(c,a,b){var m=a||0,d=0;"string"==typeof c?(d=b||c.length,this.a=function(a){return c.charCodeAt(a+m)&255}):"unknown"==typeof c&&(d=b||IEBinary_getLength(c),this.a=function(a){return IEBinary_getByteAt(c,a+m)});this.s=function(a,b){for(var d=Array(b),m=0;m<b;m++)d[m]=this.a(a+m);return d};this.l=function(){return d};this.g=function(a,b){return 0!=(this.a(a)&1<<b)};this.F=function(a){a=(this.a(a+1)<<8)+this.a(a);
|
||||
0>a&&(a+=65536);return a};this.m=function(a){var b=this.a(a),d=this.a(a+1),m=this.a(a+2);a=this.a(a+3);b=(((b<<8)+d<<8)+m<<8)+a;0>b&&(b+=4294967296);return b};this.w=function(a){var b=this.a(a),d=this.a(a+1);a=this.a(a+2);b=((b<<8)+d<<8)+a;0>b&&(b+=16777216);return b};this.c=function(a,b){for(var d=[],m=a,c=0;m<a+b;m++,c++)d[c]=String.fromCharCode(this.a(m));return d.join("")};this.h=function(a,b,d){a=this.s(a,b);switch(d.toLowerCase()){case "utf-16":case "utf-16le":case "utf-16be":d=h.J(a,d);break;
|
||||
case "utf-8":d=h.K(a);break;default:d=h.I(a)}return d};this.i=function(a,b){b()}}},{"./stringutils":9,atob:void 0,btoa:void 0}],2:[function(g,l){var h=g("./binaryfile");l.f=function(f,c,a){function b(a,b,d,e,c,f){var k=m();k?("undefined"===typeof f&&(f=!0),b&&("undefined"!=typeof k.onload?(k.onload=function(){"200"==k.status||"206"==k.status?(k.fileSize=c||k.getResponseHeader("Content-Length"),b(k)):d&&d({error:"xhr",xhr:k});k=null},d&&(k.onerror=function(){d({error:"xhr",xhr:k});k=null})):k.onreadystatechange=
|
||||
function(){4==k.readyState&&("200"==k.status||"206"==k.status?(k.fileSize=c||k.getResponseHeader("Content-Length"),b(k)):d&&d({error:"xhr",xhr:k}),k=null)}),k.open("GET",a,f),k.overrideMimeType&&k.overrideMimeType("text/plain; charset=x-user-defined"),e&&k.setRequestHeader("Range","bytes="+e[0]+"-"+e[1]),k.setRequestHeader("If-Modified-Since","Sat, 01 Jan 1970 00:00:00 GMT"),k.send(null)):d&&d({error:"Unable to create XHR object"})}function m(){var a=null;"undefined"===typeof window?a=new (g("xmlhttprequest").XMLHttpRequest):
|
||||
window.XMLHttpRequest?a=new window.XMLHttpRequest:window.ActiveXObject&&(a=new window.ActiveXObject("Microsoft.XMLHTTP"));return a}function d(a,b,d){var e=m();e?(b&&("undefined"!=typeof e.onload?(e.onload=function(){"200"==e.status||"206"==e.status?b(this):d&&d({error:"xhr",xhr:e});e=null},d&&(e.onerror=function(){d({error:"xhr",xhr:e});e=null})):e.onreadystatechange=function(){4==e.readyState&&("200"==e.status||"206"==e.status?b(this):d&&d({error:"xhr",xhr:e}),e=null)}),e.open("HEAD",a,!0),e.send(null)):
|
||||
d&&d({error:"Unable to create XHR object"})}function e(d,e){var m,c;function f(a){var b=~~(a[0]/m)-c;a=~~(a[1]/m)+1+c;0>b&&(b=0);a>=blockTotal&&(a=blockTotal-1);return[b,a]}function g(c,f){for(;n[c[0]];)if(c[0]++,c[0]>c[1]){f&&f();return}for(;n[c[1]];)if(c[1]--,c[0]>c[1]){f&&f();return}var h=[c[0]*m,(c[1]+1)*m-1];b(d,function(a){parseInt(a.getResponseHeader("Content-Length"),10)==e&&(c[0]=0,c[1]=blockTotal-1,h[0]=0,h[1]=e-1);a={data:a.W||a.responseText,offset:h[0]};for(var b=c[0];b<=c[1];b++)n[b]=
|
||||
a;f&&f()},a,h,k,!!f)}var k,l=new h("",0,e),n=[];m=m||2048;c="undefined"===typeof c?0:c;blockTotal=~~((e-1)/m)+1;for(var p in l)l.hasOwnProperty(p)&&"function"===typeof l[p]&&(this[p]=l[p]);this.a=function(a){var b;g(f([a,a]));return(b=n[~~(a/m)])&&"string"==typeof b.data?b.data.charCodeAt(a-b.offset)&255:b&&"unknown"==typeof b.data?IEBinary_getByteAt(b.data,a-b.offset):""};this.i=function(a,b){g(f(a),b)}}(function(){d(f,function(a){a=parseInt(a.getResponseHeader("Content-Length"),10)||-1;c(new e(f,
|
||||
a))},a)})()}},{"./binaryfile":1,xmlhttprequest:void 0}],3:[function(g,l){var h=g("./binaryfile");l.f=function(f,c){return function(a,b){var m=c||new FileReader;m.onload=function(a){b(new h(a.target.result))};m.readAsBinaryString(f)}}},{"./binaryfile":1}],4:[function(g,l){function h(b){return"ftypM4A"==b.c(4,7)?f:"ID3"==b.c(0,3)?a:c}var f=g("./id4"),c=g("./id3v1"),a=g("./id3v2"),b=g("./bufferedbinaryajax"),m=g("./filereader");"undefined"!==typeof window&&(window.FileAPIReader=m);var d={},e={},r=[0,
|
||||
7];d.B=function(a){delete e[a]};d.A=function(){e={}};d.H=function(a,d,c){c=c||{};(c.dataReader||b)(a,function(b){b.i(r,function(){var m=h(b);m.u(b,function(){var f=c.tags,h=m.v(b,f),f=e[a]||{},r;for(r in h)h.hasOwnProperty(r)&&(f[r]=h[r]);e[a]=f;d&&d()})})},c.onError)};d.D=function(a){if(!e[a])return null;var b={},d;for(d in e[a])e[a].hasOwnProperty(d)&&(b[d]=e[a][d]);return b};d.G=function(a,b){return e[a]?e[a][b]:null};d.FileAPIReader=m;d.loadTags=d.H;d.getAllTags=d.D;d.getTag=d.G;d.clearTags=d.B;
|
||||
d.clearAll=d.A;l.f=d},{"./bufferedbinaryajax":2,"./filereader":3,"./id3v1":5,"./id3v2":6,"./id4":8}],5:[function(g,l){var h={},f="Blues;Classic Rock;Country;Dance;Disco;Funk;Grunge;Hip-Hop;Jazz;Metal;New Age;Oldies;Other;Pop;R&B;Rap;Reggae;Rock;Techno;Industrial;Alternative;Ska;Death Metal;Pranks;Soundtrack;Euro-Techno;Ambient;Trip-Hop;Vocal;Jazz+Funk;Fusion;Trance;Classical;Instrumental;Acid;House;Game;Sound Clip;Gospel;Noise;AlternRock;Bass;Soul;Punk;Space;Meditative;Instrumental Pop;Instrumental Rock;Ethnic;Gothic;Darkwave;Techno-Industrial;Electronic;Pop-Folk;Eurodance;Dream;Southern Rock;Comedy;Cult;Gangsta;Top 40;Christian Rap;Pop/Funk;Jungle;Native American;Cabaret;New Wave;Psychadelic;Rave;Showtunes;Trailer;Lo-Fi;Tribal;Acid Punk;Acid Jazz;Polka;Retro;Musical;Rock & Roll;Hard Rock;Folk;Folk-Rock;National Folk;Swing;Fast Fusion;Bebob;Latin;Revival;Celtic;Bluegrass;Avantgarde;Gothic Rock;Progressive Rock;Psychedelic Rock;Symphonic Rock;Slow Rock;Big Band;Chorus;Easy Listening;Acoustic;Humour;Speech;Chanson;Opera;Chamber Music;Sonata;Symphony;Booty Bass;Primus;Porn Groove;Satire;Slow Jam;Club;Tango;Samba;Folklore;Ballad;Power Ballad;Rhythmic Soul;Freestyle;Duet;Punk Rock;Drum Solo;Acapella;Euro-House;Dance Hall".split(";");
|
||||
h.u=function(c,a){var b=c.l();c.i([b-128-1,b],a)};h.v=function(c){var a=c.l()-128;if("TAG"==c.c(a,3)){var b=c.c(a+3,30).replace(/\0/g,""),m=c.c(a+33,30).replace(/\0/g,""),d=c.c(a+63,30).replace(/\0/g,""),e=c.c(a+93,4).replace(/\0/g,"");if(0==c.a(a+97+28))var h=c.c(a+97,28).replace(/\0/g,""),g=c.a(a+97+29);else h="",g=0;c=c.a(a+97+30);return{version:"1.1",title:b,artist:m,album:d,year:e,comment:h,track:g,genre:255>c?f[c]:""}}return{}};l.f=h},{}],6:[function(g,l){function h(a,c){var d=c.a(a),e=c.a(a+
|
||||
1),f=c.a(a+2);return c.a(a+3)&127|(f&127)<<7|(e&127)<<14|(d&127)<<21}var f=g("./id3v2frames");f.frames={BUF:"Recommended buffer size",CNT:"Play counter",COM:"Comments",CRA:"Audio encryption",CRM:"Encrypted meta frame",ETC:"Event timing codes",EQU:"Equalization",GEO:"General encapsulated object",IPL:"Involved people list",LNK:"Linked information",MCI:"Music CD Identifier",MLL:"MPEG location lookup table",PIC:"Attached picture",POP:"Popularimeter",REV:"Reverb",RVA:"Relative volume adjustment",SLT:"Synchronized lyric/text",
|
||||
STC:"Synced tempo codes",TAL:"Album/Movie/Show title",TBP:"BPM (Beats Per Minute)",TCM:"Composer",TCO:"Content type",TCR:"Copyright message",TDA:"Date",TDY:"Playlist delay",TEN:"Encoded by",TFT:"File type",TIM:"Time",TKE:"Initial key",TLA:"Language(s)",TLE:"Length",TMT:"Media type",TOA:"Original artist(s)/performer(s)",TOF:"Original filename",TOL:"Original Lyricist(s)/text writer(s)",TOR:"Original release year",TOT:"Original album/Movie/Show title",TP1:"Lead artist(s)/Lead performer(s)/Soloist(s)/Performing group",
|
||||
TP2:"Band/Orchestra/Accompaniment",TP3:"Conductor/Performer refinement",TP4:"Interpreted, remixed, or otherwise modified by",TPA:"Part of a set",TPB:"Publisher",TRC:"ISRC (International Standard Recording Code)",TRD:"Recording dates",TRK:"Track number/Position in set",TSI:"Size",TSS:"Software/hardware and settings used for encoding",TT1:"Content group description",TT2:"Title/Songname/Content description",TT3:"Subtitle/Description refinement",TXT:"Lyricist/text writer",TXX:"User defined text information frame",
|
||||
TYE:"Year",UFI:"Unique file identifier",ULT:"Unsychronized lyric/text transcription",WAF:"Official audio file webpage",WAR:"Official artist/performer webpage",WAS:"Official audio source webpage",WCM:"Commercial information",WCP:"Copyright/Legal information",WPB:"Publishers official webpage",WXX:"User defined URL link frame",AENC:"Audio encryption",APIC:"Attached picture",COMM:"Comments",COMR:"Commercial frame",ENCR:"Encryption method registration",EQUA:"Equalization",ETCO:"Event timing codes",GEOB:"General encapsulated object",
|
||||
GRID:"Group identification registration",IPLS:"Involved people list",LINK:"Linked information",MCDI:"Music CD identifier",MLLT:"MPEG location lookup table",OWNE:"Ownership frame",PRIV:"Private frame",PCNT:"Play counter",POPM:"Popularimeter",POSS:"Position synchronisation frame",RBUF:"Recommended buffer size",RVAD:"Relative volume adjustment",RVRB:"Reverb",SYLT:"Synchronized lyric/text",SYTC:"Synchronized tempo codes",TALB:"Album/Movie/Show title",TBPM:"BPM (beats per minute)",TCOM:"Composer",TCON:"Content type",
|
||||
TCOP:"Copyright message",TDAT:"Date",TDLY:"Playlist delay",TENC:"Encoded by",TEXT:"Lyricist/Text writer",TFLT:"File type",TIME:"Time",TIT1:"Content group description",TIT2:"Title/songname/content description",TIT3:"Subtitle/Description refinement",TKEY:"Initial key",TLAN:"Language(s)",TLEN:"Length",TMED:"Media type",TOAL:"Original album/movie/show title",TOFN:"Original filename",TOLY:"Original lyricist(s)/text writer(s)",TOPE:"Original artist(s)/performer(s)",TORY:"Original release year",TOWN:"File owner/licensee",
|
||||
TPE1:"Lead performer(s)/Soloist(s)",TPE2:"Band/orchestra/accompaniment",TPE3:"Conductor/performer refinement",TPE4:"Interpreted, remixed, or otherwise modified by",TPOS:"Part of a set",TPUB:"Publisher",TRCK:"Track number/Position in set",TRDA:"Recording dates",TRSN:"Internet radio station name",TRSO:"Internet radio station owner",TSIZ:"Size",TSRC:"ISRC (international standard recording code)",TSSE:"Software/Hardware and settings used for encoding",TYER:"Year",TXXX:"User defined text information frame",
|
||||
UFID:"Unique file identifier",USER:"Terms of use",USLT:"Unsychronized lyric/text transcription",WCOM:"Commercial information",WCOP:"Copyright/Legal information",WOAF:"Official audio file webpage",WOAR:"Official artist/performer webpage",WOAS:"Official audio source webpage",WORS:"Official internet radio station homepage",WPAY:"Payment",WPUB:"Publishers official webpage",WXXX:"User defined URL link frame"};var c={title:["TIT2","TT2"],artist:["TPE1","TP1"],album:["TALB","TAL"],year:["TYER","TYE"],comment:["COMM",
|
||||
"COM"],track:["TRCK","TRK"],genre:["TCON","TCO"],picture:["APIC","PIC"],lyrics:["USLT","ULT"]},a=["title","artist","album","track"];f.u=function(a,c){a.i([0,h(6,a)],c)};f.v=function(b,m){var d=0,e=b.a(d+3);if(4<e)return{version:">2.4"};var r=b.a(d+4),g=b.g(d+5,7),l=b.g(d+5,6),w=b.g(d+5,5),x=h(d+6,b),d=d+10;if(l)var q=b.m(d),d=d+(q+4);var e={version:"2."+e+"."+r,major:e,revision:r,flags:{unsynchronisation:g,extended_header:l,experimental_indicator:w},size:x},k;if(g)k={};else{for(var x=x-10,g=b,r=m,
|
||||
l={},w=e.major,q=[],u=0,n;n=(r||a)[u];u++)q=q.concat(c[n]||[n]);for(r=q;d<x;){q=null;u=g;n=d;var p=null;switch(w){case 2:k=u.c(n,3);var t=u.w(n+3),z=6;break;case 3:k=u.c(n,4);t=u.m(n+4);z=10;break;case 4:k=u.c(n,4),t=h(n+4,u),z=10}if(""==k)break;d+=z+t;if(!(0>r.indexOf(k))){if(2<w)var p=u,y=n+8,p={message:{Y:p.g(y,6),R:p.g(y,5),V:p.g(y,4)},format:{T:p.g(y+1,7),N:p.g(y+1,3),P:p.g(y+1,2),L:p.g(y+1,1),C:p.g(y+1,0)}};n+=z;p&&p.format.C&&(h(n,u),n+=4,t-=4);p&&p.format.L||(k in f.b?q=f.b[k]:"T"==k[0]&&
|
||||
(q=f.b["T*"]),q=q?q(n,t,u,p):void 0,q={id:k,size:t,description:k in f.frames?f.frames[k]:"Unknown",data:q},k in l?(l[k].id&&(l[k]=[l[k]]),l[k].push(q)):l[k]=q)}}k=l}for(var B in c)if(c.hasOwnProperty(B)){a:{t=c[B];"string"==typeof t&&(t=[t]);z=0;for(d=void 0;d=t[z];z++)if(d in k){b=k[d].data;break a}b=void 0}b&&(e[B]=b)}for(var C in k)k.hasOwnProperty(C)&&(e[C]=k[C]);return e};l.f=f},{"./id3v2frames":7}],7:[function(g,l){function h(a){var b;switch(a){case 0:b="iso-8859-1";break;case 1:b="utf-16";
|
||||
break;case 2:b="utf-16be";break;case 3:b="utf-8"}return b}var f={b:{}},c="32x32 pixels 'file icon' (PNG only);Other file icon;Cover (front);Cover (back);Leaflet page;Media (e.g. lable side of CD);Lead artist/lead performer/soloist;Artist/performer;Conductor;Band/Orchestra;Composer;Lyricist/text writer;Recording Location;During recording;During performance;Movie/video screen capture;A bright coloured fish;Illustration;Band/artist logotype;Publisher/Studio logotype".split(";");f.b.APIC=function(a,b,
|
||||
m,d,e){e=e||"3";d=a;var f=h(m.a(a));switch(e){case "2":var g=m.c(a+1,3);a+=4;break;case "3":case "4":g=m.h(a+1,b-(a-d),""),a+=1+g.j}e=m.a(a,1);e=c[e];f=m.h(a+1,b-(a-d),f);a+=1+f.j;return{format:g.toString(),type:e,description:f.toString(),data:m.s(a,d+b-a)}};f.b.COMM=function(a,b,c){var d=a,e=h(c.a(a)),f=c.c(a+1,3),g=c.h(a+4,b-4,e);a+=4+g.j;a=c.h(a,d+b-a,e);return{language:f,X:g.toString(),text:a.toString()}};f.b.COM=f.b.COMM;f.b.PIC=function(a,b,c,d){return f.b.APIC(a,b,c,d,"2")};f.b.PCNT=function(a,
|
||||
b,c){return c.S(a)};f.b.CNT=f.b.PCNT;f.b["T*"]=function(a,b,c){var d=h(c.a(a));return c.h(a+1,b-1,d).toString()};f.b.TCON=function(a,b,c){return f.b["T*"].apply(this,arguments).replace(/^\(\d+\)/,"")};f.b.TCO=f.b.TCON;f.b.USLT=function(a,b,c){var d=a,e=h(c.a(a)),f=c.c(a+1,3),g=c.h(a+4,b-4,e);a+=4+g.j;a=c.h(a,d+b-a,e);return{language:f,O:g.toString(),U:a.toString()}};f.b.ULT=f.b.USLT;l.f=f},{}],8:[function(g,l){function h(a,b,f,d){var e=a.m(b);if(0==e)d();else{var g=a.c(b+4,4);-1<["moov","udta","meta",
|
||||
"ilst"].indexOf(g)?("meta"==g&&(b+=4),a.i([b+8,b+8+8],function(){h(a,b+8,e-8,d)})):a.i([b+(g in c.o?0:e),b+e+8],function(){h(a,b+e,f,d)})}}function f(a,b,h,d,e){e=void 0===e?"":e+" ";for(var g=h;g<h+d;){var l=b.m(g);if(0==l)break;var v=b.c(g+4,4);if(-1<["moov","udta","meta","ilst"].indexOf(v)){"meta"==v&&(g+=4);f(a,b,g+8,l-8,e);break}if(c.o[v]){var w=b.w(g+16+1),x=c.o[v],w=c.types[w];if("trkn"==v)a[x[0]]=b.a(g+16+11),a.count=b.a(g+16+13);else{var v=g+16+4+4,q=l-16-4-4,k;switch(w){case "text":k=b.h(v,
|
||||
q,"UTF-8");break;case "uint8":k=b.F(v);break;case "jpeg":case "png":k={format:"image/"+w,data:b.s(v,q)}}a[x[0]]="comment"===x[0]?{text:k}:k}}g+=l}}var c={types:{0:"uint8",1:"text",13:"jpeg",14:"png",21:"uint8"},o:{"\u00a9alb":["album"],"\u00a9art":["artist"],"\u00a9ART":["artist"],aART:["artist"],"\u00a9day":["year"],"\u00a9nam":["title"],"\u00a9gen":["genre"],trkn:["track"],"\u00a9wrt":["composer"],"\u00a9too":["encoder"],cprt:["copyright"],covr:["picture"],"\u00a9grp":["grouping"],keyw:["keyword"],
|
||||
"\u00a9lyr":["lyrics"],"\u00a9cmt":["comment"],tmpo:["tempo"],cpil:["compilation"],disk:["disc"]},u:function(a,b){a.i([0,7],function(){h(a,0,a.l(),b)})},v:function(a){var b={};f(b,a,0,a.l());return b}};l.f=c},{}],9:[function(g,l){l.f={J:function(h,f,c){var a=0,b=1,g=0;c=Math.min(c||h.length,h.length);254==h[0]&&255==h[1]?(f=!0,a=2):255==h[0]&&254==h[1]&&(f=!1,a=2);f&&(b=0,g=1);f=[];for(var d=0;a<c;d++){var e=h[a+b],l=(e<<8)+h[a+g],a=a+2;if(0==l)break;else 216>e||224<=e?f[d]=String.fromCharCode(l):
|
||||
(e=(h[a+b]<<8)+h[a+g],a+=2,f[d]=String.fromCharCode(l,e))}h=new String(f.join(""));h.j=a;return h},K:function(h,f){var c=0;f=Math.min(f||h.length,h.length);239==h[0]&&187==h[1]&&191==h[2]&&(c=3);for(var a=[],b=0;c<f;b++){var g=h[c++];if(0==g)break;else if(128>g)a[b]=String.fromCharCode(g);else if(194<=g&&224>g){var d=h[c++];a[b]=String.fromCharCode(((g&31)<<6)+(d&63))}else if(224<=g&&240>g){var d=h[c++],e=h[c++];a[b]=String.fromCharCode(((g&255)<<12)+((d&63)<<6)+(e&63))}else if(240<=g&&245>g){var d=
|
||||
h[c++],e=h[c++],l=h[c++],g=((g&7)<<18)+((d&63)<<12)+((e&63)<<6)+(l&63)-65536;a[b]=String.fromCharCode((g>>10)+55296,(g&1023)+56320)}}a=new String(a.join(""));a.j=c;return a},I:function(g,f){var c=[];f=f||g.length;for(var a=0;a<f;){var b=g[a++];if(0==b)break;c[a-1]=String.fromCharCode(b)}c=new String(c.join(""));c.j=a;return c}}},{}]},{},[4])(4)});
|
|
@ -0,0 +1,114 @@
|
|||
function DataManager(pointSearch){
|
||||
var $this = $(this),
|
||||
that = this,
|
||||
excludeRadiusMiles=5;
|
||||
includeRadiusMiles=50;
|
||||
|
||||
var _locations = [];
|
||||
|
||||
this.locations = _locations;
|
||||
|
||||
this.location = function(woeid) {
|
||||
return _locations.find(x => x.woeid === woeid);
|
||||
}
|
||||
|
||||
this.init = function (searchString) {
|
||||
_locations[0] = new Location();
|
||||
|
||||
$(_locations[0])
|
||||
|
||||
.on('refresh', function(){ $this.trigger('refresh') })
|
||||
.on('ready', function(){
|
||||
$this.trigger('ready:main');
|
||||
})
|
||||
.on('init', initLocations);
|
||||
_locations[0].first = true;
|
||||
_locations[0].init(searchString);
|
||||
|
||||
};
|
||||
|
||||
// kicks off after main location is returned.
|
||||
// create the list of neighboring cities
|
||||
function initLocations(){
|
||||
|
||||
// find reporting stations
|
||||
var observationData = _locations[0].observations(0),
|
||||
lat = observationData.lat,
|
||||
lon = observationData.lon,
|
||||
locList = [];
|
||||
|
||||
// begin the forcast pull
|
||||
_locations[0].initForecasts();
|
||||
|
||||
// get a list of observation stations info
|
||||
$.getJSON('https://api.weather.gov/points/' + lat + ',' + lon + '/stations', function(data) {
|
||||
|
||||
var feature, geo, station, dist;
|
||||
for (var i=0; i < data.features.length; i++) {
|
||||
|
||||
feature = data.features[i];
|
||||
geo = feature.geometry.coordinates;
|
||||
dist = distance(lat, lon, geo[1], geo[0]);
|
||||
|
||||
if (dist < includeRadiusMiles && dist > excludeRadiusMiles) {
|
||||
locList.push({lat: geo[1], long:geo[0], distance:dist, stationUrl:feature.id});
|
||||
}
|
||||
}
|
||||
|
||||
if (locList.length===0) {
|
||||
$this.trigger('allinit');
|
||||
return
|
||||
}
|
||||
|
||||
// sort list by distance
|
||||
locList.sort(function(a, b) {
|
||||
return parseInt(a.distance) - parseInt(b.distance);
|
||||
});
|
||||
|
||||
// set the station for location 0
|
||||
_locations[0].stationUrl = locList[0].stationUrl
|
||||
_locations[0].initNWSObservations();
|
||||
|
||||
// create location objects, get inital pull
|
||||
for(var loc of locList) {
|
||||
loc.location = new Location();
|
||||
$(loc.location).on('init',onLocationInit);
|
||||
loc.location.init(loc.lat+','+loc.long);
|
||||
loc.location.stationUrl = loc.stationUrl;
|
||||
}
|
||||
|
||||
});
|
||||
|
||||
var initCount=0;
|
||||
function onLocationInit() {
|
||||
initCount++;
|
||||
if (initCount===locList.length) {
|
||||
allLocationsInit();
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
function allLocationsInit() {
|
||||
|
||||
var location, cities=[], city;
|
||||
|
||||
// add locations removing any duplicate cities by name
|
||||
for(var loc of locList) {
|
||||
|
||||
if (_locations.filter(e => e.city == loc.location.city).length === 0) {
|
||||
_locations.push(loc.location);
|
||||
loc.location.initForecasts();
|
||||
loc.location.initNWSObservations();
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
$this.trigger('allinit');
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
}
|
File diff suppressed because one or more lines are too long
|
@ -0,0 +1,75 @@
|
|||
function GroupDataManager() {
|
||||
var locations =
|
||||
[
|
||||
{name:'Chicago', n2:'IL'},
|
||||
{name:'Minneapolis', n2:'MN'},
|
||||
{name:'Tempe', n2:'AZ'},
|
||||
{name:'Fargo', n2:'ND'},
|
||||
{name:'North Hollywood', n2:'CA'},
|
||||
{name:'Los Angeles', n2:'CA'},
|
||||
{name:'Huntington Beach'},
|
||||
{name:'Las Vegas', n2:'NV'},
|
||||
{name:'Honolulu', n2:'HI'},
|
||||
{name:'Orlando', n2:'FL'},
|
||||
{name:'New York', n2:'NY'},
|
||||
{name:'Napa', n2:'CA'},
|
||||
{name:'Montego Bay', n2:''},
|
||||
{name:'Kona', n2:'HI'},
|
||||
{name:'Kalipaki Beach', n2:''},
|
||||
{name:'Ixtapa', n2:'MX'}
|
||||
]
|
||||
;
|
||||
|
||||
checkRefresh();
|
||||
setInterval(checkRefresh, 300000);
|
||||
|
||||
|
||||
// check to see if data needs to be refreshed
|
||||
function checkRefresh() {
|
||||
var woeid, location;
|
||||
|
||||
for (location of locations) {
|
||||
|
||||
// check the expiration
|
||||
if (location.hasOwnProperty('xdate') && dateFns.isFuture(location.xdate)) { continue; }
|
||||
|
||||
woeid = location.hasOwnProperty('woeid') ? location.woeid : '';
|
||||
|
||||
|
||||
// woeid is the id for the location to pull data for
|
||||
var url = 'https://api.openweathermap.org/data/2.5/weather?q='+ location.name + '&appid=putkeyhere&units=imperial'
|
||||
|
||||
pullData(url, location);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function pullData(url, location) {
|
||||
var $span;
|
||||
|
||||
// ajax the latest observation
|
||||
$.getJSON(url, function(data) {
|
||||
location.data = data;
|
||||
|
||||
if ( !location.hasOwnProperty('woeid') ) {
|
||||
location.woeid = location.data.id;
|
||||
$span = $("<span id='" + location.woeid + "'></span>").appendTo('#marquee-now');
|
||||
} else {
|
||||
$span = $('#marquee-now>span#' + location.woeid);
|
||||
}
|
||||
|
||||
// display the current info
|
||||
$span.text(location.name + ': ' + Math.round(parseInt(location.data.main.temp)) + ' ' + location.data.weather[0].description.toLowerCase());
|
||||
|
||||
|
||||
// set the expiration date/time
|
||||
location.xdate = dateFns.addMinutes(location.data.lastBuildDate, location.data.ttl);
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
var groupDataManager = new GroupDataManager;
|
|
@ -0,0 +1,179 @@
|
|||
function Location() { // onReady, onRefresh, onAllComplete
|
||||
|
||||
var that = this,
|
||||
$this = $(this),
|
||||
_forecastmgr,
|
||||
_observations=[];
|
||||
|
||||
this.temperature = function() {
|
||||
if (_observations[1]!=null && _observations[1].temperature.value) {
|
||||
return C2F(_observations[1].temperature.value);
|
||||
} else {
|
||||
return Math.round( _observations[0].current.temp );
|
||||
}
|
||||
}
|
||||
|
||||
this.observations = function(i) {
|
||||
return _observations[i];
|
||||
};
|
||||
|
||||
this.forecasts=function(type){return _forecastmgr.forecast(type)};
|
||||
|
||||
this.init = function(searchString){
|
||||
checkRefresh(searchString);
|
||||
};
|
||||
|
||||
this.initForecasts = function() {
|
||||
// start the forecast data pull
|
||||
if (_observations[0] != undefined){
|
||||
_forecastmgr = new ForecastManager(_observations[0].lat, _observations[0].lon, function() {
|
||||
$this.trigger('ready');
|
||||
});
|
||||
}
|
||||
};
|
||||
|
||||
this.initNWSObservations = function(){
|
||||
stationObservations();
|
||||
};
|
||||
|
||||
|
||||
// check to see if data needs to be refreshed
|
||||
function checkRefresh(location) {
|
||||
|
||||
// check the expiration
|
||||
if ( _observations[0]!=undefined && dateFns.isFuture( _observations[0].xdate ) ) {
|
||||
setTimeout(checkRefresh, getRandom(5000, 10000));
|
||||
return;
|
||||
}
|
||||
|
||||
// woeid is the id for the location to pull data for
|
||||
console.log(location);
|
||||
if (location != undefined) {
|
||||
var loclat = location.split(",")[0]
|
||||
var loclong = location.split(",")[1]
|
||||
var url = 'https://api.openweathermap.org/data/2.5/onecall?lat=' + loclat + '&lon=' + loclong + '&appid=putkeyhere&units=imperial'
|
||||
|
||||
|
||||
// ajax the latest observation
|
||||
$.getJSON(url, function(data) {
|
||||
_observations[0] = json = data;
|
||||
|
||||
$this.trigger('refresh');
|
||||
|
||||
// the following block only runs on init
|
||||
if (that.woeid===undefined) {
|
||||
|
||||
that.woeid = loclat
|
||||
|
||||
that.lat = data.lat
|
||||
that.long = data.lon;
|
||||
|
||||
//that.city = data.query.results.channel.location.city;
|
||||
|
||||
$this.trigger('init');
|
||||
|
||||
}
|
||||
// set the expiration date/time
|
||||
_observations[0].xdate = dateFns.addMinutes(json.lastBuildDate, json.ttl);
|
||||
|
||||
setTimeout(checkRefresh, getRandom(5000, 10000));
|
||||
|
||||
});
|
||||
$.getJSON('http://api.openweathermap.org/geo/1.0/reverse?lat=' + loclat + '&lon=' + loclong + '&limit=1&appid=0cb279a98124446dd16dba02fbfb60ee', function(sloc) {
|
||||
that.city = (sloc[0].name);
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
// pull observations from the location observation station
|
||||
function stationObservations() {
|
||||
|
||||
var url = that.stationUrl + '/observations/current';
|
||||
|
||||
// check the expiration
|
||||
if ( _observations[1]!=undefined && dateFns.isFuture( _observations[1].xdate ) ) {
|
||||
setTimeout(checkRefresh, getRandom(5000, 10000));
|
||||
return;
|
||||
}
|
||||
|
||||
// ajax the current conditions
|
||||
$.getJSON(url, function(data) {
|
||||
_observations[1] = data.properties;
|
||||
|
||||
// set the expiration date/time
|
||||
_observations[1].xdate = dateFns.addMinutes(data.properties.timestamp, 60);
|
||||
setTimeout(stationObservations, getRandom(5000, 10000));
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
function ForecastManager (latitude, longitude, readyCallback) {
|
||||
var _forecasts = {},
|
||||
keys =['daily','hourly'],
|
||||
key,
|
||||
readycount = 0;
|
||||
|
||||
for(key of keys) {
|
||||
_forecasts[key] = new Forecast(key, latitude, longitude, count);
|
||||
}
|
||||
|
||||
|
||||
function count() {
|
||||
// count up completed forecast pulls
|
||||
readycount++;
|
||||
if (readycount===keys.length) {
|
||||
readyCallback();
|
||||
}
|
||||
}
|
||||
|
||||
this.forecast = function(type) {
|
||||
try{
|
||||
return _forecasts[type].data;
|
||||
} catch(err){}
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
function Forecast(type, lat, lon, readyCallback) {
|
||||
|
||||
var that = this,
|
||||
url = 'https://api.weather.gov/points/' + lat + ',' + lon + "/forecast/" + (type==='hourly' ? type : '');
|
||||
|
||||
this.data = {};
|
||||
|
||||
checkRefresh();
|
||||
|
||||
function checkRefresh() {
|
||||
|
||||
// check the expiration
|
||||
if ( that.data!={} && dateFns.isFuture( that.data.xdate ) ) {
|
||||
setTimeout(checkRefresh, getRandom(5000, 10000));
|
||||
return;
|
||||
}
|
||||
|
||||
// ajax the forecast
|
||||
$.getJSON(url, function(data) {
|
||||
|
||||
that.data = data.properties.periods;
|
||||
|
||||
// trigger ready callback on first data pull
|
||||
if (readyCallback){
|
||||
readyCallback();
|
||||
}
|
||||
|
||||
// set the expiration date/time
|
||||
that.data.xdate = dateFns.addMinutes(data.properties.updated, 60);
|
||||
that.data.xdate = dateFns.addMinutes(new Date(), 5);
|
||||
setTimeout(checkRefresh, getRandom(5000, 10000));
|
||||
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
}
|
|
@ -0,0 +1,522 @@
|
|||
|
||||
function Loops(bindDataManager) {
|
||||
var //dataManager,
|
||||
obsData,
|
||||
foreDataDaily,
|
||||
foreDataHourly;
|
||||
|
||||
obsData = bindDataManager.observations;
|
||||
foreDataDaily = bindDataManager.forecasts('daily');
|
||||
foreDataHourly = bindDataManager.forecasts('hourly');
|
||||
|
||||
|
||||
// init the display loops
|
||||
displayAtmospheric(0);
|
||||
displayForecast(0);
|
||||
|
||||
function displayAtmospheric(idx) {
|
||||
|
||||
var displays = {
|
||||
|
||||
conditions() {
|
||||
return (getCC(obsData(0).current.weather[0].id + obsData(0).current.weather[0].icon, obsData(0).current.wind_speed)).toLowerCase();
|
||||
},
|
||||
|
||||
wind(){ return 'wind ' + degToCompass(obsData(0).current.wind_deg) + ' ' + Math.round(parseInt(obsData(0).current.wind_speed)); },
|
||||
|
||||
gusts(){
|
||||
if ( obsData(1)!=undefined ) {
|
||||
return obsData(1).windGust.value!=null ? 'gusts ' + mps2mph( obsData(1).windGust.value ) : '';
|
||||
}
|
||||
},
|
||||
|
||||
humidity(){ return 'humidity ' + obsData(0).current.humidity + '%'; },
|
||||
|
||||
dewpoint(){ return 'dew point ' + dewPoint(obsData(0).current.temp, obsData(0).current.humidity ) + '°'; },
|
||||
|
||||
heatindex_windchill(){
|
||||
var windchill = 35.74 + (0.6215 * parseInt(obsData(0).current.temp)) + (0.4275 * parseInt(obsData(0).current.temp) - 35.75) * parseInt(obsData(0).current.wind_speed) ^ 0.16;
|
||||
if (parseInt(obsData(0).current.temp)<80 && windchill < parseInt(obsData(0).current.temp)) {
|
||||
|
||||
return 'wind chill ' + windchill + '°';
|
||||
} else if (parseInt(obsData(0).current.temp)>=80 && parseInt(obsData(0).current.humidity)>=40 ){
|
||||
return 'heat index ' + heatIndex(obsData(0).current.temp, obsData(0).current.humidity) + '°';
|
||||
}
|
||||
else return '';
|
||||
},
|
||||
|
||||
pressure(){ return 'pressure ' + (obsData(0).current.pressure*0.0295301).toFixed(2) },
|
||||
//+ ['S','R','F'][obsData(0).current.rising];
|
||||
visibility() { return 'visibility ' + (parseInt(obsData(0).current.visibility) / 1000) + ' mile' + (obsData(0).current.visibility != 1 ? 's' : ''); },
|
||||
|
||||
uvindex() { return 'UV index ' + obsData(0).current.uvi; },
|
||||
|
||||
},
|
||||
keys = Object.keys(displays),
|
||||
text = displays[ keys[idx] ]();
|
||||
|
||||
// increment the pointer
|
||||
idx = (++idx===keys.length ? 0 : idx);
|
||||
|
||||
if (text) {
|
||||
$('#current-info').html(text);
|
||||
setTimeout(function(){ displayAtmospheric(idx) }, 6000); // 6 second increment loop
|
||||
} else {
|
||||
// nothing to display - skip to the next one
|
||||
setTimeout(function(){ displayAtmospheric(idx) }, 0);
|
||||
}
|
||||
|
||||
} // end function
|
||||
|
||||
|
||||
function displayForecast(idx) {
|
||||
|
||||
var displays = {
|
||||
|
||||
text1() {
|
||||
$('#forecast-title').text( possessiveForecast(foreDataDaily[0].name) );
|
||||
resizeText(foreDataDaily[0].detailedForecast);
|
||||
},
|
||||
text2() {
|
||||
$('#forecast-title').text( possessiveForecast(foreDataDaily[1].name) );
|
||||
resizeText(foreDataDaily[1].detailedForecast);
|
||||
},
|
||||
|
||||
fiveday() {
|
||||
var newtile, weekend, icons,
|
||||
startidx = (foreDataDaily[0].name==='Tonight' ? 1 : 2),
|
||||
days = ['SUN','MON','TUE','WED','THU','FRI','SAT'];
|
||||
|
||||
$('#forecast-title').text("5 DAY FORECAST");
|
||||
$('#forecast-tiles').empty();
|
||||
|
||||
for (var i=startidx; i<=10; i+=2 ) {
|
||||
|
||||
weekend = ( dateFns.isWeekend(foreDataDaily[i].startTime) ? ' weekend' : '');
|
||||
newtile = $("<div class='forecast-tile daily" + weekend + "'></div>");
|
||||
|
||||
$("<div class='header'></div>") .appendTo(newtile) .text(days[ dateFns.getDay(foreDataDaily[i].startTime) ]);
|
||||
|
||||
icons = mapNWSicons(foreDataDaily[i].icon);
|
||||
for (x=icons.length-1; x>=0; x--){
|
||||
$("<img class='icon' src=''/>") .appendTo(newtile) .attr('src', icons[x]);
|
||||
}
|
||||
|
||||
$("<div class='high'></div>") .appendTo(newtile) .text(foreDataDaily[i].temperature);
|
||||
$("<div class='low'></div>") .appendTo(newtile) .text(foreDataDaily[i+1].temperature);
|
||||
|
||||
$('#forecast-tiles').append(newtile);
|
||||
}
|
||||
|
||||
$('#forecast-tiles').css('display','flex');
|
||||
},
|
||||
|
||||
hourly() {
|
||||
var newtile, icons, sizer, highbar,
|
||||
indexes = calcHourlyReport(foreDataHourly),
|
||||
data, label, temps=[];
|
||||
|
||||
$('#forecast-title').text( buildHourlyHeaderTitle(foreDataHourly[indexes[0]].startTime) );
|
||||
$('#forecast-tiles').empty();
|
||||
|
||||
for (var i of indexes) {
|
||||
data = foreDataHourly[i];
|
||||
|
||||
newtile = $("<div class='forecast-tile hourly'></div>");
|
||||
sizer = $("<div class='width-sizer'></div>").appendTo(newtile);
|
||||
|
||||
icons = mapNWSicons(data.icon);
|
||||
for (var x=icons.length-1; x>=0; x--){
|
||||
$("<img class='icon' src=''/>") .appendTo(sizer) .attr('src', icons[x]);
|
||||
}
|
||||
|
||||
$("<div class='footer'></div>") .appendTo(newtile) .text(buildHourlyTimeTitle(data.startTime));
|
||||
|
||||
highbar = $("<div class='hourly-high'></div>") .appendTo(sizer);
|
||||
|
||||
$("<div class='high'></div>") .appendTo(highbar) .text(data.temperature);
|
||||
temps.push(data.temperature);
|
||||
|
||||
$("<div class='temp-bar'></div>") .appendTo(highbar);
|
||||
|
||||
$('#forecast-tiles').append(newtile);
|
||||
}
|
||||
|
||||
$('#forecast-tiles').css('display','flex');
|
||||
|
||||
// animate grow and show temp
|
||||
var min = Math.min(...temps), // 54
|
||||
max = Math.max(...temps), // 73
|
||||
range = (max-min),
|
||||
prange = (95-78), // percent range for bar height
|
||||
temp, value;
|
||||
$('.forecast-tile').each(function(){
|
||||
temp = $(this).find('.high').first().text();
|
||||
value = ((temp-min)/range) * prange + 78; // find percentage of range and translate to percent and add that to the starting css % height number
|
||||
$(this).find('.hourly-high').animate({height:value+"%"}, 1500,function(){
|
||||
$(this).find('.high').fadeTo('slow', 1);
|
||||
});
|
||||
})
|
||||
},
|
||||
|
||||
dummy(){}
|
||||
|
||||
},
|
||||
keys = Object.keys(displays);
|
||||
|
||||
displays[ keys[idx] ]();
|
||||
|
||||
// increment the pointer
|
||||
idx = (++idx===keys.length ? 0 : idx);
|
||||
|
||||
setTimeout(function(){ displayForecast(idx) }, 15000); // 15 second increment loop
|
||||
|
||||
}
|
||||
|
||||
function resizeText(text){
|
||||
var s = 38,
|
||||
$test = $('<div style="position:absolute;top:100%;"></div>') .appendTo('#forecast-text') .css('font-size', s + 'px') .html(text);
|
||||
$test.width($('#forecast-text').width() );
|
||||
//setTimeout(function() {
|
||||
while ($test.outerHeight(true) >= ($('#forecast-text').height()) ) {
|
||||
s -= 1;
|
||||
$test.css('font-size', s + 'px');
|
||||
}
|
||||
$('#forecast-text div') .text(text) .css('font-size', s + 'px');
|
||||
$test.remove();
|
||||
$('#forecast-tiles').hide();
|
||||
//},100); // delay is a workaround for Interstate font not updating display
|
||||
}
|
||||
|
||||
function possessiveForecast(text){
|
||||
return text + (text.toUpperCase() != 'OVERNIGHT' ? "'S" : '') + ' FORECAST';
|
||||
}
|
||||
|
||||
|
||||
} // end Loops class
|
||||
|
||||
|
||||
function buildHourlyHeaderTitle(time) {
|
||||
var today = new Date(),
|
||||
tomorrow = dateFns.addDays(today, 1),
|
||||
sforecast = "'s Forecast";
|
||||
|
||||
// title based on the first hour reported
|
||||
switch (dateFns.getHours(time)) {
|
||||
|
||||
case 6: // 6 - Nextday's Forecast / Today's Forecast
|
||||
// if 6am today
|
||||
if (dateFns.isToday(time)) {
|
||||
return dateFns.format(today, 'dddd') + sforecast;
|
||||
}
|
||||
case 0: // 0 - Nextday's Forecast
|
||||
return dateFns.format(tomorrow, 'dddd') + sforecast;
|
||||
|
||||
case 12:
|
||||
return 'This Afternoon';
|
||||
|
||||
case 15:
|
||||
return "Today's Forecast";
|
||||
|
||||
case 17:
|
||||
return "Tonight's Forecast";
|
||||
|
||||
case 20:
|
||||
return dateFns.format(today, 'ddd') + ' Night/' + dateFns.format(tomorrow, 'ddd');
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
function buildHourlyTimeTitle(time){
|
||||
var hour=dateFns.getHours(time);
|
||||
|
||||
if (hour===0) {
|
||||
return 'midnight';
|
||||
} else if (hour===12){
|
||||
return 'noon';
|
||||
}
|
||||
|
||||
return dateFns.format(time,'h a');
|
||||
}
|
||||
|
||||
|
||||
// finds the intervals to report on the hourly forecast
|
||||
function calcHourlyReport(data) {
|
||||
var ret = [],
|
||||
targets = [0, 6, 12, 15, 17, 20], // hours that we report
|
||||
current = dateFns.getHours(new Date()),
|
||||
now = new Date(),
|
||||
//firsthour = targets[ getNextHighestIndex(targets, current) ],
|
||||
start,
|
||||
hour, i=0;
|
||||
|
||||
switch (true) {
|
||||
case (current < 3):
|
||||
start = 6;
|
||||
case (current < 9):
|
||||
start = 12; break;
|
||||
case (current < 12):
|
||||
start = 15; break;
|
||||
case (current < 15):
|
||||
start = 17; break;
|
||||
case (current < 17):
|
||||
start = 20; break;
|
||||
case (current < 20):
|
||||
start = 0; break;
|
||||
default:
|
||||
start = 6;
|
||||
}
|
||||
|
||||
while(ret.length<4){
|
||||
|
||||
// hour must be equal or greater than current
|
||||
hour = dateFns.getHours( data[i].startTime );
|
||||
if ( dateFns.isAfter(data[i].startTime, now) && (hour==start || ret.length>0) ) {
|
||||
|
||||
if ( targets.indexOf(hour)>=0 ) { // it is in our target list so record its index
|
||||
ret.push(i);
|
||||
}
|
||||
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
function mapNWSicons(url){
|
||||
var map = {
|
||||
skc:[26,25],
|
||||
few:[28,27],
|
||||
sct:[24,23],
|
||||
bkn:[22,21],
|
||||
ovc:[20,20],
|
||||
wind_skc:[26,25,47],
|
||||
wind_few:[28,27,47],
|
||||
wind_sct:[24,23,47],
|
||||
wind_bkn:[22,21,47],
|
||||
wind_ovc:[20,20,47],
|
||||
snow:[10,10],
|
||||
rain_snow:[2,2],
|
||||
rain_sleet:[38,38],
|
||||
snow_sleet:[3,3],
|
||||
fzra:[6,6],
|
||||
rain_fzra:[6,6],
|
||||
snow_fzra:[44,44],
|
||||
sleet:[13,13],
|
||||
rain:[8,8],
|
||||
rain_showers:[7,7],
|
||||
rain_showers_hi:[5,5],
|
||||
tsra:[1,1],
|
||||
tsra_sct:[29,37],
|
||||
tsra_hi:[29,37],
|
||||
tornado:[46,46],
|
||||
hurr_warn:[45,45],
|
||||
hurr_watch:[45,45],
|
||||
ts_warn:[45,45],
|
||||
ts_watch:[45,45],
|
||||
ts_hurr_warn:[45,45],
|
||||
dust:[14,14],
|
||||
smoke:[16,16],
|
||||
haze:[16,16],
|
||||
hot:[16,16],
|
||||
cold:[42,42],
|
||||
blizzard:[11,11],
|
||||
fog:[15,15]
|
||||
},
|
||||
matches = url.match(/icons\/land\/(day|night)\/([a-z_]*)\/?([a-z_]*)/), // day or night followed by one or more condition codes
|
||||
idx = {day:0, night:1}[matches[1]],
|
||||
ret=[], match;
|
||||
|
||||
for (i=2; i<matches.length; i++){
|
||||
|
||||
if (matches[i]) {
|
||||
match = map[ matches[i] ];
|
||||
|
||||
ret.push( match[idx] );
|
||||
|
||||
// some icons are 2 layered
|
||||
if (match.length>2) {
|
||||
ret.push( match[2] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// place word icons last so they render on top
|
||||
if (ret.length>1 && [15,47,41,42, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 13, 20, 31, 33, 34, 38, 39, 40, 44].indexOf( ret[1] )>-1) {
|
||||
ret.swap(0,1);
|
||||
}
|
||||
|
||||
return ret.map(function(num){
|
||||
return 'images/icons/' + ('0'+num).slice(-2) + '.png';
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
/*
|
||||
|
||||
wind E 14
|
||||
gusts 17 mph
|
||||
humidity 58%
|
||||
dew point 72(degree symbol)
|
||||
heat index 95(degree symbol) / wind chill
|
||||
pressure 30.02 S
|
||||
visibility 10 miles
|
||||
uv index High
|
||||
partly cloudy
|
||||
|
||||
*/
|
||||
|
||||
// sample data
|
||||
/*
|
||||
|
||||
https://query.yahooapis.com/v1/public/yql?format=json&q=select * from weather.forecast where woeid=2402292
|
||||
|
||||
"units":{
|
||||
"distance":"mi",
|
||||
"pressure":"in",
|
||||
"speed":"mph",
|
||||
"temperature":"F"
|
||||
},
|
||||
"title":"Yahoo! Weather - Fargo, ND, US",
|
||||
"link":"http://us.rd.yahoo.com/dailynews/rss/weather/Country__Country/*https://weather.yahoo.com/country/state/city-2402292/",
|
||||
"description":"Yahoo! Weather for Fargo, ND, US",
|
||||
"language":"en-us",
|
||||
"lastBuildDate":"Thu, 12 Oct 2017 10:10 PM CDT",
|
||||
"ttl":"60",
|
||||
"location":{
|
||||
"city":"Fargo",
|
||||
"country":"United States",
|
||||
"region":" ND"
|
||||
},
|
||||
"wind":{
|
||||
"chill":"52",
|
||||
"direction":"295",
|
||||
"speed":"18"
|
||||
},
|
||||
"atmosphere":{
|
||||
"humidity":"54",
|
||||
"pressure":"978.0",
|
||||
"rising":"0",
|
||||
"visibility":"16.1"
|
||||
},
|
||||
"astronomy":{
|
||||
"sunrise":"7:41 am",
|
||||
"sunset":"6:46 pm"
|
||||
},
|
||||
"image":{
|
||||
"title":"Yahoo! Weather",
|
||||
"width":"142",
|
||||
"height":"18",
|
||||
"link":"http://weather.yahoo.com",
|
||||
"url":"http://l.yimg.com/a/i/brand/purplelogo//uh/us/news-wea.gif"
|
||||
},
|
||||
"item":{
|
||||
"title":"Conditions for Fargo, ND, US at 09:00 PM CDT",
|
||||
"lat":"46.865089",
|
||||
"long":"-96.829224",
|
||||
"link":"http://us.rd.yahoo.com/dailynews/rss/weather/Country__Country/*https://weather.yahoo.com/country/state/city-2402292/",
|
||||
"pubDate":"Thu, 12 Oct 2017 09:00 PM CDT",
|
||||
"condition":{
|
||||
"code":"27",
|
||||
"date":"Thu, 12 Oct 2017 09:00 PM CDT",
|
||||
"temp":"55",
|
||||
"text":"Mostly Cloudy"
|
||||
},
|
||||
"forecast":[
|
||||
{
|
||||
"code":"30",
|
||||
"date":"12 Oct 2017",
|
||||
"day":"Thu",
|
||||
"high":"70",
|
||||
"low":"48",
|
||||
"text":"Partly Cloudy"
|
||||
},
|
||||
{
|
||||
"code":"32",
|
||||
"date":"13 Oct 2017",
|
||||
"day":"Fri",
|
||||
"high":"58",
|
||||
"low":"37",
|
||||
"text":"Sunny"
|
||||
},
|
||||
{
|
||||
"code":"39",
|
||||
"date":"14 Oct 2017",
|
||||
"day":"Sat",
|
||||
"high":"49",
|
||||
"low":"38",
|
||||
"text":"Scattered Showers"
|
||||
},
|
||||
{
|
||||
"code":"34",
|
||||
"date":"15 Oct 2017",
|
||||
"day":"Sun",
|
||||
"high":"56",
|
||||
"low":"31",
|
||||
"text":"Mostly Sunny"
|
||||
},
|
||||
{
|
||||
"code":"34",
|
||||
"date":"16 Oct 2017",
|
||||
"day":"Mon",
|
||||
"high":"65",
|
||||
"low":"35",
|
||||
"text":"Mostly Sunny"
|
||||
},
|
||||
{
|
||||
"code":"34",
|
||||
"date":"17 Oct 2017",
|
||||
"day":"Tue",
|
||||
"high":"65",
|
||||
"low":"39",
|
||||
"text":"Mostly Sunny"
|
||||
},
|
||||
{
|
||||
"code":"30",
|
||||
"date":"18 Oct 2017",
|
||||
"day":"Wed",
|
||||
"high":"64",
|
||||
"low":"48",
|
||||
"text":"Partly Cloudy"
|
||||
},
|
||||
{
|
||||
"code":"30",
|
||||
"date":"19 Oct 2017",
|
||||
"day":"Thu",
|
||||
"high":"65",
|
||||
"low":"44",
|
||||
"text":"Partly Cloudy"
|
||||
},
|
||||
{
|
||||
"code":"30",
|
||||
"date":"20 Oct 2017",
|
||||
"day":"Fri",
|
||||
"high":"66",
|
||||
"low":"49",
|
||||
"text":"Partly Cloudy"
|
||||
},
|
||||
{
|
||||
"code":"28",
|
||||
"date":"21 Oct 2017",
|
||||
"day":"Sat",
|
||||
"high":"61",
|
||||
"low":"49",
|
||||
"text":"Mostly Cloudy"
|
||||
}
|
||||
],
|
||||
"description":"<![CDATA[<img src=\"http://l.yimg.com/a/i/us/we/52/27.gif\"/>\n<BR />\n<b>Current Conditions:</b>\n<BR />Mostly Cloudy\n<BR />\n<BR />\n<b>Forecast:</b>\n<BR /> Thu - Partly Cloudy. High: 70Low: 48\n<BR /> Fri - Sunny. High: 58Low: 37\n<BR /> Sat - Scattered Showers. High: 49Low: 38\n<BR /> Sun - Mostly Sunny. High: 56Low: 31\n<BR /> Mon - Mostly Sunny. High: 65Low: 35\n<BR />\n<BR />\n<a href=\"http://us.rd.yahoo.com/dailynews/rss/weather/Country__Country/*https://weather.yahoo.com/country/state/city-2402292/\">Full Forecast at Yahoo! Weather</a>\n<BR />\n<BR />\n<BR />\n]]>",
|
||||
"guid":{
|
||||
"isPermaLink":"false"
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
Current Conditions:</b>\n<BR />Mostly Cloudy\n<BR />\n<BR />\n<b>
|
||||
Forecast:</b>\n<BR /> Thu - Partly Cloudy. High: 70Low: 48\n<BR /> Fri - Sunny. High: 58Low: 37\n<BR /> Sat - Scattered Showers. High: 49Low: 38\n<BR /> Sun - Mostly Sunny. High: 56Low: 31\n<BR />
|
||||
Mon - Mostly Sunny. High: 65Low: 35\n<BR />\n<BR />\n<a href=\"http://us.rd.yahoo.com/dailynews/rss/weather/Country__Country/*https://weather.yahoo.com/country/state/city-2402292/\">Full Forecast at Yahoo! Weather</a>\n<BR />\n<BR />\n<BR />\n]]>",
|
||||
"guid":{
|
||||
|
||||
*/
|
|
@ -0,0 +1,34 @@
|
|||
|
||||
$(function(){
|
||||
|
||||
var $main = $("#main"),
|
||||
$window = $( window ),
|
||||
mainHeight = $main.outerHeight(),
|
||||
mainWidth = $main.outerWidth(),
|
||||
mainAspect = 4/3,
|
||||
resizeTimer;
|
||||
|
||||
|
||||
$(window).resize( function(e) {
|
||||
clearTimeout(resizeTimer);
|
||||
resizeTimer = setTimeout(scaleWindow, 100);
|
||||
});
|
||||
|
||||
function scaleWindow() {
|
||||
var scale, windowAspect;
|
||||
|
||||
windowAspect = $window.width() / $window.height();
|
||||
|
||||
if (windowAspect>=mainAspect) {
|
||||
scale = $window.height() / mainHeight;
|
||||
} else {
|
||||
scale = $window.width() / mainWidth;
|
||||
}
|
||||
|
||||
$main.css({
|
||||
transform: "translate(-50%, -50%) " + "scale(" + scale + ")"
|
||||
});
|
||||
}
|
||||
scaleWindow(); // init
|
||||
|
||||
});
|
|
@ -0,0 +1,188 @@
|
|||
|
||||
function Radar(divIDin, intervalHoursIn, zoomIn, latitudeIn, longitudeIn, withSat) {
|
||||
|
||||
var map,
|
||||
divID = divIDin,
|
||||
intervalHours = intervalHoursIn,
|
||||
zoom = zoomIn,
|
||||
latitude = latitudeIn,
|
||||
longitude = longitudeIn;
|
||||
|
||||
this.setView = function(lat, long, zoomLevel){
|
||||
map.setView(L.latLng(lat, long), zoomLevel)
|
||||
};
|
||||
|
||||
|
||||
startAnimation();
|
||||
setInterval(updatePeriod, 300000);
|
||||
|
||||
function updatePeriod() {
|
||||
var endDate = roundDate(new Date()),
|
||||
startDate = dateFns.subHours(endDate, 3),
|
||||
newAvailableTimes = L.TimeDimension.Util.explodeTimeRange(startDate, endDate, 'PT5M');
|
||||
|
||||
map.timeDimension.setAvailableTimes(newAvailableTimes, 'replace');
|
||||
map.timeDimension.setCurrentTime(startDate);
|
||||
}
|
||||
|
||||
// snap date to 5 minute intervals
|
||||
function roundDate(date) {
|
||||
date.setUTCMinutes( Math.round(date.getUTCMinutes() / 5) * 5);
|
||||
date.setUTCSeconds(0);
|
||||
return date;
|
||||
}
|
||||
|
||||
function startAnimation () {
|
||||
|
||||
var endDate = roundDate(new Date()),
|
||||
player;
|
||||
|
||||
map = L.map(divID, {
|
||||
zoom: zoom,
|
||||
fullscreenControl: false,
|
||||
timeDimension: true,
|
||||
timeDimensionControl: true,
|
||||
timeDimensionOptions:{
|
||||
timeInterval: "PT" + intervalHours + "H/" + endDate.toISOString(),
|
||||
period: "PT5M",
|
||||
currentTime: endDate
|
||||
},
|
||||
|
||||
timeDimensionControlOptions: {
|
||||
autoPlay: true,
|
||||
playerOptions: {
|
||||
buffer: 36,
|
||||
transitionTime: 100,
|
||||
loop: false,
|
||||
startOver:true
|
||||
}
|
||||
},
|
||||
center: [latitude, longitude] // 31.205482,-82.4331197 test coordinates
|
||||
});
|
||||
map.timeDimensionControl._player.on('stop', function(){
|
||||
setTimeout( function() {
|
||||
map.timeDimensionControl._player.setLooped(true);
|
||||
map.timeDimensionControl._player.start();
|
||||
setTimeout(function(){map.timeDimensionControl._player.setLooped(false)}, 1000);
|
||||
}, 1000)
|
||||
});
|
||||
|
||||
|
||||
// basemap
|
||||
// streets cj9fqw1e88aag2rs2al6m3ko2
|
||||
// satellite streets cj8p1qym6976p2rqut8oo6vxr
|
||||
// weatherscan green cj8owq50n926g2smvagdxg9t8
|
||||
// mapbox://styles/goldbblazez/ckgc7fwvr4qmn19pevtvhyabl
|
||||
// https://api.mapbox.com/styles/v1/goldbblazez/ckgc8lzdz4lzh19qt7q9wbbr9.html?fresh=true&title=copy&access_token=
|
||||
L.tileLayer('https://api.mapbox.com/styles/v1/goldbblazez/ckgc8lzdz4lzh19qt7q9wbbr9/tiles/{z}/{x}/{y}?access_token=putkeyhere', {
|
||||
tileSize: 512,
|
||||
zoomOffset: -1
|
||||
}).addTo(map);
|
||||
|
||||
|
||||
var radarWMS = L.nonTiledLayer.wms("https://nowcoast.noaa.gov/arcgis/services/nowcoast/radar_meteo_imagery_nexrad_time/MapServer/WMSServer", {
|
||||
layers: '1',
|
||||
format: 'image/png',
|
||||
transparent: true,
|
||||
opacity: 0.8
|
||||
});
|
||||
|
||||
if (withSat) {
|
||||
|
||||
var goes_visible_sat = L.nonTiledLayer.wms('https://nowcoast.noaa.gov/arcgis/services/nowcoast/sat_meteo_imagery_time/MapServer/WMSServer', {
|
||||
layers: '9', // 9 for visible sat
|
||||
format: 'image/png',
|
||||
transparent: true,
|
||||
opacity:0.7,
|
||||
useCanvas:true
|
||||
}),
|
||||
satellitetimeLayer = L.timeDimension.layer.wms(goes_visible_sat, {
|
||||
proxy: proxy,
|
||||
updateTimeDimension: false,
|
||||
cache:1
|
||||
});
|
||||
|
||||
satellitetimeLayer.addTo(map).on('timeload',function(t) {
|
||||
var canvas, ctx,
|
||||
imageData, data,
|
||||
i,
|
||||
layers = t.target._layers,
|
||||
keys = Object.keys(layers);
|
||||
|
||||
for (var key of keys) {
|
||||
canvas = layers[key]._bufferCanvas;
|
||||
|
||||
if (canvas.dataset.isAlpha){continue}
|
||||
|
||||
ctx = canvas.getContext('2d');
|
||||
|
||||
imageData = ctx.getImageData(0, 0, canvas.width, canvas.height);
|
||||
|
||||
var pixels = imageData.data,
|
||||
brighten = 0,
|
||||
contrast = 10;
|
||||
for(var i = 0; i < pixels.length; i+=4){//loop through all data
|
||||
|
||||
pixels[i] += brighten;
|
||||
pixels[i+1] += brighten;
|
||||
pixels[i+2] += brighten;
|
||||
|
||||
var brightness = (pixels[i]+pixels[i+1]+pixels[i+2])/3; //get the brightness
|
||||
|
||||
pixels[i] += brightness > 127 ? contrast : -contrast;
|
||||
pixels[i+1] += brightness > 127 ? contrast : -contrast;
|
||||
pixels[i+2] += brightness > 127 ? contrast : -contrast;
|
||||
|
||||
var rgb = pixels[i] + pixels[i+1] + pixels[i+2];
|
||||
pixels[i] = pixels[i+1] = pixels[i+2] = 255;
|
||||
pixels[i+3] = rgb / 3;
|
||||
}
|
||||
imageData.data = pixels;
|
||||
|
||||
// overwrite original image
|
||||
ctx.putImageData(imageData, 0, 0);
|
||||
|
||||
canvas.dataset.isAlpha = true;
|
||||
|
||||
}
|
||||
|
||||
});
|
||||
}
|
||||
|
||||
|
||||
var proxy = 'js/leaflet/proxy.php';
|
||||
var radarTimeLayer = L.timeDimension.layer.wms(radarWMS, {
|
||||
proxy: proxy,
|
||||
updateTimeDimension: false
|
||||
});
|
||||
|
||||
radarTimeLayer.addTo(map);
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
/*
|
||||
* Workaround for 1px lines appearing in some browsers due to fractional transforms
|
||||
* and resulting anti-aliasing.
|
||||
* https://github.com/Leaflet/Leaflet/issues/3575
|
||||
*/
|
||||
|
||||
(function(){
|
||||
//return;
|
||||
var originalInitTile = L.GridLayer.prototype._initTile
|
||||
L.GridLayer.include({
|
||||
_initTile: function (tile) {
|
||||
originalInitTile.call(this, tile);
|
||||
|
||||
var tileSize = this.getTileSize();
|
||||
|
||||
tile.style.width = tileSize.x + 1 + 'px';
|
||||
tile.style.height = tileSize.y + 1 + 'px';
|
||||
}
|
||||
});
|
||||
})()
|
|
@ -0,0 +1,599 @@
|
|||
/*
|
||||
|
||||
headings:
|
||||
RADAR < MAIN CITY < CITY 1 < CITY 2
|
||||
*/
|
||||
|
||||
// load slide data
|
||||
function Slides(dataMan) {
|
||||
var radarSlideDuration = 60000,
|
||||
slideDelay = 10000;
|
||||
// for later
|
||||
var selectval = 0;
|
||||
buildHeader();
|
||||
|
||||
setTimeout(nextCity, 5000);
|
||||
|
||||
|
||||
// loop cities
|
||||
function nextCity(){
|
||||
|
||||
advanceHeader();
|
||||
|
||||
var city = $('#info-slides-header .city.current');
|
||||
|
||||
// is radar or city?
|
||||
if (city[0].dataset.woeid) {
|
||||
// show slide deck for the current city
|
||||
showCitySlides( dataMan.location(city[0].dataset.woeid), 0 );
|
||||
|
||||
} else {
|
||||
|
||||
|
||||
// radar
|
||||
showRadar(dataMan.locations[0].lat, dataMan.locations[0].long, 8);
|
||||
|
||||
//setTimeout(function() { weatherAudio.playLocalRadar() }, 2000 );
|
||||
|
||||
// show for how long?
|
||||
setTimeout(nextCity, 60000);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
function showRadar(lat, long, zoom) {
|
||||
|
||||
weatherMan.mainMap.setView(lat, long, zoom);
|
||||
|
||||
setTimeout(function() {
|
||||
|
||||
// fade out info, fade in radar
|
||||
$('.info-slide-content:visible').fadeOut(250, function(){
|
||||
$('.info-slide').fadeOut(250, function() {
|
||||
$('.radar-slide').fadeIn(500);
|
||||
});
|
||||
});
|
||||
|
||||
}, 1500); // give it time to load
|
||||
|
||||
}
|
||||
|
||||
|
||||
// show the set of slides for one city
|
||||
function showCitySlides(location, idx) {
|
||||
|
||||
var currentDisplay,
|
||||
displays = {
|
||||
|
||||
// Currently (10 sec)
|
||||
currentConditions() {
|
||||
$('.city-info-slide #subhead-title').text('Currently');
|
||||
$('.city-info-slide #subhead-city').text(location.city);
|
||||
var obsData = location.observations,
|
||||
strLabels = 'Humidity<br>Dew Point<br>Pressure<Br>Wind<br>',
|
||||
strData =
|
||||
obsData(0).current.humidity + '%<br>' + dewPoint(parseInt(obsData(0).current.temp), parseInt(obsData(0).current.humidity)) + '<br>' + (obsData(0).current.pressure*0.0295301).toFixed(2) + '<br>' + degToCompass(obsData(0).current.wind_deg) + ' ' + Math.round(parseInt(obsData(0).current.wind_speed)) + '<br>';
|
||||
if (obsData(0).current.wind_gust!=undefined) {
|
||||
strLabels+='Gusts<Br>';
|
||||
strData+=obsData(0).current.wind_gust + '<br>';
|
||||
} else {
|
||||
strLabels+='Gusts<Br>';
|
||||
strData+='none<br>';
|
||||
}
|
||||
var windchill = 35.74 + (0.6215 * parseInt(obsData(0).current.temp)) + (0.4275 * parseInt(obsData(0).current.temp) - 35.75) * parseInt(obsData(0).current.wind_speed) ^ 0.16;
|
||||
if (windchill < parseInt(obsData(0).current.temp)) {
|
||||
strLabels+='Wind Chill';
|
||||
strData+= windchill;
|
||||
} else if (parseInt(obsData(0).current.temp)>=80 && parseInt(obsData(0).current.humidity)>=40 ){
|
||||
strLabels+='Heat Index';
|
||||
return 'heat index ' + heatIndex(obsData(0).current.temp, obsData(0).current.humidity) + '°';
|
||||
};
|
||||
|
||||
$('.city-info .frost-pane .labels').html(strLabels);
|
||||
$('.city-info .frost-pane .data').html(strData);
|
||||
|
||||
// right pane
|
||||
$('.city-info .icon').css('background-image', 'url("' + getCCicon(+obsData(0).current.weather[0].id + obsData(0).current.weather[0].icon, obsData(0).current.wind_speed) + '")');
|
||||
$('.city-info .conditions').text(getCC(obsData(0).current.weather[0].id + obsData(0).current.weather[0].icon, obsData(0).current.wind_speed));
|
||||
$('.city-info .temp').text( Math.round(parseInt(obsData(0).current.temp)) );
|
||||
|
||||
fadeToContent('.city-info');
|
||||
wait(slideDelay);
|
||||
|
||||
}
|
||||
|
||||
// Local Doppler Radar or Radar/Satellite (15 sec, zoomed out with cloud cover)
|
||||
,localDoppler(){
|
||||
showRadar(location.lat, location.long, 8);
|
||||
wait(slideDelay + 1500);
|
||||
}
|
||||
|
||||
// daypart / hourly
|
||||
,forecast(fidx) {
|
||||
//pick between day part or local forecast
|
||||
if (selectval === 0 || selectval === 1) {
|
||||
var foreDataHourly = dataMan.locations[0].forecasts('hourly');
|
||||
var indexes = calcHourlyReport(foreDataHourly);
|
||||
var i;
|
||||
var temps=[];
|
||||
// reset tempbar animation
|
||||
$('.info-slide-content.daypart .hour').each(function(){
|
||||
$('.info-slide-content.daypart .hour .tempbar').css("height", "0px")
|
||||
$('.info-slide-content.daypart .hour .tempbar .temp').css("opacity", "0%");
|
||||
$('.info-slide-content.daypart .hour .tempbar .wind').css("opacity", "0%");
|
||||
i = i + 1
|
||||
});
|
||||
//hour title
|
||||
$('.info-slide-content.daypart .hour.i .thing .thingtext').text(buildHourlyTimeTitle(foreDataHourly[indexes[0]].startTime));
|
||||
$('.info-slide-content.daypart .hour.ii .thing .thingtext').text(buildHourlyTimeTitle(foreDataHourly[indexes[1]].startTime));
|
||||
$('.info-slide-content.daypart .hour.iii .thing .thingtext').text(buildHourlyTimeTitle(foreDataHourly[indexes[2]].startTime));
|
||||
$('.info-slide-content.daypart .hour.iv .thing .thingtext').text(buildHourlyTimeTitle(foreDataHourly[indexes[3]].startTime));
|
||||
for (var i of indexes) {
|
||||
var data = foreDataHourly[i];
|
||||
temps.push(data.temperature);
|
||||
}
|
||||
|
||||
$('.info-slide-content.daypart .hour.i .tempbar .temp').text(foreDataHourly[indexes[0]].temperature);
|
||||
$('.info-slide-content.daypart .hour.ii .tempbar .temp').text(foreDataHourly[indexes[1]].temperature);
|
||||
$('.info-slide-content.daypart .hour.iii .tempbar .temp').text(foreDataHourly[indexes[2]].temperature);
|
||||
$('.info-slide-content.daypart .hour.iv .tempbar .temp').text(foreDataHourly[indexes[3]].temperature);
|
||||
|
||||
$('.info-slide-content.daypart .hour.i .tempbar .wind').text(foreDataHourly[indexes[0]].windDirection + ' ' + (foreDataHourly[indexes[0]].windSpeed).replace(" mph", ""));
|
||||
$('.info-slide-content.daypart .hour.ii .tempbar .wind').text(foreDataHourly[indexes[1]].windDirection + ' ' + (foreDataHourly[indexes[1]].windSpeed).replace(" mph", ""));
|
||||
$('.info-slide-content.daypart .hour.iii .tempbar .wind').text(foreDataHourly[indexes[2]].windDirection + ' ' + (foreDataHourly[indexes[2]].windSpeed).replace(" mph", ""));
|
||||
$('.info-slide-content.daypart .hour.iv .tempbar .wind').text(foreDataHourly[indexes[3]].windDirection + ' ' + (foreDataHourly[indexes[3]].windSpeed).replace(" mph", ""));
|
||||
|
||||
$('.info-slide-content.daypart .hour.i .condition').text(buildConditions(foreDataHourly[indexes[0]].shortForecast));
|
||||
$('.info-slide-content.daypart .hour.ii .condition').text(buildConditions(foreDataHourly[indexes[1]].shortForecast));
|
||||
$('.info-slide-content.daypart .hour.iii .condition').text(buildConditions(foreDataHourly[indexes[2]].shortForecast));
|
||||
$('.info-slide-content.daypart .hour.iv .condition').text(buildConditions(foreDataHourly[indexes[3]].shortForecast));
|
||||
|
||||
$('.info-slide-content.daypart .hour.i .icon').css('background-image', 'url("' + mapNWSicons(foreDataHourly[indexes[0]].icon) + '")');
|
||||
$('.info-slide-content.daypart .hour.ii .icon').css('background-image', 'url("' + mapNWSicons(foreDataHourly[indexes[1]].icon) + '")');
|
||||
$('.info-slide-content.daypart .hour.iii .icon').css('background-image', 'url("' + mapNWSicons(foreDataHourly[indexes[2]].icon) + '")');
|
||||
$('.info-slide-content.daypart .hour.iv .icon').css('background-image', 'url("' + mapNWSicons(foreDataHourly[indexes[3]].icon) + '")');
|
||||
|
||||
function buildConditions(forecasttext) {
|
||||
if (forecasttext.includes("Thunderstorms") === true) {
|
||||
return forecasttext.replace(/Slight Chance/g,"Isolated").replace(/Chance/g,"Sct'd").replace(/Thunderstorms/g,"T'storms").replace(/Partly Sunny/g,"Partly Cloudy").replace(/Showers and Thunderstorms/g,"T'Storms")
|
||||
} else {
|
||||
return forecasttext.replace(/Slight Chance/g,"Few").replace(/Chance/g,"").replace(/Partly Sunny/g,"Partly Cloudy").replace(/Isolated/g,"Few")
|
||||
}
|
||||
}
|
||||
function buildHourlyTimeTitle(time){
|
||||
var hour=dateFns.getHours(time);
|
||||
|
||||
if (hour===0) {
|
||||
return 'Midnight';
|
||||
} else if (hour===12){
|
||||
return 'Noon';
|
||||
}
|
||||
return (dateFns.format(time,'h a')).replace(" ", "");
|
||||
}
|
||||
//get reporting hours: 12am, 6am, 12pm, 3pm, 5pm, 8pm...
|
||||
function calcHourlyReport(data) {
|
||||
var ret = [],
|
||||
targets = [0, 6, 12, 15, 17, 20], // hours that we report
|
||||
current = dateFns.getHours(new Date()),
|
||||
now = new Date(),
|
||||
//firsthour = targets[ getNextHighestIndex(targets, current) ],
|
||||
start,
|
||||
hour, i=0;
|
||||
|
||||
switch (true) {
|
||||
case (current < 3):
|
||||
start = 6;
|
||||
case (current < 9):
|
||||
start = 12; break;
|
||||
case (current < 12):
|
||||
start = 15; break;
|
||||
case (current < 14):
|
||||
start = 17; break;
|
||||
case (current < 17):
|
||||
start = 6; break;
|
||||
case (current < 20):
|
||||
start = 6; break;
|
||||
default:
|
||||
start = 6;
|
||||
}
|
||||
while(ret.length<4){
|
||||
|
||||
// hour must be equal or greater than current
|
||||
hour = dateFns.getHours( data[i].startTime );
|
||||
if ( dateFns.isAfter(data[i].startTime, now) && (hour==start || ret.length>0) ) {
|
||||
|
||||
if ( targets.indexOf(hour)>=0 ) { // it is in our target list so record its index
|
||||
ret.push(i);
|
||||
}
|
||||
|
||||
}
|
||||
i++;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
function buildHourlyHeaderTitle(time) {
|
||||
var today = new Date(),
|
||||
tomorrow = dateFns.addDays(today, 1);
|
||||
|
||||
// title based on the first hour reported
|
||||
switch (dateFns.getHours(time)) {
|
||||
|
||||
case 6: // 6 - Nextday's Forecast / Today's Forecast
|
||||
// if 6am today
|
||||
if (dateFns.isToday(time)) {
|
||||
return "Today's Forecast";
|
||||
}
|
||||
case 0: // 0 - Nextday's Forecast
|
||||
return "Tomorrow's Forecast";
|
||||
|
||||
case 12:
|
||||
return "Today's Forecast";
|
||||
|
||||
case 15:
|
||||
return "Today's Forecast";
|
||||
|
||||
case 17:
|
||||
return "Tonight's Forecast";
|
||||
|
||||
case 20:
|
||||
return "Tonight's Forecast"
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
// calculate height of tempbars
|
||||
$('.city-info-slide #subhead-title').text(buildHourlyHeaderTitle(foreDataHourly[indexes[0]].startTime));
|
||||
fadeToContent('.info-slide-content.daypart')
|
||||
var min = Math.min(...temps), // 54
|
||||
max = Math.max(...temps), // 73
|
||||
range = (max-min),
|
||||
prange = (100-78), // percent range for bar height
|
||||
hourlable = ['i', 'ii', 'iii', 'iv'],
|
||||
temp, value, i = 0;
|
||||
$('.info-slide-content.daypart .hour').each(function(){
|
||||
temp = foreDataHourly[indexes[i]].temperature
|
||||
value = ((temp-min)/range) * prange + 78; // find percentage of range and translate to percent and add that to the starting css % height number
|
||||
valueii = (value/100) * 165 // multiply percentage by max height
|
||||
$('.info-slide-content.daypart .hour.' + hourlable[i] + ' .tempbar').animate({height:valueii+"px"}, 1500,function(){
|
||||
$('.info-slide-content.daypart .hour .tempbar .temp').fadeTo('slow', 1);
|
||||
$('.info-slide-content.daypart .hour .tempbar .wind').fadeTo('slow', 1);
|
||||
});
|
||||
i = i + 1
|
||||
})
|
||||
wait(slideDelay)
|
||||
} else {
|
||||
// Local Forecast -Today (10 sec)
|
||||
var div = '.info-slide-content.forecast ',
|
||||
forecasts = location.forecasts('daily');
|
||||
|
||||
function fillinfo() {
|
||||
|
||||
fidx = (fidx===undefined ? 0 : fidx);
|
||||
|
||||
$('.city-info-slide #subhead-title').text('Local Forecast');
|
||||
|
||||
// title
|
||||
$(div + '.title').text( forecasts[fidx].name );
|
||||
|
||||
// content
|
||||
resizeText( forecasts[fidx].detailedForecast );
|
||||
$(div + '.content').text( forecasts[fidx].detailedForecast );
|
||||
|
||||
}
|
||||
|
||||
fadeToContent(div, fillinfo)
|
||||
|
||||
setTimeout( function() {
|
||||
|
||||
if (fidx<3) {
|
||||
currentDisplay(++fidx);
|
||||
} else {
|
||||
wait(0);
|
||||
}
|
||||
|
||||
}, slideDelay)
|
||||
}
|
||||
selectval = selectval + 1
|
||||
if (selectval === 4) {selectval = 1}
|
||||
}
|
||||
|
||||
|
||||
|
||||
// Extended Forecast(5 day columns)
|
||||
,extendedForecast() {
|
||||
$('.city-info-slide #subhead-title').text('Extended Forecast');
|
||||
|
||||
var foreDataDaily = dataMan.locations[0].forecasts('daily');
|
||||
var icons, weekend
|
||||
startidx = (foreDataDaily[0].name==='Tonight' ? 1 : 2),
|
||||
days = ['Sun','Mon','Tue','Wed','Thu','Fri','Sat'];
|
||||
//days
|
||||
$('.info-slide-content.extended-forecast .frost-pane.iw .thing').text(days[ dateFns.getDay(foreDataDaily[startidx].startTime) ])
|
||||
$('.info-slide-content.extended-forecast .frost-pane.iiw .thing').text(days[ dateFns.getDay(foreDataDaily[startidx+2].startTime) ])
|
||||
$('.info-slide-content.extended-forecast .frost-pane.iiiw .thing').text(days[ dateFns.getDay(foreDataDaily[startidx+4].startTime) ])
|
||||
$('.info-slide-content.extended-forecast .frost-pane.ivw .thing').text(days[ dateFns.getDay(foreDataDaily[startidx+6].startTime) ])
|
||||
$('.info-slide-content.extended-forecast .lfrost-pane.vw .thing .thingtext').text(days[ dateFns.getDay(foreDataDaily[startidx+8].startTime) ])
|
||||
|
||||
//icons
|
||||
$('.info-slide-content.extended-forecast .frost-pane.iw .icon').css('background-image', 'url("' + mapNWSicons(foreDataDaily[startidx].icon)[0] + '")');
|
||||
$('.info-slide-content.extended-forecast .frost-pane.iiw .icon').css('background-image', 'url("' + mapNWSicons(foreDataDaily[startidx+2].icon) + '")');
|
||||
$('.info-slide-content.extended-forecast .frost-pane.iiiw .icon').css('background-image', 'url("' + mapNWSicons(foreDataDaily[startidx+4].icon) + '")');
|
||||
$('.info-slide-content.extended-forecast .frost-pane.ivw .icon').css('background-image', 'url("' + mapNWSicons(foreDataDaily[startidx+6].icon) + '")');
|
||||
$('.info-slide-content.extended-forecast .lfrost-pane.vw .icon').css('background-image', 'url("' + mapNWSicons(foreDataDaily[startidx+8].icon) + '")');
|
||||
|
||||
//conditions
|
||||
$('.info-slide-content.extended-forecast .frost-pane.iw .conditions').text(builddailyconditions(foreDataDaily[startidx].shortForecast));
|
||||
$('.info-slide-content.extended-forecast .frost-pane.iiw .conditions').text(builddailyconditions(foreDataDaily[startidx+2].shortForecast));
|
||||
$('.info-slide-content.extended-forecast .frost-pane.iiiw .conditions').text(builddailyconditions(foreDataDaily[startidx+4].shortForecast));
|
||||
$('.info-slide-content.extended-forecast .frost-pane.ivw .conditions').text(builddailyconditions(foreDataDaily[startidx+6].shortForecast));
|
||||
$('.info-slide-content.extended-forecast .lfrost-pane.vw .conditions').text(builddailyconditions(foreDataDaily[startidx+8].shortForecast));
|
||||
|
||||
//high
|
||||
$('.info-slide-content.extended-forecast .frost-pane.iw .temphigh').text(foreDataDaily[startidx].temperature)
|
||||
$('.info-slide-content.extended-forecast .frost-pane.iiw .temphigh').text(foreDataDaily[startidx+2].temperature)
|
||||
$('.info-slide-content.extended-forecast .frost-pane.iiiw .temphigh').text(foreDataDaily[startidx+4].temperature)
|
||||
$('.info-slide-content.extended-forecast .frost-pane.ivw .temphigh').text(foreDataDaily[startidx+6].temperature)
|
||||
$('.info-slide-content.extended-forecast .lfrost-pane.vw .temphigh .temphightext').text(foreDataDaily[startidx+8].temperature)
|
||||
|
||||
//low
|
||||
$('.info-slide-content.extended-forecast .frost-pane.iw .templow').text(foreDataDaily[startidx+1].temperature)
|
||||
$('.info-slide-content.extended-forecast .frost-pane.iiw .templow').text(foreDataDaily[startidx+3].temperature)
|
||||
$('.info-slide-content.extended-forecast .frost-pane.iiiw .templow').text(foreDataDaily[startidx+5].temperature)
|
||||
$('.info-slide-content.extended-forecast .frost-pane.ivw .templow').text(foreDataDaily[startidx+7].temperature)
|
||||
$('.info-slide-content.extended-forecast .lfrost-pane.vw .templow').text(foreDataDaily[startidx+9].temperature)
|
||||
|
||||
function builddailyconditions(dailyconditiontext) {
|
||||
if (dailyconditiontext.includes("then") === true){
|
||||
var splitdc = dailyconditiontext.split("then")
|
||||
if (dailyconditiontext.includes("Thunderstorms") === true) {
|
||||
splitdc[0] = splitdc[0].replace(/Slight Chance/g,"Isolated").replace(/Chance/g,"Sct'd").replace(/Thunderstorms/g,"T'storms").replace(/Partly Sunny/g,"Partly Cloudy").replace(/Showers and Thunderstorms/g,"T'Storms").replace(/Patchy/g,"").replace(/Cloudy/g,"Clouds").replace(/Sunny/g,"Sun")
|
||||
splitdc[1] = splitdc[1].replace(/Slight Chance/g,"Isolated").replace(/Chance/g,"Sct'd").replace(/Thunderstorms/g,"T'storms").replace(/Partly Sunny/g,"Partly Cloudy").replace(/Showers and Thunderstorms/g,"T'Storms").replace(/Patchy/g,"").replace(/Cloudy/g,"Clouds").replace(/Sunny/g,"Sun")
|
||||
return "AM" + splitdc[0] + ", PM" + splitdc[1]
|
||||
} else {
|
||||
splitdc[0] = splitdc[0].replace(/Slight Chance/g,"Few").replace(/Chance/g,"").replace(/Partly Sunny/g,"Partly Cloudy").replace(/Isolated/g,"Few").replace(/Partly Sunny/g,"Partly Cloudy").replace(/Showers and Thunderstorms/g,"T'Storms").replace(/Patchy/g,"").replace(/Cloudy/g,"Clouds").replace(/Sunny/g,"Sun")
|
||||
splitdc[1] = splitdc[1].replace(/Slight Chance/g,"Few").replace(/Chance/g,"").replace(/Partly Sunny/g,"Partly Cloudy").replace(/Isolated/g,"Few").replace(/Patchy/g,"").replace(/Cloudy/g,"Clouds").replace(/Sunny/g,"Sun")
|
||||
return "AM" + splitdc[0] + ", PM" + splitdc[1]
|
||||
}
|
||||
} else {
|
||||
if (dailyconditiontext.includes("Thunderstorms") === true) {return dailyconditiontext.replace(/Slight Chance/g,"Isolated").replace(/Chance/g,"Sct'd").replace(/Thunderstorms/g,"T'storms").replace(/Partly Sunny/g,"Partly Cloudy").replace(/Showers and Thunderstorms/g,"T'Storms").replace(/Patchy/g,"")} else {return dailyconditiontext.replace(/Slight Chance/g,"Few").replace(/Chance/g,"").replace(/Partly Sunny/g,"Partly Cloudy").replace(/Isolated/g,"Few").replace(/Patchy/g,"")}
|
||||
}
|
||||
|
||||
}
|
||||
fadeToContent('.info-slide-content.extended-forecast')
|
||||
wait(slideDelay)
|
||||
}
|
||||
|
||||
},
|
||||
keys = Object.keys(displays);
|
||||
|
||||
var daypart;
|
||||
if (idx<keys.length) {
|
||||
currentDisplay = displays[keys[idx]];
|
||||
currentDisplay();
|
||||
} else { // done - exit
|
||||
nextCity();
|
||||
}
|
||||
return;
|
||||
|
||||
function wait(duration){
|
||||
setTimeout(function() {
|
||||
showCitySlides(location, ++idx);
|
||||
}, duration);
|
||||
}
|
||||
|
||||
|
||||
|
||||
function resizeText(text){
|
||||
var s = 50,
|
||||
$container = $('.info-slide-content.forecast .content'),
|
||||
$test = $('<div style="position:absolute;top:100%;"></div>') .appendTo($container) .css('font-size', s + 'px') .html(text);
|
||||
|
||||
// have to display parent so we can get measurements
|
||||
$container.closest('.info-slide-content').show();
|
||||
|
||||
$test.width($container.width() );
|
||||
while ($test.outerHeight(true) >= ($container.height()) ) {
|
||||
s -= 1;
|
||||
$test.css('font-size', s + 'px');
|
||||
}
|
||||
$container.closest('.info-slide-content').hide();
|
||||
$container .text(text) .css('font-size', s + 'px');
|
||||
$test.remove();
|
||||
|
||||
}
|
||||
|
||||
|
||||
function fadeToContent(to, callfirst) {
|
||||
var $to = $(to),
|
||||
$parent = $to.closest('.info-slide');
|
||||
|
||||
if ( $parent.is(":hidden") ) {
|
||||
// hide other visible slide then show the parent
|
||||
$to.hide();
|
||||
$('.info-slide:visible').fadeOut(250, function() {
|
||||
//$to.hide();
|
||||
$parent.fadeIn(250, showMe);
|
||||
});
|
||||
} else {
|
||||
hideOldShowMe();
|
||||
}
|
||||
|
||||
function hideOldShowMe() {
|
||||
if ($('.info-slide-content:visible')) {
|
||||
$('.info-slide-content:visible').fadeOut(500, showMe);
|
||||
} else {
|
||||
showMe();
|
||||
}
|
||||
}
|
||||
|
||||
function showMe() {
|
||||
if (callfirst) { callfirst() };
|
||||
$to.fadeIn(500);
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
//doDisplay = displays[ keys[idx] ]();
|
||||
|
||||
// increment the pointer
|
||||
//idx = (++idx===keys.length ? 0 : idx);
|
||||
|
||||
//if (text) {
|
||||
// $('#current-info').html(text);
|
||||
// setTimeout(function(){ displayAtmospheric(idx) }, 6000); // 6 second increment loop
|
||||
//} else {
|
||||
// nothing to display - skip to the next one
|
||||
// setTimeout(function(){ displayAtmospheric(idx) }, 0);
|
||||
//}
|
||||
|
||||
/*
|
||||
(Main City)
|
||||
Currently (10 sec)
|
||||
Local Doppler Radar or Radar/Satellite (15 sec, zoomed out with cloud cover)
|
||||
|
||||
Local Forecast
|
||||
-Today (10 sec)
|
||||
-Tonight (10 sec)
|
||||
-Tomorrow (name day) (10 sec)
|
||||
-Tomorrow (name day) Night (10 sec)
|
||||
|
||||
or
|
||||
|
||||
Daypart
|
||||
|
||||
Extended Forecast(5 day columns)
|
||||
Almanac (to be made)
|
||||
|
||||
(Per City)
|
||||
Local Doppler Radar (center on city)
|
||||
Currently
|
||||
Local Doppler Radar
|
||||
Today's Forecast
|
||||
Extended Forecast(5 day columns)
|
||||
*/
|
||||
|
||||
|
||||
|
||||
//idx++;
|
||||
//if (idx<=0){
|
||||
setTimeout(cityLoop, 3000); // change to 60000 for production
|
||||
//} else {
|
||||
|
||||
//}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
function advanceHeader() {
|
||||
|
||||
// swap current
|
||||
var $cities = $('#info-slides-header .city'),
|
||||
$scroller = $('#info-slides-header .hscroller'),
|
||||
left;
|
||||
|
||||
$($cities[0]).removeClass('current');
|
||||
$($cities[1]).addClass('current');
|
||||
|
||||
// animate move left
|
||||
left = $scroller.position().left - $($cities[1]).position().left;
|
||||
$scroller.animate({ 'left': left+'px' }, 700,
|
||||
function(){
|
||||
// on completion, move the old one to the end
|
||||
$scroller.css('left','');
|
||||
$($cities[0]).appendTo($scroller);
|
||||
$('#info-slides-header span').first().appendTo($scroller);
|
||||
})
|
||||
|
||||
|
||||
}
|
||||
|
||||
function buildHeader(){
|
||||
var city, first, woeid,
|
||||
cities='',
|
||||
arrow='<span class="divider-arrow"><</span>',
|
||||
radar='<span class="city radar">LOCAL RADAR</span>';
|
||||
|
||||
for (var location of dataMan.locations) {
|
||||
city = location.city;
|
||||
cities += arrow+'<span class="city" data-woeid="' + location.woeid + '">' + city + '</span>';
|
||||
}
|
||||
|
||||
$('#info-slides-header .hscroller').append(cities + arrow + (radar + cities + arrow).repeat(4));
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
} // end function
|
||||
function mapNWSicons(url){
|
||||
var map = {
|
||||
skc:[26,25],
|
||||
few:[28,27],
|
||||
sct:[24,23],
|
||||
bkn:[22,21],
|
||||
ovc:[20,20],
|
||||
wind_skc:[26,25,47],
|
||||
wind_few:[28,27,47],
|
||||
wind_sct:[24,23,47],
|
||||
wind_bkn:[22,21,47],
|
||||
wind_ovc:[20,20,47],
|
||||
snow:[10,10],
|
||||
rain_snow:[2,2],
|
||||
rain_sleet:[38,38],
|
||||
snow_sleet:[3,3],
|
||||
fzra:[6,6],
|
||||
rain_fzra:[6,6],
|
||||
snow_fzra:[44,44],
|
||||
sleet:[13,13],
|
||||
rain:[8,8],
|
||||
rain_showers:[7,7],
|
||||
rain_showers_hi:[5,5],
|
||||
tsra:[1,1],
|
||||
tsra_sct:[29,37],
|
||||
tsra_hi:[29,37],
|
||||
tornado:[46,46],
|
||||
hurr_warn:[45,45],
|
||||
hurr_watch:[45,45],
|
||||
ts_warn:[45,45],
|
||||
ts_watch:[45,45],
|
||||
ts_hurr_warn:[45,45],
|
||||
dust:[14,14],
|
||||
smoke:[16,16],
|
||||
haze:[16,16],
|
||||
hot:[16,16],
|
||||
cold:[42,42],
|
||||
blizzard:[11,11],
|
||||
fog:[15,15]
|
||||
},
|
||||
matches = url.match(/icons\/land\/(day|night)\/([a-z_]*)\/?([a-z_]*)/), // day or night followed by one or more condition codes
|
||||
idx = {day:0, night:1}[matches[1]],
|
||||
ret=[], match;
|
||||
|
||||
for (i=2; i<matches.length; i++){
|
||||
|
||||
if (matches[i]) {
|
||||
match = map[ matches[i] ];
|
||||
|
||||
ret.push( match[idx] );
|
||||
|
||||
//some icons are 2 layered but don't want it
|
||||
if (match.length>2) {
|
||||
ret.push( match[2] );
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
// place word icons last so they render on top
|
||||
if (ret.length>1 && [15,47,41,42, 1, 2, 3, 4, 5, 6, 7, 8, 9, 10, 12, 13, 20, 31, 33, 34, 38, 39, 40, 44].indexOf( ret[1] )>-1) {
|
||||
ret.swap(0,1);
|
||||
}
|
||||
|
||||
return ret.map(function(num){
|
||||
return 'images/icons/' + ('0'+num).slice(-2) + '.png';
|
||||
});
|
||||
|
||||
}
|
|
@ -0,0 +1,113 @@
|
|||
// Fisher-Yates shuffle
|
||||
function shuffle (array) {
|
||||
var i = 0,
|
||||
j = 0,
|
||||
temp = null;
|
||||
|
||||
for (i = array.length - 1; i > 0; i -= 1) {
|
||||
j = Math.floor(Math.random() * (i + 1));
|
||||
temp = array[i];
|
||||
array[i] = array[j];
|
||||
array[j] = temp;
|
||||
}
|
||||
|
||||
return array;
|
||||
}
|
||||
|
||||
function getRandom(min, max) {
|
||||
return Math.random() * (max - min) + min;
|
||||
}
|
||||
|
||||
|
||||
function getNextHighestIndex(arr, value) {
|
||||
var i = arr.length;
|
||||
while (arr[--i] > value);
|
||||
return ++i;
|
||||
}
|
||||
|
||||
|
||||
function getUrlParameter(e) {
|
||||
return decodeURI((new RegExp(e + "=(.+?)(&|$)").exec(location.search) || [, null])[1])
|
||||
}
|
||||
|
||||
|
||||
|
||||
// convert celsius to farenheight
|
||||
function C2F(c){
|
||||
return Math.round( c * 9 / 5 + 32 );
|
||||
}
|
||||
|
||||
|
||||
// meters per second to mph
|
||||
function mps2mph(meters) {
|
||||
return Math.round( parseFloat(meters) * 2.23694 );
|
||||
}
|
||||
|
||||
|
||||
// array swap
|
||||
Array.prototype.swap = function(a,b){ var tmp=this[a];this[a]=this[b];this[b]=tmp;};
|
||||
|
||||
|
||||
function degToCompass(deg){
|
||||
val = Math.round((deg/22.5)+.5);
|
||||
arr=["N","NE","E","SE","S","SW","W","NW"];
|
||||
return arr[(val % 8)];
|
||||
}
|
||||
|
||||
|
||||
|
||||
function distance(lat1, lon1, lat2, lon2) {
|
||||
var radlat1 = Math.PI * lat1/180,
|
||||
radlat2 = Math.PI * lat2/180,
|
||||
theta = lon1-lon2,
|
||||
radtheta = Math.PI * theta/180,
|
||||
dist = Math.sin(radlat1) * Math.sin(radlat2) + Math.cos(radlat1) * Math.cos(radlat2) * Math.cos(radtheta);
|
||||
dist = Math.acos(dist);
|
||||
dist = dist * 180/Math.PI;
|
||||
dist = dist * 60 * 1.1515;
|
||||
return dist;
|
||||
}
|
||||
|
||||
|
||||
function dewPoint(tem, r){
|
||||
tem = -1.0*(tem-32)*5/9 ;
|
||||
es = 6.112*Math.exp(-1.0*17.67*tem/(243.5 - tem));
|
||||
ed = r/100.0*es;
|
||||
eln = Math.log(ed/6.112);
|
||||
td = -243.5*eln/(eln - 17.67 );
|
||||
return Math.round( (td*9/5)+32 );
|
||||
}
|
||||
|
||||
function heatIndex(T, R) { // T = temp, R = relative humidity
|
||||
var T2 = T*T, R2= R*R,
|
||||
c1 = -42.379, c2 = 2.04901523, c3 = 10.14333127,
|
||||
c4 = -0.22475541, c5 = -6.83783*Math.pow(10,-3), c6 = -5.481717*Math.pow(10,-2),
|
||||
c7 = 1.22874*Math.pow(10,-3), c8 = 8.5282*Math.pow(10,-4), c9 = -1.99*Math.pow(10,-6);
|
||||
|
||||
return Math.round(c1 + c2*T + c3 *R + c4*T*R + c5*T2 + c6*R2 + c7*T2*R + c8*T*R2 + c9*T2*R2);
|
||||
}
|
||||
|
||||
|
||||
// maps current condition code to icon
|
||||
function getCCicon(ccCode, windData){
|
||||
var icon = "images/icons/" + ( "0" + {"20011d":1,"20011n":1,"20111d":1,"20111n":1,"20211d":1,"20211n":1,"21011d":46,"21011n":46,"21111d":46,"21111n":46,"21211d":46,"21211n":46,"22111d":1,"22111n":1,"23011d":1,"23011n":1,"23111d":1,"23111n":1,"23211d":1,"23211n":1,"30009d":5,"30009n":5,"30109d":5,"30109n":5,"30209d":5,"30209n":5,"31009d":5,"31009n":5,"31109d":5,"31109n":5,"31209d":5,"31209n":5,"31309d":5,"31309n":5,"31409d":5,"31409n":5,"32109d":5,"32109n":5,"50010d":7,"50010n":7,"50110d":8,"50110n":8,"50210d":31,"50210n":31,"50310d":31,"50310n":31,"50410d":31,"50410d":31,"51110d":6,"51110n":6,"52010d":7,"52010n":7,"52110d":8,"52110n":8,"52210d":31,"52210n":31,"53110d":29,"53110n":37,"60013d":10,"60013n":10,"60113d":12,"60113n":12,"60213d":33,"60213n":33,"61113d":13,"61113n":13,"61213d":13,"61213n":13,"61313d":13,"61313n":13,"61513d":2,"61513n":2,"61613d":2,"61613n":2,"62013d":10,"62013n":10,"62113d":12,"62113n":12,"62213d":33,"62213n":33,"70150d":15,"70150n":15,"71150d":14,"71150n":14,"72150d":16,"72150n":16,"73150d":16,"73150n":16,"74150d":15,"74150n":15,"75150d":16,"75150n":16,"76150d":14,"76150n":14,"76250d":14,"76250n":14,"77150d":18,"77150n":18,"78150d":1,"78150n":1,"80001d":26,"80001n":25,"80102d":28,"80102n":27,"80203d":22,"80203n":21,"80304d":24,"80304n":23,"80404d":20,"80404n":20}[ccCode]).slice(-2) + ".png";
|
||||
if (parseInt(windData) >= 20) {
|
||||
if (ccCode === "50110d" || "50110n" || "52110d" || "52110d") {
|
||||
icon = "images/icons/45.png"
|
||||
}
|
||||
if (ccCode === "60113d" || "60113n" || "62113d" || "62113n") {
|
||||
icon = "images/icons/34.png"
|
||||
}
|
||||
}
|
||||
return icon
|
||||
}
|
||||
function getCC(ccCode, windData){
|
||||
var condition = {"20011d":"Light Thunderstorm","20011n":"Light Thunderstorm","20111d":"Thunderstorm","20111n":"Thunderstorm","20211d":"Heavy Thunderstorm","20211n":"Heavy Thunderstorm","21011d":"Thunder","21011n":"Thunder","21111d":"Thunder","21111n":"Thunder","21211d":"Thunder","21211n":"Thunder","22111d":"Scattered Thunderstorm","22111n":"Scattered Thunderstorm","23011d":"Light Thunderstorm","23011n":"Light Thunderstorm","23111d":"Light Thunderstorm","23111n":"Light Thunderstorm","23211d":"Light Thunderstorm","23211n":"Light Thunderstorm","30009d":"Drizzle","30009n":"Drizzle","30109d":"Drizzle","30109n":"Drizzle","30209d":"Drizzle","30209n":"Drizzle","31009d":"Drizzle","31009n":"Drizzle","31109d":"Drizzle","31109n":"Drizzle","31209d":"Drizzle","31209n":"Drizzle","31309d":"Drizzle","31309n":"Drizzle","31409d":"Drizzle","31409n":"Drizzle","32109d":"Drizzle","32109n":"Drizzle","50010d":"Light Rain","50010n":"Light Rain","50110d":"Rain","50110n":"Rain","50210d":"Heavy Rain","50210n":"Heavy Rain","50310d":"Heavy Rain","50310n":"Heavy Rain","50410d":"Heavy Rain","50410d":"Heavy Rain","51110d":"Freezing Rain","51110n":"Freezing Rain","52010d":"Light Rain Shower","52010n":"Light Rain Shower","52110d":"Rain Shower","52110n":"Rain Shower","52210d":"Heavy Rain Shower","52210n":"Heavy Rain Shower","53110d":"Scattered Rain Showers","53110n":"Scattered Rain Showers","60013d":"Light Snow","60013n":"Light snow","60113d":"Snow","60113n":"Snow","60213d":"Heavy Snow","60213n":"Heavy Snow","61113d":"Sleet","61113n":"Sleet","61213d":"Sleet","61213n":"Sleet","61313d":"Sleet","61313n":"Sleet","61513d":"Light Rain and Snow","61513n":"Light Rain and Snow","61613d":"Rain and Snow","61613n":"Rain and Snow","62013d":"Light Snow Shower","62013n":"Light Snow Shower","62113d":"Snow Shower","62113n":"Snow Shower","62213d":"Heavy Snow Shower","62213n":"Heavy Snow Shower","70150d":"Mist","70150n":"Mist","71150d":"Smoke","71150n":"Smoke","72150d":"Haze","72150n":"Haze","73150d":"Blowing Dust","73150n":"Blowing Dust","74150d":"Fog","74150n":"Fog","75150d":"Blowing Dust","75150n":"Blowing Dust","76150d":"Blowing Dust","76150n":"Blowing Dust","76250d":"Ash","76250n":"Ash","77150d":"Squalls","77150n":"Squalls","78150d":"Tornado","78150n":"Tornado","80001d":"Sunny","80001n":"Clear","80102d":"Fair","80102n":"Fair","80203d":"Partly Cloudy","80203n":"Partly Cloudy","80304d":"Mostly Cloudy","80304n":"Mostly Cloudy","80404d":"Cloudy","80404n":"Cloudy"}[ccCode]
|
||||
if (parseInt(windData) >= 20) {
|
||||
condition = condition + ", windy"
|
||||
}
|
||||
return condition
|
||||
|
||||
}
|
||||
|
||||
// https://date-fns.org/docs/Getting-Started
|
|
@ -0,0 +1,109 @@
|
|||
|
||||
function WeatherManager() {
|
||||
|
||||
var mainloc
|
||||
var mainMap, miniMap, slides,
|
||||
dataMan, loops, // weatherAudio,
|
||||
that = this;
|
||||
|
||||
$(function(){
|
||||
|
||||
// init marquees
|
||||
function refreshMarquee () {
|
||||
|
||||
$('#marquee-container')
|
||||
.marquee('destroy')
|
||||
.marquee({speed: 200, pauseOnHover:true, delayBeforeStart:3000})
|
||||
.on('finished', refreshMarquee);
|
||||
}
|
||||
refreshMarquee();
|
||||
|
||||
|
||||
$('#marquee2').marquee({
|
||||
speed: 170, pauseOnHover: true
|
||||
});
|
||||
|
||||
|
||||
weatherAudio.playCallback = function(tags) {
|
||||
$('.track-info').text('playing "' + tags.title + '" by ' + tags.artist);
|
||||
}
|
||||
|
||||
// this little guy runs the date and time
|
||||
setInterval(
|
||||
function () {
|
||||
var today = new Date();
|
||||
|
||||
$('#date').text( today.toString().slice(4,10).trimRight() );
|
||||
$('#time').text( today.toLocaleTimeString('en-US', { hour: 'numeric', hour12: true, minute: 'numeric', second: 'numeric' }).replace(/ /g,'') );
|
||||
}
|
||||
, 1000);
|
||||
|
||||
initDataPull();
|
||||
|
||||
});
|
||||
|
||||
|
||||
|
||||
function initDataPull() {
|
||||
// get the main location data
|
||||
// on initialization ready, init local forecast loop
|
||||
// on return of fully ready, begin display loops
|
||||
|
||||
// check the url for a specific location
|
||||
var queryString = window.location.search;
|
||||
|
||||
if (queryString) {
|
||||
dataMan = createDataManager( queryString.split("?")[1] );
|
||||
} else {
|
||||
|
||||
// get lat lon from user's ip
|
||||
$.getJSON("http://ip-api.com/json/?callback=?", function(data) {
|
||||
dataMan = createDataManager( data.lat+','+data.lon );
|
||||
mainloc = data.city
|
||||
});
|
||||
|
||||
}
|
||||
|
||||
function initDisplayLoops(){
|
||||
loops = new Loops(dataMan.locations[0]);
|
||||
}
|
||||
function initSlidesLoop() {
|
||||
slides = new Slides(dataMan);
|
||||
}
|
||||
function createDataManager(searchString) {
|
||||
var dataManager = new DataManager();
|
||||
|
||||
$(dataManager)
|
||||
.on('refresh', refreshObservationDisplay)
|
||||
.on('ready:main', initDisplayLoops)
|
||||
.on('allinit', initSlidesLoop);
|
||||
|
||||
dataManager.init(searchString);
|
||||
|
||||
return dataManager;
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
function refreshObservationDisplay() {
|
||||
var data = dataMan.locations[0].observations(0),
|
||||
cond = data.current.weather[0];
|
||||
|
||||
if (mainMap===undefined) {
|
||||
mainMap = that.mainMap = new Radar("radar-1", 3, 8, data.lat, data.lon, false);
|
||||
miniMap = new Radar("minimap", 3, 5, data.lat, data.lon);
|
||||
}
|
||||
|
||||
$('#city').text(mainloc);
|
||||
$('#forecast-city').text(mainloc + ':');
|
||||
$('#current-temp').text( dataMan.locations[0].temperature() ) ;
|
||||
$('#conditions-icon').css('background-image', 'url("' + getCCicon(cond.id + cond.icon) + '")');
|
||||
|
||||
//weatherAudio.playCurrentConditions(cond);
|
||||
|
||||
}
|
||||
|
||||
}
|
||||
var weatherMan = new WeatherManager();
|
Loading…
Reference in New Issue