// ==UserScript==
// @name Steam Badge Helper
// @namespace iFantz7E.SteamBadgeHelper
// @version 1.15
// @description Add various features to Steam focus on Trading Cards and Badges
// @match http://store.steampowered.com/*
// @match http://steamcommunity.com/*
// @match https://store.steampowered.com/*
// @match http://forums.steampowered.com/*
// @match https://steamcommunity.com/*
// @match http://store.akamai.steampowered.com/*
// @match http://store.steamgames.com/*
// @grant GM_getValue
// @grant GM_setValue
// @grant GM_listValues
// @grant GM_deleteValue
// @grant GM_xmlhttpRequest
// @grant GM_addStyle
// @icon http://store.steampowered.com/favicon.ico
// @copyright 2014, 7-elephant
// @downloadURL none
// ==/UserScript==
// http://userscripts.org/scripts/show/186163
// https://greasyfork.org/en/scripts/5348-steam-badge-helper
(function ()
{
var timeStart = new Date();
// ===== Config =====
var enableDebug = false;
var enableDebugConsole = true;
var enableCleanLink = true;
var enableGreenlightNoAutoplay = true;
var enableLinkBadgeToFriend = true;
var enableLinkStoreToBadge = true;
var enableLinkForumToBadge = true;
var enableLinkBadgeToForum = true;
var enableLinkMarketToBadge = true;
var enableLinkBadgeToMarket = true;
var enableLinkProfile = true;
var enableCompareBadge = true;
var enableAlwaysClearCache = false;
var enableCleanSteamMenu = true;
var enableHideEnhancedBadgePrice = true;
var enableAutoscrollSearch = true;
var enableSwapTitle = true;
var enableShowTitleNoti = true;
var enableResizeTradeWindow = true;
var enableMoveMenuEditProfile = true;
var enableRefreshError = true;
var enableSetAllCheckBox = true;
var enableStoreFocus = true;
var enableStoreHideSection = true;
var enableCache = true;
var enableDebugCache = false;
var timeCacheExpireSec = 300;
var appCards = ["286120", "203990", "32200", "259720", "245550", "306410", "249610", "291130"
, "218640", "268420", "46500"];
var appCardMaps = {"202970": "202990"};
var appDlcs = // Exclude
[
"230889", "256576", "256611", "258643", "222606", "222615", "222618", "277751"
];
// ===== End Config =====
// ===== Cache =====
var tmpl_time = "badge_{APP}_time";
var tmpl_price = "badge_{APP}_{SET}_{NUM}_price";
var tmpl_url = "badge_{APP}_{SET}_{NUM}_url";
var tmpl_owned = "badge_{APP}_{SET}_{NUM}_owned";
function clearCache()
{
var keep = ["counter"];
var cache = GM_listValues()
debug("clearCache: " + cache.length);
for (var i = 0; i < cache.length; i++)
{
if (keep.indexOf(cache[i]) < 0)
{
GM_deleteValue(cache[i]);
}
}
}
if (enableAlwaysClearCache) clearCache();
function debugCache()
{
var cache = GM_listValues()
if (enableDebugCache)
{
debug("debugCache: ");
if (cache != null) for (var i = 0; i < cache.length; i++)
{
debug("-> " + cache[i] + ": " + GM_getValue(cache[i], 0));
}
}
debug("debugCache: " + (cache == null ? 0 : cache.length));
}
setTimeout(debugCache, 0);
function generateCacheName(tmpl, app, isFoil, number)
{
var name = tmpl.replace("{APP}", app);
if (isFoil != null)
{
var set = isFoil ? "F1" : "N1";
name = name.replace("{SET}", set);
}
if (number != null)
{
name = name.replace("{NUM}", number);
}
return name;
}
function generateCacheNameTime(app)
{
return generateCacheName(tmpl_time, app);
}
function generateCacheNamePrice(app, isFoil, number)
{
return generateCacheName(tmpl_price, app, isFoil, number);
}
function generateCacheNameUrl(app, isFoil, number)
{
return generateCacheName(tmpl_url, app, isFoil, number);
}
function generateCacheNameOwned(app, isFoil, number)
{
return generateCacheName(tmpl_owned, app, isFoil, number);
}
function getCacheTime(app)
{
var name = generateCacheNameTime(app);
return GM_getValue(name, 0);
}
function getCacheTimeDiff(app)
{
return parseInt((new Date()) / 1000 - getCacheTime(app));
}
function setCacheTime(app)
{
var name = generateCacheNameTime(app);
GM_setValue(name, parseInt((new Date()) / 1000));
}
function checkCacheExpire(app)
{
var cacheDiff = getCacheTimeDiff(app);
var isCacheExpire = cacheDiff < 0 || cacheDiff > timeCacheExpireSec;
debug("cacheTimeDiff: " + cacheDiff + "s");
debug("isCacheExpire: " + isCacheExpire);
return isCacheExpire;
}
function getCachePrice(app, isFoil, number)
{
var name = generateCacheNamePrice(app, isFoil, number);
return GM_getValue(name, 0);
}
function setCachePrice(app, isFoil, number, data)
{
var name = generateCacheNamePrice(app, isFoil, number);
GM_setValue(name, data);
}
function getCacheUrl(app, isFoil, number)
{
var name = generateCacheNameUrl(app, isFoil, number);
return GM_getValue(name, 0);
}
function setCacheUrl(app, isFoil, number, data)
{
var name = generateCacheNameUrl(app, isFoil, number);
GM_setValue(name, data);
}
function getCacheOwned(app, isFoil, number)
{
var name = generateCacheNameOwned(app, isFoil, number);
return GM_getValue(name, 0);
}
function setCacheOwned(app, isFoil, number, data)
{
var name = generateCacheNameOwned(app, isFoil, number);
GM_setValue(name, data);
}
// ===== End Cache =====
// ===== Helper =====
setTimeout(function ()
{
var counter = GM_getValue('counter', 0);
GM_setValue('counter', ++counter);
}, 0);
function debug(msg)
{
try
{
msg = msg ? (new String(msg)).trim().replace(/\s\s/gi, "").replace(/\s/gi, " ") : "";
if (enableDebugConsole)
console.log(msg);
if (enableDebug)
{
var divDebugID = "div_debug_7e";
var divDebugOuterID = divDebugID + "_outer";
var divOut = document.getElementById(divDebugOuterID);
var div = document.getElementById(divDebugID);
var isExistOuter = divOut != null;
if (!isExistOuter)
{
divOut = document.createElement("div");
divOut.id = divDebugOuterID;
divOut.style = "font-family:'Courier New', Courier; font-size: 11px; z-index: 999999; padding: 3px; text-align: left;"
+ " border: 3px solid orange; color: black; background-color: rgba(255,255,255,0.9);"
+ " position: fixed; top: 3px; left: 3px; overflow-x:hidden; overflow-y:scroll; resize: both;";
divOut.style.width = "150px";
divOut.style.height = "100px";
if (div == null)
{
div = document.createElement("div");
div.id = divDebugID;
div.style.minWidth = "1000px";
div.innerHTML = "Debug:";
}
divOut.appendChild(div);
document.body.appendChild(divOut);
}
div.innerHTML = div.innerHTML + "
" + msg;
divOut.scrollTop = divOut.scrollHeight;
}
}
catch (e)
{
console.log("Ex: " + e);
}
}
function debugTime(header)
{
header = header ? (new String(header)) + ": " : "";
var ms = (new Date()) - timeStart;
debug(header + ms + "ms");
}
function randNum()
{
return parseInt(Math.random() * 900000 + 100000);
}
function randTempID()
{
return "id_temp_7e_" + randNum();
}
function createDivTemp(id, html)
{
var div = document.getElementById(id);
if (div == null)
{
div = document.createElement("div");
div.id = id;
document.body.appendChild(div);
}
div.style.display = "none";
div.style.zIndex = "-999999";
// remove all external sources
var pattScript = /(<(script|meta|link|style|title)[^>]*>|<\/(script|meta|link|style|title)>)/gi;
html = html.replace(pattScript, "");
div.innerHTML = html;
}
function removeDivTemp(id)
{
var ele = document.getElementById(id);
ele.parentNode.removeChild(ele);
}
function attachOnLoad(callback)
{
window.addEventListener("load", function (e) {
callback();
});
}
function attachOnReady(callback)
{
document.addEventListener("DOMContentLoaded", function (e) {
if (document.readyState === "interactive")
{
callback();
}
});
}
function reload()
{
window.location = window.location.href;
}
function isError()
{
var retVal =
window.location == window.parent.location
&&
(
(
document.querySelector("body.headerless_page") == null
&& document.querySelector("body.flat_page") == null
&& document.querySelector("#main") == null
&& document.querySelector("#supernav") == null
&& document.querySelector("table.tborder") == null
&& document.querySelector("#headerrow") == null
&& document.querySelector("#global_header") == null
&& document.querySelector(".page_header_ctn") == null
)
||
(
document.querySelector(".profile_fatalerror_message") != null
|| document.querySelector("#error_msg") != null
//|| document.querySelector("#message") != null
)
);
return retVal;
}
function isErrorCard()
{
var retVal = document.querySelectorAll("#message > p.returnLink").length > 0;
return retVal;
}
function isErrorMarket()
{
var retVal = document.querySelectorAll("#searchResultsTable > .market_listing_table_message").length > 0
;//&& document.querySelector("#hover_content") == null);
return retVal;
}
// ===== End Helper =====
// ===== Cleaner =====
/** Auto refresh when error
*/
function refreshError()
{
if(isError())
{
debug("refreshError: activated");
setTimeout(reload, 3000);
}
}
function refreshErrorCard()
{
if(isErrorCard())
{
debug("refreshErrorCard: activated");
setTimeout(reload, 3000);
}
}
function refreshErrorMarket()
{
if(isErrorMarket())
{
debug("refreshErrorMarket: activated");
setTimeout(reload, 3000);
}
}
function refreshErrorTimeout(tm)
{
function refresh()
{
var url = document.documentURI;
var pattCard = /^http[s]?:\/\/steamcommunity.com\/(id|profiles)\/[^\/]+\/gamecards\/[0-9]+/i;
var pattTrade = /^http[s]?:\/\/steamcommunity.com\/(id|profiles)\/[^\/]+\/tradeoffers\//i;
var pattMarket = /^http:\/\/steamcommunity.com\/market\/listings\/[0-9]+/i;
if (url.indexOf("#") < 0)
{
setTimeout(refreshError, tm);
if (pattCard.test(url) || pattTrade.test(url))
{
setTimeout(refreshErrorCard, tm);
}
if (pattMarket.test(url))
{
setTimeout(refreshErrorMarket, tm);
}
}
}
attachOnLoad(refresh);
}
if (enableRefreshError) refreshErrorTimeout(1000);
/** Remove unnessary parameters in URL
*/
function cleanLink()
{
var url = document.documentURI;
var pattApp = /^http[s]?:\/\/store.steampowered.com\/(app|sub)\/[0-9]+/i;
var pattBadge = /^http[s]?:\/\/steamcommunity.com\/(id|profiles)\/[^\/]+\/gamecards\/[0-9]+/i;
var pattFork = /^http[s]?:\/\/store\.(.+steampowered|steamgames)\.com\//i;
var pattParam = /\/\?.*$/
var pattParamCC = /\/\?cc\=.*$/
var urlNew = url;
if (pattApp.test(url))
{
var urlNews = url.match(pattApp);
if (urlNews != null)
{
var urlTail = url.replace(pattApp, "");
if (urlTail == "")
{
urlNew = urlNews[0] + "/";
}
else if (urlTail != "/")
{
if (!pattParamCC.test(urlTail) && pattParam.test(urlTail))
{
urlNew = urlNews[0] + "/";
}
}
}
}
else if (pattBadge.test(url))
{
var urlNews = url.match(pattBadge);
if (urlNews != null)
{
var urlTail = url.replace(pattBadge, "");
if (urlTail.charAt(0) != "/")
{
urlNew = urlNews[0] + "/" + urlTail;
}
}
}
else if (pattFork.test(url))
{
urlNew = url.replace(pattFork, "http://store.steampowered.com/");
}
if (urlNew != url)
{
debug("cleanLink: activated");
window.location = urlNew;
}
}
if (enableCleanLink) cleanLink();
/** Change search parameter to page 1 to determine visited links
*/
function cleanLinkSearch()
{
var pattSearch = /snr=1_7_7_230_150_[0-9]+/i
var as = document.querySelectorAll("a.search_result_row");
for (var j = 0; j < as.length; j++)
{
var urlSearch = as[j].href;
urlSearch = urlSearch.replace(pattSearch, "snr=1_7_7_230_150_1");
as[j].href = urlSearch;
}
document.addEventListener("DOMNodeInserted", onNodeInserted);
function onNodeInserted(e)
{
try
{
var node = e.target;
if (node.classList.contains("search_result_row"))
{
var urlSearch = node.href;
urlSearch = urlSearch.replace(pattSearch, "snr=1_7_7_230_150_1");
node.href = urlSearch;
}
var count = document.querySelectorAll(".search_result_row").length;
var divs = document.querySelectorAll(".search_pagination_left");
for (var i = 0; i < divs.length; i++)
{
var oldVals = divs[i].innerHTML.match(/[0-9]+/g);
var oldVal = oldVals[oldVals.length > 0 ? oldVals.length-1 : 0];
divs[i].innerHTML = "showing " + count + " of " + oldVal;
}
}
catch (ex)
{
}
}
if (enableAutoscrollSearch)
{
var divButton = document.createElement("div");
divButton.classList.add("btn_client_small");
divButton.id = "divAutoscroll";
divButton.style = "position: fixed; right: 20px; bottom: 20px; z-index:3;";
divButton.innerHTML = "Autoscroll to end";
document.body.appendChild(divButton);
}
}
function cleanLinkSearchTimeout(tm)
{
var url = document.documentURI;
var patt = /^http[s]?:\/\/store.steampowered.com\/search\//i;
if (patt.test(url))
{
setTimeout(cleanLinkSearch, tm);
}
}
if (enableCleanLink) cleanLinkSearchTimeout(100);
/** Remove link lifter in URL
*/
function cleanLinkLifter()
{
var url = document.documentURI;
var patt = /^http[s]?:\/\/steamcommunity.com\//i;
var pattHome = /^http[s]?:\/\/steamcommunity.com\/(id|profiles)\/[^\/]+\/home/i;
function cleanLifter()
{
var lifter = "https://steamcommunity.com/linkfilter/";
var lifterLen = lifter.length;
var lifter2 = "?url=";
var lifterLen2 = lifter2.length;
var js = "javascript:"
var jsLen = js.length;
var as = document.getElementsByTagName("a");
for (var i = 0; i < as.length; i++)
{
var urlLink = as[i].href;
if (urlLink.indexOf(lifter) == 0)
{
urlLink = urlLink.substr(lifterLen);
if (urlLink.indexOf(lifter2) == 0)
{
urlLink = urlLink.substr(lifterLen2);
}
as[i].href = urlLink;
}
else if (patt.test(url) && urlLink.indexOf(js) == 0)
{
if (as[i].getAttribute('onclick') == null)
{
urlLink = decodeURIComponent(urlLink.substr(jsLen));
as[i].setAttribute('onclick', urlLink + "; return false;");
}
}
}
}
var cleanLifterTimeoutId = 0;
function cleanLifterTimeout()
{
clearTimeout(cleanLifterTimeoutId);
cleanLifterTimeoutId = setTimeout(cleanLifter, 1000);
}
attachOnReady(cleanLifter);
if (pattHome.test(url))
{
document.addEventListener("DOMNodeInserted", cleanLifterTimeout);
}
}
if (enableCleanLink) cleanLinkLifter();
/** Clean Steam's menu on top
*/
function cleanSteamMenuTimeout(tm)
{
GM_addStyle(
" .header_installsteam_btn_content , .header_installsteam_btn { display: none; } " // Steam header
+ " #enhanced_pulldown { display: none; } " // Enhanced Steam header
+ " #soe-t-menu { display: none !important; } " // SOE header
);
attachOnReady(function ()
{
setTimeout(function()
{
var soe_menu = document.querySelector("#soe-t-menu");
if (soe_menu != null)
{
soe_menu.textContent = "SOE";
var parent = soe_menu.parentElement;
for (var i = 0; i < parent.childNodes.length; i++)
{
var node = parent.childNodes[i];
if (node.nodeName == "#text" && node.nodeValue.toString().trim() == "|")
{
node.parentElement.removeChild(node);
break;
}
}
soe_menu.parentElement.parentElement.insertBefore(soe_menu, null);
}
}, tm);
});
var menu = document.querySelector("#account_pulldown");
if (menu != null)
{
menu.addEventListener('mouseover', function() {
GM_addStyle(
" #enhanced_pulldown { display: inline-block !important; } " // Enhanced Steam header
+ " #soe-t-menu { display: inline-block !important; } " // SOE header
);
});
}
// fix market transaction display // temp
GM_addStyle("#market_transactions .transactionRowTitle { display: inline-block; padding-right: 5px; }");
/*
setTimeout(function()
{
var as = document.querySelectorAll(".header_installsteam_btn_content , .header_installsteam_btn");
for (var i = 0; i < as.length; i++)
{
as[i].style.display = "none";
}
}, tm);
attachOnLoad(function ()
{
setTimeout(function()
{
var aE = document.getElementById("enhanced_pulldown");
if (aE != null)
{
aE.style.display = "none";
}
}, tm);
});
*/
}
if (enableCleanSteamMenu) cleanSteamMenuTimeout(0);
/** Hide EnhancedSteam's price on Badge page
*/
function hideEnhancedBadgePrice()
{
GM_addStyle(".es_card_search { display: none !important; } ");
/*
document.addEventListener("DOMNodeInserted", onNodeInserted);
function onNodeInserted(e)
{
try
{
var node = e.target;
if (node.classList.contains("es_card_search"))
{
debug("hideEnhanced: " + node.innerHTML);
node.style.display = "none";
}
}
catch (ex)
{
}
}
*/
}
function hideEnhancedBadgePriceTimeout(tm)
{
var url = document.documentURI;
var patt = /^http[s]?:\/\/steamcommunity.com\/(id|profiles)\/[^\/]+\/gamecards\/[0-9]+/i;
if (patt.test(url))
{
setTimeout(hideEnhancedBadgePrice, tm);
}
}
if (enableHideEnhancedBadgePrice) hideEnhancedBadgePriceTimeout(0);
// ===== End Cleaner =====
// ===== Main =====
/** Disable autoplay on Greenlight page while autoplay option is on
*/
function disableGreenlightAutoplay()
{
var iframes = document.getElementsByTagName("iframe");
for (var i in iframes)
{
if (iframes[i].className == "highlight_flash_player_notice")
{
iframes[i].src = iframes[i].src.replace("autoplay=1", "autoplay=0");
}
}
}
function disableGreenlightAutoplayTimeout(tm)
{
var url = document.documentURI;
var patt = /^http:\/\/steamcommunity.com\/sharedfiles\/filedetails\//i;
if (patt.test(url))
{
attachOnLoad(function ()
{
setTimeout(disableGreenlightAutoplay, tm);
});
}
}
if (enableGreenlightNoAutoplay) disableGreenlightAutoplayTimeout(0);
/** Move button in Edit Profile page to right
*/
function moveMenuEditProfile()
{
GM_addStyle(
".group_content_bodytext { position: fixed; top: 400px; margin-left: 680px; line-height: 34px; z-index: 10; } "
+ ".rightcol { position: fixed; top: 230px; margin-left: 658px; z-index: 10; } "
+ ".saved_changes_msg { width: 610px; } "
);
}
function moveMenuEditProfileTimeout(tm)
{
var url = document.documentURI;
var patt = /^http[s]?:\/\/steamcommunity.com\/(id|profiles)\/[^\/]+\/edit/i;
if (patt.test(url))
{
setTimeout(moveMenuEditProfile, tm);
}
}
if (enableMoveMenuEditProfile) moveMenuEditProfileTimeout(0);
/** Add small button on friend section in Badge page to view friends' Badge page for comparing cards
* Reduce height of Review textbox
*/
function linkBadgeToFriend()
{
var url = document.documentURI;
var pattHead = /^http[s]?:\/\/steamcommunity.com\/(id|profiles)\/[^\/]*/i;
var urlTail = url.replace(pattHead, "");
var pattProfile = /^http[s]?:\/\/steamcommunity.com\/(id|profiles)/i;
var styleCorrect = "";
// fix long card name show incorrect column of cards
styleCorrect += ".badge_card_set_card .badge_card_set_text { width: 220px; } ";
// fix Firefox show incorrect column of friends' avatar
styleCorrect += ".persona { line-height: 16px; } ";
// fix EnhancedSteam show incorrect size of next badge progress
styleCorrect += ".gamecard_badge_progress .badge_info { width: 250px !important; } ";
GM_addStyle(styleCorrect);
var els = document.getElementsByTagName("div");
for (var i in els)
{
if (els[i].className == "badge_friends_have_earned_friends"
|| els[i].className == "badge_friendwithgamecard")
{
var as = els[i].getElementsByTagName("a");
var limit = 1;
var curLimit = 0;
for (var j in as)
{
var a = as[j];
if (pattProfile.test(a.href))
{
var badgeUrl = a.href + urlTail;
if (els[i].className == "badge_friends_have_earned_friends"
|| !a.parentNode.classList.contains("playerAvatar"))
{
a.href = badgeUrl;
}
if (curLimit < limit && els[i].className == "badge_friendwithgamecard")
{
elActs = els[i].getElementsByClassName("badge_friendwithgamecard_actions");
for (var k in elActs)
{
elActs[k].innerHTML = elActs[k].innerHTML
+ " ";
curLimit += 1;
}
}
}
} // end for
}
}
}
function linkBadgeToFriendTimeout(tm)
{
var url = document.documentURI;
var patt = /^http[s]?:\/\/steamcommunity.com\/(id|profiles)\/[^\/]+\/gamecards\/[0-9]+/i;
if (patt.test(url) && !isErrorCard())
{
setTimeout(linkBadgeToFriend, tm);
}
}
if (enableLinkBadgeToFriend) linkBadgeToFriendTimeout(100);
/** Add button on top of Store page to view Badge page
*/
function linkStoreToBadge()
{
var url = document.documentURI;
var patt = /^http[s]?:\/\/store.steampowered.com\/app\//i;
var pattEnd = /[^0-9].*$/i;
var app = url.replace(patt, "").replace(pattEnd, "");
var aOwner = document.querySelector("#global_actions > .user_avatar");
var isLoggedIn = aOwner != null;
var ownerUrl = isLoggedIn ? aOwner.href.substr(0, aOwner.href.length - 1) : "http://steamcommunity.com/my";
var isOwned = document.querySelector(".game_area_already_owned") != null;
var urlCard = "http://store.steampowered.com/search/?category2=29";
var titleCard = "Steam Trading Cards";
var urlDlc = "http://store.steampowered.com/search/?category2=21";
var titleDlc = "Downloadable Content";
var urlAch = "http://store.steampowered.com/search/?category2=22";
var titleAch = "Steam Achievement";
var isBadge = false;
var isBadgeMap = false;
var isAch = false;
var as = document.querySelectorAll(".game_area_details_specs a");
for (var i = 0; i < as.length; i++)
{
if (appDlcs.indexOf(app) > -1 || as[i].href == urlDlc || as[i].textContent == titleDlc)
{
isBadge = false;
isAch = false;
break;
}
else if (as[i].href == urlCard || as[i].textContent == titleCard)
{
isBadge = true;
}
else if (as[i].href == urlAch || as[i].textContent == titleAch)
{
isAch = true;
}
}
if (!isBadge)
{
if (appCards.indexOf(app) > -1)
{
isBadge = true;
}
else if (appCardMaps[app] != null)
{
isBadge = true;
isBadgeMap = true;
}
}
if (isBadge)
{
var appCard = app;
if (isBadgeMap)
{
appCard = appCardMaps[app];
}
var divs = document.getElementsByClassName("apphub_OtherSiteInfo");
for (var i = 0; i < divs.length; i++)
{
divs[i].innerHTML = divs[i].innerHTML
+ " "
+ "Trading Cards";
}
}
if (false && isAch)
{
var urlAchLink = (isLoggedIn && isOwned ? ownerUrl + "/stats/appid/" : "http://steamcommunity.com/stats/")
+ app + "/achievements/";
var divCommu = document.querySelector(".communitylink .block_content_inner");
if (divCommu != null)
{
var aAch = ' '
+ '