Custom JavaScript not shown when moving to new task

Hi there,

I want to show some additional information, retrieved from the data of the current task, in our task interface using JavaScript.

I have the following code working nicely for showing information from window.prodigy.content when the user accesses the first task on their browser:

(async () => {
    while (typeof window.prodigy.content == "undefined") {
        console.log("content not loaded yet")
        await new Promise(resolve => setTimeout(resolve, 1000));
    }
    console.log("content loaded")
    const acceptValues = window.prodigy.content.combined_accept
    const options = window.prodigy.content.options

    const reasonsObj = options.filter(el => acceptValues.includes(el.id))
    const reasons = reasonsObj.map(el => el.text.toLowerCase()).join(", ")
    console.log("reasons: " + reasons)
    
    window.prodigy.update({ reason: "This task was rejected in review for reason(s): " + reasons })
})();

However, when the user answers and submits the first task, the next task does not render the JavaScript. I can see from the console that the needed information is present in window.prodigy.content but I assume the JS is never reloaded when changing tasks.

How could I change this so that the JS is shown in every task? I'm using version prodigy 1.18.0.

PS. I had to resort to the async above to show the custom information after window.prodigy.content is available, all the existing functions prodigyload, prodigymount etc. seemed to fire before the content was loaded. If there's a simpler way to achieve this, let me know, but this works as well.

Hi @helmiina,

The solution is to listen to prodigyupdate event to display the reason. This always fires on task updates (including the call to window.prodigy.update()) and it guarantees the content is available, so it eliminates the need for the async polling.

 document.addEventListener('prodigyupdate', () => {
      const content = window.prodigy.content;
      if (!content || !content.combined_accept || !content.options) {
          return;
      }

      // Prevent infinite loop (see explanation below)
      if (content.reason) {
          return;
      }

      const acceptValues = content.combined_accept;
      const options = content.options;

      const reasonsObj = options.filter(el => acceptValues.includes(el.id));
      const reasons = reasonsObj.map(el => el.text.toLowerCase()).join(", ");
      console.log("reasons: " + reasons);

      window.prodigy.update({ reason: "This task was rejected in review for reason(s): " + reasons });
  });

When you call window.prodigy.update(), Prodigy fires another prodigyupdate event (so other scripts can react to the change). Without the check if (content.reason) return; this would cause an infinite loop.

Importantly, for this fix to work you'd need to upgrade to Prodigy 1.18.4. In version 1.18.0, the prodigyupdate event had some reliability issues:

  • It was fired from a component that re-renders frequently, causing it to sometimes fire multiple times per task or miss task changes entirely
  • Events like prodigysave and prodigyscriptload didn't fire consistently in all scenarios

In versions 1.18.3 and 1.18.4, we fixed these and other issues related to event lifecycle.
Without them, your prodigyupdate event listener may not work correctly across all tasks, in particular the first task.

Thanks for the reply,

I did initially try to work with prodigyupdate but always ended up in an infinite loop. I'll try updating our prodigy version and trying your code, thank you!