Déclencher JavaScript lors du clic sur n'importe quel lien de la page, mais avant le chargement du contenu de la page

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 « J'aime »

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 « J'aime »

Exactly what I needed. Thanks!

2 « J'aime »

Cela ne semble pas se déclencher lors de l’entrée dans un sujet à partir d’une liste de sujets ?

J’ai aussi essayé d’en ajouter un :

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

mais cela ne se déclenche pas non plus.

Quelques raisons pour lesquelles cela pourrait ne pas fonctionner :

  1. Mettre des actions dans un hash est une ancienne syntaxe que nous n’utilisons plus dans Discourse. Théoriquement, cela devrait fonctionner, mais l’interopérabilité avec la nouvelle syntaxe pourrait ne pas être parfaite. La manière moderne serait

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

    Le disclaimer standard modifyClass s’applique : c’est risqué et cela pourrait casser à tout moment

  2. Je ne pense pas que willTransition soit garanti de se déclencher sur la route d’application dans toutes les situations. (par exemple, si une route enfant a une action willTransition, elle ne remontera pas nécessairement)

Je recommanderais d’utiliser les événements du service de routage Ember à la place : RouterService | 5.12.0 | Ember API Documentation
par exemple, quelque chose comme

const router = api.container.lookup("service:router");
router.on("routeWillChange", () => {
  console.log("route will change déclenché");
});
2 « J'aime »

Bien, merci David, j’essaierai ça ensuite !

Cette enquête a été déclenchée (ahem) parce que j’avais besoin d’un moyen de déclencher quelque chose à chaque changement de page, et avant le rendu.

L’événement d’API de changement de page ne semble pas garanti de se déclencher avant le rendu des éléments de la page, apparemment.

1 « J'aime »

Je pense que vous aurez du mal à faire cela parfaitement. Ember s’attend à avoir le contrôle total du rendu, donc essayer de s’accrocher à des points arbitraires sera difficile et pourrait causer des problèmes (selon ce que vous essayez de faire).

Évidemment, je ne sais pas quel est votre objectif final… donc peut-être que la douleur est justifiée. Auquel cas : n’hésitez pas à m’ignorer :wink:

(bien sûr, si vous souhaitez ouvrir un sujet Dev sur le problème que vous essayez de résoudre, je serais heureux d’y jeter un œil)

Heureux d’être explicite car le code est open source :

Je travaille avec un fournisseur de publicité tiers et ils ont une fonction de réinitialisation de page publicitaire en javascript qui doit être exécutée avant que les publicités de la nouvelle page ne soient déclenchées.

Toute amélioration est la bienvenue et je l’ai déjà implémentée dans la liste des sujets avec le code de Johani. (dans un PR ouvert).

Mais cela a laissé le sujet… J’essaierai votre suggestion ensuite et l’adopterai dans les deux cas si cela améliore encore les choses.

Ah je vois, donc vous ne modifiez pas le DOM directement :ok_hand:

Dans ce cas, j’espère que routeWillChange fonctionnera - il devrait certainement se déclencher avant que la prochaine route ne soit rendue.

La mise en garde est que… dans le cas de choses comme les redirections, il peut se déclencher deux fois. Ou peut se déclencher, puis la transition finit par être abandonnée. Mais peut-être que c’est acceptable dans ce cas.

2 « J'aime »

Oui, pas de modification directe du DOM ici chez Merefield Technology Towers. :sweat_smile:

Oui, j’utiliserai le service, c’est à cela qu’il sert ! Je reviendrai avec mon expérience car je suis sûr que les résultats pourraient intéresser d’autres personnes.

3 « J'aime »

Oui, cela nettoie et les choses se déroulent maintenant dans le bon ordre sur les deux itinéraires.

:rocket:

Merci pour votre aide !

2 « J'aime »