SheridanCoriana6

Szukaj w Archiwach - AUTO Skany

Apr 14th, 2026 (edited)
68
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 10.92 KB | Software | 0 0
  1. // ==UserScript==
  2. // @name Szukaj w Archiwach - AUTO Skany (Zawijanie wierszy)
  3. // @namespace http://tampermonkey.net/
  4. // @version 4.7
  5. // @description Jeśli skanów > 3, wyświetla je w wielu rzędach (zawijanie), aby mieściły się na ekranie.
  6. // @author marek7400
  7. // @match *://*.szukajwarchiwach.gov.pl/*
  8. // @grant none
  9. // ==/UserScript==
  10.  
  11. (function() {
  12. 'use strict';
  13.  
  14. // --- 1. STYLE GLOBALNE ---
  15. function stretchPage() {
  16. if (document.getElementById('swa-custom-stretch-styles')) {
  17. return;
  18. }
  19. const style = document.createElement('style');
  20. style.id = 'swa-custom-stretch-styles';
  21. style.textContent = `
  22. body .container, body .container-fluid, body #wrapper, body #content, body #main-content {
  23. max-width: 100% !important; width: 100% !important; padding-left: 20px !important; padding-right: 20px !important;
  24. }
  25. table.table { width: 100% !important; max-width: 100% !important; }
  26.  
  27. .swa-preview-container {
  28. display: flex;
  29. gap: 15px;
  30. padding: 15px;
  31. background: #f4f4f4;
  32. border: 1px solid #ccc;
  33. margin-top: 8px;
  34. margin-bottom: 20px;
  35. border-radius: 4px;
  36. box-shadow: inset 0 0 5px rgba(0,0,0,0.1);
  37. }
  38.  
  39. .swa-mode-horizontal {
  40. overflow-x: auto;
  41. white-space: nowrap;
  42. }
  43.  
  44. .swa-mode-wrapped {
  45. flex-wrap: wrap;
  46. white-space: normal;
  47. justify-content: flex-start;
  48. }
  49.  
  50. .swa-preview-img {
  51. height: 400px;
  52. border: 1px solid #777;
  53. cursor: pointer;
  54. box-shadow: 3px 3px 8px rgba(0,0,0,0.3);
  55. transition: transform 0.2s;
  56. object-fit: contain;
  57. background: white;
  58. }
  59. .swa-preview-img:hover {
  60. transform: scale(1.03);
  61. z-index: 10;
  62. }
  63. `;
  64. document.head.appendChild(style);
  65. }
  66.  
  67. stretchPage();
  68.  
  69. const processedHrefs = new Set();
  70.  
  71. function delay(ms) {
  72. return new Promise(function(resolve) {
  73. setTimeout(resolve, ms);
  74. });
  75. }
  76.  
  77. function clearContainer(container) {
  78. while (container.firstChild) {
  79. container.removeChild(container.firstChild);
  80. }
  81. }
  82.  
  83. // --- 2. FUNKCJA ŁADUJĄCA SKANY ---
  84. async function loadScansForUnit(link, limit) {
  85. if (limit <= 0) {
  86. return;
  87. }
  88.  
  89. const previewContainer = document.createElement('div');
  90. previewContainer.className = 'swa-preview-container';
  91.  
  92. if (limit > 3) {
  93. previewContainer.classList.add('swa-mode-wrapped');
  94. } else {
  95. previewContainer.classList.add('swa-mode-horizontal');
  96. }
  97.  
  98. const loadingSpan = document.createElement('span');
  99. loadingSpan.style.color = '#0056b3';
  100. loadingSpan.style.fontSize = '14px';
  101. const loadingItalic = document.createElement('i');
  102. loadingItalic.textContent = `⏳ Pobieranie skanów (${limit})...`;
  103. loadingSpan.appendChild(loadingItalic);
  104. previewContainer.appendChild(loadingSpan);
  105.  
  106. link.parentNode.insertBefore(previewContainer, link.nextSibling);
  107.  
  108. try {
  109. const response = await fetch(link.href);
  110. const html = await response.text();
  111. const parser = new DOMParser();
  112. const doc = parser.parseFromString(html, 'text/html');
  113.  
  114. const mainContent = doc.querySelector('#main-content') || doc.querySelector('.portlet-boundary') || doc.body;
  115. const allImages = mainContent.querySelectorAll('img');
  116. let validImages =[];
  117.  
  118. for (let i = 0; i < allImages.length; i++) {
  119. const img = allImages[i];
  120. const src = img.getAttribute('data-src') || img.getAttribute('src');
  121. if (!src) {
  122. continue;
  123. }
  124. const lowerSrc = src.toLowerCase();
  125. if (lowerSrc.includes('logo') || lowerSrc.includes('icon') || lowerSrc.includes('theme') ||
  126. lowerSrc.includes('avatar') || lowerSrc.includes('spacer') || lowerSrc.includes('portlet') ||
  127. lowerSrc.includes('button')) {
  128. continue;
  129. }
  130. validImages.push(src);
  131. }
  132.  
  133. validImages = [...new Set(validImages)];
  134. clearContainer(previewContainer);
  135.  
  136. if (validImages.length === 0) {
  137. const emptySpan = document.createElement('span');
  138. emptySpan.style.color = '#d9534f';
  139. emptySpan.style.fontSize = '14px';
  140. const emptyBold = document.createElement('b');
  141. emptyBold.textContent = 'Brak zeskanowanych stron.';
  142. emptySpan.appendChild(emptyBold);
  143. previewContainer.appendChild(emptySpan);
  144. return;
  145. }
  146.  
  147. const imagesToDisplay = validImages.slice(0, limit);
  148.  
  149. for (let i = 0; i < imagesToDisplay.length; i++) {
  150. let imgSrc = imagesToDisplay[i];
  151. if (imgSrc.startsWith('/')) {
  152. imgSrc = window.location.origin + imgSrc;
  153. }
  154.  
  155. const img = document.createElement('img');
  156. img.src = imgSrc;
  157. img.className = 'swa-preview-img';
  158. img.title = `Skan ${i + 1} z ${limit} (Kliknij, aby otworzyć jednostkę)`;
  159.  
  160. img.addEventListener('click', function() {
  161. window.open(link.href, '_blank');
  162. });
  163.  
  164. previewContainer.appendChild(img);
  165. }
  166.  
  167. if (limit > 3) {
  168. const footer = document.createElement('div');
  169. footer.style.cssText = 'width: 100%; font-size: 12px; color: #777; padding-top: 10px; border-top: 1px solid #ddd; margin-top: 5px;';
  170. footer.textContent = `Wyświetlono ${imagesToDisplay.length} skanów zgodnie z informacją w tabeli.`;
  171. previewContainer.appendChild(footer);
  172. }
  173.  
  174. } catch (error) {
  175. clearContainer(previewContainer);
  176. const errorSpan = document.createElement('span');
  177. errorSpan.style.color = 'red';
  178. errorSpan.style.fontSize = '14px';
  179. errorSpan.textContent = 'Błąd sieci.';
  180. previewContainer.appendChild(errorSpan);
  181. }
  182. }
  183.  
  184. // --- 3. ANALIZA TABELI ---
  185. async function processAllUnitsAutomatically() {
  186. const unitLinks = document.querySelectorAll('a[href*="/jednostka/"]:not(.swa-processed)');
  187.  
  188. for (let i = 0; i < unitLinks.length; i++) {
  189. const link = unitLinks[i];
  190. link.classList.add('swa-processed');
  191. const linkText = link.textContent.trim();
  192.  
  193. if (link.querySelector('img') || !linkText) {
  194. continue;
  195. }
  196.  
  197. const td = link.closest('td, div.table-cell, div[role="cell"], div.cell');
  198. const row = td ? td.closest('tr, div.table-row, div[role="row"], div.row') : link.closest('tr, div.table-row, div[role="row"], div.row');
  199.  
  200. if (!row) {
  201. continue;
  202. }
  203.  
  204. // Rozszerzono weryfikację o język angielski (dodano 'title' i 'name')
  205. let isNameCol = false;
  206. const dataTitle = (td && td.getAttribute('data-title') || '').toLowerCase();
  207. if (dataTitle.includes('name') || dataTitle.includes('title') || dataTitle.includes('tytu') || dataTitle.includes('nazw')) {
  208. isNameCol = true;
  209. }
  210.  
  211. let cellIndex = -1;
  212. if (!isNameCol && td) {
  213. cellIndex = td.cellIndex;
  214. if (cellIndex === undefined) {
  215. const siblings = Array.from(row.children);
  216. cellIndex = siblings.indexOf(td);
  217. }
  218.  
  219. const table = row.closest('table, div.table, div[role="table"]');
  220. const headers = table ? Array.from(table.querySelectorAll('thead th, th, div.th, div[role="columnheader"]')) : [];
  221. const th = headers[cellIndex];
  222. if (th) {
  223. const thText = th.textContent.toLowerCase();
  224. if (thText.includes('tytu') || thText.includes('nazw') || thText.includes('title') || thText.includes('name')) {
  225. isNameCol = true;
  226. }
  227. }
  228. }
  229.  
  230. if (!isNameCol) {
  231. continue;
  232. }
  233. if (processedHrefs.has(link.href)) {
  234. continue;
  235. }
  236. processedHrefs.add(link.href);
  237.  
  238. // Wyciąganie liczby skanów z rozszerzeniem na wariant angielski (słowo 'scan')
  239. let scanLimit = 0;
  240. const cells = row.cells ? Array.from(row.cells) : Array.from(row.children);
  241. const table = row.closest('table, div.table, div[role="table"]');
  242. const headers = table ? Array.from(table.querySelectorAll('thead th, th, div.th, div[role="columnheader"]')) :[];
  243.  
  244. for (let j = 0; j < cells.length; j++) {
  245. const cell = cells[j];
  246. const headerText = headers[j] ? headers[j].textContent.toLowerCase() : '';
  247. const cellTitle = (cell.getAttribute('data-title') || '').toLowerCase();
  248. const cellContentStr = cell.textContent.toLowerCase();
  249.  
  250. if (headerText.includes('skan') || headerText.includes('scan') ||
  251. cellTitle.includes('skan') || cellTitle.includes('scan') ||
  252. (cellContentStr.includes('skan') && /\d/.test(cellContentStr)) ||
  253. (cellContentStr.includes('scan') && /\d/.test(cellContentStr))) {
  254. scanLimit = parseInt(cell.textContent.replace(/\D/g, ''), 10) || 0;
  255. }
  256. }
  257.  
  258. if (scanLimit > 0) {
  259. await loadScansForUnit(link, scanLimit);
  260. await delay(300);
  261. }
  262. }
  263. }
  264.  
  265. setTimeout(processAllUnitsAutomatically, 1000);
  266.  
  267. const observer = new MutationObserver(function(mutations) {
  268. let hasAddedNodes = false;
  269. for (let i = 0; i < mutations.length; i++) {
  270. if (mutations[i].addedNodes.length > 0) {
  271. hasAddedNodes = true;
  272. break;
  273. }
  274. }
  275.  
  276. if (hasAddedNodes) {
  277. stretchPage();
  278. setTimeout(processAllUnitsAutomatically, 1000);
  279. }
  280. });
  281. observer.observe(document.body, { childList: true, subtree: true });
  282.  
  283. })();
Advertisement
Add Comment
Please, Sign In to add comment