Userstyles World Stats Keeper v 1.15

Keeps stats of number of install and show number of install since your last visit of the page and if you don't clear with its button "Clear StatsKeeper"

  1. // ==UserScript==
  2. // @name Userstyles World Stats Keeper v 1.15
  3. // @version 1.16
  4. // @description Keeps stats of number of install and show number of install since your last visit of the page and if you don't clear with its button "Clear StatsKeeper"
  5. // @icon https://external-content.duckduckgo.com/ip3/userstyles.world.ico
  6. // @namespace https://greasyfork.org/users/8
  7. // @match https://userstyles.world/user/*
  8.  
  9. // @author decembre
  10. // @grant none
  11. // ==/UserScript==
  12.  
  13. (function() {
  14. 'use strict';
  15.  
  16. // Create a storage object to store the stats
  17. var storage = localStorage;
  18.  
  19. // Function to get the style ID and installs from a card
  20. function getStyleStats(card) {
  21. var styleId = card.querySelector('.grid.flex.rwrap .card.col.gap .card-header.thumbnail').href.match(/\/style\/(\d+)/)[1];
  22. console.log('Number ID found:', styleId);
  23. var installs = card.querySelector('.grid.flex.rwrap .card.col.gap small:first-of-type + small > [data-tooltip]').textContent;
  24. console.log('Number Install found:', installs);
  25. return { styleId: styleId, installs: installs };
  26. }
  27.  
  28. // Function to update the stats and show the difference
  29. function updateStats(card) {
  30. console.log('Updating stats for card:', card);
  31. var styleId = getStyleStats(card).styleId;
  32. var installs = card.querySelector('.grid.flex.rwrap .card.col.gap small:first-of-type + small > [data-tooltip]').textContent;
  33. console.log('Number Install found:', installs);
  34. var initialInstalls = storage.getItem(styleId + '_initial');
  35. if (!initialInstalls) {
  36. initialInstalls = installs;
  37. storage.setItem(styleId + '_initial', initialInstalls);
  38. }
  39. console.log('Création de l\'élément statsElement');
  40. var statsElement = document.createElement('span');
  41. statsElement.className = 'StatsKeeper';
  42. var installsInt = parseInt(installs.replace(/[^0-9]/g, '')); // Remove non-numeric characters
  43. var initialInstallsInt = parseInt(initialInstalls.replace(/[^0-9]/g, '')); // Remove non-numeric characters
  44. var diff = installsInt - initialInstallsInt;
  45. console.log('Diff:', diff);
  46. if (diff > 0) {
  47. statsElement.textContent = '+' + diff;
  48. statsElement.style.background = 'green';
  49. statsElement.style.borderRadius = '5px';
  50. statsElement.style.color = 'gold';
  51. } else {
  52. statsElement.textContent = '⦁ ⦁ ⦁';
  53. statsElement.style.color = 'gray';
  54. }
  55. console.log('Récupération de l\'élément timeElement');
  56. var timeElement = card.querySelector('.grid.flex.rwrap .card.col.gap small:first-of-type + small > [data-tooltip]');
  57. if (timeElement) {
  58. console.log('Time element trouvé:', timeElement);
  59. timeElement.parentNode.insertBefore(statsElement, timeElement.nextSibling);
  60. console.log('StatsKeeper ajouté:', statsElement);
  61. } else {
  62. console.error('Time element non trouvé');
  63. }
  64. }
  65.  
  66. // Function to load stored stats
  67. function loadStats(cards) {
  68. cards.forEach(function(card) {
  69. var styleId = getStyleStats(card).styleId;
  70. var installs = getStyleStats(card).installs;
  71. var initialInstalls = storage.getItem(styleId + '_initial');
  72. if (initialInstalls) {
  73. var statsElement = document.createElement('span');
  74. statsElement.className = 'StatsKeeper';
  75. var installsInt = parseInt(installs.replace(/[^0-9]/g, '')); // Remove non-numeric characters
  76. var initialInstallsInt = parseInt(initialInstalls.replace(/[^0-9]/g, '')); // Remove non-numeric characters
  77. var diff = installsInt - initialInstallsInt;
  78. console.log('Diff:', diff);
  79. if (diff > 0) {
  80. statsElement.textContent = '+' + diff;
  81. statsElement.style.background = 'green';
  82. statsElement.style.borderRadius = '5px';
  83. statsElement.style.color = 'gold';
  84. } else {
  85. statsElement.textContent = '⦁ ⦁ ⦁';
  86. statsElement.style.color = 'gray';
  87. }
  88. console.log('Stats element:', statsElement);
  89. var timeElement = card.querySelector('.grid.flex.rwrap .card.col.gap small:first-of-type + small > [data-tooltip]');
  90. console.log('Time element:', timeElement);
  91. timeElement.parentNode.insertBefore(statsElement, timeElement.nextSibling);
  92. console.log('StatsKeeper added:', statsElement);
  93. }
  94. });
  95. }
  96.  
  97. // Function to clear all stats
  98. function clearStats() {
  99. console.log('Clearing all stats');
  100. storage.clear();
  101. var statsElements = document.querySelectorAll('.StatsKeeper');
  102. statsElements.forEach(function(element) {
  103. element.parentNode.removeChild(element);
  104. });
  105. }
  106.  
  107. // Get all cards and update the stats
  108. var cards = document.querySelectorAll('.grid.flex.rwrap .card.col.gap');
  109. console.log('Cards:', cards);
  110. // loadStats(cards);
  111. cards.forEach(function(card) {
  112. updateStats(card);
  113. });
  114.  
  115. // Add a style to the page
  116. var style = document.createElement('style');
  117. style.innerHTML = `
  118. .card-body:has(.StatsKeeper) span.author {
  119. position: relative !important;
  120. display: inline-block !important;
  121. width: 57% !important;
  122. top: 0vh !important;
  123. margin: 0vh 0 0 0px !important;
  124. padding: 2px 5px;
  125. font-size: 12px !important;
  126. border-radius: 5px;
  127. /*border: 1px solid yellow !important;*/
  128. }
  129. .card-footer small.flex:nth-child(2) span.StatsKeeper:not([style="color: gray;"]) {
  130. position: relative !important;
  131. display: inline-block !important;
  132. width: 40px!important;
  133. height: 1.5vh !important;
  134. line-height: 1.1vh !important;
  135. top: -0.2vh !important;
  136. left: -180px !important;
  137. margin: 0vh 0 0 -20px !important;
  138. padding: 2px 5px;
  139. font-size: 12px !important;
  140. border-radius: 5px;
  141. text-align: right !important;
  142. color: gold !important;
  143. /*border: 1px solid aqua !important;*/
  144. }
  145. .card-footer small.flex:nth-child(2) span.StatsKeeper[style="color: gray;"] {
  146. position: relative !important;
  147. display: inline-block !important;
  148. width: 40px!important;
  149. height: 1.5vh !important;
  150. line-height: 0.9vh !important;
  151. top: -0.2vh !important;
  152. left: -180px !important;
  153. margin: 0vh 0 0 -20px !important;
  154. padding: 2px 5px;
  155. font-size: 8px !important;
  156. border-radius: 5px;
  157. text-align: right !important;
  158. color: silver !important;
  159. border: none !important;
  160. }
  161.  
  162. .ClearStatsButton {
  163. position: absolute !important;
  164. margin: 0 0 0 -150px !important;
  165. padding: 2px 5px !important;
  166. border-radius: 5px;
  167. font-size: 12px;
  168. cursor: pointer;
  169. color: #fff;
  170. background-color: #4CAF50;
  171. border: none;
  172. }
  173. `;
  174. document.head.appendChild(style);
  175.  
  176. // Add a button to clear all stats
  177. var clearButton = document.createElement('button');
  178. clearButton.textContent = 'Clear StatsKeeper';
  179. clearButton.className = 'ClearStatsButton';
  180. clearButton.onclick = clearStats;
  181. var countElement = document.querySelector('#content section#styles .flex p.count');
  182. countElement.parentNode.appendChild(clearButton);
  183. })();