Javascript auslösen, wenn auf einen beliebigen Seitenlink geklickt wird, aber bevor der Seiteninhalt geladen wird

Hi.
When we change page in Discourse, these are the apparent steps:

  1. We click on the link
  2. The current content disappears and the loader appears
  3. The URL is updated and the new content appears

This is slightly different when we go from a page to the home, as the URL is changed to the home URL when the current content disappears, and not when the new content appears.

My goal is to have a script that is executed as soon as we click any page link on Discourse.
api.onPageChange won’t fit in this case since the code is executed quite at the same time the new page content is loaded.

Is there a Discourse method for that? I look at the event triggers but didn’t find any one corresponding to what I need.

1 „Gefällt mir“

Hey :wave:

There’s currently no method in the Plugin-API that will allow you to fire a script before a page transition because this has not come up before as far as I recall.

That said, you can leverage on the willTransition() action in the application route

You would use something that like this in your theme / component

// this fires after the transition
api.onPageChange((url, title) => {
  console.log("after transition");
});

// this fires right before the transition
api.modifyClass("route:application", {
  pluginId: "some-name",
  actions: {
    willTransition() {
      // run core code first
      this._super(...arguments);
      // then do some work
      console.log("before transition");
      // you can also do something like this to see what data you have
      // to work with like _router
      console.log(this)
    }
  }
});

6 „Gefällt mir“

Exactly what I needed. Thanks!

2 „Gefällt mir“

Dies scheint beim Betreten eines Themas aus einer Themenliste nicht ausgelöst zu werden?

Ich habe auch versucht, eines hinzuzufügen:

      api.modifyClass("route:topic", {
        pluginId: PLUGIN_ID,
        actions: {
          willTransition() {

Aber das wird auch nicht ausgelöst.

Ein paar Gründe, warum das möglicherweise nicht funktioniert:

  1. Aktionen in einem Hash zu platzieren, ist eine alte Syntax, die wir in Discourse nicht mehr verwenden. Theoretisch sollte es funktionieren, aber die Interoperabilität mit der neuen Syntax ist möglicherweise nicht perfekt. Der moderne Weg wäre

    api.modifyClass("route:application", (Superclass) => class extends Superclass {
      @action
      willTransition() {
        console.log("etwas tun");
        super.willTransition(...arguments);
      }
    });
    

    Der übliche Haftungsausschluss für modifyClass gilt: Dies ist riskant und kann jederzeit fehlschlagen.

  2. Ich glaube nicht, dass willTransition in allen Situationen auf der Anwendungsroute garantiert ausgelöst wird. (z. B. wenn eine untergeordnete Route eine willTransition-Aktion hat, wird sie nicht unbedingt nach oben weitergegeben.)

Ich würde empfehlen, stattdessen die Ereignisse im Ember Router Service zu verwenden: RouterService | 5.12.0 | Ember API Documentation
z. B. etwas wie

const router = api.container.lookup("service:router");
router.on("routeWillChange", () => {
  console.log("route will change ausgelöst");
});
2 „Gefällt mir“

Schön, danke David, das werde ich als Nächstes versuchen!

Diese Untersuchung wurde (hüstel) ausgelöst, weil ich eine Möglichkeit brauchte, etwas bei jeder Seitenänderung auszulösen, und zwar vor dem Rendern.

Das Page Change API-Ereignis scheint anscheinend nicht garantiert vor dem Rendern von Seitenelementen ausgelöst zu werden.

1 „Gefällt mir“

Ich denke, es wird schwierig sein, dies perfekt zu machen. Ember erwartet, die volle Kontrolle über das Rendern zu haben, daher wird es schwierig sein, an beliebigen Punkten anzuhaken, und kann Probleme verursachen (abhängig davon, was Sie zu tun versuchen).

Offensichtlich weiß ich nicht, was Ihr Endziel ist … also ist der Aufwand vielleicht gerechtfertigt. In diesem Fall können Sie mich gerne ignorieren :wink:

(Wenn Sie natürlich ein #dev-Thema zu dem Problem eröffnen möchten, das Sie lösen möchten, werde ich es mir gerne ansehen)

Gerne, ich bin explizit, da der Code Open Source ist:

Ich arbeite mit einem Drittanbieter-Werbeanbieter zusammen, und dieser hat eine Funktion zum Zurücksetzen der Werbeseite in JavaScript, die ausgeführt werden muss, bevor die Anzeigen der neuen Seite ausgelöst werden.

Jede Verbesserung ist willkommen, und ich habe dies bereits im Topic List mit Johani’s Code umgesetzt. (in einem offenen PR).

Aber das hat das Topic … Ich werde Ihren Vorschlag als nächstes ausprobieren und ihn in beiden Fällen übernehmen, wenn dies die Dinge weiter verbessert.

Ah, ich verstehe, Sie modifizieren also nicht direkt das DOM :ok_hand:

In diesem Fall hoffe ich, dass routeWillChange funktionieren wird – es sollte sicherlich ausgelöst werden, bevor die nächste Route gerendert wird.

Der Vorbehalt ist, dass… im Falle von Dingen wie Weiterleitungen, es möglicherweise zweimal ausgelöst wird. Oder ausgelöst wird und dann der Übergang abgebrochen wird. Aber vielleicht ist das in diesem Fall in Ordnung.

2 „Gefällt mir“

Ja, hier bei Merefield Technology Towers gibt es keine unanständige direkte DOM-Manipulation. :sweat_smile:

Ja, ich werde den Dienst nutzen, dafür ist er da! Ich werde mit meinen Erfahrungen zurückmelden, da mich die Ergebnisse sicher auch andere interessieren könnten.

3 „Gefällt mir“

Ja, das räumt auf und die Dinge geschehen jetzt auf beiden Routen in der richtigen Reihenfolge.

:rocket:

Danke für deine Hilfe!

2 „Gefällt mir“