您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Zapamiętuje w local storage najniższe ceny gier z listy życzeń i pokazuje je obok aktualnie najniższej ceny. Jeśli aktualna cena jest mniejsza od dotychczas zapisanej, wtedy tytuł oznaczany jest na zielono, jeśli cena jest równa naniższej - na niebiesko.
this.$ = this.jQuery = jQuery.noConflict(true); // ==UserScript== // @name Bazar minimalne ceny // @namespace http://tampermonkey.net/ // @version 1.1.0 // @description Zapamiętuje w local storage najniższe ceny gier z listy życzeń i pokazuje je obok aktualnie najniższej ceny. Jeśli aktualna cena jest mniejsza od dotychczas zapisanej, wtedy tytuł oznaczany jest na zielono, jeśli cena jest równa naniższej - na niebiesko. // @author nochalon // @match https://bazar.lowcygier.pl/ // @match https://bazar.lowcygier.pl/?* // @icon https://bazar.lowcygier.pl/favicon.ico // @require https://greasyfork.org/scripts/34527-gmcommonapi-js/code/GMCommonAPIjs.js?version=751210 // @require https://cdnjs.cloudflare.com/ajax/libs/jquery/2.2.4/jquery.min.js // @require https://cdnjs.cloudflare.com/ajax/libs/jquery-timeago/1.5.4/jquery.timeago.min.js // @require https://cdnjs.cloudflare.com/ajax/libs/jquery-timeago/1.5.4/locales/jquery.timeago.pl.js // @grant GM_registerMenuCommand // @grant GM.registerMenuCommand // @grant GM_addStyle // @grant unsafeWindow // ==/UserScript== //TODO // - historia cen na podstawie wielu punktów zamiast jednego - np 10 ostatnich zmian ceny większych niż 10% (function() { 'use strict'; const offersCustomSortingSettingsEntry = "_SETTINGS_offersNewLowestFirst"; const showIntegrationIconsSettingsEntry = "_SETTINGS_showIntegrationIcons"; GMC.registerMenuCommand('Usuń całą historię', () => { if (confirm( `Aktualnie zapisanych jest ${localStorage.length} tytułów. Czy chcesz je wszystkie usunąć?`)) { localStorage.clear(); } }); GMC.registerMenuCommand('Usuń historię tytułu', () => { var title = prompt( "Podaj tytuł gry której historię chcesz usunąć"); if (title != null) { if (!removeFromLocalStorage(title)) { alert("Nie znaleziono tytułu o nazwie: " + title); } } }); var showHideIntegrationToggleTitle = 'Integracja z gg.deals i allkeyshop'; GMC.registerMenuCommand(showHideIntegrationToggleTitle, () => { var showIntegrationIconsVal = (localStorage.getItem(showIntegrationIconsSettingsEntry) || 'true') == 'true'; var showHideIntegrationTogglePrompt = showIntegrationIconsVal ? 'Czy chcesz wyłączyć ikony integracji gg.deals i allkeyshop?' : 'Czy chcesz włączyć ikony integracji gg.deals i allkeyshop?'; if (confirm(showHideIntegrationTogglePrompt)) { localStorage.setItem(showIntegrationIconsSettingsEntry, !showIntegrationIconsVal); unsafeWindow.getData(); } }); GMC.addStyle( ` .new-lowest-price { color: #00FF00 !important; animation: blinkingText 3s infinite; } @keyframes blinkingText{ 0% { color: #00FF00;} 50% { color: #009000;} 100% { color: #00FF00;} } .currently-low-price { color: #0000E0 !important; } .tooltip, .tooltip-inner { padding: 10px; } p.prev-price p { font-size: 18px; } p.prev-price, p.prev-price p { margin: 0 0 1px; } .price-comparators { } .price-comparator-icon { width: 24px; height: 24px; } .game-list { padding-top: 5px; padding-bottom: 5px; } ` ); const newLowestPriceStyle = "new-lowest-price"; const currentlyLowPriceStyle = "currently-low-price"; const offersListSelector = "div.list-view"; const offersListElemSelector = offersListSelector + " > div"; const offersListInnerElemSelector = offersListElemSelector + " > div.row.game-list.wishlist-item"; const offersCustomSortingName = "offers-custom-sorting"; const offersCustomSortingStyle = "";//"float: left; width: 100%;"; const offersCustomSortingSelector = "form#search-offer-form > div.row.second"; const offersNumberSelector = offersCustomSortingSelector+ " > div:nth-child(2)"; document.querySelector(offersNumberSelector).style = "margin-left: 0px"; var searchRow = document.querySelector(offersCustomSortingSelector); var offersCustomSortingVal = (localStorage.getItem(offersCustomSortingSettingsEntry) || 'false') == 'true'; var offersCustomSortingElem = document.createElement('div'); offersCustomSortingElem.style = offersCustomSortingStyle; offersCustomSortingElem.innerHTML = `<input type="checkbox" id="${offersCustomSortingName}"><label for="${offersCustomSortingName}">Sortowanie wg. atrakcyjności ceny</label>`; searchRow.appendChild(offersCustomSortingElem); var offersCustomSortingCheckbox = document.querySelector("input#" + offersCustomSortingName); offersCustomSortingCheckbox.checked = offersCustomSortingVal; offersCustomSortingCheckbox.addEventListener("change", (e) => { localStorage.setItem(offersCustomSortingSettingsEntry, e.target.checked); //this is a callback function used for all vanilla inputs unsafeWindow.getData(); }); var ths = document.querySelectorAll(offersListInnerElemSelector); console.log("Local storage contains " + localStorage.length + " items"); var lowerPriceItems = []; var showIntegrationIconsVal = (localStorage.getItem(showIntegrationIconsSettingsEntry) || 'true') == 'true'; for (var i = 0; i < ths.length; i++) { var middleRow = ths[i].querySelector("div.item > div:nth-child(2)"); var titleElem = ths[i].querySelector(".media-heading > a"); var title = titleElem.innerHTML; var priceElem = ths[i].querySelector(".pc > p.prc"); var price = priceElem.innerHTML; var priceFloat = parseFloat(price.replace(',', '.')); var inStorage = JSON.parse(localStorage.getItem(title)); if (inStorage === null) { console.log(`Adding new entry for ${title} with price ${priceFloat}`); saveToLocalStorage(title, priceFloat); continue; } else if (inStorage.price > priceFloat) { console.log(`Replacing price for ${title} ${inStorage.price} with ${priceFloat}`); saveToLocalStorage(title, priceFloat); } var priceParent = priceElem.parentNode; var prevPriceWrapper = document.createElement("p"); prevPriceWrapper.classList.add("prev-price"); priceParent.appendChild(prevPriceWrapper); if (showIntegrationIconsVal) { appendIntegrations(title, middleRow); } var diff = inStorage.price - priceFloat; if (diff > 0) { titleElem.classList.add(newLowestPriceStyle); priceElem.classList.add(newLowestPriceStyle); appendStoredPrice(inStorage.price, priceFloat, prevPriceWrapper); lowerPriceItems.push({'title': title, 'diff': diff}); } else if (-diff <= 0.05 * inStorage.price) { titleElem.classList.add(currentlyLowPriceStyle); priceElem.classList.add(currentlyLowPriceStyle); if (diff != 0.0) { appendStoredPrice(inStorage.price, priceFloat, prevPriceWrapper); } appendTime(inStorage.timestamp, prevPriceWrapper); } else { appendStoredPrice(inStorage.price, priceFloat, prevPriceWrapper); appendTime(inStorage.timestamp, prevPriceWrapper); } ths[i].parentNode.setAttribute('data-sort', diff/inStorage.price); } //TODO make toggleable or remove if (false && lowerPriceItems.length > 0) { appendLowerPricesBanner(document.querySelector(".banner-top"), lowerPriceItems); } if (offersCustomSortingVal) { var result = jQuery(offersListElemSelector).sort(function (a, b) { var contentA = parseFloat($(a).data('sort')) || 0; var contentB = parseFloat($(b).data('sort')) || 0; return (contentA > contentB) ? -1 : (contentA < contentB) ? 1 : 0; }); jQuery(offersListElemSelector).remove(); jQuery(offersListSelector).prepend(result); } })(); function appendLowerPricesBanner(bannerTop, items) { var alert = document.createElement("p"); bannerTop.insertBefore(alert, bannerTop.firstChild); //TODO move to style section alert.classList = "lowerPrices"; alert.style = "font-weight: bold; font-size: 1.3em; background: -webkit-linear-gradient(135deg, rgb(192, 192, 192) 0%, rgb(214, 214, 214) 25%, rgb(230, 230, 230) 100%); background-color: rgb(230,230,230); background: linear-gradient(135deg, rgb(192, 192, 192) 0%, rgb(214, 214, 214) 25%, rgb(230, 230, 230) 100%); border: 2px solid lightgrey; padding: 6px;"; alert.innerHTML = "<p>Pojawiły się nowe najniższe ceny dla:</p><ul>"; for (let i = 0; i < items.length; i++) { alert.innerHTML += "<li>" + items[i].title + " (" + (parseFloat(-items[i].diff).toFixed(2)) + "zł)</li>"; } alert.innerHTML += "</ul>"; } function appendTime(timeVal, elem) { var time = document.createElement("time"); var timeString = new Date(timeVal); time.innerHTML = timeString.toLocaleString(); time.dateTime = timeString.toISOString(); time.classList = "timeago"; elem.appendChild(time); jQuery(time).timeago(); } function appendStoredPrice(old, newp, elem) { var diff = old - newp; var priceElem = document.createElement("p"); var val = (-diff/newp * 100.0).toFixed(1); priceElem.title = val > 0 ? `taniej o ${val}%` : `drożej o ${-val}%`; priceElem.setAttribute('data-toggle', 'tooltip'); priceElem.innerHTML = "" + parseFloat(old).toFixed(2) + "zł"; elem.appendChild(priceElem); } function appendIntegrations(title, elem) { var newPriceElem = document.createElement("p"); newPriceElem.classList.add("price-comparators"); elem.appendChild(newPriceElem); var ggDeals = createGGDealsButton(title); var allKeyStop = createAllKeyShopButton(title); newPriceElem.appendChild(ggDeals); newPriceElem.appendChild(allKeyStop); } function saveToLocalStorage(title, price) { var newItem = {'price': price, 'timestamp': Date.now()}; localStorage.setItem(title, JSON.stringify(newItem)); } function removeFromLocalStorage(key) { var keyLowerCase = key.toLowerCase(); for (var a in localStorage) { if (a.toLowerCase() === keyLowerCase) { localStorage.removeItem(a); return true; } } return false; } function createGGDealsButton(title) { return createLinkWithImageAndCaption("https://gg.deals/favicon.ico", `https://gg.deals/games/?title=${title}`, `Porównaj ceny ${title} a GG.deals`); } function createAllKeyShopButton(title) { return createLinkWithImageAndCaption("https://www.allkeyshop.com/favicon.ico", `https://www.allkeyshop.com/blog/catalogue/category-pc-games-all/search-${title}/sort-price-asc/`, `Porównaj ceny ${title} na AllKeyShop`); } function createLinkWithImageAndCaption(img, href, caption) { var elem = document.createElement("a"); var imgElem = document.createElement("img"); elem.appendChild(imgElem); elem.href = href; elem.target = "_blank"; elem.title = caption; imgElem.src = img; imgElem.classList.add("price-comparator-icon"); return elem; }