Guest User

Pracuj.pl - ramki ofert według lokalizacji

a guest
Oct 13th, 2026
46
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
text 2.99 KB | None | 0 0
  1. // ==UserScript==
  2. // @name Pracuj.pl - ramki ofert według lokalizacji
  3. // @namespace macgajster
  4. // @version 1.3
  5. // @match https://www.pracuj.pl/*
  6. // @match https://www.it.pracuj.pl/*
  7. // @run-at document-idle
  8. // @grant none
  9. // ==/UserScript==
  10.  
  11. (function () {
  12. 'use strict';
  13.  
  14. // Zmień miasto tutaj:
  15. const CITY = 'Warszawa';
  16.  
  17. const offerSelector = '[data-test="default-offer"][data-test-offerid]';
  18. const processedOffers = new WeakSet();
  19.  
  20. const normalize = value =>
  21. (value || '')
  22. .toLocaleLowerCase('pl')
  23. .replace(/\s+/g, ' ')
  24. .trim();
  25.  
  26. const targetCity = normalize(CITY);
  27.  
  28. function processOffer(offer) {
  29. if (processedOffers.has(offer)) return;
  30.  
  31. const infoText = normalize(
  32. Array.from(
  33. offer.querySelectorAll('li[data-test^="offer-additional-info"]')
  34. )
  35. .map(item => item.textContent)
  36. .join(' ')
  37. );
  38.  
  39. const locationText = normalize(
  40. Array.from(offer.querySelectorAll('[data-test="text-region"]'))
  41. .map(element => element.textContent)
  42. .join(' ')
  43. );
  44.  
  45. // Poczekaj, jeśli karta nie ma jeszcze załadowanych informacji.
  46. if (!infoText) return;
  47.  
  48. const isRemote = infoText.includes('zdaln');
  49. const isHybrid = infoText.includes('hybryd');
  50. const isOnsite = infoText.includes('stacjonarn');
  51. const isTargetCity = locationText.includes(targetCity);
  52.  
  53. if (isRemote) {
  54. offer.style.setProperty('outline', '3px solid #20a34a', 'important');
  55. offer.style.setProperty('outline-offset', '-3px', 'important');
  56. } else if (isHybrid || isOnsite) {
  57. const color = isTargetCity ? '#20a34a' : '#e53935';
  58. offer.style.setProperty('outline', `3px solid ${color}`, 'important');
  59. offer.style.setProperty('outline-offset', '-3px', 'important');
  60. }
  61.  
  62. processedOffers.add(offer);
  63. }
  64.  
  65. function processOffersWithin(node) {
  66. if (!(node instanceof Element)) return;
  67.  
  68. if (node.matches(offerSelector)) {
  69. processOffer(node);
  70. }
  71.  
  72. node.querySelectorAll(offerSelector).forEach(processOffer);
  73. }
  74.  
  75. document.querySelectorAll(offerSelector).forEach(processOffer);
  76.  
  77. const observer = new MutationObserver(mutations => {
  78. for (const mutation of mutations) {
  79. const target = mutation.target;
  80. const offer = target instanceof Element
  81. ? target.closest(offerSelector)
  82. : target.parentElement?.closest(offerSelector);
  83.  
  84. if (offer) processOffer(offer);
  85.  
  86. for (const node of mutation.addedNodes) {
  87. processOffersWithin(node);
  88. }
  89. }
  90. });
  91.  
  92. observer.observe(document.body, {
  93. childList: true,
  94. subtree: true
  95. });
  96. })();
  97.  
Advertisement
Add Comment
Please, Sign In to add comment