Attivare javascript al clic su qualsiasi link della pagina, ma prima che il contenuto della pagina venga caricato?

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 Mi Piace

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 Mi Piace

Exactly what I needed. Thanks!

2 Mi Piace

Questo non sembra essere eseguito quando si entra in un argomento da un elenco di argomenti?

Ho anche provato ad aggiungerne uno:

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

ma anche questo non viene eseguito.

Un paio di ragioni per cui potrebbe non funzionare:

  1. Mettere le azioni in un hash è una sintassi vecchia che non usiamo più in Discourse. Teoricamente dovrebbe funzionare, ma l’interoperabilità con la nuova sintassi potrebbe non essere perfetta. Il modo moderno sarebbe

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

    si applica il disclaimer standard di modifyClass: questo è rischioso e potrebbe interrompersi in qualsiasi momento

  2. Non credo che willTransition sia garantito che venga attivato sulla route dell’applicazione in tutte le situazioni. (ad esempio, se una route figlia ha un’azione willTransition, non necessariamente risalirà)

    Ti consiglio di utilizzare invece gli eventi sul servizio del router Ember: RouterService | 5.12.0 | Ember API Documentation

    ad esempio, qualcosa come

    const router = api.container.lookup("service:router");
    router.on("routeWillChange", () => {
      console.log("route will change attivato");
    });
    
2 Mi Piace

Bello, grazie David, ci proverò la prossima volta!

Questa indagine è stata innescata (ehm) perché avevo bisogno di un modo per attivare qualcosa ad ogni cambio di pagina, e prima di Render.

L’evento API di cambio pagina non sembra essere garantito per attivarsi prima che gli elementi della pagina vengano renderizzati, apparentemente.

1 Mi Piace

Penso che avrai difficoltà a farlo perfettamente. Ember si aspetta di avere il pieno controllo del rendering, quindi cercare di agganciarsi a punti arbitrari sarà difficile e potrebbe causare problemi (a seconda di cosa stai cercando di fare).

Ovviamente non so qual è il tuo obiettivo finale… quindi forse il problema è giustificato. In tal caso: sentiti libero di ignorarmi :wink:

(naturalmente, se volessi aprire un argomento Dev sul problema che stai cercando di risolvere, sarei felice di dare un’occhiata)

Felice di essere esplicito dato che il codice è open source:

Sto lavorando con un provider di annunci di terze parti che ha una funzione di reset della pagina pubblicitaria in javascript che deve essere eseguita prima che vengano attivati gli annunci della nuova pagina.

Qualsiasi miglioramento è benvenuto e l’ho già implementato nella Topic List con il codice di Johani. (in un PR aperto).

Ma questo ha lasciato il Topic… Proverò il tuo suggerimento la prossima volta e lo adotterò in entrambi i casi se ciò migliorerà ulteriormente le cose.

Ah capisco, quindi non stai modificando il DOM direttamente :ok_hand:

In tal caso, spero che routeWillChange funzioni: dovrebbe sicuramente attivarsi prima che venga renderizzata la prossima route.

L’avvertenza è che… nel caso di cose come i reindirizzamenti, potrebbe attivarsi due volte. O potrebbe attivarsi, e poi la transizione finisce per essere interrotta. Ma forse va bene in questo caso.

2 Mi Piace

Sì, niente di quella malizia di modifica diretta del DOM qui a Merefield Technology Towers. :sweat_smile:

Sì, userò il servizio, è quello che serve! Ti farò sapere com’è andata, sono sicuro che i risultati potrebbero interessare ad altri.

3 Mi Piace

Sì, questo sistema pulisce e ora le cose accadono nell’ordine corretto su entrambi i percorsi.

:rocket:

Grazie per il tuo aiuto!

2 Mi Piace