PageSourceSearch

https://joymeter.uk/js/functions.js

js joymeter.uk collected 2026-10-04 04:30:29 UTC 18,523 bytes, 438 lines download raw bytes

1function consent() {
2    localStorage.setItem('consent', new Date())
3    if (!(typeof sc === 'undefined' || sc === null)) { localStorage.setItem('sc', sc); }
4    document.getElementById('consent').style.display = 'none';
5    if (localStorage.getItem('sc') == null) {
6        document.getElementById('server').setAttribute('src', 'register/login.php');
7        app.moveTo('server');
8    } else {
9        updateContact('consent', new Date());
10        app.moveTo(screen);
11    }
12}
13
14function uploadActs(acts) {
15    const keysToUpload = Object.keys(acts).filter(x => !acts[x].uploaded);
16    keysToUpload.map(key => {
17       var act = acts[key];
18       delete act['title'];
19       act['path'] = act.path.toString();
20       const payload = {
21             act:    JSON.stringify(act),
22             metaID: localStorage.getItem('metaID'),
23             sc:     localStorage.getItem('sc')
24             };
25        console.log("upload Payload: ",payload);
26       const requestOptions = {
27           method:  'POST',
28           headers: {"Content-Type":  "application/json"},
29           body:    JSON.stringify(payload)
30       };
31       fetch('api/uploadActs.php', requestOptions)
32           .then(response => response.json())
33           .then(result => {
34               if (result.message == 'success') {
35                   console.log(result);
36                   acts[key].uploaded = true;
37                   console.log("uploaded:", acts[key]);
38                   localStorage.setItem('acts',JSON.stringify(acts));
39               }
40           })
41           .catch(error => console.log('error',error));
42
43    });
44    if (localStorage.getItem('metaID') != '0') { downloadActs() };
45}
46
47function downloadActs() {
48    const payload = {
49         userID: localStorage.getItem('metaID'),
50         sc:     localStorage.getItem('sc')
51    };
52    const requestOptions = {
53       method:  'POST',
54       headers: {"Content-Type":  "application/json"},
55       body:    JSON.stringify(payload)
56    };
57    fetch('api/downloadActs.php', requestOptions)
58       .then(response => response.json())
59       .then(result => {
60           if (result.success) {
61              let acts = JSON.parse(localStorage.getItem('acts'));
62              const before = Object.keys(acts).length;
63              for (key in result.acts) {
64                // the T is needed in Safari
65                result.acts[key]['dt_activity'] = result.acts[key]['dt_activity'].replace(" ","T") + 'Z';
66                result.acts[key]['dt_recorded'] = result.acts[key]['dt_recorded'].replace(" ","T") + 'Z';
67                result.acts[key]['uploaded']    = true;
68                const actKey = result.acts[key]['idActivities'];
69                acts[actKey] = result.acts[key];
70              }
71              localStorage.setItem('acts',JSON.stringify(acts));
72              const imported = Object.keys(acts).length - before;
73              if (imported > 0) {
74                  // document.getElementById('title').innerHTML = imported + " records imported";
75                  localStorage.setItem('index', parseInt(localStorage.getItem('index'))+imported);
76                  app.listActivities();
77              }
78           }
79       })
80       .catch(error => console.log('error', error));
81}
82
83function modifyActivity(mode) {
84    var key  = localStorage.getItem('key');
85    var acts = JSON.parse(localStorage.getItem('acts'));
86    var actKey;
87
88    var text = document.getElementById('freetext').value;
89        text = text.replace("`"," ");
90        text = text.replace("'"," ");
91        text = text.replace("\""," ");
92
93    if (mode == 'replace') {            // use existing key
94        actKey = acts[key]['key'];
95    } else {                            // mode = 'new'
96        if (text in app.activities) {text = text + ' '}
97        actKey = text;
98    }
99    acts[key]['key']      = actKey; 
100    acts[key]['activity'] = text;
101    acts[key]['icon']     = app.activities['Change icon'].icon;
102    localStorage.setItem('acts',JSON.stringify(acts));
103    app.activities[actKey] = acts[key];
104    uploadModifiedAct(app.activities[actKey]);
105    app.moveTo('home')
106}
107
108function uploadModifiedAct(act) {
109    console.log("modified upload: ", act);
110    if (act['next'] == null)    { act['next'] = 'home' }
111    if (act['help'] == null)    { act['help'] = '' }
112    if (act['belongs'] == null) { act['belongs'] = '' }
113    act['metaid'] = localStorage.getItem('metaID');
114    act['sc']     = localStorage.getItem('sc');
115    const requestOptions = {
116              method:  'POST',
117              headers: {"content-type":  "application/json"},
118              body:    JSON.stringify(act)
119              };
120    fetch('api/uploadCustomActivity.php', requestOptions)
121       .then(response => response.json())
122       .then(result => { console.log(result.message); })
123       .catch(error => console.log(error));
124}
125
126function updateIcon(icon,next) {
127    // using app.activities as a placeholder for icon, before it can be committed under 'freetext' Save/Done
128    app.activities['Change icon'].icon = icon;
129    app.activities['Change icon new'].icon = icon;
130    app.moveTo(next);
131}
132
133function downloadCustomActivities() {
134    console.log("Downloading custom activities");
135    const payload = { userID: localStorage.getItem('metaID'), sc:     localStorage.getItem('sc') };
136    const requestOptions = { method:  'POST', headers: {"Content-Type":  "application/json"}, body:    JSON.stringify(payload) };
137    fetch('api/downloadCustomActivities.php', requestOptions)
138       .then(response => response.json())
139       .then(result => {
140           if (result.success) {
141              cActs   = result.cActs;
142              for (i in cActs) {
143                  var cAct = cActs[i];
144                  var act = cAct.activity;
145                  app.activities[act] = {};
146                  // app.activities[act]['tuc']      = cAct.tuc;
147                  app.activities[act]['activity'] = cAct.activity;
148                  app.activities[act]['help']     = cAct.help;
149                  app.activities[act]['icon']     = cAct.icon;
150                  app.activities[act]['category'] = cAct.category;
151                  app.activities[act]['belongs']  = cAct.belongs;
152                  app.activities[act]['next']     = cAct.next;
153                  if (cAct.belongs in app.screens) {
154                      idx = app.screens[cAct.belongs]['activities'].indexOf(act);
155                      if (idx > -1) { delete app.screens[cAct.belongs]['activities'][idx]; }
156                      app.screens[cAct.belongs]['activities'].unshift(act);
157                  }
158              }
159           } else {
160               console.log(result);
161           }
162       })
163       .catch(error => console.log('error', error));
164}
165
166function uploadOptionalButtons(activity,belongs) {
167    const payload = {
168              activity: activity,
169              belongs:  belongs,
170              metaID:   localStorage.getItem('metaID'),
171              sc:       localStorage.getItem('sc')
172              };
173    const requestOptions = {
174              method:  'POST',
175              headers: {"Content-Type":  "application/json"},
176              body:    JSON.stringify(payload)
177              };
178    fetch('api/uploadOptionalButtons.php', requestOptions)
179       .then(response => response.json())
180       .then(result => { console.log(result.message); })
181       .catch(error => console.log(error));
182}
183
184function downloadOptionalButtons() {
185    const payload = { userID: localStorage.getItem('metaID'), sc:     localStorage.getItem('sc') };
186    const requestOptions = { method:  'POST', headers: {"Content-Type":  "application/json"}, body:    JSON.stringify(payload) };
187    fetch('api/downloadOptionalButtons.php', requestOptions)
188       .then(response => response.json())
189       .then(result => {
190           if (result.success) {
191              // optionalButtons = JSON.parse(localStorage.getItem('optionalButtons'));
192              remoteButtons   = result.optionalButtons;
193              for (key in remoteButtons) {
194                  var screen = remoteButtons[key]['belongs'];
195                  var activity = remoteButtons[key]['activity'];
196                  // optionalButtons[activity] = screen;
197                  idx = app.screens[screen]['activities'].indexOf(activity);
198                  if (idx > -1) { delete app.screens[screen]['activities'][idx]; }
199                  app.screens[screen]['activities'].unshift(activity);
200              }
201              // localStorage.setItem('optionalButtons', JSON.stringify(optionalButtons));
202           }
203       })
204       .catch(error => console.log('error', error));
205}
206
207function downloadCSV() {
208    const userID = localStorage.getItem('metaID');
209    const sc     = localStorage.getItem('sc');
210    const url = 'https://joymeter.uk/api/downloadCSV.php?userID='+userID+'&sc='+sc;
211    navigator.clipboard.writeText(url).then(function() {
212        document.getElementById('title').innerHTML = `<small>Your personal data link <a href='${url}'>${url}</a> has been copied to your clipboard</small>`;
213        }, function(err) {
214        document.getElementById('title').innerHTML = `<small>Your personal data link <a href='${url}'>${url}</a></small>`;
215    });
216    document.getElementById('server').setAttribute('src', 'api/downloadCSV.php?userID='+userID+'&sc='+sc);
217    app.moveTo('menu');
218}
219
220function deleteAct(key) {
221    let acts = JSON.parse(localStorage.getItem('acts'));
222    console.log('try to delete:',key);
223    const payload = {
224        actID:  acts[key].idActivities,
225        metaID: localStorage.getItem('metaID'),
226        sc:     localStorage.getItem('sc')
227    };
228    const requestOptions = {
229        method:  'POST',
230        headers: {"Content-Type":  "application/json"},
231        body:    JSON.stringify(payload)
232    };
233    fetch('api/deleteAct.php', requestOptions)
234        .then(response => response.json())
235        .then(result => {
236            if (result.message == 'success') {
237                console.log("Deleted from db: ",key);
238            }
239        })
240        .catch(error => console.log('error', error));
241}
242
243function updateContact(col,value) {
244    localStorage.setItem(col,value);
245    const payload = {
246              col:    col,
247              value:  value,
248              metaID: localStorage.getItem('metaID'),
249              sc:     localStorage.getItem('sc')
250              };
251    const requestOptions = {
252              method:  'POST',
253              headers: {"Content-Type":  "application/json"},
254              body:    JSON.stringify(payload)
255              };
256    fetch('api/updateContact.php', requestOptions)
257       .then(response => response.json())
258       .then(result => { 
259           if (result.message == 'success') { console.log("updated:", col); } 
260           else { console.log(result.message)};
261       })
262       .catch(error => console.log('error',JSON.stringify(error)));
263}
264
265function wipeData() {
266    localStorage.clear();
267    app.loadText();
268}
269
270function getLang() {
271    // languages is an array in order of preference
272    if (navigator.languages != undefined) { return navigator.languages[0]; }
273    return navigator.language;
274}
275function roundDate(dt) {
276    // date to the nearest 5 minutes
277    const res = 5*60*1000;
278    return new Date(Math.round(dt/res)*res);
279}
280
281function sliderInput(type) {
282    const sliderFloat = document.getElementById('slider-input').value;
283    const key = type+'_'+sliderFloat;
284    const act = app.activities[key];
285    const slider = document.getElementById('slider-input')
286        slider.className =`slider_${key.replace('.','_')} slider`;
287
288    const btn = document.getElementById('slider-btn')
289        btn.setAttribute('onclick', 'app.moveFromTo("'+key+'","home")');
290        btn.setAttribute('style', 'background-image: url("svg/'+key+'.svg")');
291        btn.className = `btn-${key.replace('.','_')} btn slider-btn`;
292    const btn2 = document.getElementById('slider-btn-OK')
293        btn2.setAttribute('onclick', 'app.moveFromTo("'+key+'","home")');
294    document.getElementById('slider-title').innerHTML = act.activity;
295}
296
297function getWeather(dt,hour) {
298    const key='06ab284e0c1f43069ab203534221001';
299    const postcode = localStorage.getItem('postcode').replace(' ','');
300    var url = `https://api.weatherapi.com/v1/history.json?key=${key}&q=${postcode}&dt=${dt}`;
301    const requestOptions = { method:  'GET', headers: {"Content-Type":  "application/json"} };
302    fetch(url, requestOptions)
303       .then(response => response.json())
304       .then(result => { 
305           var icon = result.forecast.forecastday[0].hour[hour].condition.icon;
306           var temp = result.forecast.forecastday[0].hour[hour].temp_c;
307           var wIcon = document.getElementById(`weather-${hour}`);
308           if (wIcon) { wIcon.src = `https:${icon}`; }
309           var tempSpan = document.getElementById(`temp-${hour}`);
310           if (tempSpan) { tempSpan.innerHTML = `<br>${temp}°C`; }
311        })
312}
313
314function onboard(postcode,eui) {
315    const payload = {
316              postcode: postcode,
317              eui:      eui,
318              email:    localStorage.getItem('userEmail'),
319              id:       localStorage.getItem('metaID')
320              };
321    const requestOptions = {
322              method:  'POST',
323              headers: {"Content-Type":  "application/json"},
324              body:    JSON.stringify(payload)
325              };
326    fetch('api/onboard.php', requestOptions)
327       .then(response => response.json())
328       .then(result => { 
329            console.log(result.message);
330            app.moveTo("user");
331            updateContact('postcode',postcode)
332            updateContact('eui',eui)
333            updateContact('DataType','joymeter')
334            document.getElementById('title').innerHTML = "Please contact <a href='mailto:[email protected]'>[email protected]</a> if you did not receive and email 'glowmarkt.com'.";
335            if (result.message['status'] == "unverified") {
336              document.getElementById('title').innerHTML = "Please check your email to confirm participation. Or ask for <a href='mailto:[email protected]'>[email protected]</a>.";
337              app.onboardedScreen();
338            }
339            localStorage.setItem('hasOnboarded',true)
340            updateContact('status',`onboard ${result.message}`)
341       })
342    // 26 Sep 22 Phil: removed this error handling
343    // it always triggered - possibly as timeout, rather than actual error.
344       //.catch(error => {
345       //    console.log('onboard.php error',JSON.stringify(error));
346       //    document.getElementById('title').innerHTML = "Unfortunately that didn't work. Please email <a href='mailto:[email protected]'>[email protected]</a> and we try to help.";
347       //    updateContact('status','onboard fail')
348       //})
349}
350
351function validateEUI() {
352    // called from onboarding
353    document.getElementById('eui-text').innerHTML = 'Checking your Smart Meter ID…';
354    document.getElementById('eui-button').style.display = 'none';
355    const eui      = document.getElementById('eui').value.toUpperCase().replace(/O/g,"0").replace(/I/g,"1");
356    const postcode = document.getElementById('postcode').value.toUpperCase();
357    const payload = {
358            eui: eui,
359            postcode: postcode
360        };
361    const requestOptions = {
362        method:  'POST',
363        redirect: 'follow',
364        headers: { "Content-Type":  "application/json", "applicationid": "3e3e5463-afbd-4f7a-b57f-365e886cf914"},
365        body:    JSON.stringify(payload)
366    };
367    fetch('https://apil.glowmarkt.com/api/v0-1/eligibility/checksmetsihd/postcode', requestOptions)
368        .then(response => response.json())
369        .then(result => {
370            if (result.valid) {
371              window.parent.postMessage('euiValidated#'+postcode+'#'+eui, '*');
372            } else {
373              document.getElementById('eui-text').innerHTML = 'Please check the code and postcode again. They are not case sensitive and 
373you can use spaces or dashes in the 16 digit code.'; 
374              document.getElementById('eui-text').style.color = 'red';
375              document.getElementById('eui-button').style.display = 'inline';
376            }
377        })
378        .catch(error => console.log('error', error));
379}
380
381window.addEventListener('message', function(e) {
382    var userEmail,userID,sc;
383    message = e.data;
384    console.log("Received message from iframe: " + message);
385    switch(message.split('#')[0]) {
386        case "changeEmail":
387            document.getElementById('server').setAttribute('src', 'register/login.php');
388            break;
389        case "validateEmail":
390            userEmail = message.split("#")[1];
391            localStorage.setItem('userEmail', userEmail);
392            document.getElementById('server').setAttribute('src', 'register/validateEmail.php?email='+userEmail);
393            break;
394        case "emailValidated":
395            localStorage.setItem('userEmail', message.split("#")[1]);
396            localStorage.setItem('metaID',    message.split("#")[2]);
397            localStorage.setItem('sc',        message.split("#")[3]);
398            localStorage.setItem('acts',      JSON.stringify({}));
399            updateContact('consent', new Date());
400            // app.activities.Logout.icon = 'user_green';
401            // document.getElementById('navbar').style.display  = 'none';
402            downloadActs();
403            app.moveTo("menu");
404            break;
405        case "guestUser":
406            localStorage.setItem('userEmail', '');
407            localStorage.setItem('metaID',    '0');
408            localStorage.setItem('sc',        'br5od02li29a6');
409            localStorage.setItem('acts',      JSON.stringify({}));
410            app.moveTo("menu");
411            break;
412        case "euiValidated":
413            document.getElementById('eui-text').innerHTML = 'Smart Meter ID is valid. Onboarding…'; 
414            postcode = message.split("#")[1];
415            eui      = message.split("#")[2];
416            onboard(postcode,eui);
417            break;
418        case "return":
419            // fired by about.html to avoid nesting
420            app.loadText();
421            break;
422        case "menu":
423            app.moveTo("menu");
424            break;
425        case "NewHH":
426            const address = JSON.parse(message.split("#")[1]);
427            localStorage.setItem('register', 'HHQ');
428            break;
429        case "HH":
430            const hhPage = message.split("#")[1];
431            localStorage.setItem('hhPage', hhPage);
432            if (hhPage == "Done") {
433                app.moveTo("menu");
434                localStorage.setItem('register', 'HHQ_done');
435            }
436            break;
437    }
438});

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.