I thought it could be due to the wrong version of the library in cache. I cleared the cache to no avail.
Then why does it consistently work when navigating pages? The problem occurs only on a page refresh. Logically if the wrong element is listened to it should fail on navigation as well.
I’m not sure either. The update I just pushed enables debug logging to make it easier for people to paste logs here that I can inspect. I’m going to see if this is a firefox vs chromium issue by testing out the script in Vivaldi. If it works fine there, then maybe it’s Chrome specific instead of chromium. And if other Chrome users have no issues then I’m sorry to say this might be machine-specific.
Edit: the log outputs using console.debug() not console.log() so that’s where to check.
Here’s an example of the logs of the script working as intended:
START: Show Total Lesson Count Debug Log:
2024-08-04T18:55:45.435Z: Start of TurboEvents ready callback
2024-08-04T18:55:46.516Z: turbo:load has fired, setting globals and calling _start()
2024-08-04T18:55:46.516Z: Starting...
2024-08-04T18:55:46.695Z: turbo:before-frame-render has fired for "#lesson-and-review-count-frame"
2024-08-04T18:55:46.723Z: turbo:frame-load has fired
2024-08-04T18:55:46.723Z: turbo:frame-load is for "#lesson-and-review-count-frame"
2024-08-04T18:55:46.723Z: Main function is executing...
2024-08-04T18:55:46.723Z: We do not have settings, setting timeout on _start()
2024-08-04T18:55:46.723Z: Did not set timeout due to already being in starting state
2024-08-04T18:55:46.735Z: turbo:before-frame-render has fired for "#todays-lessons-frame"
2024-08-04T18:55:46.753Z: turbo:frame-load has fired
2024-08-04T18:55:46.753Z: turbo:frame-load is for "#todays-lessons"
2024-08-04T18:55:46.753Z: Main function is executing...
2024-08-04T18:55:46.753Z: We do not have settings, setting timeout on _start()
2024-08-04T18:55:46.753Z: Did not set timeout due to already being in starting state
2024-08-04T18:55:47.004Z: turbo:before-frame-render has fired for "#review-forecast"
2024-08-04T18:55:47.029Z: turbo:frame-load has fired
2024-08-04T18:55:47.029Z: turbo:frame-load was for "#review-forecast", doing nothing...
2024-08-04T18:55:47.118Z: Loading settings...
2024-08-04T18:55:47.176Z: Inserting menu...
2024-08-04T18:55:47.176Z: Main function is executing...
2024-08-04T18:55:47.176Z: We have settings
2024-08-04T18:55:47.176Z: Frame(s) loaded
2024-08-04T18:55:47.176Z: At least one container exists
However, on subsequent refreshes I am seeing unexplained doubling of some events.
Ok, I forgot to account for when the script can’t even reach main(). This might still need another pass at it but 0.4.6 should help with logging in your case now.
I have 0.4.6, Still no debug information when doing a failed run.
Alright, one more try with 0.4.7. This time I have added a constant const INTERNAL_FORCE_DEBUG_OUTPUT = false; that I’d like you to set to true. Doing it this way because there’s no guarantee that the Settings module is being loaded in your not working case. Additionally, this lets you copy-paste if (INTERNAL_FORCE_DEBUG_OUTPUT) printDebugLog(INTERNAL_FORCE_DEBUG_OUTPUT); into any place that you think would be a good candidate for forcing the debug output.
Just want to check one more thing, because it’s really weird to me that it seems like the turbo events either aren’t being fired or aren’t being caught by the listeners. Please replace the section of code starting with the library dependency with the following:
const wkofTurboEventsScriptUrl = 'https://update.greasyfork.org/scripts/501980/1419628/Wanikani%20Open%20Framework%20Turbo%20Events.user.js';
addToDebugLog(`Attempting to load the TurboEvents library script...`)
await wkof.load_script(wkofTurboEventsScriptUrl, /* use_cache */ true);
addToDebugLog(`Checking if TurboEvents library script is loaded in...`)
let injectedDependency = document.head.querySelector('script[uid*="Turbo"]');
addToDebugLog(`Turbo Events library ${injectedDependency ? 'is' : 'is NOT' } loaded.`);
if (INTERNAL_FORCE_DEBUG_OUTPUT) {
window.addEventListener('turbo:load', () => { addToDebugLog(`DEBUG: turbo:load has fired`); });
window.addEventListener('turbo:before-frame-render', () => { addToDebugLog(`DEBUG: turbo:before-frame-render has fired`); });
window.addEventListener('turbo:frame-load', () => { addToDebugLog(`DEBUG: turbo:frame-load has fired`); });
}
wkof.ready('TurboEvents').then(() => {
addToDebugLog(`Start of TurboEvents ready callback`)
let urlList = [wkof.turbo.common.locations.dashboard, wkof.turbo.common.locations.items_pages, /^https:\/\/www\.wanikani\.com\/(settings|level|radicals|kanji|vocabulary)(\/|\?difficulty=).+\/?$/];
wkof.turbo.on.common.urls(() => {
addToDebugLog(`turbo:load has fired, setting globals and calling _start()`)
initial_load = stateStarting = true;
hasOutputLog = todaysLessonsFrameLoaded = navBarCountFrameLoaded = false;
_start();
}, urlList);
wkof.turbo.on.event.before_frame_render((e) => {
addToDebugLog(`turbo:before-frame-render has fired for "#${e.target.id}"`)
if (['todays-lessons-frame', 'lesson-and-review-count-frame'].includes(e.target.id)) {
todaysLessonsFrameLoaded = navBarCountFrameLoaded = false;
}
}, { urls: urlList, noTimeout: true });
wkof.turbo.on.event.frame_load(async (e) => {
addToDebugLog('turbo:frame-load has fired')
if (e.target.id === 'todays-lessons-frame') {
addToDebugLog('turbo:frame-load is for "#todays-lessons-frame"')
todaysLessonsFrameLoaded = true;
mainSource = `turbo:frame-load for "#todays-lessons-frame"`;
await main();
}
else if (e.target.id === 'lesson-and-review-count-frame') {
addToDebugLog('turbo:frame-load is for "#lesson-and-review-count-frame"')
navBarCountFrameLoaded = true;
mainSource = `turbo:frame-load for "#lesson-and-review-count-frame"`;
await main();
}
else {
addToDebugLog(`turbo:frame-load was for "#${e.target.id}", doing nothing...`)
}
mainSource = '';
}, { urls: urlList });
if (INTERNAL_FORCE_DEBUG_OUTPUT) printDebugLog(INTERNAL_FORCE_DEBUG_OUTPUT);
});
Edit: I may have forgotten to give a way for those window listeners to print…
The bug happens less frequently when compared to successful runs.

I’ll keep at it. Have to switch gears to focusing on other things for the day but I’ll get back to testing when I can.
OK. take the time you need. We have done a lot today.
Thanks. If you want you can try replacing those addToDebugLog calls in the window.addEventListener declarations with console.log or console.debug directly and seeing if that changes anything, but I doubt it will.
Did that. The events are reported by window.addEventListener but not by the wkof.turbo configured listeners.

Oh thank goodness, progress at last. Now I know the issue has to be with TurboEvents registering the event listeners. I still can’t reproduce the issue on my machine, but perhaps if you set some breakpoints in the debugger of the dev tools and step through 1-by-1 such that it also steps into the loaded TurboEvents code, watch the values of variables, and try to determine exactly what point it’s having an issue then we can uncover more of what’s going on.
@Inserio do you have any thoughts on what could be going on here given that now we know something is up with the library setting the callbacks for the listeners for prouleau?
I mean, that’s some strange shenanigans…
Without looking into the rest of your script functionality…I don’t know. When I’m trying to figure out the bugs for these kinds of things, I like to get down and dirty with the browser debugger by setting breakpoints and stepping in/over until I figure out what I need.
Which is literally what you said as well. Man, it’s been a day.
Edit:
Just copy/pasted some relevant stuff from your example above and tried it in both Edge and Firefox, with no issues.
Steps taken:
- Visit Dashboard
- Paste to console:
let hasOutputLog = false;
let scriptName = 'Show Total Lesson Count';
let debugLogText = `START: ${scriptName} Debug Log:\n`;
let urlList = [wkof.turbo.common.locations.dashboard, wkof.turbo.common.locations.items_pages, /^https:\/\/www\.wanikani\.com\/(settings|level|radicals|kanji|vocabulary)(\/|\?difficulty=).+\/?$/];
function addToDebugLog(message) {
debugLogText += `${new Date().toISOString()}: ${message}\n`;
}
function printDebugLog(force = false) {
console.log(`${scriptName}: Outputting a debug log to console.debug()`)
if (!hasOutputLog || force) console.debug(debugLogText);
hasOutputLog = true;
debugLogText = `START: ${scriptName} Debug Log:\n`;
}
wkof.turbo.on.event.before_frame_render((e) => {
addToDebugLog(`turbo:before-frame-render has fired for "#${e.target.id}"`)
if (['todays-lessons-frame', 'lesson-and-review-count-frame'].includes(e.target.id)) {
todaysLessonsFrameLoaded = navBarCountFrameLoaded = false;
}
}, { urls: urlList, noTimeout: true });
- Click WaniKani logo
- Paste to console:
printDebugLog()
- Output:
START: Show Total Lesson Count Debug Log:
2024-08-05T02:43:45.043Z: turbo:before-frame-render has fired for “#lesson-and-review-count-frame”
2024-08-05T02:43:45.547Z: turbo:before-frame-render has fired for “#todays-lessons-frame”
2024-08-05T02:43:45.596Z: turbo:before-frame-render has fired for “#review-forecast”
(In Edge, I had to enable Verbose logs for it to show up though)
Also, I have the event library installed locally, ordered to run right after WKOF.
Yeah I have it installed locally too. It’ll be a pain because I only have FF set up properly, but I will get Vivaldi and maybe even Edge set up to test this script without it being installed locally and see what happens. If I can reproduce the issue, then I can do all that debugger/breakpoint stuff myself. It’s just reproducing it that’s giving me trouble now.
But the specifics of my script should no longer be a factor as the last bit of testing seems to reveal that the callbacks passed to the library functions are just not being set at all, but the events are firing just fine. I’m just struggling to imagine what could possibly be the reason for that.
Looks up. Sighs.
I was gonna comment on this but I think I actually rooted down the issue.
Btw, unrelatedly, this:
I took straight from the Turbo docs. If it’s not working because of this, I don’t mind changing it, but it’ll take a lot to convince me that’s the issue.
Anyway, to the issue. It *is* a library problem, but not one that any of us guessed it would be. The internal URL that is being used to check against the current URL is not getting set by the time some of this is first called.
I’ll see what I can do about that.
So I worked around this in my script by using the turbo:load event rather than turbo:render. As part of the event payload, turbo:load includes the URL that turbo thinks it has just rendered, earlier than when it updates the browser history.
The catch here is that the event is triggered too soon on the first page load for the event listener that I install, so I also need to check on load if we’re already on the correct page and render from two paths. (initial load -> already on right page -> render + turbo:load -> new page is target page -> render)

