Wanikani Open Framework - Progress module

Progress module for Wanikani Open Framework

目前為 2018-04-03 提交的版本,檢視 最新版本

此腳本不應該直接安裝,它是一個供其他腳本使用的函式庫。欲使用本函式庫,請在腳本 metadata 寫上: // @require https://update.cn-greasyfork.org/scripts/38577/262841/Wanikani%20Open%20Framework%20-%20Progress%20module.js

  1. // ==UserScript==
  2. // @name Wanikani Open Framework - Progress module
  3. // @namespace rfindley
  4. // @description Progress module for Wanikani Open Framework
  5. // @version 1.0.7
  6. // @copyright 2018+, Robin Findley
  7. // @license MIT; http://opensource.org/licenses/MIT
  8. // ==/UserScript==
  9.  
  10. (function(global) {
  11.  
  12. //########################################################################
  13. //------------------------------
  14. // Published interface
  15. //------------------------------
  16. global.wkof.Progress = {
  17. update: update_progress
  18. }
  19. //########################################################################
  20.  
  21. var popup_delay = 1000; // Delay before popup will open (in milliseconds).
  22. var popup_delay_started = false, popup_delay_expired = false, popup_timer;
  23. var externals_requested = false, externals_loaded = false;
  24. var progress_bars = {};
  25. var user_closed = false;
  26. var dialog_visible = false, dialog;
  27.  
  28. //------------------------------
  29. // Update the progress bar.
  30. //------------------------------
  31. function update_progress(data) {
  32. if (data) update_data(data);
  33.  
  34. if (!dialog_visible && !have_pending()) return shutdown();
  35.  
  36. // We have something pending, but don't show dialog until popup_delay has passed.
  37. if (!popup_delay_started) return start_popup_delay();
  38.  
  39. // Popup delay has passed. Show progress.
  40. if (!popup_delay_expired) return;
  41. update_dialog();
  42. }
  43.  
  44. //------------------------------
  45. // Update our stored progress bar status
  46. //------------------------------
  47. function update_data(data) {
  48. var bar = progress_bars[data.name];
  49. if (!bar) progress_bars[data.name] = bar = {label: data.label};
  50. bar.is_updated = true;
  51. bar.value = data.value;
  52. bar.max = data.max;
  53. if (bar.max === 0) {
  54. bar.value = 1;
  55. bar.max = 1;
  56. }
  57. // Don't retain items that complete before the dialog pops up.
  58. if (!popup_delay_expired && (bar.value >= bar.max))
  59. delete progress_bars[data.name];
  60. }
  61.  
  62. //------------------------------
  63. // Check if some progress is still pending.
  64. //------------------------------
  65. function have_pending() {
  66. var all_done = true;
  67. for (name in progress_bars) {
  68. var progress_bar = progress_bars[name];
  69. if (progress_bar.value < progress_bar.max) all_done = false;
  70. }
  71. return !all_done;
  72. }
  73.  
  74. //------------------------------
  75. // Delay the dialog from popping up until progress takes at least N milliseconds.
  76. //------------------------------
  77. function start_popup_delay() {
  78. popup_delay_started = true;
  79. popup_timer = setTimeout(function(){
  80. popup_delay_expired = true;
  81. update_progress();
  82. }, popup_delay);
  83. }
  84.  
  85. //------------------------------
  86. // Update the contents of the progress dialog (if it's currently visible)
  87. //------------------------------
  88. function update_dialog() {
  89. if (!externals_requested) {
  90. externals_requested = true;
  91. load_externals()
  92. .then(function(){
  93. externals_loaded = true;
  94. update_progress();
  95. });
  96. return;
  97. }
  98. if (!externals_loaded) return;
  99. if (user_closed) return;
  100.  
  101. if (!dialog_visible) {
  102. dialog_visible = true;
  103. if ($('#wkof_ds').length === 0) $('body').prepend('<div id="wkof_ds"></div>');
  104.  
  105. dialog = $('<div id="wkof_progbar_dlg" class="wkofs_progress_dlg" style="display:none;"></div>');
  106.  
  107. dialog.dialog({
  108. title: 'Loading Data...',
  109. minHeight: 20,
  110. maxHeight: window.innerHeight,
  111. height: 'auto',
  112. dialogClass: 'wkof_progbar_dlg',
  113. modal: false,
  114. resizable: false,
  115. autoOpen: false,
  116. appendTo: '#wkof_ds',
  117. close: dialog_close
  118. });
  119. dialog.dialog('open');
  120. }
  121.  
  122. var all_done = true;
  123. for (name in progress_bars) {
  124. var progress_bar = progress_bars[name];
  125. if (progress_bar.value < progress_bar.max) all_done = false;
  126. var bar = $('#wkof_progbar_dlg .wkof_progbar_wrap[name="'+name+'"]');
  127. if (bar.length === 0) {
  128. bar = $('<div class="wkof_progbar_wrap" name="'+name+'"><label>'+progress_bar.label+'</label><div class="wkof_progbar"></div></div>');
  129. var bars = $('#wkof_progbar_dlg .wkof_progbar_wrap');
  130. bars.push(bar[0]);
  131. $('#wkof_progbar_dlg').append(bars.sort(bar_label_compare));
  132. }
  133. if (progress_bar.is_updated) {
  134. progress_bar.is_updated = false;
  135. bar.find('.wkof_progbar').progressbar({value: progress_bar.value, max: progress_bar.max});
  136. }
  137. }
  138.  
  139. if (all_done) shutdown();
  140. }
  141.  
  142. function dialog_close() {
  143. dialog.dialog('destroy');
  144. dialog_visible = false;
  145. user_closed = true;
  146. }
  147.  
  148. //------------------------------
  149. // Load external support files (jquery UI and stylesheet)
  150. //------------------------------
  151. function load_externals() {
  152. if (location.hostname.match(/^(www\.)?wanikani\.com$/) !== null)
  153. css_url = wkof.support_files['jqui_wkmain.css'];
  154.  
  155. return wkof.ready('document')
  156. .then(function(){
  157. return Promise.all([
  158. wkof.load_script(wkof.support_files['jquery_ui.js'], true /* cache */),
  159. wkof.load_css(css_url, true /* cache */)
  160. ]);
  161. })
  162. .then(function(){
  163. // Workaround... https://community.wanikani.com/t/19984/55
  164. delete $.fn.autocomplete;
  165. });
  166. }
  167.  
  168. //------------------------------
  169. // Comparison function for sorting progress bars.
  170. //------------------------------
  171. function bar_label_compare(a, b){
  172. var a = $(a).find('label').text();
  173. var b = $(b).find('label').text();
  174. return a.localeCompare(b);
  175. }
  176.  
  177. //------------------------------
  178. // Shut down the dialog box and cancel the popup delay timer.
  179. //------------------------------
  180. function shutdown() {
  181. // If popup timer was pending, cancel it.
  182. if (popup_delay_started && !popup_delay_expired)
  183. clearTimeout(popup_timer);
  184. popup_delay_started = false;
  185. popup_delay_expired = false;
  186.  
  187. // If progress dialog is open, close it.
  188. if (dialog_visible) dialog.dialog('close');
  189. user_closed = false;
  190. progress_bars = {};
  191. }
  192.  
  193. function set_ready_state(){
  194. // Delay guarantees include() callbacks are called before ready() callbacks.
  195. setTimeout(function(){wkof.set_state('wkof.Progress', 'ready');},0);
  196. }
  197. set_ready_state();
  198.  
  199. })(window);