AtCoder ResultsPage Tweaks

AtCoderの提出結果一覧画面に自動検索機能などを追加します。

目前為 2021-03-28 提交的版本,檢視 最新版本

  1. // ==UserScript==
  2. // @name AtCoder ResultsPage Tweaks
  3. // @namespace https://github.com/yukuse
  4. // @version 1.0.2
  5. // @description AtCoderの提出結果一覧画面に自動検索機能などを追加します。
  6. // @author yukuse
  7. // @include https://atcoder.jp/contests/*/submissions*
  8. // @grant window.jQuery
  9. // @grant window.fixTime
  10. // @license MIT
  11. // ==/UserScript==
  12.  
  13. // jQueryカスタムイベントを監視・発火するためwindowのjQueryを使用
  14. jQuery(($) => {
  15. const options = {
  16. // 検索条件変更時に自動検索 on/off
  17. autoSearchOnChange: true,
  18. // 検索結果の動的読み込み on/off
  19. dynamicResult: true,
  20. // 検索条件変更時のフォーカス維持 on/off
  21. keepSelectFocus: true,
  22. };
  23.  
  24. const $container = $('#main-container');
  25. const $panelSubmission = $container.find('.panel-submission');
  26.  
  27. const baseParams = {
  28. 'f.Task': '',
  29. 'f.LanguageName': '',
  30. 'f.Status': '',
  31. 'f.User': '',
  32. page: 1,
  33. };
  34.  
  35. function parseSubmissionsUrl(url) {
  36. const params = { ...baseParams };
  37. if (url) {
  38. Object.keys(params).forEach((key) => {
  39. const regexp = new RegExp(`${key}=([^&]+)`);
  40. const result = url.match(regexp);
  41. if (result) {
  42. [, params[key]] = result;
  43. }
  44. });
  45. }
  46.  
  47. return params;
  48. }
  49.  
  50. /**
  51. * 現在のURLに応じて検索結果表示を更新
  52. * TODO: ジャッジ中表示対応
  53. */
  54. function updateSearchResult() {
  55. const { href } = location;
  56. const params = parseSubmissionsUrl(href);
  57.  
  58. // 検索条件を遷移先の状態にする
  59. Object.keys(params).forEach((key) => {
  60. $panelSubmission.find(`[name="${key}"]`).val(params[key]).trigger('change');
  61. });
  62.  
  63. const $tmp = $('<div>');
  64. $tmp.load(`${href} #main-container`, '', () => {
  65. const $newTable = $tmp.find('.table-responsive, .panel-body');
  66. // テーブル置換
  67. $panelSubmission.find('.table-responsive, .panel-body').replaceWith($newTable);
  68. // ページネーション置換
  69. if ($newTable.hasClass('table-responsive')) {
  70. $container.find('.pagination').replaceWith($tmp.find('.pagination:first'));
  71. } else {
  72. $container.find('.pagination').empty();
  73. }
  74.  
  75. // 日付を表示
  76. fixTime();
  77. });
  78. }
  79.  
  80. /**
  81. * 検索条件を元にURLを更新し、結果を表示する
  82. */
  83. function showSearchResult(params) {
  84. const paramsStr = Object.keys(params).map((key) => `${key}=${params[key]}`).join('&');
  85. const url = `${location.pathname}?${paramsStr}`;
  86.  
  87. if (options.dynamicResult) {
  88. history.pushState({}, '', url);
  89.  
  90. updateSearchResult();
  91. } else {
  92. location.href = url;
  93. }
  94. }
  95.  
  96. /**
  97. * 選択欄の調整
  98. * - 選択時に自動検索
  99. * - 選択時にフォーカスが飛ばないようにする
  100. */
  101. function initSelectTweaks() {
  102. $panelSubmission.find('#select-task, #select-language, #select-status').on('select2:select select2:unselect', (event) => {
  103. // unselectの場合は選択状態が遅れて反映されるため、実行を遅らせる
  104. setTimeout(() => {
  105. // 選択時に自動検索
  106. if (options.autoSearchOnChange) {
  107. const params = { ...baseParams };
  108. Object.keys(params).forEach((key) => {
  109. params[key] = $panelSubmission.find(`[name="${key}"]`).val();
  110. });
  111. params.page = 1;
  112.  
  113. showSearchResult(params);
  114. }
  115.  
  116. // 選択時にフォーカスが飛ばないようにする
  117. if (options.keepSelectFocus) {
  118. event.target.focus();
  119. }
  120. }, 0);
  121. });
  122. }
  123.  
  124. const urlRegExp = new RegExp(location.pathname);
  125. /**
  126. * 検索結果のリンククリック時のページ遷移をなくし、表示を動的に更新する処理に置き換え
  127. */
  128. function initLinks() {
  129. $container.on('click', '.pagination a, .panel-submission a', (event) => {
  130. const { href } = event.target;
  131. if (!urlRegExp.test(href)) {
  132. return;
  133. }
  134.  
  135. event.preventDefault();
  136.  
  137. showSearchResult(parseSubmissionsUrl(href));
  138. });
  139. }
  140.  
  141. function init() {
  142. initSelectTweaks();
  143. if (options.dynamicResult) {
  144. window.addEventListener('popstate', updateSearchResult);
  145. initLinks();
  146. }
  147. }
  148.  
  149. init();
  150. });

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址