futaba auto reloader

赤福Firefox版の"リロードの代わりに続きを読む"を有効にして自動更新しちゃう(実況モードもあるよ!)

当前为 2015-06-19 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name futaba auto reloader
  3. // @namespace https://github.com/himuro-majika
  4. // @description 赤福Firefox版の"リロードの代わりに続きを読む"を有効にして自動更新しちゃう(実況モードもあるよ!)
  5. // @include http://*.2chan.net/*/res/*
  6. // @include http://board.futakuro.com/*/res/*
  7. // @require http://ajax.googleapis.com/ajax/libs/jquery/2.0.3/jquery.min.js
  8. // @version 1.2
  9. // @grant none
  10. // @icon data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAABGdBTUEAAK/INwWK6QAAABl0RVh0U29mdHdhcmUAQWRvYmUgSW1hZ2VSZWFkeXHJZTwAAAAPUExURYv4i2PQYy2aLUe0R////zorx9oAAAAFdFJOU/////8A+7YOUwAAAElJREFUeNqUj1EOwDAIQoHn/c88bX+2fq0kRsAoUXVAfwzCttWsDWzw0kNVWd2tZ5K9gqmMZB8libt4pSg6YlO3RnTzyxePAAMAzqMDgTX8hYYAAAAASUVORK5CYII=
  11. // ==/UserScript==
  12. this.$ = this.jQuery = jQuery.noConflict(true);
  13.  
  14. (function ($) {
  15. /*
  16. * 設定
  17. */
  18. var USE_SOUDANE = true; //そうだねをハイライト表示する
  19. var USE_CLEAR_BUTTON = true; //フォームにクリアボタンを表示する
  20. var USE_TITLE_NAME = true; //新着レス数・スレ消滅状態をタブに表示する
  21. var RELOAD_INTERVAL_NORMAL = 60000; //リロード間隔[ミリ秒](通常時)
  22. var RELOAD_INTERVAL_LIVE = 5000; //リロード間隔[ミリ秒](実況モード時)
  23. var LIVE_SCROLL_INTERVAL = 12; //実況モードスクロール間隔[ミリ秒]
  24. var LIVE_SCROLL_SPEED = 2; //実況モードスクロール幅[px]
  25. var LIVE_TOGGLE_KEY = "76"; //実況モードON・OFF切り替えキーコード(With Ctrl)
  26.  
  27. var live_flag = false; //実況モード有効フラグ
  28. var res = 0; //新着レス数
  29. var timerNormal, timerLiveReload, timerLiveScroll;
  30. var liveButton;
  31. var url = location.href;
  32. var script_name = "futaba_auto_reloader";
  33.  
  34. //通常時60秒おきにリロード
  35. if(!isFileNotFound()){
  36. timerNormal = setInterval(rel, RELOAD_INTERVAL_NORMAL);
  37. }
  38.  
  39. soudane();
  40. makeFormClearButton();
  41. reset_title();
  42. make_live_button();
  43.  
  44. function isFileNotFound() {
  45. if(document.title == "404 File Not Found") {
  46. return true;
  47. }
  48. else {
  49. console.log(script_name + ": Start auto reloading @" + url);
  50. return false;
  51. }
  52. }
  53.  
  54. function make_live_button() {
  55. liveButton = document.createElement("a");
  56. liveButton.id = "relButton";
  57. liveButton.style.cursor = 'pointer';
  58. liveButton.innerHTML = "[実況モード(Ctrl+" + String.fromCharCode(LIVE_TOGGLE_KEY) + ")]";
  59.  
  60. var input = document.evaluate(
  61. "//input[@value='返信する' or @value='送信する']",
  62. document,
  63. null,
  64. XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,
  65. null);
  66.  
  67. for (var i = 0; i < input.snapshotLength; i++) {
  68. var submit = input.snapshotItem(i);
  69. var tr = submit.parentNode;
  70. tr.appendChild(liveButton);
  71. liveButton.addEventListener("click", liveMode, true);
  72. }
  73.  
  74. //実況モードトグルショートカットキー
  75. window.addEventListener("keydown",function(e) {
  76. if ( e.ctrlKey && e.keyCode == LIVE_TOGGLE_KEY ) {
  77. liveMode();
  78. }
  79. }, false);
  80. }
  81.  
  82. /*
  83. * 実況モード
  84. * メソッド呼出ごとにON/OFFトグル
  85. */
  86. function liveMode() {
  87. if (!live_flag) {
  88. //実況モード時リロード
  89. timerLiveReload = setInterval(rel_scroll, RELOAD_INTERVAL_LIVE);
  90. //自動スクロール
  91. timerLiveScroll = setInterval(live_scroll, LIVE_SCROLL_INTERVAL);
  92. liveButton.style.backgroundColor = '#ffa5f0';
  93. console.log(script_name + ": Start live mode @" + url);
  94. live_flag = true;
  95. } else {
  96. clearInterval(timerLiveReload);
  97. clearInterval(timerLiveScroll);
  98. liveButton.style.background = 'none';
  99. console.log(script_name + ": Stop live mode @" + url);
  100. live_flag = false;
  101. }
  102.  
  103. //新着スクロール
  104. function rel_scroll() {
  105. $('html, body').animate(
  106. {scrollTop:window.scrollMaxY},"fast"
  107. );
  108. if(isAkahukuNotFound()){
  109. //404時
  110. liveMode();
  111. }
  112. else {
  113. location.reload();
  114. }
  115. }
  116.  
  117. function live_scroll() {
  118. window.scrollBy( 0, LIVE_SCROLL_SPEED );
  119. }
  120. }
  121.  
  122. /*
  123. * 新着レスをリセット
  124. */
  125. function reset_title() {
  126. //ページ末尾でホイールダウンした時
  127. window.addEventListener("DOMMouseScroll",function scroll(event) {
  128. var window_y = window.scrollY;
  129. var window_ymax = window.scrollMaxY;
  130. if (event.detail > 0 && window_y >= window_ymax) {
  131. reset_titlename();
  132. }
  133. return;
  134. } ,false);
  135. //F5キー押された時
  136. window.addEventListener("keydown",function(e) {
  137. if ( e.keyCode == "116" ) {
  138. reset_titlename();
  139. }
  140. }, false);
  141.  
  142. function reset_titlename() {
  143. res = 0;
  144. var title_char = title_name();
  145. document.title = title_char;
  146. }
  147. }
  148.  
  149. function rel() {
  150. soudane();
  151. setTimeout(changetitle, 1000);
  152. if(isAkahukuNotFound()){
  153. //404時
  154. clearInterval(timerNormal);
  155. console.log(script_name + ": Page not found, Stop auto reloading @" + url);
  156. }
  157. else {
  158. location.reload();
  159. }
  160. }
  161.  
  162. /*
  163. * そうだねの数に応じてレスを着色
  164. */
  165. function soudane() {
  166. if ( USE_SOUDANE ) {
  167. $("td > .sod").each(function(){
  168. var sodnum = $(this).text().match(/\d+/);
  169. if (sodnum){
  170. var col = "rgb(180, 240," + (Math.round(10 * sodnum + 180)) + ")";
  171. $(this).parent().css("background-color", col);
  172. }
  173. });
  174. }
  175. }
  176.  
  177. /*
  178. * タブタイトルに新着レス数・スレ消滅状態を表示
  179. */
  180. function changetitle() {
  181. if ( USE_TITLE_NAME ) {
  182. var title_char = title_name();
  183. var newres = $("#akahuku_new_reply_header_number").text();
  184. if (isAkahukuNotFound()) {
  185. document.title = "#" + title_char;
  186. } else {
  187. if(newres) {
  188. res += parseInt(newres);
  189. }
  190. if ( res !== 0) {
  191. document.title = "(" + res + ")" + title_char;
  192. }
  193. }
  194. }
  195. }
  196.  
  197. /*
  198. * 赤福のステータスからスレ消滅状態をチェック
  199. */
  200. function isAkahukuNotFound() {
  201. var statustext = $("#akahuku_reload_status").text();
  202. if (statustext.match(/(No Future)|((M|N)ot Found)/)) {
  203. return true;
  204. }
  205. else {
  206. return false;
  207. }
  208. }
  209.  
  210. function title_name() {
  211. var title = document.title;
  212. var title_num = title.match(/^(#|\(\d+\))/);
  213. var title_num_length;
  214. if(!title_num){
  215. title_num_length = 0;
  216. }
  217. else {
  218. title_num_length = title_num[0].length;
  219. }
  220. var act_title_name = title.substr(title_num_length);
  221. return act_title_name;
  222. }
  223.  
  224. function makeFormClearButton() {
  225. if ( USE_CLEAR_BUTTON ) {
  226. var $formClearButton = $("<div>", {
  227. id: "formClearButton",
  228. text: "[クリア]",
  229. css: {
  230. cursor: "pointer",
  231. margin: "0 5px"
  232. },
  233. click: function() {
  234. clearForm();
  235. }
  236. });
  237. var $comeTd = $(".ftdc b:contains('コメント')");
  238. $comeTd.after($formClearButton);
  239. }
  240.  
  241. function clearForm() {
  242. $("#ftxa").val("");
  243. }
  244. }
  245.  
  246. })(jQuery);