Activar JavaScript al hacer clic en cualquier enlace de la página, pero antes de que cargue el contenido de la página

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 me gusta

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 Me gusta

Exactly what I needed. Thanks!

2 Me gusta

Esto no parece activarse al entrar en un Tema desde una Lista de Temas.

También he intentado añadir uno:

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

pero tampoco se activa.

Un par de razones por las que podría no estar funcionando:

  1. Poner acciones en un hash es una sintaxis antigua que ya no usamos en Discourse. Teóricamente debería funcionar, pero la interoperabilidad con la nueva sintaxis podría no ser perfecta. La forma moderna sería

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

    se aplica el descargo de responsabilidad estándar de modifyClass: esto es arriesgado y podría romperse en cualquier momento

  2. No creo que willTransition esté garantizado que se active en la ruta de la aplicación en todas las situaciones. (por ejemplo, si una ruta hija tiene una acción willTransition, no necesariamente se propagará)

    Recomendaría usar los eventos en el servicio del enrutador de Ember en su lugar: RouterService | 5.12.0 | Ember API Documentation
    por ejemplo, algo como

    const router = api.container.lookup("service:router");
    router.on("routeWillChange", () => {
      console.log("route will change se activó");
    });
    
2 Me gusta

¡Genial, gracias David, lo intentaré la próxima vez!

Esta investigación se activó (ejem) porque necesitaba una forma de disparar algo en cada cambio de página, y antes de Render.

Al parecer, el evento de la API de cambio de página no garantiza que se active antes de que se rendericen los elementos de la página.

1 me gusta

Creo que te costará hacerlo perfectamente. Ember espera tener el control total de la renderización, por lo que intentar engancharse en puntos arbitrarios será difícil y puede causar problemas (dependiendo de lo que estés intentando hacer).

Obviamente, no sé cuál es tu objetivo final… así que tal vez el dolor esté justificado. En ese caso: siéntete libre de ignorarme :wink:

(por supuesto, si te gustaría abrir un tema de Dev sobre el problema que estás intentando resolver, con gusto le echaré un vistazo)

Encantado de ser explícito ya que el código es de código abierto:

Estoy trabajando con un proveedor de anuncios externo y tienen una función de reinicio de página de anuncios en javascript que necesita ejecutarse antes de que se activen los anuncios de la nueva página.

Cualquier mejora es bienvenida y ya me he dado cuenta de esto en la Lista de Temas con el código de Johani. (en un PR abierto).

Pero esto dejó el Tema… Intentaré tu sugerencia a continuación y la adoptaré en ambos casos si eso mejora aún más las cosas.

Ya veo, así que no estás modificando el DOM directamente :ok_hand:

En ese caso, espero que routeWillChange funcione; ciertamente debería activarse antes de que se renderice la siguiente ruta.

La advertencia es que… en el caso de cosas como redirecciones, puede activarse dos veces. O puede activarse y luego la transición termina siendo abortada. Pero tal vez eso esté bien en este caso.

2 Me gusta

Sí, nada de esa perversa modificación directa del DOM por aquí en Merefield Technology Towers. :sweat_smile:

Sí, usaré el servicio, ¡para eso está! Te informaré de mi experiencia, ya que estoy seguro de que los resultados podrían interesar a otros.

3 Me gusta

Así que sí, eso se limpia y las cosas ahora ocurren en el orden correcto en ambas rutas.

:rocket:

¡Gracias por tu ayuda!

2 Me gusta