WaniKani Study Config

Provides website settings for easier studying.

  1. // ==UserScript==
  2. // @name WaniKani Study Config
  3. // @namespace wkstudycfg
  4. // @version 1.0.3
  5. // @description Provides website settings for easier studying.
  6. // @author Robin Findley
  7. // @copyright 2014+, Robin Findley
  8. // @license MIT; http://opensource.org/licenses/MIT
  9. // @include http://www.wanikani.com/level/*
  10. // @include https://www.wanikani.com/level/*
  11. // @include http://www.wanikani.com/radicals*
  12. // @include https://www.wanikani.com/radicals*
  13. // @include http://www.wanikani.com/kanji*
  14. // @include https://www.wanikani.com/kanji*
  15. // @include http://www.wanikani.com/vocabulary*
  16. // @include https://www.wanikani.com/vocabulary*
  17. // @grant GM_addStyle
  18. // @grant GM_registerMenuCommand
  19. // ==/UserScript==
  20.  
  21. //==[ History ]======================================================
  22. // 1.0.3 - Remove need for jquery.
  23. // 1.0.2 - Fix Firefox sandbox issue by @requiring jquery.
  24. // 1.0.1 - Fix @includes to add some missed pages.
  25. // 1.0.0 - Initial release.
  26. //===================================================================
  27.  
  28. //-------------------------------------------------------------------
  29. // Global data container and initialization.
  30. //-------------------------------------------------------------------
  31. var wksc = {};
  32. wksc.criteria = {};
  33. wksc.criteria.unlocked_first = true;
  34.  
  35. //-------------------------------------------------------------------
  36. // Vocabulary sort comparison.
  37. //-------------------------------------------------------------------
  38. function wk_vocab_compare(a, b) {
  39. var a_text, b_text, a_lock, b_lock;
  40.  
  41. a_text = a.querySelector('.character').innerHTML;
  42. b_text = b.querySelector('.character').innerHTML;
  43. // If 'unlocked_first' option is selected, push locked items to the end of the list.
  44. if (wksc.criteria.unlocked_first == true) {
  45. a_lock = (a.className.match(/\blocked\b/)!=null);
  46. b_lock = (b.className.match(/\blocked\b/)!=null);
  47. if (!a_lock && b_lock) {
  48. return -1;
  49. }
  50. if (a_lock && !b_lock) {
  51. return 1;
  52. }
  53. }
  54. if (a_text < b_text) {
  55. return -1;
  56. }
  57. if (a_text > b_text) {
  58. return 1;
  59. }
  60. return 0;
  61. }
  62.  
  63. //-------------------------------------------------------------------
  64. // Sort groups vocabulary.
  65. //-------------------------------------------------------------------
  66. function sort_vocab()
  67. {
  68. var vocab_groups, group, grp_cnt, grp_idx, words, word_cnt, word_idx;
  69. vocab_groups = document.querySelectorAll('.multi-character-grid');
  70.  
  71. grp_cnt = vocab_groups.length;
  72. for (grp_idx = 0; grp_idx < grp_cnt; grp_idx++)
  73. {
  74. group = vocab_groups[grp_idx];
  75. if (group.querySelector('li[id|=vocabulary]')==undefined) {
  76. continue;
  77. }
  78.  
  79. words = [];
  80. word_cnt = group.childElementCount;
  81. for (word_idx = 0; word_idx < word_cnt; word_idx++) {
  82. words.push(group.children[word_idx]);
  83. }
  84.  
  85. words.sort(wk_vocab_compare);
  86.  
  87. for (word_idx = 0; word_idx < word_cnt; word_idx++) {
  88. group.appendChild(words[word_idx]);
  89. }
  90. }
  91. }
  92.  
  93. //-------------------------------------------------------------------
  94. // Add CSS styles to the document.
  95. //-------------------------------------------------------------------
  96. function add_styles() {
  97. GM_addStyle('.wksc_hide .character-item ul {opacity:0} .wksc_hide .character-item:hover ul {opacity:1.0}');
  98. }
  99.  
  100. //-------------------------------------------------------------------
  101. // Hide or unhide radicals, kanji, and vocabulary meaning and pronunciation.
  102. //-------------------------------------------------------------------
  103. function set_visibility(hidden) {
  104. var elems, cnt, idx;
  105. elems = document.querySelectorAll('.single-character-grid, .multi-character-grid');
  106. cnt = elems.length;
  107. for (idx=0; idx<cnt; idx++) {
  108. if (hidden) {
  109. elems[idx].className += ' wksc_hide';
  110. } else {
  111. elems[idx].className = elems[idx].className.replace(/(^|\s+)wksc_hide(\s+|$)/g, ' ');
  112. }
  113. }
  114. }
  115.  
  116. //-------------------------------------------------------------------
  117. // Check that all localStorage items are present and valid. Assign defaults as needed.
  118. //-------------------------------------------------------------------
  119. function check_storage() {
  120. wksc.hide_info = Number(localStorage.getItem("wksc_hide") || 1);
  121. if (!(wksc.hide_info >= 0 && wksc.hide_info <= 1)) {
  122. wksc.hide_info = 1;
  123. localStorage.setItem("wksc_hide", wksc.hide_info);
  124. }
  125. }
  126.  
  127. //-------------------------------------------------------------------
  128. // Set up GreaseMonkey menu commands.
  129. //-------------------------------------------------------------------
  130. function GMsetup() {
  131. if (GM_registerMenuCommand) {
  132. GM_registerMenuCommand('WaniKani Study: Hide info until hover', function() {
  133. wksc.hide_info++;
  134. wksc.hide_info %= 2;
  135. localStorage.setItem("wksc_hide", wksc.hide_info);
  136. set_visibility(wksc.hide_info);
  137. });
  138. }
  139. }
  140.  
  141. //-------------------------------------------------------------------
  142. // main()
  143. //-------------------------------------------------------------------
  144. function main() {
  145. check_storage();
  146. GMsetup();
  147. add_styles();
  148. sort_vocab();
  149. set_visibility(wksc.hide_info);
  150. }
  151.  
  152. // Run main upon load.
  153. window.addEventListener("load", main, false);