futaba auto reloader

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

当前为 2015-08-11 提交的版本,查看 最新版本

  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.4
  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 Alt)
  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. formSizeFixForFx40();
  44.  
  45. function isFileNotFound() {
  46. if(document.title == "404 File Not Found") {
  47. return true;
  48. }
  49. else {
  50. console.log(script_name + ": Start auto reloading @" + url);
  51. return false;
  52. }
  53. }
  54.  
  55. function make_live_button() {
  56. liveButton = document.createElement("a");
  57. liveButton.id = "relButton";
  58. liveButton.style.cursor = 'pointer';
  59. liveButton.innerHTML = "[実況モード(Alt+" + String.fromCharCode(LIVE_TOGGLE_KEY) + ")]";
  60.  
  61. var input = document.evaluate(
  62. "//input[@value='返信する' or @value='送信する']",
  63. document,
  64. null,
  65. XPathResult.ORDERED_NODE_SNAPSHOT_TYPE,
  66. null);
  67.  
  68. for (var i = 0; i < input.snapshotLength; i++) {
  69. var submit = input.snapshotItem(i);
  70. var tr = submit.parentNode;
  71. tr.appendChild(liveButton);
  72. liveButton.addEventListener("click", liveMode, true);
  73. }
  74.  
  75. //実況モードトグルショートカットキー
  76. window.addEventListener("keydown",function(e) {
  77. if ( e.altKey && e.keyCode == LIVE_TOGGLE_KEY ) {
  78. liveMode();
  79. }
  80. }, false);
  81. }
  82.  
  83. /*
  84. * 実況モード
  85. * メソッド呼出ごとにON/OFFトグル
  86. */
  87. function liveMode() {
  88. if (!live_flag) {
  89. //実況モード時リロード
  90. timerLiveReload = setInterval(rel_scroll, RELOAD_INTERVAL_LIVE);
  91. //自動スクロール
  92. timerLiveScroll = setInterval(live_scroll, LIVE_SCROLL_INTERVAL);
  93. liveButton.style.backgroundColor = '#ffa5f0';
  94. console.log(script_name + ": Start live mode @" + url);
  95. live_flag = true;
  96. } else {
  97. clearInterval(timerLiveReload);
  98. clearInterval(timerLiveScroll);
  99. liveButton.style.background = 'none';
  100. console.log(script_name + ": Stop live mode @" + url);
  101. live_flag = false;
  102. }
  103.  
  104. //新着スクロール
  105. function rel_scroll() {
  106. $('html, body').animate(
  107. {scrollTop:window.scrollMaxY},"fast"
  108. );
  109. if(isAkahukuNotFound()){
  110. //404時
  111. liveMode();
  112. }
  113. else {
  114. location.reload();
  115. }
  116. }
  117.  
  118. function live_scroll() {
  119. window.scrollBy( 0, LIVE_SCROLL_SPEED );
  120. }
  121. }
  122.  
  123. /*
  124. * 新着レスをリセット
  125. */
  126. function reset_title() {
  127. //ページ末尾でホイールダウンした時
  128. window.addEventListener("DOMMouseScroll",function scroll(event) {
  129. var window_y = window.scrollY;
  130. var window_ymax = window.scrollMaxY;
  131. if (event.detail > 0 && window_y >= window_ymax) {
  132. reset_titlename();
  133. }
  134. return;
  135. } ,false);
  136. //F5キー押された時
  137. window.addEventListener("keydown",function(e) {
  138. if ( e.keyCode == "116" ) {
  139. reset_titlename();
  140. }
  141. }, false);
  142.  
  143. function reset_titlename() {
  144. res = 0;
  145. var title_char = title_name();
  146. document.title = title_char;
  147. }
  148. }
  149.  
  150. function rel() {
  151. soudane();
  152. setTimeout(changetitle, 1000);
  153. if(isAkahukuNotFound()){
  154. //404時
  155. clearInterval(timerNormal);
  156. console.log(script_name + ": Page not found, Stop auto reloading @" + url);
  157. }
  158. else {
  159. location.reload();
  160. }
  161. }
  162.  
  163. /*
  164. * そうだねの数に応じてレスを着色
  165. */
  166. function soudane() {
  167. if ( USE_SOUDANE ) {
  168. $("td > .sod").each(function(){
  169. var sodnum = $(this).text().match(/\d+/);
  170. if (sodnum){
  171. var col = "rgb(180, 240," + (Math.round(10 * sodnum + 180)) + ")";
  172. $(this).parent().css("background-color", col);
  173. }
  174. });
  175. }
  176. }
  177.  
  178. /*
  179. * タブタイトルに新着レス数・スレ消滅状態を表示
  180. */
  181. function changetitle() {
  182. if ( USE_TITLE_NAME ) {
  183. var title_char = title_name();
  184. var newres = $("#akahuku_new_reply_header_number").text();
  185. if (isAkahukuNotFound()) {
  186. document.title = "#" + title_char;
  187. } else {
  188. if(newres) {
  189. res += parseInt(newres);
  190. }
  191. if ( res !== 0) {
  192. document.title = "(" + res + ")" + title_char;
  193. }
  194. }
  195. }
  196. }
  197.  
  198. /*
  199. * 赤福のステータスからスレ消滅状態をチェック
  200. */
  201. function isAkahukuNotFound() {
  202. var statustext = $("#akahuku_reload_status").text();
  203. if (statustext.match(/(No Future)|((M|N)ot Found)/)) {
  204. return true;
  205. }
  206. else {
  207. return false;
  208. }
  209. }
  210.  
  211. function title_name() {
  212. var title = document.title;
  213. var title_num = title.match(/^(#|\(\d+\))/);
  214. var title_num_length;
  215. if(!title_num){
  216. title_num_length = 0;
  217. }
  218. else {
  219. title_num_length = title_num[0].length;
  220. }
  221. var act_title_name = title.substr(title_num_length);
  222. return act_title_name;
  223. }
  224.  
  225. function makeFormClearButton() {
  226. if ( USE_CLEAR_BUTTON ) {
  227. var $formClearButton = $("<div>", {
  228. id: "formClearButton",
  229. text: "[クリア]",
  230. css: {
  231. cursor: "pointer",
  232. margin: "0 5px"
  233. },
  234. click: function() {
  235. clearForm();
  236. }
  237. });
  238. var $comeTd = $(".ftdc b:contains('コメント')");
  239. $comeTd.after($formClearButton);
  240. }
  241.  
  242. function clearForm() {
  243. $("#ftxa").val("");
  244. }
  245. }
  246.  
  247. function formSizeFixForFx40() {
  248. $("input[name='name']").css("width", "15em");
  249. $("input[name='email']").css("width", "15em");
  250. $("input[name='sub']").css("width", "18em");
  251. }
  252.  
  253. })(jQuery);