HAYLoader

An automatic page refresher for Ponychan

  1. // ==UserScript==
  2. // @name HAYLoader
  3. // @namespace Ponychan.net
  4. // @description An automatic page refresher for Ponychan
  5. // @include http://www.ponychan.net/chan/*/*
  6. // @version 1.00
  7. // @grant metadata
  8. // ==/UserScript==
  9.  
  10. var HAYmenuTitle = '<a id=\"haymenutitle\" class=\"adminbaritem\" >HAY ▼</a>';
  11. document.getElementById('mainmenu').innerHTML = HAYmenuTitle + document.getElementById('mainmenu').innerHTML;
  12. document.getElementById('haymenutitle').addEventListener('click', HAYmenuClick, false);
  13. var HAYrefreshTime = parseInt(localStorage.HAYrefreshTime)>1?localStorage.HAYrefreshTime*1000:"15000";
  14. var refreshTimer = setInterval(HAYcleanRefresh, HAYrefreshTime);
  15. var HAYtimezone;
  16. var HAYtwentyfourhour;
  17. try{
  18. HAYtimezone = window.Ponychan.settings.get("time-zone");
  19. HAYtwentyfourhour = window.Ponychan.settings.get("twelve-hour");
  20. }catch(e){
  21. HAYtimezone = localStorage.HAYtimezone?localStorage.HAYtimezone:"0";
  22. HAYtwentyfourhour = localStorage.HAYtwentyfourhour?localStorage.HAYtwentyfourhour:"false";
  23. }
  24. var HAYunread = 0;
  25. var HAYpageTitle = document.title;
  26. var HAYunfocused = false;
  27.  
  28. HAYcreateQuickReply();
  29. document.getElementById("HAYQRmover").addEventListener("mousedown",HAYDownQuickReply, false);
  30. document.getElementById("HAYQRmover").addEventListener("mouseup", HAYUpQuickReply, false);
  31. document.addEventListener("mousemove", HAYdragQuickReply, false);
  32. window.addEventListener("blur", function(){HAYunfocused=true;});
  33. document.body.addEventListener("mouseout", function(){HAYunfocused=true;});
  34. document.body.addEventListener("mouseover", function(){HAYunfocused=false; HAYunread = 0; document.title = HAYpageTitle;});
  35. window.addEventListener("focus", function(){HAYunfocused=false; HAYunread = 0; document.title = HAYpageTitle;});
  36. window.scrollTo(0, document.body.clientHeight);
  37.  
  38. //make the page refresh cleanly
  39. function HAYcleanRefresh(){
  40. var req = new XMLHttpRequest();
  41. req.open("GET", location.href, true);
  42. req.onreadystatechange=function(){
  43. if(req.readyState == 4 && (req.status == 200 || req.status == 302)){
  44. var res = req.responseText;
  45. var tabls = document.getElementById("firstpageinside").getElementsByTagName("TABLE");
  46. var lastKnownPost = tabls[tabls.length-1].children[0].children[0].children[1].id;
  47. var parser = new DOMParser();
  48. var doc;
  49. doc = parser.parseFromString(res, "text/html"); //my original FF implementation
  50. if(doc == null) { //chromium workaround
  51. doc = document.implementation.createHTMLDocument();
  52. doc.write(res);
  53. }
  54. var addedElements = new Array();
  55. var tabls2 = doc.getElementById("firstpageinside").getElementsByTagName("TABLE");
  56. var j = tabls2.length-1;
  57. var adopted = new Array();
  58. while(j>0 && tabls2[j].children[0].children[0].children[1].id!=lastKnownPost){
  59. adopted.push(document.importNode(tabls2[j], true));
  60. j--;
  61. }
  62. while(adopted.length>0){
  63. var currentNode = adopted.pop();
  64. currentNode.getElementsByClassName("posttime")[0].innerHTML = correctTime(currentNode);
  65. HAYcollectReplies(currentNode);
  66. HAYgetPreviews(currentNode);
  67. HAYplayGIF(currentNode);
  68. HAYinsertLinks(currentNode);
  69. tabls[tabls.length-1].parentNode.insertBefore(currentNode,tabls[tabls.length-1].nextSibling);
  70. if(currentNode.getElementsByClassName("postername")[0].children[0]!=null){
  71. if(currentNode.getElementsByClassName("postername")[0].children[0].innerHTML != document.getElementsByname("name")[0].value) HAYunread++;
  72. //console.log("link: " + currentNode.getElementByClassName("postername")[0].children[0].innerHTML + ", " + document.getElementsByName("name")[0].value);
  73. }else{
  74. if(currentNode.getElementsByClassName("postername")[0].innerHTML != document.getElementsByName("name")[0].value) HAYunread++;
  75. //console.log("no link: " + currentNode.getElementsByClassName("postername")[0].innerHTML + ", " + document.getElementsByName("name")[0].value);
  76. }
  77. }
  78. if(HAYunread>0 && HAYunfocused == true){
  79. document.title = HAYpageTitle + " (" + HAYunread + ")";
  80. window.scrollTo(window.pageXOffset, document.body.scrollHeight);
  81. }
  82. document.getElementById("errorArea").innerHTML = "";
  83. }else if(req.readyState == 4 && !(req.status == 200 || req.status == 302)){
  84. document.getElementById("errorArea").innerHTML = "A recieving error has occurred: " + req.status;
  85. }
  86. }
  87. req.send();
  88. }
  89.  
  90. //make the page send cleanly
  91. function HAYcleanSend(){
  92. var req = new XMLHttpRequest();
  93. req.open("POST","http://www.ponychan.net/chan/board.php", true);
  94. req.onreadystatechange=function(){
  95. if(req.readyState == 4 && (req.status == 200 || req.status == 302)){
  96. document.getElementsByName("message")[0].value="";
  97. document.getElementsByName("imagefile")[0].value="";
  98. document.getElementById("quickmessage").value="";
  99. HAYcleanRefresh();
  100. }else if(req.readyState == 4 && !(req.status == 200 || req.status == 302)){
  101. document.getElementById("errorArea").innerHTML = "A sending error has occurred: " + req.status;
  102. }
  103. document.getElementById("quicksubmit").disabled = false;
  104. document.getElementById("quicksubmit").innerHTML = "Reply";
  105. }
  106. document.getElementById("quicksubmit").disabled = true;
  107. document.getElementById("quicksubmit").innerHTML = "Sending...";
  108. req.send(new FormData(document.getElementById("postform")));
  109. }
  110.  
  111. //runs HAYcollectReplies in a timed fashion
  112. //watch it. If you screw up any function called by this function then they will all go wacky.
  113. var HAYlinkruns = 0;
  114. var HAYlinkcomplete = document.getElementById("firstpageinside").getElementsByTagName("TABLE").length-1;
  115. var HAYruninterval = setInterval(HAYtraverseLinks, 200);
  116. function HAYtraverseLinks(){
  117. var tabls = document.getElementById("firstpageinside").getElementsByTagName("TABLE");
  118. var fromPageBottom = document.body.scrollHeight - window.pageYOffset;
  119. for(var i = 0;HAYlinkruns<HAYlinkcomplete && i<50; i++,HAYlinkruns++){
  120. HAYcollectReplies(tabls[HAYlinkcomplete - HAYlinkruns]);
  121. HAYplayGIF(tabls[HAYlinkcomplete - HAYlinkruns]);
  122. HAYinsertLinks(tabls[HAYlinkcomplete - HAYlinkruns]);
  123. }
  124. if(document.body.scrollHeight - fromPageBottom > 100) window.scrollTo(window.pageXOffset, document.body.scrollHeight - fromPageBottom);
  125. if(HAYlinkruns>=HAYlinkcomplete){
  126. clearInterval(HAYruninterval);
  127. }
  128. }
  129.  
  130. //moves the quick reply box
  131. var HAYxOffset = 0;
  132. var HAYyOffset = 0;
  133. var QRdrag = false;
  134. function HAYdragQuickReply(pos){
  135. if(QRdrag == true){
  136. var quickReply = document.getElementById("HAYquickReply");
  137. if(HAYxOffset == 0){
  138. HAYxOffset = pos.clientX - quickReply.style.left.substr(0, quickReply.style.left.length - 2);
  139. HAYyOffset = pos.clientY - quickReply.style.top.substr(0, quickReply.style.top.length - 2);
  140. //console.log("%i - %i = %i, %i - %i = %i", pos.clientX, quickReply.style.left, HAYxOffset, pos.clientY, quickReply.style.top, HAYyOffset);
  141. }else{
  142. quickReply.style.left = new String(pos.clientX - HAYxOffset).concat("px");
  143. quickReply.style.top = new String(pos.clientY - HAYyOffset).concat("px");
  144. }
  145. window.getSelection().removeAllRanges();
  146. }
  147. }
  148. function HAYDownQuickReply(){
  149. QRdrag = true;
  150. }
  151. function HAYUpQuickReply(){
  152. QRdrag = false;
  153. HAYxOffset = 0;
  154. HAYyOffset = 0;
  155. }
  156.  
  157. //will poll and make sure reply forms are the same
  158. var matchReplies = "quickmessage"; //the reply box being used: message or quickmessage
  159. setInterval(HAYmatchReplies, 200);
  160. function HAYmatchReplies(){
  161. if(matchReplies == "message"){
  162. document.getElementById("quickmessage").value = document.forms.postform.message.value;
  163. document.getElementById("quickimagefile").value = document.forms.postform.imagefile.value.substring(document.forms.postform.imagefile.value.lastIndexOf("/")==-1?document.forms.postform.imagefile.value.lastIndexOf("\\"):document.forms.postform.imagefile.value.lastIndexOf("/"));
  164. }else if(matchReplies == "quickmessage"){
  165. document.forms.postform.message.value = document.getElementById("quickmessage").value;
  166. document.getElementById("quickimagefile").value = document.forms.postform.imagefile.value.substring(document.forms.postform.imagefile.value.lastIndexOf("/")==-1?document.forms.postform.imagefile.value.lastIndexOf("\\"):document.forms.postform.imagefile.value.lastIndexOf("/"));
  167. }
  168. }
  169.  
  170. //creates the quick reply box
  171. function HAYcreateQuickReply(){
  172. var quickReply = document.createElement("DIV");
  173. quickReply.id = "HAYquickReply";
  174. quickReply.setAttribute("class","postblock");
  175. quickReply.setAttribute("style","display:block;position:fixed;padding: 0px 2px 2px;");
  176. quickReply.style.left = new String(window.innerWdith*0.6>window.innerWidth - 530?window.innerWidth*0.6:window.innerWidth - 530).concat("px");
  177. quickReply.style.top = "50px";
  178. quickReply.innerHTML="<div id=\"HAYQRmover\" style=\"font-family:Sans-Serif;text-align:center;cursor:default\" class=\"postername\">HAYcreatequickreply</div><div id=\"errorArea\" style=\"font-weight:bold;color:#992222;\"></div><textarea id=\"quickmessage\" style=\"font-family:Serif;height:150px;width:484px\"></textarea><br \><textarea style=\"height:18px;width:344px;\" multiline=\"false\" id=\"quickimagefile\" disabled></textarea><button type=\"button\" style=\"width:70px;height:26px;vertical-align:top;\" id=\"quickimagefilebutton\">Browse</button><button type=\"button\" style=\"height:26px;width:70px;position:fixed;vertical-align:top\" id=\"quicksubmit\">Reply</button>";
  179. document.getElementById("firstpageinside").appendChild(quickReply);
  180. document.getElementById("quickmessage").addEventListener("focus", function(){matchReplies = "quickmessage"}, false);
  181. document.forms.postform.message.addEventListener("focus", function(){matchReplies = "message"}, false);
  182. document.getElementById("quickimagefile").addEventListener("click", function(){document.forms.postform.imagefile.click();matchReplies = "quickmessage"}, false);
  183. document.getElementById("quickimagefilebutton").addEventListener("click", function(){document.forms.postform.imagefile.click();matchReplies = "quickmessage"}, false);
  184. document.forms.postform.imagefile.addEventListener("focus", function(){matchReplies = "message"}, false);
  185. document.getElementById("quickmessage").addEventListener("blur", function(){matchReplies = "null"}, false);
  186. document.forms.postform.message.addEventListener("blur", function(){matchReplies = "null"}, false);
  187. document.forms.postform.imagefile.addEventListener("blur", function(){matchReplies = "null"}, false);
  188. document.getElementById("quicksubmit").addEventListener("click", HAYcleanSend, false);
  189. }
  190.  
  191. //make the HAYmenu drop down
  192. var menuClosed = true;
  193. var HAYmenu = document.createElement('div');
  194. HAYmenu.id = 'haymenu';
  195. function HAYmenuClick(){
  196. var menuRect = document.getElementById('haymenutitle').getBoundingClientRect();
  197. var HAYmenuStyle = "position:fixed;top:" + menuRect.bottom + "px;left:" + menuRect.left + "px;display:block;padding:4px;";
  198. HAYmenu.setAttribute("style", HAYmenuStyle);
  199. HAYmenu.setAttribute('class', 'darkbar');
  200. var refreshTime = localStorage.HAYrefreshTime!=null?localStorage.HAYrefreshTime:"20";
  201. if(menuClosed == true){
  202. document.getElementById('verytopbar').insertBefore(HAYmenu,document.getElementById('homedropdown'));
  203. HAYmenu.innerHTML = "Refresh Time:<br><input type=\"text\" size=\"3\" value=\"" + refreshTime + "\" id=\"HAYrefreshTime\"></input>Seconds<br>"
  204. try{
  205. HAYmenu.innerHTML = HAYmenu.innerHTML + "24-hour time: <input type=\"checkbox\" " + (HAYtwentyfourhour=="true"?"checked":"") + " id=\"HAYtwentyfourhour\" /><br>Timezone:<input type=\"text\" value=\"" + HAYtimezone + "\" size=3 id=\"HAYtimezone\" /><br>";
  206. }catch(e){
  207. HAYmenu.innerHTML = HAYmenu.innerHTML + "24-hour time: <input type=\"checkbox\" id=\"HAYtwentyfourhour\" /><br>Timezone:<input type=\"text\" value=\"0\" size=3 id=\"HAYtimezone\" /><br>";
  208. }
  209. var apply = document.createElement("button");
  210. apply.type = "button";
  211. apply.innerHTML = "APPLY";
  212. HAYmenu.appendChild(apply);
  213. apply.addEventListener("click", function(){
  214. localStorage.HAYrefreshTime = parseInt(document.getElementById("HAYrefreshTime").value);
  215. localStorage.HAYtimezone = parseInt(document.getElementById("HAYtimezone").value);
  216. localStorage.HAYtwentyfourhour = document.getElementById("HAYtwentyfourhour").checked;
  217. window.location.reload();
  218. });
  219. document.getElementById('haymenutitle').innerHTML='HAY ▲';
  220. menuClosed = false;
  221. }else{
  222. HAYmenu.parentNode.removeChild(HAYmenu);
  223. document.getElementById('haymenutitle').innerHTML='HAY ▼';
  224. menuClosed = true;
  225. }
  226. }
  227.  
  228. //here is a function to correct the time on the posts
  229. function correctTime(elem){
  230. var timezone;
  231. var twentyfourhour;
  232. try{
  233. timezone = window.Ponychan.settings.get("time-zone") + 8;
  234. twentyfourhour = window.Ponychan.settings.get("twelve-hour");
  235. }catch(e){ //fallback settings for dumb browsers
  236. timezone = HAYtimezone!=null && HAYtimezone!="NaN" && HAYtimezone < 12 && HAYtimezone >-12?parseInt(HAYtimezone) + 8:"8";
  237. twentyfourhour = HAYtwentyfourhour!=null?HAYtwentyfourhour:"false";
  238. }
  239. var postTime = elem.getElementsByClassName("posttime")[0].innerHTML.substring(5,26);
  240. var postDay = postTime.charAt(5)>='0' && postTime.charAt(5)<='9'?postTime.substring(4,6):postTime.substring(4,5);
  241. var postYear = postDay<10?postTime.substring(9,13):postTime.substring(10, 14);
  242. var postMonth = postTime.substring(0, 3);
  243. postMonth = postMonth=="Jan"?0:postMonth=="Feb"?1:postMonth=="Mar"?2:postMonth=="Apr"?3:postMonth=="May"?4:postMonth=="Jun"?5:postMonth=="Jul"?6:postMonth=="Aug"?7:postMonth=="Sep"?8:postMonth=="Oct"?9:postMonth=="Nov"?10:postMonth=="Dec"?11:postMonth;
  244. var postHour = postDay<10?postTime.substring(14,16):postTime.substring(15,17);
  245. var postMinute = postDay<10?postTime.substring(17,19):postTime.substring(18,20);
  246. var finalDate = new Date(new Date(postYear, postMonth, postDay, postHour, postMinute).getTime()+(3600000*timezone));
  247. var dateString = finalDate.toString().substring(0,3) + ", " + finalDate.toString().substring(4,10) + ", " + finalDate.getFullYear() + " ";
  248. //console.log(postTime + ", " + (postTime.charAt(6)>='0' && postTime.charAt(6)<='9') + " " + postYear + " " + postMonth + " " + postHour + " " + postMinute + " " + finalDate.toString() + " " + timezone);
  249. if(twentyfourhour==false){
  250. dateString = dateString + finalDate.toString().substring(16, 18) + ":" + finalDate.toString().substring(19,21);
  251. }else{
  252. dateString = dateString + (finalDate.getHours()>12?finalDate.getHours()-12:finalDate.toString().substring(16,18)) + ":" + finalDate.toString().substring(19,21) + " <span style=\"font-size:0.75em\">" + (finalDate.getHours()>12?"PM":"AM") + "</span>";
  253. }
  254. return dateString;
  255. }
  256.  
  257. //this function will create links to any post that replies to this one.
  258. function HAYcollectReplies(elem){
  259. var links = elem.getElementsByTagName("a");
  260. var linklength = links.length;
  261. for(var i = 0; i<linklength; i++){
  262. if(links[i].innerHTML.trim().substr(0,8) == "&gt;&gt;"){
  263. if(links[i].innerHTML.trim().substr(8)<elem.children[0].children[0].children[1].id.trim().substr(5)){
  264. try{
  265. var illink = document.createElement("a");
  266. illink.href = window.location.href.substr(0, (window.location.href.lastIndexOf("#")>0?window.location.href.lastIndexOf("#"):window.location.href.length)) + "#" + elem.getElementsByClassName("reflink")[0].children[1].innerHTML;
  267. illink.innerHTML = ">>" + elem.getElementsByClassName("reflink")[0].children[1].innerHTML;
  268. illink.setAttribute("style", "font-size:9pt;color:rgb(0,16,176);");
  269. illink.addEventListener("mouseover", HAYaddRefLinkPreview);
  270. illink.addEventListener("mouseout", HAYdelRefLinkPreview);
  271. document.getElementById("reply" + links[i].innerHTML.trim().substr(8)).children[2].appendChild(illink);
  272. }catch(e){
  273. }
  274. }
  275. }
  276. }
  277. }
  278.  
  279. //replaces the post links that insert links to the quickmessage box. Makes them work myway.
  280. function HAYinsertLinks(elem){
  281. var links = elem.getElementsByClassName("reflink")[0].getElementsByTagName("a");
  282. var linkslength = links.length;
  283. if(linkslength > 0){
  284. for(var i = 0; i<linkslength; i++){
  285. if(links[i].innerHTML.trim().substr(0,8)!="&gt;&gt;"){
  286. //console.log("fixing: " + links[i].innerHTML);
  287. var newlink = document.createElement("a");
  288. newlink.innerHTML = links[i].innerHTML;
  289. newlink.href = links[i].href;
  290. newlink.addEventListener("click", function(e){
  291. e.preventDefault();
  292. var n = document.getElementById("quickmessage");
  293. var text = n.value;
  294. var link = e.target.href.substring(e.target.href.lastIndexOf("#") + 1);
  295. if(link.substr(0,1) == "i") link = link.substr(1);
  296. text = text + ">>" + link + "\n";
  297. n.value = text;
  298. n.setSelectionRange(n.value.length, n.value.length);
  299. n.focus();
  300. });
  301. links[i].parentNode.replaceChild(newlink, links[i]);
  302. }
  303. }
  304. }
  305. }
  306.  
  307. //my function to add the previews when hovering postlinks. I've replaced the kubasa functions.
  308. function HAYgetPreviews(elem){
  309. var links = elem.getElementsByTagName("a");
  310. var i = 0;
  311. while(i<links.length){
  312. if(links[i].innerHTML.trim().substring(0,8) == "&gt;&gt;"){
  313. try{
  314. links[i].addEventListener("mouseover", HAYaddRefLinkPreview);
  315. links[i].addEventListener("mouseout", HAYdelRefLinkPreview);
  316. }catch(e){
  317. }
  318. }
  319. i++;
  320. }
  321. }
  322.  
  323. //here is an addreflinkpreview, I didn't override because chrome get's a bit wacky so I'm rewriting myown.
  324. function HAYaddRefLinkPreview(e){
  325. HAYunfocused = false;
  326. var tab = document.createElement("div");
  327. tab.id = "HAYpreviewThingo";
  328. tab.innerHTML = document.getElementById("reply" + e.target.innerHTML.trim().substring(8)).innerHTML;
  329. var pos = e.target.getBoundingClientRect();
  330. tab.style.position = "fixed";
  331. tab.style.top = (pos.bottom + 14) + "px";
  332. tab.style.left = pos.right + "px";
  333. tab.className="reflinkpreview";
  334. tab.style.BoxShadow = "4px 4px 2px #888888";
  335. tab.getElementsByClassName("postfooter")[0].parentNode.removeChild(tab.getElementsByClassName("postfooter")[0]);
  336. tab.getElementsByClassName("reflink")[0].parentNode.removeChild(tab.getElementsByClassName("reflink")[0]);
  337. document.body.appendChild(tab);
  338. }
  339.  
  340. //here is the delreflinkprewiew, no override again. writing it myself.
  341. function HAYdelRefLinkPreview(e){
  342. HAYunfocused = true;
  343. document.body.removeChild(document.getElementById("HAYpreviewThingo"));
  344. }
  345. //play the gifs using HAYtraverseLinks to go through them timingly
  346. function HAYplayGIF(elem){
  347. pic = elem.getElementsByClassName("thumb")[0];
  348. if(pic!=null){
  349. if(pic.src.substr(pic.src.length - 3).toLowerCase() == "gif"){
  350. var rgif = document.createElement("img");
  351. rgif.style.height = "125px";
  352. rgif.style.width = "125px";
  353. rgif.src = pic.parentNode.parentNode.href;
  354. rgif.style.display = "none";
  355. rgif.setAttribute("class", "thumb");
  356. rgif.addEventListener("load", function(e){
  357. var g = 0;
  358. var rgif = e.target;
  359. var fromPageBottom = document.body.scrollHeight - window.pageYOffset;
  360. if(rgif.height > rgif.width){
  361. g = rgif.height/125;
  362. }else{
  363. g = rgif.width/125;
  364. }
  365. if(g>0){
  366. rgif.setAttribute("style","height:" + rgif.height/g + "px;width:" + rgif.width/g + "px:float:left");
  367. }
  368. rgif.style.display="block";
  369. if(document.body.scrollHeight - fromPageBottom > 100) window.scrollTo(window.pageXOffset, document.body.scrollHeight - fromPageBottom);
  370. });
  371. pic.parentNode.replaceChild(rgif, pic);
  372. }
  373. }
  374. }