Bangumi 番组计划 - 排序

按星期顺序分组,高亮显示当前日期

  1. // ==UserScript==
  2. // @name bangumi enhancement
  3. // @name:zh-CN Bangumi 番组计划 - 排序
  4. // @namespace http://xuefer.win/
  5. // @version 0.3
  6. // @description group items by day
  7. // @description:zh-CN 按星期顺序分组,高亮显示当前日期
  8. // @author Xuefer
  9. // @include http://bangumi.tv/
  10. // @include https://bangumi.tv/
  11. // @include http://bgm.tv/
  12. // @include https://bgm.tv/
  13. // @include http://chii.in/
  14. // @include https://chii.in/
  15. // @run-at document-start
  16. // ==/UserScript==
  17.  
  18. function sortElements(childs, compareFunction) {
  19. if (!childs.length) {
  20. return;
  21. }
  22. var parent = childs[0].parentNode;
  23. var sorting = [];
  24. for (var i = childs.length - 1; i >= 0; --i) {
  25. sorting.push(childs[i]);
  26. parent.removeChild(childs[i]);
  27. }
  28. sorting.sort(compareFunction);
  29. for (let child of sorting) {
  30. parent.appendChild(child);
  31. }
  32. }
  33.  
  34. Number.prototype.zeroPad = function(length) {
  35. var s = (this||"0").toString();
  36. while (s.length < length) {
  37. s = "0" + s;
  38. }
  39. return s;
  40. };
  41.  
  42. String.prototype.trim = function() {
  43. return this.replace(/^[ \t]+|[ \t]+$/g, "");
  44. };
  45.  
  46. String.prototype.extractDate = function() {
  47. return (this.match(/(20\d\d-\d{1,2}-\d{1,2})/)||[])[1] || NaN;
  48. };
  49.  
  50. String.prototype.getPrefix = function() {
  51. return ((this.match(/^([^(:]*)/)||[])[1] || "").trim();
  52. };
  53.  
  54. function changeLayout() {
  55. // wait for element to finish
  56. var unsafeWindow = self.unsafeWindow||window;
  57. if (!unsafeWindow.loadXML || !unsafeWindow.$ || !document.getElementById("subject_prg_content") || !document.getElementById("cluetip")) {
  58. setTimeout(changeLayout, 1);
  59. return;
  60. }
  61. var weekdayLabels = [ '日', '一', '二', '三', '四', '五', '六', '??' ];
  62. console.log("Changing layout");
  63. var $ = unsafeWindow.$;
  64.  
  65. var now = new Date();
  66. var oldDate = now.valueOf() - 365 * 24 * 60 * 60 * 1000;
  67.  
  68. do {
  69. let subjects = $("#cloumnSubjectInfo > div:first > div").toArray();
  70. if (!subjects.length) {
  71. break;
  72. }
  73.  
  74. var container = subjects[0].parentNode;
  75. for (let subject of subjects) {
  76. container.removeChild(subject);
  77. }
  78. while (container.lastChild) {
  79. container.removeChild(container.lastChild);
  80. }
  81. var days = [];
  82. for (let i = 0; i < 8; ++i) {
  83. let day = container.appendChild(document.createElement("div"));
  84. day.className = "day";
  85. day.style.overflow = "auto";
  86. let caption = day.appendChild(document.createElement("div"));
  87. caption.appendChild(document.createTextNode("周" + weekdayLabels[i]));
  88. day.subjects = day.appendChild(document.createElement("div"));
  89. days.push(day);
  90. }
  91. let oldDay = days[7];
  92. let today = days[new Date().getDay()];
  93.  
  94. today.className += " today";
  95. for (let subject of subjects) {
  96. let tips = (function() {
  97. try {
  98. for (let ep_info of $('.load-epinfo', subject).toArray()) {
  99. if (!/epBtnDrop|epBtnWatched/.test(ep_info.className)) {
  100. return $(".tip:first", $(ep_info.rel));
  101. }
  102. }
  103. let ep_info = $('.load-epinfo:last', subject);
  104. return $(".tip:first", $(ep_info[0].rel));
  105. } catch (e) {
  106. console.log(e, subject);
  107. }
  108. })();
  109. if (!tips) {
  110. subject.sortId = 0;
  111. oldDay.appendChild(subject);
  112. continue;
  113. }
  114.  
  115. let date = new Date(tips.text().extractDate());
  116. let title = $("> a:last", subject)[0].title;
  117. if (/*date.valueOf() <= oldDate ||*/ isNaN(date.valueOf())) {
  118. subject.sortId = title.getPrefix() + "-" + date.getYear().zeroPad(3) + date.getMonth().zeroPad(2) + "-" + title;
  119. if (isNaN(date.valueOf())) {
  120. subject.appendChild(document.createTextNode("Missing On Air Date"));
  121. }
  122. oldDay.appendChild(subject);
  123. }
  124. else {
  125. subject.sortId = title.getPrefix();
  126. days[date.getDay()].subjects.appendChild(subject);
  127. }
  128. }
  129. for (let day of days) {
  130. let nodes = day.subjects.childNodes;
  131. sortElements(nodes, function(a, b) {
  132. return a.sortId.localeCompare(b.sortId);
  133. });
  134.  
  135. for (var i = 0; i < nodes.length; ++i) {
  136. var $obj = $(nodes[i]);
  137. if (i % 2 === 0) {
  138. $obj.removeClass('even');
  139. $obj.addClass('odd');
  140. }
  141. else {
  142. $obj.removeClass('odd');
  143. $obj.addClass('even');
  144. }
  145. }
  146. }
  147. } while (0);
  148.  
  149. {
  150. let subjects = $("#prgSubjectList > li").toArray();
  151. for (let i in subjects) {
  152. subjects[i].sortId = $('> a:last', subjects[i])[0].title;
  153. }
  154. sortElements(subjects, function localeCompare(a, b) {
  155. return a.sortId.localeCompare(b.sortId);
  156. });
  157. }
  158.  
  159. var within_24hours = now.valueOf() - 60 * 60 * 24 * 1000;
  160. var within_48hours = now.valueOf() - 60 * 60 * 48 * 1000;
  161. $.each($(".epBtnAir"), function(i, o) {
  162. var airDate = new Date($(".tip:first", $(o.rel)).text().extractDate()).valueOf();
  163. if (isNaN(airDate)) {
  164. $(o).removeClass("epBtnAir");
  165. $(o).addClass("epBtnUnknown");
  166. }
  167. else if (airDate >= within_48hours) {
  168. $(o).addClass(airDate >= within_24hours ? "epBtnAirNewDay1" : "epBtnAirNewDay2");
  169. }
  170. });
  171. }
  172.  
  173. changeLayout();