PepperTweaker

Pepper na resorach...

  1. // ==UserScript==
  2. // @name PepperTweaker
  3. // @namespace bearbyt3z
  4. // @version 0.9.197
  5. // @description Pepper na resorach...
  6. // @author bearbyt3z
  7. // @match https://www.pepper.pl/*
  8. // @run-at document-start
  9. // @grant none
  10. // ==/UserScript==
  11.  
  12. (function () {
  13. 'use strict';
  14.  
  15. /***********************************************/
  16. /***** RUN AT DOCUMENT START (BEFORE LOAD) *****/
  17. /***********************************************/
  18.  
  19. /*** Default configuration ***/
  20.  
  21. const backupConfigOnFailureLoad = {
  22. dealsFilters: true,
  23. commentsFilters: true,
  24. };
  25.  
  26. /* Plugin Enabled */
  27. const defaultConfigPluginEnabled = true;
  28.  
  29. /* Dark Theme Enabled */
  30. const defaultConfigDarkThemeEnabled = true;
  31.  
  32. /* Improvements */
  33. const defaultConfigImprovements = {
  34. listToGrid: true,
  35. gridColumnCount: 0,
  36. transparentPaginationFooter: true,
  37. hideTopDealsWidget: false,
  38. hideGroupsBar: false,
  39. repairDealDetailsLinks: true,
  40. repairDealImageLink: true,
  41. addLikeButtonsToBestComments: true,
  42. addSearchInterface: true,
  43. addCommentPreviewOnProfilePage: true,
  44. };
  45.  
  46. /* Auto Update */
  47. const defaultConfigAutoUpdate = {
  48. dealsDefaultEnabled: false,
  49. commentsDefaultEnabled: false,
  50. soundEnabled: true,
  51. askBeforeLoad: false,
  52. };
  53.  
  54. /* Deals Filters */
  55. const defaultConfigDealsFilters = [
  56. { name: 'Alkohol słowa kluczowe', active: false, keyword: /\bpiw[oa]\b|\bbeer|alkohol|whiske?y|likier|w[óo]d(ecz)?k[aąieę]|\bwark[aąieę]|\bbols|\bsoplica\b|johnni?(e|y) walker|jim ?beam|gentleman ?jack|beefeater|tequilla|\bmacallan|hennessy|armagnac ducastaing|\bbaczewski|\baperol|\bvodka|carlsberg|kasztelan|okocim|smuggler|martini|\blager[ay]?\b|żywiec|pilsner|\brum[uy]?\b|książęce|\btrunek|amundsen|\bbrandy\b|żubrówk[aąięe]|\bradler\b|\btyskie\b|bourbon|glen moray|\bbrowar|\bgran[td]'?s\b|jagermeister|jack daniel'?s|\blech\b|heineken|\bcalsberg|\bbacardi\b|\bbushmills|\bballantine'?s|somersby|gentelman jack/i, style: { opacity: '0.3' } }, // don't use: \bwin(a|o)\b <-- to many false positive e.g. Wiedźmin 3 Krew i Wino
  57. { name: 'Disco Polo', active: false, keyword: /disco polo/i, style: { display: 'none' } },
  58. { name: 'Niezdrowe jedzenie', active: false, merchant: /mcdonalds|kfc|burger king/i, style: { opacity: '0.3' } },
  59. { name: 'Aliexpress/Banggood', active: false, merchant: /aliexpress|banggood/i, style: { border: '4px dashed #e00034' } },
  60. { name: 'Nieuczciwi sprzedawcy', active: false, merchant: /empik|komputronik|proline|super-pharm/i, style: { border: '4px dashed #1f7ecb' } },
  61. { name: 'Największe przeceny', active: false, discountAbove: 80, style: { border: '4px dashed #51a704' } },
  62. { name: 'Spożywcze', active: false, groups: /spożywcze/i, style: { opacity: '0.3' } },
  63. { name: 'Lokalne', active: false, local: true, style: { border: '4px dashed #880088' } },
  64. ];
  65.  
  66. /* Comments filters */
  67. const defaultConfigCommentsFilters = [
  68. { name: 'SirNiedźwiedź', active: true, user: /SirNiedźwiedź/i, style: { border: '2px dotted #51a704' } },
  69. { name: 'G... burze by urtedbo', user: /urtedbo/i, keyword: /poo.*burz[eęaą]/i, style: { display: 'none' } }, // can match emoticons (also in brackets) => <i class="emoji emoji--type-poo" title="(poo)"></i>
  70. { name: 'Brzydkie słowa', keyword: /gówno|gowno|dópa|dupa/i, style: { opacity: '0.3' } },
  71. ];
  72.  
  73. const createNewFilterName = 'Utwórz nowy...';
  74.  
  75. const defaultFilterStyleValues = {
  76. deals: {
  77. display: 'none',
  78. opacity: '0.3',
  79. borderWidth: '4px',
  80. borderStyle: 'dashed',
  81. borderColor: '#880088', // '#ff7900'
  82. },
  83. comments: {
  84. display: 'none',
  85. opacity: '0.3',
  86. borderWidth: '2px',
  87. borderStyle: 'dotted',
  88. borderColor: '#880088',
  89. },
  90. };
  91.  
  92. /*** END: Deafult Configuration ***/
  93.  
  94. const messageWrongJSONStyle = 'Niewłaściwa składnia w polu stylu. Należy użyć składni JSON.';
  95.  
  96. //RegExp.prototype.toJSON = RegExp.prototype.toString; // to stringify & parse RegExp
  97. //const MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver;
  98. const newRegExp = (pattern, flags = 'i') => (pattern instanceof RegExp || pattern.constructor.name === 'RegExp') ? pattern : pattern && new RegExp(pattern, flags) || null;
  99. // const isEmptyObject = Object.entries(value).length === 0 && value.constructor === Object;
  100. const isBoolean = value => value === true || value === false; // faster than typeof
  101. const isNumeric = value => !isNaN(parseFloat(value)) && isFinite(value);
  102. const isInteger = value => !isNaN(value) && parseInt(Number(value)) == value && !isNaN(parseInt(value, 10));
  103. const isString = value => typeof value === 'string' || value instanceof String;
  104.  
  105. const getCSSBorderColor = borderCSS => borderCSS && isString(borderCSS) && (borderCSS.match(/#[a-fA-F0-9]+/) || [''])[0] || null; // match returns array or null => null will throw an error for index [0]
  106. const getCSSBorderStyle = borderCSS => borderCSS && isString(borderCSS) && (borderCSS.match(/dashed|dotted|solid|double|groove|ridge|inset|outset/) || [''])[0] || null;
  107.  
  108. const arrayDifference = (array1, array2) => array1.filter(value => !array2.includes(value));
  109. const arrayIntersection = (array1, array2) => array1.filter(value => array2.includes(value));
  110.  
  111. const JSONRegExpReplacer = (key, value) => (value instanceof RegExp) ? { __type__: 'RegExp', source: value.source, flags: value.flags } : value;
  112. const JSONRegExpReviver = (key, value) => (value && value.__type__ === 'RegExp') ? new RegExp(value.source, value.flags) : value;
  113.  
  114. const zeroPad = number => (number < 10) ? `0${number}` : number;
  115. const getCurrentDateTimeString = () => {
  116. const now = new Date(),
  117. year = now.getFullYear(),
  118. month = zeroPad(now.getMonth() + 1), // months starting from 0
  119. day = zeroPad(now.getDate()),
  120. hours = zeroPad(now.getHours()),
  121. minutes = zeroPad(now.getMinutes()),
  122. seconds = zeroPad(now.getSeconds());
  123. return `${year}-${month}-${day}_${hours}-${minutes}-${seconds}`;
  124. };
  125.  
  126. const removeAllChildren = parent => { while (parent.hasChildNodes()) parent.removeChild(parent.lastChild); };
  127. const moveAllChildren = (oldParent, newParent) => { while (oldParent.hasChildNodes()) newParent.appendChild(oldParent.firstChild); };
  128. const cloneAttributes = (source, target) => [...source.attributes].forEach(attr => target.setAttribute(attr.nodeName, attr.nodeValue));
  129.  
  130. const getWindowSize = () => ({
  131. width: window.innerWidth || document.documentElement.clientWidth || document.body.clientWidth,
  132. height: window.innerHeight || document.documentElement.clientHeight || document.body.clientHeight,
  133. });
  134.  
  135. /*** Configuration Functions ***/
  136. const setConfig = (configuration = { pluginEnabled, darkThemeEnabled, improvements, autoUpdate, dealsFilters, commentsFilters }, reload = false) => {
  137. if ((configuration.pluginEnabled !== undefined) && isBoolean(configuration.pluginEnabled)) {
  138. localStorage.setItem('PepperTweaker.config.pluginEnabled', JSON.stringify(configuration.pluginEnabled));
  139. pepperTweakerConfig.pluginEnabled = configuration.pluginEnabled;
  140. }
  141. if ((configuration.darkThemeEnabled !== undefined) && isBoolean(configuration.darkThemeEnabled)) {
  142. localStorage.setItem('PepperTweaker.config.darkThemeEnabled', JSON.stringify(configuration.darkThemeEnabled));
  143. pepperTweakerConfig.darkThemeEnabled = configuration.darkThemeEnabled;
  144. }
  145. if (configuration.improvements !== undefined) { // only one option can be specified here
  146. configuration.improvements = { // to ensure only these props are in the autoUpdate object
  147. listToGrid: isBoolean(configuration.improvements.listToGrid) ? configuration.improvements.listToGrid : pepperTweakerConfig.improvements.listToGrid,
  148. gridColumnCount: isInteger(configuration.improvements.gridColumnCount) ? parseInt(configuration.improvements.gridColumnCount) : parseInt(pepperTweakerConfig.improvements.gridColumnCount),
  149. transparentPaginationFooter: isBoolean(configuration.improvements.transparentPaginationFooter) ? configuration.improvements.transparentPaginationFooter : pepperTweakerConfig.improvements.transparentPaginationFooter,
  150. hideTopDealsWidget: isBoolean(configuration.improvements.hideTopDealsWidget) ? configuration.improvements.hideTopDealsWidget : pepperTweakerConfig.improvements.hideTopDealsWidget,
  151. hideGroupsBar: isBoolean(configuration.improvements.hideGroupsBar) ? configuration.improvements.hideGroupsBar : pepperTweakerConfig.improvements.hideGroupsBar,
  152. repairDealDetailsLinks: isBoolean(configuration.improvements.repairDealDetailsLinks) ? configuration.improvements.repairDealDetailsLinks : pepperTweakerConfig.improvements.repairDealDetailsLinks,
  153. repairDealImageLink: isBoolean(configuration.improvements.repairDealImageLink) ? configuration.improvements.repairDealImageLink : pepperTweakerConfig.improvements.repairDealImageLink,
  154. addLikeButtonsToBestComments: isBoolean(configuration.improvements.addLikeButtonsToBestComments) ? configuration.improvements.addLikeButtonsToBestComments : pepperTweakerConfig.improvements.addLikeButtonsToBestComments,
  155. addSearchInterface: isBoolean(configuration.improvements.addSearchInterface) ? configuration.improvements.addSearchInterface : pepperTweakerConfig.improvements.addSearchInterface,
  156. addCommentPreviewOnProfilePage: isBoolean(configuration.improvements.addCommentPreviewOnProfilePage) ? configuration.improvements.addCommentPreviewOnProfilePage : pepperTweakerConfig.improvements.addCommentPreviewOnProfilePage,
  157. };
  158. localStorage.setItem('PepperTweaker.config.improvements', JSON.stringify(configuration.improvements));
  159. pepperTweakerConfig.improvements = configuration.improvements;
  160. }
  161. if (configuration.autoUpdate !== undefined) { // only one option can be specified here
  162. configuration.autoUpdate = { // to ensure only these props are in the autoUpdate object
  163. dealsDefaultEnabled: isBoolean(configuration.autoUpdate.dealsDefaultEnabled) ? configuration.autoUpdate.dealsDefaultEnabled : pepperTweakerConfig.autoUpdate.dealsDefaultEnabled,
  164. commentsDefaultEnabled: isBoolean(configuration.autoUpdate.commentsDefaultEnabled) ? configuration.autoUpdate.commentsDefaultEnabled : pepperTweakerConfig.autoUpdate.commentsDefaultEnabled,
  165. soundEnabled: isBoolean(configuration.autoUpdate.soundEnabled) ? configuration.autoUpdate.soundEnabled : pepperTweakerConfig.autoUpdate.soundEnabled,
  166. askBeforeLoad: isBoolean(configuration.autoUpdate.askBeforeLoad) ? configuration.autoUpdate.askBeforeLoad : pepperTweakerConfig.autoUpdate.askBeforeLoad,
  167. };
  168. localStorage.setItem('PepperTweaker.config.autoUpdate', JSON.stringify(configuration.autoUpdate));
  169. pepperTweakerConfig.autoUpdate = configuration.autoUpdate;
  170. }
  171. if ((configuration.dealsFilters !== undefined) && Array.isArray(configuration.dealsFilters)) {
  172. localStorage.setItem('PepperTweaker.config.dealsFilters', JSON.stringify(configuration.dealsFilters, JSONRegExpReplacer));
  173. pepperTweakerConfig.dealsFilters = configuration.dealsFilters;
  174. }
  175. if ((configuration.commentsFilters !== undefined) && Array.isArray(configuration.commentsFilters)) {
  176. localStorage.setItem('PepperTweaker.config.commentsFilters', JSON.stringify(configuration.commentsFilters, JSONRegExpReplacer));
  177. pepperTweakerConfig.commentsFilters = configuration.commentsFilters;
  178. }
  179. if (reload) {
  180. location.reload();
  181. }
  182. };
  183.  
  184. const resetConfig = (resetConfiguration = { resetPluginEnabled: true, resetDarkThemeEnabled: true, resetImprovements: true, resetAutoUpdate: true, resetDealsFilters: true, resetCommentsFilters: true }, reload = true) => {
  185. const setConfigObject = {};
  186. if (!resetConfiguration || resetConfiguration.resetPluginEnabled === true) {
  187. setConfigObject.pluginEnabled = defaultConfigPluginEnabled;
  188. }
  189. if (!resetConfiguration || resetConfiguration.resetDarkThemeEnabled === true) {
  190. setConfigObject.darkThemeEnabled = defaultConfigDarkThemeEnabled;
  191. }
  192. if (!resetConfiguration || resetConfiguration.resetImprovements === true) {
  193. setConfigObject.improvements = defaultConfigImprovements;
  194. }
  195. if (!resetConfiguration || resetConfiguration.resetAutoUpdate === true) {
  196. setConfigObject.autoUpdate = defaultConfigAutoUpdate;
  197. }
  198. if (!resetConfiguration || resetConfiguration.resetDealsFilters === true) {
  199. setConfigObject.dealsFilters = defaultConfigDealsFilters;
  200. }
  201. if (!resetConfiguration || resetConfiguration.resetCommentsFilters === true) {
  202. setConfigObject.commentsFilters = defaultConfigCommentsFilters;
  203. }
  204. setConfig(setConfigObject, reload);
  205. };
  206.  
  207. const loadConfig = (outputConfig, inputConfig, reload = false) => {
  208. if (inputConfig) {
  209. try {
  210. outputConfig = JSON.parse(inputConfig, JSONRegExpReviver);
  211. setConfig(outputConfig, false); // reload == false --> missing config entries have to be reset first (below)
  212. } catch (error) {
  213. return false;
  214. }
  215. } else {
  216. const failedSettings = [];
  217. try {
  218. outputConfig.pluginEnabled = JSON.parse(localStorage.getItem('PepperTweaker.config.pluginEnabled'));
  219. } catch (error) {
  220. failedSettings.push({ name: 'pluginEnabled', error: error.message });
  221. }
  222. try {
  223. outputConfig.darkThemeEnabled = JSON.parse(localStorage.getItem('PepperTweaker.config.darkThemeEnabled'));
  224. } catch (error) {
  225. failedSettings.push({ name: 'darkThemeEnabled', error: error.message });
  226. }
  227. try {
  228. outputConfig.improvements = JSON.parse(localStorage.getItem('PepperTweaker.config.improvements'));
  229. } catch (error) {
  230. failedSettings.push({ name: 'improvements', error: error.message });
  231. }
  232. try {
  233. outputConfig.autoUpdate = JSON.parse(localStorage.getItem('PepperTweaker.config.autoUpdate'));
  234. } catch (error) {
  235. failedSettings.push({ name: 'autoUpdate', error: error.message });
  236. }
  237. try {
  238. outputConfig.dealsFilters = JSON.parse(localStorage.getItem('PepperTweaker.config.dealsFilters'), JSONRegExpReviver);
  239. } catch (error) {
  240. failedSettings.push({ name: 'dealsFilters', error: error.message });
  241. }
  242. try {
  243. outputConfig.commentsFilters = JSON.parse(localStorage.getItem('PepperTweaker.config.commentsFilters'), JSONRegExpReviver);
  244. } catch (error) {
  245. failedSettings.push({ name: 'commentsFilters', error: error.message });
  246. }
  247. for (const failed of failedSettings) {
  248. console.error(`Cannot parse PepperTweaker.config.${failed.name}: ${failed.error}`);
  249. console.error(`Value of ${failed.name}: ` + localStorage.getItem(`PepperTweaker.config.${failed.name}`));
  250. if (backupConfigOnFailureLoad[failed.name] === true) {
  251. localStorage.setItem(`PepperTweaker.config.${failed.name}-backup`, localStorage.getItem(`PepperTweaker.config.${failed.name}`));
  252. console.error(`Current ${failed.name} value saved as PepperTweaker.config.${failed.name}-backup`);
  253. }
  254. outputConfig[failed.name] = null;
  255. }
  256. }
  257. const configToReset = {};
  258. if (!isBoolean(outputConfig.pluginEnabled)) {
  259. configToReset.resetPluginEnabled = true;
  260. }
  261. if (!isBoolean(outputConfig.darkThemeEnabled)) {
  262. configToReset.resetDarkThemeEnabled = true;
  263. }
  264. if (!outputConfig.improvements
  265. || !isBoolean(outputConfig.improvements.listToGrid)
  266. || !isInteger(outputConfig.improvements.gridColumnCount)
  267. || !isBoolean(outputConfig.improvements.transparentPaginationFooter)
  268. || !isBoolean(outputConfig.improvements.hideTopDealsWidget)
  269. || !isBoolean(outputConfig.improvements.hideGroupsBar)
  270. || !isBoolean(outputConfig.improvements.repairDealDetailsLinks)
  271. || !isBoolean(outputConfig.improvements.repairDealImageLink)
  272. || !isBoolean(outputConfig.improvements.addLikeButtonsToBestComments)
  273. || !isBoolean(outputConfig.improvements.addSearchInterface)
  274. || !isBoolean(outputConfig.improvements.addCommentPreviewOnProfilePage)) {
  275. configToReset.resetImprovements = true;
  276. }
  277. if (!outputConfig.autoUpdate
  278. || !isBoolean(outputConfig.autoUpdate.dealsDefaultEnabled)
  279. || !isBoolean(outputConfig.autoUpdate.commentsDefaultEnabled)
  280. || !isBoolean(outputConfig.autoUpdate.soundEnabled)
  281. || !isBoolean(outputConfig.autoUpdate.askBeforeLoad)) {
  282. configToReset.resetAutoUpdate = true;
  283. }
  284. if (!Array.isArray(outputConfig.dealsFilters)) {
  285. configToReset.resetDealsFilters = true;
  286. }
  287. if (!Array.isArray(outputConfig.commentsFilters)) {
  288. configToReset.resetCommentsFilters = true;
  289. }
  290. resetConfig(configToReset, reload);
  291. return true;
  292. }
  293.  
  294. const saveConfigFile = () => {
  295. const link = document.createElement('A');
  296. const file = new Blob([JSON.stringify(pepperTweakerConfig, JSONRegExpReplacer)], { type: 'text/plain' });
  297. link.href = URL.createObjectURL(file);
  298. link.download = `PepperTweaker-config-[${getCurrentDateTimeString()}].json`;
  299. link.dispatchEvent(new MouseEvent('click', { bubbles: true, cancelable: true, view: window }));
  300. };
  301.  
  302. const importConfigFromFile = () => {
  303. const fileInput = document.createElement('input');
  304. fileInput.type = 'file';
  305. fileInput.accept = 'application/json';
  306. fileInput.onchange = event => {
  307. const file = fileInput.files[0];
  308. const reader = new FileReader();
  309. reader.onload = () => {
  310. if (!loadConfig({}, reader.result, true)) {
  311. alert('Ten plik nie wygląda jak konfiguracja PepperTweakera :/');
  312. }
  313. };
  314. reader.readAsText(file);
  315. };
  316. fileInput.click();
  317. };
  318. /*** END: Configuration Functions ***/
  319.  
  320. /*** Load Configuration from Local Storage ***/
  321. const pepperTweakerConfig = {};
  322. loadConfig(pepperTweakerConfig);
  323. /*** END: Load configuration ***/
  324.  
  325. /*** Setting CSS ***/
  326. let css = '';
  327.  
  328. const orangeColor = '#f7641b';
  329.  
  330. /* Theme independent style */
  331. const voteRedColor = '#e00034';
  332. const voteBlueColor = '#1f7ecb';
  333.  
  334. css += `
  335. /* The override of the color variables used by Pepper */
  336. :root {
  337. /* hot deal temperature + hot badge icon */
  338. --temperature90: ${voteRedColor} !important;
  339. /* cold deal temperature */
  340. --temperature10: ${voteBlueColor} !important;
  341. }
  342. /* END */
  343.  
  344. body {
  345. font-family: Arial;
  346. }
  347.  
  348. /* Font Size */
  349. .userHtml {
  350. font-size: 0.925rem !important;
  351. }
  352. .size--fromW3-xxl, .thread-title--item, .userHtml--subtitles h3 {
  353. font-size: 1.25rem !important;
  354. }
  355. #threadDetailPortal .threadItemCard-price { /* the main price in deal details */
  356. font-size: 1.5rem !important;
  357. }
  358. .card .threadItemCard-price { /* the price of a deal in related threads */
  359. font-size: 1rem !important;
  360. }
  361. .card .textBadge { /* the discount badge of a deal in related threads */
  362. font-size: 0.925rem;
  363. line-height: 1.25rem;
  364. --line-height: 1.25rem;
  365. }
  366. .threadListCard-body .textBadge { /* the discount badge of a deal in the main page */
  367. line-height: 1.3rem;
  368. --line-height: 1.3rem;
  369. }
  370. /* END: Font Size */
  371.  
  372. .button--fromW3-size-l {
  373. height: 40px !important;
  374. }
  375.  
  376. /* Pepper ads */
  377. #leftStickySidebarLinkedAdSlotPortal,
  378. #sidebarTopAdSlotPortal, #sidebarBottomAdSlotPortal,
  379. #mrec1FuseZonePortal, #vrec1FuseZonePortal {
  380. display: none;
  381. }
  382. /* END: Pepper ads */
  383.  
  384. /* Pepper Widgets */
  385. #voteSecondarySectionPortal, /* Secondary vote section */
  386. #threadDetailPortal *[data-t="keywordSuggestionsWidget"], /* the keyword widget for an expired deal */
  387. #keywordSuggestionsWidgetPortal { /* the keyword widget below deal details */
  388. display: none;
  389. }
  390. /* END: Pepper Widgets */
  391.  
  392. /* Voting buttons: Replaced up/down arrow with +/- */
  393. .vote-button .icon--arrow-rounded-down, .vote-button .icon--arrow-rounded-up {
  394. display: none;
  395. }
  396.  
  397. .vote-button.vote-button--mode-up span:after {
  398. content: '+';
  399. font-weight: bold;
  400. font-size: 1.7em;
  401. }
  402. .vote-button.vote-button--mode-down span:after {
  403. content: '\u2013';
  404. font-weight: bold;
  405. font-size: 1.7em;
  406. margin-top: -0.17em;
  407. }
  408.  
  409. /* Changing the color only when voting enabled (not voted already) */
  410. .vote-button.vote-button--mode-up:not(:disabled) span:after {
  411. color: ${voteRedColor};
  412. }
  413. .vote-button.vote-button--mode-down:not(:disabled) span:after {
  414. color: ${voteBlueColor};
  415. }
  416. /***/
  417.  
  418. .vote-button.vote-button--mode-up.vote-button--mode-selected {
  419. background-color: ${voteRedColor} !important;
  420. }
  421. .vote-button.vote-button--mode-down.vote-button--mode-selected {
  422. background-color: ${voteBlueColor} !important;
  423. }
  424. /* END: Voting buttons */
  425.  
  426. /* Thread description: All deals, sorted by... etc. */
  427. #threadListingDescriptionPortal {
  428. display: none !important;
  429. }
  430.  
  431. /* Force the orange color */
  432. .text--color-green, /* green text like in "For free" */
  433. .button[data-t="removeBookmark"] { /* bookmark button for saved deals */
  434. color: ${orangeColor} !important;
  435. }
  436. `;
  437.  
  438. if (pepperTweakerConfig.pluginEnabled) {
  439.  
  440. /* Hide top deals widget */
  441. if (pepperTweakerConfig.improvements.hideTopDealsWidget) {
  442. css += `
  443. .listLayout .vue-portal-target, .listLayout-side .vue-portal-target,
  444. .js-vue2[data-vue2*="HottestWidget"] {
  445. display: none !important;
  446. }
  447. `;
  448. }
  449.  
  450. /* Hide top bar with group & category buttons */
  451. if (pepperTweakerConfig.improvements.hideGroupsBar) {
  452. css += `
  453. header .subNav--light {
  454. display: none !important;
  455. }
  456. #subNavMenu {
  457. top: 57px !important;
  458. }
  459. `;
  460. }
  461.  
  462. /* Dark Theme Style */
  463. if (pepperTweakerConfig.darkThemeEnabled) {
  464.  
  465. // const invertColor = color => '#' + (Number(`0x1${ color.replace('#', '') }`) ^ 0xFFFFFF).toString(16).substr(1);
  466. const darkBorderColor = '#121212';
  467. const lightBorderColor = '#5c5c5c';
  468. const darkBackgroundColor = '#242424';
  469. const veryDarkBackgroundColor = '#1d1f20';
  470. const darkestBackgroundColor = '#050c13';
  471. const lightBackgroundColor = '#35373b';
  472. const textColor = '#bfbfbf';
  473. const secondaryTextColor = '#8f949b';
  474. // const greyButtonColor = '#8f949b';
  475. // const orangeColor = '#d1d5db';
  476.  
  477. css += `
  478. :root {
  479. /* text color variables used by Pepper */
  480. --textNeutralPrimary: ${textColor};
  481. --textNeutralSecondary: ${textColor};
  482. --textTranslucentPrimary: ${textColor};
  483. --textTranslucentSecondary: ${secondaryTextColor};
  484. --textTranslucentSecondaryHover: ${textColor};
  485. --textTranslucentTertiary: ${textColor};
  486. --graphicTranslucentTertiary: ${secondaryTextColor};
  487. --graphicTranslucentTertiaryHover: ${textColor};
  488. --graphicTranslucentSecondary: ${secondaryTextColor};
  489.  
  490. /* background color variables used by Pepper */
  491. --bgBaseSecondary: ${darkBackgroundColor};
  492. --bgNeutralPrimary: ${lightBackgroundColor};
  493.  
  494. /* border color variables used by Pepper */
  495. --borderNeutralPrimary: ${lightBorderColor};
  496. }
  497. .subNavMenu-link,
  498. .vote-temp--inert,
  499. .formList-label,
  500. .navMenu-label,
  501. .card-title,
  502. #threadBreadcrumbsPortal .text--color-white,
  503. footer .text--color-white,
  504. .text--color-charcoalShade,
  505. .comments-pagi--header .comments-pagi-pages:not(:disabled),
  506. .page2-center .mute--text2, .page2-subTitle2.mute--text2, .conversation-content.mute--text2, .linkGrey, .thread-userOptionLink, .cept-nav-subheadline, .user:not(.thread-user), .tabbedInterface-tab, .subNavMenu, .subNavMenu-btn, .tag, .page-label, .page-subTitle, .page2-secTitle, .userProfile-title, .userProfile-title--sub, .bg--color-inverted .text--color-white, .comments-pagination--header .pagination-next, .comments-pagination--header .pagination-page, .comments-pagination--header .pagination-previous, .conversationList-msgPreview, .thread-title, .mute--text, .text--color-charcoal, .text--color-charcoalTint, .cept-tt, .cept-description-container, /*.cept-tp,*/ .thread-username, .voucher input, .hide--bigCards1, .hide--toBigCards1 {
  507. color: ${textColor};
  508. }
  509. .nav {
  510. background-color: ${lightBackgroundColor};
  511. }
  512. .redactor button,
  513. .redactor button.button--disabled svg,
  514. .redactor button.button--disabled span,
  515. .button--type-primary.button--mode-brand.button--disabled,
  516. .button--type-secondary:not(.cept-on), .button--mode-secondary {
  517. color: ${secondaryTextColor} !important;
  518. }
  519. .navDropDown-trigger.button--type-primary.button--mode-white,
  520. .speechBubble {
  521. background-color: ${darkBackgroundColor};
  522. color: ${textColor};
  523. }
  524. .thread--type-card, .thread--type-list, .conversationList-msg--read:not(.conversationList-msg--active), .card, .threadCardLayout--card article, .threadCardLayout--card article span .threadCardLayout--card article span, .cept-comments-link, .subNavMenu-btn {
  525. background-color: ${darkBackgroundColor} !important;
  526. border-color: ${darkBorderColor};
  527. }
  528. .thread--deal, .thread--discussion {
  529. background-color: ${darkBackgroundColor};
  530. border-color: ${darkBorderColor};
  531. border-top: none; /* there is some problem with the top border => whole article goes up */
  532. border-radius: 5px;
  533. }
  534. .vote-box, .input, .inputBox, .secretCode-codeBox, .toolbar, .voucher-code {
  535. background-color: ${darkBackgroundColor} !important;
  536. border-color: ${lightBorderColor} !important;
  537. }
  538. /* MC Notifications, e.g. reindeers */
  539. .mc-notification .text--color-white {
  540. color: ${textColor} !important;
  541. }
  542. .button--type-primary.button--mode-white {
  543. --text-default: ${textColor};
  544. }
  545. .mc-notification-inner {
  546. border-color: ${textColor} !important;
  547. }
  548. .mc-background--primary,
  549. .mc-background--shade,
  550. .mc-background--shadow,
  551. .mc-background--grey,
  552. .mc-background--lvl1,
  553. .mc-background--lvl2,
  554. .mc-background--lvl3 {
  555. background: none;
  556. background-color: ${veryDarkBackgroundColor} !important;
  557. }
  558. /* END: MC Notifications */
  559. /* Range sliders - have to be defined separately */
  560. .rangeSlider::-moz-range-thumb { /* Firefox */
  561. background-color: ${darkBackgroundColor} !important;
  562. }
  563. .rangeSlider::-webkit-slider-thumb { /* Chrome, Safari, Opera */
  564. background-color: ${darkBackgroundColor} !important;
  565. }
  566. .rangeSlider::-ms-thumb { /* IE - not tested */
  567. background-color: ${darkBackgroundColor} !important;
  568. }
  569. /* END: Range sliders */
  570. /* Arrows */
  571. .input-caretLeft {
  572. border-right-color: ${lightBorderColor};
  573. }
  574. .input-caretLeft:before {
  575. border-right-color: ${darkBackgroundColor};
  576. }
  577. .popover--layout-s > .popover-arrow:after, .inputBox:after {
  578. border-bottom-color: ${darkBackgroundColor};
  579. }
  580. .popover--layout-n > .popover-arrow:after {
  581. border-top-color: ${darkBackgroundColor};
  582. }
  583. .popover--layout-w > .popover-arrow:after {
  584. border-left-color: ${darkBackgroundColor};
  585. }
  586. .popover--layout-e > .popover-arrow:after {
  587. border-right-color: ${darkBackgroundColor};
  588. }
  589. .popover--layout-s > .popover-arrow::after, .inputBox::after {
  590. border-bottom-color: ${orangeColor};
  591. }
  592. /* END: Arrows */
  593. /* Faders */
  594. .overflow--fade-b-r--l:after, .overflow--fade-b-r--s:after, .overflow--fade-b-r:after, .overflow--fromW3-fade-b-r--l:after, .overflow--fromW3-fade-r--l:after, .thread-title--card:after, .thread-title--list--merchant:after, .thread-title--list:after {
  595. background: -webkit-linear-gradient(left,hsla(0,0%,100%,0),${darkBackgroundColor} 50%,${darkBackgroundColor});
  596. background: linear-gradient(90deg,hsla(0,0%,100%,0),${darkBackgroundColor} 50%,${darkBackgroundColor});
  597. /* filter: brightness(100%) !important; */
  598. }
  599. .fadeEdge--r:after, .overflow--fade:after, .subNavMenu--lFade {
  600. background: -webkit-linear-gradient(left,hsla(0,0%,100%,0),${darkBackgroundColor} 80%);
  601. background: linear-gradient(90deg,hsla(0,0%,100%,0) 0,${darkBackgroundColor} 80%);
  602. filter: brightness(100%) !important;
  603. }
  604. .text--overlay:before {
  605. background-image: -webkit-linear-gradient(left,hsla(0,0%,100%,0),${darkBackgroundColor} 90%);
  606. background-image: linear-gradient(90deg,hsla(0,0%,100%,0),${darkBackgroundColor} 90%);
  607. filter: brightness(100%) !important;
  608. }
  609. .no-touch .carousel-list--air.carousel--isPrev:before {
  610. background: linear-gradient(-270deg, rgba(36, 36, 36, .98) 10%, hsla(0, 0%, 100%, 0));
  611. }
  612. .no-touch .carousel-list--air.carousel--isNext:after {
  613. background: linear-gradient(270deg, rgba(36, 36, 36, .98) 10%, hsla(0, 0%, 100%, 0));
  614. }
  615. /* END: Faders */
  616. .btn--border, .bg--off, .boxSec--fromW3:not(.thread-infos), .boxSec, .voucher-codeCopyButton, .search input, .userHtml-placeholder, .userHtml img, .popover--subNavMenu .popover-content {
  617. border: 1px solid ${darkBorderColor} !important; /* need full border definition for .bg--off */
  618. }
  619. .userProfile-header-inner .bg--color-greyPanel {
  620. border: 1px solid ${lightBorderColor} !important;
  621. }
  622. .commentList-comment--highlighted, .comments-item-inner--edit,
  623. .notification-item--read,
  624. .bg--color-white, .carousel-list--air, .tabbedInterface-tab:hover, .tabbedInterface-tab--selected, .bg--main, .tabbedInterface-tab--horizontal, .tabbedInterface-tab--selected, .comment--selected, .comments-item--in-moderation, .comments-item-inner--active, .comments-item-inner--edit, /*.thread.cept-sale-event-thread.thread--deal,*/ .vote-btn, .search input, .text--overlay, .popover--brandAccent .popover-content, .popover--brandPrimary .popover-content, .popover--default .popover-content, .popover--menu .popover-content, .popover--red .popover-content {
  625. background-color: ${darkBackgroundColor} !important;
  626. }
  627. .notification-item:hover, .notification-item--read:hover {
  628. filter: brightness(75%);
  629. }
  630. .speechBubble:before, .speechBubble:after, .text--color-white.threadTempBadge--card, .text--color-white.threadTempBadge {
  631. color: ${darkBackgroundColor};
  632. }
  633. .stickyBar-top,
  634. .notification-item:not(.notification-item--read),
  635. .bg--off, .js-pagi-bottom, .js-sticky-pagi--on, .bg--color-grey, #main, .subNavMenu--menu .subNavMenu-list {
  636. background-color: ${lightBackgroundColor} !important;
  637. color: ${textColor};
  638. }
  639. .tabbedInterface-tab--transparent {
  640. background-color: ${lightBackgroundColor};
  641. }
  642. .comment-replies,
  643. .userHtml blockquote,
  644. .userHtml hr,
  645. .internalLinking-tabContent, .border--color-greyBackground, .page-divider, .popover-item, .boxSec-divB, .boxSec--fromW3, .cept-comment-link, .border--color-borderGrey, .border--color-greyTint, .staticPageHtml table, .staticPageHtml td, .staticPageHtml th {
  646. border-color: ${lightBorderColor};
  647. }
  648. .bg--color-charcoalTint,
  649. .listingProfile, .tabbedInterface-tab--primary:not(.tabbedInterface-tab--selected):hover, .navMenu-trigger, .navMenu-trigger--active, .navMenu-trigger--active:focus, .navMenu-trigger--active:hover, .navDropDown-link:focus, .navDropDown-link:hover {
  650. background-color: ${veryDarkBackgroundColor} !important;
  651. }
  652. .softMessages-item, .popover--modal .popover-content, .bg--fromW3-color-white, .listingProfile-header, .profileHeader, .bg--em, nav.comments-pagination {
  653. background-color: ${veryDarkBackgroundColor};
  654. color: ${textColor} !important;
  655. }
  656. .bg--color-greyPanel {
  657. background-color: ${veryDarkBackgroundColor};
  658. }
  659. .progressBar::before,
  660. .bg--color-greyTint, .thread-divider, .btn--mode-filter {
  661. background-color: ${textColor};
  662. }
  663. img.avatar[src*="placeholder"] {
  664. filter: brightness(75%);
  665. }
  666. .button--type-primary.button--mode-brand,
  667. .btn--mode-primary, .btn--mode-highlight, .bg--color-brandPrimary { /* Orange Buttons/Backgrounds */
  668. filter: brightness(90%);
  669. }
  670. /* Animated badge */
  671. .animation--colorTransfusion {
  672. background-color: ${orangeColor} !important;
  673. filter: brightness(90%);
  674. }
  675. .animation--colorTransfusion .text--color-brandPrimary {
  676. color: #fff !important;
  677. font-weight: bold !important;
  678. }
  679. /***/
  680.  
  681. .btn--mode-dark-transparent, .btn--mode-dark-transparent:active, .btn--mode-dark-transparent:focus, button:active .btn--mode-dark-transparent, button:focus .btn--mode-dark-transparent {
  682. background-color: inherit;
  683. }
  684. .boxSec-div, .boxSec-div--toW2 {
  685. border-top: 1px solid ${darkBorderColor};
  686. }
  687. .profileHeader, .nav, .navDropDown-item, .navDropDown-link, .navDropDown-pItem, .subNavMenu--menu .subNavMenu-item--separator {
  688. border-bottom: 1px solid ${darkBorderColor};
  689. }
  690. .footer, .subNav, .voteBar, .comment-item {
  691. background-color: ${darkBackgroundColor};
  692. border-bottom: 1px solid ${darkBorderColor};
  693. }
  694. .commentList-item:not(:last-child), /* New comment list class */
  695. .comments-list--top .comments-item:target .comments-item-inner, .comments-list .comments-item, .comments-list .comments-list-item:target .comments-item-inner {
  696. border-bottom: 1px solid ${darkBorderColor};
  697. }
  698. .fadeOuterEdge--l {
  699. box-shadow: -20px 0 17px -3px ${darkBackgroundColor};
  700. }
  701. .vote-box {
  702. box-shadow: 10px 0 10px -3px ${darkBackgroundColor};
  703. }
  704. .btn--mode-boxSec, .btn--mode-boxSec:active, .btn--mode-boxSec:focus, .btn--mode-boxSec:hover, button:active .btn--mode-boxSec, button:focus .btn--mode-boxSec, button:hover .btn--mode-boxSec {
  705. background-color: ${textColor};
  706. }
  707. .overflow--fade:after {
  708. background-color: linear-gradient(90deg,hsla(0,0%,100%,0) 0,#242424 80%) !important;
  709. }
  710. .nav-logo,
  711. img, .badge, .btn--mode-primary-inverted, .btn--mode-primary-inverted--no-state, .btn--mode-primary-inverted--no-state:active, .btn--mode-primary-inverted--no-state:focus, .btn--mode-primary-inverted--no-state:hover, .btn--mode-primary-inverted:active, .btn--mode-primary-inverted:focus, button:active .btn--mode-primary-inverted, button:active .btn--mode-primary-inverted--no-state, button:focus .btn--mode-primary-inverted, button:focus .btn--mode-primary-inverted--no-state, button:hover .btn--mode-primary-inverted--no-state {
  712. filter: invert(2%) brightness(90%);
  713. }
  714. .thread--expired > * {
  715. filter: opacity(50%) brightness(95%);
  716. }
  717. .icon--overflow {
  718. color: ${textColor};
  719. }
  720. .input {
  721. line-height: 1.1rem;
  722. }
  723. /* White Covers/Seals etc. */
  724. .progress--cover, .seal--cover:after {
  725. opacity: 0.8;
  726. background-color: ${veryDarkBackgroundColor} !important;
  727. }
  728. @-webkit-keyframes pulseBgColor {
  729. 0% { background-color: transparent; filter: contrast(100%); }
  730. 15% { background-color: ${veryDarkBackgroundColor}; filter: contrast(105%); }
  731. 85% { background-color: ${veryDarkBackgroundColor}; filter: contrast(105%); }
  732. to { background-color: transparent; filter: contrast(100%); }
  733. }
  734. @keyframes pulseBgColor {
  735. 0% { background-color: transparent; filter: contrast(100%); }
  736. 15% { background-color: ${veryDarkBackgroundColor}; filter: contrast(105%); }
  737. 85% { background-color: ${veryDarkBackgroundColor}; filter: contrast(105%); }
  738. to { background-color: transparent; filter: contrast(100%); }
  739. }
  740. /* END */
  741. /* Reactions */
  742. .popover--reactions .popover-content {
  743. background-color: ${veryDarkBackgroundColor};
  744. border: 1px solid ${lightBorderColor};
  745. }
  746. /* END */
  747.  
  748. /* Buttons: coupons, comments, alerts */
  749. .button--type-tertiary {
  750. background-color: ${darkBackgroundColor} !important;
  751. }
  752. .btn--mode-boxSec,
  753. .btn--mode-primary-inverted,
  754. .btn--mode-primary-inverted--no-state {
  755. /* color: ${secondaryTextColor}; */
  756. background-color: ${darkBackgroundColor} !important;
  757. border: 1px solid ${lightBorderColor} !important;
  758. }
  759. .button--type-tag.button--mode-dark {
  760. background-color: ${lightBackgroundColor} !important;
  761. color: ${textColor} !important;
  762. }
  763. .radio-icon {
  764. background-color: var(--bgNeutralPrimary);
  765. }
  766. .footerMeta-actionSlot .btn--mode-boxSec { /* comment buttons in the grid list */
  767. color: ${secondaryTextColor};
  768. padding-left: 0.57143em !important;
  769. padding-right: 0.57143em !important;
  770. }
  771. .popover--dropdown .popover-content,
  772. .redactor,
  773. .redactor button,
  774. .button--type-primary.button--mode-brand.button--disabled,
  775. .button--emoji,
  776. .button--type-secondary,
  777. .btn--mode-boxSec:hover,
  778. .btn--mode-primary-inverted:hover,
  779. .btn--mode-primary-inverted--no-state:hover,
  780. .btn--mode-boxSec:active,
  781. .btn--mode-primary-inverted:active,
  782. .btn--mode-primary-inverted--no-state:active,
  783. .btn--mode-boxSec:focus,
  784. .btn--mode-primary-inverted:focus,
  785. .btn--mode-primary-inverted--no-state:focus {
  786. background-color: ${veryDarkBackgroundColor} !important;
  787. border: 1px solid ${lightBorderColor} !important;
  788. }
  789. .btn--mode-white--dark,
  790. .btn--mode-white--dark:hover,
  791. .btn--mode-white--dark:active,
  792. .btn--mode-white--dark:focus {
  793. background-color: ${veryDarkBackgroundColor} !important;
  794. }
  795. .redactor button.button--mode-brand:hover,
  796. .button--selected,
  797. .btn--mode-white--dark:hover,
  798. .btn--mode-white--dark:active,
  799. .btn--mode-white--dark:focus {
  800. color: ${orangeColor} !important;
  801. }
  802. .button--type-tertiary.button--mode-default:hover,
  803. .button--type-tertiary.button--mode-default.button--selected,
  804. .button--type-tertiary.button--mode-default.button--selected:hover {
  805. background-color: ${darkBackgroundColor} !important;
  806. color: ${orangeColor} !important;
  807. }
  808.  
  809. /* Voting buttons */
  810. .vote-button {
  811. background-color: ${darkBackgroundColor} !important;
  812. }
  813. .vote-button:not(.vote-button--mode-selected):disabled {
  814. background-color: ${darkBackgroundColor} !important;
  815. color: ${textColor};
  816. }
  817. .vote-button.vote-button--mode-selected span:after {
  818. color: ${darkBackgroundColor} !important;
  819. }
  820.  
  821. /* Set borders of vote box & vote buttons */
  822. button.vote-button--primary {
  823. border-width: 0 !important;
  824. }
  825. .vote-box {
  826. border: 1px solid ${lightBorderColor};
  827. }
  828. /* END: Voting buttons */
  829.  
  830. /* Badges */
  831. .textBadge,
  832. .textBadge--greyBackground {
  833. background-color: ${orangeColor} !important;
  834. color: ${darkestBackgroundColor} !important;
  835. font-weight: bold !important;
  836. }
  837. .comment-newBadge--animated {
  838. color: ${orangeColor} !important;
  839. }
  840. /* END */
  841. `;
  842.  
  843. /* Transparent Footer */
  844. if (pepperTweakerConfig.improvements.transparentPaginationFooter) { // must be after dark theme
  845. css += `
  846. .js-sticky-pagi--on {
  847. background-color: transparent !important;
  848. border-top: none !important;
  849. }
  850. .js-sticky-pagi--on .tGrid-cell:not(:first-child):not(:last-child) {
  851. background-color: ${lightBackgroundColor} !important;
  852. border-top: 1px solid ${darkBorderColor};
  853. border-bottom: 1px solid ${darkBorderColor};
  854. padding-top: 0.7em;
  855. padding-bottom: 0.6em;
  856. }
  857. .js-sticky-pagi--on .tGrid-cell:first-child .hide--toW3, .js-sticky-pagi--on .tGrid-cell:last-child .hide--toW3 {
  858. visibility: hidden;
  859. }
  860. .js-sticky-pagi--on .tGrid-cell:first-child .hide--toW3, .js-sticky-pagi--on .tGrid-cell:last-child .hide--toW3 {
  861. display: none !important;
  862. }
  863. .js-sticky-pagi--on .tGrid-cell:first-child .hide--fromW3, .js-sticky-pagi--on .tGrid-cell:last-child .hide--fromW3 {
  864. display: inline-flex !important;
  865. background-color: ${lightBackgroundColor} !important;
  866. border: 1px solid ${darkBorderColor};
  867. border-radius: 5px;
  868. width: 42px;
  869. height: 42px;
  870. }
  871. .js-sticky-pagi--on .tGrid-cell:first-child .hide--fromW3 svg, .js-sticky-pagi--on .tGrid-cell:last-child .hide--fromW3 svg {
  872. color: #ff7900;
  873. }
  874. .js-sticky-pagi--on .tGrid-cell:nth-child(2) {
  875. padding-left: 1em !important;
  876. border-left: 1px solid ${darkBorderColor};
  877. border-radius: 5px 0 0 5px;
  878. }
  879. .js-sticky-pagi--on .tGrid-cell:nth-last-child(2) {
  880. padding-right: 1em !important;
  881. border-right: 1px solid ${darkBorderColor};
  882. border-radius: 0 5px 5px 0;
  883. }
  884. `;
  885. }
  886. /* END: Transparent Footer */
  887. }
  888. /* END: Dark Theme Style */
  889. }
  890.  
  891. /* Check What Browser */
  892. const isFirefoxBrowser = typeof InstallTrigger !== 'undefined';
  893. // const isOperaBrowser = (!!window.opr && !!opr.addons) || !!window.opera || navigator.userAgent.indexOf(' OPR/') >= 0;
  894.  
  895. // Apply CSS
  896. if (css.length > 0) {
  897. if (isFirefoxBrowser && (document.hidden || !document.hasFocus())) {
  898. const appendStyle = () => {
  899. const style = document.createElement('style');
  900. style.appendChild(document.createTextNode(css));
  901. document.head.appendChild(style);
  902. };
  903. document.addEventListener('DOMContentLoaded', appendStyle);
  904. } else {
  905. const appendStyle = () => {
  906. if (document.head !== null) {
  907. document.head.insertAdjacentHTML('afterend', `<style id="pepper-tweaker-style">${css}</style>`);
  908. } else if (document.documentElement !== null) {
  909. document.documentElement.insertAdjacentHTML('beforeend', `<style id="pepper-tweaker-style">${css}</style>`);
  910. } else {
  911. setTimeout(appendStyle, 10);
  912. }
  913. }
  914. appendStyle();
  915. }
  916. }
  917.  
  918. /*** END: Setting CSS ***/
  919.  
  920. /***** END: RUN AT DOCUMENT START (BEFORE LOAD) *****/
  921.  
  922.  
  923. /**********************************************/
  924. /***** RUN AFTER DOCUMENT HAS BEEN LOADED *****/
  925. /**********************************************/
  926.  
  927. const startPepperTweaker = () => {
  928.  
  929. const pepperTweakerStyleNode = document.getElementById('pepper-tweaker-style');
  930. if (pepperTweakerStyleNode) {
  931. document.head.appendChild(pepperTweakerStyleNode); // move <style> to the proper position (the end of <head>) - only if <style> exists
  932. }
  933.  
  934. if (pepperTweakerConfig.pluginEnabled) {
  935.  
  936. /*** Change Theme Button ***/
  937. const addChangeThemeButton = (searchForm) => {
  938. if (searchForm !== null && searchForm instanceof HTMLElement) { // sanity
  939. const themeButtonDiv = document.createElement('DIV');
  940. themeButtonDiv.classList.add('navDropDown', 'hAlign--all-l', 'vAlign--all-m', 'space--r-3', 'hide--toW2'); // space--r-3 => right space
  941. const themeButtonLink = document.createElement('BUTTON');
  942. themeButtonLink.classList.add('navDropDown-trigger', 'overflow--visible', 'button', 'button--shape-circle', 'button--type-primary', 'button--mode-white', 'button--square');
  943. const themeButtonImg = document.createElement('IMG');
  944. themeButtonImg.src = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABQAAAAUCAMAAAC6V+0/AAAArlBMVEVHcEwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAADDOkjZAAAAOXRSTlMA3fOZiRSwMxFVoU/YkfKdOwP8Q0hu63cnC4Fw9vtaclSktufqy7H+9dvljTK1JhfKEsWlD3a37i9GF/eYAAAAnklEQVQY04XQ1xLCIBBA0QU0YmKiacbee++6//9jignMMj54n5gzQ1lgyNE0G0EeMVzOC0TaWqMvTfuaxhKYHIJbIY4vIe4WNhFbHn8+4Hqy8ZZUdXGoMM2y84W8wSkukuhXdG4EkasWB4oIi++O1JoBwlgdvrMxr4y4YWyFAWNTio3PRFgH8P5iIuUEx1IOKP5e1O4T4/rXOj1jQfcNdIApApX/xhoAAAAASUVORK5CYII=';
  945. themeButtonImg.style.filter = 'invert(60%)';
  946. themeButtonLink.appendChild(themeButtonImg);
  947. themeButtonDiv.appendChild(themeButtonLink);
  948. themeButtonDiv.onclick = () => setConfig({ darkThemeEnabled: !pepperTweakerConfig.darkThemeEnabled }, true);
  949. searchForm.parentNode.insertBefore(themeButtonDiv, searchForm);
  950. }
  951. }
  952.  
  953. const headerPortalObserver = new MutationObserver((allMutations, observer) => {
  954. allMutations.every((mutation) => {
  955. const searchForm = mutation.target.querySelector('form.search');
  956. if (searchForm !== null) {
  957. addChangeThemeButton(searchForm);
  958. observer.disconnect();
  959. return false;
  960. }
  961. });
  962. });
  963. headerPortalObserver.observe(document.querySelector('#header-portal, #ve-header-desktop'), { childList: true, subtree: true });
  964. /*** END: Change Theme Button ***/
  965.  
  966. /*** Menu Links Addition ***/
  967. const subNav = document.querySelector('section.subNav');
  968. if (subNav) {
  969. /* Add my alerts and saved threads links */
  970. const addSubNavMenuItem = (text, link) => { // this can be done with cloneNode too...
  971. const subNavMenu = document.querySelector('.subNavMenu-list');
  972. const savedThreadsElement = document.createElement('LI');
  973. savedThreadsElement.classList.add('subNavMenu-item--separator', 'cept-sort-tab');
  974. const savedThreadsLink = document.createElement('A');
  975. savedThreadsLink.href = link;
  976. savedThreadsLink.classList.add('subNavMenu-item', 'subNavMenu-link', 'boxAlign-ai--all-c');
  977. const savedThreadsSpan = document.createElement('SPAN');
  978. savedThreadsSpan.classList.add('box--all-i', 'size--all-m', 'vAlign--all-m');
  979. const savedThreadsText = document.createTextNode(text);
  980. savedThreadsSpan.appendChild(savedThreadsText);
  981. savedThreadsLink.appendChild(savedThreadsSpan);
  982. savedThreadsElement.appendChild(savedThreadsLink);
  983. subNavMenu.appendChild(savedThreadsElement);
  984. }
  985. let linkElement;
  986. // nie ma już takich linków na stronie...
  987. if (!subNav.querySelector('a[href$="/keyword-alarms"]') && (linkElement = document.querySelector('a[href$="/keyword-alarms"]'))) {
  988. addSubNavMenuItem('Lista alertów', linkElement.href);
  989. }
  990. if (!subNav.querySelector('a[href$="/saved-deals"]') && (linkElement = document.querySelector('a[href$="/saved-deals"]'))) {
  991. addSubNavMenuItem('Ulubione', linkElement.href);
  992. }
  993. }
  994. /*** END: Menu Links Addition ***/
  995. }
  996.  
  997. const createLabeledCheckbox = ({ label = '', id, checked, callback } = {}) => {
  998. const wrapperDiv = document.createElement('DIV');
  999. wrapperDiv.classList.add('space--v-1');
  1000.  
  1001. const labelElement = document.createElement('LABEL');
  1002. labelElement.classList.add('checkbox', 'size--all-m');
  1003.  
  1004. const inputElement = document.createElement('INPUT');
  1005. inputElement.classList.add('input', 'checkbox-input');
  1006. inputElement.type = 'checkbox';
  1007. if (id) {
  1008. inputElement.id = id;
  1009. }
  1010. if (checked === true) {
  1011. inputElement.checked = true;
  1012. }
  1013. if (callback) {
  1014. inputElement.onchange = callback;
  1015. }
  1016.  
  1017. const spanGridCell = document.createElement('SPAN');
  1018. spanGridCell.classList.add('tGrid-cell', 'tGrid-cell--shrink');
  1019. const spanCheckboxBox = document.createElement('SPAN');
  1020. spanCheckboxBox.classList.add('checkbox-box', 'flex--inline', 'boxAlign-jc--all-c', 'boxAlign-ai--all-c');
  1021. const svgElement = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
  1022. svgElement.classList.add('icon', 'icon--tick', 'text--color-brandPrimary', 'checkbox-tick');
  1023. svgElement.setAttribute('width', '20');
  1024. svgElement.setAttribute('height', '16');
  1025. const useElement = document.createElementNS('http://www.w3.org/2000/svg', 'use');
  1026. useElement.setAttributeNS('http://www.w3.org/1999/xlink', 'href', '/assets/img/ico_37b33.svg#tick');
  1027. svgElement.appendChild(useElement);
  1028. spanCheckboxBox.appendChild(svgElement);
  1029. spanGridCell.appendChild(spanCheckboxBox);
  1030.  
  1031. const spanCheckboxText = document.createElement('SPAN');
  1032. spanCheckboxText.classList.add('checkbox-text', 'tGrid-cell', 'space--l-2');
  1033. spanCheckboxText.textContent = label;
  1034.  
  1035. labelElement.appendChild(inputElement);
  1036. labelElement.appendChild(spanGridCell);
  1037. labelElement.appendChild(spanCheckboxText);
  1038.  
  1039. wrapperDiv.appendChild(labelElement);
  1040. return wrapperDiv;
  1041. };
  1042.  
  1043. const createLabeledButton = ({ label = '', id, className = 'default', callback } = {}) => {
  1044. const wrapperDiv = document.createElement('DIV');
  1045. wrapperDiv.classList.add('space--v-2');
  1046.  
  1047. const buttonElement = document.createElement('BUTTON');
  1048. buttonElement.classList.add('btn', 'width--all-12', 'hAlign--all-c', `btn--mode-${className}`);
  1049. if (id) {
  1050. buttonElement.id = id;
  1051. }
  1052. if (callback) {
  1053. buttonElement.onclick = callback;
  1054. }
  1055. const buttonText = document.createTextNode(label);
  1056. buttonElement.appendChild(buttonText);
  1057.  
  1058. wrapperDiv.appendChild(buttonElement);
  1059. return wrapperDiv;
  1060. };
  1061.  
  1062. const createTextInput = ({ id, value, placeholder, required = false } = {}) => {
  1063. const wrapperDiv = document.createElement('DIV');
  1064. wrapperDiv.classList.add('space--v-2');
  1065. const textInput = document.createElement('INPUT');
  1066. textInput.classList.add('input', 'width--all-12', 'size--all-l');
  1067. if (id) {
  1068. textInput.id = id;
  1069. }
  1070. if (value) {
  1071. textInput.value = value;
  1072. }
  1073. if (placeholder) {
  1074. textInput.placeholder = placeholder;
  1075. }
  1076. if (required === true) {
  1077. textInput.required = true;
  1078. }
  1079. wrapperDiv.appendChild(textInput);
  1080. return wrapperDiv;
  1081. };
  1082.  
  1083. /*** Settings Page ***/
  1084. if (location.pathname.indexOf('/settings') >= 0) {
  1085.  
  1086. let settingsPageConfig = {}; // will be set after function definitions (we need create-function names)
  1087.  
  1088. const filterType = Object.freeze({
  1089. deals: 'deals',
  1090. comments: 'comments',
  1091. });
  1092.  
  1093. const createSettingsBlock = label => {
  1094. const blockContainer = document.createElement('DIV');
  1095. blockContainer.classList.add('iGrid', 'space--v-4', 'page-divider');
  1096. const headerContainer = document.createElement('DIV');
  1097. headerContainer.classList.add('iGrid-item', 'width--all-12', 'width--fromW4-6', 'space--b-2');
  1098. const headerElement = document.createElement('H2');
  1099. headerElement.classList.add('userProfile-title--sub', 'text--b');
  1100. const labelText = document.createTextNode(label);
  1101. headerElement.appendChild(labelText);
  1102. headerContainer.appendChild(headerElement);
  1103. blockContainer.appendChild(headerContainer);
  1104. return blockContainer;
  1105. };
  1106.  
  1107. const createSettingsBlockHeader = (label, divider = true) => {
  1108. const headerContainer = document.createElement('DIV');
  1109. headerContainer.classList.add('formList-row', 'width--all-12', 'space--b-2');
  1110. const headerElement = document.createElement('H2');
  1111. headerElement.classList.add('userProfile-title--sub', 'text--b', 'space--v-4');
  1112. const labelText = document.createTextNode(label);
  1113. headerElement.appendChild(labelText);
  1114. if (divider) {
  1115. headerContainer.appendChild(createDivider(false));
  1116. }
  1117. headerContainer.appendChild(headerElement);
  1118. return headerContainer;
  1119. };
  1120.  
  1121. const createSettingsRow = label => {
  1122. const rowDiv = document.createElement('DIV');
  1123. rowDiv.classList.add('formList-row');
  1124. const labelSpan = document.createElement('SPAN');
  1125. labelSpan.classList.add('formList-label');
  1126. const labelText = document.createTextNode(label);
  1127. const contentDiv = document.createElement('DIV');
  1128. contentDiv.classList.add('formList-content');
  1129. labelSpan.appendChild(labelText);
  1130. rowDiv.appendChild(labelSpan);
  1131. rowDiv.appendChild(contentDiv);
  1132. return rowDiv;
  1133. }
  1134.  
  1135. const addSelectOptionElement = (selectElement, optionValue) => {
  1136. const optionElement = document.createElement('OPTION');
  1137. optionElement.value = optionValue;
  1138. optionElement.appendChild(document.createTextNode(optionValue))
  1139. selectElement.appendChild(optionElement);
  1140. return optionElement;
  1141. };
  1142.  
  1143. // Works only in settings page because of cloneNode() !!!
  1144. const createSelectInput = ({ options = [createNewFilterName], value, id, callback } = {}) => {
  1145. const select = document.querySelector('#defaultLandingPage .select').cloneNode(true);
  1146. const selectCtrl = select.querySelector('.select-ctrl');
  1147. selectCtrl.name = 'filter_selection';
  1148. if (id) {
  1149. selectCtrl.id = id;
  1150. }
  1151. if (callback) {
  1152. selectCtrl.onchange = callback;
  1153. }
  1154. removeAllChildren(selectCtrl);
  1155. for (const optionValue of options) {
  1156. addSelectOptionElement(selectCtrl, optionValue);
  1157. }
  1158. if (value && options.includes(value)) {
  1159. selectCtrl.value = value;
  1160. }
  1161. select.querySelector('.js-select-val').textContent = options[selectCtrl.selectedIndex];
  1162. return select;
  1163. };
  1164.  
  1165. const createLabeledInput = ({ id, callback, beforeLabel = '', afterLabel = '', min, max, step, value } = {}) => {
  1166. const wrapperDiv = document.createElement('DIV');
  1167. wrapperDiv.classList.add('space--v-2');
  1168.  
  1169. const divElement = document.createElement('DIV');
  1170. divElement.classList.add('tGrid', 'tGrid--auto', 'width--all-12');
  1171. const inputElement = document.createElement('INPUT');
  1172. inputElement.classList.add('input', 'width--all-12', 'bRad--r-r');
  1173. inputElement.type = 'number';
  1174. if (id) {
  1175. inputElement.id = id;
  1176. }
  1177. if (callback) {
  1178. inputElement.onchange = callback;
  1179. }
  1180. if (isNumeric(min)) {
  1181. inputElement.min = min;
  1182. }
  1183. if (isNumeric(max) && (max >= min)) {
  1184. inputElement.max = max;
  1185. }
  1186. if (isNumeric(step)) {
  1187. inputElement.step = step;
  1188. }
  1189. if (isNumeric(value) && (!isNumeric(min) || value >= min) && (!isNumeric(max) || value <= max)) {
  1190. inputElement.value = value;
  1191. }
  1192. divElement.appendChild(inputElement);
  1193.  
  1194. if (afterLabel && afterLabel.length > 0) {
  1195. const labelElement = document.createElement('LABEL');
  1196. labelElement.classList.add('tGrid-cell', 'tGrid-cell--shrink', 'btn', 'bRad--l-r', 'vAlign--all-m');
  1197. const labelText = document.createTextNode(afterLabel);
  1198. labelElement.appendChild(labelText);
  1199. divElement.appendChild(labelElement);
  1200. }
  1201.  
  1202. if (beforeLabel && beforeLabel.length > 0) {
  1203. const spanElement = document.createElement('SPAN');
  1204. spanElement.classList.add('formList-label-content', 'lbox--v-1');
  1205. const spanText = document.createTextNode(beforeLabel);
  1206. spanElement.appendChild(spanText);
  1207. wrapperDiv.appendChild(spanElement);
  1208. }
  1209.  
  1210. wrapperDiv.appendChild(divElement);
  1211. return wrapperDiv;
  1212. };
  1213.  
  1214. const createColorInput = ({ color = '#000000', id, callback, wrapper = false, style: { width = '36px', height = '30px', ...restStyle } = {} } = {}) => {
  1215. const colorInput = document.createElement('INPUT');
  1216. colorInput.type = 'color';
  1217. colorInput.value = color;
  1218. Object.assign(colorInput.style, { width, height, restStyle }); // default values for style.width and/or style.height will be overwritten if supplied to style parameter
  1219. if (id) {
  1220. colorInput.id = id;
  1221. }
  1222. if (callback) {
  1223. colorInput.onchange = callback;
  1224. }
  1225. if (wrapper === true) {
  1226. const wrapperDiv = document.createElement('DIV');
  1227. wrapperDiv.classList.add('space--v-1');
  1228. wrapperDiv.appendChild(colorInput);
  1229. return wrapperDiv;
  1230. }
  1231. return colorInput;
  1232. };
  1233.  
  1234. const createDivider = (verticalSpace = true) => {
  1235. const wrapperDiv = document.createElement('DIV');
  1236. if (verticalSpace) {
  1237. wrapperDiv.classList.add('space--v-4');
  1238. }
  1239. const dividerDiv = document.createElement('DIV');
  1240. dividerDiv.classList.add('page-divider');
  1241. dividerDiv.style.width = '682px'; // TODO: set to 100% some how...
  1242. wrapperDiv.appendChild(dividerDiv);
  1243. return wrapperDiv;
  1244. };
  1245.  
  1246. // display: { id: 'deals-filter-style-display', label: 'Ukrycie' },
  1247. // opacity: { id: 'deals-filter-style-opacity', label: 'Przezroczystość' },
  1248. // border: { id: 'deals-filter-style-border', label: 'Ramka' },
  1249. const createStylingBlock = ({ display, opacity, border, borderColor, borderStyle, styleText, callback } = {}) => {
  1250. // const createStylingBlock = ({
  1251. // display: { label: displayLabel = 'Ukrycie', id: displayId, checked: displayChecked = false } = {},
  1252. // opacity, border, borderColor, styleText, callback
  1253. // } = {}) => {
  1254. const wrapperDiv = document.createElement('DIV');
  1255. if (display) {
  1256. wrapperDiv.appendChild(createLabeledCheckbox({ label: display.label, id: display.id, checked: display.checked, callback }));
  1257. }
  1258. // if (true) {
  1259. // wrapperDiv.appendChild(createLabeledCheckbox({ label: displayLabel, id: displayId, checked: displayChecked, callback }));
  1260. // }
  1261. if (opacity) {
  1262. wrapperDiv.appendChild(createLabeledCheckbox({ label: opacity.label, id: opacity.id, checked: opacity.checked, callback }));
  1263. }
  1264. if (border) {
  1265. const borderBlock = createLabeledCheckbox({ label: border.label, id: border.id, checked: border.checked, callback });
  1266. borderBlock.style.display = 'flex';
  1267. borderBlock.style.justifyContent = 'space-between';
  1268. borderBlock.style.alignItems = 'center';
  1269. if (borderColor) {
  1270. borderBlock.appendChild(createColorInput({ color: borderColor.color, id: borderColor.id, callback }));
  1271. }
  1272. if (borderStyle) {
  1273. const borderStyleSelect = createSelectInput({ options: ['dashed', 'dotted', 'solid', 'double', 'groove', 'ridge', 'inset', 'outset'], value: borderStyle.value, id: borderStyle.id, callback });
  1274. borderStyleSelect.classList.replace('width--all-12', 'width--all-6');
  1275. borderBlock.appendChild(borderStyleSelect);
  1276. }
  1277. wrapperDiv.appendChild(borderBlock);
  1278. }
  1279. if (styleText) {
  1280. wrapperDiv.appendChild(createTextInput({ id: styleText.id }));
  1281. }
  1282. return wrapperDiv;
  1283. };
  1284.  
  1285. const getFilterType = elementId => {
  1286. for (const type of Object.values(filterType)) {
  1287. for (const rowBlock of Object.values(settingsPageConfig[type].rows)) {
  1288. for (const rowEntry of Object.values(rowBlock.entries)) {
  1289. if ((rowEntry.params.id === elementId) || Object.values(rowEntry.params).some(item => item.id === elementId)) {
  1290. return type;
  1291. }
  1292. }
  1293. }
  1294. }
  1295. return undefined;
  1296. }
  1297.  
  1298. const filterSelectionChange = event => {
  1299. const filterType = getFilterType(event.target.id);
  1300. const selectedFilter = pepperTweakerConfig[`${filterType}Filters`].find(filter => filter.name === event.target.value);
  1301. updateFilterInputs(filterType, selectedFilter);
  1302. };
  1303.  
  1304. const updateFilterStyle = event => {
  1305. const filterType = getFilterType(event.target.id);
  1306. const styleBlock = settingsPageConfig[filterType].rows.filterStyle.entries.style;
  1307. const styleTextInput = document.getElementById(styleBlock.params.styleText.id);
  1308. let styleValue = {};
  1309. if (styleTextInput.value) {
  1310. try {
  1311. styleValue = styleBlock.parse(styleTextInput.value);
  1312. } catch (error) {
  1313. alert(messageWrongJSONStyle);
  1314. }
  1315. }
  1316. styleValue.display = styleBlock.params.display && document.getElementById(styleBlock.params.display.id).checked ? defaultFilterStyleValues[filterType].display : undefined;
  1317. styleValue.opacity = styleBlock.params.opacity && document.getElementById(styleBlock.params.opacity.id).checked ? defaultFilterStyleValues[filterType].opacity : undefined;
  1318. if (styleBlock.params.border) {
  1319. let borderColor = defaultFilterStyleValues[filterType].borderColor;
  1320. let borderStyle = defaultFilterStyleValues[filterType].borderStyle;
  1321. let enableBorderCheckbox = false;
  1322. if (styleBlock.params.borderColor) {
  1323. borderColor = document.getElementById(styleBlock.params.borderColor.id).value;
  1324. if (event.target.id === styleBlock.params.borderColor.id) {
  1325. enableBorderCheckbox = true;
  1326. }
  1327. }
  1328. if (styleBlock.params.borderStyle) {
  1329. borderStyle = document.getElementById(styleBlock.params.borderStyle.id).value;
  1330. if (event.target.id === styleBlock.params.borderStyle.id) {
  1331. enableBorderCheckbox = true;
  1332. }
  1333. }
  1334. if (enableBorderCheckbox) {
  1335. document.getElementById(styleBlock.params.border.id).checked = true;
  1336. }
  1337. styleValue.border = document.getElementById(styleBlock.params.border.id).checked ? `${defaultFilterStyleValues[filterType].borderWidth} ${borderStyle} ${borderColor}` : undefined;
  1338. }
  1339. styleTextInput.value = styleBlock.stringify(styleValue);
  1340. };
  1341.  
  1342. const updateFilterInputs = (filterType, filter) => {
  1343. const filterSelectionInput = document.getElementById(settingsPageConfig[filterType].rows.filterSelection.entries.filterSelectionInput.params.id);
  1344. const filterOptionElement = filter && filter.name && filterSelectionInput.querySelector(`option[value="${filter.name}"]`) || null;
  1345. filterSelectionInput.value = filterOptionElement && filterOptionElement.value || createNewFilterName;
  1346. filterSelectionInput.parentNode.querySelector('.js-select-val').textContent = filter && filter.name || createNewFilterName;
  1347.  
  1348. for (const settingRow of Object.values(settingsPageConfig[filterType].rows)) {
  1349. for (const [key, value] of Object.entries(settingRow.entries)) {
  1350. switch (value.create) {
  1351. case createTextInput:
  1352. document.getElementById(value.params.id).value = filter && filter[key] && (filter[key].source || filter[key]) || '';
  1353. break;
  1354. case createLabeledInput:
  1355. document.getElementById(value.params.id).value = filter && filter[key] || '';
  1356. break;
  1357. case createLabeledCheckbox:
  1358. document.getElementById(value.params.id).checked = (filter && isBoolean(filter[key])) ? filter[key] : value.params.checked;
  1359. break;
  1360. case createStylingBlock:
  1361. document.getElementById(value.params.display.id).checked = (filter && filter.style && filter.style.display === 'none') ? true : false;
  1362. document.getElementById(value.params.opacity.id).checked = (filter && filter.style && filter.style.opacity && parseFloat(filter.style.opacity) < 1) ? true : false;
  1363. document.getElementById(value.params.border.id).checked = (filter && filter.style && filter.style.border && filter.style.border !== 'none') ? true : false;
  1364. document.getElementById(value.params.borderColor.id).value = filter && filter.style && filter.style.border && getCSSBorderColor(filter.style.border) || defaultFilterStyleValues[filterType].borderColor;
  1365. document.getElementById(value.params.borderStyle.id).value = filter && filter.style && filter.style.border && getCSSBorderStyle(filter.style.border) || defaultFilterStyleValues[filterType].borderStyle;
  1366. document.getElementById(value.params.borderStyle.id).parentNode.querySelector('.js-select-val').textContent = document.getElementById(value.params.borderStyle.id).value;
  1367. document.getElementById(value.params.styleText.id).value = filter && filter.style && JSON.stringify(filter.style) || '';
  1368. }
  1369. }
  1370. }
  1371. };
  1372.  
  1373. const applyFilterChanges = event => {
  1374. const filterType = getFilterType(event.target.id);
  1375. const filterArrayName = `${filterType}Filters`;
  1376. const filterSelectionInput = document.getElementById(settingsPageConfig[filterType].rows.filterSelection.entries.filterSelectionInput.params.id);
  1377. const filterName = filterSelectionInput.value;
  1378. const filterIndex = (filterSelectionInput.selectedIndex === 0) ? pepperTweakerConfig[filterArrayName].length : pepperTweakerConfig[filterArrayName].findIndex(item => item.name === filterName); // if selectedIndex === 0 => add new filter
  1379.  
  1380. if (event.target.id === settingsPageConfig[filterType].rows.filterSaveRemove.entries.removeButton.params.id) {
  1381. if (filterSelectionInput.selectedIndex === 0) {
  1382. alert('Musisz wybrać filtr, aby go usunąć.');
  1383. return;
  1384. }
  1385. if (confirm(`Potwierdź usunięcie filtra: ${filterName}`)) {
  1386. pepperTweakerConfig[filterArrayName].splice(filterIndex, 1);
  1387. filterSelectionInput.querySelector(`option[value="${filterName}"]`).remove();
  1388. localStorage.setItem(`PepperTweaker.config.${filterArrayName}`, JSON.stringify(pepperTweakerConfig[filterArrayName], JSONRegExpReplacer));
  1389. updateFilterInputs(filterType, null);
  1390. }
  1391. }
  1392. else if (event.target.id === settingsPageConfig[filterType].rows.filterSaveRemove.entries.saveButton.params.id) {
  1393. const newFilter = {};
  1394. let isEmptyFilter = true;
  1395. for (const settingRow of Object.values(settingsPageConfig[filterType].rows)) {
  1396. for (const [key, value] of Object.entries(settingRow.entries)) {
  1397. switch (value.create) {
  1398. case createTextInput:
  1399. case createLabeledInput:
  1400. const inputNode = document.getElementById(value.params.id);
  1401. const inputValue = inputNode && inputNode.value.trim();
  1402. if (inputValue) {
  1403. newFilter[key] = value.parse ? value.parse(inputValue) : inputValue;
  1404. if (value.filtering !== false) {
  1405. isEmptyFilter = false;
  1406. }
  1407. } else if (inputNode.required) {
  1408. alert(`Musisz wypełnić pole ${settingRow.label.toLowerCase()}`);
  1409. return;
  1410. }
  1411. break;
  1412. case createLabeledCheckbox:
  1413. const inputChecked = document.getElementById(value.params.id).checked;
  1414. if (inputChecked !== value.params.checked) {
  1415. newFilter[key] = inputChecked;
  1416. if (value.filtering !== false) {
  1417. isEmptyFilter = false;
  1418. }
  1419. }
  1420. break;
  1421. case createStylingBlock: // this can be combine with Text & Labeled above
  1422. newFilter[key] = document.getElementById(value.params.styleText.id).value.trim();
  1423. if (newFilter[key].length < 1) {
  1424. alert('Nie wybrano żadnego stylu dla filtra.');
  1425. return;
  1426. }
  1427. try {
  1428. newFilter[key] = value.parse(newFilter[key]);
  1429. } catch (error) {
  1430. alert(messageWrongJSONStyle);
  1431. return;
  1432. }
  1433. if (Object.entries(newFilter[key]).length === 0) {
  1434. alert('Podany styl jest obiektem pustym.');
  1435. return;
  1436. }
  1437. break;
  1438. }
  1439. }
  1440. }
  1441.  
  1442. if (isEmptyFilter) {
  1443. alert('Wszystkie parametry nie mogą być puste. Taki filtr nie ma sensu ;)');
  1444. return;
  1445. }
  1446.  
  1447. const confirmMessage = (filterSelectionInput.selectedIndex === 0) ? `Czy chcesz utworzyć nowy filtr: ${newFilter.name}?` : `Czy rzeczywiście nadpisać filtr: ${filterName}?`;
  1448. if (confirm(confirmMessage)) {
  1449. filterSelectionInput.options[filterSelectionInput.selectedIndex || filterSelectionInput.options.length] = new Option(newFilter.name, newFilter.name, false, true);
  1450. pepperTweakerConfig[filterArrayName][filterIndex] = newFilter;
  1451. localStorage.setItem(`PepperTweaker.config.${filterArrayName}`, JSON.stringify(pepperTweakerConfig[filterArrayName], JSONRegExpReplacer));
  1452. updateFilterInputs(filterType, pepperTweakerConfig[filterArrayName][filterIndex]);
  1453. }
  1454. }
  1455. };
  1456.  
  1457. const createSupportButtons = () => {
  1458. const wrapperDiv = document.createElement('DIV');
  1459. wrapperDiv.classList.add('space--v-2');
  1460.  
  1461. const anchorElement = document.createElement('A');
  1462. anchorElement.href = 'https://buycoffee.to/peppertweaker';
  1463. anchorElement.target = '_blank';
  1464.  
  1465. const imageElement = document.createElement('IMG');
  1466. imageElement.src = 'https://raw.githubusercontent.com/PepperTweaker/PepperTweaker/master/images/buycoffeeto-banner.gif';
  1467. imageElement.style.width = '200px';
  1468.  
  1469. anchorElement.appendChild(imageElement);
  1470. wrapperDiv.appendChild(anchorElement);
  1471.  
  1472. return wrapperDiv;
  1473. };
  1474.  
  1475. /* Settings Page Configuration */
  1476. settingsPageConfig = {
  1477. support: {
  1478. header: 'Wsparcie projektu',
  1479. rows: {
  1480. buttons: {
  1481. label: 'Wesprzyj rozwój stawiając Misiowi kawkę! :D',
  1482. entries: {
  1483. buyCoffeeTo: {
  1484. create: createSupportButtons,
  1485. },
  1486. },
  1487. },
  1488. },
  1489. },
  1490. global: {
  1491. header: 'Ustawienia ogólne',
  1492. rows: {
  1493. pluginEnabled: {
  1494. label: 'Włącz/Wyłącz plugin',
  1495. entries: {
  1496. pluginEnabledCheckbox: {
  1497. create: createLabeledCheckbox,
  1498. params: {
  1499. label: 'PepperTweaker aktywny',
  1500. id: 'plugin-enabled',
  1501. checked: pepperTweakerConfig.pluginEnabled,
  1502. callback: event => setConfig({ pluginEnabled: event.target.checked }, true),
  1503. },
  1504. },
  1505. },
  1506. },
  1507. darkThemeEnabled: {
  1508. label: 'Ciemny motyw',
  1509. entries: {
  1510. darkThemeCheckbox: {
  1511. create: createLabeledCheckbox,
  1512. params: {
  1513. label: 'Ciemny motyw włączony',
  1514. id: 'dark-theme-enabled',
  1515. checked: pepperTweakerConfig.darkThemeEnabled,
  1516. callback: event => setConfig({ darkThemeEnabled: event.target.checked }, true),
  1517. },
  1518. },
  1519. },
  1520. },
  1521. improvements: {
  1522. label: 'Poprawki / Ulepszenia',
  1523. entries: {
  1524. listToGrid: {
  1525. create: createLabeledCheckbox,
  1526. params: {
  1527. label: 'Zamień listę na siatkę',
  1528. id: 'list-to-grid',
  1529. checked: pepperTweakerConfig.improvements.listToGrid,
  1530. callback: event => setConfig({ improvements: { listToGrid: event.target.checked } }, false),
  1531. },
  1532. },
  1533. gridColumnCount: {
  1534. create: createLabeledInput,
  1535. params: {
  1536. id: 'grid-column-count',
  1537. afterLabel: 'Liczba kolumn',
  1538. min: 0,
  1539. step: 1,
  1540. value: pepperTweakerConfig.improvements.gridColumnCount,
  1541. callback: event => setConfig({ improvements: { gridColumnCount: event.target.value } }, false),
  1542. },
  1543. },
  1544. transparentPaginationFooter: {
  1545. create: createLabeledCheckbox,
  1546. params: {
  1547. label: 'Przezroczysta stopka z paginacją',
  1548. id: 'transparent-pagination-footer',
  1549. checked: pepperTweakerConfig.improvements.transparentPaginationFooter,
  1550. callback: event => setConfig({ improvements: { transparentPaginationFooter: event.target.checked } }, false),
  1551. },
  1552. },
  1553. hideTopDealsWidget: {
  1554. create: createLabeledCheckbox,
  1555. params: {
  1556. label: 'Ukryj wigdet najgorętszych okazji',
  1557. id: 'hide-top-deals',
  1558. checked: pepperTweakerConfig.improvements.hideTopDealsWidget,
  1559. callback: event => setConfig({ improvements: { hideTopDealsWidget: event.target.checked } }, false),
  1560. },
  1561. },
  1562. hideGroupsBar: {
  1563. create: createLabeledCheckbox,
  1564. params: {
  1565. label: 'Ukryj pasek grup z przyciskami "Kategorie", "Kupony", "Okazje" etc.',
  1566. id: 'hide-groups-bar',
  1567. checked: pepperTweakerConfig.improvements.hideGroupsBar,
  1568. callback: event => setConfig({ improvements: { hideGroupsBar: event.target.checked } }, false),
  1569. },
  1570. },
  1571. repairDealDetailsLinksCheckbox: {
  1572. create: createLabeledCheckbox,
  1573. params: {
  1574. label: 'Napraw linki w opisach ofert i komentarzach',
  1575. id: 'repair-deal-details-links',
  1576. checked: pepperTweakerConfig.improvements.repairDealDetailsLinks,
  1577. callback: event => setConfig({ improvements: { repairDealDetailsLinks: event.target.checked } }, false),
  1578. },
  1579. },
  1580. repairDealImageLinkCheckbox: {
  1581. create: createLabeledCheckbox,
  1582. params: {
  1583. label: 'Klik na miniaturce oferty zawsze otwiera pełnowymiarowy obrazek',
  1584. id: 'repair-deal-image-link',
  1585. checked: pepperTweakerConfig.improvements.repairDealImageLink,
  1586. callback: event => setConfig({ improvements: { repairDealImageLink: event.target.checked } }, false),
  1587. },
  1588. },
  1589. addLikeButtonsToBestCommentsCheckbox: {
  1590. create: createLabeledCheckbox,
  1591. params: {
  1592. label: 'Dodaj przyciski "Lubię to" do najlepszych komentarzy',
  1593. id: 'add-like-buttons-to-best-comments',
  1594. checked: pepperTweakerConfig.improvements.addLikeButtonsToBestComments,
  1595. callback: event => setConfig({ improvements: { addLikeButtonsToBestComments: event.target.checked } }, false),
  1596. },
  1597. },
  1598. addSearchInterfaceCheckbox: {
  1599. create: createLabeledCheckbox,
  1600. params: {
  1601. label: 'Dodaj interfejs wyszukiwania',
  1602. id: 'add-search-interface',
  1603. checked: pepperTweakerConfig.improvements.addSearchInterface,
  1604. callback: event => setConfig({ improvements: { addSearchInterface: event.target.checked } }, false),
  1605. },
  1606. },
  1607. addCommentPreviewOnProfilePage: {
  1608. create: createLabeledCheckbox,
  1609. params: {
  1610. label: 'Dodaj podgląd komentarzy na stronie profilu użytkownika',
  1611. id: 'add-comment-preview-on-profile-page',
  1612. checked: pepperTweakerConfig.improvements.addCommentPreviewOnProfilePage,
  1613. callback: event => setConfig({ improvements: { addCommentPreviewOnProfilePage: event.target.checked } }, false),
  1614. },
  1615. },
  1616. },
  1617. },
  1618. autoUpdate: {
  1619. label: 'Automatyczne odświeżanie',
  1620. entries: {
  1621. dealsDeafultCheckbox: {
  1622. create: createLabeledCheckbox,
  1623. params: {
  1624. label: 'Domyślne odświeżanie listy ofert',
  1625. id: 'autoupdate-deals-default-enabled',
  1626. checked: pepperTweakerConfig.autoUpdate.dealsDefaultEnabled,
  1627. callback: event => setConfig({ autoUpdate: { dealsDefaultEnabled: event.target.checked } }, false),
  1628. },
  1629. },
  1630. commentsDefaultCheckbox: {
  1631. create: createLabeledCheckbox,
  1632. params: {
  1633. label: 'Domyślne odświeżanie komentarzy',
  1634. id: 'autoupdate-comments-default-enabled',
  1635. checked: pepperTweakerConfig.autoUpdate.commentsDefaultEnabled,
  1636. callback: event => setConfig({ autoUpdate: { commentsDefaultEnabled: event.target.checked } }, false),
  1637. },
  1638. },
  1639. soundEnabledCheckbox: {
  1640. create: createLabeledCheckbox,
  1641. params: {
  1642. label: 'Powiadom dzwiękiem',
  1643. id: 'autoupdate-sound-enabled',
  1644. checked: pepperTweakerConfig.autoUpdate.soundEnabled,
  1645. callback: event => setConfig({ autoUpdate: { soundEnabled: event.target.checked } }, false),
  1646. },
  1647. },
  1648. askBeforeLoadCheckbox: {
  1649. create: createLabeledCheckbox,
  1650. params: {
  1651. label: 'Pytaj przed załadowaniem',
  1652. id: 'autoupdate-ask-before-load',
  1653. checked: pepperTweakerConfig.autoUpdate.askBeforeLoad,
  1654. callback: event => setConfig({ autoUpdate: { askBeforeLoad: event.target.checked } }, false),
  1655. },
  1656. },
  1657. },
  1658. },
  1659. importExportConfig: {
  1660. label: 'Import/Export ustawień',
  1661. entries: {
  1662. importButton: {
  1663. create: createLabeledButton,
  1664. params: {
  1665. label: 'Import z pliku',
  1666. className: 'default',
  1667. callback: importConfigFromFile
  1668. },
  1669. },
  1670. exportButton: {
  1671. create: createLabeledButton,
  1672. params: {
  1673. label: 'Export do pliku',
  1674. className: 'default',
  1675. callback: saveConfigFile
  1676. },
  1677. },
  1678. },
  1679. },
  1680. resetConfig: {
  1681. label: 'Reset ustawień',
  1682. entries: {
  1683. importButton: {
  1684. create: createLabeledButton,
  1685. params: {
  1686. label: 'Zresetuj wszystkie ustawienia',
  1687. className: 'error',
  1688. callback: () => {
  1689. if (confirm('Czy zresetować wszystkie ustawienia do wartości domyślnych pluginu?')) {
  1690. resetConfig();
  1691. updateFilterInputs(filterType.deals, null);
  1692. updateFilterInputs(filterType.comments, null);
  1693. }
  1694. },
  1695. },
  1696. },
  1697. },
  1698. },
  1699. },
  1700. },
  1701. deals: {
  1702. header: 'Filtry okazji',
  1703. rows: {
  1704. filterSelection: {
  1705. label: 'Wybierz filtr',
  1706. entries: {
  1707. filterSelectionInput: {
  1708. create: createSelectInput,
  1709. params: {
  1710. id: 'deals-filter-selection',
  1711. options: [createNewFilterName, ...pepperTweakerConfig.dealsFilters.map(filter => filter.name)],
  1712. callback: filterSelectionChange,
  1713. },
  1714. },
  1715. },
  1716. },
  1717. filterName: {
  1718. label: 'Nazwa filtra',
  1719. entries: {
  1720. name: {
  1721. create: createTextInput,
  1722. params: {
  1723. id: 'deals-filter-name',
  1724. placeholder: 'Wpisz nazwę filtra',
  1725. required: true,
  1726. },
  1727. filtering: false,
  1728. },
  1729. },
  1730. },
  1731. filterKeyword: {
  1732. label: 'Słowa kluczowe',
  1733. entries: {
  1734. keyword: {
  1735. create: createTextInput,
  1736. params: {
  1737. id: 'deals-filter-keyword',
  1738. },
  1739. parse: newRegExp,
  1740. },
  1741. },
  1742. },
  1743. filterMerchant: {
  1744. label: 'Sprzedawca',
  1745. entries: {
  1746. merchant: {
  1747. create: createTextInput,
  1748. params: {
  1749. id: 'deals-filter-merchant',
  1750. },
  1751. parse: newRegExp,
  1752. },
  1753. },
  1754. },
  1755. filterUser: {
  1756. label: 'Użytkownik',
  1757. entries: {
  1758. user: {
  1759. create: createTextInput,
  1760. params: {
  1761. id: 'deals-filter-user',
  1762. },
  1763. parse: newRegExp,
  1764. },
  1765. },
  1766. },
  1767. filterGroup: {
  1768. label: 'Grupy',
  1769. entries: {
  1770. groups: {
  1771. create: createTextInput,
  1772. params: {
  1773. id: 'deals-filter-groups',
  1774. },
  1775. parse: newRegExp,
  1776. },
  1777. },
  1778. },
  1779. filterLocal: {
  1780. label: 'Oferty lokalne',
  1781. entries: {
  1782. local: {
  1783. create: createLabeledCheckbox,
  1784. params: {
  1785. label: 'Filtr tylko dla ofert lokalnych',
  1786. id: 'deals-filter-local',
  1787. checked: false,
  1788. },
  1789. },
  1790. },
  1791. },
  1792. filterPrice: {
  1793. label: 'Cena',
  1794. entries: {
  1795. priceBelow: {
  1796. create: createLabeledInput,
  1797. params: {
  1798. id: 'deals-filter-price-below',
  1799. beforeLabel: 'Cena poniżej',
  1800. afterLabel: 'zł',
  1801. min: 0,
  1802. step: 0.01,
  1803. },
  1804. parse: parseFloat,
  1805. },
  1806. priceAbove: {
  1807. create: createLabeledInput,
  1808. params: {
  1809. id: 'deals-filter-price-above',
  1810. beforeLabel: 'Cena powyżej',
  1811. afterLabel: 'zł',
  1812. min: 0,
  1813. step: 0.01,
  1814. },
  1815. parse: parseFloat,
  1816. },
  1817. discountBelow: {
  1818. create: createLabeledInput,
  1819. params: {
  1820. id: 'deals-filter-discount-below',
  1821. beforeLabel: 'Wielkość rabatu poniżej',
  1822. afterLabel: '%',
  1823. min: 0,
  1824. max: 100,
  1825. step: 1,
  1826. },
  1827. parse: parseInt,
  1828. },
  1829. discountAbove: {
  1830. create: createLabeledInput,
  1831. params: {
  1832. id: 'deals-filter-discount-above',
  1833. beforeLabel: 'Wielkość rabatu powyżej',
  1834. afterLabel: '%',
  1835. min: 0,
  1836. max: 100,
  1837. step: 1,
  1838. },
  1839. parse: parseInt,
  1840. },
  1841. },
  1842. },
  1843. filterStyle: {
  1844. label: 'Styl (CSS)',
  1845. entries: {
  1846. style: {
  1847. create: createStylingBlock,
  1848. params: {
  1849. display: { id: 'deals-filter-style-display', label: 'Ukrycie' },
  1850. opacity: { id: 'deals-filter-style-opacity', label: 'Przezroczystość' },
  1851. border: { id: 'deals-filter-style-border', label: 'Ramka' },
  1852. borderColor: { id: 'deals-filter-style-border-color', color: defaultFilterStyleValues.deals.borderColor },
  1853. borderStyle: { id: 'deals-filter-style-border-style', value: defaultFilterStyleValues.deals.borderStyle },
  1854. styleText: { id: 'deals-filter-style-text' },
  1855. callback: updateFilterStyle,
  1856. },
  1857. parse: JSON.parse,
  1858. stringify: JSON.stringify,
  1859. filtring: false,
  1860. },
  1861. },
  1862. },
  1863. filterActive: {
  1864. label: 'Włącz/Wyłącz filtr',
  1865. entries: {
  1866. active: {
  1867. create: createLabeledCheckbox,
  1868. params: {
  1869. label: 'Filtr aktywny',
  1870. id: 'deals-filter-active',
  1871. checked: true,
  1872. },
  1873. filtring: false,
  1874. },
  1875. },
  1876. },
  1877. filterSaveRemove: {
  1878. label: 'Zapisz/Usuń filtr',
  1879. entries: {
  1880. saveButton: {
  1881. create: createLabeledButton,
  1882. params: {
  1883. label: 'Zapisz filtr',
  1884. id: 'deals-filter-save',
  1885. className: 'success',
  1886. callback: applyFilterChanges
  1887. },
  1888. },
  1889. removeButton: {
  1890. create: createLabeledButton,
  1891. params: {
  1892. label: 'Usuń filtr',
  1893. id: 'deals-filter-remove',
  1894. className: 'error',
  1895. callback: applyFilterChanges
  1896. },
  1897. },
  1898. },
  1899. },
  1900. },
  1901. },
  1902. comments: {
  1903. header: 'Filtry komentarzy',
  1904. rows: {
  1905. filterSelection: {
  1906. label: 'Wybierz filtr',
  1907. entries: {
  1908. filterSelectionInput: {
  1909. create: createSelectInput,
  1910. params: {
  1911. id: 'comments-filter-selection',
  1912. options: [createNewFilterName, ...pepperTweakerConfig.commentsFilters.map(filter => filter.name)],
  1913. callback: filterSelectionChange,
  1914. },
  1915. },
  1916. },
  1917. },
  1918. filterName: {
  1919. label: 'Nazwa filtra',
  1920. entries: {
  1921. name: {
  1922. create: createTextInput,
  1923. params: {
  1924. id: 'comments-filter-name',
  1925. placeholder: 'Wpisz nazwę filtra',
  1926. required: true,
  1927. },
  1928. filtering: false,
  1929. },
  1930. },
  1931. },
  1932. filterKeyword: {
  1933. label: 'Słowa kluczowe',
  1934. entries: {
  1935. keyword: {
  1936. create: createTextInput,
  1937. params: {
  1938. id: 'comments-filter-keyword',
  1939. },
  1940. parse: newRegExp,
  1941. },
  1942. },
  1943. },
  1944. filterUser: {
  1945. label: 'Użytkownik',
  1946. entries: {
  1947. user: {
  1948. create: createTextInput,
  1949. params: {
  1950. id: 'comments-filter-user',
  1951. },
  1952. parse: newRegExp,
  1953. },
  1954. },
  1955. },
  1956. filterStyle: {
  1957. label: 'Styl (CSS)',
  1958. entries: {
  1959. style: {
  1960. create: createStylingBlock,
  1961. params: {
  1962. display: { id: 'comments-filter-style-display', label: 'Ukrycie' },
  1963. opacity: { id: 'comments-filter-style-opacity', label: 'Przezroczystość' },
  1964. border: { id: 'comments-filter-style-border', label: 'Ramka' },
  1965. borderColor: { id: 'comments-filter-style-border-color', color: defaultFilterStyleValues.comments.borderColor },
  1966. borderStyle: { id: 'comments-filter-style-border-style', value: defaultFilterStyleValues.comments.borderStyle },
  1967. styleText: { id: 'comments-filter-style-text' },
  1968. callback: updateFilterStyle,
  1969. },
  1970. parse: JSON.parse,
  1971. stringify: JSON.stringify,
  1972. filtring: false,
  1973. },
  1974. },
  1975. },
  1976. filterActive: {
  1977. label: 'Włącz/Wyłącz filtr',
  1978. entries: {
  1979. active: {
  1980. create: createLabeledCheckbox,
  1981. params: {
  1982. label: 'Filtr aktywny',
  1983. id: 'comments-filter-active',
  1984. checked: true,
  1985. },
  1986. filtring: false,
  1987. },
  1988. },
  1989. },
  1990. filterSaveRemove: {
  1991. label: 'Zapisz/Usuń filtr',
  1992. entries: {
  1993. saveButton: {
  1994. create: createLabeledButton,
  1995. params: {
  1996. label: 'Zapisz filtr',
  1997. id: 'comments-filter-save',
  1998. className: 'success',
  1999. callback: applyFilterChanges
  2000. },
  2001. },
  2002. removeButton: {
  2003. create: createLabeledButton,
  2004. params: {
  2005. label: 'Usuń filtr',
  2006. id: 'comments-filter-remove',
  2007. className: 'error',
  2008. callback: applyFilterChanges
  2009. },
  2010. },
  2011. },
  2012. },
  2013. },
  2014. },
  2015. };
  2016.  
  2017. const preferencesTabLink = document.querySelector('a[href="#preferences"]');
  2018. const filtersTabLink = preferencesTabLink.cloneNode(true);
  2019. filtersTabLink.href = '#peppertweaker';
  2020. filtersTabLink.classList.remove('tabbedInterface-tab--selected');
  2021. filtersTabLink.querySelector('svg use').setAttribute('xlink:href', '/assets/img/ico_37b33.svg#filter');
  2022. const filtersTabLinkInner = filtersTabLink.querySelector('.js-tabbedInterface-tab--inner-preferences');
  2023. filtersTabLinkInner.classList.remove('js-tabbedInterface-tab--inner-preferences');
  2024. filtersTabLinkInner.classList.add('js-tabbedInterface-tab--inner-filters');
  2025. filtersTabLinkInner.textContent = 'PepperTweaker';
  2026. preferencesTabLink.parentNode.appendChild(filtersTabLink);
  2027. const preferencesTab = document.getElementById('tab-preferences');
  2028. const filtersTab = preferencesTab.cloneNode(true);
  2029. filtersTab.id = 'tab-peppertweaker';
  2030. const filtersTitle = filtersTab.querySelector('.userProfile-title');
  2031. filtersTitle.textContent = 'PepperTweaker';
  2032.  
  2033. const rowsContainer = filtersTab.querySelector('.formList');
  2034. removeAllChildren(rowsContainer);
  2035.  
  2036. for (const settingsBlock of Object.values(settingsPageConfig)) {
  2037. rowsContainer.appendChild(createSettingsBlockHeader(settingsBlock.header));
  2038. for (const rowBlock of Object.values(settingsBlock.rows)) {
  2039. const newRowNode = createSettingsRow(rowBlock.label);
  2040. const newRowNodeContent = newRowNode.querySelector('.formList-content');
  2041. for (const rowEntry of Object.values(rowBlock.entries)) {
  2042. const newRowEntryNode = rowEntry.create(rowEntry.params);
  2043. if (rowEntry.style) {
  2044. Object.assign(newRowEntryNode.style, rowEntry.style);
  2045. }
  2046. newRowNodeContent.appendChild(newRowEntryNode);
  2047. }
  2048. rowsContainer.appendChild(newRowNode);
  2049. }
  2050. }
  2051.  
  2052. preferencesTab.parentNode.insertBefore(filtersTab, preferencesTab.parentNode.querySelector('.userProfile-footer'));
  2053. updateFilterInputs(filterType.deals, null);
  2054. updateFilterInputs(filterType.comments, null);
  2055. if (location.hash.indexOf('peppertweaker') >= 0) {
  2056. filtersTab.classList.remove('hide');
  2057. filtersTabLink.classList.add('tabbedInterface-tab--selected');
  2058. }
  2059. return;
  2060. }
  2061. /*** END: Settings Page Configuration ***/
  2062.  
  2063. /*** Search Engines ***/
  2064. const searchEngine = Object.freeze({
  2065. google: { name: 'Google', url: 'https://www.google.pl/search?q=', icon: 'data:image/png;base64,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' },
  2066. ceneo: { name: 'Ceneo', url: 'https://www.ceneo.pl/;szukaj-', icon: 'data:image/x-icon;base64,AAABAAMAMDAAAAEACACoDgAANgAAACAgAAABAAgAqAgAAN4OAAAQEAAAAQAIAGgFAACGFwAAKAAAADAAAABgAAAAAQAIAAAAAAAACQAAAAAAAAAAAAAAAQAAAAAAAGu5+gBtufoAz+j9ANDo/QDx+P8Acrz6ANTr/QDV6/0A9vv/APf7/wB5v/oAG5P3AByT9wD8/v8AHZP3AP3+/wD+/v8AfsL6AKDS/AAilvcAI5b3AKbV/ACn1fwAKJn3ACmZ9wCu2PwAUKz5AFGs+QDV6/4AVq/5ANvu/gBdsvkAXrL5AOHx/gDi8f4AZLX5AOj0/gCLyPsAjMj7AC6c+ADu9/4AL5z4AO/3/gCRy/sANJ/4ADWf+AA2n/gAmM77ALne/QA7ovgAPKL4AMDh/QBBpfgAQqX4AGS1+gDH5P0AR6j4AGq4+gDM5/0Azef9AHG7+gDS6v0A9Pr/APX6/wAakvcA+v3/ABuS9wD7/f8A/P3/AH3B+gAflfcAIJX3ACGV9wCl1PwAJ5j3AEio+QCr1/wALJv3AE6r+QBPq/kAsdr8ALLa/ADU6v4AVK75AFWu+QC43fwA2e3+ANrt/gDf8P4AhMT7AOXz/gCJx/sA7Pb+AC2b+ACPyvsAM574AJbN+wC43f0AOaH4ADqh+ABFp/gAZ7f6AMrm/QDR6f0A0un9APL5/wBzvfoA8/n/AHS9+gB1vfoA+fz/APr8/wB6wPoAHZT3AB6U9wD+//8A////AKPT/AAkl/cAJZf3AKnW/AAqmvcAS6r5AE2q+QCu2fwAr9n8ALDZ/ABSrfkAU635ALTc/AC13PwAWrD5AN3v/gBes/kA3u/+AF+z+QBgs/kAgMP7AOPy/gDk8v4Ah8b7AIjG+wDp9f4A6vX+AOv1/gDw+P4A8fj+ADKd+ACTzPsAN6D4ADig+ACZz/sAPaP4AMLi/QBEpvgAZrb6AMfl/QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnIODEJAQEBCDHFycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnIMQkcpNYAgI4WANF1GQgxycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJyDA5jbBkckD9uQ28/jj1MBWNyDHJycnJycnJycnJycnJycnJycnJycnJycnJycnIMLCaEDXR0dHR0dHR0dHR0DViUYgxycnJycnJycnJycnJycnJycnJycnJycnJycgxTOxB0dHR0dHR0dHR0dHR0dHR0A0sMcnJycnJycnJycnJycnJycnJycnJycnJyDIiLdHR0dHR0dHR0dHR0dHR0dHR0dI0LcnJycnJycnJycnJycnJycnJycnJycnILTiF0dHR0dHR0dHR0dHR0dHR0dHR0JHsMcnJycnJycnJycnJycnJycnJycnJycg4nmXR0dHR0dHR0dA+Si1ppEHR0dHR0XnJycnJycnJycnJycnJycnJycnJycnJycgwRDXR0dHR0dHRzPUV6MTJPRTM+dHRnLQxycnJycnJycnJycnJycnJycnJycnJyDl9SdHR0dHR0dHSClkALDAwLQkoffQY2DHJycnJycnJycnJycnJycnJycnJycnJyQgFDdHR0dHR0dBxjC3JycnJycnELEydGcnJycnJycnJycnJycnJycnJycnJycnJySBl0dHR0dHR0D3BCcnJycnJycnJycnFycnJycnJycnJycnJycnJycnJycnJycnIMLoR0dHR0dHR0ITEMcnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJCHT90dHR0dHR0ghNycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJACnR0dHR0dHR0JQtycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnIML3R0dHR0dHQPAEBycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJGfnR0dHR0dHQIVEJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJ3M3R0dHR0dHQoOAtycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnEXOnR0dHR0dHQkmAxycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnFNPXR0dHR0dHQilQxycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnEnHHR0dHR0dHRYLQxycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnEnB3R0dHR0dHRXkw5ycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnF5A3R0dHR0dHRXkw5ycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnFKN3R0dHR0dHSGLQ5ycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnITMHR0dHR0dHSKYgxycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJySXR0dHR0dHSPNAxycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnILW3R0dHR0dHRrTwtycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJAZUN0dHR0dHRDm0BycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnIMZFx0dHR0dHR0WwtycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJxeWZ0dHR0dHR0YRRycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJyDCt0dHR0dHR0JJoLcnJycnJycnJyDAxycnJycnJycnJycnJycnJycnJycnJycnJyCxuRdHR0dHR0dGBycnJycnJycnEMLS1xcnJycnJycnJycnJycnJycnJycnJycnJycXdhdHR0dHR0dChlDAxycnJxQndqVgI1DHJycnJycnJycnJycnJycnJycnJycnJycguHa3R0dHR0dHSOWZYTcXIXVFEJdHSBGA5ycnJycnJycnJycnJycnJycnJycnJycnIUFXR0dHR0dHR0DYZVdRacBHR0dHRDjHJycnJycnJycnJycnJycnJycnJycnJycnIMMmd0dHR0dHR0dHR0dHR0dHR0dHR0XB0LcnJycnJycnJycnJycnJycnJycnJycnJyDBoedHR0dHR0dHR0dHR0dHR0dHR0dIlCcnJycnJycnJycnJycnJycnJycnJycnJycgwaAnR0dHR0dHR0dHR0dHR0dHRBUC0OcnJycnJycnJycnJycnJycnJycnJycnJycnIMYhIqdHR0dHR0dHR0dHR0Q2htGAxycnJycnJycnJycnJycnJycnJycnJycnJycnJyDEh/Eh4JdHR0dHR0RCQwPJMLcXJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnILci2DEZd4fBZeOTR2Qg5ycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycg5CQAxyRnILQAxycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnJycnIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA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' }, // ?nocatnarrow=1
  2067. skapiec: { name: 'Skąpiec', url: 'https://www.skapiec.pl/szukaj/w_calym_serwisie/', icon: 'data:image/x-icon;base64,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////////i772/xV35f8Vd+X/FXfl/yhtvP9zSjP/c0oz/21CKv9jNRz/YzUc/2M1HP9jNRz/Ty0V/08tFf9JNy7/GYn5/xmJ+f8Vd+X/FXfl/xZ97P8XgO//F4Dv/xeA7/8XgO//F4Dv/zCN8f+Rw/f/6PL9//////////////////////96tvb/Fn3s/xV35f8Vd+X/FXfl/z5hj/9zSjP/c0oz/2g8JP9jNRz/YzUc/2M1HP9PLRX/Ty0V/0U+P/8Zifn/GYj4/xV35f8Vd+X/FXfl/xZ97P8XgO//F4Dv/xeA7/9apfT/9fr+////////////////////////////7fX9/yyL8P8XgO//Fn3s/xV35f8Vd+X/Fnjl/2BRUv9zSjP/ckgx/2Q3Hv9jNRz/YzUc/08tFf9PLRX/Rjw6/xmJ+f8Zifn/FXfl/xV35f8Vd+X/FXfl/xZ97P8XgO//JIfw//H4/v///////////////////////////9Ll+v88jen/Fnvp/xeA7/8XgO//Fn3s/xV35f8Vd+X/IHTP/3NKM/9zSjP/bUIq/2M1HP9jNRz/Ty0V/08tFf9LNCb/GYn5/xmJ+f8Veef/FXfl/xV35f8Vd+X/FXfl/xZ97P9Xo/P//////////////////f7//7HU+v9VovP/F3vo/xV35f8Vd+X/Fnvp/xeA7/8XgO//Fn3s/xV35f8XgO//S1py/3NKM/9zSjP/Zjkg/2M1HP9PLRX/Ty0V/08tFf8egeX/GYn5/xZ96/8Vd+X/FXfl/xV35f8Vd+X/FXfl/1uk8v////////////////9usPX/F4Dv/xeA7/8XgO//FXro/xV35f8Vd+X/Fnvp/xeA7/8XgO//Fnrp/xiE8/8egeX/b0s3/3NKM/9vRC3/YzUc/08tFf9PLRX/Ty0V/ytqrP8Zifn/GIPy/xV35f8Vd+X/FXfl/xV35f8Vd+X/Po/q/////////////////26w9f8XgO//GoHv/0qc8/+cyfj/qc73/xV35f8Vd+X/Fnvp/xeA7/8Veuj/GYj4/xmJ+f9YRkH/c0oz/3NKM/9nOiH/Ty0V/08tFf9PLRX/Pkte/xmJ+f8ZiPj/FXnn/xV35f8Vd+X/FXfl/xV35f8XeOX/6PL8/////////////f7//+Du/f/2+v7/////////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' },
  2068. aliexpress: { name: 'Aliexpress', url: 'https://www.aliexpress.com/wholesale?SearchText=', icon: 'data:image/x-icon;base64,AAABAAEAICAAAAEAIACoEAAAFgAAACgAAAAgAAAAQAAAAAEAIAAAAAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQu5kAELua3BC7m8QQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELubxBC7mtwQu5kAAAAAAAAAAAAAAAAAELuZ0BC7m/QQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/QQu5nQAAAAABC7mQAQu5v0ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/QQu5kAELua3BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7mtwQu5vEELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELubxBC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BS/m/yVJ6f89Xuv/PV7r/yVJ6f8FL+b/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/MFPq/5ys9f/p7fz//v7+/////////////v7+/+nt/P+crPX/MFPq/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/DTbm/5eo9P/8/P7////////////////////////////////////////////8/P7/l6j0/w025v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/xY95//K0/n////////////6+/7/sL33/2uE8P9JaOz/SWjs/2uE8P+wvff/+vv+////////////ytP5/xY95/8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8JMub/w835////////////v8r4/yhM6f8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8oTOn/v8r4////////////w835/wky5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/4CV8v///////////6a19v8IMeb/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8IMeb/prX2////////////gJXy/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8YP+j/9PX9///////P1/r/CjPm/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8KM+b/z9f6///////09f3/GD/o/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/3SL8f///////v7+/0Ni7P8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v9DYuz//v7+//////90i/H/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/vMf4///////a4Pv/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v/a4Pv//////7zH+P8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v/p7Pz//////56u9f8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/56u9f//////6ez8/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BjDm//r7/v//////hZny/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/hZny///////6+/7/BjDm/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/qrj2/+vu/f88XOv/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v88XOv/6+/9/6m49v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/Bi/m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8GL+b/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wMv5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8DL+b/Az7p/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wM+6f8CYPH/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/AmDx/wCR/f8DOej/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wM56P8Akf3/AJn//wCF+v8DOej/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8ELub/BC7m/wQu5v8DOej/AIX6/wCZ//8Amf/xAJn//wCR/f8BYvL/A0Dq/wMy5/8DMeb/AzHm/wMx5v8DMeb/AzHm/wMx5v8DMeb/AzHm/wMx5v8DMeb/AzHm/wMx5v8DMeb/AzHm/wMx5v8DMeb/AzHm/wMx5v8DMeb/AzHm/wMy5/8DQOr/AWLy/wCR/f8Amf//AJn/8QCZ/rcAmf//AJn//wCZ//8Amf//AJn//wCZ//8Amf//AJn//wCZ//8Amf//AJn//wCZ//8Amf//AJn//wCZ//8Amf//AJn//wCZ//8Amf//AJn//wCZ//8Amf//AJn//wCZ//8Amf//AJn//wCZ//8Amf//AJn//wCZ//8Amf+3AJn/QACZ//0Amf//AJn//wCZ//8Amf//AJn//wCZ//8Amf//AJn//wCZ//8Amf//AJn//wCZ//8Amf//AJn//wCZ//8Amf//AJn//wCZ//8Amf//AJn//wCZ//8Amf//AJn//wCZ//8Amf//AJn//wCZ//8Amf//AJn//QCZ/0AAAAAAAJn/dACZ//0Amf//AJn//wCZ//8Amf//AJn//wCZ//8Amf//AJn//wCZ//8Amf//AJn//wCZ//8Amf//AJn//wCZ//8Amf//AJn//wCZ//8Amf//AJn//wCZ//8Amf//AJn//wCZ//8Amf//AJn//wCZ//0Amf90AAAAAAAAAAAAAAAAAJn/QACZ/7cAmf7xAJn//wCZ//8Amf//AJn//wCZ//8Amf//AJn//wCZ//8Amf//AJn//wCZ//8Amf//AJn//wCZ//8Amf//AJn//wCZ//8Amf//AJn//wCZ//8Amf//AJn//wCZ/vEAmf+3AJn/QAAAAAAAAAAA4AAAB8AAAAOAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACAAAABwAAAA+AAAAc=' },
  2069. banggood: { name: 'Banggood', url: 'https://www.banggood.com/search/$$.html', icon: 'data:image/x-icon;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAQAABILAAASCwAAAAAAAAAAAAASduzaEnbs/xJ27P8Sduz/Enbs/xJ27P8Sduz/Enbs/xJ27P8Sduz/Enbs/xJ27P8Sduz/Enbs/xJ27P8SduzaEnbs/xJ27P8Sduz/Enbs/xJ27P8Sduz/Enbs/xJ27P8Sduz/Enbs/xJ27P8Sduz/Enbs/xJ27P8Sduz/Enbs/hJ27P8Sduz/Enbs/xJ27P8Sduz/Enbs/xJ27P8Sduz/Enbs/xJ27P8Sduz/Enbs/xJ27P8Sduz/Enbs/xJ27P8Sduz/Enbs/xZ47P8Xeez/F3ns/xV47P8Qdez/EXbs/xJ27P8PdOz/FHfs/xZ47P8Qdez/EXXs/xJ27P8Sduz/EXbs/xx87f+ZxPf/vNj6/7rX+v+31fn/eLH0/xt77f8Xeez/Zqfz/7LS+f+51/n/hrn1/yqE7v8Rdez/Enbs/xF17P8hfu3/0+X7/7zY+v9wrPP/m8X3/+/2/v9ipPL/aKjz/+71/v+v0fn/mcT3/+Lu/f+w0fn/HXzt/xF27P8Rdez/IX7t/9Tm/P+IuvX/Bm/r/yeC7v/d6/z/jb32/8Hb+v+v0fn/GHrt/xl67f9wrPT/7PT9/0WT8P8PdOz/EXXs/yF+7f/S5fv/yN/7/4u89v+x0vn/yeD7/1mf8v/e7Pz/drD0/xF27P+Pvvb/zuL7/+jy/f9RmvH/DnTs/xF17P8hfu3/0uX7/8jf+/+MvPb/xN36/7PT+f87ju//3uz8/3ew9P8OdOz/NIrv/0aU8P9OmfH/I4Dt/xF17P8Rdez/IX7t/9Tm/P+Ju/b/CHDr/1Wd8f/t9f7/Vp3x/7rX+f+61/n/J4Lu/xl67f94sfT/v9r6/zOJ7/8Qdez/EXXs/yF+7f/S5fv/1ef8/6XL+P/S5fv/2On8/zGI7/9TnPH/4e79/9Xm/P/K4Pv/7fX+/5XC9/8Yeu3/EXbs/xF27P8Zeu3/ca30/4y99v+Nvfb/gbb1/0CQ8P8Sduz/Enbs/z+Q8P9+tPX/hrn1/1ad8f8ae+3/EXXs/xJ27P8Sduz/Enbs/w907P8PdOz/D3Ts/w507P8Qdez/Enbs/xJ27P8Qdez/DnTs/w507P8PdOz/EXbs/xJ27P8Sduz/Enbs/xJ27P8Sduz/Enbs/xJ27P8Sduz/Enbs/xJ27P8Sduz/Enbs/xJ27P8Sduz/Enbs/xJ27P8Sduz/Enbs/xJ27P8Sduz/Enbs/xJ27P8Sduz/Enbs/xJ27P8Sduz/Enbs/xJ27P8Sduz/Enbs/xJ27P8Sduz/Enbs/xJ27P8SduzaEnbs/xJ27P8Sduz/Enbs/xJ27P8Sduz/Enbs/xJ27P8Sduz/Enbs/xJ27P8Sduz/Enbs/xJ27P8SduzaAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==' },
  2070. joybuy: { name: 'Joybuy', url: 'https://www.joybuy.com/search?keywords=', icon: 'data:image/x-icon;base64,AAABAAkAMDAQAAEABABoBgAAlgAAACAgEAABAAQA6AIAAP4GAAAQEBAAAQAEACgBAADmCQAAMDAAAAEACACoDgAADgsAACAgAAABAAgAqAgAALYZAAAQEAAAAQAIAGgFAABeIgAAMDAAAAEAIACoJQAAxicAACAgAAABACAAqBAAAG5NAAAQEAAAAQAgAGgEAAAWXgAAKAAAADAAAABgAAAAAQAEAAAAAACABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAIAAAACAgACAAAAAgACAAICAAACAgIAAwMDAAAAA/wAA/wAAAP//AP8AAAD/AP8A//8AAP///wCRkZGRkZGRkZGRkZGRkZGRkZGRkZGRkZGVl5WXlZeVl5WXlZeVl5WXlZeVl5WXlZkZkZl5mVmZeZlZmXmZWZl5mVmZeZlZmXmXlZeRWTlZkVk5WZFZOVmRWTlZkVk5WRmRk5kZl5k5WTmVk1mTlZNZk5WTWZOVk5UZWVlZeRlZOVlZOZeVmTmXlZk5l5WZOVmXmTmXmVmVmZeZWRmRlZWZGXlZGZl5WZORl5eXl5d5eVkZeYeYeYl3l5eXlZWRlZWXlXiIiId5eTl5eHiIiIiIiJiZeTkZeZmVl5iIiIiIl5WZeIiIiIiIiIiJeVl5kXkZeYiPj4iIiXl5iP///4//j4iImJlZWZGXl5iIiIiIiJeZePj4iIiIiIiIh3l5k1mZWXmJiI/4iIl5iPiIiYmIiIiIiHl5WZEZeZeY2IiPiI2VeP+IiXeYmIj/+IeXmXmVl5WXmYiIiIiZiPiImJl5iYiIiIiZeRmTmZeZeZiI+IiXmPiIl5WVl52I+IiJWVmVlZlZl5eIj4iZiPiI2XmXmXmIj4iJl5kZGXkXmVmIiIh5iPiJiZWZWZeYiPiHmVmXmRmZWXmIj4iVePiIl5OVl5l4eI+JeXmRl5U5GXmHiPiZiPiIeVlZOVmXePiIlZmVkZlZeZd4j4h5iPiHeXmZWZeYmPiNl5cZeVk5lZiYiPiZePiIl5l5GTl5iI+Hl5mVmTlZWTmIj4iViPiIl5WRl5WXmPiIl5GTlZWZOViYj4iXmPiIl5lZeZl5iI+JiZeVmRl5WZeIiPiViPiInZOZkVl5iI+Il5mRl5kZl5mHj4iZiPiIl5WXmXl5iI+JeVkZeVl5GXmIiPh5iPiIl5kZWRl4mPiIl5WVmRmVlZiYiP2ZiPiIl5eVk5eYiP+JWZmTlZeRk5eIj4h5ePiNeZWTlZmIiPiJl5WVk5GXmVmJ+PiZiPiImJkZWXeIiPjXmVkZWVmZWXmIj4h5iPiHeVOXmJiIiIh5eRmXmZcZeZiYj4iZePiIl5l5h4iI+IiXmXmZF5lZlZeIiPiXePiIiYmHeIiPiImJlZEVmRmXkZeYj4iZiP+IiIiIiIiIjZeVkZmZeVORl5iIiPhZiI//+PiI+PiIiXmXmXkZGZlZWZWYiIiVmPiI+Pj4+IiJiZeZWRmXlZeZOXl5jYl5iYiIiIiIjYmJeXlZOVmRk5GVmVl5eXmVmJiYl52Xl5eVlZkZWTmVlZWTlZl5eYl5l5eVeXmJeZl5l5WTmVkZeZOVk5eZeZeZeXl5l5eZeXmVmRmVlZOZlZWZWZlZl5lZlZlZeZWXmVl5F5eZOZVTkZl5lxl5WVk5WXmXlZl5lZkZmZGVlZmZWXkZGVmRmTlZOZWZmXmRk5eVNZWTk5UZeZGXmTlZeVmVlZOVGRlZWVmZmXmVlZmVkZeZWVmTkZWZOZWTlZeTmRlxWZGXmXmRl5lZGTWVlZOVlZGVmXmVl5WZl5WZGRmXmVkZeZkZk5WTkZeZeZGRmRk5WRk1l5UZWRl5lZeXlZkZWZlZGVl5WXlZGXmZWZEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoAAAAIAAAAEAA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AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////AAEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEF/w0KAgH/////CwUBAQEBAgYK/woB/woFCAz/BgEBAQEBAQsNAf8IAQECDAwBAQEBAQEI/wH/CAEBAQf/BAEBAQEBCP8B/wgBAQEF/wUBAQEBAQj/Af8IAQEBBv8FAQEBAQEI/wH/CAEBAQv/AQEBAQEBCP8B/wgBBAv/CQEBAQEBAQj/Af////8NCAEBAQEBAQEDBQEFBQUFAgEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEBAQEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAKAAAADAAAABgAAAAAQAgAAAAAACAJQAAAAAAAAAAAAAAAAAAAAAAACIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8mGcn/Kh7K/y4iy/86Ls7/RzzR/1NJ1P9WTNX/VUvU/1RJ1P9QRtP/S0DS/0U60P8+M87/NCjM/yseyv8kGMj/IxfI/yIVyP8mGcn/NyvN/0g90f9XTdX/V03V/1dN1f9XTdX/V03V/1dN1f9XTdX/V03V/1dN1f9XTdX/U0jU/01D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yP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP88Mc7/Z17Z/5KL5P+0sOz/zcrz/+fl+f/d2/b/mZPl/1VL1P8zJ8z/enLe/8G97//6+v3/19T1/7Sv7P+RiuT/bWTb/0k/0v8mGcn/IhXI/yIVyP8iFcj/IxfI/yYZyP8oHMn/RTrQ/3Bo2/+cl+b/vLju/8/N8//j4fj/2Nb1/5yX5v9gV9f/MibM/ywgyv8nGsn/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP86Ls7/YFfX/4eA4f+qper/ycXx/+jm+f/h3/f/m5bm/1ZM1f8zJ8z/enLe/8G97//6+v3/19T1/7Sv7P+RiuT/bWTb/0k/0v8mGcn/IhXI/yIVyP8iFcj/IhXI/yMXyP8kGMj/Oi/O/1xT1v9+d9//oJrn/8G+7//j4fj/4uD3/6ei6f9tZNr/PjPO/zQpzP8qHsr/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP84LM3/W1HW/3933/+inOj/xcLw/+jn+f/k4vj/nZjm/1dN1f8zJ8z/enLe/8G97//6+v3/19T1/7Sv7P+RiuT/bWTb/0k/0v8mGcn/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/MibM/0tB0v9lXNn/iYLh/7ax7f/i4fj/6ej5/7Cr6/93b93/SD7R/zswzv8tIcr/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP84LM3/W1HW/3933/+inOj/xcLw/+jn+f/k4vj/nZjm/1dN1f8zJ8z/enLe/8G97//6+v3/19T1/7Sv7P+RiuT/bWTb/0k/0v8mGcn/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/MCTL/0c80f9eVdf/gXrg/7Gt6//h3/f/6uj5/7Ku6/96c97/TEPS/z0yzv8vIsv/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP84LM3/W1HW/3933/+inOj/xcLw/+jn+f/k4vj/nZjm/1dN1f8zJ8z/enLe/8G97//6+v3/19T1/7Sv7P+RiuT/bWTb/0k/0v8mGcn/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/LiLL/0I30P9WTdX/enLe/6yo6v/f3ff/6un5/7Sw7P99dt7/UEfT/0A1z/8wJMv/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP84LM3/W1HW/3933/+inOj/xcLw/+jn+f/k4vj/nZjm/1dN1f8zJ8z/enLe/8G97//6+v3/19T1/7Sv7P+RiuT/bWTb/0k/0v8mGcn/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/LSDK/z4zz/9QR9P/dGzc/6ik6f/d3Pb/6+n6/7Wy7P+Aet//VEvU/0I40P8xJcv/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP84LM3/W1HW/3933/+inOj/xcLw/+jn+f/k4vj/nZjm/1dN1f8zJ8z/enLe/8G97//6+v3/19T1/7Sv7P+RiuT/bWTb/0k/0v8mGcn/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/LiHL/0E2z/9UStT/d3Dd/6um6v/e3ff/6+n6/7Wy7P+Aet//VEvU/0I40P8xJcv/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP84LM3/W1HW/3933/+inOj/xcLw/+jn+f/k4vj/nZjm/1dN1f8zJ8z/enLe/8G97//6+v3/19T1/7Sv7P+RiuT/bWTb/0k/0v8mGcn/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/LiLL/0M40P9YTtX/e3Pe/62o6v/f3ff/6+n6/7Wy7P+Aet//VEvU/0I40P8xJcv/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP84LM3/W1HW/3933/+inOj/xcLw/+jn+f/k4vj/nZjm/1dN1f8zJ8z/enLe/8G97//6+v3/19T1/7Sv7P+RiuT/bWTb/0k/0v8mGcn/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/LyPL/0U60P9bUtb/f3ff/6+r6//g3vf/6+n6/7Wy7P+Aet//VEvU/0I40P8xJcv/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP84LM3/W1HW/3933/+inOj/xcLw/+jn+f/k4vj/nZjm/1dN1f8zJ8z/enLe/8G97//6+v3/19T1/7Sv7P+RiuT/bWTb/0k/0v8mGcn/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/NSnM/1NJ1P9yadv/lY/k/7257v/l5Pj/6Of5/66p6v9za9z/RDnQ/zgtzf8sIMr/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP84LM3/W1HW/3933/+inOj/xcLw/+jn+f/k4vj/nZjm/1dN1f8zJ8z/enLe/8G97//6+v3/19T1/7Sv7P+RiuT/bWTb/0k/0v8mGcn/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/Oi7O/2FY1/+IgeH/q6fq/8vI8v/r6vr/5uX5/6ah6f9mXdn/NCjM/y0hy/8nGsn/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP84LM3/W1HW/3933/+inOj/xcLw/+jn+f/k4vj/nZjm/1dN1f8zJ8z/enLe/8G97//6+v3/19T1/7Sv7P+RiuT/bWTb/0k/0v8mGcn/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/PzTP/29m2/+emef/wr7w/9nX9f/w7/v/5OP4/56Z5/9YTtX/JBfI/yMWyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP84LM3/W1HW/3933/+inOj/xcLw/+jn+f/k4vj/nZjm/1dN1f8zJ8z/enLe/8G97//6+v3/19T1/7Sv7P+RiuT/bWTb/0k/0v8mGcn/JRjI/ygcyf8sIMr/NCnM/z4zz/9IPtH/Zl3Z/4+I4/+4tO3/0M7z/9jV9f/f3ff/zMny/46I4/9QRtP/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP84LM3/W1HW/3933/+inOj/xcLw/+jn+f/k4vj/nZjm/1dN1f8zJ8z/enLe/8G97//6+v3/19T1/7Sv7P+RiuT/bWTb/0k/0v8mGcn/KBzJ/zAky/84Lc3/SkDS/19W1/91bdz/kYvj/7Kt7P/T0PT/3tz2/9TS9P/KyPL/sa3r/3113v9JPtH/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP84LM3/W1HW/3933/+inOj/xcLw/+jn+f/k4vj/nZjm/1dN1f8zJ8z/enLe/8G97//6+v3/19T1/7Sv7P+RiuT/bWTb/0k/0v8mGcn/LCDK/zgtzf9EOtD/YFfX/4B53/+hnOf/vLnu/9XS9P/t7Pr/7Ov6/9HO8/+2su3/lZDk/2tj2v9BNs//IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP84LM3/W1HW/3933/+inOj/xcLw/+jn+f/k4vj/nZjm/1dN1f8zJ8z/enLe/8G97//7+/7/4N73/8bC8f+rpur/kInj/3Vt3P9aUNb/X1bX/2lh2f9za9z/iYPh/6Oe6P+9ue7/zcry/9bU9f/f3ff/1NL0/7Sw7P+UjuT/dG3c/1ZN1f84Lc3/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP84LM3/W1HW/3933/+inOj/xcLw/+jn+f/k4vj/nZjm/1dN1f8zJ8z/enLe/8G97//9/P7/7ez6/97b9v/Oy/P/vrvv/6+q6/+fmuf/op3o/6ij6f+uqer/ubXt/8bD8f/T0fT/1NH0/8zJ8v/FwfD/sKvr/4+I4/9tZdr/UkjU/0A1z/8vIsv/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP84LM3/W1HW/3933/+inOj/xcLw/+jn+f/k4vj/nZjm/1dN1f8zJ8z/enLe/8G97//+/v7/+vn9//b1/P/x8Pv/7ez6/+nn+f/l4/j/5eT4/+fm+f/p5/n/6ej5/+no+v/q6Pr/29j2/8K+8P+qpOr/jIXi/2lg2v9GO9H/LyLL/yodyv8lGMj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP80KMz/U0jU/3Fo2/+PiOP/rajq/8vI8v/HxPH/i4Ti/09E0/8xJMv/bWTa/6mk6f/d2/b/3dv2/93b9v/d2/b/3dv2/93b9v/d2/b/3dv2/93b9v/d2/b/2df1/9LQ9P/MyfL/urbu/6Gb5/+HgOH/bGPa/1BF0/8zJ8z/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8vI8v/RTrQ/1pQ1v9wZ9v/hX7h/5uV5v+YkuX/bWXa/0I30P8sIMr/V07V/4J74P+opOn/qKTp/6ik6f+opOn/qKTp/6ik6f+opOn/qKTp/6ik6f+opOn/oZzn/5iT5f+QieP/gXrf/3Bo2/9fVtf/TkTT/z0yzv8sIMr/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8qHcr/NyvN/0Q50P9RR9P/XlXX/2tj2v9pYdr/T0XT/zUpzP8oG8n/QjfQ/1xT1v9zbNz/c2zc/3Ns3P9zbNz/c2zc/3Ns3P9zbNz/c2zc/3Ns3P9zbNz/amLa/19V1/9TSdT/ST7R/0A1z/84LM3/MCTL/yseyv8lGMj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8mGcn/LiHL/zUpzP89Mc7/RDnQ/0tB0v9KQNL/OzDO/y0gyv8lGMj/NCjM/0M40P9QRtP/UEbT/1BG0/9QRtP/UEbT/1BG0/9QRtP/UEbT/1BG0/9QRtP/Rz3R/zwxzv8xJsv/Kx/K/ycbyf8jF8j/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8kGMj/KRzJ/y4hy/8yJsz/NyvN/zswzv87L87/MibM/ygcyf8kF8j/LSHK/zYrzf8+M8//PjPP/z4zz/8+M8//PjPP/z4zz/8+M8//PjPP/z4zz/8+M8//OS7N/zImzP8rH8r/JxvJ/yUYyP8jFsj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8jFsj/JBjI/yYZyf8oG8n/Kh3K/ysfyv8rH8r/KBvJ/yQXyP8iFcj/JhnJ/ykdyv8sIMr/LCDK/ywgyv8sIMr/LCDK/ywgyv8sIMr/LCDK/ywgyv8sIMr/Kx7K/ygbyf8lGcj/JBfI/yMWyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA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z/8iFcj/IhXI/yIVyP8iFcj/LSHK/1FH1P9+dt//xcLw/+/u+/+ZlOX/TELS/zYrzf8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/01D0/+De+D/uLTt/+7t+v+1sOz/Sj/S/2Rb2P/QzfP/4N/3/6um6v92bd3/QDTP/yIVyP8iFcj/IhXI/yIVyP8rHsr/SD7R/3Jq3P+/vO//7+77/52Y5v9SSdT/OS7N/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/TUPT/4N74P+4tO3/7u36/7Ww7P9KP9L/ZFvY/9DN8//g3/f/q6bq/3Zt3f9ANM//IhXI/yIVyP8iFcj/IhXI/yoeyv9HPNH/cGjb/7+77//v7/v/n5rn/1VM1f86L87/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP9NQ9P/g3vg/7i07f/u7fr/tbDs/0o/0v9kW9j/0M3z/+Df9/+rpur/dm3d/0A0z/8iFcj/IhXI/yIVyP8iFcj/Kx/K/0tB0v92btz/wb7v/+/v+/+fmuf/VUzV/zovzv8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/01D0/+De+D/uLTt/+7t+v+1sOz/Sj/S/2Rb2P/QzfP/4N/3/6um6v92bd3/QDTP/yIVyP8iFcj/IhXI/yIVyP8vI8v/WlHW/4uE4v/Lx/L/7u36/5eS5f9JPtH/NCnM/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/TUPT/4N74P+4tO3/7u36/7Ww7P9KP9L/ZFvY/9DN8//g3/f/q6bq/3Zt3f9ANM//IhXI/yIVyP8iFcj/IhXI/zUpzP90bNz/rqnr/9rY9v/s6/r/iIHh/zAky/8oHMn/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP9NQ9P/g3vg/7i07f/u7fr/tbDs/0o/0v9kW9j/0M3z/+Df9/+rpur/dm3d/0A0z/8jFsj/KBvJ/y4iy/86Ls7/VkzV/5eR5f/MyfL/3dv2/9jW9f93b93/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/01D0/+De+D/uLTt/+7t+v+1sOz/Sj/S/2Rb2P/QzfP/4N/3/6um6v92bd3/QDTP/ygbyf81Ksz/TELS/3Jq2/+alOb/x8Tx/+Ti+P/Ny/L/ranq/2Na2P8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/TUPT/4N74P+4tO3/7u36/7Ww7P9KP9L/ZFvY/9DN8//m5Pj/urbu/46I4/9iWdj/UUfT/2FY1/97dN7/pqHp/8nG8f/c2vb/3t33/66q6/9+d9//TULS/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP9NQ9P/g3vg/7i07f/u7fr/tbDs/0o/0v9kW9j/0M3z//X0/P/j4fj/0c7z/7+77/+4tO3/vrvu/8jE8f/V0/T/2Nb1/8TA8P+oo+n/dW3c/0c80f8zJ8z/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/0g90f94cN3/p6Lp/9fU9f+kn+j/RTrQ/11T1v+8uO7/5eT4/+Xk+P/l5Pj/5eT4/+Xk+P/l5Pj/4uD4/9nX9f/Hw/H/npjn/3Rs3P9HPNH/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/OC3N/1VK1P9waNv/jIbi/25m2/82K83/RDrQ/3x13v+Vj+T/lY/k/5WP5P+Vj+T/lY/k/5WP5P+PieP/gHnf/29n2/9aUNb/RTrQ/zElzP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8rH8r/NyvN/0M40P9ORNP/QjfQ/yoeyv8wJMv/SD3R/1JI1P9SSNT/UkjU/1JI1P9SSNT/UkjU/0tB0v86L83/LCDK/yYZyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yYZyf8rH8r/MCTL/zYqzf8wJMv/JRnJ/ygcyf8zJ8z/NyzN/zcszf83LM3/NyzN/zcszf83LM3/NCnM/ywgyv8mGsn/JBfI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAoAAAAEAAAACAAAAABACAAAAAAAEAEAAAAAAAAAAAAAAAAAAAAAAAAIhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/1lQ1v//////8fD8/6yn6v8wJMv/IhXI//////////////////////+6tu7/WVDW/yIVyP8iFcj/IhXI/yIVyP8wJMv/Z17Z/6yn6v//////rKfq/yIVyP//////rKfq/1lQ1v+RiuT/4+L4//////9nXtn/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/urbu//Hw/P8iFcj//////5GK5P8iFcj/IhXI/zAky//j4vj/4+L4/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/5GK5P//////IhXI//////+RiuT/IhXI/yIVyP8iFcj/dW3d//////9LQdL/IhXI/yIVyP8iFcj/IhXI/yIVyP+RiuT//////yIVyP//////kYrk/yIVyP8iFcj/IhXI/1lQ1v//////WVDW/yIVyP8iFcj/IhXI/yIVyP8iFcj/kYrk//////8iFcj//////5GK5P8iFcj/IhXI/yIVyP9nXtn//////1lQ1v8iFcj/IhXI/yIVyP8iFcj/IhXI/5GK5P//////IhXI//////+RiuT/IhXI/yIVyP8iFcj/urbu//////8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP+RiuT//////yIVyP//////kYrk/yIVyP9LQdL/urbu//////+emef/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/kYrk//////8iFcj///////////////////////Hw/P+RiuT/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/z4yz/9ZUNb/IhXI/1lQ1v9ZUNb/WVDW/1lQ1v8wJMv/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/yIVyP8iFcj/IhXI/wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=' },
  2071. amazonDe: { name: 'Amazon.de', url: 'https://www.amazon.de/s?k=', icon: 'data:image/x-icon;base64,AAABAAQAMDAAAAEAIACoJQAARgAAACAgAAABACAAqBAAAO4lAAAYGAAAAQAgAIgJAACWNgAAEBAAAAEAIABoBAAAHkAAACgAAAAwAAAAYAAAAAEAIAAAAAAAgCUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///0X///+Z////zP////P////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////w////zP///5P///8/AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8k////wP//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////t////x4AAAAAAAAAAAAAAAAAAAAAAAAAAP///0L////z///////////////////////////////////////////////////////////////////////////X7///u+T//5DV//+R1f//csr//1C+//+Cz///kdX//5/Z///L6v//8vr//////////////////////////////////////////////////////////////////////////////////////+3///85AAAAAAAAAAAAAAAA////Lf////D///////////////////////////////////////////////////////////////+85f//csr//xOt//8AqP//AKj//wCn//8Ap///AKf+/wCn//8AqP//AKf//wCn//8Ap///AKj//z64//+Q1f//2PD////////////////////////////////////////////////////////////////////////////q////JAAAAAAAAAAA////zP/////////////////////////////////////////////////////y+v//kNX//xOs//8Ap///AKf//wCo//8Ap///AKf//wCo//8AqP//AKf//wCn/v8Ap///AKj//wCn//8AqP//AKf//wCn//8Ap///AKf//z64//+u4P//////////////////////////////////////////////////////////////////////vQAAAAD///9R////////////////////////////////////////////////8vr//5HV//8TrP//AKj//wCo//8AqP//AKj//wCo//8Ap///AKf//wCn//8AqP//AKf//wCo//8AqP//AKj//wCn//8Ap/7/AKf//wCo//8AqP//AKf//wCo//8Ap///KbL//67g////////////////////////5fT//////////////////////////////////////0L///+l//////////////////////////////////////////+75P//E63//wCn//8Ap///AKf//wCn/v8AqP//AKf//wCo//8psv//UL///4LQ//+R1f//kNX//5DV//+Q1f//kNX//5HV//9hw///UL7//wCo//8Ap/7/AKj//wCn//8Ap///AKj//wCn//9Qvv//5vX/////////////Ub///5DV/////////////////////////////////5b////q////////////////////////////////8vr//3LK//8AqP//AKf//wCn//8AqP//AKj//1C///+R1f//y+r////////////////////////////////////////////////////////////////////////Y7///rd///3LJ//8Trf//AKf+/wCn//8AqP//E63//7zl////////n9r//wCo///l9P///////////////////////////9v////////////////////////////////Y7///Prj//wCn//8Ap///AKf+/1C+//+t3///8vr/////////////////////////////////////////////////////////////////////////////////////////////////////////////vOX//3LK//8Ap///AKf//wCo//+t3///2O///wCn//9zyv////////////////////////////n//////////////////////////9jw//8Trf//AKf//wCn//9yyf//5fT////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////y+v//kNX//xOt//9hw////////xOt//8Trf//////////////////////////////////////////////////u+T//xOt//8AqP//csn//+X0/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////1G///8Ap///5vX////////////////////////////////////////Y7///AKj//1C+///l9f///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////9jv//8Ap///Ub///2HD//+Q1f//csr//wCn//8Ap///y+r////////////////////////////////////////Y8P//ruD////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////L6v//YsP//wCn//8Ap///AKj//wCo//8Ap///2PD///////////////////////////////////////////////////////////////////////////////////////////////////Pz8/+ioqL/VlZU/x0dG/8FBQT/BQUD/x0dHP9WVlX/hoaE/9jY2P////////////////////////////////++vr7/VlZV/6Kiov/////////////////////////////////K6f//yun//8rq///l9P//////////////////////////////////////////////////////////////////////////////////////////////////oqKi/x0dHP8FBQT/BQUE/wUFBP8FBQT/BQUE/wUFBP8FBQP/BQUE/wUFBP9WVlT/5ubm/////////////////7Cwr/8FBQT/BQUE/wUFBP92dnb///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////+GhoX/BQUE/wUFBP8FBQT/BQUD/wUFBP8FBQT/BQUE/wQEA/8FBQT/BQUD/wUFA/8FBQT/HR0c/7Cwr///////2dnZ/wUFBP8FBQT/BQUE/wUFBP8FBQT/Z2dm//Ly8v///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////729vf8FBQP/BQUE/wUFBP8FBQT/BQUE/wUFA/8FBQT/BQUE/wUFBP8FBQP/BQUD/wUFBP8FBQT/BQUE/wUFBP+ioqL/MjIw/wUFBP8FBQT/BQUD/wUFA/8FBQT/BQUE/0REQ//y8vL//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////zExMP8FBQT/BQUD/wUFBP8FBQT/BQUE/wUFBP8FBQP/BQUE/wUFBP8FBQT/BQUE/wUFBP8FBQT/BQUE/wUFBP8FBQT/BQUE/wUFBP8FBQT/BQUD/wUFBP8FBQT/BQUE/wUFBP8dHRv/////////////////////////////////////////////////////////////////////////////////////////////////////////////////2dnZ/wUFBP8FBQT/BQUE/wUFBP8FBQT/BQUE/wUFBP8FBQT/BQUE/wUFBP8dHRz/BQUE/wUFBP8FBQT/BQUD/wUFBP8FBQP/BQUE/wUFBP8FBQT/BQUD/wUFBP8FBQT/BQUE/wUFBP8yMjD/////////////////////////////////////////////////////////////////////////////////////////////////////////////////lJST/wUFBP8FBQT/BQUE/wUFBP8FBQT/BQUE/wUFBP8FBQT/HR0c/8zMzP///////////8zMzP8xMTD/BQUE/wUFBP8FBQT/BQUD/wUFA/8FBQT/BQUE/wUFBP8FBQT/BQUE/wUFBP/MzMz/////////////////////////////////////////////////////////////////////////////////////////////////////////////////hoaF/wUFBP8FBQT/BQUE/wUFBP8FBQT/BQUE/wUFBP8FBQP/zMzM///////////////////////y8vL/HR0c/wUFBP8FBQT/BQUE/wUFBP8FBQT/BQUE/wUFBP8FBQP/BQUE/4aGhP//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////VlZV/wUFBP8EBAP/BQUD/wUFA/8FBQT/BQUE/wUFBP9FRUT/////////////////////////////////sLCv/wUFBP8FBQT/BQUE/wUFBP8FBQT/BQUE/wUFBP8FBQT/BQUE/+Xl5f//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////ZmZl/wUFA/8FBQT/BQUD/wUFBP8FBQT/BQUE/wUFBP9VVVT//////////////////////////////////////zExMP8FBQT/BQUE/wUFBP8FBQT/BQUE/wUFBP8FBQT/VlZV////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////lJST/wUFBP8FBQT/BQUE/wUFBP8FBQT/BQUE/wUFBP9WVlX//////////////////////////////////////3Z2dv8FBQT/BQUE/wUFBP8FBQT/BQUE/wUFBP8FBQT/VlZV////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////sbGw/wUFBP8FBQT/BQUE/wUFBP8FBQT/BQUE/wUFA/8dHRz//////////////////////////////////////5SUk/8FBQP/BQUE/wUFA/8FBQT/BQUE/wUFBP8FBQT/VlZU////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////8vLy/wUFA/8FBQP/BQUD/wUFBP8FBQT/BQUE/wUFBP8FBQT/oqKi/////////////////////////////////5SUk/8FBQP/BQUE/wUFBP8FBQT/BQUD/wUFBP8FBQP/VlZV/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////3Z2dv8FBQT/BQUE/wUFBP8FBQT/BQUE/wUFA/8FBQT/HR0c/729vf///////////////////////////83Nzf8FBQT/BQUE/wUFBP8FBQT/BQUE/wUFBP8FBQT/VlZV/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////+bm5v8dHRz/BQUD/wUFA/8FBQT/BQUE/wUFBP8EBAP/BQUE/wUFBP9WVlX/vb29//Pz8////////////83Nzf8FBQP/BQUE/wUFBP8FBQT/BQUE/wUFA/8FBQT/VlZV//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////++vr7/BQUE/wUFBP8FBQT/BQUE/wUFBP8FBQP/BQUE/wUFBP8FBQT/BQUE/wUFBP8FBQT/VlZU/0REQ/8FBQT/BQUE/wUFBP8FBQP/BQUE/wUFBP8FBQT/VVVU////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////zMzM/x0dG/8FBQT/BQUE/wUFBP8FBQT/BQUE/wUFBP8FBQP/BQUE/wUFBP8FBQT/BQUE/wUFA/8FBQT/BQUE/wUFBP8FBQT/BQUE/wUFA/8FBQP/VVVU//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////Ly8v92dnb/BQUE/wUFBP8FBQT/BQUE/wUFA/8FBQT/BQUE/wUFBP8FBQT/BQUE/wUFA/8FBQP/BQUE/wUFBP8FBQT/BQUE/wUFBP8FBQT/VlZV////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////5ubm/6Kiov9VVVT/BQUE/wUFBP8FBQT/BQUE/wUFBP8FBQT/BQUE/wUFBP8FBQT/BQUE/wUFBP8FBQT/BQUE/wUFBP8FBQP/VlZV/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////9nZ2f/MzMz/lJST/5SUk/9WVlT/VlZV/zExMP8FBQT/BQUE/wUFBP8FBQT/BQUE/wUFBP8FBQT/VlZV/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////8zMzP8FBQP/BQUE/wUFA/8FBQT/BAQD/wUFBP8FBQT/VlZV////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////8/Pz/8zMzP/MzMz/lJST/5SUk//Z2dn//////////////////////////////////////76+vv8FBQT/BQUE/wUFBP8FBQT/BQUE/wUFBP8FBQP/VlZV/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////5WVk/8FBQT/BQUE/wUFBP8FBQT/BQUE/wUFBP9nZ2b//////////////////////////////////////5SUk/8FBQT/BQUE/wUFA/8FBQT/BQUE/wUFBP8FBQT/dnZ2/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////1ZWVP8FBQT/BQUE/wUFBP8FBQT/BQUD/wUFA/8dHRz/8/Pz/////////////////////////////////3Z2dv8FBQP/BQUE/wUFBP8FBQT/BQUE/wUFBP8FBQT/lJST/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////6Ghof8FBQT/BQUE/wUFBP8FBQT/BQUE/wUFA/8FBQT/dnZ2////////////////////////////2dnZ/x0dHP8FBQT/BQUE/wUFBP8FBQT/BQUD/wUFBP8FBQT/lJST/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////+bm5v8FBQT/BQUE/wUFBP8FBQT/BQUE/wUFA/8FBQT/BAQD/zExMP+xsbD/zMzM/8zMzP+UlJP/HR0c/wUFBP8FBQT/BQUE/wUFBP8FBQT/BQUE/wUFBP8FBQT/zMzM//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////92dnb/BQUE/wUFBP8FBQT/BQUE/wUFBP8FBQT/BQUE/wUFBP8FBQT/BQUE/wUFBP8FBQT/BQUE/wUFBP8FBQT/BQUE/wUFBP8FBQT/BQUE/wUFBP8dHRv///////////////////////////////////////////////////////////////////////////n////t///////////////////////////////////////////////////////////m5ub/Hh4c/wUFBP8FBQT/BQUE/wUFBP8FBQT/BQUE/wUFBP8FBQT/BQUE/wUFBP8FBQT/BQUE/wUFBP8FBQT/BQUE/wQEA/8FBQP/BQUD/wUFBP+UlJP//////////////////////////////////////////////////////////////////////////97///+o////////////////////////////////////////////////////////////////2dnZ/x0dG/8FBQT/BQUE/wUFA/8FBQT/BQUE/wUFBP8FBQT/BQUE/wUFBP8FBQT/BQUE/wUFBP8FBQT/BQUE/wUFBP8FBQP/BQUE/0VFRP/z8/P//////////////////////////////////////////////////////////////////////////5b///9U/////////////////////////////////////////////////////////////////////9nZ2f8xMTD/BQUE/wUFBP8FBQP/BQUE/wUFBP8FBQT/BQUD/wUFBP8FBQT/BQUE/wUFBP8FBQT/BQUE/wUFBP8FBQT/VVVU//Ly8v///////////////////////////////////////////////////////////////////////////////0L///8D////z///////////////////////////////////////////////////////////////////////////lZWU/zExMP8FBQT/BQUD/wUFA/8FBQT/BQUE/wUFBP8FBQT/BQUE/wUFA/8FBQT/BQUD/zExMP+xsbD/////////////////////////////////////////////////////////////////////////////////////wwAAAAAAAAAA////MP////b////////////////////////////////////////////////////////////////////////////////Z2dn/lJST/1ZWVf9WVlX/BAQD/wUFBP8FBQT/RUVD/1ZWVf+UlJP/zMzM///////////////////////////////////////////////////////////////////////////////////////////w////JwAAAAAAAAAAAAAAAP///0v////z//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////D///8/AAAAAAAAAAAAAAAAAAAAAAAAAAD///8t////yf//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////w////yQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP///0v///+f////z///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////zP///5n///9FAAAAAAAAAAAAAAAAAAAAAAAAAAD4AAAAAB8AAOAAAAAABwAAwAAAAAADAACAAAAAAAEAAIAAAAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAQAAgAAAAAABAADAAAAAAAMAAOAAAAAABwAA+AAAAAAfAAAoAAAAIAAAAEAAAAABACAAAAAAAIAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////Uf///5/////S///////////////////////////////////////////////////////////////////////////////////////////////////////////////P////nP///0gAAAAAAAAAAAAAAAAAAAAA////GP///7H//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////6X///8SAAAAAP///wb////P////////////////////////////////////////////////5fX//67g//+R1f//UL7//1C+//9Rv///YsT//5DU//+85f//8vr//////////////////////////////////////////////////////8P///8D////df//////////////////////////////////////////ruD//z24//8AqP//AKf//wCo//8Ap///AKj//wCo//8Ap/7/AKf//wCn//8AqP//csr//8vq/////////////////////////////////////////////////2b////S////////////////////////////////y+r//ymy//8Ap///AKj//wCo//8Ap///AKf//wCn//8Ap///AKj//wCn//8Ap///AKj//wCo//8AqP//AKj//1C////Y8P///////8rq///Y7///////////////////////w/////z/////////////////////8vr//3LJ//8AqP//AKf//wCn/v9ixP//kNT//8vq///y+v////////////////////////L6///L6v//n9r//2LE//8Trf//AKf//wCo//+u4P//vOX//z65///////////////////////w//////////////////////L6//8+uP//AKf//1C+//+t3///8/r///////////////////////////////////////////////////////////////////////+85f//UL7//wCo///Y7///AKf//8rp///////////////////////////////////Y7///E63//1C+///L6v////////////////////////////////////////////////////////////////////////////////////////P7///L6v//5fT///L6//8ps///kNT//////////////////////////////////5DU//+t3///////////////////////////////////////////////////////////////////////////////////////////////////5fX//1C+//8AqP//AKf//wCn//+Q1f//////////////////////////////////////////////////////////////////8vLy/5SUk/9FRUT/BQUE/wQEA/8yMjD/Z2dm/8zMzP////////////////+GhoX/Z2dm//Lz8////////////+X0///L6v//yun///L6//////////////////////////////////////////////////////////////Ly8v9FRUT/BQUE/wUFBP8FBQT/BQUE/wQEA/8FBQT/BQUD/3Z2dv/z8/P/dnZ2/wUFBP8FBQP/MTEw/9nZ2f//////////////////////////////////////////////////////////////////////////////////////VlZV/wUFBP8FBQT/BQUE/wUFBP8FBQT/BQUE/wUFBP8FBQT/BQUE/zIyMP8FBQT/BQUE/wUFBP8FBQT/HR0c/9nZ2f///////////////////////////////////////////////////////////////////////////+bm5v8FBQT/BQUE/wUFBP8FBQT/BQUE/wUFA/8xMTD/HR0c/wUFA/8FBQT/BQUE/wUFBP8FBQT/BQUE/wUFA/8FBQT/lJST////////////////////////////////////////////////////////////////////////////vb29/wUFBP8EBAP/BQUE/wUFBP8FBQT/dnZ2////////////oqKi/wUFBP8EBAP/BQUE/wUFBP8FBQP/BQUE/zIyMf/y8vL///////////////////////////////////////////////////////////////////////////+UlJP/BQUE/wUFBP8FBQT/BQUE/wUFBP/y8vL/////////////////Z2dm/wUFBP8FBQT/BQUE/wUFBP8FBQT/sbGw/////////////////////////////////////////////////////////////////////////////////7GxsP8FBQT/BQUD/wUFBP8FBQT/BQUD//////////////////////+9vb3/BQUE/wUFBP8FBQT/BQUE/wUFBP/m5ub/////////////////////////////////////////////////////////////////////////////////2dnZ/wUFBP8FBQT/BQUE/wUFBP8FBQT/zMzM/////////////////+bm5v8FBQT/BQUE/wUFA/8FBQT/BQUD////////////////////////////////////////////////////////////////////////////////////////////MTEw/wUFBP8FBQT/BQUE/wUFBP9FRUT/5eXl/////////////////wUFBP8FBQT/BQUE/wUFBP8FBQT////////////////////////////////////////////////////////////////////////////////////////////MzMz/BQUE/wUFA/8FBQT/BQUD/wUFBP8FBQT/dnZ2/5SUk/+9vb3/BQUE/wUFBP8FBQT/BQUE/wUFA/////////////////////////////////////////////////////////////////////////////////////////////////+wsK//HR0c/wUFBP8FBQT/BQUE/wUFBP8FBQT/BQUD/wUFBP8FBQT/BQUE/wUFBP8FBQT/BQUE///////////////////////////////////////////////////////////////////////////////////////////////////////m5ub/hoaF/zIyMP8FBQT/BQUE/wUFBP8FBQT/BQUD/wUFBP8FBQT/BQUE/wUFBP8FBQP//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////+bm5v/MzMz/lJST/5SUk/9WVlX/BQUE/wQEA/8FBQT/BQUE/wUFA//////////////////////////////////////////////////////////////////////////////////////////////////y8vL/zMzM/8zMzP/Nzc3///////////////////////////8FBQT/BQUE/wUFBP8FBQT/BQUD////////////////////////////////////////////////////////////////////////////////////////////Z2dm/wUFBP8FBQT/BQUE/wUFBP/y8vL/////////////////2dnZ/wUFA/8FBQP/BQUD/wUFBP8FBQT///////////////////////////////////////////////////////////////////////////////////////////9mZmX/BQUE/wUFBP8FBQT/BQUE/3Z2dv////////////////92dnb/BQUE/wUFBP8FBQT/BQUE/wUFBP///////////////////////////////////////////////////////////////////////////////////////////7CwsP8FBQT/BQUE/wUFBP8FBQT/BQUE/zIyMP9WVlX/RUVE/wUFBP8FBQT/BQUE/wUFBP8FBQT/RUVD/////////////////////////////////////////////////////////////////////////////////////////////////1ZWVf8FBQT/BQUE/wUFBP8EBAP/BQUD/wUFBP8FBQT/BQUE/wUFBP8FBQT/BQUE/wUFBP+wsK/////////////////////////////////////////////////2////2///////////////////////////////////////////8vLy/0VFRP8FBQP/BQUE/wUFBP8FBQT/BQUE/wUFBP8FBQT/BQUE/wUFBP8FBQT/dnZ2/////////////////////////////////////////////////////8z///9+/////////////////////////////////////////////////////7Cwr/9FRUT/BQUE/wUFBP8FBQT/BQUD/wUFBP8FBQT/RUVE/7Cwr///////////////////////////////////////////////////////////b////wz////b///////////////////////////////////////////////////////////y8vL/zMzM/8zMzP/MzMz/zc3N/+bm5v///////////////////////////////////////////////////////////////9L///8GAAAAAP///yf////b///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////S////HgAAAAAAAAAAAAAAAP///wz///94////2P/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////S////cv///wkAAAAAAAAAAOAAAAeAAAABAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAIAAAAHAAAADKAAAABgAAAAwAAAAAQAgAAAAAABgCQAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///8G////hP///9v/////////////////////////////////////////////////////////////////////////////////////////2////4T///8GAAAAAP///wz////P///////////////////////////y+v//vOX//5DV//+C0P//YsT//5DU//+u4P//5fT////////////////////////////////////////////G////Cf///4T/////////////////////8vr//3LK//8Trf//AKj//wCn//8Ap///AKf+/wCo//8AqP//AKf//1C+///K6v//////////////////////////////////////e////9v///////////////+u4P//E6z//wCn//8AqP//AKf//wCo//8Ap///AKf//wCo//8AqP//AKf//wCo//8Ap///kNX/////////////kdX//9jw////////////z/////D//////////4LP//8Ap///AKf//wCo//8qs///csr//5DV///K6f//y+r//8rq///L6v//n9n//3LK//8TrP//AKf//5/a////////kNX//1C+////////////7f////D/////kdX//wCo//8AqP//csn//9jw///////////////////////////////////////////////////y+v//n9r//4LQ////////yun//wCn///l9P//////8P////DK6v//AKf//1C+///l9P//////////////////////////////////////////////////////////////////////////////////yun//wCn//+85f//////8P////Aps///kNX///////////////////////////////////////////////////////////////////////+g2v//KrP//2LE//+Q1P//csr//wCn//+R1f//////8P////C75P////////////////////////////+xsbD/VlZV/1VVVP9WVlX/oaGh//Ly8v/y8vL/dnZ2/7Cwr///////vOT//2HD//8Ap///AKj//wCn/v+85f//////8P////D//////////////////////////4aGhf8EBAP/BQUD/wUFBP8EBAP/BQUD/0VFRP9nZ2b/BQUE/wUFBP92dnb/////////////////2O///+b1////////////8P////D/////////////////////8vLy/wUFBP8FBQT/BQUE/wUFA/9EREP/HR0b/wUFBP8FBQT/BQUD/wUFBP8FBQT/////////////////////////////////////8P////D/////////////////////zMzM/wUFBP8FBQT/BQUE/3Z2dv//////8vLy/x0dHP8FBQT/BQUE/wUFBP+UlJP/////////////////////////////////////8P////D/////////////////////zc3N/wUFBP8FBQT/BQUE/5SUk////////////4aGhf8FBQT/BQUE/wUFBP/MzMz/////////////////////////////////////8P////D//////////////////////////x0dG/8FBQT/BQUE/0VFQ//z8/P//////76+vv8FBQT/BQUE/wUFBP/Nzc3/////////////////////////////////////8P////D//////////////////////////7CwsP8FBQP/BQUE/wUFBP8dHRv/dnZ2/3Z2dv8FBQP/BQUE/wUFBP/MzMz/////////////////////////////////////8P////D///////////////////////////////++vr7/MTEw/wUFBP8FBQP/BQUD/wUFBP8FBQT/BQUE/wUFBP/MzMz/////////////////////////////////////8P////D//////////////////////////////////////////+Xl5f/MzMz/lJST/3Z2dv8FBQT/BQUE/wUFBP/MzMz/////////////////////////////////////8P////D//////////////////////////4aGhf9WVlX/HR0b/729vf///////////7Cwr/8FBQP/BQUE/wUFBP/MzMz/////////////////////////////////////8P////D//////////////////////////2ZmZf8FBQT/BQUE/x0dHP++vr7/zMzM/0VFRP8FBQT/BQUE/wUFBP/y8vL/////////////////////////////////////8P////D//////////////////////////8zMzP8FBQT/BQUE/wUFBP8FBQT/BQUE/wUFBP8FBQT/BQUD/1ZWVP/29vb/////////////////////////////////////7f///9X///////////////////////////////+wsK//HR0c/wUFBP8FBQT/BQUE/wUFBP8FBQT/MTEw/9vb2//6+vr/////////////////////////////////////z////3v/////////////////////////////////////8vLy/76+vv+UlJP/lJST/5SUk/++vr7/////////////////////////////////////////////////////df///wn////D//////////////////////////////////////////////////////////////////////////////////////////////////////////////+9////BgAAAAD///8D////df///9L/////////////////////////////////////////////////////////////////////////////////////////z////3X///8DAAAAAIAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAABACgAAAAQAAAAIAAAAAEAIAAAAAAAQAQAAAAAAAAAAAAAAAAAAAAAAAD///8G////lv////b/////////////////////////////////////////////////////////9v///5b///8G////iv/////////////////////Y7///n9r//5DV//+Q1P//vOT/////////////////////////////////iv///+f//////////8vq//9Qvv//AKj//wCn//8Ap///AKf+/wCn//8ps///u+T////////y+v//8vr//////+f////w/////67g//8AqP//AKj//z24//+C0P//kNX//5DU//+R1f//UL7//wCn//+u4P//vOX//4LQ///////w////8Lzl//8AqP//csn//+bz///////////////////////////////////l9P//rd///9jv//8Trf//////8P////Aqs///2O//////////////////////////////////////////////Ur7//3LK//+C0P//AKf///////D////w5vX/////////////zMzM/x0dG/8FBQT/HR0b/5SUk/9WVlT/RUVD/+fu8/+i2P7/csr//3LK///////w////8P///////////////zExMP8FBQT/BQUE/0VFRP8FBQP/BQUE/wUFBP+UlJP/////////////////////8P////D///////////////8FBQT/BQUE/4aGhP//////ZmZl/wUFBP8FBQT/8vLy//////////////////////D////w////////////////VlZV/wUFBP8yMjD/5ubm/5SUk/8FBQT/BQUE///////////////////////////w////8P///////////////9nZ2f8yMjD/BQUE/wUFBP8FBQT/BQUE/wUFBP//////////////////////////8P////D////////////////m5ub/zMzM/729vf+wsK//VlZV/wUFBP8FBQT///////////////////////////D////w////////////////Z2dm/wUFBP9FRUT/2NjY/2dnZv8FBQT/HR0c///////////////////////////w////5////////////////8zMzP8FBQP/BQUE/wUFBP8FBQT/BQUE/3Z2dv//////////////////////////5////4f/////////////////////2dnZ/3Z2dv9VVVT/VlZV/6Kiov///////////////////////////////4r///8G////jf///+T/////////////////////////////////////////////////////////5P///43///8GAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA==' },
  2072. ebay: { name: 'eBay', url: 'https://www.ebay.com/sch/i.html?_nkw=', icon: 'data:image/x-icon;base64,AAABAAEAEBAAAAEAIABoBAAAFgAAACgAAAAQAAAAIAAAAAEAIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP84MuX/ODLl/zgy5f84MuX/0mQA/9JkAP/SZAD/0mQA/wKv9f8Cr/X/Aq/1/wKv9f8XuIb/F7iG/xe4hv8XuIb/ODLl/zgy5f84MuX/ODLl/9JkAP/SZAD/0mQA/9JkAP8Cr/X/Aq/1/wKv9f8Cr/X/F7iG/xe4hv8XuIb/F7iG/zgy5f84MuX/ODLl/zgy5f/SZAD/0mQA/9JkAP/SZAD/Aq/1/wKv9f8Cr/X/Aq/1/xe4hv8XuIb/F7iG/xe4hv84MuX/ODLl/zgy5f84MuX/0mQA/9JkAP/SZAD/0mQA/wKv9f8Cr/X/Aq/1/wKv9f8XuIb/F7iG/xe4hv8XuIb/ODLl/zgy5f84MuX/ODLl/9JkAP/SZAD/0mQA/9JkAP8Cr/X/Aq/1/wKv9f8Cr/X/F7iG/xe4hv8XuIb/F7iG/zgy5f84MuX/ODLl/zgy5f/SZAD/0mQA/9JkAP/SZAD/Aq/1/wKv9f8Cr/X/Aq/1/xe4hv8XuIb/F7iG/xe4hv84MuX/ODLl/zgy5f84MuX/0mQA/9JkAP/SZAD/0mQA/wKv9f8Cr/X/Aq/1/wKv9f8XuIb/F7iG/xe4hv8XuIb/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAD/AAAA/wAAAP8AAAAAAAAAAAAAAAAAAAAAAAAA8wAAAAwAAAAAAAAAAAAAAAAAAAAAAAAAGAAAAPMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAK4AAABsAAAAAAAAAAAAAAAAAAAAAAAAAG8AAACuAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAkAAAA6gAAAGkAAAAMAAAADAAAAGkAAADqAAAAJAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAACcAAAC3AAAA8wAAAPMAAAC3AAAAJwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAUAAAAFAAAAAAAAD4QQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA888AUPPPAFDwD///+B8AAA==' },
  2073. allegro: { name: 'Allegro', url: 'https://allegro.pl/listing?string=', icon: 'data:image/x-icon;base64,AAABAAEAMDAAAAEAIACoJQAAFgAAACgAAAAwAAAAYAAAAAEAIAAAAAAAACQAABMLAAATCwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWP8aAFv/cABb/6YAWv/ZAFr/7gBa//AAWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa//kAWv9jAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFv/NQBa/7UAWv/8AFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv+hAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABd/wsAWv+cAFr//QBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv+hAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFX/BgBa/7YAWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv+hAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFr/pwBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv+hAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWf9CAFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv+hAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWv/LAFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr/2wBa/40AWv9pAFr/ZgBa/2YAWv9mAFr/ZgBa/2YAWv9mAFr/ZgBa/2YAWv9mAFn/ZwBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv+hAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABY/yAAWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa//UAWv9jAID/AgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAID/AgBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv+hAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABZ/2oAWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr//QBa/0EAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAID/AgBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv+hAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABZ/4YAWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr/qgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAID/AgBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv+hAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABb/5UAWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFv/awAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAID/AgBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv+hAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABa/5cAWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFv/aAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAID/AgBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv+hAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABa/4UAWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr/ngAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAID/AgBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv+hAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABb/18AWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr/9QBY/xoAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAID/AgBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv+hAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABX/yMAWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa/8MAYv8NAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAID/AgBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv+hAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWv/GAFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv/VAFr/SgAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAID/AgBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv+hAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAW/9MAFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa/+MAWv+hAFv/gQBa/24AWv9mAFr/ZgBa/2YAWv9mAFr/ZgBa/2YAWv9mAFn/ZwBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv+hAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFr/pwBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv+hAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAF3/CwBa/8YAWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv+hAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABd/wsAW/+pAFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv+hAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFv/VwBa/94AWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv+hAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABV/wMAXP9OAFv/tABa//sAWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv+fAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAABV/wwAW/9GAFr/gABb/6YAWv/GAFr/2gBa/90AWv/dAFr/3QBa/90AWv/dAFr/3QBa/90AWv/dAFr/3QBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv+QAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAED/BABa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AW/+BAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFz/GQBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv9xAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFz/TgBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWP9LAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFr/XgBa/6cAXf8sAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAP8BAFr/uwBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AXf8WAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFv/yABa//8AWv/8AFr/ngBd/ywAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAWf91AFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa/94AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFr/1wBa//8AWv//AFr//wBa//8AWf/CAFr/bgBX/yMAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFr/HwBa/5sAWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa/4UAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFv/5wBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv/rAFr/uwBZ/6AAWv+NAFr/lABa/6QAWf/QAFr//QBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr//ABe/x4AAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAFr/9wBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFn/oAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAYP8IAFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv/jAFX/FQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZv8FAFr/2QBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa/+kAWv8wAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAGb/BQBa/2MAWv/dAFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr/wABd/yEAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZv8FAFr/UgBa/6gAWv/0AFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr//wBa//8AWv//AFr//QBa/7sAW/9MAAD/AQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAZv8KAFr/RwBa/3oAWv+sAFn/0wBa/+IAWv/yAFr/+wBa/+kAWv/XAFr/wQBZ/4wAW/9RAFn/FwAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAD///////8AAP///////wAA////////AAD///////8AAP///////wAA////////AAD//gAAAP8AAP/4AAAA/wAA/+AAAAD/AAD/wAAAAP8AAP/AAAAA/wAA/4AAAAD/AAD/gAAAAP8AAP8AD/4A/wAA/wA//gD/AAD/AH/+AP8AAP8Af/4A/wAA/wB//gD/AAD/AH/+AP8AAP8AP/4A/wAA/wAf/gD/AAD/gA/+AP8AAP+AAAAA/wAA/8AAAAD/AAD/wAAAAP8AAP/gAAAA/wAA//gAAAD/AAD//AAAAP8AAP//gAAA/wAA/////gD/AAD////+AP8AAP////4A/wAA//j//AD/AAD/+D/8Af8AAP/4B/AB/wAA//gAAAH/AAD/+AAAA/8AAP/wAAAD/wAA//AAAAf/AAD/+AAAD/8AAP/+AAAf/wAA///AAP//AAD///////8AAP///////wAA////////AAD///////8AAP///////wAA////////AAA=' },
  2074. olx: { name: 'OLX', url: 'https://www.olx.pl/oferty/q-', icon: 'data:image/x-icon;base64,AAABAAIAEBAAAAEAIABoBAAAJgAAACAgAAABACAAqBAAAI4EAAAoAAAAEAAAACAAAAABACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////AP///wD///8A////AP///zD///+W////1v////L////y////1v///5r///8y////AP///wD///8A////AP///wD///8A////CP///5T//////////////////////////////////////////////5j///8K////AP///wD///8A////Bv///8D/////////////////////////////////////////////////////////yP///wj///8A////AP///5T///////////////////////////////////////////////////////////////////+c////AP///yz///////////Xt8f////////////////////////////X4/v/x9v7//////+vx/f+uyfr/6/L9/////zT///+U8+ru/5dDaP+OL1r/lkFn//Lo7f////////////////92pPb/WZL0//////9imPX/EWLv/52/+P////+c////1KZbff+pYoL//////6tmhf+kWHr/5/bz/8Tp4P/F6eH/fq/s/xdn8f+ZvPj/JG/x/06L9P//////////3Pz6+/KGIU//2LjH///////au8n/lSRV/23LtP8lr47/IK2M/4zXu/96pfj/JXDx/ytz8f/i7P3///////////T9/PzyhyRR/9Wywv//////17bF/5YnWP930Lr/U8Cm//T7+f/7/f3/0uH8/x5r8P9Uj/T////////////////0////1LR1kv+aSGz/8ebr/5xLb/+7dpX/e9TC/1XBp////////////1aQ9P9WkPT/Pn3y/6TD+f//////////3P///5T79/n/sHKM/4wtWf+vcIr/+vb4/2/JtP9Sv6b//////+fv/f8lbPD/4uz9/+Tt/f8tbfD/7PP9/////5z///8q//////////////////////////+j3c//itPB////////////////////////////9vn+//39//////8y////AP///5L///////////////////////////////////////////////////////////////////+a////AP///wD///8E////vv/////////////////////////////////////////////////////////E////CP///wD///8A////AP///wb///+S//////////////////////////////////////////////+W////CP///wD///8A////AP///wD///8A////AP///y7///+U////1P////L////0////1v///5j///8w////AP///wD///8A////APgfAADgBwAAwAMAAIABAACAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAEAAIABAADAAwAA4AcAAPgfAAAoAAAAIAAAAEAAAAABACAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///xD///9Y////lP///8L////c////6v///+r////c////xP///5j///9c////Fv///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///yb///+W////8P/////////////////////////////////////////////////////////0////nP///yz///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///+E/////////////////////////////////////////////////////////////////////////////////////////4z///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8a////yP///////////////////////////////////////////////////////////////////////////////////////////////////9L///8i////AP///wD///8A////AP///wD///8A////AP///wD///8A////JP///+r///////////////////////////////////////////////////////////////////////////////////////////////////////////////T///8w////AP///wD///8A////AP///wD///8A////AP///xL////u//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////j///8e////AP///wD///8A////AP///wD///8A////0P///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////97///8A////AP///wD///8A////AP///37//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////5D///8A////AP///wD///8W/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////yL///8A////AP///5b/////////////////////7N3k/+zc4////////////////////////////////////////////////////////////9nm/P/I2/z//////////////////////6/K+v9AgfP/eqf3/7fQ+v/5+///////qP///wD///8I////9v//////////27zK/5xKb/98D0H/fA5A/5tIbv/YuMf////////////////////////////////////////////7/P//OX3y/wZb7//w9f7////////////u9P7/G2rw/wZc7/8AVe7/DF/w/+jw/f//////////Ev///1D//////////9Grvf94Bzv/cAAv/59QdP+hUnb/cQAx/3cFOf/Oprj//////////////////////////////////////6LB+f8CWe//C1/v/2OZ9f///////////3yp9/8GXO//OX3y/wZb7/+Er/f//v////////////9g////kv/////t3uX/ghlJ/3UBNv+ua4n///////////+xcI3/dQI2/4AWRv/m197/////////////////////////////////y9P//wVZ8v8pdPD/Blzv/8rc+//7/P//GGfw/y528v8TZPD/QoPz/////////////////////6L////A/////7Z4lf9zADT/jCxX//jz9f////////////v4+f+OMFv/cgAz/7p2lP/+////o97Q/4TSwP+P1sX/kNbF/4bTwf+06sz/dqjz/w5e9f8ibvH/RoXz/1uT9f8fbPH/LHXy/xBi8P/W5P3/////////////////////zv///97+/v7/m0Zt/3UCN/+rZYX//////////////////////69ti/91ATb/uU56/8nq4/8NsIn/EqiF/xWphv8MpoL/AqJ8/xCte//y/+j/hKX//wpe7/8ncfH/HWvx/zp+8v8EWu//jrX4///////////////////////////k////7Pbv8/+SN2H/dwU5/7p/mv//////////////////////vISe/3gHOv+vPGz/s8/K/yzDnf86t5n/NbWX/z64nP81tZf/NrSZ//r/8f//////XJT1/x9s8f8yePL/HWrx/1KN9P////////////////////////////////D////s+fT2/5M6Y/92BDj/tnqV//////////////////////+6gJv/dwU5/7A/bv+61dD/L8Kd/xqrif+B0b7/6/j1/+n39P/z+vn//f7////////X5fz/EWPw/y118v8MX/D/zd78////////////////////////////////8P///97/////oVN2/3QANf+hU3f//////////////////////6Zbff90ADT/v1uF/8v06v8otpT/EKiE/6Pdz////////////////////////////3Oj9v8XZ/D/I27x/w9i8P9qnfb////////////////////////////////k////wP/////JnLD/dAA1/4IZSf/iy9X////////////m0dv/gxtL/3MANP/oo77/2f///yOtjv8UqYb/l9nJ///////////////////////X5Pz/GGfw/x5r8f8/gfP/NHny/wBQ7v+hwvn//////////////////////////87///+Q//////z5+v+YQWn/bgAs/5Y/Z//jzNf/5M7Y/5lDav9uACz/lTxl///8///N9+7/I62O/xSphv+X2cn//////////////////////2md9f8BWO//GGfw/+bv/f/H2vv/AFLu/xBh7//i7P3/////////////////////oP///1D//////////+/i6P+VPGX/bQAq/3UCN/92Azj/bAAp/5M5Yv/t3uX//////8Hn3f8jro7/FKmG/5XYyP/////////////////J3Pv/AFbu/wBN7f+NtPj///////////+TuPj/AEDs/zt/8v/x9v7///////////////9g////CP////b///////////z6+//Ekqn/pFh7/6RXev/CkKf/+/f5////////////vebd/x6si/8SqIX/j9bF/////////////////9Xk/P8wd/L/ZJn1//////////////////////95p/b/AFDu/8TY+////////////////xD///8A////lP/////////////////////////////////////////////////////K6+P/DKaC/wCcdP+V2Mj////////////////////////////////////////////////////////////e6f3/9/r///////////+m////AP///wD///8U//////////////////////////////////////////////////////3+/v+65tv/p9/S/+759v///////////////////////////////////////////////////////////////////////////////yD///8A////AP///wD///98//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////+O////AP///wD///8A////AP///wD////O////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////2v///wD///8A////AP///wD///8A////AP///xD////s//////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////T///8a////AP///wD///8A////AP///wD///8A////AP///yD////o///////////////////////////////////////////////////////////////////////////////////////////////////////////////y////LP///wD///8A////AP///wD///8A////AP///wD///8A////AP///xb////E////////////////////////////////////////////////////////////////////////////////////////////////////zv///yD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///+A/////P///////////////////////////////////////////////////////////////////////////////////4j///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8i////kv///+z/////////////////////////////////////////////////////////8P///5j///8o////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP///wD///8A////Dv///1T///+Q////wP///97////u////7v///+D////C////lP///1r///8S////AP///wD///8A////AP///wD///8A////AP///wD///8A////AP/wD///gAH//gAAf/wAAD/4AAAf8AAAD+AAAAfgAAADwAAAA4AAAAGAAAABgAAAAQAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAgAAAAYAAAAGAAAABwAAAA+AAAAPgAAAH8AAAD/gAAB/8AAA//gAAf/+AAf//8A//' },
  2075. ggdeals: { name: 'GG.deals', url: 'https://gg.deals/games/?title=', icon: 'data:image/png;base64,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' },
  2076. iszop: { name: 'I-Szop', url: 'https://i-szop.pl/szukaj2/1/', icon: 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAMAAAAoLQ9TAAAAAXNSR0IArs4c6QAAAqNQTFRFDgkEFQ4AFxcMEhkSHBgPKRsTICAdIiIgKiUiKigXJyocLCoaLiwnLzAiNi4sNTktOjorPTkyQzwjREAzQ0U4TEpJV01ET09NYVZEX1dJZFlJZlpGYVxIaVpFZltFZ1xPa1xFYmBcbWFIaWRMbGVTbWdVcGdScWlcdWpMdmpbcmtedGxPe2pUc25ddm5ZeG9ZeG9bgG9jfHFjfnBodXNmfXNRf3RXe3VigHRlfnVhhHRmh3RnendxhXdkhHljhHhwhnhth3huiXpshnxlhXxtjHtoj3xojn1jiX5ogn91iH57gYB+jH9tjIFuiIJyh4J4joFui4NtkoFtkoNskoR1joV4i4eDiYmHkoh4l4d1kIl2mIdzlYh0mIh4lol0kop5mIpxmoptkIuHm4t0kI+LmJCMoZB3oZF9opJ6opN3pJN1mJWJopV7qZR6m5aSoJd6pph5p5h6oJqRqJuAqZuDpp2Eop6RnZ+frJ6Erp6Drp+BtJ+As6CBsqCHsKGDp6KWtKCHr6KGs6GJtaKDtqKBsaOGtqGMtqKEtaOHtaSEtKSHraaMtKSMs6WGuaOLraaatKaIuaWGuKeGuKeJuaeKuaeNu6eLrqyiwKuHsa6kv6ySva2aubCOwa2WtrKpv7OUxLGev7KpxLyvycGxxMK/z8/S2dDC4NfH3tfQ39vW4tvO49/S4d/c4eDY4+DW4+DZ5uLb5uTf6Obm6ujj6ejm6ujn7Orq6+vp8O7n8O7t8O/t8vLv8/Pu8vPx9fPw9fP39vTz/Pn3+/r2/Pv4+fz9//zz/fz5/Pz9/fz8/fz9+v3++/38/P36+/3+/P39/f38/f39/v37/f3+/v3+/v3///3+//3//v79///x/v7+/v7///79//7//v/+///9///+////q9zVfwAAAAFiS0dEAIgFHUgAAAAJcEhZcwAACxMAAAsTAQCanBgAAAAHdElNRQfbCAIIEg/IDPn8AAABG0lEQVQY0wEQAe/+ANna0tLZ0NfPydDVrLzc09sA0eDg3eDg4ODg4G5YNODS1wC4f56t4KRkPElrGHFRxtTaAK6jqo8TKUaCgIiWYRK+3MsAsKKmGjhokoOHe45eXxXgzADAYhk9aXp0c3x+RN7g4EvWALMlPjpZp8WrfWbYFwYUDL8AmSM5SsFWBxFFm1onDghX4AClveB3AwoPEIEiAUwFFuDQAMchBAACCQ0LU00tGyyfTsgArzdDQkFAPzM7MVSGk5wksgCXLmBsZ2OFkHCNiZVbNkioAHJclISRRyAeJhyLeB2NbaEAqTKMaoqanaBdH3mYUjBPuQDO33ZVKi81KCt1b1BlseDEAMrN3sK6t7S0tba7y+Dew8+WuHySTaTv0gAAAABJRU5ErkJggg==' },
  2077. getUrlWithQuery: (engine, query) => engine.url && ((engine.url.indexOf('$$') >= 0) ? engine.url.replace('$$', encodeURIComponent(query)) : engine.url + encodeURIComponent(query)),
  2078. // getUrlWithQuery: (engine, query) => engine.url && query && (query = query.replace(/[:]+/g, '')) && ((engine.url.indexOf('$$') >= 0) ? engine.url.replace('$$', encodeURIComponent(query)) : engine.url + encodeURIComponent(query)),
  2079. });
  2080. const createSearchButton = (engine, query, { label, marginRight = 2, marginLeft = 0 } = {}) => {
  2081. const searchLink = document.createElement('A');
  2082. if (query instanceof Function) {
  2083. searchLink.onclick = () => {
  2084. const queryResult = query();
  2085. if (queryResult) {
  2086. searchLink.href = searchEngine.getUrlWithQuery(engine, queryResult);
  2087. return true;
  2088. }
  2089. else {
  2090. return false;
  2091. }
  2092. };
  2093. } else {
  2094. searchLink.href = searchEngine.getUrlWithQuery(engine, query);
  2095. }
  2096. searchLink.target = '_blank';
  2097. searchLink.classList.add('subNavMenu-btn', `space--mr-${marginRight}`, `space--ml-${marginLeft}`);
  2098. const wrapper = document.createElement('DIV');
  2099. wrapper.classList.add('subNavMenu', 'subNavMenu--menu', 'tGrid-cell', 'vAlign--all-m', 'subNav-item');
  2100. let nodeToAppend;
  2101. if (isString(label) && (label = label.trim()).length > 0) {
  2102. nodeToAppend = document.createTextNode(label);
  2103. } else if (engine.icon) {
  2104. nodeToAppend = document.createElement('IMG');
  2105. nodeToAppend.src = engine.icon;
  2106. nodeToAppend.alt = engine.name;
  2107. // nodeToAppend.style.height = '24px';
  2108. // wrapper.style.height = '42px';
  2109. // searchLink.style.padding = '5px';
  2110. nodeToAppend.style.height = '22px';
  2111. wrapper.style.height = '40px';
  2112. searchLink.style.height = '34px';
  2113. searchLink.style.padding = '5px';
  2114. searchLink.style.borderRadius = '5px';
  2115. searchLink.title = engine.name;
  2116. } else {
  2117. nodeToAppend = document.createTextNode(engine.name);
  2118. }
  2119. searchLink.appendChild(nodeToAppend);
  2120. wrapper.appendChild(searchLink);
  2121. return wrapper;
  2122. };
  2123. /*** END: Search Engines ***/
  2124.  
  2125. /*** Search Page ***/
  2126. if (pepperTweakerConfig.improvements.addSearchInterface && (location.pathname.indexOf('/search') >= 0) && (location.search.indexOf('q=') >= 0)) {
  2127. const searchSubheadline = document.querySelector('h1.cept-nav-subheadline');
  2128. if (searchSubheadline) {
  2129. const searchQuery = `site:${location.host.replace('www.', '')} ${searchSubheadline.textContent.replace(/Szukaj |"/gi, '')}`;
  2130. const searchButton = createSearchButton(searchEngine.google, searchQuery, { label: 'Szukaj przez Google' });
  2131. searchButton.querySelector('a')?.classList.add('button--type-secondary');
  2132. searchButton.style.cssFloat = 'right';
  2133. searchButton.classList.remove(...searchButton.classList); // remove all classes from wrapper, because they messing up the alignment
  2134. searchSubheadline.parentNode.insertBefore(searchButton, searchSubheadline);
  2135. }
  2136. }
  2137. /*** END: Search Page ***/
  2138.  
  2139. const DEFAULT_NOTIFICATION_SOUND = new Audio('data:audio/mp3;base64,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bIckFua2x/PXG9Wzjds03FjQZJc4zjOM4///x///q1bSyQoMkskskOAJTEFNRTMuOTkuNVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVf/7ksTsA5lODPADGTICysFTCDM+uVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVVU=');
  2140.  
  2141. class BlinkingPageTitle {
  2142. // #running = false; // not implemented in FF yet (only experimental, set to false as default :/)
  2143. constructor({ playSound = false, stopOnFocus = true, delay = 1100, soundSource = DEFAULT_NOTIFICATION_SOUND } = {}) {
  2144. if (BlinkingPageTitle._instance) {
  2145. throw new Error(`${this.constructor.name}: Only one instance of the class is allowed`);
  2146. }
  2147. BlinkingPageTitle._instance = this;
  2148. this._running = false;
  2149. this._interval = null;
  2150. this._isOriginalTitle = true;
  2151.  
  2152. this.stop = this.stop.bind(this); // bind 'this' to stop() function
  2153.  
  2154. this.originalTitle = document.title;
  2155. this.playSound = playSound;
  2156. this.stopOnFocus = stopOnFocus;
  2157. this.delay = delay;
  2158.  
  2159. this._soundSource = (soundSource instanceof HTMLAudioElement) ? soundSource : DEFAULT_NOTIFICATION_SOUND;
  2160. }
  2161. get soundSource() {
  2162. return this._soundSource;
  2163. }
  2164. set soundSource(newSource) {
  2165. if (newSource instanceof HTMLAudioElement) {
  2166. this._soundSource = newSource;
  2167. }
  2168. }
  2169. run(message, callback) {
  2170. if (this._running === true) {
  2171. // console.warn(`${this.constructor.name}: run() was called but running already`);
  2172. return false;
  2173. }
  2174. this._running = true;
  2175. this._callback = callback;
  2176. this._changeTitle(message);
  2177. if (this.stopOnFocus === true) {
  2178. if (document.hidden || !document.hasFocus()) {
  2179. document.addEventListener('visibilitychange', this.stop);
  2180. window.addEventListener('focus', this.stop); // must be window not document!
  2181. this._interval = setInterval(() => this._changeTitle(message), this.delay);
  2182. } else {
  2183. setTimeout(this.stop, this.delay);
  2184. }
  2185. } else {
  2186. this._interval = setInterval(() => this._changeTitle(message), this.delay);
  2187. if (this._callback instanceof Function) {
  2188. this._callback(this);
  2189. }
  2190. }
  2191. return true;
  2192. }
  2193. stop() {
  2194. if (!this._running) {
  2195. console.warn(`${this.constructor.name}: stop() was called but not running`);
  2196. return false;
  2197. }
  2198. if (this._interval) {
  2199. clearInterval(this._interval);
  2200. this._interval = null;
  2201. }
  2202. if (this.stopOnFocus === true) {
  2203. document.removeEventListener('visibilitychange', this.stop);
  2204. window.removeEventListener('focus', this.stop); // must be window not document!
  2205. if (this._callback instanceof Function) {
  2206. this._callback(this);
  2207. }
  2208. }
  2209. document.title = this.originalTitle;
  2210. this._running = false;
  2211. return true;
  2212. }
  2213. _changeTitle(message) {
  2214. if (this._isOriginalTitle) {
  2215. document.title = message;
  2216. if (this.playSound === true) {
  2217. this._soundSource.play();
  2218. }
  2219. } else {
  2220. document.title = this.originalTitle;
  2221. }
  2222. this._isOriginalTitle = !this._isOriginalTitle;
  2223. }
  2224. }
  2225.  
  2226. const arrayFilterIndexes = (array, callback) => {
  2227. if (!array) { return null; }
  2228. const arrayLength = array.length;
  2229. const result = new Array();
  2230. for (let i = 0; i < arrayLength; i++) {
  2231. if (callback(array[i], i)) {
  2232. result.push(i);
  2233. }
  2234. }
  2235. return result;
  2236. };
  2237.  
  2238. const removeAttributeRecursively = (node, attribute) => {
  2239. node.removeAttribute(attribute);
  2240. for (let i = 0, childrenLength = node.children.length; i < childrenLength; i++) {
  2241. removeAttributeRecursively(node.children[i], attribute);
  2242. }
  2243. return node;
  2244. };
  2245.  
  2246. const removeDataAttributesRecursively = node => {
  2247. for (const dataKey of Object.keys(node.dataset)) {
  2248. delete node.dataset[dataKey];
  2249. }
  2250. for (let i = 0, childrenLength = node.children.length; i < childrenLength; i++) {
  2251. removeDataAttributesRecursively(node.children[i]);
  2252. }
  2253. return node;
  2254. };
  2255.  
  2256. const nodeListDifference = (list1, list2, { ignoreInlineStyle = false, ignoreClassList = false, ignoreDataAttributes = false, deepCompare = false } = {}) => {
  2257. if (!(list1 instanceof NodeList) || !(list2 instanceof NodeList)) { return null; }
  2258. let array1, array2;
  2259. if (deepCompare === true) { // will check entire nodes
  2260. array1 = Array.from(list1).map(node => node.cloneNode(true));
  2261. array2 = Array.from(list2).map(node => node.cloneNode(true));
  2262. } else { // will check outer nodes only (without children)
  2263. array1 = Array.from(list1).map(node => node.cloneNode(false));
  2264. array2 = Array.from(list2).map(node => node.cloneNode(false));
  2265. }
  2266. let reducersToApply = [];
  2267. if (ignoreInlineStyle === true) {
  2268. reducersToApply.push(node => removeAttributeRecursively(node, 'style'));
  2269. }
  2270. if (ignoreClassList === true) {
  2271. reducersToApply.push(node => removeAttributeRecursively(node, 'class')); // node.classList.remove(...node.classList)
  2272. }
  2273. if (ignoreDataAttributes === true) {
  2274. reducersToApply.push(node => removeDataAttributesRecursively(node));
  2275. }
  2276. if (reducersToApply.length > 0) {
  2277. array1 = array1.map(node => reducersToApply.reduce((result, reducer) => reducer(result), node));
  2278. array2 = array2.map(node => reducersToApply.reduce((result, reducer) => reducer(result), node));
  2279. // array1 = array1.map(node => {
  2280. // reducersToApply.forEach(reducer => reducer(node));
  2281. // return node;
  2282. // });
  2283. // array2 = array2.map(node => {
  2284. // reducersToApply.forEach(reducer => reducer(node));
  2285. // return node;
  2286. // });
  2287. }
  2288. return arrayFilterIndexes(array1, node1 => !array2.some(node2 => node2.isEqualNode(node1))).map(index => list1[index]);
  2289. }
  2290.  
  2291. class RemoteChildrenUpdateObserver {
  2292. constructor({ containerSelector, childrenSelector, remoteUrl, updateCallback, tickCallback = undefined, errorCallback = undefined, ignoreInlineStyle = true, ignoreClassList = true, ignoreDataAttributes = true, deepCompare = false }) {
  2293. if (!(updateCallback instanceof Function) || (tickCallback && !(updateCallback instanceof Function))) {
  2294. throw new TypeError(`${this.constructor.name}: updateCallback parameter must be a function (value: ${updateCallback})`);
  2295. }
  2296. Object.assign(this, { containerSelector, childrenSelector, remoteUrl, updateCallback, tickCallback, errorCallback, ignoreInlineStyle, ignoreClassList, ignoreDataAttributes, deepCompare });
  2297. this._interval = null;
  2298. this._running = false;
  2299. }
  2300. observe() {
  2301. if (this._running) { return false; }
  2302. this._interval = setInterval(() => {
  2303. fetch(this.remoteUrl, { cache: 'no-store' })
  2304. .then(response => {
  2305. if (response.ok) {
  2306. return response.text();
  2307. }
  2308. throw new Error(`fetch() resulted with status ${response.status} for url: ${this.remoteUrl}`);
  2309. })
  2310. .then(text => {
  2311. const htmlDoc = (new DOMParser()).parseFromString(text, 'text/html');
  2312. const cloudflareAlert = htmlDoc.documentElement.querySelector('#cf_alert_div');
  2313. if (cloudflareAlert) {
  2314. console.warn(`${this.constructor.name}: fetch() got the Cloudflare response (alert div with id: ${cloudflareAlert.id}) => this response will not be processed`);
  2315. return false;
  2316. }
  2317. this.container = document.querySelector(this.containerSelector); // container can change, so we need to search it everytime
  2318. if (!this.container) {
  2319. console.warn(`${this.constructor.name}: this.container not found (value: ${this.container})`);
  2320. return false;
  2321. }
  2322. this.children = this.container.querySelectorAll(this.childrenSelector);
  2323. this.remoteContainer = htmlDoc.documentElement.querySelector(this.containerSelector);
  2324. if (!this.remoteContainer) {
  2325. console.warn(`${this.constructor.name}: this.remoteContainer not found (value: ${this.remoteContainer})`);
  2326. return false;
  2327. }
  2328. this.remoteChildren = this.remoteContainer.querySelectorAll(this.childrenSelector);
  2329. this.newChildren = nodeListDifference(this.remoteChildren, this.children, { ignoreInlineStyle: this.ignoreInlineStyle, ignoreClassList: this.ignoreClassList, ignoreDataAttributes: this.ignoreDataAttributes, deepCompare: this.deepCompare });
  2330. if (this.newChildren.length > 0) {
  2331. this.updateCallback(this);
  2332. }
  2333. if (this.tickCallback) {
  2334. this.tickCallback(this);
  2335. }
  2336. // console.log('Observer check done at: ' + (new Date()).toISOString());
  2337. })
  2338. .catch(error => {
  2339. console.error(`${this.constructor.name}: ${error}`);
  2340. if (this.errorCallback instanceof Function) {
  2341. this.errorCallback(this, error);
  2342. }
  2343. });
  2344. }, 10 * 1000);
  2345. this._running = true;
  2346. return true;
  2347. }
  2348. disconnect() {
  2349. if (!this._running) { return false; }
  2350. if (this._interval) {
  2351. clearInterval(this._interval);
  2352. this._interval = null;
  2353. }
  2354. this._running = false;
  2355. // console.log('Observer disconnect() at: ' + (new Date()).toISOString());
  2356. return true;
  2357. }
  2358. }
  2359.  
  2360. const blinkingTitle = new BlinkingPageTitle({
  2361. stopOnFocus: !pepperTweakerConfig.autoUpdate.askBeforeLoad,
  2362. playSound: pepperTweakerConfig.autoUpdate.soundEnabled,
  2363. });
  2364.  
  2365. const repairSvgWithUseChildren = element => {
  2366. const svgChildren = element.querySelectorAll('svg');
  2367. for (const svgChild of svgChildren) {
  2368. const svgReplacement = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
  2369. for (const svgChildAttribute of svgChild.attributes) {
  2370. svgReplacement.setAttribute(svgChildAttribute.name, svgChildAttribute.value);
  2371. }
  2372. const useChild = svgChild.querySelector('use');
  2373. const useReplacement = document.createElementNS('http://www.w3.org/2000/svg', 'use');
  2374. useReplacement.setAttributeNS('http://www.w3.org/1999/xlink', 'href', useChild.href.baseVal);
  2375. svgReplacement.appendChild(useReplacement);
  2376. svgChild.parentNode.insertBefore(svgReplacement, svgChild);
  2377. svgChild.remove();
  2378. }
  2379. return element;
  2380. };
  2381.  
  2382. const openConfirmDialog = (title, message, confirmCallback, cancelCallback) => {
  2383. const modalSection = document.createElement('SECTION');
  2384. modalSection.classList.add('js-layer', 'popover', 'popover--modal', 'popover--fade', 'popover--layout-modal', 'popover--visible');
  2385. const popoverContent = document.createElement('DIV');
  2386. popoverContent.classList.add('popover-content', 'popover-content--expand');
  2387. popoverContent.classList.add('space--h-3', 'space--v-3');
  2388. const titleBox = document.createElement('H1');
  2389. titleBox.classList.add('formList-label', 'size--all-xl', 'space--v-1');
  2390. titleBox.style.textAlign = 'center';
  2391. titleBox.appendChild(document.createTextNode(title));
  2392. const messageBox = document.createElement('DIV');
  2393. messageBox.classList.add('space--v-2', 'space--h-2');
  2394. messageBox.style.textAlign = 'center';
  2395. messageBox.style.lineHeight = '1.5';
  2396. for (const messageLine of message.split('\n')) {
  2397. const newLine = document.createElement('P');
  2398. newLine.appendChild(document.createTextNode(messageLine));
  2399. messageBox.appendChild(newLine);
  2400. }
  2401. const confirmButton = createLabeledButton({
  2402. label: 'Potwierdź', className: 'success', callback: () => {
  2403. if (confirmCallback instanceof Function) {
  2404. confirmCallback();
  2405. }
  2406. modalSection.remove();
  2407. }
  2408. });
  2409. confirmButton.classList.add('space--h-2');
  2410. const cancelButton = createLabeledButton({
  2411. label: 'Anuluj', className: 'error', callback: () => {
  2412. if (cancelCallback instanceof Function) {
  2413. cancelCallback();
  2414. }
  2415. modalSection.remove();
  2416. }
  2417. });
  2418. cancelButton.classList.add('space--h-2');
  2419. const buttonsBox = document.createElement('DIV');
  2420. buttonsBox.classList.add('space--v-1');
  2421. buttonsBox.style.display = 'flex';
  2422. buttonsBox.style.justifyContent = 'center';
  2423. buttonsBox.style.alignItems = 'center';
  2424. buttonsBox.append(confirmButton, cancelButton);
  2425. popoverContent.append(titleBox, messageBox, buttonsBox);
  2426. modalSection.style.position = 'fixed';
  2427. modalSection.style.top = '50%';
  2428. modalSection.style.left = '50%';
  2429. modalSection.style.zIndex = 2002;
  2430. modalSection.role = 'dialog';
  2431. popoverContent.style.transform = 'translate(-50%, -50%)'; // cannot do translate with modalSection (overlay disappears)
  2432. const popoverCover = document.createElement('DIV');
  2433. popoverCover.classList.add('popover-cover');
  2434. modalSection.append(popoverContent, popoverCover);
  2435. document.body.appendChild(modalSection);
  2436. }
  2437.  
  2438. /* Prevent Cropping Image Height in Lightbox */
  2439. const lightboxPopoverObserver = new MutationObserver((allMutations, observer) => {
  2440. allMutations.every((mutation) => {
  2441. for (const addedNode of mutation.addedNodes) {
  2442. if (addedNode.classList && addedNode.classList.contains('popover--lightbox')) {
  2443. const heightPopoverObserver = new MutationObserver((allMutations, observer) => {
  2444. allMutations.every((mutation) => {
  2445. const imgHeight = mutation.target.querySelector('img').height;
  2446. mutation.target.style.height = `${imgHeight}px`;
  2447. });
  2448. });
  2449. heightPopoverObserver.observe(addedNode, { attributes: true });
  2450. return false; // break every()
  2451. }
  2452. }
  2453. });
  2454. });
  2455. lightboxPopoverObserver.observe(document.body, { childList: true });
  2456.  
  2457. /*** Profile Page ***/
  2458. if (pepperTweakerConfig.improvements.addCommentPreviewOnProfilePage
  2459. && pepperTweakerConfig.pluginEnabled && location.pathname.match(/\/profile\//)) {
  2460.  
  2461. /* Remove 'Escape' Key Binding at Message Page */
  2462. if (location.pathname.match(/\/messages\//)) {
  2463. document.addEventListener('keyup', (event) => {
  2464. if (event.key.match(/Esc|Escape/i)) { // IE/Edge use 'Esc'
  2465. event.stopPropagation();
  2466. }
  2467. }, true);
  2468. }
  2469.  
  2470. /* Add Comment Preview on Profile Page */
  2471. const commentPermalinks = document.querySelectorAll('a[href*="/comments/permalink/"]');
  2472. for (const commentPermalink of commentPermalinks) {
  2473. fetch(commentPermalink.href)
  2474. .then(response => {
  2475. if (response.ok) {
  2476. return response.text();
  2477. }
  2478. throw new Error(`fetch() resulted with status ${response.status} for url: ${commentPermalink.href}`);
  2479. })
  2480. .then(text => {
  2481. const splitedPermalink = commentPermalink.href.split('/');
  2482. const commentID = splitedPermalink[splitedPermalink.length - 1];
  2483. let htmlDoc = (new DOMParser()).parseFromString(text, 'text/html');
  2484. const remoteCommentBody = htmlDoc.documentElement.querySelector(`article[id="comment-${commentID}"] .comment-body`);
  2485. if (remoteCommentBody) {
  2486. const newCommentBody = document.createElement('DIV');
  2487. newCommentBody.classList.add('width--all-12');
  2488. newCommentBody.style.padding = '15px 5px 0 5px';
  2489. moveAllChildren(remoteCommentBody, newCommentBody);
  2490. commentPermalink.parentNode.appendChild(newCommentBody);
  2491. }
  2492. })
  2493. .catch(error => console.error(error));
  2494. }
  2495. }
  2496.  
  2497. /*** Deal Details Page ***/
  2498. if (pepperTweakerConfig.pluginEnabled && location.pathname.match(/promocje|kupony|dyskusji|feedback/) && location.pathname.match(/-\d+\/?$/)) { // ends with ID
  2499.  
  2500. /* Comment Filtering */
  2501. const hideCommentMessage = 'Ten komentarz został ukryty (kliknij, aby go pokazać)';
  2502. const showCommentMessage = 'Kliknij ponownie, aby ukryć poniższy komentarz';
  2503.  
  2504. const animationDuration = 150;
  2505. const animationEasing = 'linear';
  2506.  
  2507. const showCommentOnClick = event => {
  2508. event.stopPropagation();
  2509. const commentRoot = event.target.parentNode;
  2510. const commentContent = commentRoot.getElementsByClassName('comments-item-inner')[0];
  2511. jQuery(commentContent).show(animationDuration, animationEasing);
  2512. event.target.style.borderBottomWidth = '0';
  2513. event.target.textContent = showCommentMessage;
  2514. event.target.onclick = hideCommentOnClick;
  2515. };
  2516. const hideCommentOnClick = event => {
  2517. event.stopPropagation();
  2518. const commentRoot = event.target.parentNode;
  2519. const commentContent = commentRoot.getElementsByClassName('comments-item-inner')[0];
  2520. jQuery(commentContent).hide(animationDuration, animationEasing);
  2521. setTimeout(function () { event.target.style.borderBottomWidth = '1px'; }, animationDuration);
  2522. event.target.textContent = hideCommentMessage;
  2523. event.target.onclick = showCommentOnClick;
  2524. };
  2525.  
  2526. const createHiddenCommentBar = (textContent, callback) => {
  2527. const hiddenCommentBar = document.createElement('DIV');
  2528. hiddenCommentBar.textContent = textContent;
  2529. hiddenCommentBar.style.textAlign = 'center';
  2530. hiddenCommentBar.style.cursor = 'pointer';
  2531. hiddenCommentBar.style.filter = 'opacity(50%)'; // change text color a little to differentiate from comments
  2532. hiddenCommentBar.style.padding = '3px';
  2533. hiddenCommentBar.style.height = '21px';
  2534. hiddenCommentBar.onclick = callback;
  2535. return hiddenCommentBar;
  2536. };
  2537.  
  2538. const filterComments = (node) => {
  2539. const comments = node.querySelectorAll('.commentList-comment');
  2540. for (const comment of comments) {
  2541. for (const filter of pepperTweakerConfig.commentsFilters) {
  2542. //if (Object.keys(filter).length === 0) continue; // if the filter is empty => continue (otherwise empty filter will remove all elements!)
  2543. if ((filter.active === false) || !filter.keyword && !filter.user) {
  2544. continue;
  2545. }
  2546.  
  2547. let commentAuthor = comment.querySelector('.comment-header .user');
  2548. commentAuthor = commentAuthor && commentAuthor.textContent?.trim();
  2549.  
  2550. if ((!filter.user || commentAuthor && commentAuthor.match(newRegExp(filter.user, 'i')))
  2551. && (!filter.keyword || comment.innerHTML.match(newRegExp(filter.keyword, 'i')))) { // innerHTML here for emoticon match too (e.g. <i class="emoji emoji--type-poo" title="(poo)"></i>)
  2552.  
  2553. if (filter.style.display === 'none') {
  2554. comment.insertBefore(createHiddenCommentBar(hideCommentMessage, showCommentOnClick), comment.firstChild);
  2555. }
  2556. Object.assign(comment.style, filter.style);
  2557. break; // comment style has been applied => stop checking next filters
  2558. }
  2559. }
  2560. }
  2561. }
  2562.  
  2563. /* Add Profile Info */
  2564. const toggleUnderline = event => event.target.style.textDecoration = (event.target.style.textDecoration !== 'underline') ? 'underline' : 'none';
  2565.  
  2566. const addProfileInfo = element => { // this function is used in comments addition too
  2567. // const profileLinks = element.querySelectorAll('.cept-thread-main a[href*="/profile/"], .comment-header a[href*="/profile/"]');
  2568. const profileLinks = element.querySelectorAll('.cept-thread-main a[href*="/profile/"], .comment-header a.user');
  2569. for (const profileLink of profileLinks) {
  2570. const profileLinkHref = profileLink.href || `${location.protocol}//${location.hostname}/profile/${profileLink.textContent}`;
  2571. if (profileLinkHref) {
  2572. fetch(profileLinkHref)
  2573. .then(response => response.text())
  2574. .then(text => {
  2575. let htmlDoc = (new DOMParser()).parseFromString(text, 'text/html');
  2576. const profileSubHeaders = htmlDoc.documentElement.querySelectorAll('.profileHeader-bodyMaxWidth span.profileHeader-text');
  2577. const profileLinkParent = profileLink.parentNode;
  2578. const wrapper = document.createElement('DIV');
  2579. for (const subHeader of profileSubHeaders) {
  2580. const clonedNode = subHeader.cloneNode(true);
  2581. clonedNode.classList.add('space--mr-3');
  2582. wrapper.appendChild(clonedNode);
  2583. }
  2584. wrapper.classList.add('space--ml-3', 'text--color-greyShade');
  2585. profileLink.classList.remove('space--mr-1');
  2586. const spaceBox = profileLinkParent.querySelector('.lbox.space--mr-2');
  2587. if (spaceBox) {
  2588. spaceBox.remove();
  2589. }
  2590. profileLinkParent.appendChild(wrapper);
  2591.  
  2592. /* Add Permalink to Comment Date */
  2593. const commentDateParent = profileLinkParent.nextSibling;
  2594. if (!commentDateParent) return;
  2595. const commentDateElement = commentDateParent.querySelector('time');
  2596. const articleElement = profileLinkParent.closest('article[id^="comment-"]');
  2597. if (articleElement && articleElement.id) {
  2598. const commentID = articleElement.id.split('-')[1];
  2599. const commentDateLink = document.createElement('A');
  2600. const permalinkAddress = `https://www.pepper.pl/comments/permalink/${commentID}`;
  2601. commentDateLink.href = permalinkAddress;
  2602. commentDateLink.target = '_blank';
  2603. commentDateLink.addEventListener('mouseenter', toggleUnderline);
  2604. commentDateLink.addEventListener('mouseleave', toggleUnderline);
  2605. commentDateLink.appendChild(commentDateElement);
  2606. commentDateParent.insertBefore(commentDateLink, commentDateParent.firstChild);
  2607.  
  2608. /* Change Premalink Button to an Anchor */
  2609. const permalinkButton = articleElement.querySelector('button[data-popover*="permalink"]');
  2610. if (permalinkButton) {
  2611. const permalinkAnchor = document.createElement('A');
  2612. moveAllChildren(permalinkButton, permalinkAnchor);
  2613. cloneAttributes(permalinkButton, permalinkAnchor);
  2614. permalinkAnchor.removeAttribute('data-handler');
  2615. permalinkAnchor.href = permalinkAddress;
  2616. permalinkAnchor.target = '_blank';
  2617. permalinkButton.parentNode.replaceChild(permalinkAnchor, permalinkButton);
  2618. }
  2619. }
  2620. })
  2621. .catch(error => console.error(error));
  2622. }
  2623. }
  2624. };
  2625. addProfileInfo(document);
  2626.  
  2627. /* Disabled, because there is no more exact start & end date info => it has to be extracted from human friednly strings... :/ */
  2628. /* Add calendar option */
  2629. // if (location.pathname.match(/(promocje|kupony)\//)) {
  2630. // const dateToGoogleCalendarFormat = date => date.toISOString().replace(/-|:|\.\d\d\d/g, "");
  2631. // const extractDealDateFromString = (str, time) => {
  2632. // if (!str) {
  2633. // return new Date();
  2634. // }
  2635. // let dateResult;
  2636. // const dateString = str.match(/\d+\/\d+\/\d+/); // date in the format: 15/12/2019
  2637. // if (dateString) {
  2638. // const parts = dateString[0].split('/');
  2639. // dateResult = new Date(parts[2], parts[1] - 1, parts[0]);
  2640. // } else if (str.match(/jutro/i)) {
  2641. // dateResult = new Date();
  2642. // dateResult.setDate(dateResult.getDate() + 1);
  2643. // // } else if (str.match(/dzisiaj/i)) {
  2644. // } else {
  2645. // dateResult = new Date();
  2646. // }
  2647. // if (time) {
  2648. // time = time.split(':');
  2649. // dateResult.setHours(time[0], time[1], 0);
  2650. // }
  2651. // return dateResult;
  2652. // };
  2653. // const extractDealDates = () => {
  2654. // // const dateSpans = document.querySelectorAll('.cept-thread-content .border--color-borderGrey.bRad--a span');
  2655. // let start = document.querySelector('.cept-thread-content .border--color-borderGrey .icon--clock.text--color-green');
  2656. // start = extractDealDateFromString(start && start.parentNode.parentNode.textContent, '00:01');
  2657. // let end = document.querySelector('.cept-thread-content .border--color-borderGrey .icon--hourglass');
  2658. // end = extractDealDateFromString(end && end.parentNode.parentNode.textContent, '23:59');
  2659. // if (start >= end) {
  2660. // end.setTime(start.getTime());
  2661. // end.setDate(start.getDate() + 1);
  2662. // }
  2663. // return { start, end };
  2664. // };
  2665. // let dealTitle = document.querySelector('.thread-title--item');
  2666. // dealTitle = dealTitle && encodeURIComponent(dealTitle.textContent.trim());
  2667. // let dealDescription = document.querySelector('.cept-description-container');
  2668. // dealDescription = dealDescription && encodeURIComponent(`${location.href}<br><br>${dealDescription.innerHTML.trim()}`);
  2669. // let dealMerchant = document.querySelector('.cept-merchant-name');
  2670. // dealMerchant = dealMerchant && encodeURIComponent(dealMerchant.textContent.trim());
  2671. // const dealDates = extractDealDates();
  2672.  
  2673. // const timeFrameBox = document.querySelector('.cept-thread-content button');
  2674. // const calendarOptionLink = document.createElement('A');
  2675. // // calendarOptionLink.classList.add('btn', 'space--h-3', 'btn--mode-secondary');
  2676. // calendarOptionLink.classList.add('thread-userOptionLink');
  2677. // calendarOptionLink.style.cssFloat = 'right';
  2678. // calendarOptionLink.style.fontWeight = '900';
  2679. // calendarOptionLink.style.setProperty('margin-right', '7px', 'important');
  2680. // calendarOptionLink.target = '_blank';
  2681. // calendarOptionLink.href = `https://www.google.com/calendar/render?action=TEMPLATE&text=${dealTitle}&details=${dealDescription}&location=${dealMerchant}&dates=${dateToGoogleCalendarFormat(dealDates.start)}%2F${dateToGoogleCalendarFormat(dealDates.end)}`;
  2682. // const calendarOptionImg = document.createElement('IMG');
  2683. // calendarOptionImg.style.width = '18px';
  2684. // calendarOptionImg.style.height = '20px';
  2685. // calendarOptionImg.style.filter = `invert(${pepperTweakerConfig.darkThemeEnabled ? 77 : 28}%)`;
  2686. // calendarOptionImg.style.verticalAlign = 'middle';
  2687. // calendarOptionImg.classList.add('icon', 'space--mr-2');
  2688. // calendarOptionImg.src = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABoAAAAaCAYAAACpSkzOAAAABmJLR0QA/wD/AP+gvaeTAAABAklEQVRIid2WPQ6CMBSAPwx6CokH8Aj+DCYeQTdu4ClcrBdxdtLFGI16FPECJi4mOFDJi4FSlDL4koYC3+vXEtI+yI8LcDK8/5VPI9atEr4BtIAlEBnguKDl8VdAaQcqJzGrbxKZeOUDYcaM2sBZQ0HWpyjJh3mz3ejkANharKiQ98RynUajDkmtIl/0PUeOGP7x09mKTL/2o0qRKe42kF+MADD9uB8CM91f2c6o7C4NyXHwzuvajl9WNBY5ewv+a9FR5ExciUaCvwFNV6KD4OeWOaVFPcE+gY4r0U6wa0tJOr48j5xvqpF+0HcgGehrBNnFSdVtAUkppEhKo6oFabn1Ajsht5QbUQgDAAAAAElFTkSuQmCC';
  2689. // calendarOptionLink.appendChild(calendarOptionImg);
  2690. // const calendarOptionSpan = document.createElement('SPAN');
  2691. // calendarOptionSpan.classList.add('space--t-1');
  2692. // calendarOptionSpan.appendChild(document.createTextNode('Kalendarz'))
  2693. // calendarOptionLink.appendChild(calendarOptionSpan);
  2694. // timeFrameBox.parentNode.appendChild(calendarOptionLink);
  2695. // }
  2696.  
  2697. /* Repair Deal Details Links */ // and comment links
  2698. const repairDealDetailsLinks = (node) => {
  2699. if (pepperTweakerConfig.improvements.repairDealDetailsLinks) {
  2700. const links = node.querySelectorAll('a[title^="http"]');
  2701. const mobileLinkRegExp = /:\/\/(www\.)?m\./i;
  2702. for (const link of links) {
  2703. link.href = link.title.replace(mobileLinkRegExp, '://'); // remove also the part of a mobile link e.g.: m.
  2704. }
  2705. }
  2706. }
  2707.  
  2708. /* Repair Thread Image Link */ // -> to open an image in the box, not a deal in new tab
  2709. if (pepperTweakerConfig.improvements.repairDealImageLink) {
  2710. const replaceClickoutLinkWithPopupImage = clickoutLink => {
  2711. if (!clickoutLink) return null;
  2712. const img = clickoutLink.querySelector('img.thread-image').cloneNode(true);
  2713. const srcFullScreen = img.src.replace('/thread_large/', '/thread_full_screen/');
  2714. img.setAttribute('data-handler', 'track lightbox');
  2715. img.setAttribute('data-track', '{"action":"show_full_image","label":"engagement"}');
  2716. img.setAttribute('data-lightbox', `{"images":[{"width":640,"height":474,"unattached":"","uid":"","url":"${srcFullScreen}"}]}`);
  2717. const popupDiv = clickoutLink.querySelector('div.threadItem-imgCell--wide').cloneNode(true);
  2718. popupDiv.setAttribute('data-handler', 'track lightbox');
  2719. popupDiv.setAttribute('data-track', '{"action":"show_full_image","label":"engagement"}');
  2720. popupDiv.setAttribute('data-lightbox', `{"images":[{"width":640,"height":474,"unattached":"","uid":"","url":"${srcFullScreen}"}]}`);
  2721. const imgFrameDiv = document.createElement('DIV');
  2722. imgFrameDiv.classList.add('imgFrame', 'imgFrame--noBorder', 'threadItem-imgFrame', 'box--all-b', 'clickable', 'cept-thread-img');
  2723. imgFrameDiv.append(img, popupDiv);
  2724. clickoutLink.replaceWith(imgFrameDiv);
  2725. return imgFrameDiv;
  2726. };
  2727.  
  2728. const dealImageLink = document.querySelector('*[id^="thread"] .cept-thread-image-clickout');
  2729. replaceClickoutLinkWithPopupImage(dealImageLink);
  2730. }
  2731.  
  2732. /* Add Like Buttons to Best Comments */
  2733. const addLikeButtonsToBestComments = () => {
  2734. return;
  2735. if (pepperTweakerConfig.improvements.addLikeButtonsToBestComments) {
  2736. let firstLikeButtonNotBlue = document.querySelector('.comment-footer .icon--thumb-up');
  2737. firstLikeButtonNotBlue = firstLikeButtonNotBlue && firstLikeButtonNotBlue.closest('button');
  2738. if (firstLikeButtonNotBlue) { // only if any like button exists
  2739. const bestComments = document.querySelectorAll('#comments .commentList:not(.commentList--anchored) .commentList-item article.comment');
  2740. for (const bestComment of bestComments) {
  2741. const newLikeButton = repairSvgWithUseChildren(firstLikeButtonNotBlue.cloneNode(true));
  2742. const bestCommentId = bestComment.id.replace('comment-', '');
  2743. const likeCountButton = bestComment.querySelector('.cept-like-comment-count');
  2744. let buttonAction, buttonLabel;
  2745. if (likeCountButton.classList.contains('text--color-blue')) {
  2746. newLikeButton.classList.add('linkBlue');
  2747. newLikeButton.classList.remove('linkMute');
  2748. buttonAction = 'unlike';
  2749. buttonLabel = 'Nie lubię';
  2750. } else {
  2751. newLikeButton.classList.add('linkMute');
  2752. newLikeButton.classList.remove('linkBlue');
  2753. buttonAction = 'like';
  2754. buttonLabel = 'Lubię to';
  2755. }
  2756. newLikeButton.querySelector('span span').textContent = buttonLabel;
  2757. newLikeButton.setAttribute('data-track', newLikeButton.getAttribute('data-track').replace(/(un)?like/, buttonAction));
  2758. //data-replace="{"endpoint":"https://www.pepper.pl/promocje/lenovo-ideapad-s340-15iwl-156-intel-core-i5-8265u-8gb-ram-256gb-dysk-mx250-grafika-win10-194390/comments/2997677/like","replaces":["$self",{"target":"body/.js-like-comment-2997677","key":"option","seal":null}]}"
  2759. let dataReplaceAttribute = newLikeButton.getAttribute('data-replace');
  2760. dataReplaceAttribute = dataReplaceAttribute.replace(/\/comments\/\d+\/(un)?like/, `/comments/${bestCommentId}/${buttonAction}`).replace(/like-comment-\d+/, `like-comment-${bestCommentId}`);
  2761. newLikeButton.setAttribute('data-replace', dataReplaceAttribute);
  2762. const permalinkButton = bestComment.querySelector('button[data-popover*="permalink"]');
  2763. permalinkButton.parentNode.insertBefore(newLikeButton, permalinkButton);
  2764. }
  2765. }
  2766. }
  2767. }
  2768.  
  2769. const layoutChangeObserver = new MutationObserver((allMutations, observer) => {
  2770. allMutations.every((mutation) => {
  2771. for (const addedNode of mutation.addedNodes) {
  2772. if (addedNode.id?.match(/comment-\d+/)) {
  2773. // if (addedNode.id === 'comments') {
  2774. // addLikeButtonsToBestComments();
  2775. // }
  2776. repairDealDetailsLinks(addedNode);
  2777. addProfileInfo(addedNode);
  2778. filterComments(addedNode);
  2779. }
  2780. }
  2781. return true;
  2782. });
  2783. });
  2784. layoutChangeObserver.observe(document.querySelector('.listLayout-main'), { childList: true, subtree: true });
  2785.  
  2786. /* Add Search Interface */
  2787. if (pepperTweakerConfig.improvements.addSearchInterface && location.pathname.match(/promocje|kupony|dyskusji\//)) {
  2788.  
  2789. const getSelectionHTML = () => {
  2790. let html = '';
  2791. if (typeof window.getSelection !== 'undefined') {
  2792. const selection = window.getSelection();
  2793. if (selection.rangeCount) {
  2794. const container = document.createElement('div');
  2795. for (let i = 0, selectionRangeCount = selection.rangeCount; i < selectionRangeCount; i++) {
  2796. container.appendChild(selection.getRangeAt(i).cloneContents());
  2797. }
  2798. html = container.innerHTML;
  2799. }
  2800. } else if (typeof document.selection !== 'undefined') { // only for IE < 9
  2801. if (document.selection.type === 'Text') {
  2802. html = document.selection.createRange().htmlText;
  2803. }
  2804. }
  2805. return html;
  2806. };
  2807.  
  2808. const getSelectionText = () => {
  2809. let text = '';
  2810. if (typeof window.getSelection !== 'undefined') {
  2811. const selection = window.getSelection();
  2812. if (selection.rangeCount) {
  2813. for (let i = 0, selectionRangeCount = selection.rangeCount; i < selectionRangeCount; i++) {
  2814. text += selection.getRangeAt(i).toString();
  2815. }
  2816. }
  2817. } else if (typeof document.selection !== 'undefined') { // only for IE < 9
  2818. if (document.selection.type === 'Text') {
  2819. text = document.selection.createRange().text;
  2820. }
  2821. }
  2822. return text;
  2823. };
  2824.  
  2825. // const dealTitleSpan = document.querySelector('article .thread-title--item');
  2826. // const dealTitleInput = createTextInput({ value: dealTitleSpan.textContent.trim() });
  2827. // dealTitleSpan.replaceWith(dealTitleInput);
  2828. const getActualSelectionValue = () => {
  2829. // return dealTitleInput.querySelector('input').value.trim();
  2830. const input = document.activeElement;
  2831. let value = getSelectionText().trim() || (input && input.value && input.value.trim());
  2832. if (value && value.length > 0) {
  2833. return value;
  2834. }
  2835. alert('Najpierw zaznacz fragment tekstu na stronie do wyszukiwania');
  2836. return null;
  2837. // return (input.selectionStart < input.selectionEnd) ? value.substring(input.selectionStart, input.selectionEnd) : value;
  2838. };
  2839.  
  2840. const searchButtonsWrapper = document.createElement('DIV');
  2841. searchButtonsWrapper.style.display = 'flex';
  2842. searchButtonsWrapper.style.flexDirection = 'column';
  2843. searchButtonsWrapper.style.position = 'fixed';
  2844. searchButtonsWrapper.style.width = '42px'; // for setSearchInterfacePosition()
  2845. searchButtonsWrapper.style.top = '50%';
  2846. // searchButtonsWrapper.style.left = `55px`;
  2847. searchButtonsWrapper.style.zIndex = 2002;
  2848. searchButtonsWrapper.style.transform = 'translate(0, -50%)';
  2849. searchButtonsWrapper.append(
  2850. createSearchButton(searchEngine.google, getActualSelectionValue),
  2851. createSearchButton(searchEngine.ceneo, getActualSelectionValue),
  2852. createSearchButton(searchEngine.skapiec, getActualSelectionValue),
  2853. createSearchButton(searchEngine.allegro, getActualSelectionValue),
  2854. createSearchButton(searchEngine.olx, getActualSelectionValue),
  2855. createSearchButton(searchEngine.amazonDe, getActualSelectionValue),
  2856. createSearchButton(searchEngine.aliexpress, getActualSelectionValue),
  2857. createSearchButton(searchEngine.banggood, getActualSelectionValue),
  2858. createSearchButton(searchEngine.joybuy, getActualSelectionValue),
  2859. createSearchButton(searchEngine.ebay, getActualSelectionValue),
  2860. createSearchButton(searchEngine.ggdeals, getActualSelectionValue),
  2861. createSearchButton(searchEngine.iszop, getActualSelectionValue)
  2862. // createSearchButton(searchEngine.ggdeals, getActualSelectionValue, { marginRight: 0 })
  2863. );
  2864.  
  2865. const setSearchInterfacePosition = () => {
  2866. // const searchButtonsWrapperWidth = parseInt(window.getComputedStyle(searchButtonsWrapper).width);
  2867. const searchButtonsWrapperWidth = parseInt(searchButtonsWrapper.style.width);
  2868. const threadArticle = document.querySelector('.thread');
  2869. const threadArticleBoundingClientRect = threadArticle.getBoundingClientRect();
  2870. if (threadArticleBoundingClientRect.left > searchButtonsWrapperWidth) {
  2871. searchButtonsWrapper.style.left = `${threadArticleBoundingClientRect.left - searchButtonsWrapperWidth}px`;
  2872. searchButtonsWrapper.style.opacity = '1';
  2873. return;
  2874. }
  2875. if (threadArticleBoundingClientRect.right + searchButtonsWrapperWidth < getWindowSize().width - 5) {
  2876. searchButtonsWrapper.style.left = `${threadArticleBoundingClientRect.right + 5}px`;
  2877. searchButtonsWrapper.style.opacity = '1';
  2878. return;
  2879. }
  2880. searchButtonsWrapper.style.left = `${threadArticleBoundingClientRect.right - searchButtonsWrapperWidth}px`;
  2881. searchButtonsWrapper.style.opacity = '0.5';
  2882. };
  2883. document.body.appendChild(searchButtonsWrapper); // must add before computing position to get computed width: https://stackoverflow.com/questions/2921428/dom-element-width-before-appended-to-dom
  2884. window.addEventListener('load', setSearchInterfacePosition);
  2885. window.addEventListener('resize', setSearchInterfacePosition);
  2886. // const voteBox = document.querySelector('.cept-vote-box');
  2887. // voteBox.parentNode.style.justifyContent = 'space-between';
  2888. // voteBox.parentNode.style.width = '100%';
  2889. // voteBox.parentNode.appendChild(searchButtonsWrapper);
  2890. }
  2891.  
  2892. /* Auto Update */
  2893. const insertNewCommentsBarBefore = commentNode => {
  2894. let newCommentsBar = document.getElementById('comments-new');
  2895. if (!newCommentsBar) {
  2896. // <div id="comments-new" class="comments-division--landslide"><h2 class="space--v-2 hAlign--all-c aGrid zIndex--above comments-marker-up ">Nowy komentarz</h2></div>
  2897. newCommentsBar = document.createElement('DIV');
  2898. newCommentsBar.id = 'comments-new';
  2899. newCommentsBar.classList.add('comments-division--landslide');
  2900. const newCommentsHeader = document.createElement('H2');
  2901. newCommentsHeader.classList.add('space--v-2', 'hAlign--all-c', 'aGrid', 'zIndex--above', 'comments-marker-up');
  2902. newCommentsHeader.appendChild(document.createTextNode('Nowy komentarz'));
  2903. newCommentsBar.appendChild(newCommentsHeader);
  2904. }
  2905. commentNode.parentNode.insertBefore(newCommentsBar, commentNode);
  2906. };
  2907.  
  2908. const insertNewComments = observer => {
  2909. for (const newComment of observer.newChildren) {
  2910. addProfileInfo(newComment);
  2911. observer.container.insertBefore(repairSvgWithUseChildren(newComment), observer.children[0]);
  2912. }
  2913. const firstCurrentComment = observer.newChildren[observer.newChildren.length - 1].nextSibling;
  2914. const newCommentsBar = document.getElementById('comments-new');
  2915. if (newCommentsBar) {
  2916. newCommentsBar.remove();
  2917. }
  2918. insertNewCommentsBarBefore(firstCurrentComment);
  2919.  
  2920. // Update comments list pagination:
  2921. const remoteHeaderPaginationNav = observer.remoteContainer.parentNode.querySelector('nav.comments-pagination.comments-pagination--header');
  2922. const remoteFooterPaginationNav = observer.remoteContainer.parentNode.querySelector('nav.comments-pagination:not(.comments-pagination--header)');
  2923. if (remoteHeaderPaginationNav && remoteFooterPaginationNav) {
  2924. const headerPaginationNav = observer.container.parentNode.querySelector('nav.comments-pagination.comments-pagination--header');
  2925. const footerPaginationNav = observer.container.parentNode.querySelector('nav.comments-pagination:not(.comments-pagination--header)');
  2926. if (headerPaginationNav) {
  2927. headerPaginationNav.remove();
  2928. }
  2929. if (footerPaginationNav) {
  2930. footerPaginationNav.remove();
  2931. }
  2932. observer.container.parentNode.insertBefore(repairSvgWithUseChildren(remoteHeaderPaginationNav), observer.container);
  2933. observer.container.parentNode.insertBefore(repairSvgWithUseChildren(remoteFooterPaginationNav), observer.container.nextSibling);
  2934. observer.container.classList.add('comments-list--paginated'); // don't need to check if the class exists: "If these classes already exist in the element's class attribute they are ignored."
  2935. }
  2936.  
  2937. // Update number of comments:
  2938. const commentsCountSpan = observer.container.parentNode.querySelector('#thread-comments .icon--comment').nextSibling;
  2939. const remoteCommentsCountSpan = observer.remoteContainer.parentNode.querySelector('#thread-comments .icon--comment').nextSibling;
  2940. commentsCountSpan.replaceWith(remoteCommentsCountSpan);
  2941. };
  2942.  
  2943. const commentsObserver = new RemoteChildrenUpdateObserver({
  2944. containerSelector: 'section#comments .comments-list:not(.comments-list--top)',
  2945. childrenSelector: 'article[id]',
  2946. remoteUrl: location.href, // TODO: ?page=2 etc.
  2947. tickCallback: observer => {
  2948. // Update current comments:
  2949. for (const comment of observer.children) {
  2950. const matchingRemoteComment = Array.from(observer.remoteChildren).find(remoteComment => remoteComment.id === comment.id);
  2951. if (matchingRemoteComment) {
  2952. // Update comment time:
  2953. const commentTime = comment.querySelector('time');
  2954. const remoteCommentTime = matchingRemoteComment.querySelector('time');
  2955. if (commentTime && remoteCommentTime) {
  2956. commentTime.textContent = remoteCommentTime.textContent;
  2957. }
  2958. // Update comment likes:
  2959. const commentLikes = comment.querySelector('.cept-like-comment-count');
  2960. let remoteCommentLikes = matchingRemoteComment.querySelector('.cept-like-comment-count');
  2961. if (remoteCommentLikes) {
  2962. remoteCommentLikes = repairSvgWithUseChildren(remoteCommentLikes);
  2963. if (commentLikes) {
  2964. commentLikes.replaceWith(remoteCommentLikes);
  2965. } else {
  2966. const commentHeader = comment.querySelector('.comment-header');
  2967. commentHeader.appendChild(remoteCommentLikes);
  2968. }
  2969. }
  2970. // Update comment body in case of edit:
  2971. const commentBody = comment.querySelector('.comment-body');
  2972. const remoteCommentBody = matchingRemoteComment.querySelector('.comment-body');
  2973. if (commentBody && remoteCommentBody) {
  2974. commentBody.replaceWith(remoteCommentBody);
  2975. }
  2976. // Update comment buttons in case of liked/reported state changed:
  2977. const commentFooter = comment.querySelector('.comment-footer');
  2978. const remoteCommentFooter = matchingRemoteComment.querySelector('.comment-footer');
  2979. if (commentFooter && remoteCommentFooter) {
  2980. commentFooter.replaceWith(repairSvgWithUseChildren(remoteCommentFooter));
  2981. }
  2982. } else { // comment not found in remoteChildren => remove it
  2983. comment.remove();
  2984. }
  2985. }
  2986. },
  2987. updateCallback: observer => blinkingTitle.run('NOWE komentarze', () => {
  2988. if (pepperTweakerConfig.autoUpdate.askBeforeLoad) {
  2989. openConfirmDialog(
  2990. 'Nowe komentarze',
  2991. 'Czy załadować nowe komentarze?\n(anulowanie przerwie obserwację)',
  2992. () => {
  2993. blinkingTitle.stop();
  2994. insertNewComments(observer);
  2995. },
  2996. () => {
  2997. blinkingTitle.stop();
  2998. observer.disconnect();
  2999. autoUpdateCheckbox.querySelector('input').checked = false;
  3000. }
  3001. );
  3002. } else {
  3003. insertNewComments(observer);
  3004. }
  3005. }),
  3006. // errorCallback: observer => {
  3007. // if (confirm(`Wystąpił błąd podczas pobierania strony (status: ${observer.responseStatus}).\nCzy przerwać obserwowanie?`)) {
  3008. // observer.disconnect();
  3009. // autoUpdateCheckbox.querySelector('input').checked = false;
  3010. // }
  3011. // },
  3012. });
  3013.  
  3014. const autoUpdateCheckbox = createLabeledCheckbox({
  3015. label: 'Obserwuj', callback: event => {
  3016. if (event.target.checked) {
  3017. commentsObserver.observe();
  3018. } else {
  3019. commentsObserver.disconnect();
  3020. }
  3021. }
  3022. });
  3023. autoUpdateCheckbox.classList.add('space--ml-3');
  3024. autoUpdateCheckbox.title = 'Aktualizuj komentarze';
  3025. if (pepperTweakerConfig.autoUpdate.commentsDefaultEnabled) {
  3026. autoUpdateCheckbox.querySelector('input').checked = true;
  3027. commentsObserver.observe();
  3028. }
  3029. const threadCommentsIcon = document.querySelector('#thread-comments .icon--comment');
  3030. if (threadCommentsIcon) { // TODO: this check should be before the whole auto upgrade start
  3031. threadCommentsIcon.parentNode.appendChild(autoUpdateCheckbox);
  3032. }
  3033.  
  3034. return;
  3035. }
  3036. /*** END: Deal Details Page ***/
  3037.  
  3038. /*** Deals List ***/
  3039. if (pepperTweakerConfig.pluginEnabled && ((location.pathname.length < 2) || location.pathname.match(/search|gor%C4%85ce|najgoretsze|dlaciebie|nowe|grupa|om%C3%B3wione|promocje|kupony[^\/]|dyskusji|profile/))) {
  3040.  
  3041. /* Deals Filtering */
  3042. const checkFilters = (filters, deal) => {
  3043. let resultStyle = {};
  3044. for (const filter of filters) {
  3045. //if (Object.keys(filter).length === 0) { continue; } // if the filter is empty => continue (otherwise empty filter will remove all elements!)
  3046. if ((filter.active === false) || !filter.keyword && !filter.merchant && !filter.user && !filter.groups && !(filter.local === true) && !filter.priceBelow && !filter.priceAbove && !filter.discountBelow && !filter.discountAbove) {
  3047. continue;
  3048. }
  3049.  
  3050. if ((!filter.keyword || (deal.title && deal.title.search(newRegExp(filter.keyword, 'i')) >= 0) || (deal.description && deal.description.search(newRegExp(filter.keyword, 'i')) >= 0) || (deal.merchant && deal.merchant.search(newRegExp(filter.keyword, 'i')) >= 0))
  3051. && (!filter.merchant || (deal.merchant && deal.merchant.search(newRegExp(filter.merchant, 'i')) >= 0))
  3052. && (!filter.user || (deal.user && deal.user.search(newRegExp(filter.user, 'i')) >= 0))
  3053. && (!filter.groups || (deal.groups && (deal.groups.length > 0) && deal.groups.findIndex(group => newRegExp(filter.groups, 'i').test(group)) >= 0))
  3054. && (!filter.local || deal.local)
  3055. && (!filter.priceBelow || (deal.price !== null && deal.price < filter.priceBelow))
  3056. && (!filter.priceAbove || (deal.price !== null && deal.price > filter.priceAbove))
  3057. && (!filter.discountBelow || (deal.discount !== null && deal.discount < filter.discountBelow))
  3058. && (!filter.discountAbove || (deal.discount !== null && deal.discount > filter.discountAbove))) {
  3059. Object.assign(resultStyle, filter.style);
  3060. }
  3061. }
  3062. return resultStyle;
  3063. };
  3064.  
  3065. const checkFiltersAndApplyStyle = (element, deal) => {
  3066. const styleToApply = checkFilters(pepperTweakerConfig.dealsFilters, deal);
  3067. if (Object.keys(styleToApply).length > 0) {
  3068. if ((styleToApply.display === 'none') && element.classList.contains('thread--type-card')) {
  3069. element.parentNode.style.display = 'none';
  3070. } else {
  3071. delete Object.assign(styleToApply, { ['outline']: styleToApply['border'] })['border']; // outline instead of border, TODO: it's to heaevy here
  3072. Object.assign(element.style, styleToApply);
  3073. }
  3074. }
  3075. };
  3076.  
  3077. /* List to grid update */
  3078. const updateGridDeal = (dealNode) => {
  3079. const vueString = dealNode?.querySelector('div[data-vue2]')?.dataset?.vue2;
  3080.  
  3081. if (vueString) {
  3082. const vueObject = JSON.parse(vueString);
  3083. const threadObject = vueObject?.props?.thread;
  3084.  
  3085. if (threadObject) {
  3086. const dealHeader = dealNode.querySelector('.threadListCard-header');
  3087. if (dealHeader !== null) {
  3088. const nowDate = new Date();
  3089.  
  3090. // startDate & endDate are in object format i.e.: { timestamp: 1740006060 }
  3091. // publishedAt is defined just as an integer (timestamp)
  3092. const dealStartDate = isInteger(threadObject.startDate?.timestamp) ? new Date(threadObject.startDate.timestamp * 1000) : null;
  3093. const dealEndDate = isInteger(threadObject.endDate?.timestamp) ? new Date(threadObject.endDate.timestamp * 1000) : null;
  3094. const dealPublishedAtDate = isInteger(threadObject.publishedAt) ? new Date(threadObject.publishedAt * 1000) : null;
  3095.  
  3096. let date = null;
  3097. let color = null;
  3098.  
  3099. if (dealStartDate !== null && dealStartDate > nowDate) {
  3100. date = dealStartDate;
  3101. color = 'var(--textStatusInfo)';
  3102. } else if (dealEndDate !== null && dealEndDate < nowDate) {
  3103. date = dealEndDate;
  3104. color = 'var(--textStatusNegative)';
  3105. } else {
  3106. date = dealPublishedAtDate;
  3107. color = null;
  3108. }
  3109.  
  3110. if (date !== null) {
  3111. const dealDateInfo = createDealDateInfo(date, color);
  3112. dealHeader.append(dealDateInfo);
  3113. }
  3114. } else {
  3115. console.error('Deal header not found (.threadListCard-header)');
  3116. }
  3117.  
  3118. const dealFooter = dealNode.querySelector('.threadListCard-footer');
  3119. if (dealFooter !== null) {
  3120. const userSpan = createUserSpanInfo(threadObject.user, threadObject.commentCount);
  3121. dealFooter.prepend(userSpan);
  3122. } else {
  3123. console.error('Deal footer not found (.threadListCard-footer)');
  3124. }
  3125. } else {
  3126. console.error('Extracting VUE object failed');
  3127. }
  3128. } else {
  3129. console.error('VUE element not found in DOM');
  3130. }
  3131. }
  3132.  
  3133. const createDealDateInfo = (date, color = null) => {
  3134. const containerSpan = document.createElement('SPAN');
  3135. containerSpan.classList.add('color--text-TranslucentSecondary');
  3136. containerSpan.style.cssFloat = 'right';
  3137. containerSpan.style.lineHeight = '2.1em';
  3138. if (color) containerSpan.style.color = color;
  3139.  
  3140. const svgElement = document.createElementNS('http://www.w3.org/2000/svg', 'svg');
  3141. svgElement.classList.add('icon', 'icon--clock');
  3142. svgElement.style.verticalAlign = 'middle';
  3143. svgElement.style.setProperty('margin-right', '0.25em', 'important');
  3144. svgElement.setAttribute('width', '18');
  3145. svgElement.setAttribute('height', '18');
  3146.  
  3147. const useElement = document.createElementNS('http://www.w3.org/2000/svg', 'use');
  3148. useElement.setAttributeNS('http://www.w3.org/1999/xlink', 'href', '/assets/img/ico_22b5d.svg#clock');
  3149. svgElement.appendChild(useElement);
  3150.  
  3151. const labelSpan = document.createElement('SPAN');
  3152. labelSpan.style.fontSize = '0.95em';
  3153.  
  3154. const labelText = document.createTextNode(createDealDateInfoString(date));
  3155. labelSpan.appendChild(labelText);
  3156.  
  3157. containerSpan.append(svgElement, labelSpan);
  3158.  
  3159. return containerSpan;
  3160. };
  3161.  
  3162. const isSameDay = (date1, date2) => date1?.setHours(0, 0, 0, 0) === date2?.setHours(0, 0, 0, 0);
  3163.  
  3164. const createDealDateInfoString = (date) => {
  3165. const hours = zeroPad(date.getHours());
  3166. const minutes = zeroPad(date.getMinutes());
  3167. const month = zeroPad(date.getMonth() + 1); // months starting from 0
  3168. const day = zeroPad(date.getDate());
  3169.  
  3170. const nowDate = new Date();
  3171.  
  3172. return isSameDay(date, nowDate) ? `${hours}:${minutes}` : `${day}/${month}`;
  3173. }
  3174.  
  3175. const createUserSpanInfo = (userObject, commentCount = 0) => {
  3176. const containerSpan = document.createElement('SPAN');
  3177. containerSpan.classList.add('color--text-TranslucentSecondary', 'overflow--wrap-off', 'gap--h-1', 'flex', 'boxAlign-ai--all-c');
  3178. // Add some overlay to longer labels
  3179. containerSpan.style['-webkit-mask-image'] = 'linear-gradient(90deg, #000 85%, transparent)';
  3180.  
  3181. // Computing the width of the container based on comments count
  3182. let containerWidth = '108px';
  3183. if (commentCount >= 10 && commentCount <= 99) {
  3184. containerWidth = '100px'
  3185. } else if (commentCount >= 100 && commentCount <= 999) {
  3186. containerWidth = '93px'
  3187. } else if (commentCount >= 1000 && commentCount <= 9999) {
  3188. containerWidth = '85px'
  3189. } else if (commentCount >= 10000 && commentCount <= 99999) {
  3190. containerWidth = '77px'
  3191. }
  3192.  
  3193. containerSpan.style.width = containerWidth;
  3194.  
  3195. const avatarImg = document.createElement('IMG');
  3196. avatarImg.classList.add('size--all-s', 'size--fromW3-m', 'avatar--type-xs', 'img', 'img--type-entity', 'img--square-s');
  3197.  
  3198. // Set an user avatar if present, otherwise set the default Pepper avatar
  3199. if (userObject.avatar && userObject.avatar.path && userObject.avatar.name) {
  3200. avatarImg.src = `https://static.pepper.pl/${userObject.avatar.path}/${userObject.avatar.name}/fi/60x60/qt/45/${userObject.avatar.name}.jpg`;
  3201. } else {
  3202. avatarImg.src = '/assets/img/profile-placeholder_09382.png';
  3203. }
  3204.  
  3205. avatarImg.srcset = avatarImg.src;
  3206.  
  3207. const labelSpan = document.createElement('SPAN');
  3208. labelSpan.classList.add('overflow--ellipsis', 'size--all-xs', 'size--fromW3-s');
  3209. labelSpan.style.textOverflow = 'unset';
  3210.  
  3211. const labelText = document.createTextNode(userObject.username);
  3212.  
  3213. labelSpan.appendChild(labelText);
  3214.  
  3215. containerSpan.append(avatarImg, labelSpan);
  3216.  
  3217. return containerSpan;
  3218. }
  3219. /* END: List to grid update */
  3220.  
  3221. let dealCount = 0;
  3222. const startPage = Number((new URLSearchParams(location.search)).get('page') || 1);
  3223. const getVerticalScrollPercentage = (node) => (node.scrollTop || node.parentNode.scrollTop) / (node.parentNode.scrollHeight - node.parentNode.clientHeight ) * 100;
  3224. const rescale = (v, rMin, rMax, tMin, tMax) => ((v - rMin) / (rMax - rMin)) * (tMax - tMin) + tMin;
  3225. const updatePagination = () => {
  3226. const pageSize = window?.__INITIAL_STATE__?.pagination?.pageSize ?? 30;
  3227.  
  3228. if (dealCount % pageSize === 0) {
  3229. const position = getVerticalScrollPercentage(document.body);
  3230. const currentPage = startPage - 1 + Math.round(rescale((dealCount / pageSize) * (position / 100), 0, 10, 1, 10));
  3231.  
  3232. const searchParams = new URLSearchParams(location.search);
  3233. if (searchParams.get('page') != currentPage) {
  3234. searchParams.set('page', currentPage);
  3235. const newRelativePathQuery = window.location.pathname + '?' + searchParams.toString();
  3236. history.replaceState(null, '', newRelativePathQuery);
  3237.  
  3238. // const pagination = document.getElementById('pagination');
  3239. // const paginationPageText = pagination?.querySelector('.pagination-page .hide--toW2');
  3240. // if (paginationPageText) {
  3241. // paginationPageText.textContent = paginationPageText.textContent.replace(/\d+/, currentPage);
  3242. // }
  3243. // const nextButton = pagination?.querySelector('.cept-next-page button');
  3244. // if (nextButton) {
  3245. // nextButton.dataset.pagination = nextButton.dataset.pagination.replace(/\d+/, currentPage + 1);
  3246. // }
  3247. }
  3248. }
  3249. };
  3250. document.addEventListener('scroll', updatePagination);
  3251.  
  3252. const processElement = (element, deepSearch = false, isGridLayout = false) => {
  3253. if ((element.nodeName === 'DIV') && element.classList.contains('threadCardLayout--card')) {
  3254. element = element.querySelector('article[id^="thread"]');
  3255. }
  3256. if (element && (element.nodeName === 'ARTICLE') && element.id && (element.id.indexOf('thread') === 0)) {
  3257.  
  3258. /* Thread Image to Lightbox */
  3259. const threadImage = element.querySelector('.cept-thread-img');
  3260. if (threadImage) {
  3261. threadImage.dataset.handler = 'lightbox';
  3262. // threadImage.dataset.lightbox = `{"images":[{"width":640,"height":474,"unattached":"","uid":"","url":"${threadImage.src.replace('thread_large', 'thread_full_screen')}"}]}`;
  3263. // image links have beed changed:
  3264. // threadImage.src.replace(/\/re.*/, '.jpg') => original image
  3265. // threadImage.src.replace('300x300/qt/60', '768x768/qt/90') => scaled image to 768x768 with 90 quality (original scale: 300x300 / 60)
  3266. // there are other sizes too: 1024x1024, 1200x1200 (more?)
  3267. threadImage.dataset.lightbox = `{"images":[{"width":640,"height":474,"unattached":"","uid":"","url":"${threadImage.src.replace('300x300/qt/60', '768x768/qt/90')}"}]}`;
  3268.  
  3269. // remove go to the thread behavior after clicking
  3270. try {
  3271. const dataHistory = JSON.parse(element.dataset.history);
  3272. dataHistory.delegate = undefined;
  3273. dataHistory.endpoint = undefined;
  3274. element.dataset.history = JSON.stringify(dataHistory);
  3275. } catch { }
  3276. }
  3277. /* END */
  3278.  
  3279. /* List to grid update */
  3280. if (pepperTweakerConfig.improvements.listToGrid && !isGridLayout) {
  3281. updateGridDeal(element);
  3282. }
  3283. // Pagination
  3284. dealCount++;
  3285. /* END */
  3286.  
  3287. // No deals filtering at search and profile pages (profile => alerts/saved etc.)
  3288. if (location.pathname.match(/search|profile/)) return;
  3289.  
  3290. // Apparently some info has been moved/copied to the "ThreadMainListItemNormalizer" Vue object
  3291. // Becuase the object has to be parsed to find merchant info, it will be faster to get some other info from this object too instead of parsing DOM (e.g. for deal title)
  3292. // Some properties are still missing though (e.g. description, user)
  3293. const threadVueString = element?.querySelector('div[data-vue2]')?.dataset?.vue2;
  3294. const threadVueObject = threadVueString ? JSON.parse(threadVueString)?.props?.thread : undefined;
  3295.  
  3296. const title = threadVueObject?.title ?? element.querySelector('.cept-tt')?.textContent?.trim();;
  3297.  
  3298. const description = element.querySelector('.userHtml-content div')?.textContent?.trim();
  3299.  
  3300. // no more merchant info in the innerHTML property of the thread element => using Vue object instead
  3301. const merchant = threadVueObject?.merchant?.merchantName;
  3302.  
  3303. const user = threadVueObject?.user?.username ?? element.querySelector('span.thread-user')?.textContent?.trim();
  3304.  
  3305. const price = threadVueObject?.price;
  3306. let discount = undefined;
  3307.  
  3308. if (price !== null && price > 0) {
  3309. const nextBestPrice = threadVueObject?.nextBestPrice;
  3310. if (nextBestPrice !== null && nextBestPrice > price) {
  3311. discount = (nextBestPrice - price) / nextBestPrice * 100;
  3312. }
  3313. }
  3314.  
  3315. const local = threadVueObject?.isLocal;
  3316.  
  3317. /**
  3318. * Extracts the groups list from the provided HTML document.
  3319. * @param {Document} htmlDoc - The HTML document to extract the groups list from.
  3320. * @returns {Array<string>} - The list of group names found in the HTML document.
  3321. */
  3322. const getGroupsListFromDocument = (htmlDoc) => {
  3323. try {
  3324. // Get all script elements in the document
  3325. const scriptElements = htmlDoc.getElementsByTagName('script');
  3326.  
  3327. // Iterate through the script elements
  3328. for (const scriptElement of scriptElements) {
  3329. const content = scriptElement.textContent;
  3330.  
  3331. // Attempt to match the content against the regex
  3332. const match = content.match(/window\.__INITIAL_STATE__\s*=\s*(\{[\s\S]*?\});/);
  3333.  
  3334. // If there's no match or the match doesn't contain the JSON object, move to the next script element
  3335. if (!match || !match[1]) {
  3336. continue;
  3337. }
  3338.  
  3339. // Parse the JSON object from the matched string
  3340. const initialState = JSON.parse(match[1]);
  3341.  
  3342. // Extract the groups list from the initialState object and return it
  3343. return initialState.threadDetail?.groupsPath?.map(({ threadGroupName }) => threadGroupName) || [];
  3344. }
  3345. } catch (error) {
  3346. // Log an error message if something goes wrong during processing
  3347. console.error('An error occurred while processing the page:', error);
  3348. return [];
  3349. }
  3350. // Return an empty array if no matching elements were found
  3351. return [];
  3352. }
  3353.  
  3354. const link = element.querySelector('a.cept-tt');
  3355. if (deepSearch && link && link.href && link.href.length > 0) {
  3356. fetch(link.href)
  3357. .then(response => {
  3358. if (response.ok) {
  3359. return response.text();
  3360. }
  3361. throw new Error(`fetch() resulted with status ${response.status} for url: ${link.href}`);
  3362. })
  3363. .then(text => {
  3364. let htmlDoc = (new DOMParser()).parseFromString(text, 'text/html');
  3365. const groups = getGroupsListFromDocument(htmlDoc);
  3366.  
  3367. // After Pepper developers changes there is no more such info preloaded in HTML
  3368. // => window.__INITIAL_STATE__ must be used instead, but isLocol is a property of threadVueObject too
  3369. // const merchantIcon = htmlDoc.documentElement.querySelector('*[id^="thread"] .threadItem-content svg.icon--merchant');
  3370. // const local = merchantIcon !== null && merchantIcon.parentNode.parentNode.textContent.search(/Ogólnopolska/i) < 0;
  3371.  
  3372. htmlDoc = null; // inform GC to clear parsed doc???
  3373.  
  3374. checkFiltersAndApplyStyle(element, { title, description, merchant, user, groups, local, price, discount });
  3375. })
  3376. .catch(error => {
  3377. console.error(`processElement: ${error}`);
  3378. checkFiltersAndApplyStyle(element, { title, description, merchant, user, price, discount });
  3379. });
  3380. } else {
  3381. checkFiltersAndApplyStyle(element, { title, description, merchant, user, price, discount });
  3382. }
  3383. }
  3384. }
  3385.  
  3386. let dealsSectionSelector;
  3387. const dealsSection = document.querySelector(dealsSectionSelector = '.js-threadList') || document.querySelector(dealsSectionSelector = '#toc-target-deals .js-threadList') || document.querySelector(dealsSectionSelector = '#toc-target-deals') || document.querySelector(dealsSectionSelector = '.listLayout') || document.querySelector(dealsSectionSelector = '.listLayout-scrollBox');
  3388. // cannot combine as one selector => div.gridLayout appears before section.gridLayout on the main page
  3389. const isGridLayout = dealsSectionSelector.indexOf('gridLayout') >= 0;
  3390.  
  3391. // local is no more needed to be parsed from HTML doc => using Vue object instead
  3392. // const deepSearch = pepperTweakerConfig.dealsFilters.findIndex(filter => (filter.active !== false) && (filter.groups || (filter.local === true))) >= 0;
  3393. const deepSearch = pepperTweakerConfig.dealsFilters.findIndex(filter => (filter.active !== false) && filter.groups) >= 0;
  3394.  
  3395. if (dealsSection) {
  3396.  
  3397. if (!location.pathname.includes("dyskusji")) {
  3398. /* Process already visible elements */
  3399. for (let childNode of dealsSection.childNodes) {
  3400. processElement(childNode, deepSearch, isGridLayout);
  3401. }
  3402.  
  3403. /* Set the observer to process elements on addition */
  3404. const dealsSectionObserver = new MutationObserver(function (allMutations, observer) {
  3405. allMutations.every(function (mutation) {
  3406. for (const addedNode of mutation.addedNodes) {
  3407. processElement(addedNode, deepSearch, isGridLayout);
  3408. }
  3409. return false;
  3410. });
  3411. });
  3412. dealsSectionObserver.observe(dealsSection, { childList: true });
  3413. }
  3414. /* END: Deals Filtering */
  3415.  
  3416. /* List to Grid */
  3417. if (pepperTweakerConfig.improvements.listToGrid && !isGridLayout) {
  3418. const sideWidgets = document.querySelectorAll('.listLayout-side .listLayout-box');
  3419. const sideWidgetsWidth = Array.from(sideWidgets).map((widget) => parseFloat(window.getComputedStyle(widget).width));
  3420. let sideContainerWidth;
  3421. if (location.pathname.match(/\/search|\/grupa/))
  3422. sideContainerWidth = 304;
  3423. else
  3424. sideContainerWidth = sideWidgetsWidth.reduce((acc, cur) => acc || (isNumeric(cur) && cur > 0), false) ? 234 : 0;
  3425. const sideContainerPadding = 8;
  3426. const columnWidth = 227;
  3427. const gridGapWidth = 10;
  3428. const gridPadding = 10;
  3429. dealsSection.style.display = 'grid';
  3430. dealsSection.style.gridGap = `${gridGapWidth}px`;
  3431. dealsSection.style.gridAutoRows = 'min-content';
  3432.  
  3433. const updateGridView = () => {
  3434. const windowSize = getWindowSize();
  3435. const gridMaxWidth = windowSize.width - sideContainerWidth - 2 * sideContainerPadding - 2 * gridPadding;
  3436. const gridColumnCount = Math.min(pepperTweakerConfig.improvements.gridColumnCount || Infinity, Math.floor(gridMaxWidth / (columnWidth + gridGapWidth)));
  3437. dealsSection.style.gridTemplateColumns = `repeat(${gridColumnCount}, ${columnWidth}px)`;
  3438.  
  3439. if (location.pathname.indexOf("/profile") < 0) {
  3440. const gridMarginLeft = (document.querySelector('.tabbedInterface') != null) ? 0 : Math.floor((gridMaxWidth - gridColumnCount * (columnWidth + gridGapWidth)) / 2);
  3441. dealsSection.style.setProperty('margin-left', `${gridMarginLeft}px`, 'important');
  3442. // id="listingOptionsPortal" => the search sort option with the number of deals found
  3443. document.getElementById('listingOptionsPortal')?.style.setProperty('margin-left', `${gridMarginLeft}px`, 'important');
  3444. }
  3445. }
  3446.  
  3447. updateGridView();
  3448. window.addEventListener('resize', updateGridView);
  3449.  
  3450. const styleNode = document.createElement('style');
  3451. const styleText = document.createTextNode(`
  3452. .listLayout-box.bg--color-brandPrimaryPale {
  3453. grid-column: 1 / -1;
  3454. }
  3455. .threadGrid-headerMeta, .threadListCard-header {
  3456. grid-column: 1;
  3457. grid-row: 1;
  3458. -ms-grid-row-span: 1;
  3459. }
  3460. .cept-meta-ribbon .icon--clock.text--color-green, .cept-meta-ribbon .icon--clock.text--color-green ~ span[class^="hide--"], /* deal starts */
  3461. .cept-meta-ribbon .icon--hourglass, .cept-meta-ribbon .icon--hourglass ~ span[class^="hide--"], /* deal ends */
  3462. .cept-meta-ribbon .icon--location, .cept-meta-ribbon .icon--location ~ span[class^="hide--"], /* local deal */
  3463. .cept-meta-ribbon .icon--world, .cept-meta-ribbon .icon--world ~ span[class^="hide--"], /* delievery */
  3464. .vote-box .cept-show-expired-threads, /* deal ended text */
  3465. .vote-box span[class^="hide--"], /* discussion ended text */
  3466. .threadGrid-headerMeta > div > div:not(.vote-box) button, /* three dots button, covering deal starting date */
  3467. #exploreMoreRelatedWidget, #exploreMoreTopWidgetPortal, /* explore more widget */
  3468. #incontentFuseZonePortal, #incontent1FuseZonePortal, #incontent2FuseZonePortal, #incontent3FuseZonePortal, #incontent4FuseZonePortal, #inListing1AdSlotPortal, #inListing2AdSlotPortal, #inListing3AdSlotPortal, /* empty tiles on a search page */
  3469. #groupHottestWidgetPortal, /* hottests deals widget on the category subpage */
  3470. #rlpBannerPortal, /* link to a voucher subpage on a merchant search page */
  3471. .js-threadList > div:not([class]):not([id]) { /* empty tiles on category subpages */
  3472. display: none;
  3473. }
  3474. .cept-meta-ribbon .icon--refresh {
  3475. margin-right: .35em !important;
  3476. }
  3477. /* Deal added / start / ends etc. */
  3478. .threadListCard-header { /* move the "chip" element to a new line */
  3479. padding-top: 0.8em;
  3480. }
  3481. .chip--type-info, .chip--type-default, .chip--type-warning, .chip--type-expired { /* hide original time info */
  3482. display: none;
  3483. }
  3484. /* END: Deal added / start / ends etc. */
  3485. /* Smaller vote box */
  3486. .cept-vote-box button[data-track*="vote"] {
  3487. padding-left: .28em !important;
  3488. padding-right: .28em !important;
  3489. }
  3490. /* OLD CLASS => Save to delete?
  3491. .threadGrid-image {
  3492. grid-row-start: 2;
  3493. grid-row-end: 4;
  3494. -ms-grid-row-span: 3;
  3495. grid-column: 1;
  3496. width: 196px !important;
  3497. padding: 0.35em 0 0.65em 0 !important;
  3498. }
  3499. */
  3500. .threadListCard-image {
  3501. grid-row-start: 2;
  3502. grid-row-end: 4;
  3503. -ms-grid-row-span: 3;
  3504. grid-column: 1;
  3505. width: 196px !important;
  3506. padding: 0.25em 0 0.2em 0 !important;
  3507. margin: 8px auto 0;
  3508. }
  3509. .threadListCard-image .thread-image {
  3510. max-width: 100%;
  3511. max-height: 100%;
  3512. }
  3513. .thread-listImgCell, .thread-listImgCell--medium {
  3514. width: 100%;
  3515. }
  3516. /* OLD CLASS => Required for discution subpage */
  3517. .threadGrid-title {
  3518. grid-column: 1;
  3519. grid-row-start: 5;
  3520. grid-row-end: 6;
  3521. width: 196px !important;
  3522. }
  3523. .threadGrid-title .thread-title, .threadListCard-body .thread-title {
  3524. padding-top: 0.2em;
  3525. height: 3.1em !important;
  3526. display: inline-block !important;
  3527. }
  3528. .threadGrid-title .overflow--fade {
  3529. height: 1.9em;
  3530. }
  3531. .threadListCard-body .flex--wrap { /* disable wrapping of the price + delivery (etc.) line */
  3532. flex-wrap: nowrap;
  3533. }
  3534. /* OLD CLASS => Required for discution subpage */
  3535. .threadGrid-body {
  3536. grid-column: 1;
  3537. -ms-grid-column-span: 1;
  3538. grid-row: 7;
  3539. padding-top: .28571em !important;
  3540. height: 4.1em;
  3541. text-overflow: ellipsis;
  3542. overflow: hidden;
  3543. display: -webkit-box;
  3544. -webkit-line-clamp: 3;
  3545. -webkit-box-orient: vertical;
  3546. }
  3547. .threadListCard-body {
  3548. grid-column: 1;
  3549. -ms-grid-column-span: 1;
  3550. grid-row: 7;
  3551. padding-top: .28571em !important;
  3552. height: 8.8em;
  3553. text-overflow: ellipsis;
  3554. overflow: hidden;
  3555. display: -webkit-box;
  3556. -webkit-line-clamp: 3;
  3557. -webkit-box-orient: vertical;
  3558. font-size: 1rem !important;
  3559. line-height: 1.5rem !important;
  3560. --line-height: 1.5rem !important;
  3561. }
  3562. @media (min-width: 48em) {
  3563. .threadListCard-body {
  3564. margin: 0.2em 0 0.1em;
  3565. }
  3566. }
  3567. .threadListCard-body div.flex {
  3568. height: 1.7em;
  3569. }
  3570. /* TODO: Move user info to the footer */
  3571. .threadListCard-body div.flex div.flex--inline + span,
  3572. .threadListCard-body .thread-price + span {
  3573. display: none !important;
  3574. }
  3575. .threadListCard-body .userHtml-content { /* remove ellipse text overflow in the middle of a deal description */
  3576. display: inline-block;
  3577. }
  3578. .userHtml-content .size--fromW3-m, .userHtml-content .hide--toW3 { /* add more space between deal description lines */
  3579. line-height: 1.1rem !important;
  3580. --line-height: 1.1rem !important;
  3581. }
  3582. .threadGrid-title .userHtml-content { /* Discussion description */
  3583. height: 6.2em;
  3584. margin-bottom: 0.5em;
  3585. text-overflow: ellipsis;
  3586. overflow: hidden;
  3587. display: -webkit-box;
  3588. -webkit-line-clamp: 4;
  3589. -webkit-box-orient: vertical;
  3590. }
  3591. .userHtml-content .size--fromW3-m, .userHtml-content .hide--toW3 {
  3592. line-height: 1.05rem;
  3593. --line-height: 1.05rem;
  3594. }
  3595. .threadGrid-body.threadGrid--row--collapsed {
  3596. display: none;
  3597. }
  3598. .threadGrid-body .flex--dir-row-reverse {
  3599. flex-direction: column;
  3600. }
  3601. .threadGrid-body .space--t-2 {
  3602. padding-top: 0 !important;
  3603. }
  3604. .threadGrid-body .thread-updates-top,
  3605. .threadGrid-body .voucher {
  3606. display: none;
  3607. }
  3608. /* Voucher buttons */
  3609. .threadListCard-footer .voucher .buttonWithCode-button { /* Allow smaller width of a button */
  3610. min-width: 1rem;
  3611. }
  3612. .threadListCard-footer .voucher .buttonWithCode-button span { /* Hide button text (left only an icon) */
  3613. font-size: 0;
  3614. }
  3615. .threadListCard-footer .voucher .buttonWithCode-code { /* Center the text of a voucher code */
  3616. margin: 0 auto;
  3617. padding-left: 1.25em !important;
  3618. }
  3619. .threadListCard-footer .voucher .color--text-StatusPositive span { /* Hide the defualt long text when clicking the vouvher button */
  3620. display: none;
  3621. }
  3622. .threadListCard-footer .voucher .color--text-StatusPositive:after { /* Replace the default text with short message */
  3623. content: "Skopiowano";
  3624. }
  3625. /* END: Voucher buttons */
  3626. /* Comments, share & bookmark button + user info section */
  3627. .threadListCard-footer .button[data-t="shareBtn"] {
  3628. display: none;
  3629. }
  3630. .threadListCard-footer .button[data-t="addBookmark"],
  3631. .threadListCard-footer .button[data-t="removeBookmark"] {
  3632. order: -1; /* set as the second in a row */
  3633. }
  3634. .threadListCard-footer span:has(> img[src*="/users/"], > img[src*="profile-placeholder"]) {
  3635. order: -2; /* set as the first in a row */
  3636. }
  3637. /* END: Comments & share button */
  3638.  
  3639. /* Hide original user info, local deal info, merchant info etc. */
  3640. .threadListCard-body span:has(> img[src*="/users/"], > img[src*="profile-placeholder"]),
  3641. .threadListCard-body span:has(> a[data-t="merchantLink"]),
  3642. .threadListCard-body span.overflow--ellipsis:has(> span:not([class])), /* merchant info without a link */
  3643. .threadListCard-body div:has(> svg.icon--location) { /* local deal info */
  3644. display: none;
  3645. }
  3646.  
  3647. .threadGrid-body .width--fromW2-6 {
  3648. width: 100%;
  3649. padding: 0 !important;
  3650. margin: 5px;
  3651. }
  3652. .threadGrid-body .cept-threadUpdate,
  3653. .threadGrid-body .flex--dir-row-reverse {
  3654. display: none;
  3655. }
  3656. .threadGrid-footerMeta, .threadListCard-footer {
  3657. grid-column: 1;
  3658. -ms-grid-column-span: 1;
  3659. grid-row: 8;
  3660. padding-top: 0.25em !important;
  3661. }
  3662. .threadGrid-footerMeta { /* needed for discutions */
  3663. width: 196px !important;
  3664. }
  3665. .threadGrid-footerMeta .footerMeta.fGrid, .threadListCard-footer {
  3666. flex-flow: row wrap;
  3667. }
  3668. .threadGrid-footerMeta .iGrid-item {
  3669. margin: 13px 0;
  3670. padding: 0 !important;
  3671. width: 100%;
  3672. }
  3673. .threadGrid-footerMeta .iGrid-item .space--fromW2-r-1 {
  3674. padding-right: 0 !important;
  3675. }
  3676. .threadGrid-footerMeta .cept-flag-mobile-source {
  3677. display: none;
  3678. }
  3679. #toc-target-deals div.thread {
  3680. display: none !important;
  3681. }
  3682. /* .threadGrid-footerMeta .cept-off {
  3683. display: none;
  3684. } */
  3685. #toc-target-deals .listLayout-side {
  3686. position: absolute !important;
  3687. right: 0;
  3688. top: 0;
  3689. }
  3690. /* max-height trims the height of the widget
  3691. #toc-target-deals .listLayout-side > div, .card--type-vertical {
  3692. min-height: 500px;
  3693. max-height: 500px;
  3694. }
  3695. */
  3696. /* this hides some "get deal" buttons
  3697. .footerMeta .iGrid-item.width--all-12.width--fromW3-auto.space--l-0.space--fromW3-l-2.space--t-2.space--fromW3-t-0.hide--empty {
  3698. display: none;
  3699. }
  3700. */
  3701. .js-pagi-top { /* hiding top pagination */
  3702. display: none;
  3703. }
  3704. .listLayout, .tGrid-row.height--all-full .page-content {
  3705. position: static;
  3706. max-width: none;
  3707. }
  3708. .tabbedInterface-tabs.width--max-listLayoutWidth, .cept-hottest-widget-position-top {
  3709. width: 85.4em;
  3710. margin-left: auto;
  3711. margin-right: auto;
  3712. }
  3713. .listLayout-main {
  3714. width: max-content;
  3715. }
  3716. .listLayout-side {
  3717. width: ${sideContainerWidth}px;
  3718. padding: 0 ${sideContainerPadding}px;
  3719. }
  3720. .thread .threadGrid {
  3721. padding-bottom: 0; /* removes padding that appears at the bootm of outline from filters */
  3722. }
  3723. /* Font Size */
  3724. .cept-description-container {
  3725. font-size: 0.75rem !important;
  3726. line-height: 1rem !important;
  3727. }
  3728. .thread-title--list {
  3729. font-size: 0.875rem !important;
  3730. line-height: 1.25rem !important;
  3731. }
  3732. /* END: Font Size */
  3733. .thread-title--list::after {
  3734. top: 20px;
  3735. }
  3736. .size--all-l, .size--all-xl {
  3737. font-size: 1rem !important;
  3738. /* line-height: 1.5rem !important; */
  3739. }
  3740. .listLayout-main > div:empty {
  3741. display: none;
  3742. }
  3743. /* Alert page */
  3744. .flex--expand-v .page-content.page-center {
  3745. max-width: 100%;
  3746. }
  3747. .tabbedInterface-tabs {
  3748. max-width: 60em;
  3749. min-width: 20em;
  3750. margin-left: auto;
  3751. margin-right: auto;
  3752. }
  3753. #tab-manage {
  3754. width: 60em; /* TODO: for some reason alert manage tab doesn't keep width set in the '.tabbedInterface-tabs' class */
  3755. }
  3756. /* END: Alert page */
  3757. /* "Your new tab..." div on "For You" subpage */
  3758. /* id="listingOptionsPortal" => the search sort option with the number of deals found */
  3759. .listLayout-main > div:not([class]):not([id="listingOptionsPortal"]) {
  3760. display: none;
  3761. }
  3762. /* END */
  3763. /* Weird empty space as the first tile on the alert subpage */
  3764. #threadMainListPortal {
  3765. display: none;
  3766. }
  3767. /* END */
  3768. /* Hidding some promo deals with a different class "threadListCard" */
  3769. /* Now all deals have the ".threadListCard" class
  3770. article.thread:has(> .threadListCard) {
  3771. display: none !important;
  3772. } */
  3773. /* END */
  3774. /* Hidding some deal meta ribbons */
  3775. .threadGrid-headerMeta .metaRibbon:not(:has(svg.icon--clock, svg.icon--refresh, svg.icon--flame)) {
  3776. display: none !important;
  3777. }
  3778. /* END */
  3779. /* Hiding dilivery cost with an icon */
  3780. .threadGrid-title span.color--text-TranslucentSecondary:has(svg.icon--truck),
  3781. .threadListCard-body span.color--text-TranslucentSecondary:has(svg.icon--truck) {
  3782. display: none;
  3783. }
  3784. /* END */
  3785. /* Hiding the "ended" text when deal is expired */
  3786. .thread--expired span:has(> svg.icon--hourglass) span {
  3787. display: none !important;
  3788. }
  3789. /* END */
  3790. `);
  3791. styleNode.appendChild(styleText);
  3792. document.head.appendChild(styleNode);
  3793. }
  3794. /* END: List to Grid */
  3795.  
  3796. /* Auto Update */
  3797. if (location.pathname.indexOf("/search") < 0) {
  3798.  
  3799. const updateGridWidgetsPosition = (isGridLayout, container, dealsSelector) => {
  3800. if (isGridLayout) {
  3801. const allCurrentDeals = container.querySelectorAll(dealsSelector);
  3802. if (allCurrentDeals.length < 13) { // only 3 widgets => index: 4 + 2 * 4 => 12 (but starting from 0)
  3803. return false;
  3804. }
  3805. const widgets = container.querySelectorAll('.gridLayout-item.hide--toW4[data-grid-pin="n!"]');
  3806. for (let i = 0, widgetsLength = widgets.length; i < widgetsLength; i++) {
  3807. container.insertBefore(widgets[i], allCurrentDeals[4 + i * 4].parentNode);
  3808. }
  3809. return true;
  3810. }
  3811. };
  3812.  
  3813. const insertNewDeals = observer => {
  3814. for (let newDeal of observer.newChildren) {
  3815. // if deal is already present => remove it
  3816. const dealToReplace = Array.from(observer.children).find(child => child.id === newDeal.id);
  3817. if (dealToReplace) {
  3818. dealToReplace.replaceWith(newDeal);
  3819. continue;
  3820. }
  3821. let firstCurrentDeal = observer.container.querySelector(observer.childrenSelector); // first deal can change in the tickCallback!
  3822. if (isGridLayout) {
  3823. newDeal = newDeal.parentNode;
  3824. if (firstCurrentDeal) {
  3825. firstCurrentDeal = firstCurrentDeal.parentNode;
  3826. }
  3827. }
  3828. newDeal = repairSvgWithUseChildren(newDeal);
  3829. observer.container.insertBefore(newDeal, firstCurrentDeal);
  3830. processElement(newDeal, deepSearch);
  3831. }
  3832. updateGridWidgetsPosition(isGridLayout, observer.container, observer.childrenSelector);
  3833. const refreshBar = document.querySelector('div[class=""][data-handler="vue"]');
  3834. removeAllChildren(refreshBar);
  3835. // observer.container.replaceWith(repairSvgWithUseChildren(observer.remoteContainer));
  3836. };
  3837.  
  3838. const replaceElementDatasetWith = (targetDataset, sourceDataset) => {
  3839. for (const key of Object.keys(targetDataset)) {
  3840. delete targetDataset[key];
  3841. }
  3842. for (const key of Object.keys(sourceDataset)) {
  3843. targetDataset[key] = sourceDataset[key];
  3844. }
  3845. return targetDataset;
  3846. };
  3847.  
  3848. const newDealsObserver = new RemoteChildrenUpdateObserver({
  3849. containerSelector: dealsSectionSelector,
  3850. childrenSelector: 'article[id]',
  3851. remoteUrl: location.href, // TODO: ?page=2 etc. //.replace(location.search, '')
  3852. tickCallback: observer => {
  3853. // if (observer.remoteChildren.length < 20) { // no remote children => there will be no matching deals
  3854. // return;
  3855. // }
  3856. let updateWidgets = false;
  3857. // updating deals details:
  3858. for (const deal of observer.children) {
  3859. const matchingRemoteDeal = Array.from(observer.remoteChildren).find(remoteDeal => remoteDeal.id === deal.id);
  3860. if (matchingRemoteDeal) {
  3861. deal.classList = matchingRemoteDeal.classList; // update class list
  3862. replaceElementDatasetWith(deal.dataset, matchingRemoteDeal.dataset); // update data attributes
  3863. removeAllChildren(deal);
  3864. Array.from(matchingRemoteDeal.children).forEach(child => deal.appendChild(repairSvgWithUseChildren(child)));
  3865. processElement(deal, deepSearch);
  3866. } else { // deal not found in remoteChildren => remove it
  3867. if (isGridLayout) {
  3868. deal.parentNode.remove();
  3869. } else {
  3870. deal.remove();
  3871. }
  3872. updateWidgets = true;
  3873. }
  3874. }
  3875. if (updateWidgets) {
  3876. updateGridWidgetsPosition(isGridLayout, observer.container, observer.childrenSelector);
  3877. }
  3878. },
  3879. updateCallback: observer => blinkingTitle.run('NOWE oferty', () => {
  3880. if (pepperTweakerConfig.autoUpdate.askBeforeLoad) {
  3881. openConfirmDialog(
  3882. 'Nowe oferty',
  3883. 'Czy załadować nowe oferty?\n(anulowanie przerwie obserwację)',
  3884. () => {
  3885. blinkingTitle.stop();
  3886. insertNewDeals(observer);
  3887. },
  3888. () => {
  3889. blinkingTitle.stop();
  3890. observer.disconnect();
  3891. autoUpdateCheckbox.querySelector('input').checked = false;
  3892. }
  3893. );
  3894. } else {
  3895. insertNewDeals(observer);
  3896. }
  3897. }),
  3898. // errorCallback: (observer, error) => {
  3899. // if (observer.responseStatus !== 200) {
  3900. // if (confirm(`Wystąpił błąd podczas pobierania strony (status: ${observer.responseStatus}).\nCzy przerwać obserwowanie?`)) {
  3901. // observer.disconnect();
  3902. // autoUpdateCheckbox.querySelector('input').checked = false;
  3903. // }
  3904. // }
  3905. // },
  3906. });
  3907.  
  3908. const autoUpdateCheckbox = createLabeledCheckbox({
  3909. label: 'Obserwuj', callback: event => {
  3910. if (event.target.checked) {
  3911. newDealsObserver.observe();
  3912. } else {
  3913. newDealsObserver.disconnect();
  3914. }
  3915. }
  3916. });
  3917. autoUpdateCheckbox.classList.add('space--r-3', 'tGrid-cell', 'vAlign--all-m');
  3918. autoUpdateCheckbox.title = 'Aktualizuj stronę z ofertami';
  3919. if (pepperTweakerConfig.autoUpdate.dealsDefaultEnabled) {
  3920. autoUpdateCheckbox.querySelector('input').checked = true;
  3921. newDealsObserver.observe();
  3922. }
  3923. const subNavMenu = document.querySelector('.subNavMenu--menu');
  3924. subNavMenu.parentNode.insertBefore(autoUpdateCheckbox, subNavMenu);
  3925.  
  3926. }
  3927. }
  3928.  
  3929. }
  3930. /*** END: Deals List ***/
  3931. }
  3932. /*** END: startPepperTweaker() ***/
  3933.  
  3934. if (document.readyState === 'complete' || document.readyState === 'interactive') {
  3935. // call on next available tick
  3936. setTimeout(startPepperTweaker, 1);
  3937. } else {
  3938. document.addEventListener('DOMContentLoaded', startPepperTweaker);
  3939. }
  3940.  
  3941. /***** END: RUN AFTER DOCUMENT HAS BEEN LOADED *****/
  3942.  
  3943. })();