1// ActivEnergy App v 1.2.1 2var type; 3 4var app = { 5 loadJSON: async function(version) { 6 localStorage.setItem('version',version); 7 const response = await fetch(`js/getContent.php?v=${version}`) 8 const json = await response.json(); 9 app.screens = json.screens; 10 app.activities = json.activities; 11 app.tips = json.tips; 12 document.getElementById('loading').style.display = 'none'; 13 downloadCustomActivities(); 14 app.history = new Array(); 15 app.history.push(screen); // for 'back' 16 console.log(screen); 17 app.moveTo(screen); 18 }, 19 20 changeVersion: async function(version,title) { 21 await app.loadJSON(version); 22 app.moveTo("menu"); 23 document.getElementById('title').innerHTML = "Changed to "+title; 24 }, 25 26 loadText: async function() { 27 // passed as _GET values to index.php 28 if (!(typeof id === 'undefined' || id === null)) { 29 if (localStorage.getItem('metaID') != id) { localStorage.clear(); } // change of user 30 localStorage.setItem('metaID', id); 31 } 32 localStorage.setItem('version',version); 33 34 if (localStorage.getItem('hhPage') == null) { localStorage.setItem('hhPage',1); } 35 if (!(localStorage.getItem('index') > 0)) { localStorage.setItem('index',0); } 36 if (localStorage.getItem('lastNotification') == null) { localStorage.setItem('lastNotification',new Date()); } 37 if (localStorage.getItem('scheme') != null) { document.documentElement.setAttribute('scheme', localStorage.getItem('scheme')) }; 38 39 // load JSON 40 await app.loadJSON(localStorage.getItem('version')); 41 42 // does a local record of activities exist? 43 if (localStorage.getItem('acts') == null) { 44 localStorage.setItem('acts', JSON.stringify({})); // JSON to store activities 45 localStorage.setItem('key', 0); // activity key currently being modified 46 localStorage.setItem('index', 0); // incremental for unique keys 47 } else { 48 if (localStorage.getItem('metaID') != '0') { 49 localStorage.setItem('acts', JSON.stringify({})); // JSON to store activities 50 downloadActs() 51 }; 52 app.actCount(); 53 } 54 55 // CONSENT? 56 if (localStorage.getItem('consent') != null) { 57 document.getElementById('consent').style.display = 'none'; 58 if (!(typeof sc === 'undefined' || sc === null)) { localStorage.setItem('sc', sc); } 59 // app.moveTo("menu"); 60 } else { 61 document.getElementById('consent').style.display = ''; 62 document.getElementById('navbar').style.display = 'none'; 63 document.getElementById('header').style.display = 'none'; 64 document.getElementById('slider').style.display = 'none'; 65 document.getElementById('input').style.display = 'none'; 66 document.getElementById('server').style.display = 'none'; 67 document.getElementById('list').style.display = 'none'; 68 document.getElementById('buttons').style.display = 'none'; 69 document.getElementById('footer').style.display = 'none'; 70 window.scrollTo(0, 0); 71 } 72 // external url given with: https://joymeter.uk?url=XY 73 if (typeof url !== 'undefined') { 74 console.log(url); 75 document.getElementById('server').setAttribute('src',url); 76 app.moveTo("server"); 77 } 78 // app.history = new Array(); 79 }, 80 81 getAct: function() { // returns current activity 82 const key = localStorage.getItem('key'); 83 const acts = JSON.parse(localStorage.getItem('acts')); 84 return acts[key]; 85 }, 86 87 isHome: function() { // true is currently reported activity is at home 88 if (app.getAct() != undefined) { 89 if (app.getAct()['location'] == 1) { 90 return true; 91 } else { 92 return false; 93 } 94 } else { 95 return false; 96 } 97 }, 98 99 actCount: function() { 100 let acts = JSON.parse(localStorage.getItem('acts')); 101 var weekAgo = new Date(); 102 weekAgo.setDate(weekAgo.getDate() - 7); 103 var midnight = new Date().setHours(0,0,0,0); 104 const nonSurvey = Object.keys(acts).filter(x => (acts[x].category != 'survey')); 105 const weekKeys = nonSurvey.filter(x => x.split('_')[0] > weekAgo); 106 const dayKeys = nonSurvey.filter(x => x.split('_')[0] > midnight); 107 const count = dayKeys.length; 108 var score = 0; 109 if (count > 0) { score = 1 } 110 if (count > 4) { score = 2 } 111 if (count > 8) { score = 3 } 112 if (count > 12) { score = 4 } 113 if (count > 19) { score = 5 } 114 app.activities.Home.icon = 'stars_'+score; 115 document.getElementById('nav-home-img').src = `svg/stars_${score}.svg`; 116 return count; 117 }, 118 119 formatString: function(str) { 120 if (str.includes('${actCount}')) { 121 str = str.replace('${actCount}', app.actCount()); 122 } 123 if (str.includes('${metaID}')) { 124 str = str.replace('${metaID}', localStorage.getItem('metaID')); 125 } 126 return str 127 }, 128 129 moveFrom: function(from) { 130 const act = app.activities[from];
131 var cat = act.category; 132 var key = localStorage.getItem('key'); 133 var acts = JSON.parse(localStorage.getItem('acts')); 134 if (cat == 'selection') { 135 app.activities[from]['icon'] = "done"; 136 app.activities[from]['help'] = "Done. You can update it."; 137 app.activities[from]['activity'] = from; // reinstated to aid custom act download ... removed - messed up the label with the json 'key' ?! 138 uploadModifiedAct(app.activities[from]); 139 cat = 'survey'; 140 } 141 142 switch(cat) { 143 case "menu": 144 console.log("no FROM action (menu)"); 145 break; 146 case "skip": 147 console.log("skipping"); 148 break; 149 case "abort": 150 delete acts[key] 151 key = ''; 152 localStorage.setItem('key',key); 153 break; 154 case "location": 155 acts[key]['location'] = act.value; 156 break; 157 case "people": 158 acts[key]['people'] = act.value; 159 break; 160 case "enjoyment": 161 acts[key]['enjoyment'] = act.value; 162 break; 163 case "comfort": 164 acts[key]['comfort'] = act.value; 165 if (acts[key]['activity'] == null) { 166 acts[key]['activity'] = act.activity; 167 acts[key]['category'] = act.category; 168 } 169 localStorage.setItem('lastNotification',new Date()); 170 break; 171 //case "freetext": 172 // app.setFooter('save'); 173 // break; 174 case "server": 175 var url = act.url; 176 url = url.replace("{hhID}", localStorage.getItem('hhID')); 177 url = url.replace("{hhSC}", localStorage.getItem('hhSC')); 178 url = url.replace("{hhPage}", localStorage.getItem('hhPage')); 179 document.getElementById('server').setAttribute('src',`${url}`); 180 console.log(`server: ${url}`); 181 break; 182 case "survey": 183 // immediate upload as activity 184 // app.newAct('survey'); 185 console.log("New Survey Entry") 186 key = `${Number(new Date())}_${localStorage.getItem('index')}_${localStorage.getItem('metaID')}`; 187 acts[key] = {}; 188 acts[key]['idActivities'] = key; 189 acts[key]['dt_recorded'] = new Date(); 190 acts[key]['dt_activity'] = new Date(); 191 acts[key]['Meta_idMeta'] = localStorage.getItem('metaID'); 192 acts[key]['path'] = from; 193 acts[key]['key'] = from; 194 // acts[key]['tuc'] = act.tuc; 195 acts[key]['activity'] = act.activity; 196 acts[key]['category'] = cat; 197 uploadActs(acts); 198 // make Menu/Survey button return to last survey screen 199 app.activities.Survey.next = act.next; 200 app.activities.Survey['activity'] = "Survey"; 201 app.activities.Survey['icon'] = "survey_progress"; 202 app.activities.Survey['help'] = act.help; 203 uploadModifiedAct(app.activities.Survey); 204 break; 205 default: 206 console.log(from); 207 console.log(key); 208 console.log(acts[key]); 209 acts[key]['key'] = from; 210 // acts[key]['tuc'] = act.tuc; 211 acts[key]['activity'] = act.activity; 212 acts[key]['category'] = act.category; 213 document.getElementById('freetext').value = act.activity; 214 app.setFooter('done'); 215 } 216 217 if ('belongs' in act) { 218 if (act.belongs != "") { 219 console.log("XXX Uploading a belonger:", act.belongs); 220 acts[key]['belongs'] = act.belongs; 221 // any activity that 'belongs' somewhere is put there and prepared to become a custom activity during upload 222 app.activities[from].icon = act.icon; 223 app.activities['Change icon new'].icon = act.icon; 224 app.activities['Change icon'].icon = act.icon; 225 idx = app.screens[act.belongs]['activities'].indexOf(from); 226 // button exists: delete and insert at top 227 if (idx > -1) { delete app.screens[act.belongs]['activities'][idx]; } 228 app.screens[act.belongs]['activities'].unshift(from); 229 uploadModifiedAct(app.activities[from]); 230 } 231 } 232 233 if (key in acts) { acts[key]['path'] += `,${act.key}` }; // 'if' for server use (key could be '') 234 localStorage.setItem('acts',JSON.stringify(acts)); 235 }, 236 237 238 moveTo: function(to) { 239 if ((to == "home") && app.isHome()) { 240 // time for a timed request? 241 hoursElapsed = (new Date().getTime() - new Date(localStorage.getItem('lastNotification')).getTime())/3600000; 242 if (hoursElapsed > 22) { to = 'comfort'; } 243 } 244 document.getElementById('buttons').style.height = ''; 245 app.drawButtons(to); 246 switch(to) { 247 case "home": 248 downloadCustomActivities( uploadActs(app.listActivities()) ); 249 app.history = new Array(); 250 document.getElementById('list').style.display = ''; 251 setTimeout(function() { document.getElementById('buttons').style.display = 'none'; }, 0); 252 document.getElementById('footer').style.display = 'none'; 253 localStorage.setItem('eOffset',0);
254 app.setNav('nav-home'); 255 break; 256 case "user": 257 app.setNav('nav-user'); 258 document.getElementById('footer').style.display = 'none'; 259 break; 260 case "menu": 261 downloadCustomActivities(); 262 app.history = new Array(); 263 app.setNav('nav-menu'); 264 document.getElementById('footer').style.display = 'none'; 265 document.getElementById('buttons').style.height = '75%'; 266 break; 267 case "comfort": 268 sliderInput('comfort'); 269 document.getElementById('slider').style.display = ''; 270 setTimeout(function() { document.getElementById('buttons').style.display = 'none'; }, 0); 271 app.setFooter('abort'); 272 document.getElementById('footer').style.display = ''; 273 break; 274 case "freetext": 275 app.setFooter('save'); 276 document.getElementById('input').style.display = ''; 277 break; 278 case "freetextNew": 279 app.setFooter('save'); 280 document.getElementById('input').style.display = ''; 281 break; 282 } 283 app.history.push(to); // for 'back' 284 }, 285 286 drawButtons: function(to) { 287 if (typeof app.screens[to] == 'undefined') { 288 to = "menu"; 289 } 290 const screen = app.screens[to]; 291 app.defaultView(); 292 if (to == "server") { 293 if (localStorage.getItem('sc') == null) { 294 document.getElementById('navbar').style.display = 'none'; 295 } 296 document.getElementById('server').style.display = ''; 297 document.getElementById('header').style.display = 'none'; 298 document.getElementById('footer').style.display = 'none'; 299 } else { 300 document.getElementById('buttons').innerHTML = ''; // start afresh 301 document.getElementById('buttons').className = 'buttons'; 302 document.getElementById('title').innerHTML = app.formatString(screen.title); 303 for (i in screen.activities) { 304 actKey = screen.activities[i]; 305 act = app.activities[actKey]; 306 // Button 307 var btn = document.createElement('div'); 308 btn.className = `btn ${act.category}`; 309 btn.style.backgroundImage = `url('svg/${act.icon}.svg')`; 310 if (Object.keys(screen.activities).length > 6) { 311 document.getElementById('buttons').className = 'buttons oneCol'; 312 btn.style.backgroundPosition = 'left'; 313 } 314 if (act.category == 'function') { 315 btn.setAttribute("onclick", act.next); 316 } else { 317 btn.setAttribute("onclick", `app.moveFromTo('${actKey}','${act.next}')`); 318 } 319 // Title 320 var title = document.createElement('div'); 321 title.className = 'btn-title'; 322 title.innerHTML = app.formatString(act.activity); 323 // Help 324 var help = document.createElement('div'); 325 help.className = 'help no-help'; 326 help.innerHTML = act.help; 327 btn.appendChild(title); 328 btn.appendChild(help); 329 document.getElementById('buttons').appendChild(btn); 330 } 331 // quirk to make animation work 332 setTimeout(function() { 333 document.getElementById('list').scrollTo(0,0); 334 document.getElementById('buttons').style.display = ''; } 335 , 0); 336 } 337 }, 338 339 340 moveFromTo: function(from, to) { 341 console.log("FROM:",from); 342 console.log("to:",to); 343 document.getElementById('buttons').style.animation = '0.5s ease-out 0s 1 slideIn'; 344 app.moveFrom(from); 345 app.moveTo(to); 346 }, 347 348 setFooter: function(footRight) { 349 const footer = app.activities[footRight]; 350 document.getElementById('foot-right-img').src = `svg/${footer.icon}.svg`; 351 document.getElementById('foot-right-help').innerHTML = footer.help; 352 document.getElementById('foot-right').setAttribute("onclick", footer.next); 353 }, 354 355 defaultView: async function() { 356 document.getElementById('navbar').style.display = ''; 357 document.getElementById('header').style.display = ''; 358 document.getElementById('slider').style.display = 'none'; 359 document.getElementById('input').style.display = 'none'; 360 document.getElementById('server').style.display = 'none'; 361 document.getElementById('list').style.display = 'none'; 362 document.getElementById('buttons').style.display = 'none'; 363 document.getElementById('footer').style.display = ''; 364 [...document.querySelectorAll('.help')].map(e=>{e.classList.add('no-help')}); 365 document.getElementById('nav-help').classList.remove('nav-on'); 366 }, 367 368 setNav: function(on) { 369 document.getElementById('nav-menu').classList = 'btn-nav'; 370 document.getElementById('nav-home').classList = 'btn-nav'; 371 document.getElementById('nav-user').classList = 'btn-nav'; 372 document.getElementById(on).classList = 'nav-on'; 373 }, 374 375 deleteAct: async function() {
376 const key = localStorage.getItem('key'); 377 var acts = JSON.parse(localStorage.getItem('acts')); 378 deleteAct(key); // remove from server 379 await delete acts[key]; 380 await localStorage.setItem('acts',JSON.stringify(acts)); 381 app.moveTo('home'); 382 }, 383 384 changeEnj: function(key) { 385 localStorage.setItem('key',key); 386 app.moveTo('enjoyment'); 387 app.setFooter('done'); 388 app.markForUpload(key); 389 }, 390 391 changeTitle: function(key) { 392 localStorage.setItem('key',key); 393 console.log("Changing key:",key); 394 var acts = JSON.parse(localStorage.getItem('acts')); 395 document.getElementById('freetext').value = acts[key]['activity']; 396 if (acts[key].key in app.activities) { 397 app.activities['Change icon'].icon = app.activities[acts[key].key].icon; 398 } 399 app.setFooter('save'); 400 app.moveTo('freetext'); 401 app.markForUpload(key); 402 }, 403 404 markForUpload: function(key) { 405 var acts = JSON.parse(localStorage.getItem('acts')); 406 acts[key]['uploaded'] = false; 407 localStorage.setItem('acts',JSON.stringify(acts)); 408 }, 409 410 listActivities: function() { 411 var list = document.getElementById('list'); 412 list.innerHTML = ''; // start afresh 413 list.className = ''; 414 const options = { weekday: 'long', day: 'numeric', month: 'short'}; 415 var acts = JSON.parse(localStorage.getItem('acts')); 416 var weekday = ''; 417 var row = document.createElement('div'); 418 row.className = 'activity-row new'; 419 var recent = document.createElement('div'); 420 recent.setAttribute("onclick","app.newAct('setTime');"); 421 recent.className = 'activity-time'; 422 recent.innerHTML = 'Set'; 423 var actImg = document.createElement('img'); 424 actImg.className = 'activity-icon'; 425 actImg.setAttribute("onclick","app.newAct('setTime')"); 426 actImg.src = 'svg/act_add.svg'; 427 var label = document.createElement('div'); 428 label.setAttribute("onclick","app.newAct('activity root');"); 429 label.className = 'activity-item'; 430 label.innerHTML = "New entry"; 431 var blank = document.createElement('div'); 432 blank.setAttribute("onclick","app.newAct('activity root');"); 433 row.appendChild(recent); 434 row.appendChild(actImg); 435 row.appendChild(label); 436 row.appendChild(blank); 437 var recentHelp = document.createElement('div'); 438 recentHelp.setAttribute("onclick","app.newAct('setTime');"); 439 recentHelp.className = 'help no-help help-relative span-2'; 440 recentHelp.innerHTML = 'Set time & duration'; 441 var labelHelp = document.createElement('div'); 442 labelHelp.setAttribute("onclick","app.newAct('activity root');"); 443 labelHelp.className = 'help no-help help-relative'; 444 labelHelp.innerHTML = 'Add activity or appliance you use now'; 445 row.appendChild(recentHelp); 446 row.appendChild(labelHelp); 447 list.appendChild(row); 448 449 450 for (key in acts) { 451 act = acts[key]; 452 if (!('activity' in act) || (act['activity'] == null)) { 453 console.log("deleted:", act.idActivities); 454 delete acts[key]; 455 } 456 } 457 var keys = Object.keys(acts).sort().reverse(); 458 for (var i = 0; i < keys.length; i++) { 459 // use i to process in date (key) order 460 var key = keys[i]; 461 var act = acts[key]; 462 if (('activity' in act) & (act['activity'] !== null) & (act['category'] != 'comfort') & (act['category'] != 'survey')) { 463 var dt = new Date(act.dt_activity); 464 thisWeekday = dt.toLocaleString(getLang(), options); 465 if (weekday != thisWeekday) { // add date row 466 var row = document.createElement('div'); 467 row.className = 'activity-row date'; 468 var label = document.createElement('div'); 469 label.innerHTML = thisWeekday; 470 row.appendChild(document.createElement('div')); 471 row.appendChild(document.createElement('div')); 472 row.appendChild(label); 473 list.appendChild(row); 474 weekday = thisWeekday; 475 } 476 var row = document.createElement('div'); 477 row.className = `activity-row ${act.category}`; 478 var time = document.createElement('div'); 479 time.className = 'activity-time'; 480 time.setAttribute("onclick",`app.timeSliders("${key}")`); 481 time.innerHTML = dt.toLocaleTimeString(getLang(), {hour: 'numeric', minute:'2-digit'}); 482 var icon = document.createElement('img'); 483 icon.className = 'activity-icon'; 484 icon.setAttribute("onclick",`app.changeTitle("${key}")`);
485 if (act.key in app.activities) { 486 icon.src = `svg/${app.activities[act.key].icon}.svg`; 487 } 488 var title = document.createElement('div'); 489 title.className = 'activity-item'; 490 title.setAttribute("onclick",`app.changeTitle("${key}")`); 491 title.innerHTML = act.activity; 492 var divEnj = document.createElement('div'); 493 divEnj.className = 'activity-item'; 494 divEnj.setAttribute("onclick",`app.changeEnj("${key}")`); 495 var actIcon = document.createElement('img'); 496 actIcon.className = 'activity-enjoy'; 497 actIcon.src = `svg/enjoy_${act.enjoyment}.svg`; 498 list.appendChild(row); 499 row.appendChild(time); 500 row.appendChild(icon); 501 row.appendChild(title); 502 row.appendChild(divEnj); 503 if (i == 0) { 504 var recentActHelp = document.createElement('div'); 505 recentActHelp.setAttribute("onclick",`app.timeSliders("${key}")`); 506 recentActHelp.className = 'help no-help help-relative span-2'; 507 recentActHelp.innerHTML = 'Change time & duration'; 508 var labelActHelp = document.createElement('div'); 509 labelActHelp.setAttribute("onclick",`app.changeTitle("${key}")`); 510 labelActHelp.className = 'help no-help help-relative'; 511 labelActHelp.innerHTML = 'Rename, pick icon, or delete'; 512 var enjoyActHelp = document.createElement('div'); 513 enjoyActHelp.setAttribute("onclick",`app.changeEnj("${key}")`); 514 enjoyActHelp.className = 'help no-help help-relative'; 515 enjoyActHelp.innerHTML = 'Change enjoyment'; 516 row.appendChild(recentActHelp); 517 row.appendChild(labelActHelp); 518 row.appendChild(enjoyActHelp); 519 } 520 521 divEnj.appendChild(actIcon); 522 } 523 } 524 localStorage.setItem('acts',JSON.stringify(acts)); 525 return acts; 526 }, 527 528 529 listIcons: function(next) { 530 SVGs = ['renew', 'help', 'other', 'plus', 'dots', 'act', 'appliance', 'arrange', 'baking', 'bath', 'bathroom', 'battery_mower', 'bbq', 'beauty', 'bed_awake', 'bike', 'book', 'bread', 'car', 'child_bed', 'child_play', 'children', 'clean_floor', 'clean_yard', 'clothes_sort', 'coffeemaker', 'computer', 'cook', 'copy', 'custom', 'customised', 'data_transfer', 'dishwasher', 'dog', 'dress', 'dry_line', 'e_shower', 'eat', 'enjoy_1', 'enjoy_2', 'enjoy_3', 'enjoy_4', 'enjoy_5', 'EV', 'exercise', 'family', 'fan_heater', 'female', 'fish', 'food', 'foodprocessor', 'friends', 'games', 'garden', 'gardening', 'getting_ready', 'hair_curler', 'hair_dryer', 'hair_trimmer', 'AC', 'heater', 'help_physical', 'hob', 'home', 'hot_drink', 'house_garden', 'iron', 'kettle', 'laptop', 'laundry', 'lay_table', 'leisure', 'light', 'machinery', 'male', 'meal_cold', 'meal_hot', 'microwave', 'mixer', 'mobile', 'nature', 'others', 'outside', 'oven', 'patio_heater', 'personal', 'petrol_mower', 'pets', 'pottering', 'power_tool', 'printer', 'public_transport', 'radio', 'rest', 'router', 'run', 'sauna', 'save', 'screen', 'search', 'server', 'sewing', 'shaver', 'shop', 'shopping', 'shower', 'sink', 'sleep', 'slowcooker', 'snack', 'streaming', 'study', 'supervise', 'tablet', 'tidy', 'tip', 'toaster', 'toothbrush', 'toy', 'travel', 'tumble_dryer', 'TV', 'user_star', 'user', 'vacuum_cleaner', 'volunteer', 'walk', 'wash_dress', 'washer_dryer', 'washing_machine', 'with_child', 'with_others', 'work_machine', 'work_manual', 'work', 'workplace', 'english','language', 'www'] 531 532 var list = document.getElementById('list'); 533 list.innerHTML = ''; // start afresh 534 list.className = ''; 535 var div = document.createElement('div'); 536 div.className = 'icon-grid'; 537 var cell = document.createElement('div'); 538 cell.innerHTML = 'Current icon'; 539 div.append(cell); 540 541 var key = localStorage.getItem('key'); 542 var acts = JSON.parse(localStorage.getItem('acts')); 543 var actKey = acts[key].key; 544 var icon = app.activities[actKey].icon; 545 var img = document.createElement('img'); 546 img.className = 'icon-item'; 547 img.setAttribute("src",`svg/${icon}.svg`); 548 img.setAttribute("alt",`Current Icon`); 549 img.setAttribute("onclick", `updateIcon('${icon}','${next}')`); 550 div.append(img) 551 var cell2 = document.createElement('div'); 552 cell2.innerHTML = ''; 553 div.append(cell2); 554 555 for (i in SVGs) { 556 icon = SVGs[i]; 557 //svg = icon.replace('icon/','');
558 //svg = svg.replace('.svg',''); 559 img = document.createElement('img'); 560 img.className = 'icon-item'; 561 img.setAttribute("src",`svg/${icon}.svg`); 562 img.setAttribute("alt",`Image ${icon}`); 563 img.setAttribute("onclick", `updateIcon('${icon}','${next}')`); 564 div.append(img) 565 } 566 list.appendChild(div); 567 document.getElementById('input').style.display = 'none'; 568 document.getElementById('footer').style.display = 'none'; 569 document.getElementById('buttons').style.display = 'none'; 570 document.getElementById('title').innerHTML = "Pick an icon"; 571 document.getElementById('list').style.display = ''; 572 }, 573 574 featureGrid: function(feature,title,help) { 575 var list = document.getElementById('list'); 576 list.innerHTML = ''; // start afresh 577 list.className = `feature-grid`; 578 var actFeature = feature; 579 if (feature == 'enjoy') {actFeature = 'enjoyment'} // bit of a hack to avoid renaming all enjoyment to enjoy 580 var recent = "app.newAct('setTime')" 581 var action = "app.newAct('activity root')"; 582 if (feature == 'comfort') { 583 recent = "app.newAct('comfort root')"; 584 action = "app.newAct('comfort root')"; 585 } 586 587 var div = document.createElement('div'); 588 div.className = 'feature-item-add'; 589 var row = document.createElement('div'); 590 row.className = 'activity-row new'; 591 var actImg = document.createElement('img'); 592 actImg.className = 'activity-icon'; 593 actImg.setAttribute("onclick",recent); 594 actImg.src = 'svg/act.svg'; 595 var plus = document.createElement('img'); 596 plus.setAttribute("onclick",action); 597 plus.className = 'activity-icon'; 598 plus.src = 'svg/plus.svg'; 599 var label = document.createElement('div'); 600 label.setAttribute("onclick",action); 601 label.className = 'activity-item'; 602 label.innerHTML = "New entry"; 603 var blank = document.createElement('div'); 604 blank.setAttribute("onclick",action); 605 row.appendChild(actImg); 606 row.appendChild(plus); 607 row.appendChild(label); 608 row.appendChild(blank); 609 div.appendChild(row); 610 list.appendChild(div); 611 612 var lastMonth = ''; 613 var acts = JSON.parse(localStorage.getItem('acts')); 614 var keys = Object.keys(acts).sort().reverse(); 615 var count = 0; 616 for (var i = 0; i < keys.length; i++) { 617 var key = keys[i]; 618 var act = acts[key]; 619 if ((actFeature in act) & (act[actFeature] !== null)) { 620 var div = document.createElement('div'); 621 var featureVal = `${feature}_${act[actFeature]}`; 622 featureVal = featureVal.replace('.','_'); 623 div.className = `feature-item ${featureVal}`; 624 div.setAttribute("onclick",`app.toggleId("feature_${key}",".feature-label")`); 625 var label = document.createElement('div'); 626 label.className = `feature-label ${featureVal}`; 627 label.id = `feature_${key}`; 628 label.setAttribute("onclick",`app.toggleId("feature_${key}",".feature-label")`); 629 var dt = new Date(act.dt_activity); 630 var day = dt.toLocaleString(getLang(), { weekday: 'short', day: 'numeric', month: 'numeric'}); 631 var time = dt.toLocaleTimeString(getLang(), {hour: '2-digit', minute:'2-digit'}); 632 if (featureVal in app.activities) { // e.g. 'comfort_1' exists 633 caption = app.activities[featureVal].activity; 634 label.innerHTML = `${day}<br>${time}<br><b>${caption}</b>`; 635 } else { 636 label.innerHTML = `${day}<br>${time}<br><b>${act.activity}</b><span class="zoom-inner">`; 637 } 638 label.style.display = 'none'; 639 var month = dt.toLocaleString(getLang(), {month: 'long', year: 'numeric'}); 640 if (month != lastMonth) { 641 var monthDiv = document.createElement('div'); 642 monthDiv.innerHTML = month; 643 monthDiv.className = 'feature-date'; 644 list.appendChild(monthDiv); 645 } 646 lastMonth = month; 647 list.appendChild(div); 648 list.appendChild(label); 649 count +=1; 650 } 651 } 652 var tipText = document.createElement('div'); 653 tipText.className = "help help-top no-help"; 654 tipText.setAttribute("onclick","app.toggleHelp()"); 655 tipText.innerHTML = help 656 list.appendChild(tipText); 657 app.defaultView(); 658 document.getElementById('footer').style.display = 'none'; 659 document.getElementById('title').innerHTML = title; 660 document.getElementById('list').style.display = ''; 661 }, 662 663 664 onboardedScreen: function() { 665 document.getElementById('title').innerHTML = "Registration in progress"; 666 var list = document.getElementById('list'); 667 list.innerHTML = ''; // start afresh 668 var strapline = document.createElement('p'); 669 strapline.innerHTML = "Your smart meter information has been submitted.<br><br>Please check your email (and junk folder) for an email to confirm your consent. At the very bottom of the Terms & Conditions you need to 'sign' with your postcode. Once you have done this, it should not take long for you to be able to access your smart meter data here. <br><br>Any problems? Please email <a href='mailto:[email protected]'>[email protected]</a> and we try to help."; 670 list.append(strapline); 671 672 var button = document.createElement('button'); 673 button.className = 'btn-green'; 674 button.setAttribute("onclick",'app.validateEUIscreen()'); 675 button.innerHTML = "Enter smart meter details again"; 676 list.append(button); 677 678 app.defaultView(); 679 document.getElementById('footer').style.display = 'none'; 680 document.getElementById('list').style.display = ''; 681 }, 682 683 684 validateEUIscreen: function() { 685 document.getElementById('title').innerHTML = "Register your smart meter"; 686 var list = document.getElementById('list'); 687 list.className = ''; 688 list.innerHTML = ''; // start afresh 689 var display = document.createElement('img'); 690 display.src = 'svg/GUID.svg'; 691 display.setAttribute("width","80%"); 692 list.append(display); 693 var strapline = document.createElement('p'); 694 strapline.id = 'eui-text'; 695 strapline.innerHTML = 'Please enter the 16 digit code under your smart meter display and confirm your postcode'; 696 list.append(strapline); 697 var eui = document.createElement('input'); 698 eui.id = 'eui'; 699 eui.type = 'text'; 700 eui.className = 'input-eui'; 701 eui.placeholder = 'xx xx xx xx xx xx xx xx'; 702 list.append(eui); 703 var postcode = document.createElement('input'); 704 postcode.id = 'postcode'; 705 postcode.type = 'text'; 706 postcode.className = 'input-postcode'; 707 postcode.placeholder = 'postcode'; 708 list.append(postcode); 709 var button = document.createElement('button'); 710 button.id = 'eui-button'; 711 button.className = 'btn-green'; 712 button.setAttribute("onclick",'validateEUI()'); 713 button.innerHTML = "Submit"; 714 list.append(button); 715 app.defaultView(); 716 document.getElementById('footer').style.display = 'none'; 717 document.getElementById('list').style.display = ''; 718}, 719 720 newAct: function(next) { 721 var acts = JSON.parse(localStorage.getItem('acts')); 722 localStorage.setItem('index', parseInt(localStorage.getItem('index'))+1); 723 key = `${Number(new Date())}_${localStorage.getItem('index')}_${localStorage.getItem('metaID')}`; 724 localStorage.setItem('key',key); 725 acts[key] = {}; 726 acts[key]['idActivities'] = key; 727 acts[key]['dt_recorded'] = new Date(); 728 if (localStorage.getItem('dt_activity') != null) {
729 // hack for appliances to store their time from energy graph 730 acts[key]['dt_activity'] = new Date(localStorage.getItem('dt_activity')); 731 localStorage.removeItem('dt_activity'); 732 } else { 733 acts[key]['dt_activity'] = new Date(); 734 } 735 acts[key]['Meta_idMeta'] = localStorage.getItem('metaID'); 736 acts[key]['path'] = ''; //act.tuc; 737 localStorage.setItem('acts',JSON.stringify(acts)); 738 if (next == 'setTime') { 739 app.timeSliders(key); 740 } else { 741 app.moveTo(next); 742 } 743 }, 744 745 timeSliders: function(key) { 746 localStorage.setItem('key',key); 747 app.markForUpload(key); 748 const acts = JSON.parse(localStorage.getItem('acts')); 749 var act = acts[key]; 750 var list = document.getElementById('list'); 751 list.innerHTML = ''; // start afresh 752 list.className = ''; 753 app.defaultView(); 754 document.getElementById('list').style.display = ''; 755 if ('activity' in act) { 756 document.getElementById('title').innerHTML = act.activity; 757 app.setFooter('saveTime'); 758 } else { 759 document.getElementById('title').innerHTML = "Set time for new activity"; 760 app.setFooter('next'); 761 } 762 763 var dt = new Date(act.dt_activity); 764 var time = document.createElement('h1'); 765 time.id = 'sliderTime'; 766 time.innerHTML = dt.toLocaleTimeString(getLang(), {hour: 'numeric', minute:'2-digit'})+"<br><small>Slide to change time</small>"; 767 var timeSlider = document.createElement('input'); 768 timeSlider.id = 'timeSlider'; 769 timeSlider.className = 'time-slider'; 770 timeSlider.type = 'range'; 771 timeSlider.setAttribute("min","-60"); 772 timeSlider.setAttribute("max","60"); 773 timeSlider.setAttribute("step","5"); 774 timeSlider.setAttribute("value","0"); 775 timeSlider.setAttribute("oninput","app.changeTime()"); 776 timeSlider.setAttribute("onmouseup","app.setTime()"); 777 timeSlider.setAttribute("ontouchend","app.setTime()"); 778 list.append(time) 779 list.append(timeSlider) 780 781 var duration = 0; 782 if ('duration' in act) { duration = parseInt(act.duration); } 783 784 var durationText = document.createElement('h1'); 785 durationText.id = 'sliderDuration'; 786 var durationSlider = document.createElement('input'); 787 durationSlider.id = 'durationSlider'; 788 durationSlider.className = 'time-slider'; 789 durationSlider.type = 'range'; 790 durationSlider.setAttribute("min","0"); 791 durationSlider.setAttribute("max",duration+60); 792 durationSlider.setAttribute("step",5); 793 durationSlider.setAttribute("value",duration); 794 durationSlider.setAttribute("oninput","app.changeDuration()"); 795 durationSlider.setAttribute("onmouseup","app.setDuration()"); 796 durationSlider.setAttribute("ontouchend","app.setDuration()"); 797 list.append(durationText); 798 list.append(durationSlider); 799 app.changeDuration(); 800}, 801 802 changeDuration: function() { 803 var duration = parseInt(document.getElementById('durationSlider').value); 804 const key = localStorage.getItem('key'); 805 var acts = JSON.parse(localStorage.getItem('acts')); 806 var act = acts[key]; 807 var dt = new Date(act.dt_activity); 808 var dtime = new Date(dt.setTime(dt.getTime() + (60000*duration))); 809 dtime = roundDate(dtime); 810 var dtimeStr = dtime.toLocaleTimeString(getLang(), {hour: 'numeric', minute:'2-digit'}); 811 dtimeStr = `<br><small>until ${dtimeStr}</small>` 812 if (duration > 57) { 813 var hours = Math.floor(duration/60); 814 var minutes = duration%60; 815 if (minutes < 10) {minutes = '0'+minutes;} 816 document.getElementById('sliderDuration').innerHTML = `For ${hours}h ${minutes}min ${dtimeStr}`; 817 } else if (duration > 0) { 818 document.getElementById('sliderDuration').innerHTML = `For ${duration} min ${dtimeStr}`; 819 } else { 820 document.getElementById('sliderDuration').innerHTML = `Duration (optional)`; 821 } 822 }, 823 824 setDuration: function() { 825 const key = localStorage.getItem('key'); 826 var acts = JSON.parse(localStorage.getItem('acts')); 827 var durationSlider = document.getElementById('durationSlider'); 828 const duration = parseInt(durationSlider.value); 829 acts[key]['duration'] = duration; 830 localStorage.setItem('acts',JSON.stringify(acts)); 831 durationSlider.setAttribute("max",duration+60); 832 durationSlider.setAttribute("value",duration); 833 }, 834 835 changeTime: function() {
836 const key = localStorage.getItem('key'); 837 var acts = JSON.parse(localStorage.getItem('acts')); 838 var act = acts[key]; 839 var dt = new Date(act.dt_activity); 840 var time = document.getElementById('sliderTime'); 841 var slider = document.getElementById('timeSlider'); 842 const res = 5*60*1000; 843 var dt = new Date(dt.setTime(dt.getTime() + (60000*slider.value))); 844 dt = roundDate(dt); 845 var diff = parseInt((dt-roundDate(new Date()))/60000); 846 var diffStr = "(now)"; 847 if (diff > 0) { 848 diffStr = `(in ${diff} min)`; 849 } 850 if (diff > 59) { 851 var hours = Math.floor(diff/60); 852 var minutes = diff%60; 853 if (minutes < 10) {minutes = '0'+minutes;} 854 diffStr = `(in ${hours}:${minutes})`; 855 } 856 if (diff < 0) { 857 diffStr = `(${-diff} min ago)`; 858 } 859 if (diff < -59) { 860 var hours = Math.floor(-diff/60); 861 var minutes = -diff%60; 862 if (minutes < 10) {minutes = '0'+minutes;} 863 diffStr = `(${hours}h ${minutes}min ago)`; 864 } 865 diffStr = `<br><small> ${diffStr}</small>` 866 time.innerHTML = dt.toLocaleTimeString(getLang(), {hour: 'numeric', minute:'2-digit'}) + diffStr; 867 // update duration end time 868 869 var duration = parseInt(document.getElementById('durationSlider').value); 870 if (duration > 0) { 871 var dtime = new Date(dt.setTime(dt.getTime() + (60000*duration))); 872 var dtimeStr = dtime.toLocaleTimeString(getLang(), {hour: 'numeric', minute:'2-digit'}); 873 dtimeStr = `<br><small>until ${dtimeStr}</small>` 874 document.getElementById('sliderDuration').innerHTML = dtimeStr; 875 } 876 877 }, 878 879 setTime: function() { 880 const key = localStorage.getItem('key'); 881 var acts = JSON.parse(localStorage.getItem('acts')); 882 var act = acts[key]; 883 var dt = new Date(act.dt_activity); 884 const slider = document.getElementById('timeSlider'); 885 const res = 5*60*1000; 886 dt = new Date(Math.round(dt.setTime(dt.getTime() + (60000*slider.value))/res)*res); 887 const newKey = `${Number(dt)}_${localStorage.getItem('index')}_${localStorage.getItem('metaID')}`; 888 acts[key]['dt_activity'] = dt; 889 if (newKey != key) { 890 localStorage.setItem('key',newKey); 891 acts[key]['idActivities'] = newKey; 892 acts[newKey] = acts[key]; // create copy 893 delete acts[key]; // remove local 894 deleteAct(key); // remove server 895 } 896 localStorage.setItem('acts',JSON.stringify(acts)); 897 document.getElementById('timeSlider').value = 0; 898 }, 899 900 saveTime: function() { 901 // called from footer as belts and braces in case the 'ontouchend' doesn't fire (Safiri, IE, Opera) 902 app.setDuration(); 903 app.setTime(); 904 app.moveTo('home'); 905 }, 906 907 908 energyHistory: function(_type) { 909 type = _type; 910 app.defaultView(); 911 document.getElementById('footer').style.display = 'none'; 912 913 var list = document.getElementById('list'); 914 list.innerHTML = ''; // start afresh 915 list.style.display = ''; 916 var container = document.createElement('div'); 917 container.id = 'energy-year-container'; 918 container.className = 'energy-year-container'; 919 var switchBtn = document.createElement('button'); 920 // switchBtn.id = 'energy-switch'; 921 switchBtn.className = 'energy-switch'; 922 if (type == 'el') { 923 document.getElementById('title').innerHTML = "Annual Electricity"; 924 switchBtn.innerHTML = "show Gas"; 925 switchBtn.setAttribute("onclick","app.energyHistory('gas')"); 926 } else { 927 document.getElementById('title').innerHTML = "Annual Gas use"; 928 switchBtn.innerHTML = "show Electricity"; 929 switchBtn.setAttribute("onclick","app.energyHistory('el')"); 930 } 931 list.append(switchBtn); 932 var monthContainer = document.createElement('div'); 933 monthContainer.id = 'energy-month-container'; 934 monthContainer.className = 'energy-month-container'; 935 monthContainer.width = '100%'; 936 937 var loading = document.createElement('img'); 938 loading.id = 'loadingYear'; 939 loading.setAttribute("src","vid/loading.gif"); 940 loading.setAttribute("alt","Loading your data ..."); 941 loading.className = "loading"; 942 list.append(loading); 943 944 for (let m = 1; m < 13; m++) { 945 var thisBar = document.createElement('div'); 946 thisBar.id = `m${m}`; 947 thisBar.className = `energy-day-bar movable`; 948 thisBar.style.height = "1px"; 949 thisBar.style.width = "6%"; 950 thisBar.style.left = `${m*6}%`; 951 container.appendChild(thisBar); 952 var dayLabel = document.createElement('div');
953 dayLabel.id = `m${m}_lbl`; 954 dayLabel.className = 'energy-month-label'; 955 dayLabel.style.width = "6%"; 956 dayLabel.style.left = `${m*6}%`; 957 container.appendChild(dayLabel); 958 } 959 var thisBar = document.createElement('div'); 960 thisBar.id = `year`; 961 thisBar.className = `energy-day-bar movable`; 962 thisBar.style.height = "100px"; 963 thisBar.style.width = "8%"; 964 thisBar.style.right = `5%`; 965 container.appendChild(thisBar); 966 var thisLine = document.createElement('div'); 967 thisLine.id = `year_avg`; 968 thisLine.className = `energy-avg-line movable`; 969 container.appendChild(thisLine); 970 var thisLabel = document.createElement('div'); 971 thisLabel.id = `year_lbl`; 972 thisLabel.className = `energy-month-label`; 973 container.appendChild(thisLabel); 974 list.appendChild(container); 975 976 for (let d = 1; d < 32; d++) { 977 var thisBar = document.createElement('div'); 978 thisBar.id = `d${d}`; 979 thisBar.className = `energy-day-bar movable`; 980 thisBar.style.width = "2.8%"; 981 thisBar.style.left = `${d*2.7}%`; 982 monthContainer.appendChild(thisBar); 983 var refBar = document.createElement('div'); 984 refBar.id = `d${d}_ref`; 985 refBar.className = `energy-day-bar-ref movable`; 986 refBar.style.width = "2%" 987 refBar.style.left = `${d*2.7}%`; 988 monthContainer.appendChild(refBar); 989 var dayLabel = document.createElement('div'); 990 dayLabel.id = `d${d}_lbl`; 991 dayLabel.className = 'energy-day-label'; 992 dayLabel.style.left = `${d*2.7}%`; 993 monthContainer.appendChild(dayLabel); 994 } 995 list.appendChild(monthContainer); 996 var thisBar = document.createElement('div'); 997 thisBar.id = `month`; 998 thisBar.className = `energy-day-bar movable`; 999 thisBar.style.height = "100px"; 1000 thisBar.style.width = "8%"; 1001 thisBar.style.right = `5%`; 1002 monthContainer.appendChild(thisBar); 1003 var thisLine = document.createElement('div'); 1004 thisLine.id = `month_avg`; 1005 thisLine.className = `energy-avg-line movable`; 1006 monthContainer.appendChild(thisLine); 1007 var thisLabel = document.createElement('div'); 1008 thisLabel.id = `month_lbl`; 1009 thisLabel.className = `energy-month-label`; 1010 monthContainer.appendChild(thisLabel); 1011 1012 var graphLabel = document.createElement('div'); 1013 graphLabel.id = 'energy-month-label'; 1014 graphLabel.className = 'energy-graph-label'; 1015 monthContainer.append(graphLabel); 1016 1017// POPULATE WITH DATA 1018 var id = localStorage.getItem('metaID'); 1019 var sc = localStorage.getItem('sc'); 1020 var thisYear = `api/getEnergy.php?range=thisYear&id=${id}&sc=${sc}&type=${type}` 1021 var refYear = `api/getEnergy.php?range=refYear&id=${id}&sc=${sc}&type=${type}` 1022 console.log("refYear api: ",refYear); 1023 if (localStorage.getItem(`thisYear_${type}`) !== null) { 1024 plotEnergyThisYear(JSON.parse(localStorage.getItem(`thisYear_${type}`))); 1025 } 1026 fetch(thisYear) 1027 .then(response => response.json()) 1028 .then(d => { 1029 if ('noAccess' in d) { 1030 // sc and id didn't pass security 1031 url = "register/login.php" 1032 document.getElementById('server').setAttribute('src',url); 1033 app.moveTo("server"); 1034 } else if ('notOnboarded' in d) { 1035 // not listed in Meta as 'active','fulfilled' or 'connected' 1036 console.log("not onboarded"); 1037 if (localStorage.getItem('hasOnboarded')) { 1038 // user has already submitted data 1039 app.onboardedScreen(); 1040 } else { 1041 app.validateEUIscreen(); 1042 } 1043 } else { 1044 document.getElementById("loadingYear").style.display = 'none'; 1045 localStorage.setItem(`thisYear_${type}`,JSON.stringify(d)); 1046 plotEnergyThisYear(d); 1047 fetch(refYear) 1048 .then(response => response.json()) 1049 .then(d => { 1050 localStorage.setItem(`refYear_${type}`,JSON.stringify(d)); 1051 plotEnergyRefYear(d); 1052 }) 1053 } 1054 }); 1055 }, 1056 1057 energyMonth: function(month) { 1058 document.getElementById("loadingYear").style.display = ''; 1059
1060 // clear up any previously displayed month 1061 for (let d = 1; d < 32; d++) { 1062 document.getElementById(`d${d}`).style.height = "2px"; 1063 document.getElementById(`d${d}_ref`).style.bottom = "0%"; 1064 document.getElementById(`d${d}_lbl`).innerHTML = ""; 1065 } 1066 1067 var mContainer = document.getElementById('month-container'); 1068 var id = localStorage.getItem('metaID'); 1069 var sc = localStorage.getItem('sc'); 1070 var thisMonth = `api/getEnergy.php?range=thisMonth&id=${id}&sc=${sc}&month=${month}&type=${type}` 1071 var refMonth = `api/getEnergy.php?range=refMonth&id=${id}&sc=${sc}&month=${month}&type=${type}` 1072 console.log(thisMonth); 1073 fetch(thisMonth) 1074 .then(response => response.json()) 1075 .then(d => { 1076 if ('noAccess' in d) { 1077 // sc and id didn't pass security 1078 url = "register/login.php" 1079 document.getElementById('server').setAttribute('src',url); 1080 app.moveTo("server"); 1081 } else if ('notOnboarded' in d) { 1082 // not listed in Meta as 'active','fulfilled' or 'connected' 1083 console.log("not onboarded"); 1084 if (localStorage.getItem('hasOnboarded')) { 1085 // user has already submitted data 1086 app.onboardedScreen(); 1087 } else { 1088 app.validateEUIscreen(); 1089 } 1090 } else { 1091 // document.getElementById('loadingMonth').remove(); 1092 plotEnergyThisMonth(d); 1093 fetch(refMonth) 1094 .then(response => response.json()) 1095 .then(d => { plotEnergyRefMonth(d); 1096 document.getElementById("loadingYear").style.display = 'none'; 1097 }) 1098 } 1099 }); 1100 }, 1101 1102 energyGrid: function(type) { 1103 document.getElementById('title').innerHTML = "Daily energy use"; 1104 list.innerHTML = ''; // start afresh 1105 app.defaultView(); 1106 document.getElementById('footer').style.display = 'none'; 1107 document.getElementById('list').style.display = ''; 1108 var loading = document.createElement('img'); 1109 loading.setAttribute("src","vid/loading.gif"); 1110 loading.setAttribute("alt","Loading your data ..."); 1111 loading.setAttribute("width","100%"); 1112 list.append(loading); 1113 var id = localStorage.getItem('metaID'); 1114 var sc = localStorage.getItem('sc'); 1115 var api = `api/getEnergy.php?range=days&id=${id}&sc=${sc}` 1116 fetch(api) 1117 .then(response => response.json()) 1118 .then(d => { 1119 if ('noAccess' in d) { 1120 // sc and id didn't pass security 1121 url = "register/login.php" 1122 document.getElementById('server').setAttribute('src',url); 1123 app.moveTo("server"); 1124 } else if ('notOnboarded' in d) { 1125 // not listed in Meta as 'active','fulfilled' or 'connected' 1126 console.log("not onboarded"); 1127 if (localStorage.getItem('hasOnboarded')) { 1128 // user has already submitted data 1129 app.onboardedScreen(); 1130 } else { 1131 app.validateEUIscreen(); 1132 } 1133 } else { 1134 energyGrid(d,type); 1135 } 1136 }); 1137 }, 1138 1139 energyActGraph: function() { 1140 var list = document.getElementById('list'); 1141 list.innerHTML = ''; // start afresh 1142 list.className = ''; 1143 app.defaultView(); 1144 document.getElementById('footer').style.display = 'none'; 1145 document.getElementById('list').style.display = ''; 1146 document.getElementById('title').innerHTML = "Recent energy use"; 1147 var loading = document.createElement('img'); 1148 loading.setAttribute("src","vid/loading.gif"); 1149 loading.setAttribute("alt","Loading your data ..."); 1150 loading.setAttribute("width","100%"); 1151 list.append(loading); 1152 1153 var id = localStorage.getItem('metaID'); 1154 var sc = localStorage.getItem('sc'); 1155 var api = `api/getEnergy.php?id=${id}&sc=${sc}&range=day`; 1156 fetch(api) 1157 .then(response => response.json()) 1158 .then(d => { 1159 if ('noAccess' in d) { 1160 // sc and id didn't pass security 1161 url = "register/login.php" 1162 document.getElementById('server').setAttribute('src',url); 1163 app.moveTo("server"); 1164 } else if ('notOnboarded' in d) { 1165 // not listed in Meta as 'active','fulfilled' or 'connected' 1166 console.log("not onboarded"); 1167 if (localStorage.getItem('hasOnboarded')) { 1168 // user has already submitted data 1169 app.onboardedScreen(); 1170 } else { 1171 app.validateEUIscreen(); 1172 } 1173 } else { 1174 // in Meta as 'active', fulfilled of connected 1175 // XXX handle 'no data' 1176 localStorage.setItem('postcode', d.postcode); 1177 plotEnergyPerHour(d); 1178 peakE = parseInt(localStorage.getItem('peakE')); 1179 d.el.forEach(el => { 1180 var watt = parseInt(el.watt); 1181 bar = document.getElementById(`bar_${el.hour}`); 1182 bar.style.height = `${watt/peakE*80}%`; 1183 } 1184 ) 1185 1186 var refAPI = `api/getRefEnergy.php?id=${id}&sc=${sc}&range=day`; 1187 console.log(refAPI); 1188 fetch(refAPI) 1189 .then(response => response.json()) 1190 .then(d => { 1191 peakE = parseInt(localStorage.getItem('peakE')); 1192 d.el_ref.forEach( e => { peakE = Math.max(e.watt, peakE) }) 1193 d.el_self_ref.forEach( e => { peakE = Math.max(e.watt, peakE) }) 1194 localStorage.setItem('peakE',peakE); 1195 1196 d.el_self_ref.forEach( 1197 ref => { 1198 watt = parseInt(ref.watt); 1199 refBar = document.getElementById(`self_ref_${ref.hour}`); 1200 if (refBar) { refBar.style.bottom = `${10+(watt/peakE*80)}%`; } 1201 self_refLbl = document.getElementById(`self_refLabel_${ref.hour}`); 1202 if (self_refLbl) { self_refLbl.innerHTML = `Typical for you: ${watt} W`;} 1203 } 1204 ) 1205 d.el_ref.forEach( 1206 ref => { 1207 watt = parseInt(ref.watt) 1208 refBar = document.getElementById(`ref_${ref.hour}`) 1209 if (refBar) { refBar.style.bottom = `${10+(watt/peakE*80)}%`; } 1210 refLbl = document.getElementById(`refLabel_${ref.hour}`) 1211 if (refLbl) { refLbl.innerHTML = `Typical for UK: ${watt} W`;} 1212 } 1213 ) 1214 }) 1215 } 1216 }); 1217 1218 }, 1219 1220 addActToHour: function(dt) { 1221 localStorage.setItem('dt_activity', new Date(dt.replace(/-/g, "/"))); 1222 app.newAct('appliances'); 1223 }, 1224 1225 showLabel: function(label) { 1226 var labels = document.getElementsByClassName('hour-label') 1227 for (var i = 0; i < labels.length; i++) { 1228 labels[i].style.display='none'; 1229 } 1230 document.getElementById(label).style.display = ''; 1231 }, 1232 eShift: function(shift) { 1233 var offset = parseInt(localStorage.getItem('eOffset')); 1234 offset += shift; 1235 if (offset < 0) { offset = 0; } 1236 localStorage.setItem('eOffset',offset); 1237 app.energyActGraph(); 1238 }, 1239 eZoom: function(zoom) { 1240 // ±8 1241 var hours = parseInt(localStorage.getItem('eHours')); 1242 hours += zoom; 1243 localStorage.setItem('eHours',hours); 1244 app.energyActGraph(); 1245 }, 1246 1247 toggleZoom: function() { 1248 var list = document.getElementById('list'); 1249 var zoom = document.getElementById('zoom');
1250 if (document.documentElement.getAttribute('zoom') == 'in') { 1251 document.documentElement.setAttribute('zoom','out'); 1252 zoom.setAttribute("src","svg/zoom_in.svg"); 1253 } else { 1254 document.documentElement.setAttribute('zoom','in'); 1255 zoom.setAttribute("src","svg/zoom_out.svg"); 1256 } 1257 }, 1258 1259 toggleId: function(id,divClass) { 1260 var toggle = document.getElementById(id).style.display; 1261 var labels = document.querySelectorAll(divClass); 1262 for (var i = 0; i < labels.length; i++) { 1263 labels[i].style.display = 'none'; 1264 } 1265 if (toggle == 'none') { 1266 document.getElementById(id).style.display = ''; 1267 } 1268 }, 1269 1270 toggleClass: function(divClass) { 1271 div = document.getElementsByClassName(divClass); 1272 for (var i = 0; i < div.length; i++) { 1273 if (div[i].style.display == 'none') { 1274 div[i].style.display = ''; 1275 } else { 1276 div[i].style.display = 'none'; 1277 } 1278 } 1279 }, 1280 1281 goBack: function() { 1282 app.history.pop(); // remove current 1283 const prev = app.history.pop(); 1284 document.getElementById('buttons').style.animation = '0.5s ease-out 0s 1 slideBack'; 1285 if (prev === undefined) { 1286 app.moveTo("home"); 1287 } else { 1288 app.moveTo(prev); 1289 } 1290 }, 1291 1292 1293// HELP 1294 1295 toggleHelp: function() { 1296 [...document.querySelectorAll('.help')].map(e=>{ 1297 e.classList.toggle('no-help') 1298 }); 1299 [...document.querySelectorAll('.help-float')].map(e=>{ 1300 e.classList.toggle('no-help') 1301 }); 1302 document.getElementById('nav-help').classList.toggle('nav-on'); 1303 }, 1304 1305 colourScheme: function(scheme) { 1306 document.documentElement.setAttribute('scheme',scheme); 1307 localStorage.setItem('scheme',scheme); 1308 app.moveTo('menu'); 1309 }, 1310 1311}; 1312 1313app.loadText(); 1314
Line numbers count LF bytes from the start of the resource, as the search results do. Vendor segments are library code the classifier recognised; they are stored but not indexed. Bytes are shown as Latin1 characters, one per byte.