Das könnte nützlich sein, wenn der Link „x neue oder aktualisierte Themen anzeigen" unterhalb der Kopfzeile fixiert (sticky) wäre, sodass man ihn beim Durchscrollen der Themenliste sofort sieht. Beim Klicken auf die Leiste springt die Ansicht nach oben, um die neuen oder aktualisierten Themen zu laden.
Der sticky-Teil funktioniert hervorragend mit diesem Code
Der andere Teil (JavaScript) soll eine Klickfunktion sein, die zur Spitze springt oder nach oben scrollt, aber ich weiß nicht, wie das geht oder was der beste Weg dafür ist.
Ich habe diesen Abschnitt in den Templates discovery/topics.hbs und discovery/categories.hbs gefunden. Wenn man das <a href in <a href="/"> ändert, könnte das funktionieren (ich bin mir nicht sicher, ich habe es nicht ausprobiert), aber dann würde bei jedem Klick so geladen werden, als würde man auf das Logo klicken.
Ja, das Hinzufügen einer URL führt zu einer Navigation, da es keine Logik gibt, die das Ereignis abfängt.
Der Link ruft eine Ember-Aktion auf. Alle Aktionen in Discourse sind erweiterbar. Sie wirken also gewissermaßen wie Anpassungshooks. Wie modifiziert man also eine Aktion? Nun, schauen wir uns zunächst an, was sie tut.
Suche auf GitHub oder lokal nach dem Namen der Aktion. Aktionen werden immer in JS-Dateien definiert und in Handlebars referenziert. Wir wollen die Definition sehen, also beschränken wir die Suche auf JS-Dateien.
Wir wissen bereits, welche Klasse wir ändern möchten. Es ist discovery/topics. Wir müssen wissen, um welche Art von Klasse es sich handelt. Prüfen wir also das Verzeichnis.
discourse/app/controllers/discovery/topics.js
Es ist ein Controller.
Wir wissen auch, dass wir die showInserted-Aktion in dieser Klasse ändern möchten. Also beginnen wir damit.
api.modifyClass("controller:discovery/topics", {
pluginId: 'sticky-new-topics-banner',
actions: {
showInserted() {
// lass uns etwas arbeiten
}
}
});
Anschließend kannst du beliebigen Code hinzufügen, um das Fenster zu scrollen, wenn der Benutzer auf das Banner „neue Themen" klickt. Ich habe mich für etwas wie das hier entschieden.
Sind wir also fertig? Nein. Das bricht Discourse, weil du die Aktion vollständig überschreibst. Beim Klicken auf den Link wird nun zum list-controls-Element gescrollt, aber die neuen Themen werden nicht geladen. Warum? Weil der Code im Kern nicht mehr ausgeführt wird. Ich meine, dieser Teil hier
Wie behebt man das also? Mit dieser einfachen Zeile
this._super(...arguments);
Du musst keinen Code aus dem Kern kopieren, wenn du ihn nur erweitern möchtest. Erledige deine Arbeit und füge dann diese Zeile hinzu. Alles, was sie bewirkt, ist, dass der Code aus dem Kern angewendet wird.
Wenn du dies testest, wirst du sehen, dass fast alles gut funktioniert, außer … der Header überlappt mit list-controls. Warum? Weil der Header auf „sticky" gesetzt ist.
Du kannst dies auf verschiedene Arten in JS beheben – die Höhe berechnen, den Offset ermitteln, einen Helfer aus Discourse importieren usw. Ich werde darauf nicht näher eingehen.
Der einfachste Weg ist CSS mit scroll-margin-top, über das du hier mehr lesen kannst.
Auf Deutsch: Wenn auf den Link geklickt wird, zum oberen Rand von list-controls scrollen – 2 * die Headerhöhe, damit keine Überlappung entsteht und etwas Platz darunter bleibt.
#list-area {
// Mobile hat ein anderes Layout
.alert-info,
.show-more.has-topics {
position: sticky;
// Safari ist manchmal ohne das Präfix pingelig
position: -webkit-sticky;
top: var(--header-offset);
// Banner sollte über dem Inhalt liegen
z-index: z("header");
}
}
.list-controls {
scroll-margin-top: calc(var(--header-offset) * 2);
}
Vielen Dank, @Johani! Das war mir sehr hilfreich, und ich glaube, ich habe endlich viele Dinge verstanden. Deine detaillierten Antworten gefallen mir wirklich gut, denn man kann viel daraus lernen – wie Dinge funktionieren und natürlich, dass sie perfekt funktionieren. Nochmals vielen Dank!