mirror of
https://github.com/letscontrolit/ESPEasy.git
synced 2026-07-27 19:57:38 +00:00
[LOG] autoscroll fix, code reduction
- Fixes a long-existing autoscroll issue where the whole site would scroll instead of just the log content. - reducing the code by simplifying the „browser check" and refining the loop
This commit is contained in:
@@ -406,68 +406,61 @@ static const char DATA_UPDATE_SENSOR_VALUES_DEVICE_PAGE_JS[] PROGMEM = {
|
||||
#ifdef WEBSERVER_INCLUDE_JS
|
||||
static const char DATA_FETCH_AND_PARSE_LOG_JS[] PROGMEM = {
|
||||
"function elId(e){return document.getElementById(e)}"
|
||||
"function getBrowser(){var e,t=navigator.userAgent,o=t.match(/(opera|chrome|safari|firefox|msie|trident(?=\\/))\\/?\\s*(\\d+)/i)||[];"
|
||||
"return/trident/i.test(o[1])?{name:'IE',version:(e=/\\brv[ :]+(\\d+)/g.exec(t)||[])[1]||''}:"
|
||||
"'Chrome'===o[1]&&null!=(e=t.match(/\\bOPR|Edge\\/(\\d+)/))?"
|
||||
"{name:'Opera',version:e[1]}:"
|
||||
"(o=o[2]?[o[1],o[2]]:[navigator.appName,navigator.appVersion,'-?'],"
|
||||
"null!=(e=t.match(/version\\/(\\d+)/i))&&o.splice(1,1,e[1]),{name:o[0],version:o[1]})}"
|
||||
"var browser=getBrowser(),currentBrowser=browser.name+browser.version;"
|
||||
"textToDisplay=(browser.name=browser.version<12)?"
|
||||
"'Error: '+currentBrowser+' is not supported! Please try a modern web browser.':"
|
||||
"'Fetching log entries...';"
|
||||
"elId('copyText_1').innerHTML=textToDisplay;"
|
||||
"loopDeLoop(1000,0);"
|
||||
"var logLevel=['Unused','Error','Info','Debug','Debug More','Undefined','Undefined','Undefined','Undefined','Debug Dev'];"
|
||||
"function loopDeLoop(e,t){let o='copyText_1';"
|
||||
"isNaN(t)&&(t=1),null==e&&(e=1000),scrolling_type=e<=500?'auto':'smooth';"
|
||||
"var r,n,i='',l=0,s=setInterval(function(){"
|
||||
"if(l>0){clearInterval(s);return}"
|
||||
"++t>1?l=1:fetch('/logjson').then(function(t){"
|
||||
"if(200!==t.status){console.log('Looks like there was a problem. Status Code: '+t.status);return}"
|
||||
"t.json().then(function(t){var l;"
|
||||
"for(null==n&&(n=''),r=0;r<t.Log.nrEntries;++r)"
|
||||
"try{l=t.Log.Entries[r].timestamp}"
|
||||
"catch(a){l=a.name}"
|
||||
"finally{'TypeError'!==l&&(i=t.Log.Entries[r].timestamp,"
|
||||
"n+='<div class=level_'+t.Log.Entries[r].level+' id='+i+'><font color=\\'gray\\'>'+t.Log.Entries[r].timestamp+':</font> '+"
|
||||
"t.Log.Entries[r].text+'</div>')}"
|
||||
"e=t.Log.TTL,"
|
||||
"''!==n&&('Fetching log entries...'==elId(o).innerHTML&&(elId(o).innerHTML=''),"
|
||||
"elId(o).innerHTML+=n),"
|
||||
"n='';"
|
||||
"!0==(autoscroll_on=elId('autoscroll').checked)&&''!==i&&elId(i).scrollIntoView({behavior:scrolling_type});"
|
||||
"document.getElementById('logfilter')||(document.querySelector('section').innerHTML+="
|
||||
"'<label>Filter: <input id=\"logfilter\" size=\"35\"></label>');"
|
||||
"const ct1=elId('copyText_1');"
|
||||
"window.fetch?ct1.textContent='Fetching log entries...':"
|
||||
"ct1.textContent='Error: This browser is not supported. Please use a modern browser.';"
|
||||
"const logLevel={0:'Unused',1:'Error',2:'Info',3:'Debug',4:'Debug More',9:'Debug Dev'};"
|
||||
"function loopDeLoop(e=1000){setTimeout(function(){fetch('/logjson')"
|
||||
".then(e=>{if(!e.ok)throw Error(e.status);return e.json()})"
|
||||
".then(t=>{let o='';"
|
||||
"for(let l=0;l<t.Log.nrEntries;l++){let i=t.Log.Entries[l];"
|
||||
"i&&i.timestamp&&(o+=`<div class=level_${i.level}>"
|
||||
"<font color='gray'>${i.timestamp}:</font> ${i.text}</div>`)}"
|
||||
"e=t.Log.TTL||e;"
|
||||
"o&&(ct1.textContent==='Fetching log entries...'&&(ct1.innerHTML=''),ct1.innerHTML+=o);"
|
||||
"applyLogFilter();"
|
||||
"elId('current_loglevel').innerHTML='Logging: '+logLevel[t.Log.SettingsWebLogLevel]+' ('+t.Log.SettingsWebLogLevel+')';"
|
||||
"clearInterval(s);loopDeLoop(e,0)"
|
||||
"})}).catch(function(t){"
|
||||
"elId(o).innerHTML+='<div>>> '+t.message+' <<</div>';"
|
||||
"autoscroll_on=elId('autoscroll').checked;"
|
||||
"elId(o).scrollTop=elId(o).scrollHeight;"
|
||||
"e=5000;clearInterval(s);loopDeLoop(e,0)"
|
||||
"}),l=1},e)}"
|
||||
"function applyLogFilter(){let e=elId('logfilter').value.split(';').map(e=>e.trim()).filter(Boolean),"
|
||||
"elId('autoscroll')?.checked&&ct1.scrollTo({top:ct1.scrollHeight,behavior:e<=500?'auto':'smooth'});"
|
||||
"let n=t.Log.SettingsWebLogLevel,r=logLevel[n]??'Undefined';"
|
||||
"elId('current_loglevel').textContent=`Logging: ${r} (${n})`;"
|
||||
"loopDeLoop(e)})"
|
||||
".catch(e=>{ct1.innerHTML+=`<div>>> ${e.message} <<</div>`;"
|
||||
"ct1.scrollTop=ct1.scrollHeight;loopDeLoop(5000)})},e)}"
|
||||
"function applyLogFilter(){"
|
||||
"let e=elId('logfilter').value.split(';').map(e=>e.trim()).filter(Boolean),"
|
||||
"t=document.querySelectorAll('#copyText_1 > div'),"
|
||||
"o=e.some(e=>!e.startsWith('!'));"
|
||||
"for(let r of t){r.dataset.originalHtml||(r.dataset.originalHtml=r.innerHTML);"
|
||||
"let n=r.dataset.originalHtml,i=r.textContent.toLowerCase(),l=[],s=!1,a=!o;"
|
||||
"for(let d of e){"
|
||||
"if(d.startsWith('!')){let c=d.slice(1);"
|
||||
"if(!c.includes('&')||c.startsWith('&')||c.endsWith('&')){"
|
||||
"if(c&&i.includes(c.toLowerCase())){s=!0;break}}else{"
|
||||
"let g=c.split('&').map(e=>e.trim()).filter(Boolean),f=-1,u=!0;"
|
||||
"for(let p of g){let L=i.indexOf(p.toLowerCase(),f+1);if(-1===L){u=!1;break}f=L}if(u){s=!0;break}}continue}"
|
||||
"if(d.includes('&')&&!d.startsWith('&')&&!d.endsWith('&')){"
|
||||
"let h=d.split('&').map(e=>e.trim()).filter(Boolean);"
|
||||
"if(h.length>=2){let m=-1,$=!0;for(let _ of h){let b=i.indexOf(_.toLowerCase(),m+1);if(-1===b){$=!1;break}m=b}if($){l.push(...h),a=!0;break}}continue}"
|
||||
"if(i.includes(d.toLowerCase())){l.push(d),a=!0;break}}"
|
||||
"if(s||!a){r.style.display='none';continue}r.style.display='';r.innerHTML=highlightOutsideTags(n,l)}}"
|
||||
"for(let l of t){"
|
||||
"l.dataset.originalHtml||(l.dataset.originalHtml=l.innerHTML);"
|
||||
"let i=l.dataset.originalHtml,n=l.textContent.toLowerCase(),r=[],s=!1,a=!o;"
|
||||
"for(let c of e){"
|
||||
"if(c.startsWith('!')){let g=c.slice(1);"
|
||||
"if(!g.includes('&')||g.startsWith('&')||g.endsWith('&')){"
|
||||
"if(g&&n.includes(g.toLowerCase())){s=!0;break}}"
|
||||
"else{let f=g.split('&').map(e=>e.trim()).filter(Boolean),u=-1,d=!0;"
|
||||
"for(let p of f){let h=n.indexOf(p.toLowerCase(),u+1);if(h===-1){d=!1;break}u=h}"
|
||||
"if(d){s=!0;break}}continue}"
|
||||
"if(c.includes('&')&&!c.startsWith('&')&&!c.endsWith('&')){"
|
||||
"let L=c.split('&').map(e=>e.trim()).filter(Boolean);"
|
||||
"if(L.length>=2){let _=-1,$=!0;"
|
||||
"for(let b of L){let m=n.indexOf(b.toLowerCase(),_+1);if(m===-1){$=!1;break}_=m}"
|
||||
"if($){r.push(...L),a=!0;break}}continue}"
|
||||
"if(n.includes(c.toLowerCase())){r.push(c),a=!0;break}}"
|
||||
"if(s||!a){l.style.display='none';continue}"
|
||||
"l.style.display='';l.innerHTML=highlightOutsideTags(i,r)}}"
|
||||
"function highlightOutsideTags(e,t){if(!t.length)return e;"
|
||||
"let o='',r=!1,n=0;"
|
||||
"for(;n<e.length;){let i=e[n];"
|
||||
"if('<'===i&&(r=!0),'>'===i){r=!1;o+=i;n++;continue}"
|
||||
"if(!r){let l=!1;for(let s of t){let a=e.slice(n,n+s.length);"
|
||||
"if(a.toLowerCase()===s.toLowerCase()){o+=`<span style='background-color: #bb9300;color: black;'>${a}</span>`;n+=s.length;l=!0;break}}if(l)continue}o+=i;n++}return o}"
|
||||
"let o='',l=!1,i=0;"
|
||||
"for(;i<e.length;){let n=e[i];"
|
||||
"if('<'===n&&(l=!0),'>'===n){l=!1;o+=n;i++;continue}"
|
||||
"if(!l){let r=!1;"
|
||||
"for(let s of t){let a=e.slice(i,i+s.length);"
|
||||
"if(a.toLowerCase()===s.toLowerCase()){"
|
||||
"o+=`<span style='background-color: #bb9300;color: black;'>${a}</span>`;"
|
||||
"i+=s.length;r=!0;break}}"
|
||||
"if(r)continue}"
|
||||
"o+=n;i++}return o}"
|
||||
"loopDeLoop(1000);"
|
||||
"const input=document.getElementById('logfilter');"
|
||||
"input&&(input.placeholder='\"!\"=exclude \";\"=or \"&\"=and (e.g. !act)');"
|
||||
};
|
||||
|
||||
+73
-118
@@ -1,132 +1,87 @@
|
||||
//---------------no need to be included into WebStaticData.h---------------------------------------------
|
||||
// if no filter input exists, create it
|
||||
document.getElementById("logfilter") ||
|
||||
(document.querySelector("section").innerHTML +=
|
||||
'<label>Filter: <input id="logfilter" size="35"></label>');
|
||||
(document.querySelector("section").innerHTML +=
|
||||
'<label>Filter: <input id="logfilter" size="35"></label>');
|
||||
//------------------------------------------------------------
|
||||
function elId(e) {
|
||||
return document.getElementById(e);
|
||||
}
|
||||
function getBrowser() {
|
||||
var ua = navigator.userAgent,
|
||||
tem, M = ua.match(/(opera|chrome|safari|firefox|msie|trident(?=\/))\/?\s*(\d+)/i) || [];
|
||||
if (/trident/i.test(M[1])) {
|
||||
tem = /\brv[ :]+(\d+)/g.exec(ua) || [];
|
||||
return {
|
||||
name: 'IE',
|
||||
version: (tem[1] || '')
|
||||
};
|
||||
}
|
||||
if (M[1] === 'Chrome') {
|
||||
tem = ua.match(/\bOPR|Edge\/(\d+)/);
|
||||
if (tem != null) {
|
||||
return {
|
||||
name: 'Opera',
|
||||
version: tem[1]
|
||||
};
|
||||
}
|
||||
}
|
||||
M = M[2] ? [M[1], M[2]] : [navigator.appName, navigator.appVersion, '-?'];
|
||||
if ((tem = ua.match(/version\/(\d+)/i)) != null) {
|
||||
M.splice(1, 1, tem[1]);
|
||||
}
|
||||
return {
|
||||
name: M[0],
|
||||
version: M[1]
|
||||
};
|
||||
}
|
||||
var browser = getBrowser();
|
||||
var currentBrowser = browser.name + browser.version;
|
||||
if (browser.name = 'IE' && browser.version < 12) {
|
||||
textToDisplay = 'Error: ' + currentBrowser + ' is not supported! Please try a modern web browser.'
|
||||
} else {
|
||||
textToDisplay = 'Fetching log entries...';
|
||||
}
|
||||
elId('copyText_1').innerHTML = textToDisplay;
|
||||
loopDeLoop(1000, 0);
|
||||
var logLevel = new Array('Unused', 'Error', 'Info', 'Debug', 'Debug More', 'Undefined', 'Undefined', 'Undefined', 'Undefined', 'Debug Dev');
|
||||
|
||||
function loopDeLoop(timeForNext, activeRequests) {
|
||||
var maximumRequests = 1;
|
||||
const ct1 = elId('copyText_1');
|
||||
|
||||
if (!window.fetch) {
|
||||
ct1.textContent = 'Error: This browser is not supported. Please use a modern browser.';
|
||||
} else {
|
||||
ct1.textContent = 'Fetching log entries...';
|
||||
}
|
||||
|
||||
const logLevel = {
|
||||
0: 'Unused',
|
||||
1: 'Error',
|
||||
2: 'Info',
|
||||
3: 'Debug',
|
||||
4: 'Debug More',
|
||||
9: 'Debug Dev'
|
||||
};
|
||||
|
||||
loopDeLoop(1000);
|
||||
|
||||
function loopDeLoop(timeForNext = 1000) {
|
||||
const url = '/logjson';
|
||||
const ct1 = 'copyText_1';
|
||||
if (isNaN(activeRequests)) {
|
||||
activeRequests = maximumRequests;
|
||||
}
|
||||
if (timeForNext == null) {
|
||||
timeForNext = 1000;
|
||||
}
|
||||
if (timeForNext <= 500) {
|
||||
scrolling_type = 'auto';
|
||||
} else {
|
||||
scrolling_type = 'smooth';
|
||||
}
|
||||
var c;
|
||||
var logEntriesChunk;
|
||||
var currentIDtoScrollTo = '';
|
||||
var check = 0;
|
||||
var i = setInterval(function() {
|
||||
if (check > 0) {
|
||||
clearInterval(i);
|
||||
return;
|
||||
}
|
||||
++activeRequests;
|
||||
if (activeRequests > maximumRequests) {
|
||||
check = 1;
|
||||
} else {
|
||||
fetch(url).then(function(response) {
|
||||
if (response.status !== 200) {
|
||||
console.log('Looks like there was a problem. Status Code: ' + response.status);
|
||||
return;
|
||||
|
||||
setTimeout(function () {
|
||||
fetch(url)
|
||||
.then(response => {
|
||||
if (!response.ok) {
|
||||
throw new Error(response.status);
|
||||
}
|
||||
response.json().then(function(data) {
|
||||
var logEntry;
|
||||
if (logEntriesChunk == null) {
|
||||
logEntriesChunk = '';
|
||||
}
|
||||
for (c = 0; c < data.Log.nrEntries; ++c) {
|
||||
try {
|
||||
logEntry = data.Log.Entries[c].timestamp;
|
||||
} catch (err) {
|
||||
logEntry = err.name;
|
||||
} finally {
|
||||
if (logEntry !== "TypeError") {
|
||||
currentIDtoScrollTo = data.Log.Entries[c].timestamp;
|
||||
logEntriesChunk += '<div class=level_' + data.Log.Entries[c].level + ' id=' + currentIDtoScrollTo + '><font color="gray">' + data.Log.Entries[c].timestamp + ':</font> ' + data.Log.Entries[c].text + '</div>';
|
||||
}
|
||||
}
|
||||
}
|
||||
timeForNext = data.Log.TTL;
|
||||
if (logEntriesChunk !== '') {
|
||||
if (elId(ct1).innerHTML == 'Fetching log entries...') {
|
||||
elId(ct1).innerHTML = '';
|
||||
}
|
||||
elId(ct1).innerHTML += logEntriesChunk;
|
||||
}
|
||||
logEntriesChunk = '';
|
||||
autoscroll_on = elId('autoscroll').checked;
|
||||
if (autoscroll_on == true && currentIDtoScrollTo !== '') {
|
||||
elId(currentIDtoScrollTo).scrollIntoView({
|
||||
behavior: scrolling_type
|
||||
});
|
||||
}
|
||||
applyLogFilter();
|
||||
elId('current_loglevel').innerHTML = 'Logging: ' + logLevel[data.Log.SettingsWebLogLevel] + ' (' + data.Log.SettingsWebLogLevel + ')';
|
||||
clearInterval(i);
|
||||
loopDeLoop(timeForNext, 0);
|
||||
return;
|
||||
})
|
||||
}).catch(function(err) {
|
||||
elId(ct1).innerHTML += '<div>>> ' + err.message + ' <<</div>';
|
||||
autoscroll_on = elId('autoscroll').checked;
|
||||
elId(ct1).scrollTop = elId(ct1).scrollHeight;
|
||||
timeForNext = 5000;
|
||||
clearInterval(i);
|
||||
loopDeLoop(timeForNext, 0);
|
||||
return;
|
||||
return response.json();
|
||||
})
|
||||
};
|
||||
check = 1;
|
||||
.then(data => {
|
||||
let logEntriesChunk = '';
|
||||
|
||||
for (let c = 0; c < data.Log.nrEntries; c++) {
|
||||
const entry = data.Log.Entries[c];
|
||||
if (!entry || !entry.timestamp) continue;
|
||||
|
||||
logEntriesChunk +=
|
||||
`<div class="level_${entry.level}">
|
||||
<font color="gray">${entry.timestamp}:</font> ${entry.text}
|
||||
</div>`;
|
||||
}
|
||||
|
||||
timeForNext = data.Log.TTL || timeForNext;
|
||||
|
||||
if (logEntriesChunk) {
|
||||
if (ct1.textContent === 'Fetching log entries...') {
|
||||
ct1.innerHTML = '';
|
||||
}
|
||||
ct1.innerHTML += logEntriesChunk;
|
||||
}
|
||||
|
||||
applyLogFilter();
|
||||
|
||||
if (elId('autoscroll')?.checked) {
|
||||
ct1.scrollTo({
|
||||
top: ct1.scrollHeight,
|
||||
behavior: timeForNext <= 500 ? 'auto' : 'smooth'
|
||||
});
|
||||
}
|
||||
|
||||
const level = data.Log.SettingsWebLogLevel;
|
||||
const levelName = logLevel[level] ?? 'Undefined';
|
||||
|
||||
elId('current_loglevel').textContent =
|
||||
`Logging: ${levelName} (${level})`;
|
||||
|
||||
loopDeLoop(timeForNext);
|
||||
})
|
||||
.catch(err => {
|
||||
ct1.innerHTML += `<div>>> ${err.message} <<</div>`;
|
||||
ct1.scrollTop = ct1.scrollHeight;
|
||||
loopDeLoop(5000);
|
||||
});
|
||||
}, timeForNext);
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user