Das Folgende tut, was du brauchst (ich habe mein Bestes gegeben, mit vielen Google-Suchen auf dem Weg):
// kein jQuery oder anderer Wahnsinn. Einfach
// geradlinige Vanilla-JavaScript-Funktionen
// um den Inhalt eines divs zum unteren Rand zu scrollen
// wenn der Benutzer nicht nach oben gescrollt hat. Inklusive
// eines anklickbaren "Alerts", wenn sich der "Inhalt" ändert.
// dies sollte für jede Art von Inhalt funktionieren
// sei es Bilder, Links oder einfacher Text
// füge einfach das neue Element an
// das div an, und der Rest wird wie beschrieben behandelt.
let scrolled = false; // am Boden?
let scrolling = false; // im nächsten Nachrichten-Scrollen?
let listener = false; // hat das Element einen Content-Changed-Listener?
let contentChanged = false; // ziemlich offensichtlich
let alerted = false; // weniger offensichtlich
function innerHTMLChanged() {
// das ist hier für den Fall, dass wir
// anpassen möchten, was hier passiert.
// für jetzt nur:
contentChanged = true;
}
function scrollToBottom(id) {
if (!id) { id = "scrollable_element"; }
let DEBUG = 0; // auf 1 ändern und Konsole öffnen
let dstr = "";
let e = document.getElementById(id);
if (e) {
if (!listener) {
dstr += "content changed listener not active\n";
e.addEventListener("DOMSubtreeModified", innerHTMLChanged);
listener = true;
} else {
dstr += "content changed listener active\n";
}
let height = (e.scrollHeight - e.offsetHeight); // das ist nicht perfekt
let offset = (e.offsetHeight - e.clientHeight); // und behebt dies das? scheint so...
let scrollMax = height + offset;
dstr += "offsetHeight: " + e.offsetHeight + "\n";
dstr += "clientHeight: " + e.clientHeight + "\n";
dstr += "scrollHeight: " + e.scrollHeight + "\n";
dstr += "scrollTop: " + e.scrollTop + "\n";
dstr += "scrollMax: " + scrollMax + "\n";
dstr += "offset: " + offset + "\n";
dstr += "height: " + height + "\n";
dstr += "contentChanged: " + contentChanged + "\n";
if (!scrolled && !scrolling) {
dstr += "Benutzer hat nicht gescrollt\n";
if (e.scrollTop != scrollMax) {
dstr += "Scrollen nicht am Ende\n";
e.scroll({
top: scrollMax,
left: 0,
behavior: "auto"
})
e.scrollTop = scrollMax;
scrolling = true;
} else {
if (alerted) {
dstr += "Alarm existiert\n";
} else {
dstr += "Alarm existiert nicht\n";
}
if (contentChanged) { contentChanged = false; }
}
} else {
dstr += "Benutzer hat sich vom Ende entfernt gescrollt\n";
if (!scrolling) {
dstr += "nicht automatisch scrollen\n";
if (e.scrollTop >= scrollMax) {
dstr += "Scrollen am Ende\n";
scrolled = false;
if (alerted) {
dstr += "Alarm existiert\n";
let n = document.getElementById("alert");
n.remove();
alerted = false;
contentChanged = false;
scrolled = false;
}
} else {
dstr += "Scrollen nicht am Ende\n";
if (contentChanged) {
dstr += "Inhalt geändert\n";
if (!alerted) {
dstr += "Alarm wird nicht angezeigt\n";
let n = document.createElement("div");
e.append(n);
n.id = "alarm";
n.style.position = "absolute";
n.classList.add("normal-panel");
n.classList.add("klickbar");
n.classList.add("blinkend");
n.innerHTML = "neuer Inhalt!";
let nposy = parseFloat(getComputedStyle(e).height) + 18;
let nposx = 18 + (parseFloat(getComputedStyle(e).width) / 2) - (parseFloat(getComputedStyle(n).width) / 2);
dstr += "nposx: " + nposx + "\n";
dstr += "nposy: " + nposy + "\n";
n.style.left = nposx;
n.style.top = nposy;
n.addEventListener("click", () => {
dstr += "Alarm löschen\n";
scrolled = false;
alerted = false;
contentChanged = false;
n.remove();
});
alerted = true;
} else {
dstr += "Alarm bereits angezeigt\n";
}
} else {
alerted = false;
}
}
} else {
dstr += "automatisches Scrollen\n";
if (e.scrollTop >= scrollMax) {
dstr += "Scrollen beendet";
scrolling = false;
scrolled = false;
} else {
dstr += "immer noch am Scrollen...\n";
}
}
}
}
if (DEBUG && dstr) console.log("stb:\n" + dstr);
setTimeout(() => { scrollToBottom(id); }, 50);
}
function scrollMessages(id) {
if (!id) { id = "scrollable_element"; }
let DEBUG = 1;
let dstr = "";
if (scrolled) {
dstr += "bereits gescrollt";
} else {
dstr += "gescrollt";
scrolled = true;
}
dstr += "\n";
if (contentChanged && alerted) {
dstr += "Inhalt geändert, und Alarm ausgelöst\n";
let n = document.getElementById("alert");
if (n) {
dstr += "Alarm-Div existiert\n";
let e = document.getElementById(id);
let nposy = parseFloat(getComputedStyle(e).height) + 18;
dstr += "nposy: " + nposy + "\n";
n.style.top = nposy;
} else {
dstr += "Alarm-Div existiert nicht!\n";
}
} else {
dstr += "Inhalt NICHT geändert, und kein Alarm ausgelöst";
}
if (DEBUG && dstr) console.log("sm: " + dstr);
}
setTimeout(() => { scrollToBottom("messages"); }, 1000);
/////////////////////
// HILFSFUNKTION
// simuliert das Hinzufügen von dynamischem Inhalt zum "chat" div
let count = 0;
function addContent() {
let e = document.getElementById("messages");
if (e) {
let br = document.createElement("br");
e.append("test " + count);
e.append(br);
count++;
}
}
button {
border-radius: 5px;
}
#container {
padding: 5px;
}
#messages {
background-color: blue;
border: 1px inset black;
border-radius: 3px;
color: white;
padding: 5px;
overflow-x: none;
overflow-y: auto;
max-height: 100px;
width: 100px;
margin-bottom: 5px;
text-align: left;
}
.bordered {
border: 1px solid black;
border-radius: 5px;
}
.inline-block {
display: inline-block;
}
.centered {
text-align: center;
}
.normal-panel {
background-color: #888888;
border: 1px solid black;
border-radius: 5px;
padding: 2px;
}
.klickbar {
cursor: pointer;
}
test
test
test
test
test
test
test
test
test
test
Inhalt hinzufügen
Hinweis: Möglicherweise müssen Sie die Position des Alerts (nposx
und nposy
) in den Funktionen scrollToBottom
und scrollMessages
an Ihre Bedürfnisse anpassen...