freecadForumDoomScroll.user.js 5.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190
  1. // ==UserScript==
  2. // @name freecadweb.org doom scroll
  3. // @description to infiniti and beyond
  4. // @author github.com/ipatch
  5. // @namespace Violentmonkey Scripts
  6. // @homepageURL https://github.com/ipatch/dotfiles
  7. // @supportURL https://github.com/ipatch/dotfiles/issues
  8. // @icon
  9. // @match https://forum.freecadweb.org/viewtopic.php*
  10. // @exclude-match https://forum.freecadweb.org/posting.php*
  11. // @grant GM.*
  12. // @grant GM_*
  13. // @run-at document-end
  14. // @version 1.0.32
  15. // @downloadURL http://localhost/~/capin/freecadForumDoomScroll.user.js
  16. // @updateURL http://localhost/~/capin/freecadForumDoomScroll.user.js
  17. // ==/UserScript==
  18. (function () {
  19. 'use strict';
  20. // TODO: the URL and page number need to be updated after a page is loaded, ie.
  21. // as this presently works the contents of page 2 will load into the dom but page 1
  22. // will still appear to be the active page (button) and the URL in the address
  23. // bar nees to be updated accordingly
  24. // NOTE: version number may require bumping on intial load to read updates
  25. //
  26. // REF: https://www.youtube.com/watch?v=Al-ZSuVHHM8 <- debounce explanation
  27. // REF: https://www.youtube.com/watch?v=T8EYosX4NOo <- intersect observer
  28. // REF: https://www.w3schools.com/xml/xml_http.asp
  29. // REF: https://code-boxx.com/infinite-page-scroll/
  30. // REF: https://medium.com/better-programming/everything-about-xmlhttprequest-in-javascript-8adacc98a209
  31. // REF: https://www.youtube.com/watch?v=4K33w-0-p2c
  32. // REF: https://openuserjs.org/scripts/tumpio/Endless_Google
  33. // REF: https://wiki.greasespot.net/Tutorials
  34. //
  35. // console.log('w00t'); // DEBUG
  36. //
  37. // NOTE: i believe first topic of thread is indexed at `1` and page 2, ie. post 10 refers to the 11th post of a thread, but is the 10th reply
  38. // NOTE: pg2 button puts `&start=10` at the end of the `viewtopic.php` URL
  39. // NOTE: pg2 contains replies 10 through 19, ie. each page has 10 posts
  40. // EXAMPLES, tests /*{{{*/
  41. //------------------------------------
  42. console.log('violentmonkey, doom scroll hello!');
  43. // exp
  44. var mlife = 43;
  45. unsafeWindow.iVar1 = mlife;
  46. //---------------------------------------
  47. //
  48. // NOTE; able to access function via browser console for testing
  49. var multiplyES5 = function(x, y) {
  50. return x * y;
  51. };
  52. unsafeWindow.iVar2 = multiplyES5;
  53. //--------------------------------------------------
  54. //
  55. // NOTE: arrow func works with latest ver of Vivaldi
  56. // es6, fat arrow function, (arrow function)
  57. const multiplyES6 = (x, y) => {
  58. return x * y;
  59. };
  60. unsafeWindow.iVar3 = multiplyES6;
  61. //*}}}*/
  62. // XMLHttpRequest example ----------- {{{
  63. // 1. define URL
  64. // 2. define request object
  65. // 3. open request, ie. use GET or POST
  66. // 4. use `onload` function log results
  67. // 5. set `responseType` ie. document (HTML), JSON
  68. // https://developer.mozilla.org/en-US/docs/Web/API/XMLHttpRequest/response
  69. // 6. send request
  70. // EXAMPLE,
  71. // let myURL = "https://forum.freecadweb.org/viewtopic.php?f=10&t=13710&start=10";
  72. // let myRequest = new XMLHttpRequest();
  73. // myRequest.open("GET", myURL);
  74. // myRequest.onload = function(){
  75. // console.log(myRequest.response);
  76. // }
  77. // myRequest.responseType = "document";
  78. // myRequest.send();
  79. // }}}
  80. // regular expression to match only div id cotaining post(s) & reply(s) {{{
  81. //
  82. // REF: https://scriptular.com
  83. //
  84. // `/^[pP]{1}\d+[0-9]$/` everything contained within the backticks
  85. //
  86. // }}}
  87. // wrap a nodelist within a div {{{
  88. // REF: https://stackoverflow.com/a/59581407/708807
  89. //---------------------------------------------------
  90. // BEGIN SCRIPT
  91. //
  92. // encapsulate topic in html section with classname `ds-thread-wrapper` {{{
  93. var dsSibling = document.querySelector('.action-bar.top');
  94. var children = document.querySelectorAll('.post');
  95. var dsThreadWrapper = document.createElement('section');
  96. dsThreadWrapper.className = 'ds-thread-wrapper';
  97. children.forEach((child) => {
  98. dsThreadWrapper.appendChild(child);
  99. });
  100. dsSibling.after(dsThreadWrapper);
  101. //----- }}}
  102. // Setting up URL dom structures {{{
  103. // store current URL in js var
  104. var dsNextPageBtnUrl = document.querySelector('.arrow.next').firstElementChild.getAttribute('href');
  105. unsafeWindow.iVarNextPageURL = dsNextPageBtnUrl;
  106. console.log(iVarNextPageURL);
  107. // Setup XMLHttpRequest - {{{
  108. var dsRequest = new XMLHttpRequest();
  109. dsRequest.open('GET', dsNextPageBtnUrl);
  110. dsRequest.onload = function() {
  111. // console.log(dsRequest.response); // DEBUG
  112. //
  113. var dsNextPagePosts = dsRequest.response;
  114. var replies = dsNextPagePosts.querySelectorAll('.post');
  115. replies.forEach((reply) => {
  116. dsThreadWrapper.appendChild(reply);
  117. });
  118. };
  119. dsRequest.responseType = 'document';
  120. dsRequest.send();
  121. // use above URL as GET for xmlhttpreques // - }}}
  122. // Q: howto store/get contents of retreieved doc ?
  123. // 1. grab just posts from response doc, store in js var
  124. // 2. append js posts var to bottom of ds-thread-wrapper-class
  125. //--------}}}
  126. // css
  127. const css = `
  128. .css-class: {
  129. position: relative;
  130. }
  131. `;
  132. let pageFooter = document.getElementById('page-footer');
  133. unsafeWindow.iVar42 = pageFooter;
  134. let options = {
  135. root: document.querySelector("#page-body"),
  136. rootMargin: "0px",
  137. threshold: 1.0
  138. };
  139. // let target = document.querySelectorAll(".action-bar");
  140. let target = pageFooter;
  141. function handleIntersection(entries) {
  142. entries.map((entry) => {
  143. if (entry.isIntersecting) {
  144. console.log('target sighted');
  145. }
  146. });
  147. }
  148. let observer = new IntersectionObserver(handleIntersection);
  149. observer.observe(target);
  150. })(); // iffe, END
  151. // vim: foldmethod=marker