commit 776d331412dc0c68bf47d9cc58516eeabfd6712b Author: boris Date: Mon Aug 14 01:21:46 2023 +0200 Init diff --git a/webfiles/Reports/.placeholder.txt b/webfiles/Reports/.placeholder.txt new file mode 100644 index 0000000..e69de29 diff --git a/webfiles/css/colours.css b/webfiles/css/colours.css new file mode 100644 index 0000000..2bfeddc --- /dev/null +++ b/webfiles/css/colours.css @@ -0,0 +1,40 @@ +/* ------------------------------------------------------------------- + * Colours for the CumulusMX Alternative Interface + * Produced using w3Schools colour generator + * + * Key Colour: #4e5b31 + * + * Theme modified to change font 'color's to either lightest or darkest + * theme colour. Also modified names for text, borders & hover colours. + * I have added a few extras. Not all are used. + * Neil Thomas + ------------------------------------------------------------------*/ + +/* Check that your theme is named as shown below */ + +.w3-theme-white {color:#2e5473; background-color:#FFFFFF;} +.w3-theme-l5 {color:#2e5473; background-color:#f7fafc;} +.w3-theme-l4 {color:#2e5473; background-color:#e4edf4;} +.w3-theme-l3 {color:#2e5473 ; background-color:#c9dbe9;} +.w3-theme-l2 {color:#2e5473 ; background-color:#aec9df;} +.w3-theme-l1 {color:#2e5473 ; background-color:#93b7d4;} +.w3-theme-d1 {color:#f7fafc ; background-color:#6195c0;} +.w3-theme-d2 {color:#f7fafc ; background-color:#4a86b7;} +.w3-theme-d3 {color:#f7fafc ; background-color:#4075a1;} +.w3-theme-d4 {color:#f7fafc ; background-color:#37658a;} +.w3-theme-d5 {color:#f7fafc ; background-color:#2e5473;} + +.w3-theme-light {color:#2e5473 ; background-color:#f7fafc;} +.w3-theme-dark {color:#f7fafc ; background-color:#2e5473;} +.w3-theme-action {color:#f7fafc ; background-color:#2e5473;} + +.w3-theme {color:#f7fafc ; background-color:#78a5c9;} +.w3-theme-txt {color:#78a5c9;} +.w3-theme-bdr {border-color:#78a5c9;} +.w3-theme-d5-bdr {border-color:#2e5473;} +.w3-theme-l1-bdr {border-color:#f7fafc;} + +.w3-theme-hvr:hover {color:#f7fafc; background-color:#78a5c9;} +.w3-theme-d5-hvr:hover {color:#f7fafc; background-color:#2e5473;} +.w3-theme-txt-hvr:hover {color:#78a5c9;} +.w3-theme-bdr-hvr:hover {border-color:#78a5c9;} diff --git a/webfiles/css/gauges.css b/webfiles/css/gauges.css new file mode 100644 index 0000000..ed4068b --- /dev/null +++ b/webfiles/css/gauges.css @@ -0,0 +1,101 @@ +/* CSS for SteelSeries Gauges + * Mark Crossley | modified by Neil Thomas + * v2.5.0 - 03 Dec 2014 | Feb 2021 + */ + +.gauge { + position: relative; +} + +.odo { + position: absolute; + top: 67%; + left: 50%; + transform: translateX(-50%); + -webkit-transform: translateX(-50%); +} +.gaugeSmall { + max-width:181px; + max-height: 181px; + width:100%; + height:100%; +} +.at-gaugeSmall { + width: 221px; + margin-left:8px; + margin-right:8px; +} + +.gaugeMedium { + max-width: 221px; + max-height:221px; +} +.at-gaugeMedium { + width: 261px; + margin-left:8px; + margin-right:8px; +} + +.gaugeLarge { + max-width:261px; + max-height:261px; + width:100%; + height:100%; +} + +.at-gaugeLarge { + width:301px; + margin-left:8px; + margin-right:8px; +} + +@media screen and (max-width:550px) { + .at-gaugeSmall { width:100%; } + .at-gaugeMedium{ width:100%;} +} + +@media screenand (max-width:640px) { + .at-gaugeLarge { width:100%;} + } + +@font-face { + font-family: 'LCDMono2Ultra'; + src: url('data:font/woff;charset=utf-8;base64,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') format('woff'), + url('../fonts/lcdmono2ultra-webfont.eot'), + url('../fonts/lcdmono2ultra-webfont.ttf') format('truetype'), + url('../fonts/lcdmono2ultra-webfont.svg#LCDMono2Ultra') format('svg'); + font-weight: normal; + font-style: normal; +} + +.ddimgtooltip{ + z-index: 2000; + box-shadow: 3px 3px 5px #818181; /*shadow for CSS3 capable browsers.*/ + border-radius: 8px; + display: none; + position: absolute; + border: 2px solid #2e5473!important; /* Changed to match d5 of theme */ + background: #f7fafc!important; /* Changed to match l1 of theme */ + color: #2e5473!important; /* Changed to match d5 of theme */ + padding: 0 7px 3px 7px; + /*font-family: sans-serif; */ + font-size: 86%!important; + max-width: 300px; +} + +.tipinfo{ + text-align: left; + padding: 3px 0 3px 2px; +} + +.tipinfo h5, .tipinfo h6 { + + line-height:1.2em; + margin:0; + padding:0; +} + +.tipimg{ + width: 438px; /* suggest 380 for wxgraphs */ + height: 175px; /* suggest 260 for wxgraphs */ +} diff --git a/webfiles/css/mx-templates.css b/webfiles/css/mx-templates.css new file mode 100644 index 0000000..97ffaca --- /dev/null +++ b/webfiles/css/mx-templates.css @@ -0,0 +1,215 @@ +/* ----------------------------------- + * Styles for CumulusMX Templates + Last modified: 2021/03/19 09:23:15 + * ----------------------------------*/ + +html, body, p, h1, h2, h3, h4, h5, h6, li, td, th { + font-family: 'Rosario', sans-serif; +} + +p { + font-size: 15px; +} + +#Header { + border-style: solid; + border-width: 0 0 10px 0; +} + +.site-width { + max-width:1140px; + margin:auto; +} + +.graph-width { + max-width:1250px; + margin:auto; +} + +#Footer { + border-width:5px 0 0 0; + border-style: solid; +} + +.logo { + max-width:250px; + margin: 5px 0 5px 16px; +} + +.subText { + font-size: 80% !important; + font-weight:400; +} + +body { + background-image: url('../images/picture.jpg'); + background-position: bottom left; + background-repeat: no-repeat; + background-attachment: fixed; +} + +.statusPanel h5 { + margin-bottom: -5px; +} +/* ------------------------------------- + * Flex boxes + * -------------------------------------*/ +.at-flex-start { display:flex;} +.at-flex-end { + display:flex; + justify-content: flex-end; + flex-wrap:wrap; +} + +.at-flex-justify { + display:flex; + justify-content: space-around; + flex-wrap:wrap; +} + +.at-flex-between { + display:flex; + justify-content: space-between; + flex-wrap:wrap; +} + +.at-flex-bottom, +.at-flex-items-bottom { + align-items: flex-end; +} + +.at-flex-items-center { + align-items: center; +} + +/* -------------------------------------------------- + * Menu enhancements + * --------------------------------------------------*/ +#Main_Menu { + margin-bottom: 4px; + border-width:2px 0 0 0 ; + border-style: solid; + min-height: 32px; +} + +.at-slim { + padding: 4px 14px!important; +} + +.at-divider { + margin: 0 5px; + color:#F80; +} + +.at-spacer { + min-height:2em; +} + +.at-menu-lable { + display:block; + width:100%; + font-size: 13px; + font-style: italic; + padding-bottom: 2px!important; + padding-top:4px!important; + border-bottom: 1px dotted #c2cfa5!important; +} + +.at-menu-bar { + display:block; + height: 2px; + padding: 0 2px!important; +} + +.at-indent { + padding-left: 40px!important; +} + +/* ------------------------------- + * Model enhancements + * ------------------------------*/ + +.w3-modal-content { + margin-top:10%; + border-radius: 8px; +} + +.w3-modal header { border-radius: 8px 8px 0 0;} +.w3-modal footer { border-radius: 0 0 8px 8px;} +.w3-modal .w3-btn { border-radius: 0 8px;} + +/* ---------------------------------------- + * Media enhancements + * ---------------------------------------*/ +@media screen and (max-width:780px) { + #Footer { position: unset; } + #Content { + /*margin-top: 170px!important;*/ + margin-bottom: 5px!important; + } + + .statusPanel { + text-align:center!important; + margin:auto!important; + } +} + +@media screen and (max-height:768px) { + #Footer { position: unset; item: center;} + #Content { + margin-bottom: 5px!important; + } +} + +/* -------------------------------------- + * LED enhancements + * -------------------------------------*/ +.at-led-round { + display:inline-block; + height: 1.2em; + width: 1.2em; + margin: 0 0.5em -3px 0.5em; + border-radius: 50%; + background-color: #888; + box-shadow: inset 3px 3px 2px rgba(220, 220, 220, 0.6), inset -2px -2px 2px rgba(32, 32, 32,0.6); +} + +.at-led-block { + display:inline-block; + height: 1.2em; + width: 1.2em; + margin: 0 0.5em -3px 0.5em; + background-color: #888; + box-shadow: inset 3px 3px 2px rgba(220, 220, 220, 0.6), inset -2px -2px 2px rgba(32, 32, 32,0.6); +} + +.at-led-brick { + display:inline-block; + height:0.8em; + width:1.6em; + margin:0 0.5em -3px 0.5em; + background-color: #888; + box-shadow: inset 3px 3px 2px rgba(220, 220, 220, 0.6), inset -2px -2px 2px rgba(32, 32, 32,0.6); +} +.at-led-oval { + display:inline-block; + height:1em; + width:2em; + margin:0 0.5em -3px 0.5em; + border-radius: 50%; + background-color: #888; + box-shadow: inset 3px 3px 2px rgba(220, 220, 220, 0.6), inset -2px -2px 2px rgba(32, 32, 32,0.6); +} + +.at-led-green { + background-color: #0b0; +} + +.at-led-flash-red { + animation: flashR 1s infinite; +} + +@keyframes flashR { + 0%, 60% {background-color: #f00;} + 61%,100% {background-color: #800;} +} diff --git a/webfiles/css/w3Pro.css b/webfiles/css/w3Pro.css new file mode 100644 index 0000000..3e59f4c --- /dev/null +++ b/webfiles/css/w3Pro.css @@ -0,0 +1,151 @@ +/* W3PRO.CSS 4.15 December 2020 by Jan Egil and Borge Refsnes */ +html{box-sizing:border-box}*,*:before,*:after{box-sizing:inherit} +/* Extract from normalize.css by Nicolas Gallagher and Jonathan Neal git.io/normalize */ +html{-ms-text-size-adjust:100%;-webkit-text-size-adjust:100%}body{margin:0} +article,aside,details,figcaption,figure,footer,header,main,menu,nav,section{display:block}summary{display:list-item} +audio,canvas,progress,video{display:inline-block}progress{vertical-align:baseline} +audio:not([controls]){display:none;height:0}[hidden],template{display:none} +a{background-color:transparent}a:active,a:hover{outline-width:0} +abbr[title]{border-bottom:none;text-decoration:underline;text-decoration:underline dotted} +b,strong{font-weight:bolder}dfn{font-style:italic}mark{background:#ff0;color:#000} +small{font-size:80%}sub,sup{font-size:75%;line-height:0;position:relative;vertical-align:baseline} +sub{bottom:-0.25em}sup{top:-0.5em}figure{margin:1em 40px}img{border-style:none} +code,kbd,pre,samp{font-family:monospace,monospace;font-size:1em}hr{box-sizing:content-box;height:0;overflow:visible} +button,input,select,textarea,optgroup{font:inherit;margin:0}optgroup{font-weight:bold} +button,input{overflow:visible}button,select{text-transform:none} +button,[type=button],[type=reset],[type=submit]{-webkit-appearance:button} +button::-moz-focus-inner,[type=button]::-moz-focus-inner,[type=reset]::-moz-focus-inner,[type=submit]::-moz-focus-inner{border-style:none;padding:0} +button:-moz-focusring,[type=button]:-moz-focusring,[type=reset]:-moz-focusring,[type=submit]:-moz-focusring{outline:1px dotted ButtonText} +fieldset{border:1px solid #c0c0c0;margin:0 2px;padding:.35em .625em .75em} +legend{color:inherit;display:table;max-width:100%;padding:0;white-space:normal}textarea{overflow:auto} +[type=checkbox],[type=radio]{padding:0} +[type=number]::-webkit-inner-spin-button,[type=number]::-webkit-outer-spin-button{height:auto} +[type=search]{-webkit-appearance:textfield;outline-offset:-2px} +[type=search]::-webkit-search-decoration{-webkit-appearance:none} +::-webkit-file-upload-button{-webkit-appearance:button;font:inherit} +/* End extract */ +html,body{font-family:Verdana,sans-serif;font-size:15px;line-height:1.5}html{overflow-x:hidden} +h1{font-size:36px}h2{font-size:30px}h3{font-size:24px}h4{font-size:20px}h5{font-size:18px}h6{font-size:16px} +.w3-serif{font-family:serif}.w3-sans-serif{font-family:sans-serif}.w3-cursive{font-family:cursive}.w3-monospace{font-family:monospace} +h1,h2,h3,h4,h5,h6{font-family:"Segoe UI",Arial,sans-serif;font-weight:400;margin:10px 0}.w3-wide{letter-spacing:4px} +hr{border:0;border-top:1px solid #eee;margin:20px 0} +.w3-image{max-width:100%;height:auto}img{vertical-align:middle}a{color:inherit} +.w3-table,.w3-table-all{border-collapse:collapse;border-spacing:0;width:100%;display:table}.w3-table-all{border:1px solid #ccc} +.w3-bordered tr,.w3-table-all tr{border-bottom:1px solid #ddd}.w3-striped tbody tr:nth-child(even){background-color:#f1f1f1} +.w3-table-all tr:nth-child(odd){background-color:#fff}.w3-table-all tr:nth-child(even){background-color:#f1f1f1} +.w3-hoverable tbody tr:hover,.w3-ul.w3-hoverable li:hover{background-color:#ccc}.w3-centered tr th,.w3-centered tr td{text-align:center} +.w3-table td,.w3-table th,.w3-table-all td,.w3-table-all th{padding:8px 8px;display:table-cell;text-align:left;vertical-align:top} +.w3-table th:first-child,.w3-table td:first-child,.w3-table-all th:first-child,.w3-table-all td:first-child{padding-left:16px} +.w3-btn,.w3-button{border:none;display:inline-block;padding:8px 16px;vertical-align:middle;overflow:hidden;text-decoration:none;color:inherit;background-color:inherit;text-align:center;cursor:pointer;white-space:nowrap} +.w3-btn:hover{box-shadow:0 8px 16px 0 rgba(0,0,0,0.2),0 6px 20px 0 rgba(0,0,0,0.19)} +.w3-btn,.w3-button{-webkit-touch-callout:none;-webkit-user-select:none;-khtml-user-select:none;-moz-user-select:none;-ms-user-select:none;user-select:none} +.w3-disabled,.w3-btn:disabled,.w3-button:disabled{cursor:not-allowed;opacity:0.3}.w3-disabled *,:disabled *{pointer-events:none} +.w3-btn.w3-disabled:hover,.w3-btn:disabled:hover{box-shadow:none} +.w3-badge,.w3-tag{background-color:#000;color:#fff;display:inline-block;padding-left:8px;padding-right:8px;text-align:center}.w3-badge{border-radius:50%} +.w3-ul{list-style-type:none;padding:0;margin:0}.w3-ul li{padding:8px 16px;border-bottom:1px solid #ddd}.w3-ul li:last-child{border-bottom:none} +.w3-tooltip,.w3-display-container{position:relative}.w3-tooltip .w3-text{display:none}.w3-tooltip:hover .w3-text{display:inline-block} +.w3-ripple:active{opacity:0.5}.w3-ripple{transition:opacity 0s} +.w3-input{padding:8px;display:block;border:none;border-bottom:1px solid #ccc;width:100%} +.w3-select{padding:9px 0;width:100%;border:none;border-bottom:1px solid #ccc} +.w3-dropdown-click,.w3-dropdown-hover{position:relative;display:inline-block;cursor:pointer} +.w3-dropdown-hover:hover .w3-dropdown-content{display:block} +.w3-dropdown-hover:first-child,.w3-dropdown-click:hover{background-color:#ccc;color:#000} +.w3-dropdown-hover:hover > .w3-button:first-child,.w3-dropdown-click:hover > .w3-button:first-child{background-color:#ccc;color:#000} +.w3-dropdown-content{cursor:auto;color:#000;background-color:#fff;display:none;position:absolute;min-width:160px;margin:0;padding:0;z-index:1} +/*.w3-check,.w3-radio{width:24px;height:24px;position:relative;top:6px}*/ +.w3-check,.w3-radio{width:24px;position:relative;} +.w3-sidebar{height:100%;width:200px;background-color:#fff;position:fixed!important;z-index:1;overflow:auto} +.w3-bar-block .w3-dropdown-hover,.w3-bar-block .w3-dropdown-click{width:100%} +.w3-bar-block .w3-dropdown-hover .w3-dropdown-content,.w3-bar-block .w3-dropdown-click .w3-dropdown-content{min-width:100%} +.w3-bar-block .w3-dropdown-hover .w3-button,.w3-bar-block .w3-dropdown-click .w3-button{width:100%;text-align:left;padding:8px 16px} +.w3-main,#main{transition:margin-left .4s} +.w3-modal{z-index:3;display:none;padding-top:100px;position:fixed;left:0;top:0;width:100%;height:100%;overflow:auto;background-color:rgb(0,0,0);background-color:rgba(0,0,0,0.4)} +.w3-modal-content{margin:auto;background-color:#fff;position:relative;padding:0;outline:0;width:600px} +.w3-bar{width:100%;overflow:hidden}.w3-center .w3-bar{display:inline-block;width:auto} +.w3-bar .w3-bar-item{padding:8px 16px;float:left;width:auto;border:none;display:block;outline:0} +.w3-bar .w3-dropdown-hover,.w3-bar .w3-dropdown-click{position:static;float:left} +.w3-bar .w3-button{white-space:normal} +.w3-bar-block .w3-bar-item{width:100%;display:block;padding:8px 16px;text-align:left;border:none;white-space:normal;float:none;outline:0} +.w3-bar-block.w3-center .w3-bar-item{text-align:center}.w3-block{display:block;width:100%} +.w3-responsive{display:block;overflow-x:auto} +.w3-container:after,.w3-container:before,.w3-panel:after,.w3-panel:before,.w3-row:after,.w3-row:before,.w3-row-padding:after,.w3-row-padding:before, +.w3-cell-row:before,.w3-cell-row:after,.w3-clear:after,.w3-clear:before,.w3-bar:before,.w3-bar:after{content:"";display:table;clear:both} +.w3-col,.w3-half,.w3-third,.w3-twothird,.w3-threequarter,.w3-quarter{float:left;width:100%} +.w3-col.s1{width:8.33333%}.w3-col.s2{width:16.66666%}.w3-col.s3{width:24.99999%}.w3-col.s4{width:33.33333%} +.w3-col.s5{width:41.66666%}.w3-col.s6{width:49.99999%}.w3-col.s7{width:58.33333%}.w3-col.s8{width:66.66666%} +.w3-col.s9{width:74.99999%}.w3-col.s10{width:83.33333%}.w3-col.s11{width:91.66666%}.w3-col.s12{width:99.99999%} +@media (min-width:601px){.w3-col.m1{width:8.33333%}.w3-col.m2{width:16.66666%}.w3-col.m3,.w3-quarter{width:24.99999%}.w3-col.m4,.w3-third{width:33.33333%} +.w3-col.m5{width:41.66666%}.w3-col.m6,.w3-half{width:49.99999%}.w3-col.m7{width:58.33333%}.w3-col.m8,.w3-twothird{width:66.66666%} +.w3-col.m9,.w3-threequarter{width:74.99999%}.w3-col.m10{width:83.33333%}.w3-col.m11{width:91.66666%}.w3-col.m12{width:99.99999%}} +@media (min-width:993px){.w3-col.l1{width:8.33333%}.w3-col.l2{width:16.66666%}.w3-col.l3{width:24.99999%}.w3-col.l4{width:33.33333%} +.w3-col.l5{width:41.66666%}.w3-col.l6{width:49.99999%}.w3-col.l7{width:58.33333%}.w3-col.l8{width:66.66666%} +.w3-col.l9{width:74.99999%}.w3-col.l10{width:83.33333%}.w3-col.l11{width:91.66666%}.w3-col.l12{width:99.99999%}} +.w3-rest{overflow:hidden}.w3-stretch{margin-left:-16px;margin-right:-16px} +.w3-content,.w3-auto{margin-left:auto;margin-right:auto}.w3-content{max-width:980px}.w3-auto{max-width:1140px} +.w3-cell-row{display:table;width:100%}.w3-cell{display:table-cell} +.w3-cell-top{vertical-align:top}.w3-cell-middle{vertical-align:middle}.w3-cell-bottom{vertical-align:bottom} +.w3-hide{display:none!important}.w3-show-block,.w3-show{display:block!important}.w3-show-inline-block{display:inline-block!important} +@media (max-width:1205px){.w3-auto{max-width:95%}} +@media (max-width:600px){.w3-modal-content{margin:0 10px;width:auto!important}.w3-modal{padding-top:30px} +.w3-dropdown-hover.w3-mobile .w3-dropdown-content,.w3-dropdown-click.w3-mobile .w3-dropdown-content{position:relative} +.w3-hide-small{display:none!important}.w3-mobile{display:block;width:100%!important}.w3-bar-item.w3-mobile,.w3-dropdown-hover.w3-mobile,.w3-dropdown-click.w3-mobile{text-align:center} +.w3-dropdown-hover.w3-mobile,.w3-dropdown-hover.w3-mobile .w3-btn,.w3-dropdown-hover.w3-mobile .w3-button,.w3-dropdown-click.w3-mobile,.w3-dropdown-click.w3-mobile .w3-btn,.w3-dropdown-click.w3-mobile .w3-button{width:100%}} +@media (max-width:768px){.w3-modal-content{width:500px}.w3-modal{padding-top:50px}} +@media (min-width:993px){.w3-modal-content{width:900px}.w3-hide-large{display:none!important}.w3-sidebar.w3-collapse{display:block!important}} +@media (max-width:992px) and (min-width:601px){.w3-hide-medium{display:none!important}} +@media (max-width:992px){.w3-sidebar.w3-collapse{display:none}.w3-main{margin-left:0!important;margin-right:0!important}.w3-auto{max-width:100%}} +.w3-top,.w3-bottom{position:fixed;width:100%;z-index:1}.w3-top{top:0}.w3-bottom{bottom:0} +.w3-overlay{position:fixed;display:none;width:100%;height:100%;top:0;left:0;right:0;bottom:0;background-color:rgba(0,0,0,0.5);z-index:2} +.w3-display-topleft{position:absolute;left:0;top:0}.w3-display-topright{position:absolute;right:0;top:0} +.w3-display-bottomleft{position:absolute;left:0;bottom:0}.w3-display-bottomright{position:absolute;right:0;bottom:0} +.w3-display-middle{position:absolute;top:50%;left:50%;transform:translate(-50%,-50%);-ms-transform:translate(-50%,-50%)} +.w3-display-left{position:absolute;top:50%;left:0%;transform:translate(0%,-50%);-ms-transform:translate(-0%,-50%)} +.w3-display-right{position:absolute;top:50%;right:0%;transform:translate(0%,-50%);-ms-transform:translate(0%,-50%)} +.w3-display-topmiddle{position:absolute;left:50%;top:0;transform:translate(-50%,0%);-ms-transform:translate(-50%,0%)} +.w3-display-bottommiddle{position:absolute;left:50%;bottom:0;transform:translate(-50%,0%);-ms-transform:translate(-50%,0%)} +.w3-display-container:hover .w3-display-hover{display:block}.w3-display-container:hover span.w3-display-hover{display:inline-block}.w3-display-hover{display:none} +.w3-display-position{position:absolute} +.w3-circle{border-radius:50%} +.w3-round-small{border-radius:2px}.w3-round,.w3-round-medium{border-radius:4px}.w3-round-large{border-radius:8px}.w3-round-xlarge{border-radius:16px}.w3-round-xxlarge{border-radius:32px} +.w3-row-padding,.w3-row-padding>.w3-half,.w3-row-padding>.w3-third,.w3-row-padding>.w3-twothird,.w3-row-padding>.w3-threequarter,.w3-row-padding>.w3-quarter,.w3-row-padding>.w3-col{padding:0 8px} +.w3-container,.w3-panel{padding:0.01em 16px}.w3-panel{margin-top:16px;margin-bottom:16px} +.w3-code,.w3-codespan{font-family:Consolas,"courier new";font-size:16px} +.w3-code{width:auto;background-color:#fff;padding:8px 12px;border-left:4px solid #4CAF50;word-wrap:break-word} +.w3-codespan{color:crimson;background-color:#f1f1f1;padding-left:4px;padding-right:4px;font-size:110%} +.w3-card,.w3-card-2{box-shadow:0 2px 5px 0 rgba(0,0,0,0.16),0 2px 10px 0 rgba(0,0,0,0.12)} +.w3-card-4,.w3-hover-shadow:hover{box-shadow:0 4px 10px 0 rgba(0,0,0,0.2),0 4px 20px 0 rgba(0,0,0,0.19)} +.w3-spin{animation:w3-spin 2s infinite linear}@keyframes w3-spin{0%{transform:rotate(0deg)}100%{transform:rotate(359deg)}} +.w3-animate-fading{animation:fading 10s infinite}@keyframes fading{0%{opacity:0}50%{opacity:1}100%{opacity:0}} +.w3-animate-opacity{animation:opac 0.8s}@keyframes opac{from{opacity:0} to{opacity:1}} +.w3-animate-top{position:relative;animation:animatetop 0.4s}@keyframes animatetop{from{top:-300px;opacity:0} to{top:0;opacity:1}} +.w3-animate-left{position:relative;animation:animateleft 0.4s}@keyframes animateleft{from{left:-300px;opacity:0} to{left:0;opacity:1}} +.w3-animate-right{position:relative;animation:animateright 0.4s}@keyframes animateright{from{right:-300px;opacity:0} to{right:0;opacity:1}} +.w3-animate-bottom{position:relative;animation:animatebottom 0.4s}@keyframes animatebottom{from{bottom:-300px;opacity:0} to{bottom:0;opacity:1}} +.w3-animate-zoom {animation:animatezoom 0.6s}@keyframes animatezoom{from{transform:scale(0)} to{transform:scale(1)}} +.w3-animate-input{transition:width 0.4s ease-in-out}.w3-animate-input:focus{width:100%!important} +.w3-opacity,.w3-hover-opacity:hover{opacity:0.60}.w3-opacity-off,.w3-hover-opacity-off:hover{opacity:1} +.w3-opacity-max{opacity:0.25}.w3-opacity-min{opacity:0.75} +.w3-greyscale-max,.w3-grayscale-max,.w3-hover-greyscale:hover,.w3-hover-grayscale:hover{filter:grayscale(100%)} +.w3-greyscale,.w3-grayscale{filter:grayscale(75%)}.w3-greyscale-min,.w3-grayscale-min{filter:grayscale(50%)} +.w3-sepia{filter:sepia(75%)}.w3-sepia-max,.w3-hover-sepia:hover{filter:sepia(100%)}.w3-sepia-min{filter:sepia(50%)} +.w3-tiny{font-size:10px!important}.w3-small{font-size:12px!important}.w3-medium{font-size:15px!important}.w3-large{font-size:18px!important} +.w3-xlarge{font-size:24px!important}.w3-xxlarge{font-size:36px!important}.w3-xxxlarge{font-size:48px!important}.w3-jumbo{font-size:64px!important} +.w3-left-align{text-align:left!important}.w3-right-align{text-align:right!important}.w3-justify{text-align:justify!important}.w3-center{text-align:center!important} +.w3-border-0{border:0!important}.w3-border{border:1px solid #ccc!important} +.w3-border-top{border-top:1px solid #ccc!important}.w3-border-bottom{border-bottom:1px solid #ccc!important} +.w3-border-left{border-left:1px solid #ccc!important}.w3-border-right{border-right:1px solid #ccc!important} +.w3-topbar{border-top:6px solid #ccc!important}.w3-bottombar{border-bottom:6px solid #ccc!important} +.w3-leftbar{border-left:6px solid #ccc!important}.w3-rightbar{border-right:6px solid #ccc!important} +.w3-section,.w3-code{margin-top:16px!important;margin-bottom:16px!important} +.w3-margin{margin:16px!important}.w3-margin-top{margin-top:16px!important}.w3-margin-bottom{margin-bottom:16px!important} +.w3-margin-left{margin-left:16px!important}.w3-margin-right{margin-right:16px!important} +.w3-padding-small{padding:4px 8px!important}.w3-padding{padding:8px 16px!important}.w3-padding-large{padding:12px 24px!important} +.w3-padding-16{padding-top:16px!important;padding-bottom:16px!important}.w3-padding-24{padding-top:24px!important;padding-bottom:24px!important} +.w3-padding-32{padding-top:32px!important;padding-bottom:32px!important}.w3-padding-48{padding-top:48px!important;padding-bottom:48px!important} +.w3-padding-64{padding-top:64px!important;padding-bottom:64px!important} +.w3-padding-top-64{padding-top:64px!important}.w3-padding-top-48{padding-top:48px!important} +.w3-padding-top-32{padding-top:32px!important}.w3-padding-top-24{padding-top:24px!important} +.w3-left{float:left!important}.w3-right{float:right!important} +.w3-button:hover{color:#000!important;background-color:#ccc!important} +.w3-transparent,.w3-hover-none:hover{background-color:transparent!important} +.w3-hover-none:hover{box-shadow:none!important} diff --git a/webfiles/gauges.htm b/webfiles/gauges.htm new file mode 100644 index 0000000..e7b546a --- /dev/null +++ b/webfiles/gauges.htm @@ -0,0 +1,257 @@ + + + + + + + + + Cumulus MX + + + + + + + + + + + + + + + + + + + + + + +
+
+
+
+
+

Gauges

+
+
+
+
Status:
+
+
+ +
+ +
+
Temperature
+
+
+
Other Temps
+
+
+
+
+
+
+
Humidity
+
+
+
+
+
+
+
+
+
+ +
+
+
+ +
+
+ +
Temperature
+
+
+ +
+
+
+
+ +
Other Temps
+
+
+ +
+
+
+
+ +
Humidity
+
+
+ +
+
+
+
+ +
Wind
+
+ +
+
+
+ +
Wind Direction
+
+ +
+
+
+ +
Wind Rose
+
+ +
+
+
+ +
Pressure
+
+ +
+
+
+ +
Rainfall
+
+ +
+
+
+ +
Rainfall Rate
+
+ +
+
+
+ +
UV Radiation
+
+ +
+
+
+ +
Solar
+
+ +
+
+
+ +
Cloudbase
+
+ +
+
+
+ +
+
+
+
+ + + +
+
+
+ × +

Gauge Units

+
+
+
+
Temperature:
+
+
+ +
Rainfall
+
+
+ +
Pressure
+
+
+
 
+
+
+ +
Wind Speed
+
+
+
 
+
+
+ +
Cloud Base
+
+
+
+
+
+

Powered by Cumulus MX

+
+
+
+ + + + + + + + + + + diff --git a/webfiles/historic.htm b/webfiles/historic.htm new file mode 100644 index 0000000..5199e69 --- /dev/null +++ b/webfiles/historic.htm @@ -0,0 +1,112 @@ + + + + + + + + + Cumulus MX + + + + + + + + + + + + + + + + + + + + +
+
+
+

Charts based on summary data

+

Welcome to

+
+
+
+
+
+
+
+
+
+
+
+
+
+
+
+ + + + + + + + +
+

Mouse over the chart to see the values at any given time. + You can add or remove data sets from the chart by clicking the entry on the chart legend.

+
+
+
+
+ + + + + + + + + + \ No newline at end of file diff --git a/webfiles/images/CumulusMX-Logo.png b/webfiles/images/CumulusMX-Logo.png new file mode 100644 index 0000000..ecf0246 Binary files /dev/null and b/webfiles/images/CumulusMX-Logo.png differ diff --git a/webfiles/images/favicon.png b/webfiles/images/favicon.png new file mode 100644 index 0000000..26f009f Binary files /dev/null and b/webfiles/images/favicon.png differ diff --git a/webfiles/images/picture.jpg b/webfiles/images/picture.jpg new file mode 100644 index 0000000..2336b37 Binary files /dev/null and b/webfiles/images/picture.jpg differ diff --git a/webfiles/index.htm b/webfiles/index.htm new file mode 100644 index 0000000..5d4bb51 --- /dev/null +++ b/webfiles/index.htm @@ -0,0 +1,238 @@ + + + + + + + + + Cumulus MX + + + + + + + + + + + + + + + + + + + + +
+
+
+

Weather

+
+
+
+
+
+
+
+

Almanac

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Dawn:Sun Rise:Moon Rise:MoonVisible %
Dusk:Sun Set:Moon Set:
Daylight:Day Length:Moon Phase:
Current conditions:
+
+
+
+
+
+
+
+

Conditions at local time

+
+ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + +
Temperature and Humidity
Temperature Dew Point 
Windchill Humidity %
Heat Index Apparent TemperatureFeels Like 
Temp change last hour 
Rainfall
Rainfall Today Rainfall Rate /hr
Rainfall This Month Rainfall This Year 
Rainfall Last Hour Last rainfall
Rainfall Since Midnight Rainfall Last 24 Hours 
Wind
Wind Speed (gust) Wind Speed (avg) 
Wind Bearing° Beaufort
Wind Variation (last 10 minutes)From ° to °
Pressure (sea level)
Barometer  /hr
Solar
Solar Radiation W/m²Evapotranspiration Today 
UV Index
+
+

Page updated .

+
+
+
+
+
+
+
+
+

Welcome to

+

The weather station in use is the
+ This page is updated every minutes. The meteorological day used at this station ends at . +

+

Forecast:

+
+
+
+
+
+
+ + + \ No newline at end of file diff --git a/webfiles/js/alltimerecdata.js b/webfiles/js/alltimerecdata.js new file mode 100644 index 0000000..a719166 --- /dev/null +++ b/webfiles/js/alltimerecdata.js @@ -0,0 +1,40 @@ +// Last modified: 2021/03/19 09:15:55 + + +$.getJSON("websitedata.json", function (json) { + console.log( "success" ); + var cmx_data = json; + + $(document).prop('title', cmx_data['cmx-location'] + ' weather'); + $('meta[name=description]').attr('content', cmx_data['cmx-location'] + ' weather data'); + $('meta[name=keywords]').attr('content', $('meta[name=keywords]').attr('content') + ', ' + cmx_data['cmx-location'] + ' weather data'); + + $.getJSON("alltimerecdata.json", function (json) { + console.log( "success" ); + Object.keys(json).forEach(key => { + cmx_data[key] = json[key]; + }); + + // Update all spans with id beginning "cmx-" + $('span[id^=cmx-]').each(function () { + this.innerHTML = cmx_data[this.id]; + }); + // Update all spans with class beginning "cmx-" + $('span[class^=cmx-]').each(function () { + this.innerHTML = cmx_data[this.className]; + }); + }) + .fail(function (jqxhr, textStatus, error) { + var err = textStatus + ", " + error; + console.log("Request Failed: " + err); + }); + + +}) +.fail(function (jqxhr, textStatus, error) { + var err = textStatus + ", " + error; + console.log( "Request Failed: " + err ); +}); + +$(document).ready(function() { +}); \ No newline at end of file diff --git a/webfiles/js/cumuluscharts.js b/webfiles/js/cumuluscharts.js new file mode 100644 index 0000000..54f3c3c --- /dev/null +++ b/webfiles/js/cumuluscharts.js @@ -0,0 +1,2463 @@ +// Last modified: 2023/03/16 09:59:29 + +var chart, config; + +var myRangeBtns = { + buttons: [{ + count: 12, + type: 'hour', + text: '12h' + }, { + count: 24, + type: 'hour', + text: '24h' + }, { + count: 2, + type: 'day', + text: '2d' + }, { + type: 'all', + text: 'All' + }], + inputEnabled: false, + selected: 1 +}; + +$(document).ready(function () { + $('#mySelect').change(function () { + changeGraph($('#mySelect').val()); + }); + + + $.ajax({ + url: "availabledata.json", + dataType: "json", + success: function (result) { + if (result.Temperature === undefined || result.Temperature.Count == 0) { + $('#mySelect option[value="temp"]').remove(); + } + if (result.DailyTemps === undefined || result.DailyTemps.Count == 0) { + $('#mySelect option[value="dailytemp"]').remove(); + } + if (result.Humidity === undefined || result.Humidity.Count == 0) { + $('#mySelect option[value="humidity"]').remove(); + } + if (result.Solar === undefined || result.Solar.Count == 0) { + $('#mySelect option[value="solar"]').remove(); + } + if (result.Sunshine === undefined || result.Sunshine.Count == 0) { + $('#mySelect option[value="sunhours"]').remove(); + } + if (result.AirQuality === undefined || result.AirQuality.Count == 0) { + $('#mySelect option[value="airquality"]').remove(); + } + if (result.ExtraTemp == undefined || result.ExtraTemp.Count == 0) { + $('#mySelect option[value="extratemp"]').remove(); + } + if (result.ExtraHum == undefined || result.ExtraHum.Count == 0) { + $('#mySelect option[value="extrahum"]').remove(); + } + if (result.ExtraDewPoint == undefined || result.ExtraDewPoint.Count == 0) { + $('#mySelect option[value="extradew"]').remove(); + } + if (result.SoilTemp == undefined || result.SoilTemp.Count == 0) { + $('#mySelect option[value="soiltemp"]').remove(); + } + if (result.SoilMoist == undefined || result.SoilMoist.Count == 0) { + $('#mySelect option[value="soilmoist"]').remove(); + } + if (result.LeafWetness == undefined || result.LeafWetness.Count == 0) { + $('#mySelect option[value="leafwet"]').remove(); + } + if (result.UserTemp == undefined || result.UserTemp.Count == 0) { + $('#mySelect option[value="usertemp"]').remove(); + } + if (result.CO2 == undefined || result.CO2.Count == 0) { + $('#mySelect option[value="co2"]').remove(); + } + } + }); + + $.ajax({ + url: "graphconfig.json", + dataType: "json", + success: function (result) { + config = result; + var value = parent.location.hash.replace('#', ''); + if (value == '') + value = 'temp'; + + changeGraph(value); + // set the correct option + $('#mySelect option[value="' + value + '"]').attr('selected', true); + } + }); +}); + + +function changeGraph(graph) { + switch (graph) { + case 'temp': + doTemp(); + break; + case 'dailytemp': + doDailyTemp(); + break; + case 'press': + doPress(); + break; + case 'wind': + doWind(); + break; + case 'windDir': + doWindDir(); + break; + case 'rain': + doRain(); + break; + case 'dailyrain': + doDailyRain(); + break; + case 'humidity': + doHum(); + break; + case 'solar': + doSolar(); + break; + case 'sunhours': + doSunHours(); + break; + case 'airquality': + doAirQuality(); + break; + case 'extratemp': + doExtraTemp(); + break; + case 'extrahum': + doExtraHum(); + break; + case 'extradew': + doExtraDew(); + break; + case 'soiltemp': + doSoilTemp(); + break; + case 'soilmoist': + doSoilMoist(); + break; + case 'leafwet': + doLeafWet(); + break; + case 'usertemp': + doUserTemp(); + break; + case 'co2': + doCO2(); + break; + default: + doTemp(); + break; + } + parent.location.hash = graph; +} + +var doTemp = function () { + var freezing = config.temp.units === 'C' ? 0 : 32; + var options = { + chart: { + renderTo: 'chartcontainer', + type: 'line', + alignTicks: false + }, + title: { + text: 'Temperature' + }, + credits: { + enabled: true + }, + xAxis: { + type: 'datetime', + ordinal: false, + dateTimeLabelFormats: { + day: '%e %b', + week: '%e %b %y', + month: '%b %y', + year: '%Y' + } + }, + yAxis: [{ + // left + title: { + text: 'Temperature (°' + config.temp.units + ')' + }, + opposite: false, + labels: { + align: 'right', + x: -5, + formatter: function () { + return '' + this.value + ''; + } + }, + plotLines: [{ + // freezing line + value: freezing, + color: 'rgb(0, 0, 180)', + width: 1, + zIndex: 2 + }] + }, { + // right + gridLineWidth: 0, + linkedTo: 0, + opposite: true, + labels: { + align: 'left', + x: 5, + formatter: function () { + return '' + this.value + ''; + } + } + }], + legend: { + enabled: true + }, + plotOptions: { + series: { + dataGrouping: { + enabled: false + }, + states: { + hover: { + halo: { + size: 5, + opacity: 0.25 + } + } + }, + cursor: 'pointer', + marker: { + enabled: false, + states: { + hover: { + enabled: true, + radius: 0.1 + } + } + } + }, + line: { + lineWidth: 2 + } + }, + tooltip: { + shared: true, + crosshairs: true, + valueDecimals: config.temp.decimals, + xDateFormat: "%A, %b %e, %H:%M" + }, + series: [], + rangeSelector: myRangeBtns + }; + + chart = new Highcharts.StockChart(options); + chart.showLoading(); + + $.ajax({ + url: 'tempdata.json', + cache: false, + dataType: 'json', + success: function (resp) { + var titles = { + 'temp' : 'Temperature', + 'dew' : 'Dew Point', + 'apptemp' : 'Apparent', + 'feelslike': 'Feels Like', + 'wchill' : 'Wind Chill', + 'heatindex': 'Heat Index', + 'humidex' : 'Humidex', + 'intemp' : 'Inside' + }; + var idxs = ['temp', 'dew', 'apptemp', 'feelslike', 'wchill', 'heatindex', 'humidex', 'intemp']; + var yaxis = 0; + + idxs.forEach(function(idx) { + var valueSuffix = ' °' + config.temp.units; + yaxis = 0; + + if (idx in resp) { + if (idx === 'humidex') { + valueSuffix = null; + if (config.temp.units == 'F') { + chart.yAxis[1].remove(); + chart.addAxis({ + id: 'humidex', + title:{text: 'Humidex'}, + opposite: true, + labels: { + align: 'left' + }, + alignTicks: true, + gridLineWidth: 0, // Not working? + gridZIndex: -10, // Hides the grid lines for this axis + showEmpty: false + }, false, false); + + yaxis = 'humidex'; + } + } + + chart.addSeries({ + name: titles[idx], + id: 'series-' + idx, + data: resp[idx], + color: config.series[idx].colour, + yAxis: yaxis, + tooltip: {valueSuffix: valueSuffix} + }, false); + + if (idx === 'temp') { + chart.get('series-' + idx).options.zIndex = 99; + } + } + }); + + chart.hideLoading(); + chart.redraw(); + } + }); +}; + +var doPress = function () { + var options = { + chart: { + renderTo: 'chartcontainer', + type: 'line', + alignTicks: false + }, + title: { + text: 'Pressure' + }, + credits: { + enabled: true + }, + xAxis: { + type: 'datetime', + ordinal: false, + dateTimeLabelFormats: { + day: '%e %b', + week: '%e %b %y', + month: '%b %y', + year: '%Y' + } + }, + yAxis: [{ + // left + title: { + text: 'Pressure (' + config.press.units + ')' + }, + opposite: false, + labels: { + align: 'right', + x: -5 + } + }, { + // right + linkedTo: 0, + gridLineWidth: 0, + opposite: true, + title: { + text: null + }, + labels: { + align: 'left', + x: 5 + } + }], + legend: { + enabled: true + }, + plotOptions: { + series: { + dataGrouping: { + enabled: false + }, + states: { + hover: { + halo: { + size: 5, + opacity: 0.25 + } + } + }, + cursor: 'pointer', + marker: { + enabled: false, + states: { + hover: { + enabled: true, + radius: 0.1 + } + } + } + }, + line: { + lineWidth: 2 + } + }, + tooltip: { + shared: true, + split: false, + valueSuffix: ' ' + config.press.units, + valueDecimals: config.press.decimals, + xDateFormat: "%A, %b %e, %H:%M" + }, + series: [{ + name: 'Pressure', + color: config.series.press.colour + }], + rangeSelector: myRangeBtns + }; + + chart = new Highcharts.StockChart(options); + chart.showLoading(); + + $.ajax({ + url: 'pressdata.json', + dataType: 'json', + cache: false, + success: function (resp) { + chart.hideLoading(); + chart.series[0].setData(resp.press); + } + }); +}; + +var compassP = function (deg) { + var a = ['N', 'NE', 'E', 'SE', 'S', 'SW', 'W', 'NW']; + return a[Math.floor((deg + 22.5) / 45) % 8]; +}; + +var doWindDir = function () { + var options = { + chart: { + renderTo: 'chartcontainer', + type: 'scatter', + alignTicks: false + }, + title: { + text: 'Wind Direction' + }, + credits: { + enabled: true + }, + navigator: { + series: { + // pseudo scatter + type: 'line', + dataGrouping: { + groupPixelWidth: 1, + anchor: 1 + }, + lineWidth: 0, + marker : { + // enable the marker to simulate a scatter + enabled: true, + radius : 1 + } + } + }, + xAxis: { + type: 'datetime', + ordinal: false, + dateTimeLabelFormats: { + day: '%e %b', + week: '%e %b %y', + month: '%b %y', + year: '%Y' + } + }, + yAxis: [{ + // left + title: { + text: 'Bearing' + }, + opposite: false, + min: 0, + max: 360, + tickInterval: 45, + labels: { + align: 'right', + x: -5, + formatter: function () { + return compassP(this.value); + } + } + }, { + // right + linkedTo: 0, + gridLineWidth: 0, + opposite: true, + title: { + text: null + }, + min: 0, + max: 360, + tickInterval: 45, + labels: { + align: 'left', + x: 5, + formatter: function () { + return compassP(this.value); + } + } + }], + legend: { + enabled: true + }, + plotOptions: { + scatter: { + cursor: 'pointer', + enableMouseTracking: true, + boostThreshold: 200, + marker: { + states: { + hover: { + enabled: false + }, + select: { + enabled: false + } + } + }, + shadow: false, + label: { + enabled: false + } + } + }, + tooltip: { + enabled: true, + split: true, + useHTML: true + }, + series: [{ + name: 'Bearing', + type: 'scatter', + color: config.series.bearing.colour, + marker: { + symbol: 'circle', + radius: 2 + }, + enableMouseTracking: false, + showInNavigator: false + }, { + name: 'Avg Bearing', + type: 'scatter', + color: config.series.avgbearing.colour, + marker: { + symbol: 'circle', + radius: 2 + }, + showInNavigator: true, + tooltip: { + headerFormat: '', + xDateFormat: '%A, %b %e %H:%M ', + pointFormatter() { + return '\u25CF ' + + this.series.name + ': ' + (this.y == 0 ? 'calm' : this.y + '°') + '
'; + } + } + }], + rangeSelector: myRangeBtns + }; + + chart = new Highcharts.StockChart(options); + chart.showLoading(); + + $.ajax({ + url: 'wdirdata.json', + dataType: 'json', + cache: false, + success: function (resp) { + chart.hideLoading(); + chart.series[0].setData(resp.bearing); + chart.series[1].setData(resp.avgbearing); + } + }); +}; + +var doWind = function () { + var options = { + chart: { + renderTo: 'chartcontainer', + type: 'line', + alignTicks: false + }, + title: { + text: 'Wind Speed' + }, + credits: { + enabled: true + }, + xAxis: { + type: 'datetime', + ordinal: false, + dateTimeLabelFormats: { + day: '%e %b', + week: '%e %b %y', + month: '%b %y', + year: '%Y' + } + }, + yAxis: [{ + // left + title: { + text: 'Wind Speed (' + config.wind.units + ')' + }, + opposite: false, + min: 0, + labels: { + align: 'right', + x: -5 + } + }, { + // right + linkedTo: 0, + gridLineWidth: 0, + opposite: true, + min: 0, + title: { + text: null + }, + labels: { + align: 'left', + x: 5 + } + }], + legend: { + enabled: true + }, + plotOptions: { + series: { + dataGrouping: { + enabled: false + }, + states: { + hover: { + halo: { + size: 5, + opacity: 0.25 + } + } + }, + cursor: 'pointer', + marker: { + enabled: false, + states: { + hover: { + enabled: true, + radius: 0.1 + } + } + } + }, + line: { + lineWidth: 2 + } + }, + tooltip: { + shared: true, + crosshairs: true, + valueSuffix: ' ' + config.wind.units, + valueDecimals: config.wind.decimals, + xDateFormat: "%A, %b %e, %H:%M" + }, + series: [{ + name: 'Wind Speed', + color: config.series.wspeed.colour + }, { + name: 'Wind Gust', + color: config.series.wgust.colour + }], + rangeSelector: myRangeBtns + }; + + chart = new Highcharts.StockChart(options); + chart.showLoading(); + + $.ajax({ + url: 'winddata.json', + dataType: 'json', + cache: false, + success: function (resp) { + chart.hideLoading(); + chart.series[0].setData(resp.wspeed); + chart.series[1].setData(resp.wgust); + } + }); +}; + +var doRain = function () { + var options = { + chart: { + renderTo: 'chartcontainer', + type: 'line', + alignTicks: true + }, + title: { + text: 'Rainfall' + }, + credits: { + enabled: true + }, + xAxis: { + type: 'datetime', + ordinal: false, + dateTimeLabelFormats: { + day: '%e %b', + week: '%e %b %y', + month: '%b %y', + year: '%Y' + } + }, + yAxis: [{ + // left + title: { + text: 'Rainfall rate (' + config.rain.units + '/hr)' + }, + min: 0, + opposite: false, + labels: { + align: 'right', + x: -5 + }, + showEmpty: false + }, { + // right + opposite: true, + title: { + text: 'Rainfall (' + config.rain.units + ')' + }, + min: 0, + labels: { + align: 'left', + x: 5 + } + }], + legend: { + enabled: true + }, + plotOptions: { + series: { + boostThreshold: 0, + dataGrouping: { + enabled: false + }, + showInNavigator: true, + states: { + hover: { + halo: { + size: 5, + opacity: 0.25 + } + } + }, + cursor: 'pointer', + marker: { + enabled: false, + states: { + hover: { + enabled: true, + radius: 0.1 + } + } + } + }, + line: { + lineWidth: 2 + } + }, + tooltip: { + shared: true, + crosshairs: true, + valueDecimals: config.rain.decimals, + xDateFormat: "%A, %b %e, %H:%M" + }, + series: [{ + name: 'Daily rain', + type: 'area', + color: config.series.rfall.colour, + yAxis: 1, + tooltip: {valueSuffix: ' ' + config.rain.units}, + fillOpacity: 0.3 + }, { + name: 'Rain rate', + type: 'line', + color: config.series.rrate.colour, + yAxis: 0, + tooltip: {valueSuffix: ' ' + config.rain.units + '/hr'} + }], + rangeSelector: myRangeBtns + }; + + chart = new Highcharts.StockChart(options); + chart.showLoading(); + + $.ajax({ + url: 'raindata.json', + dataType: 'json', + cache: false, + success: function (resp) { + chart.hideLoading(); + chart.series[0].setData(resp.rfall); + chart.series[1].setData(resp.rrate); + } + }); +}; + +var doHum = function () { + var options = { + chart: { + renderTo: 'chartcontainer', + type: 'line', + alignTicks: false + }, + title: { + text: 'Relative Humidity' + }, + credits: { + enabled: true + }, + xAxis: { + type: 'datetime', + ordinal: false, + dateTimeLabelFormats: { + day: '%e %b', + week: '%e %b %y', + month: '%b %y', + year: '%Y' + } + }, + yAxis: [{ + // left + title: { + text: 'Humidity (%)' + }, + opposite: false, + min: 0, + max: 100, + labels: { + align: 'right', + x: -5 + } + }, { + // right + linkedTo: 0, + gridLineWidth: 0, + opposite: true, + min: 0, + max: 100, + title: { + text: null + }, + labels: { + align: 'left', + x: 5 + } + }], + legend: { + enabled: true + }, + plotOptions: { + series: { + dataGrouping: { + enabled: false + }, + states: { + hover: { + halo: { + size: 5, + opacity: 0.25 + } + } + }, + cursor: 'pointer', + marker: { + enabled: false, + states: { + hover: { + enabled: true, + radius: 0.1 + } + } + } + }, + line: { + lineWidth: 2 + } + }, + tooltip: { + shared: true, + crosshairs: true, + valueSuffix: ' %', + valueDecimals: config.hum.decimals, + xDateFormat: "%A, %b %e, %H:%M" + }, + series: [], + rangeSelector: myRangeBtns + }; + + chart = new Highcharts.StockChart(options); + chart.showLoading(); + + $.ajax({ + url: 'humdata.json', + dataType: 'json', + cache: false, + success: function (resp) { + var titles = { + 'hum' : 'Outdoor Humidity', + 'inhum': 'Indoor Humidity' + } + var idxs = ['hum', 'inhum']; + var cnt = 0; + idxs.forEach(function(idx) { + if (idx in resp) { + chart.addSeries({ + name: titles[idx], + color: config.series[idx].colour, + data: resp[idx] + }, false); + + cnt++; + } + }); + + chart.hideLoading(); + chart.redraw(); + } + }); +}; + +var doSolar = function () { + var options = { + chart: { + renderTo: 'chartcontainer', + type: 'line', + alignTicks: true + }, + title: { + text: 'Solar' + }, + credits: { + enabled: true + }, + xAxis: { + type: 'datetime', + ordinal: false, + dateTimeLabelFormats: { + day: '%e %b', + week: '%e %b %y', + month: '%b %y', + year: '%Y' + } + }, + yAxis: [], + legend: { + enabled: true + }, + plotOptions: { + series: { + boostThreshold: 0, + dataGrouping: { + enabled: false + }, + showInNavigator: true, + states: { + hover: { + halo: { + size: 5, + opacity: 0.25 + } + } + }, + cursor: 'pointer', + marker: { + enabled: false, + states: { + hover: { + enabled: true, + radius: 0.1 + } + } + } + }, + line: { + lineWidth: 2 + } + }, + tooltip: { + shared: true, + crosshairs: true, + xDateFormat: "%A, %b %e, %H:%M" + }, + series: [], + rangeSelector: myRangeBtns + }; + + chart = new Highcharts.StockChart(options); + chart.showLoading(); + + $.ajax({ + url: 'solardata.json', + dataType: 'json', + cache: false, + success: function (resp) { + var titles = { + SolarRad : 'Solar Radiation', + CurrentSolarMax: 'Theoretical Max', + UV: 'UV Index' + }; + var types = { + SolarRad: 'area', + CurrentSolarMax: 'area', + UV: 'line' + }; + var colours = { + SolarRad: 'rgb(255,165,0)', + CurrentSolarMax: 'rgb(128,128,128)', + UV: 'rgb(0,0,255)' + }; + var tooltips = { + SolarRad: { + valueSuffix: ' W/m\u00B2', + valueDecimals: 0 + }, + CurrentSolarMax: { + valueSuffix: ' W/m\u00B2', + valueDecimals: 0 + }, + UV: { + valueSuffix: null, + valueDecimals: config.uv.decimals + } + }; + + var idxs = ['SolarRad', 'CurrentSolarMax', 'UV']; + var cnt = 0; + var solarAxisCreated = false; + + idxs.forEach(function(idx) { + if (idx in resp) { + if (idx === 'UV') { + chart.addAxis({ + id: 'uv', + title:{text: 'UV Index'}, + opposite: true, + min: 0, + labels: { + align: 'left' + }, + showEmpty: false + }); + } else if (!solarAxisCreated) { + chart.addAxis({ + id: 'solar', + title: {text: 'Solar Radiation (W/m\u00B2)'}, + min: 0, + opposite: false, + labels: { + align: 'right', + x: -5 + }, + showEmpty: false + }); + solarAxisCreated = true; + } + + + chart.addSeries({ + name: titles[idx], + type: types[idx], + yAxis: idx === 'UV' ? 'uv' : 'solar', + tooltip: tooltips[idx], + data: resp[idx], + color: config.series[idx.toLowerCase()].colour, + fillOpacity: idx === 'CurrentSolarMax' ? 0.2 : 0.5, + zIndex: 100 - cnt + }, false); + + cnt++; + } + }); + + chart.hideLoading(); + chart.redraw(); + } + }); +}; + +var doSunHours = function () { + var options = { + chart: { + renderTo: 'chartcontainer', + type: 'column', + alignTicks: false + }, + title: { + text: 'Sunshine Hours' + }, + credits: { + enabled: true + }, + xAxis: { + type: 'datetime', + ordinal: false, + dateTimeLabelFormats: { + day: '%e %b', + week: '%e %b %y', + month: '%b %y', + year: '%Y' + } + }, + yAxis: [{ + // left + title: { + text: 'Sunshine Hours' + }, + min: 0, + opposite: false, + labels: { + align: 'right', + x: -12 + } + }, { + // right + linkedTo: 0, + gridLineWidth: 0, + opposite: true, + title: { + text: null + }, + labels: { + align: 'left', + x: 12 + } + }], + legend: { + enabled: true + }, + plotOptions: { + series: { + dataGrouping: { + enabled: false + }, + pointPadding: 0, + groupPadding: 0.1, + states: { + hover: { + halo: { + size: 5, + opacity: 0.25 + } + } + }, + cursor: 'pointer', + marker: { + enabled: false, + states: { + hover: { + enabled: true, + radius: 0.1 + } + } + } + } + }, + tooltip: { + shared: true, + crosshairs: true, + xDateFormat: "%A, %b %e" + }, + series: [{ + name: 'Sunshine Hours', + type: 'column', + color: config.series.sunshine.colour, + yAxis: 0, + valueDecimals: 1, + tooltip: { + valueSuffix: ' Hrs' + } + }] + }; + + chart = new Highcharts.Chart(options); + chart.showLoading(); + + $.ajax({ + url: 'sunhours.json', + dataType: 'json', + cache: false, + success: function (resp) { + chart.hideLoading(); + chart.series[0].setData(resp.sunhours); + } + }); +}; + +var doDailyRain = function () { + var options = { + chart: { + renderTo: 'chartcontainer', + type: 'column', + alignTicks: false + }, + title: { + text: 'Daily Rainfall' + }, + credits: { + enabled: true + }, + xAxis: { + type: 'datetime', + ordinal: false, + dateTimeLabelFormats: { + day: '%e %b', + week: '%e %b %y', + month: '%b %y', + year: '%Y' + } + }, + yAxis: [{ + // left + title: { + text: 'Daily Rainfall' + }, + min: 0, + opposite: false, + labels: { + align: 'right', + x: -12 + } + }, { + // right + linkedTo: 0, + gridLineWidth: 0, + opposite: true, + title: { + text: null + }, + labels: { + align: 'left', + x: 12 + } + }], + legend: { + enabled: true + }, + plotOptions: { + series: { + dataGrouping: { + enabled: false + }, + pointPadding: 0, + groupPadding: 0.1, + states: { + hover: { + halo: { + size: 5, + opacity: 0.25 + } + } + }, + cursor: 'pointer', + marker: { + enabled: false, + states: { + hover: { + enabled: true, + radius: 0.1 + } + } + } + } + }, + tooltip: { + shared: true, + crosshairs: true, + xDateFormat: "%A, %b %e" + }, + series: [{ + name: 'Daily Rainfall', + type: 'column', + color: config.series.rfall.colour, + yAxis: 0, + valueDecimals: config.rain.decimals, + tooltip: { + valueSuffix: ' ' + config.rain.units + } + }] + }; + + chart = new Highcharts.Chart(options); + chart.showLoading(); + + $.ajax({ + url: 'dailyrain.json', + dataType: 'json', + cache: false, + success: function (resp) { + chart.hideLoading(); + chart.series[0].setData(resp.dailyrain); + } + }); +}; + +var doDailyTemp = function () { + var freezing = config.temp.units === 'C' ? 0 : 32; + var options = { + chart: { + renderTo: 'chartcontainer', + type: 'line', + alignTicks: false + }, + title: { + text: 'Daily Temperature' + }, + credits: { + enabled: true + }, + xAxis: { + type: 'datetime', + ordinal: false, + dateTimeLabelFormats: { + day: '%e %b', + week: '%e %b %y', + month: '%b %y', + year: '%Y' + } + }, + yAxis: [{ + // left + title: { + text: 'Daily Temperature (°' + config.temp.units + ')' + }, + opposite: false, + labels: { + align: 'right', + x: -5, + formatter: function () { + return '' + this.value + ''; + } + }, + plotLines: [{ + // freezing line + value: freezing, + color: 'rgb(0, 0, 180)', + width: 1, + zIndex: 2 + }] + }, { + // right + linkedTo: 0, + gridLineWidth: 0, + opposite: true, + title: { + text: null + }, + labels: { + align: 'left', + x: 5, + formatter: function () { + return '' + this.value + ''; + } + } + }], + legend: { + enabled: true + }, + plotOptions: { + series: { + dataGrouping: { + enabled: false + }, + states: { + hover: { + halo: { + size: 5, + opacity: 0.25 + } + } + }, + cursor: 'pointer', + marker: { + enabled: false, + states: { + hover: { + enabled: true, + radius: 0.1 + } + } + } + }, + line: { + lineWidth: 2 + } + }, + tooltip: { + shared: true, + crosshairs: true, + valueSuffix: ' °' + config.temp.units, + valueDecimals: config.temp.decimals, + xDateFormat: "%A, %b %e" + }, + rangeSelector: { + enabled: false + }, + series: [] + }; + + chart = new Highcharts.StockChart(options); + chart.showLoading(); + + $.ajax({ + url: 'dailytemp.json', + dataType: 'json', + cache: false, + success: function (resp) { + var titles = { + 'avgtemp': 'Avg Temp', + 'mintemp': 'Min Temp', + 'maxtemp': 'Max Temp' + }; + var idxs = ['avgtemp', 'mintemp', 'maxtemp']; + + idxs.forEach(function (idx) { + if (idx in resp) { + chart.addSeries({ + name: titles[idx], + data: resp[idx], + color: config.series[idx].colour + }, false); + } + }); + + chart.hideLoading(); + chart.redraw(); + } + }); +}; + +var doAirQuality = function () { + var options = { + chart: { + renderTo: 'chartcontainer', + type: 'line', + alignTicks: false + }, + title: {text: 'Air Quality'}, + credits: {enabled: true}, + xAxis: { + type: 'datetime', + ordinal: false, + dateTimeLabelFormats: { + day: '%e %b', + week: '%e %b %y', + month: '%b %y', + year: '%Y' + } + }, + yAxis: [{ + // left + title: {text: 'µg/m³'}, + opposite: false, + min: 0, + labels: { + align: 'right', + x: -5 + } + }, { + // right + linkedTo: 0, + gridLineWidth: 0, + opposite: true, + min: 0, + title: {text: null}, + labels: { + align: 'left', + x: 5 + } + }], + legend: {enabled: true}, + plotOptions: { + series: { + dataGrouping: { + enabled: false + }, + states: { + hover: { + halo: { + size: 5, + opacity: 0.25 + } + } + }, + cursor: 'pointer', + marker: { + enabled: false, + states: { + hover: { + enabled: true, + radius: 0.1 + } + } + } + }, + line: {lineWidth: 2} + }, + tooltip: { + shared: true, + split: false, + valueSuffix: ' µg/m³', + valueDecimals: 1, + xDateFormat: "%A, %b %e, %H:%M" + }, + series: [], + rangeSelector: myRangeBtns + }; + + chart = new Highcharts.StockChart(options); + chart.showLoading(); + + $.ajax({ + url: 'airquality.json', + dataType: 'json', + cache: false, + success: function (resp) { + var titles = { + 'pm2p5': 'PM 2.5', + 'pm10' : 'PM 10' + } + var idxs = ['pm2p5', 'pm10']; + idxs.forEach(function(idx) { + if (idx in resp) { + chart.addSeries({ + name: titles[idx], + color: config.series[idx].colour, + data: resp[idx] + }, false); + } + }); + + chart.hideLoading(); + chart.redraw(); + } + }); +}; + +var doExtraTemp = function () { + var freezing = config.temp.units === 'C' ? 0 : 32; + var options = { + chart: { + renderTo: 'chartcontainer', + type: 'line', + alignTicks: false + }, + title: {text: 'Extra Temperature'}, + credits: {enabled: true}, + xAxis: { + type: 'datetime', + ordinal: false, + dateTimeLabelFormats: { + day: '%e %b', + week: '%e %b %y', + month: '%b %y', + year: '%Y' + } + }, + yAxis: [{ + // left + title: {text: 'Temperature (°' + config.temp.units + ')'}, + opposite: false, + labels: { + align: 'right', + x: -5, + formatter: function () { + return '' + this.value + ''; + } + }, + plotLines: [{ + // freezing line + value: freezing, + color: 'rgb(0, 0, 180)', + width: 1, + zIndex: 2 + }] + }, { + // right + gridLineWidth: 0, + opposite: true, + linkedTo: 0, + labels: { + align: 'left', + x: 5, + formatter: function () { + return '' + this.value + ''; + } + } + }], + legend: {enabled: true}, + plotOptions: { + series: { + dataGrouping: { + enabled: false + }, + states: { + hover: { + halo: { + size: 5, + opacity: 0.25 + } + + } + }, + cursor: 'pointer', + marker: { + enabled: false, + states: { + hover: { + enabled: true, + radius: 0.1 + } + } + } + }, + line: {lineWidth: 2} + }, + tooltip: { + shared: true, + split: false, + valueSuffix: ' °' + config.temp.units, + valueDecimals: config.temp.decimals, + xDateFormat: "%A, %b %e, %H:%M" + }, + series: [], + rangeSelector: myRangeBtns + }; + + chart = new Highcharts.StockChart(options); + chart.showLoading(); + + $.ajax({ + url: 'extratempdata.json', + dataType: 'json', + success: function (resp) { + Object.entries(resp).forEach(([key, value]) => { + var id = config.series.extratemp.name.findIndex(val => val == key); + chart.addSeries({ + name: key, + color: config.series.extratemp.colour[id], + data: value + }); + }); + + chart.hideLoading(); + chart.redraw(); + } + }); +}; + +var doExtraHum = function () { + var options = { + chart: { + renderTo: 'chartcontainer', + type: 'line', + alignTicks: false + }, + title: {text: 'Extra Humidity'}, + credits: {enabled: true}, + xAxis: { + type: 'datetime', + ordinal: false, + dateTimeLabelFormats: { + day: '%e %b', + week: '%e %b %y', + month: '%b %y', + year: '%Y' + } + }, + yAxis: [{ + // left + title: {text: 'Humidity (%)'}, + opposite: false, + min: 0, + max: 100, + labels: { + align: 'right', + x: -5 + } + }, { + // right + linkedTo: 0, + gridLineWidth: 0, + opposite: true, + min: 0, + max: 100, + title: {text: null}, + labels: { + align: 'left', + x: 5 + } + }], + legend: {enabled: true}, + plotOptions: { + series: { + dataGrouping: { + enabled: false + }, + states: { + hover: { + halo: { + size: 5, + opacity: 0.25 + } + + } + }, + cursor: 'pointer', + marker: { + enabled: false, + states: { + hover: { + enabled: true, + radius: 0.1 + } + } + } + }, + line: {lineWidth: 2} + }, + tooltip: { + shared: true, + split: false, + valueSuffix: ' %', + valueDecimals: config.hum.decimals, + xDateFormat: "%A, %b %e, %H:%M" + }, + series: [], + rangeSelector: myRangeBtns + }; + + chart = new Highcharts.StockChart(options); + chart.showLoading(); + + $.ajax({ + url: 'extrahumdata.json', + dataType: 'json', + success: function (resp) { + Object.entries(resp).forEach(([key, value]) => { + var id = config.series.extrahum.name.findIndex(val => val == key); + chart.addSeries({ + name: key, + color: config.series.extrahum.colour[id], + data: value + }); + }); + + chart.hideLoading(); + chart.redraw(); + } + }); +}; + +var doExtraDew = function () { + var freezing = config.temp.units === 'C' ? 0 : 32; + var options = { + chart: { + renderTo: 'chartcontainer', + type: 'line', + alignTicks: false + }, + title: {text: 'Extra Dew Point'}, + credits: {enabled: true}, + xAxis: { + type: 'datetime', + ordinal: false, + dateTimeLabelFormats: { + day: '%e %b', + week: '%e %b %y', + month: '%b %y', + year: '%Y' + } + }, + yAxis: [{ + // left + title: {text: 'Dew Point (°' + config.temp.units + ')'}, + opposite: false, + labels: { + align: 'right', + x: -5, + formatter: function () { + return '' + this.value + ''; + } + }, + plotLines: [{ + // freezing line + value: freezing, + color: 'rgb(0, 0, 180)', + width: 1, + zIndex: 2 + }] + }, { + // right + gridLineWidth: 0, + opposite: true, + linkedTo: 0, + labels: { + align: 'left', + x: 5, + formatter: function () { + return '' + this.value + ''; + } + } + }], + legend: {enabled: true}, + plotOptions: { + series: { + dataGrouping: { + enabled: false + }, + states: { + hover: { + halo: { + size: 5, + opacity: 0.25 + } + + } + }, + cursor: 'pointer', + marker: { + enabled: false, + states: { + hover: { + enabled: true, + radius: 0.1 + } + } + } + }, + line: {lineWidth: 2} + }, + tooltip: { + shared: true, + split: false, + valueSuffix: ' °' + config.temp.units, + valueDecimals: config.temp.decimals, + xDateFormat: "%A, %b %e, %H:%M" + }, + series: [], + rangeSelector: myRangeBtns + }; + + chart = new Highcharts.StockChart(options); + chart.showLoading(); + + $.ajax({ + url: 'extradewdata.json', + dataType: 'json', + success: function (resp) { + Object.entries(resp).forEach(([key, value]) => { + var id = config.series.extradew.name.findIndex(val => val == key); + chart.addSeries({ + name: key, + color: config.series.extradew.colour[id], + data: value + }); + }); + + chart.hideLoading(); + chart.redraw(); + } + }); +}; + +var doSoilTemp = function () { + var freezing = config.temp.units === 'C' ? 0 : 32; + var options = { + chart: { + renderTo: 'chartcontainer', + type: 'line', + alignTicks: false + }, + title: {text: 'Soil Temperature'}, + credits: {enabled: true}, + xAxis: { + type: 'datetime', + ordinal: false, + dateTimeLabelFormats: { + day: '%e %b', + week: '%e %b %y', + month: '%b %y', + year: '%Y' + } + }, + yAxis: [{ + // left + title: {text: 'Temperature (°' + config.temp.units + ')'}, + opposite: false, + labels: { + align: 'right', + x: -5, + formatter: function () { + return '' + this.value + ''; + } + }, + plotLines: [{ + // freezing line + value: freezing, + color: 'rgb(0, 0, 180)', + width: 1, + zIndex: 2 + }] + }, { + // right + gridLineWidth: 0, + opposite: true, + linkedTo: 0, + labels: { + align: 'left', + x: 5, + formatter: function () { + return '' + this.value + ''; + } + } + }], + legend: {enabled: true}, + plotOptions: { + series: { + dataGrouping: { + enabled: false + }, + states: { + hover: { + halo: { + size: 5, + opacity: 0.25 + } + + } + }, + cursor: 'pointer', + marker: { + enabled: false, + states: { + hover: { + enabled: true, + radius: 0.1 + } + } + } + }, + line: {lineWidth: 2} + }, + tooltip: { + shared: true, + split: false, + valueSuffix: ' °' + config.temp.units, + valueDecimals: config.temp.decimals, + xDateFormat: "%A, %b %e, %H:%M" + }, + series: [], + rangeSelector: myRangeBtns + }; + + chart = new Highcharts.StockChart(options); + chart.showLoading(); + + $.ajax({ + url: 'soiltempdata.json', + dataType: 'json', + success: function (resp) { + Object.entries(resp).forEach(([key, value]) => { + var id = config.series.soiltemp.name.findIndex(val => val == key); + chart.addSeries({ + name: key, + color: config.series.soiltemp.colour[id], + data: value + }); + }); + + chart.hideLoading(); + chart.redraw(); + } + }); +}; + +var doSoilMoist = function () { + var options = { + chart: { + renderTo: 'chartcontainer', + type: 'line', + alignTicks: false + }, + title: {text: 'Soil Moisture'}, + credits: {enabled: true}, + xAxis: { + type: 'datetime', + ordinal: false, + dateTimeLabelFormats: { + day: '%e %b', + week: '%e %b %y', + month: '%b %y', + year: '%Y' + } + }, + yAxis: [{ + // left + title: {text: 'Moisture (' + config.soilmoisture.units + ')'}, + opposite: false, + labels: { + align: 'right', + x: -5 + } + }, { + // right + gridLineWidth: 0, + opposite: true, + linkedTo: 0, + labels: { + align: 'left', + x: 5 + } + }], + legend: {enabled: true}, + plotOptions: { + series: { + dataGrouping: { + enabled: false + }, + states: { + hover: { + halo: { + size: 5, + opacity: 0.25 + } + + } + }, + cursor: 'pointer', + marker: { + enabled: false, + states: { + hover: { + enabled: true, + radius: 0.1 + } + } + } + }, + line: {lineWidth: 2} + }, + tooltip: { + shared: true, + split: false, + valueSuffix: ' ' + config.soilmoisture.units, + valueDecimals: 0, + xDateFormat: "%A, %b %e, %H:%M" + }, + series: [], + rangeSelector: myRangeBtns + }; + + chart = new Highcharts.StockChart(options); + chart.showLoading(); + + $.ajax({ + url: 'soilmoistdata.json', + dataType: 'json', + success: function (resp) { + Object.entries(resp).forEach(([key, value]) => { + var id = config.series.soilmoist.name.findIndex(val => val == key); + chart.addSeries({ + name: key, + color: config.series.soilmoist.colour[id], + data: value + }); + }); + + chart.hideLoading(); + chart.redraw(); + } + }); +}; + +var doLeafWet = function () { + var options = { + chart: { + renderTo: 'chartcontainer', + type: 'line', + alignTicks: false + }, + title: {text: 'Leaf Wetness'}, + credits: {enabled: true}, + xAxis: { + type: 'datetime', + ordinal: false, + dateTimeLabelFormats: { + day: '%e %b', + week: '%e %b %y', + month: '%b %y', + year: '%Y' + } + }, + yAxis: [{ + // left + title: {text: 'Leaf Wetness' + (config.leafwet.units == '' ? '' : '(' + config.leafwet.units + ')')}, + opposite: false, + min: 0, + labels: { + align: 'right', + x: -5 + } + }, { + // right + gridLineWidth: 0, + opposite: true, + min: 0, + linkedTo: 0, + labels: { + align: 'left', + x: 5 + } + }], + legend: {enabled: true}, + plotOptions: { + series: { + dataGrouping: { + enabled: false + }, + states: { + hover: { + halo: { + size: 5, + opacity: 0.25 + } + + } + }, + cursor: 'pointer', + marker: { + enabled: false, + states: { + hover: { + enabled: true, + radius: 0.1 + } + } + } + }, + line: {lineWidth: 2} + }, + tooltip: { + shared: true, + split: false, + valueSuffix: ' ' + config.leafwet.units, + valueDecimals: config.leafwet.decimals, + xDateFormat: "%A, %b %e, %H:%M" + }, + series: [], + rangeSelector: myRangeBtns + }; + + chart = new Highcharts.StockChart(options); + chart.showLoading(); + + $.ajax({ + url: 'leafwetdata.json', + dataType: 'json', + success: function (resp) { + Object.entries(resp).forEach(([key, value]) => { + var id = config.series.leafwet.name.findIndex(val => val == key); + chart.addSeries({ + name: key, + color: config.series.leafwet.colour[id], + data: value + }); + }); + + chart.hideLoading(); + chart.redraw(); + } + }); +}; + +var doUserTemp = function () { + var freezing = config.temp.units === 'C' ? 0 : 32; + var options = { + chart: { + renderTo: 'chartcontainer', + type: 'line', + alignTicks: false + }, + title: {text: 'User Temperature'}, + credits: {enabled: true}, + xAxis: { + type: 'datetime', + ordinal: false, + dateTimeLabelFormats: { + day: '%e %b', + week: '%e %b %y', + month: '%b %y', + year: '%Y' + } + }, + yAxis: [{ + // left + title: {text: 'Temperature (°' + config.temp.units + ')'}, + opposite: false, + labels: { + align: 'right', + x: -5, + formatter: function () { + return '' + this.value + ''; + } + }, + plotLines: [{ + // freezing line + value: freezing, + color: 'rgb(0, 0, 180)', + width: 1, + zIndex: 2 + }] + }, { + // right + gridLineWidth: 0, + opposite: true, + linkedTo: 0, + labels: { + align: 'left', + x: 5, + formatter: function () { + return '' + this.value + ''; + } + } + }], + legend: {enabled: true}, + plotOptions: { + series: { + dataGrouping: { + enabled: false + }, + states: { + hover: { + halo: { + size: 5, + opacity: 0.25 + } + + } + }, + cursor: 'pointer', + marker: { + enabled: false, + states: { + hover: { + enabled: true, + radius: 0.1 + } + } + } + }, + line: {lineWidth: 2} + }, + tooltip: { + shared: true, + split: false, + valueSuffix: ' °' + config.temp.units, + valueDecimals: config.temp.decimals, + xDateFormat: "%A, %b %e, %H:%M" + }, + series: [], + rangeSelector: myRangeBtns + }; + + chart = new Highcharts.StockChart(options); + chart.showLoading(); + + $.ajax({ + url: 'usertempdata.json', + dataType: 'json', + success: function (resp) { + Object.entries(resp).forEach(([key, value]) => { + var id = config.series.usertemp.name.findIndex(val => val == key); + chart.addSeries({ + name: key, + color: config.series.usertemp.colour[id], + data: value + }); + }); + + chart.hideLoading(); + chart.redraw(); + } + }); +}; + +var doCO2 = function () { + var options = { + chart: { + renderTo: 'chartcontainer', + type: 'line', + alignTicks: false + }, + title: {text: 'CO₂ Sensor'}, + credits: {enabled: true}, + xAxis: { + type: 'datetime', + ordinal: false, + dateTimeLabelFormats: { + day: '%e %b', + week: '%e %b %y', + month: '%b %y', + year: '%Y' + } + }, + yAxis: [{ + // left + id: 'co2', + title: {text: 'CO₂ (ppm)'}, + opposite: false, + min: 0, + minRange: 10, + alignTicks: true, + showEmpty: false, + labels: { + align: 'right', + x: -5 + } + }], + legend: {enabled: true}, + plotOptions: { + series: { + dataGrouping: { + enabled: false + }, + states: { + hover: { + halo: { + size: 5, + opacity: 0.25 + } + + } + }, + cursor: 'pointer', + marker: { + enabled: false, + states: { + hover: { + enabled: true, + radius: 0.1 + } + } + } + }, + line: {lineWidth: 2} + }, + tooltip: { + shared: true, + split: true, + xDateFormat: "%A, %b %e, %H:%M" + }, + series: [], + rangeSelector: myRangeBtns + }; + + chart = new Highcharts.StockChart(options); + chart.showLoading(); + + $.ajax({ + url: 'co2sensordata.json', + dataType: 'json', + success: function (resp) { + Object.entries(resp).forEach(([key, value]) => { + var yaxis = 0; + var tooltip; + // id - remove all spaces and lowercase + var id = key.toLowerCase().split(' ').join(''); + + if (key == 'CO2' || key == 'CO2 Average') { + yaxis = 'co2'; + tooltip = {valueSuffix: ' ppm'}; + } else if (key.startsWith('PM')) { + yaxis = 'pm'; + tooltip = {valueSuffix: ' µg/m³'}; + + + if (!chart.get('pm')) { + chart.addAxis({ + // left + id: 'pm', + title: {text: 'PM (µg/m³)'}, + opposite: false, + min: 0, + minRange: 10, + alignTicks: true, + showEmpty: false, + labels: { + align: 'right', + x: -5 + } + }); + } + } else if (key == 'Temperature') { + yaxis = 'temp'; + tooltip = {valueSuffix: ' °' + config.temp.units}; + chart.addAxis({ + // right + id: 'temp', + title: {text: 'Temperature (°' + config.temp.units + ')'}, + //gridLineWidth: 0, + opposite: true, + alignTicks: true, + showEmpty: false, + labels: { + align: 'left', + x: 5 + } + }); + } else if (key == 'Humidity') { + yaxis = 'hum'; + tooltip = {valueSuffix: ' %'}; + chart.addAxis({ + // right + id: 'hum', + title: {text: 'Humidity (%)'}, + min: 0, + //gridLineWidth: 0, + opposite: true, + alignTicks: true, + showEmpty: false, + labels: { + align: 'left', + x: 5 + } + }); + } + + chart.addSeries({ + name: config.series.co2[id].name, + color: config.series.co2[id].colour, + data: value, + yAxis: yaxis, + tooltip: tooltip + }); + + }); + + chart.hideLoading(); + chart.redraw(); + } + }); +}; diff --git a/webfiles/js/historiccharts.js b/webfiles/js/historiccharts.js new file mode 100644 index 0000000..0b6fdad --- /dev/null +++ b/webfiles/js/historiccharts.js @@ -0,0 +1,1129 @@ +// Last modified: 2023/01/18 16:48:20 + +var chart, config, available; + +$(document).ready(function () { + $.ajax({ + url: "availabledata.json", + dataType: "json", + success: function (result) { + available = result; + if (result.Temperature === undefined || result.Temperature.Count == 0) { + $('#btnTemp').remove(); + } + if (result.Humidity === undefined || result.Humidity.Count == 0) { + $('#btnHum').remove(); + } + if (result.Solar === undefined || result.Solar.Count == 0) { + $('#btnSolar').remove(); + } + if (result.DegreeDays === undefined || result.DegreeDays.Count == 0) { + $('#btnDegDay').remove(); + } + if (result.TempSum === undefined || result.TempSum.Count == 0) { + $('#btnTempSum').remove(); + } + } + }); + + $.ajax({ + url: "graphconfig.json", + dataType: "json", + success: function (result) { + config = result; + changeGraph(parent.location.hash.replace('#', '')); + } + }); +}); + + +function changeGraph(graph) { + switch (graph) { + case 'temp': + doTemp(); + break; + case 'press': + doPress(); + break; + case 'wind': + doWind(); + break; + case 'rain': + doRain(); + break; + case 'humidity': + doHum(); + break; + case 'solar': + doSolar(); + break; + case 'degday': + doDegDays(); + break; + case 'tempsum': + doTempSum(); + break; + default: + doTemp(); + break; + } + parent.location.hash = graph; +} + +var doTemp = function () { + var freezing = config.temp.units === 'C' ? 0 : 32; + var options = { + chart: { + renderTo: 'chartcontainer', + type: 'line', + alignTicks: false + }, + title: {text: 'Temperature'}, + credits: {enabled: true}, + xAxis: { + type: 'datetime', + ordinal: false, + dateTimeLabelFormats: { + day: '%e %b %y', + week: '%e %b %y', + month: '%b %y', + year: '%Y' + } + }, + yAxis: [{ + // left + title: {text: 'Temperature (°' + config.temp.units + ')'}, + opposite: false, + labels: { + align: 'right', + x: -5, + formatter: function () { + return '' + this.value + ''; + } + }, + plotLines: [{ + // freezing line + value: freezing, + color: 'rgb(0, 0, 180)', + width: 1, + zIndex: 2 + }] + }, { + // right + gridLineWidth: 0, + opposite: true, + linkedTo: 0, + labels: { + align: 'left', + x: 5, + formatter: function () { + return '' + this.value + ''; + } + } + }], + legend: {enabled: true}, + plotOptions: { + series: { + dataGrouping: { + enabled: false + }, + states: { + hover: { + halo: { + size: 5, + opacity: 0.25 + } + } + }, + cursor: 'pointer', + marker: { + enabled: false, + states: { + hover: { + enabled: true, + radius: 0.1 + } + } + } + }, + line: {lineWidth: 2} + }, + tooltip: { + shared: true, + split: false, + valueSuffix: ' °' + config.temp.units, + valueDecimals: config.temp.decimals, + xDateFormat: '%e %b %y' + }, + series: [], + rangeSelector: { + inputEnabled: false, + selected: 1 + } + }; + + chart = new Highcharts.StockChart(options); + chart.showLoading(); + + $.ajax({ + url: 'alldailytempdata.json', + dataType: 'json', + success: function (resp) { + var titles = { + 'minTemp' : 'Min Temp', + 'maxTemp' : 'Max Temp', + 'avgTemp' : 'Avg Temp', + 'heatIndex': 'Heat Index', + 'minApp' : 'Min Apparent', + 'maxApp' : 'Max Apparent', + 'minDew' : 'Min Dewpoint', + 'maxDew' : 'Max Dewpoint', + 'minFeels' : 'Min Feels', + 'maxFeels' : 'Max Feels', + 'humidex' : 'Humidex', + 'windChill': 'Wind Chill' + }; + var visibility = { + 'minTemp' : true, + 'maxTemp' : true, + 'avgTemp' : false, + 'heatIndex': false, + 'minApp' : false, + 'maxApp' : false, + 'minDew' : false, + 'maxDew' : false, + 'minFeels' : false, + 'maxFeels' : false, + 'humidex' : false, + 'windChill': false + }; + var idxs = ['minTemp', 'maxTemp', 'avgTemp', 'heatIndex', 'minApp', 'maxApp', 'minDew', 'maxDew', 'minFeels', 'maxFeels', 'windChill', 'humidex']; + + idxs.forEach(function(idx) { + var valueSuffix = ' °' + config.temp.units; + yaxis = 0; + + if (idx in resp) { + var clrIdx = idx.toLowerCase(); + if ('heatIndex' === idx || 'humidex' === idx) { + clrIdx = 'max' + clrIdx; + } else if ('windChill' === idx) { + clrIdx = 'min' + clrIdx; + } + + if (idx === 'humidex') { + valueSuffix = null; + // Link Humidex and temp scales if using Celsius + // For Fahrenheit use separate scales + if (config.temp.units === 'F') { + chart.yAxis[1].remove(); + chart.addAxis({ + id: 'humidex', + title:{text: 'Humidex'}, + opposite: true, + labels: { + align: 'left' + }, + alignTicks: true, + gridLineWidth: 0, // Not working? + gridZIndex: -10, // Hides the grid lines for this axis + showEmpty: false + }); + yaxis = 'humidex'; + } + } + + chart.addSeries({ + name: titles[idx], + data: resp[idx], + color: config.series[clrIdx].colour, + visible: visibility[idx], + showInNavigator: visibility[idx], + yAxis: yaxis, + tooltip: {valueSuffix: valueSuffix} + }, false); + } + }); + chart.hideLoading(); + chart.redraw(); + } + }); +}; + +var doPress = function () { + var options = { + chart: { + renderTo: 'chartcontainer', + type: 'line', + alignTicks: false + }, + title: {text: 'Pressure'}, + credits: {enabled: true}, + xAxis: { + type: 'datetime', + ordinal: false, + dateTimeLabelFormats: { + day: '%e %b %y', + week: '%e %b %y', + month: '%b %y', + year: '%Y' + } + }, + yAxis: [{ + // left + title: {text: 'Pressure (' + config.press.units + ')'}, + opposite: false, + labels: { + align: 'right', + x: -5 + } + }, { + // right + linkedTo: 0, + gridLineWidth: 0, + opposite: true, + title: {text: null}, + labels: { + align: 'left', + x: 5 + } + }], + legend: {enabled: true}, + plotOptions: { + series: { + dataGrouping: { + enabled: false + }, + states: { + hover: { + halo: { + size: 5, + opacity: 0.25 + } + } + }, + cursor: 'pointer', + marker: { + enabled: false, + states: { + hover: { + enabled: true, + radius: 0.1 + } + } + } + }, + line: {lineWidth: 2} + }, + tooltip: { + shared: true, + split: false, + valueSuffix: ' ' + config.press.units, + valueDecimals: config.press.decimals, + xDateFormat: '%e %b %y' + }, + series: [{ + name: 'High Pressure', + color: config.series.maxpress.colour, + showInNavigator: true + }, { + name: 'Low Pressure', + color: config.series.minpress.colour, + showInNavigator: true + }], + rangeSelector: { + inputEnabled: false, + selected: 1 + } + }; + + chart = new Highcharts.StockChart(options); + chart.showLoading(); + + $.ajax({ + url: 'alldailypressdata.json', + dataType: 'json', + success: function (resp) { + chart.hideLoading(); + chart.series[0].setData(resp.maxBaro); + chart.series[1].setData(resp.minBaro); + } + }); +}; + +var compassP = function (deg) { + var a = ['N', 'NE', 'E', 'SE', 'S', 'SW', 'W', 'NW']; + return a[Math.floor((deg + 22.5) / 45) % 8]; +}; + +var doWind = function () { + var options = { + chart: { + renderTo: 'chartcontainer', + type: 'line', + alignTicks: false + }, + title: {text: 'Wind Speed'}, + credits: {enabled: true}, + xAxis: { + type: 'datetime', + ordinal: false, + dateTimeLabelFormats: { + day: '%e %b %y', + week: '%e %b %y', + month: '%b %y', + year: '%Y' + } + }, + yAxis: [{ + // left + title: {text: 'Wind Speed (' + config.wind.units + ')'}, + opposite: false, + min: 0, + labels: { + align: 'right', + x: -5 + } + }, { + // right + //linkedTo: 0, + gridLineWidth: 0, + opposite: true, + min: 0, + title: {text: 'Wind Run (' + config.wind.rununits + ')'}, + labels: { + align: 'left', + x: 5 + }, + showEmpty: false + }], + legend: {enabled: true}, + plotOptions: { + series: { + dataGrouping: { + enabled: false + }, + states: { + hover: { + halo: { + size: 5, + opacity: 0.25 + } + } + }, + cursor: 'pointer', + marker: { + enabled: false, + states: { + hover: { + enabled: true, + radius: 0.1 + } + } + } + }, + line: {lineWidth: 2} + }, + tooltip: { + shared: true, + split: false, + valueSuffix: ' ' + config.wind.units, + valueDecimals: config.wind.decimals, + xDateFormat: '%e %b %y' + }, + series: [{ + name: 'Wind Speed', + color: config.series.wspeed.colour, + showInNavigator: true + }, { + name: 'Wind Gust', + color: config.series.wgust.colour, + showInNavigator: true + }, { + name: 'Wind Run', + type: 'column', + color: config.series.windrun.colour, + yAxis: 1, + visible: false, + tooltip: { + valueSuffix: ' ' + config.wind.rununits, + valueDecimals: 0 + }, + zIndex: -1 + }], + rangeSelector: { + inputEnabled: false, + selected: 1 + } + }; + + chart = new Highcharts.StockChart(options); + chart.showLoading(); + + $.ajax({ + url: 'alldailywinddata.json', + dataType: 'json', + success: function (resp) { + chart.hideLoading(); + chart.series[0].setData(resp.maxWind); + chart.series[1].setData(resp.maxGust); + chart.series[2].setData(resp.windRun); + } + }); +}; + +var doRain = function () { + var options = { + chart: { + renderTo: 'chartcontainer', + type: 'column', + alignTicks: true + }, + title: {text: 'Rainfall'}, + credits: {enabled: true}, + xAxis: { + type: 'datetime', + ordinal: false, + dateTimeLabelFormats: { + day: '%e %b %y', + week: '%e %b %y', + month: '%b %y', + year: '%Y' + } + }, + yAxis: [{ + // left + title: {text: 'Rainfall (' + config.rain.units + ')'}, + opposite: false, + min: 0, + labels: { + align: 'right', + x: -5 + } + }, { + // right + title: {text: 'Rainfall rate (' + config.rain.units + '/hr)'}, + opposite: true, + min: 0, + labels: { + align: 'left', + x: 5 + }, + showEmpty: false + }], + legend: {enabled: true}, + plotOptions: { + series: { + dataGrouping: { + enabled: false + }, + pointPadding: 0, + groupPadding: 0.1, + states: { + hover: { + halo: { + size: 5, + opacity: 0.25 + } + + } + }, + cursor: 'pointer', + marker: { + enabled: false, + states: { + hover: { + enabled: true, + radius: 0.1 + } + } + } + }, + line: {lineWidth: 2} + }, + tooltip: { + shared: true, + split: false, + valueDecimals: config.rain.decimals, + xDateFormat: '%e %b %y' + }, + series: [{ + name: 'Daily rain', + type: 'column', + color: config.series.rfall.colour, + yAxis: 0, + tooltip: {valueSuffix: ' ' + config.rain.units} + }, { + name: 'Rain rate', + type: 'column', + color: config.series.rrate.colour, + yAxis: 1, + tooltip: {valueSuffix: ' ' + config.rain.units + '/hr'}, + visible: false + }], + rangeSelector: { + inputEnabled: false, + selected: 1 + } + }; + + chart = new Highcharts.StockChart(options); + chart.showLoading(); + + $.ajax({ + url: 'alldailyraindata.json', + dataType: 'json', + success: function (resp) { + chart.hideLoading(); + chart.series[0].setData(resp.rain); + chart.series[1].setData(resp.maxRainRate); + } + }); +}; + +var doHum = function () { + var options = { + chart: { + renderTo: 'chartcontainer', + type: 'line', + alignTicks: false + }, + title: {text: 'Relative Humidity'}, + credits: {enabled: true}, + xAxis: { + type: 'datetime', + ordinal: false, + dateTimeLabelFormats: { + day: '%e %b %y', + week: '%e %b %y', + month: '%b %y', + year: '%Y' + } + }, + yAxis: [{ + // left + title: {text: 'Humidity (%)'}, + opposite: false, + min: 0, + max: 100, + labels: { + align: 'right', + x: -5 + } + }, { + // right + linkedTo: 0, + gridLineWidth: 0, + opposite: true, + min: 0, + max: 100, + title: {text: null}, + labels: { + align: 'left', + x: 5 + } + }], + legend: {enabled: true}, + plotOptions: { + series: { + dataGrouping: { + enabled: false + }, + states: { + hover: { + halo: { + size: 5, + opacity: 0.25 + } + + } + }, + cursor: 'pointer', + marker: { + enabled: false, + states: { + hover: { + enabled: true, + radius: 0.1 + } + } + } + }, + line: {lineWidth: 2} + }, + tooltip: { + shared: true, + split: false, + valueSuffix: ' %', + valueDecimals: config.hum.decimals, + xDateFormat: '%e %b %y' + }, + series: [], + rangeSelector: { + inputEnabled: false, + selected: 1 + } + }; + + chart = new Highcharts.StockChart(options); + chart.showLoading(); + + $.ajax({ + url: 'alldailyhumdata.json', + dataType: 'json', + success: function (resp) { + var titles = { + 'minHum' : 'Minimum Humidity', + 'maxHum': 'Maximum Humidity' + } + var idxs = ['minHum', 'maxHum']; + var cnt = 0; + idxs.forEach(function(idx) { + if (idx in resp) { + chart.addSeries({ + name: titles[idx], + color: config.series[idx.toLowerCase()].colour, + data: resp[idx], + showInNavigator: true + }, false); + + cnt++; + } + }); + + chart.hideLoading(); + chart.redraw(); + } + }); +}; + +var doSolar = function () { + var options = { + chart: { + renderTo: 'chartcontainer', + type: 'line', + alignTicks: true + }, + title: {text: 'Solar'}, + credits: {enabled: true}, + xAxis: { + type: 'datetime', + ordinal: false, + dateTimeLabelFormats: { + day: '%e %b %y', + week: '%e %b %y', + month: '%b %y', + year: '%Y' + } + }, + yAxis: [], + legend: {enabled: true}, + plotOptions: { + boostThreshold: 0, + series: { + dataGrouping: { + enabled: false + }, + pointPadding: 0, + groupPadding: 0.1, + states: { + hover: { + halo: { + size: 5, + opacity: 0.25 + } + + } + }, + cursor: 'pointer', + marker: { + enabled: false, + states: { + hover: { + enabled: true, + radius: 0.1 + } + } + } + }, + line: {lineWidth: 2} + }, + tooltip: { + shared: true, + split: false, + xDateFormat: '%e %b %y' + }, + series: [], + rangeSelector: { + inputEnabled: false, + selected: 1 + } + }; + + chart = new Highcharts.StockChart(options); + chart.showLoading(); + + $.ajax({ + url: 'alldailysolardata.json', + dataType: 'json', + success: function (resp) { + var titles = { + solarRad: 'Solar Radiation', + uvi : 'UV Index', + sunHours: 'Sunshine Hours' + }; + var types = { + solarRad: 'area', + uvi : 'line', + sunHours: 'column' + }; + var tooltips = { + solarRad: { + valueSuffix: ' W/m\u00B2', + valueDecimals: 0 + }, + uvi: { + valueSuffix: ' ', + valueDecimals: config.uv.decimals + }, + sunHours: { + valueSuffix: ' hours', + valueDecimals: 0 + } + }; + var indexes = { + solarRad: 1, + uvi : 2, + sunHours: 0 + } + var fillColor = { + solarRad: { + linearGradient: { + x1: 0, + y1: 0, + x2: 0, + y2: 1 + }, + stops: [ + [0, config.series.solarrad.colour], + [1, Highcharts.color(config.series.solarrad.colour).setOpacity(0).get('rgba')] + ] + }, + uvi : null, + sunHours: null + }; + var idxs = ['solarRad', 'uvi', 'sunHours']; + + idxs.forEach(function(idx) { + if (idx in resp) { + var clrIdx; + if (idx === 'uvi') + clrIdx ='uv'; + else if (idx === 'solarRad') + clrIdx = 'solarrad'; + else if (idx === 'sunHours') + clrIdx = 'sunshine'; + + if (idx === 'uvi') { + chart.addAxis({ + id: idx, + title: {text: 'UV Index'}, + opposite: true, + min: 0, + labels: { + align: 'left' + }, + showEmpty: false + }); + } else if (idx === 'sunHours') { + chart.addAxis({ + id: idx, + title: {text: 'Sunshine Hours'}, + opposite: true, + min: 0, + labels: { + align: 'left' + }, + showEmpty: false + }); + } else if (idx === 'solarRad') { + chart.addAxis({ + id: idx, + title: {text: 'Solar Radiation (W/m\u00B2)'}, + min: 0, + opposite: false, + labels: { + align: 'right', + x: -5 + }, + showEmpty: false + }); + } + chart.addSeries({ + name: titles[idx], + type: types[idx], + yAxis: idx, + tooltip: tooltips[idx], + data: resp[idx], + color: config.series[clrIdx].colour, + showInNavigator: idx !== 'sunHours', + index: indexes[idx], + fillColor: fillColor[idx], + zIndex: idx === 'uvi' ? 99 : null + }, false); + } + }); + + chart.hideLoading(); + chart.redraw(); + } + }); +}; + +var doDegDays = function () { + var options = { + chart: { + renderTo: 'chartcontainer', + type: 'line', + alignTicks: false, + zoomType: 'x' + }, + title: {text: 'Degree Days'}, + credits: {enabled: true}, + xAxis: { + type: 'datetime', + ordinal: false, + dateTimeLabelFormats: { + day: '%e %b', + week: '%e %b', + month: '%b', + year: '' + } + }, + yAxis: [{ + // left + title: {text: '°' + config.temp.units + ' days'}, + opposite: false, + min: 0, + labels: { + align: 'right', + x: -10 + } + }, { + // right + linkedTo: 0, + gridLineWidth: 0, + opposite: true, + min: 0, + title: {text: null}, + labels: { + align: 'left', + x: 10 + } + }], + legend: {enabled: true}, + plotOptions: { + series: { + dataGrouping: { + enabled: false + }, + states: { + hover: { + halo: { + size: 5, + opacity: 0.25 + } + + } + }, + cursor: 'pointer', + marker: { + enabled: false, + states: { + hover: { + enabled: true, + radius: 0.1 + } + } + } + }, + line: {lineWidth: 2} + }, + tooltip: { + shared: true, + split: false, + xDateFormat: '%e %B', + useHTML: true, + headerFormat: '{point.key}', + pointFormat: '' + + '', + footerFormat: '
\u25CF {series.name}: {point.y:.1f}
' + }, + series: [] + }; + + chart = new Highcharts.Chart(options); + chart.showLoading(); + + $.ajax({ + url: 'alldailydegdaydata.json', + dataType: 'json', + success: function (resp) { + var subtitle = ''; + if (available.DegreeDays.indexOf('GDD1') != -1) { + subtitle = 'GDD#1 base: ' + resp.options.gddBase1 + '°' + config.temp.units; + if (available.DegreeDays.indexOf('GDD2') != -1) { + subtitle += ' - '; + } + } + if (available.DegreeDays.indexOf('GDD2') != -1) { + subtitle += 'GDD#2 base: ' + resp.options.gddBase2 + '°' + config.temp.units; + } + + chart.setSubtitle({text: subtitle}); + + available.DegreeDays.forEach(idx => { + if (idx in resp) { + Object.keys(resp[idx]).forEach(yr => { + chart.addSeries({ + name: idx + '-' + yr, + visible: false, + data: resp[idx][yr] + }, false); + }); + // make the last series visible + chart.series[chart.series.length -1].visible = true; + } + }); + + chart.hideLoading(); + chart.redraw(); + } + }); +}; + +var doTempSum = function () { + var options = { + chart: { + renderTo: 'chartcontainer', + type: 'line', + alignTicks: false, + zoomType: 'x' + }, + title: {text: 'Temperature Sum'}, + credits: {enabled: true}, + xAxis: { + type: 'datetime', + ordinal: false, + dateTimeLabelFormats: { + day: '%e %b', + week: '%e %b', + month: '%b', + year: '' + } + }, + yAxis: [{ + // left + title: {text: 'Total °' + config.temp.units}, + opposite: false, + labels: { + align: 'right', + x: -10 + } + }, { + // right + linkedTo: 0, + gridLineWidth: 0, + opposite: true, + title: {text: null}, + labels: { + align: 'left', + x: 10 + } + }], + legend: {enabled: true}, + plotOptions: { + series: { + dataGrouping: { + enabled: false + }, + states: { + hover: { + halo: { + size: 5, + opacity: 0.25 + } + + } + }, + cursor: 'pointer', + marker: { + enabled: false, + states: { + hover: { + enabled: true, + radius: 0.1 + } + } + } + }, + line: {lineWidth: 2} + }, + tooltip: { + shared: true, + split: false, + xDateFormat: '%e %B', + useHTML: true, + headerFormat: '{point.key}', + pointFormat: '' + + '', + footerFormat: '
\u25CF {series.name}: {point.y:0f}
' + }, + series: [] + }; + + chart = new Highcharts.Chart(options); + chart.showLoading(); + + $.ajax({ + url: 'alltempsumdata.json', + dataType: 'json', + success: function (resp) { + var subtitle = ''; + if (available.TempSum.indexOf('Sum0') != -1) { + subtitle = 'Sum#0 base: 0°' + config.temp.units; + if (available.TempSum.indexOf('Sum1') != -1 || available.TempSum.indexOf('Sum2') != -1) { + subtitle += ' - '; + } + } + if (available.TempSum.indexOf('Sum1') != -1) { + subtitle += 'Sum#1 base: ' + resp.options.sumBase1 + '°' + config.temp.units; + if (available.TempSum.indexOf('Sum2') != -1) { + subtitle += ' - '; + } + } + if (available.TempSum.indexOf('Sum2') != -1) { + subtitle += 'Sum#2 base: ' + resp.options.sumBase2 + '°' + config.temp.units; + } + + chart.setSubtitle({text: subtitle}); + + available.TempSum.forEach(idx => { + if (idx in resp) { + Object.keys(resp[idx]).forEach(yr => { + chart.addSeries({ + name: idx + '-' + yr, + visible: false, + data: resp[idx][yr] + }, false); + }); + // make the last series visible + chart.series[chart.series.length -1].visible = true; + } + }); + + chart.hideLoading(); + chart.redraw(); + } + }); +}; diff --git a/webfiles/js/menu.js b/webfiles/js/menu.js new file mode 100644 index 0000000..9f7d7f2 --- /dev/null +++ b/webfiles/js/menu.js @@ -0,0 +1,36 @@ +/* + Menu configuration file for NEW CuMX template + Last modified: 2022/07/05 11:39:38 + menu.js - typical name, you define the one used in setpagedata.js + + It is STRONGLY RECOMMENDED that if you customise this file, you create a new file with a different name, e.g. mymenu.js + and change setpagedata.js to use that file. This will avoid your customisations being accidentally overwritten during upgrades + + Properties: + .menu - can be 'b' (both menus), 'w' (wide menu ONLY), 'n' (narrow menu ONLY) + .new_window:true - forces the link to open in new browser window + .forum:true - flags a forum link menu item, it will use the url provided in CuMX config, if that is blank the menu item will be hidden + .webcam:true - flags a webcam link menu item, it will use the url provided in CuMX config, if that is blank the menu item will be hidden +*/ + +menuSrc = [ + {title: "Now", menu: "b", url: "index.htm"}, + {title: "Today", menu: "b", url: "today.htm"}, + {title: "Yesterday", menu: "b", url: "yesterday.htm"}, + {title: "Today-Yest", menu: "b", url: "todayyest.htm"}, + {title: "Gauges", menu: "b", url: "gauges.htm"}, + {title: "Records", menu: "b", submenu: true, items: [ + {title: "This Month", menu: "b", url: "thismonth.htm"}, + {title: "This Year", menu: "b", url: "thisyear.htm"}, + {title: "All Time", menu: "b", url: "record.htm"}, + {title: "Monthly", menu: "b", url: "monthlyrecord.htm"} + ]}, + {title: "Charts", menu: "b", submenu: true, items: [ + {title: "Trends", menu: "b", url: "trends.htm"}, + {title: "Select-a-graph", menu: "b", url: "selectachart.htm"}, + {title: "Historic", menu: "b", url: "historic.htm"} + ]}, + {title: "Reports", menu: "b", url: "noaareport.htm"}, + {title: "Forum", menu: "b", url: "#", forum: true, new_window: true}, + {title: "Webcam", menu: "b", url: "#", webcam: true} +]; diff --git a/webfiles/js/menuSample.js b/webfiles/js/menuSample.js new file mode 100644 index 0000000..68277c6 --- /dev/null +++ b/webfiles/js/menuSample.js @@ -0,0 +1,38 @@ +/* + An example extended/modified Menu configuration file for NEW CuMX template + Last modified: 2021/03/19 09:17:14 + menuSample.js - typical name, you define the one used in setpagedata.js + + Properties: + .menu - can be 'b' (both menus), 'w' (wide menu ONLY), 'n' (narrow menu ONLY) + .new_window:true - forces the link to open in new browser window + .forum:true - flags a forum link menu item, it will use the url provided in CuMX config, if that is blank the menu item will be hidden + .webcam:true - flags a webcam link menu item, it will use the url provided in CuMX config, if that is blank the menu item will be hidden +*/ + +menuSrc = [ + {title: "Now", menu: "b", url: "index.htm"}, + {title: "Today", menu: "b", url: "today.htm"}, + {title: "Yesterday", menu: "b", url: "yesterday.htm"}, + {title: "Gauges", menu: "b", url: "gauges.htm"}, + {title: "Records", menu: "b", submenu: true, items: [ + {title: "This Month", menu: "b", url: "thismonth.htm"}, + {title: "This Year", menu: "b", url: "thisyear.htm"}, + {title: "All Time", menu: "b", url: "record.htm"}, + {title: "Monthly", menu: "b", url: "monthlyrecord.htm"} + ]}, + {title: "Charts", menu: "b", submenu: true, items: [ + {title: "Trends", menu: "b", url: "trends.htm"}, + {title: "Select-a-graph", menu: "b", url: "selectachart.htm"}, + {title: "Historic", menu: "b", url: "historic.htm"} + ]}, + {title: "Reports", menu: "b", url: "noaareport.htm"}, + {title: "Forum", menu: "n", url: "#", new_window: true}, + {title: "Webcam", menu: "n", url: "#", new_window: true}, + {title: "Other Links", menu: "w", submenu: true, items: [ + {title: "Cumulus Forum", menu: "w", url: "#", forum: true, new_window: true}, + {title: "Webcam", menu: "b", url: "#", webcam: true, new_window: true}, + {title: "My Cat", menu: "b", url: "mycatpage.htm"}, + {title: "Some Cat", menu: "b", url: "https://pixnio.com/free-images/2020/07/26/2020-07-26-08-52-19-1200x1200.jpg", new_window: true} + ]} +]; diff --git a/webfiles/js/monthlyrecdata.js b/webfiles/js/monthlyrecdata.js new file mode 100644 index 0000000..6b8528c --- /dev/null +++ b/webfiles/js/monthlyrecdata.js @@ -0,0 +1,74 @@ +// Last modified: 2022/07/27 15:35:57 + +$(document).ready(function() { + dataLoadedPromise.then(function() { + var yesterday = new Date() + yesterday.setDate(yesterday.getDate() - 1) + changeData(yesterday.getMonth()); + $('#btnMon' + yesterday.getMonth()).attr('aria-pressed', true); + }); +}); + +var monthnames = new Array("January","February","March","April","May","June","July","August","September","October","November","December"); + +function changeData(month) { + document.getElementById('MonthName').innerHTML = monthnames[month]; + document.getElementById('TempH').innerHTML = cmx_data.monthlyrecs.hightemp[month]; + document.getElementById('TempHT').innerHTML = cmx_data.monthlyrecs.hightempT[month]; + document.getElementById('TempL').innerHTML = cmx_data.monthlyrecs.lowtemp[month]; + document.getElementById('TempLT').innerHTML = cmx_data.monthlyrecs.lowtempT[month]; + document.getElementById('DewPointH').innerHTML = cmx_data.monthlyrecs.highDP[month]; + document.getElementById('DewPointHT').innerHTML = cmx_data.monthlyrecs.highDPT[month]; + document.getElementById('DewPointL').innerHTML = cmx_data.monthlyrecs.lowDP[month]; + document.getElementById('DewPointLT').innerHTML = cmx_data.monthlyrecs.lowDPT[month]; + document.getElementById('AppTempH').innerHTML = cmx_data.monthlyrecs.highapptemp[month]; + document.getElementById('AppTempHT').innerHTML = cmx_data.monthlyrecs.highapptempT[month]; + document.getElementById('AppTempL').innerHTML = cmx_data.monthlyrecs.lowapptemp[month]; + document.getElementById('AppTempLT').innerHTML = cmx_data.monthlyrecs.lowapptempT[month]; + document.getElementById('FeelsLikeH').innerHTML = cmx_data.monthlyrecs.highfeelslike[month]; + document.getElementById('FeelsLikeHT').innerHTML = cmx_data.monthlyrecs.highfeelslikeT[month]; + document.getElementById('FeelsLikeL').innerHTML = cmx_data.monthlyrecs.lowfeelslike[month]; + document.getElementById('FeelsLikeLT').innerHTML = cmx_data.monthlyrecs.lowfeelslikeT[month]; + document.getElementById('WChillL').innerHTML = cmx_data.monthlyrecs.lowchill[month]; + document.getElementById('WChillLT').innerHTML = cmx_data.monthlyrecs.lowchillT[month]; + document.getElementById('HeatIndexH').innerHTML = cmx_data.monthlyrecs.highheatindex[month]; + document.getElementById('HeatIndexHT').innerHTML = cmx_data.monthlyrecs.highheatindexT[month]; + document.getElementById('MinTempH').innerHTML = cmx_data.monthlyrecs.highmintemp[month]; + document.getElementById('MinTempHT').innerHTML = cmx_data.monthlyrecs.highmintempT[month]; + document.getElementById('MaxTempL').innerHTML = cmx_data.monthlyrecs.lowmaxtemp[month]; + document.getElementById('MaxTempLT').innerHTML = cmx_data.monthlyrecs.lowmaxtempT[month]; + document.getElementById('HumH').innerHTML = cmx_data.monthlyrecs.highhum[month]; + document.getElementById('HumHT').innerHTML = cmx_data.monthlyrecs.highhumT[month]; + document.getElementById('HumL').innerHTML = cmx_data.monthlyrecs.lowhum[month]; + document.getElementById('HumLT').innerHTML = cmx_data.monthlyrecs.lowhumT[month]; + document.getElementById('HighDailyTempRange').innerHTML = cmx_data.monthlyrecs.hightemprange[month]; + document.getElementById('HighDailyTempRangeT').innerHTML = cmx_data.monthlyrecs.hightemprangeT[month]; + document.getElementById('LowDailyTempRange').innerHTML = cmx_data.monthlyrecs.lowtemprange[month]; + document.getElementById('LowDailyTempRangeT').innerHTML = cmx_data.monthlyrecs.lowtemprangeT[month]; + document.getElementById('RainRateH').innerHTML = cmx_data.monthlyrecs.rainrate[month]; + document.getElementById('RainRateHT').innerHTML = cmx_data.monthlyrecs.rainrateT[month]; + document.getElementById('HourlyRainH').innerHTML = cmx_data.monthlyrecs.hourlyrain[month]; + document.getElementById('HourlyRainHT').innerHTML = cmx_data.monthlyrecs.hourlyrainT[month]; + document.getElementById('Rain24HourH').innerHTML = cmx_data.monthlyrecs.rain24h[month]; + document.getElementById('Rain24HourHT').innerHTML = cmx_data.monthlyrecs.rain24hT[month]; + document.getElementById('DailyRainH').innerHTML = cmx_data.monthlyrecs.dailyrain[month]; + document.getElementById('DailyRainHT').innerHTML = cmx_data.monthlyrecs.dailyrainT[month]; + document.getElementById('MonthlyRainH').innerHTML = cmx_data.monthlyrecs.monthlyrain[month]; + document.getElementById('MonthlyRainHT').innerHTML = cmx_data.monthlyrecs.monthlyrainT[month]; + document.getElementById('LongestDryPeriod').innerHTML = cmx_data.monthlyrecs.dryperiod[month]; + document.getElementById('LongestDryPeriodT').innerHTML = cmx_data.monthlyrecs.dryperiodT[month]; + document.getElementById('LongestWetPeriod').innerHTML = cmx_data.monthlyrecs.wetperiod[month]; + document.getElementById('LongestWetPeriodT').innerHTML = cmx_data.monthlyrecs.wetperiodT[month]; + document.getElementById('GustH').innerHTML = cmx_data.monthlyrecs.highgust[month]; + document.getElementById('GustHT').innerHTML = cmx_data.monthlyrecs.highgustT[month]; + document.getElementById('WindH').innerHTML = cmx_data.monthlyrecs.highwind[month]; + document.getElementById('WindHT').innerHTML = cmx_data.monthlyrecs.highwindT[month]; + document.getElementById('WindRunH').innerHTML = cmx_data.monthlyrecs.highwindrun[month]; + document.getElementById('WindRunHT').innerHTML = cmx_data.monthlyrecs.highwindrunT[month]; + document.getElementById('PressL').innerHTML = cmx_data.monthlyrecs.lowpress[month]; + document.getElementById('PressLT').innerHTML = cmx_data.monthlyrecs.lowpressT[month]; + document.getElementById('PressH').innerHTML = cmx_data.monthlyrecs.highpress[month]; + document.getElementById('PressHT').innerHTML = cmx_data.monthlyrecs.highpressT[month]; + $('#btnArray').children('button').attr("aria-pressed", false); + $('#btnMon' + month).attr('aria-pressed', true); +} diff --git a/webfiles/js/noaarpts.js b/webfiles/js/noaarpts.js new file mode 100644 index 0000000..f501d15 --- /dev/null +++ b/webfiles/js/noaarpts.js @@ -0,0 +1,142 @@ +/* ---------------------------------------------------------- + * noaarpts.js + * Last modified: 2021/07/10 13:19:42 + * Populates the dropdown menus using the records began date + * + * Requires jQuery + * ----------------------------------------------------------*/ + +let rptPath = 'Reports/'; // Your path should have a trailing "/", eg. 'Reports/' +let startYear, endYear; +let startMonth, endMonth; +let rptAvail = {}; + +if (rptPath.length && rptPath.slice(-1) !== '/') + rptPath += '/'; + +$(document).ready(function() { + dataLoadedPromise.then(function() { + startYear = cmx_data.recordsbegandateISO.split('-')[0] * 1; + startMonth = cmx_data.recordsbegandateISO.split('-')[1] * 1; + endYear = cmx_data.metdateyesterdayISO.split('-')[0] * 1; + endMonth = cmx_data.metdateyesterdayISO.split('-')[1] * 1; + + // This does the initial disable of out of range months this year + rptAvail[endYear] = []; + for (let m = 1; m < 13; m++) { + // greater than end month + rptAvail[endYear][m] = m <= endMonth; + // if start year is this year, then less start month + if (startYear == endYear) { + rptAvail[endYear][m] = rptAvail[endYear][m] && m >= startMonth + } + $('#opt-' + m).prop('hidden', !rptAvail[endYear][m]); + } + + // get the current year report and display it whilst we sort out the rest in background + getYearRpt(endYear); + + // add the year select dropdown values, most recent first + for (let y = endYear; y >= startYear; y--) { + let option = $(''); + optgrp.attr('label', k); + result1[k].forEach(function (val) { + var option = $('