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;
}