[Userscript] Wanikani Item Lattice Script

Wanikani Item Lattice Script

This script brings back the previously removed item lattices, which display your SRS progress for radicals and kanji as a lattice:

The lattices are displayed at the bottom of your profile page:


This script can be installed via greasyfork.

Wanikani Open Framework is required.


I made this script a while ago and it has been sitting around for the past 2 weeks in purgatory because I can’t for the life of me get the image radicals to display. In the end I figured I’m better off publishing it with 30 or so missing file pictures than ripping my hair out trying to fix it for several weeks:

Also, your lattice will display on any user profile, which is obviously not meant to happen but I haven’t got around to fixing it since it’s a minor issue.

Finally, I never actually knew about this feature until after it was removed so I had to recreate the lattices using what few screenshots I could find. It seems like a pretty straightforward thing, but if I’ve missed any key features, please let me know.


Cool script!

Some things I noticed in the code:

  • What is this line supposed to do:

    filtered_items.sort((a,b) => a.data.slug - b.data.slug);

    The slugs are strings and attempting to subtract them will probably result in a bunch of NaN (I think – you never know with Javascript).

  • In the line

    let item_level = item_obj.assignments.srs_stage;

    you try to access the srs_stage property of assignments without first checking if assignments even exists (which it doesn’t if you have not unlocked the item yet). You could use optional chaining:

    let item_level = item_obj.assignments?.srs_stage ?? 0;
  • As for the problem with the image-based radicals: I have no idea if this can be fixed. I just noticed that the method I’m using in ConfusionGuesser has also stopped working. I think it is some CORS problem, but I’m not certain.

    EDIT: The reason why I’m thinking it is probably a CORS problem is that

    await (await fetch(items.find(i => i.id === 1).data.character_images[0].url)).text()

    works without a problem, but when I try to fetch it for item 8761 (which is the image-based “Stick” radical), I get a CORS error:

    await (await fetch(items.find(i => i.id === 8761).data.character_images[0].url)).text()


So originally I was going to convert the strings to unicode, however after checking the documentation for sort(), it turns out you can just compare the strings as is, as it converts strings automatically. I’m using the sort method here to arrange the items within each level in unicode order as @rfindley recommended a while back (however thinking about it, sorting by the character rather than the English may be closer to what WK did).


I spent ages trying to find what that was called since I didn’t know what it did but google kept thinking I meant ternary operators. I’ll be sure to add that later.

Oh well that’s slightly relieving knowing it may not entirely be my inability to implement svgs. I’ll look into it later maybe. I noticed the images still worked on the stats site though so I’m not entirely sure what I’ll be able to do.


fyi… strings in Javascript are already unicoded.
And the “proper” way to sort them:

filtered_items.sort((a,b) => a.data.slug.localeCompare(b.data.slug));

Just out of curiosity, is there any difference between this method and just using the greater than operator? I know localecompare is supposedly the correct way, but I never looked into the difference

1 Like

Different languages sort things differently.

In German, “a” and “ä” get sorted together.
In Spanish, “n” and “ñ” get sorted together.

['Hängt', 'Haut', 'Hüllen', 'Hubert'].sort();
// ['Haut', 'Hubert', 'Hängt', 'Hüllen']

['Hängt', 'Haut', 'Hüllen', 'Hubert'].sort((a, b) => a.localeCompare(b));
// ['Hängt', 'Haut', 'Hubert', 'Hüllen']

Oh that’s useful to know! Although is there a way to sort by the alphabetical order of a given locale in that case? Since (and Kumirei can confirm) I believe Swedish puts those accented vowels at the end of the alphabet (X, Y, Z, Å, Ä, Ö).

This may have to be something I look into later since now I’m also curious about Japanese kana order… :thinking:

I think localeCompare() pulls your language settings from the Browser, which defaults to the OS settings.

If you need to specify the locale, you can use Intl.Collator, which is probably used internally by localeCompare():

['z', 'ä', 'Z', 'a'].sort(new Intl.Collator('en-US').compare);
['z', 'ä', 'Z', 'a'].sort(new Intl.Collator('en-GB').compare);
['z', 'ä', 'Z', 'a'].sort(new Intl.Collator('de').compare);
['z', 'ä', 'Z', 'a'].sort(new Intl.Collator('sv').compare);

[Edit: Some interesting Intl.Collator options [here] ].


Cool script!

Just one lil nugget left 0: