Milovana Preload

Preloads the next image/tease

  1. // ==UserScript==
  2. // @name Milovana Preload
  3. // @namespace https://greasyfork.org/en/users/167665-zoecl
  4. // @description Preloads the next image/tease
  5. // @include https://milovana.com/webteases/showtease.php?id=*
  6. // @version 1.0.0
  7. // @grant GM_addStyle
  8. // ==/UserScript==
  9.  
  10. let preload = {
  11. init: function () {
  12. this.current_tease = document.getElementById('cm_wide');
  13. this.next_page = this.get_next_page();
  14.  
  15. if (!this.next_page) {
  16. console.log('Could not find next page.');
  17. return;
  18. }
  19.  
  20. this.preload();
  21. this.add_event_listeners();
  22. },
  23.  
  24. get_next_page: function () {
  25. return document.getElementById('continue').href;
  26. },
  27.  
  28. preload: function () {
  29. this.preloading = 1;
  30.  
  31. fetch(this.next_page, { credentials: 'include' })
  32. .then(function (response) {
  33. return response.text();
  34. })
  35. .then(this.got_response.bind(this));
  36. },
  37.  
  38. add_event_listeners: function () {
  39. for (let link of document.links) {
  40. if (link.href == this.next_page) {
  41. link.addEventListener('click', this.init_insert_tease.bind(this));
  42. }
  43. }
  44. },
  45.  
  46. got_response: function (response) {
  47. let doc = new DOMParser().parseFromString(response, 'text/html');
  48.  
  49. this.next_tease = document.importNode(doc.getElementById('cm_wide'), 1);
  50. this.next_image = this.next_tease.getElementsByClassName('tease_pic')[0];
  51.  
  52. this.next_image.addEventListener('load', this.finish_preload.bind(this));
  53. },
  54.  
  55. finish_preload: function (event) {
  56. this.preloading = 0;
  57.  
  58. if (this.insert_asap) {
  59. this.insert_asap = 0;
  60. document.body.classList.remove('preloading');
  61.  
  62. if (this.fallback) {
  63. this.fallback = window.clearTimeout(this.fallback);
  64. }
  65.  
  66. this.insert_tease();
  67. }
  68. },
  69.  
  70. init_insert_tease: function (event) {
  71. event.preventDefault();
  72.  
  73. if (this.preloading) {
  74. this.insert_asap = 1;
  75.  
  76. /* change cursor */
  77. document.body.classList.add('preloading');
  78.  
  79. /* add timer in case preloading fails */
  80. if (!this.fallback) {
  81. this.fallback = window.setTimeout(this.force_next.bind(this), 1000);
  82. }
  83.  
  84. return;
  85. }
  86.  
  87. this.insert_tease();
  88. },
  89.  
  90. insert_tease: function (tease) {
  91. window.history.pushState(this.next_page, document.title, this.next_page);
  92.  
  93. this.current_tease.replaceWith(this.next_tease);
  94.  
  95. this.init();
  96. },
  97.  
  98. force_next: function () {
  99. window.location = this.next_page;
  100. },
  101.  
  102. popstate: function (event) {
  103. /* force reload */
  104. window.location.reload(1);
  105. },
  106. };
  107.  
  108. try {
  109. preload.init();
  110. window.addEventListener('popstate', preload.popstate);
  111.  
  112. GM_addStyle('body.preloading * { cursor: progress; }');
  113. }
  114. catch (error) {
  115. console.log(error);
  116. }