Filelist.io Size Filter

Add sliders and dropdown menus to filter filelist.io results by size

  1. // ==UserScript==
  2. // @name Filelist.io Size Filter
  3. // @version 0.2
  4. // @description Add sliders and dropdown menus to filter filelist.io results by size
  5. // @author konvar
  6. // @match https://filelist.io/browse.php*
  7. // @grant none
  8. // @namespace https://greasyfork.org/users/1228860
  9. // ==/UserScript==
  10.  
  11. (function () {
  12. 'use strict';
  13.  
  14. // Your existing HTML block
  15. const existingForm = document.querySelector('table tbody tr td form');
  16.  
  17. // Create a div to hold sliders and dropdown menus
  18. const filterContainer = document.createElement('div');
  19. filterContainer.style.display = 'flex';
  20. filterContainer.style.justifyContent = 'center';
  21. filterContainer.style.alignItems = 'center';
  22. filterContainer.style.flexWrap = 'wrap'; // Allow flex items to wrap
  23. filterContainer.style.marginTop = '10px'; // Adjust the top margin
  24. filterContainer.style.marginBottom = '10px'; // Adjust the bottom margin
  25.  
  26. // Create dropdown menus for minimum and maximum size
  27. const minSizeDropdown = createDropdown('Min Size:', 'minSizeDropdown', ['KB', 'MB', 'GB', 'TB']);
  28. const maxSizeDropdown = createDropdown('Max Size:', 'maxSizeDropdown', ['KB', 'MB', 'GB', 'TB']);
  29.  
  30. // Set default values for dropdowns if not present in localStorage
  31. minSizeDropdown.value = localStorage.getItem('minSizeDropdown') || 'KB';
  32. maxSizeDropdown.value = localStorage.getItem('maxSizeDropdown') || 'TB';
  33.  
  34. // Create sliders for minimum and maximum size
  35. const minSizeSlider = createSlider('Min Size:', 'minSizeSlider', 0, 999);
  36. const maxSizeSlider = createSlider('Max Size:', 'maxSizeSlider', 0, 999);
  37.  
  38. // Append the div containing sliders and dropdown menus after the existing form
  39. existingForm.appendChild(filterContainer);
  40.  
  41. // Function to create sliders
  42. function createSlider(labelText, sliderId, minValue, maxValue) {
  43. const sliderContainer = document.createElement('div');
  44. sliderContainer.style.display = 'flex';
  45. sliderContainer.style.flexDirection = 'row'; // Display label, slider, and value in a row
  46. sliderContainer.style.alignItems = 'center';
  47. sliderContainer.style.margin = '0 10px';
  48.  
  49. const label = document.createElement('label');
  50. label.textContent = labelText;
  51. label.style.marginRight = '5px'; // Adjust margin for spacing
  52. sliderContainer.appendChild(label);
  53.  
  54. const slider = document.createElement('input');
  55. slider.type = 'range';
  56. slider.id = sliderId;
  57. slider.min = minValue;
  58. slider.max = maxValue;
  59. slider.value = minValue;
  60.  
  61. // Retrieve saved value from localStorage
  62. const savedValue = localStorage.getItem(sliderId);
  63. if (savedValue !== null) {
  64. slider.value = savedValue;
  65. }
  66.  
  67. sliderContainer.appendChild(slider);
  68.  
  69. // Display current value
  70. const valueSpan = document.createElement('span');
  71. valueSpan.id = sliderId + 'Value';
  72. valueSpan.textContent = `${parseFloat(slider.value).toFixed(2)} ${sliderId.includes('min') ? minSizeDropdown.value : maxSizeDropdown.value}`;
  73. valueSpan.style.marginLeft = '5px'; // Adjust margin for spacing
  74. sliderContainer.appendChild(valueSpan);
  75.  
  76. // Add event listener to update the displayed value and save to localStorage
  77. slider.addEventListener('input', function () {
  78. const unit = sliderId.includes('min') ? minSizeDropdown.value : maxSizeDropdown.value;
  79. valueSpan.textContent = `${parseFloat(slider.value).toFixed(2)} ${unit}`;
  80. localStorage.setItem(sliderId, slider.value);
  81.  
  82. // Call the function to filter results based on size
  83. filterTorrentResults(
  84. parseFloat(minSizeSlider.value),
  85. parseFloat(maxSizeSlider.value),
  86. minSizeDropdown.value,
  87. maxSizeDropdown.value
  88. );
  89. });
  90.  
  91. // Append slider to the common div
  92. filterContainer.appendChild(sliderContainer);
  93.  
  94. return slider;
  95. }
  96.  
  97. // Function to create dropdown menus
  98. function createDropdown(labelText, dropdownId, options) {
  99. const dropdownContainer = document.createElement('div');
  100. dropdownContainer.style.display = 'flex';
  101. dropdownContainer.style.flexDirection = 'row'; // Display label, dropdown in a row
  102. dropdownContainer.style.alignItems = 'center';
  103. dropdownContainer.style.margin = '0 10px';
  104.  
  105. const label = document.createElement('label');
  106. label.textContent = labelText;
  107. label.style.marginRight = '5px'; // Adjust margin for spacing
  108. dropdownContainer.appendChild(label);
  109.  
  110. const dropdown = document.createElement('select');
  111. dropdown.id = dropdownId;
  112.  
  113. // Create options for the dropdown
  114. options.forEach((option) => {
  115. const optionElement = document.createElement('option');
  116. optionElement.value = option;
  117. optionElement.text = option;
  118. dropdown.appendChild(optionElement);
  119. });
  120.  
  121. // Retrieve saved value from localStorage
  122. const savedValue = localStorage.getItem(dropdownId);
  123. if (savedValue !== null) {
  124. dropdown.value = savedValue;
  125. }
  126.  
  127. dropdownContainer.appendChild(dropdown);
  128.  
  129. // Add event listener to update the displayed value and save to localStorage
  130. dropdown.addEventListener('change', function () {
  131. localStorage.setItem(dropdownId, dropdown.value);
  132. // Call the function to filter results based on size
  133. filterTorrentResults(
  134. parseFloat(minSizeSlider.value),
  135. parseFloat(maxSizeSlider.value),
  136. minSizeDropdown.value,
  137. maxSizeDropdown.value
  138. );
  139. });
  140.  
  141. // Append dropdown to the common div
  142. filterContainer.appendChild(dropdownContainer);
  143.  
  144. return dropdown;
  145. }
  146.  
  147. // Add event listeners to dropdown menus
  148. minSizeDropdown.addEventListener('change', updateUnitAndFilter);
  149. maxSizeDropdown.addEventListener('change', updateUnitAndFilter);
  150.  
  151. // Function to update the displayed filter values and unit
  152. function updateUnitAndFilter() {
  153. const minSizeUnit = minSizeDropdown.value;
  154. const maxSizeUnit = maxSizeDropdown.value;
  155.  
  156. // Ensure that the minimum unit is smaller than or equal to the maximum unit
  157. if (minSizeDropdown.selectedIndex > maxSizeDropdown.selectedIndex) {
  158. // Swap the values if the order is incorrect
  159. const temp = minSizeDropdown.value;
  160. minSizeDropdown.value = maxSizeDropdown.value;
  161. maxSizeDropdown.value = temp;
  162. }
  163.  
  164. // Update the displayed unit for the sliders
  165. document.getElementById('minSizeSliderValue').textContent = `${parseFloat(minSizeSlider.value).toFixed(2)} ${minSizeDropdown.value}`;
  166. document.getElementById('maxSizeSliderValue').textContent = `${parseFloat(maxSizeSlider.value).toFixed(2)} ${maxSizeDropdown.value}`;
  167.  
  168. // Save the selected units to localStorage
  169. localStorage.setItem('minSizeDropdown', minSizeDropdown.value);
  170. localStorage.setItem('maxSizeDropdown', maxSizeDropdown.value);
  171.  
  172. // Call the function to filter results based on size
  173. filterTorrentResults(
  174. parseFloat(minSizeSlider.value),
  175. parseFloat(maxSizeSlider.value),
  176. minSizeUnit,
  177. maxSizeUnit
  178. );
  179. }
  180.  
  181. // Add event listener to update the displayed value and save to localStorage for minSizeSlider
  182. minSizeSlider.addEventListener('input', function () {
  183. const unit = minSizeDropdown.value;
  184. const maxValue = parseFloat(maxSizeSlider.value);
  185.  
  186. // Update the displayed value
  187. const valueSpan = document.getElementById('minSizeSliderValue');
  188. valueSpan.textContent = `${parseFloat(minSizeSlider.value).toFixed(2)} ${unit}`;
  189.  
  190. // Save to localStorage
  191. localStorage.setItem('minSizeSlider', minSizeSlider.value);
  192.  
  193. // Check if the new minimum value is greater than the current maximum value
  194. if (parseFloat(minSizeSlider.value) > maxValue && minSizeDropdown.value === maxSizeDropdown.value) {
  195. // If yes, update the maximum slider to the new minimum value
  196. maxSizeSlider.value = minSizeSlider.value;
  197. // Update the displayed value for the maximum slider
  198. document.getElementById('maxSizeSliderValue').textContent = `${parseFloat(maxSizeSlider.value).toFixed(2)} ${unit}`;
  199. // Save to localStorage
  200. localStorage.setItem('maxSizeSlider', maxSizeSlider.value);
  201. }
  202.  
  203. // Call the function to filter results based on size
  204. filterTorrentResults(
  205. parseFloat(minSizeSlider.value),
  206. parseFloat(maxSizeSlider.value),
  207. minSizeDropdown.value,
  208. maxSizeDropdown.value
  209. );
  210. });
  211.  
  212.  
  213. // Function to update the displayed filter values
  214. function updateFilter() {
  215. const minSize = parseFloat(minSizeSlider.value);
  216. const maxSize = parseFloat(maxSizeSlider.value);
  217.  
  218. // Update the displayed unit for the sliders
  219. document.getElementById('minSizeSliderValue').textContent = `${minSize.toFixed(2)} ${minSizeDropdown.value}`;
  220. document.getElementById('maxSizeSliderValue').textContent = `${maxSize.toFixed(2)} ${maxSizeDropdown.value}`;
  221.  
  222. // Call the function to filter results based on size
  223. filterTorrentResults(minSize, maxSize, minSizeDropdown.value, maxSizeDropdown.value);
  224. }
  225.  
  226. // Initial setup to set the correct unit for the sliders
  227. minSizeDropdown.value = localStorage.getItem('minSizeDropdown') || 'KB';
  228. maxSizeDropdown.value = localStorage.getItem('maxSizeDropdown') || 'KB';
  229. updateUnitAndFilter(); // Call the function to set the correct unit initially
  230.  
  231. // Function to filter torrent results based on size
  232. function filterTorrentResults(minSize, maxSize, minSizeUnit, maxSizeUnit) {
  233. const torrentRows = document.querySelectorAll('.torrentrow');
  234. torrentRows.forEach((row) => {
  235. const sizeElement = row.querySelector('.torrenttable:nth-child(7) font.small');
  236. if (sizeElement) {
  237. const sizeText = sizeElement.textContent.trim(); // Extract size value
  238. const size = parseSize(sizeText, minSizeUnit);
  239. const sizeInMaxUnit = convertSize(size, minSizeUnit, maxSizeUnit);
  240.  
  241. // Check if the size is greater than or equal to the min size slider
  242. // and less than or equal to the max size slider
  243. row.style.display = size >= minSize && sizeInMaxUnit <= maxSize ? '' : 'none';
  244. }
  245. });
  246. }
  247.  
  248. // Function to parse sizes and convert them to the selected unit
  249. function parseSize(sizeText, sizeUnit) {
  250. const match = sizeText.match(/([\d.]+)\s*([KMGTP]B)/i);
  251. if (match) {
  252. const value = parseFloat(match[1]);
  253. const unit = match[2].toUpperCase();
  254.  
  255. return convertSize(value, unit, sizeUnit);
  256. }
  257. return 0; // Default to 0 for unrecognized units
  258. }
  259.  
  260. // Function to convert sizes to the selected unit
  261. function convertSize(value, fromUnit, toUnit) {
  262. const units = { KB: 1, MB: 1024, GB: 1024 * 1024, TB: 1024 * 1024 * 1024 };
  263.  
  264. if (fromUnit in units && toUnit in units) {
  265. return (value * units[fromUnit]) / units[toUnit];
  266. }
  267.  
  268. return value; // Default to the original value if units are not recognized
  269. }
  270.  
  271. // Watch for changes in the content using MutationObserver
  272. const observer = new MutationObserver(() => {
  273. // Reapply filtering when the content changes
  274. filterTorrentResults(
  275. parseFloat(minSizeSlider.value),
  276. parseFloat(maxSizeSlider.value),
  277. minSizeDropdown.value,
  278. maxSizeDropdown.value
  279. );
  280. });
  281.  
  282. // Configure and start the observer
  283. const config = { childList: true, subtree: true };
  284. observer.observe(document.body, config);
  285. })();