Steam Badge Helper

Add various features to Steam focus on Trading Cards and Badges

当前为 2014-10-10 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Steam Badge Helper
  3. // @namespace iFantz7E.SteamBadgeHelper
  4. // @version 1.14
  5. // @description Add various features to Steam focus on Trading Cards and Badges
  6. // @match http://store.steampowered.com/*
  7. // @match http://steamcommunity.com/*
  8. // @match https://store.steampowered.com/*
  9. // @match http://forums.steampowered.com/*
  10. // @match https://steamcommunity.com/*
  11. // @match http://store.akamai.steampowered.com/*
  12. // @match http://store.steamgames.com/*
  13. // @grant GM_getValue
  14. // @grant GM_setValue
  15. // @grant GM_listValues
  16. // @grant GM_deleteValue
  17. // @grant GM_xmlhttpRequest
  18. // @grant GM_addStyle
  19. // @icon http://store.steampowered.com/favicon.ico
  20. // @copyright 2014, 7-elephant
  21. // ==/UserScript==
  22.  
  23. // OldHost: http://userscripts.org/scripts/show/186163
  24.  
  25. (function ()
  26. {
  27. var timeStart = new Date();
  28.  
  29. // ===== Config =====
  30.  
  31. var enableDebug = false;
  32. var enableDebugConsole = true;
  33. var enableCleanLink = true;
  34. var enableGreenlightNoAutoplay = true;
  35. var enableLinkBadgeToFriend = true;
  36. var enableLinkStoreToBadge = true;
  37. var enableLinkForumToBadge = true;
  38. var enableLinkBadgeToForum = true;
  39. var enableLinkMarketToBadge = true;
  40. var enableLinkBadgeToMarket = true;
  41. var enableLinkProfile = true;
  42. var enableCompareBadge = true;
  43. var enableAlwaysClearCache = false;
  44. var enableHideSteamMenu = false;
  45. var enableHideEnhancedBadgePrice = true;
  46. var enableAutoscrollSearch = true;
  47. var enableSwapTitle = true;
  48. var enableShowTitleNoti = true;
  49. var enableResizeTradeWindow = true;
  50. var enableMoveMenuEditProfile = true;
  51. var enableRefreshError = true;
  52. var enableSetAllCheckBox = true;
  53. var enableStoreFocus = true;
  54. var enableStoreHideSection = true;
  55. var enableCache = true;
  56. var enableDebugCache = false;
  57. var timeCacheExpireSec = 300;
  58. var appCards = ["286120", "203990", "32200", "259720", "245550", "306410", "249610", "291130"
  59. , "218640", "268420", "46500"];
  60. var appCardMaps = {"202970": "202990"};
  61. var appDlcs = ["230889", "256576", "256611", "258643", "222606", "222615", "222618"]; // Exclude
  62. // ===== End Config =====
  63.  
  64. // ===== Cache =====
  65.  
  66. var tmpl_time = "badge_{APP}_time";
  67. var tmpl_price = "badge_{APP}_{SET}_{NUM}_price";
  68. var tmpl_url = "badge_{APP}_{SET}_{NUM}_url";
  69. var tmpl_owned = "badge_{APP}_{SET}_{NUM}_owned";
  70.  
  71. function clearCache()
  72. {
  73. var keep = ["counter"];
  74. var cache = GM_listValues()
  75. debug("clearCache: " + cache.length);
  76. for (var i = 0; i < cache.length; i++)
  77. {
  78. if (keep.indexOf(cache[i]) < 0)
  79. {
  80. GM_deleteValue(cache[i]);
  81. }
  82. }
  83. }
  84. if (enableAlwaysClearCache) clearCache();
  85.  
  86. function debugCache()
  87. {
  88. var cache = GM_listValues()
  89. if (enableDebugCache)
  90. {
  91. debug("debugCache: ");
  92. if (cache != null) for (var i = 0; i < cache.length; i++)
  93. {
  94. debug("-> " + cache[i] + ": " + GM_getValue(cache[i], 0));
  95. }
  96. }
  97. debug("debugCache: " + (cache == null ? 0 : cache.length));
  98. }
  99. setTimeout(debugCache, 0);
  100.  
  101. function generateCacheName(tmpl, app, isFoil, number)
  102. {
  103. var name = tmpl.replace("{APP}", app);
  104. if (isFoil != null)
  105. {
  106. var set = isFoil ? "F1" : "N1";
  107. name = name.replace("{SET}", set);
  108. }
  109. if (number != null)
  110. {
  111. name = name.replace("{NUM}", number);
  112. }
  113. return name;
  114. }
  115. function generateCacheNameTime(app)
  116. {
  117. return generateCacheName(tmpl_time, app);
  118. }
  119. function generateCacheNamePrice(app, isFoil, number)
  120. {
  121. return generateCacheName(tmpl_price, app, isFoil, number);
  122. }
  123. function generateCacheNameUrl(app, isFoil, number)
  124. {
  125. return generateCacheName(tmpl_url, app, isFoil, number);
  126. }
  127. function generateCacheNameOwned(app, isFoil, number)
  128. {
  129. return generateCacheName(tmpl_owned, app, isFoil, number);
  130. }
  131.  
  132. function getCacheTime(app)
  133. {
  134. var name = generateCacheNameTime(app);
  135. return GM_getValue(name, 0);
  136. }
  137. function getCacheTimeDiff(app)
  138. {
  139. return parseInt((new Date()) / 1000 - getCacheTime(app));
  140. }
  141. function setCacheTime(app)
  142. {
  143. var name = generateCacheNameTime(app);
  144. GM_setValue(name, parseInt((new Date()) / 1000));
  145. }
  146. function checkCacheExpire(app)
  147. {
  148. var cacheDiff = getCacheTimeDiff(app);
  149. var isCacheExpire = cacheDiff < 0 || cacheDiff > timeCacheExpireSec;
  150. debug("cacheTimeDiff: " + cacheDiff + "s");
  151. debug("isCacheExpire: " + isCacheExpire);
  152. return isCacheExpire;
  153. }
  154.  
  155. function getCachePrice(app, isFoil, number)
  156. {
  157. var name = generateCacheNamePrice(app, isFoil, number);
  158. return GM_getValue(name, 0);
  159. }
  160. function setCachePrice(app, isFoil, number, data)
  161. {
  162. var name = generateCacheNamePrice(app, isFoil, number);
  163. GM_setValue(name, data);
  164. }
  165.  
  166. function getCacheUrl(app, isFoil, number)
  167. {
  168. var name = generateCacheNameUrl(app, isFoil, number);
  169. return GM_getValue(name, 0);
  170. }
  171. function setCacheUrl(app, isFoil, number, data)
  172. {
  173. var name = generateCacheNameUrl(app, isFoil, number);
  174. GM_setValue(name, data);
  175. }
  176.  
  177. function getCacheOwned(app, isFoil, number)
  178. {
  179. var name = generateCacheNameOwned(app, isFoil, number);
  180. return GM_getValue(name, 0);
  181. }
  182. function setCacheOwned(app, isFoil, number, data)
  183. {
  184. var name = generateCacheNameOwned(app, isFoil, number);
  185. GM_setValue(name, data);
  186. }
  187.  
  188. // ===== End Cache =====
  189.  
  190. // ===== Helper =====
  191.  
  192. setTimeout(function ()
  193. {
  194. var counter = GM_getValue('counter', 0);
  195. GM_setValue('counter', ++counter);
  196. }, 0);
  197.  
  198. function debug(msg)
  199. {
  200. try
  201. {
  202. msg = msg ? (new String(msg)).trim().replace(/\s\s/gi, "").replace(/\s/gi, " ") : "";
  203. if (enableDebugConsole)
  204. console.log(msg);
  205. if (enableDebug)
  206. {
  207. var divDebugID = "div_debug_7e";
  208. var divDebugOuterID = divDebugID + "_outer";
  209. var divOut = document.getElementById(divDebugOuterID);
  210. var div = document.getElementById(divDebugID);
  211.  
  212. var isExistOuter = divOut != null;
  213. if (!isExistOuter)
  214. {
  215. divOut = document.createElement("div");
  216. divOut.id = divDebugOuterID;
  217. divOut.style = "font-family:'Courier New', Courier; font-size: 11px; z-index: 999999; padding: 3px; text-align: left;"
  218. + " border: 3px solid orange; color: black; background-color: rgba(255,255,255,0.9);"
  219. + " position: fixed; top: 3px; left: 3px; overflow-x:hidden; overflow-y:scroll; resize: both;";
  220. divOut.style.width = "150px";
  221. divOut.style.height = "100px";
  222.  
  223. if (div == null)
  224. {
  225. div = document.createElement("div");
  226. div.id = divDebugID;
  227. div.style.minWidth = "1000px";
  228. div.innerHTML = "<span style='font-weight: bold; line-height: 18px;'>Debug:</span>";
  229. }
  230. divOut.appendChild(div);
  231. document.body.appendChild(divOut);
  232. }
  233. div.innerHTML = div.innerHTML + " <br/> " + msg;
  234. divOut.scrollTop = divOut.scrollHeight;
  235. }
  236. }
  237. catch (e)
  238. {
  239. console.log("Ex: " + e);
  240. }
  241. }
  242.  
  243. function debugTime(header)
  244. {
  245. header = header ? (new String(header)) + ": " : "";
  246. var ms = (new Date()) - timeStart;
  247. debug(header + ms + "ms");
  248. }
  249.  
  250. function randNum()
  251. {
  252. return parseInt(Math.random() * 900000 + 100000);
  253. }
  254.  
  255. function randTempID()
  256. {
  257. return "id_temp_7e_" + randNum();
  258. }
  259.  
  260. function createDivTemp(id, html)
  261. {
  262. var div = document.getElementById(id);
  263. if (div == null)
  264. {
  265. div = document.createElement("div");
  266. div.id = id;
  267. document.body.appendChild(div);
  268. }
  269. div.style.display = "none";
  270. div.style.zIndex = "-999999";
  271.  
  272. // remove all external sources
  273. var pattScript = /(<(script|meta|link|style|title)[^>]*>|<\/(script|meta|link|style|title)>)/gi;
  274. html = html.replace(pattScript, "");
  275.  
  276. div.innerHTML = html;
  277. }
  278.  
  279. function removeDivTemp(id)
  280. {
  281. var ele = document.getElementById(id);
  282. ele.parentNode.removeChild(ele);
  283. }
  284.  
  285. function attachOnLoad(callback)
  286. {
  287. window.addEventListener("load", function (e) {
  288. callback();
  289. });
  290. }
  291. function attachOnReady(callback)
  292. {
  293. document.addEventListener("DOMContentLoaded", function (e) {
  294. if (document.readyState === "interactive")
  295. {
  296. callback();
  297. }
  298. });
  299. }
  300. function reload()
  301. {
  302. window.location = window.location.href;
  303. }
  304. function isError()
  305. {
  306. var retVal =
  307. window.location == window.parent.location
  308. &&
  309. (
  310. (
  311. document.querySelector("body.headerless_page") == null
  312. && document.querySelector("body.flat_page") == null
  313. && document.querySelector("#main") == null
  314. && document.querySelector("#supernav") == null
  315. && document.querySelector("table.tborder") == null
  316. && document.querySelector("#headerrow") == null
  317. && document.querySelector("#global_header") == null
  318. && document.querySelector(".page_header_ctn") == null
  319. )
  320. ||
  321. (
  322. document.querySelector(".profile_fatalerror_message") != null
  323. || document.querySelector("#error_msg") != null
  324. //|| document.querySelector("#message") != null
  325. )
  326. );
  327. return retVal;
  328. }
  329. function isErrorCard()
  330. {
  331. var retVal = document.querySelectorAll("#message > p.returnLink").length > 0;
  332. return retVal;
  333. }
  334. function isErrorMarket()
  335. {
  336. var retVal = document.querySelectorAll("#searchResultsTable > .market_listing_table_message").length > 0
  337. ;//&& document.querySelector("#hover_content") == null);
  338. return retVal;
  339. }
  340.  
  341. // ===== End Helper =====
  342.  
  343.  
  344. // ===== Cleaner =====
  345. /** Auto refresh when error
  346. */
  347. function refreshError()
  348. {
  349. if(isError())
  350. {
  351. debug("refreshError: activated");
  352. setTimeout(reload, 3000);
  353. }
  354. }
  355. function refreshErrorCard()
  356. {
  357. if(isErrorCard())
  358. {
  359. debug("refreshErrorCard: activated");
  360. setTimeout(reload, 3000);
  361. }
  362. }
  363. function refreshErrorMarket()
  364. {
  365. if(isErrorMarket())
  366. {
  367. debug("refreshErrorMarket: activated");
  368. setTimeout(reload, 3000);
  369. }
  370. }
  371. function refreshErrorTimeout(tm)
  372. {
  373. function refresh()
  374. {
  375. var url = document.documentURI;
  376. var pattCard = /^http[s]?:\/\/steamcommunity.com\/(id|profiles)\/[^\/]+\/gamecards\/[0-9]+/i;
  377. var pattTrade = /^http[s]?:\/\/steamcommunity.com\/(id|profiles)\/[^\/]+\/tradeoffers\//i;
  378. var pattMarket = /^http:\/\/steamcommunity.com\/market\/listings\/[0-9]+/i;
  379.  
  380. if (url.indexOf("#") < 0)
  381. {
  382. setTimeout(refreshError, tm);
  383. if (pattCard.test(url) || pattTrade.test(url))
  384. {
  385. setTimeout(refreshErrorCard, tm);
  386. }
  387.  
  388. if (pattMarket.test(url))
  389. {
  390. setTimeout(refreshErrorMarket, tm);
  391. }
  392. }
  393. }
  394. attachOnLoad(refresh);
  395. }
  396. if (enableRefreshError) refreshErrorTimeout(1000);
  397. /** Remove unnessary parameters in URL
  398. */
  399. function cleanLink()
  400. {
  401. var url = document.documentURI;
  402. var pattApp = /^http[s]?:\/\/store.steampowered.com\/(app|sub)\/[0-9]+/i;
  403. var pattBadge = /^http[s]?:\/\/steamcommunity.com\/(id|profiles)\/[^\/]+\/gamecards\/[0-9]+/i;
  404. var pattFork = /^http[s]?:\/\/store\.(.+steampowered|steamgames)\.com\//i;
  405. var pattParam = /\/\?.*$/
  406. var pattParamCC = /\/\?cc\=.*$/
  407. var urlNew = url;
  408. if (pattApp.test(url))
  409. {
  410. var urlNews = url.match(pattApp);
  411. if (urlNews != null)
  412. {
  413. var urlTail = url.replace(pattApp, "");
  414. if (urlTail == "")
  415. {
  416. urlNew = urlNews[0] + "/";
  417. }
  418. else if (urlTail != "/")
  419. {
  420. if (!pattParamCC.test(urlTail) && pattParam.test(urlTail))
  421. {
  422. urlNew = urlNews[0] + "/";
  423. }
  424. }
  425. }
  426. }
  427. else if (pattBadge.test(url))
  428. {
  429. var urlNews = url.match(pattBadge);
  430. if (urlNews != null)
  431. {
  432. var urlTail = url.replace(pattBadge, "");
  433.  
  434. if (urlTail.charAt(0) != "/")
  435. {
  436. urlNew = urlNews[0] + "/" + urlTail;
  437. }
  438. }
  439. }
  440. else if (pattFork.test(url))
  441. {
  442. urlNew = url.replace(pattFork, "http://store.steampowered.com/");
  443. }
  444. if (urlNew != url)
  445. {
  446. debug("cleanLink: activated");
  447. window.location = urlNew;
  448. }
  449. }
  450. if (enableCleanLink) cleanLink();
  451.  
  452. /** Change search parameter to page 1 to determine visited links
  453. */
  454. function cleanLinkSearch()
  455. {
  456. var pattSearch = /snr=1_7_7_230_150_[0-9]+/i
  457.  
  458. var as = document.querySelectorAll("a.search_result_row");
  459. for (var j = 0; j < as.length; j++)
  460. {
  461. var urlSearch = as[j].href;
  462. urlSearch = urlSearch.replace(pattSearch, "snr=1_7_7_230_150_1");
  463. as[j].href = urlSearch;
  464. }
  465.  
  466. document.addEventListener("DOMNodeInserted", onNodeInserted);
  467. function onNodeInserted(e)
  468. {
  469. try
  470. {
  471. var node = e.target;
  472. if (node.classList.contains("search_result_row"))
  473. {
  474. var urlSearch = node.href;
  475. urlSearch = urlSearch.replace(pattSearch, "snr=1_7_7_230_150_1");
  476. node.href = urlSearch;
  477. }
  478. var count = document.querySelectorAll(".search_result_row").length;
  479. var divs = document.querySelectorAll(".search_pagination_left");
  480. for (var i = 0; i < divs.length; i++)
  481. {
  482. var oldVals = divs[i].innerHTML.match(/[0-9]+/g);
  483. var oldVal = oldVals[oldVals.length > 0 ? oldVals.length-1 : 0];
  484. divs[i].innerHTML = "showing " + count + " of " + oldVal;
  485. }
  486. }
  487. catch (ex)
  488. {
  489. }
  490. }
  491. if (enableAutoscrollSearch)
  492. {
  493. var divButton = document.createElement("div");
  494. divButton.classList.add("btn_client_small");
  495. divButton.id = "divAutoscroll";
  496. divButton.style = "position: fixed; right: 20px; bottom: 20px; z-index:3;";
  497. divButton.innerHTML = "<a href='' onclick='document.addEventListener(\"DOMNodeInserted\", function(){ window.scrollTo(0,document.body.scrollHeight); }); this.parentElement.style.display=\"none\"; window.scrollTo(0,document.body.scrollHeight); return false;'>Autoscroll to end</a>";
  498. document.body.appendChild(divButton);
  499. }
  500. }
  501. function cleanLinkSearchTimeout(tm)
  502. {
  503. var url = document.documentURI;
  504. var patt = /^http[s]?:\/\/store.steampowered.com\/search\//i;
  505.  
  506. if (patt.test(url))
  507. {
  508. setTimeout(cleanLinkSearch, tm);
  509. }
  510. }
  511. if (enableCleanLink) cleanLinkSearchTimeout(100);
  512.  
  513. /** Remove link lifter in URL
  514. */
  515. function cleanLinkLifter()
  516. {
  517. var url = document.documentURI;
  518. var patt = /^http[s]?:\/\/steamcommunity.com\//i;
  519. var pattHome = /^http[s]?:\/\/steamcommunity.com\/(id|profiles)\/[^\/]+\/home/i;
  520. function cleanLifter()
  521. {
  522. var lifter = "https://steamcommunity.com/linkfilter/";
  523. var lifterLen = lifter.length;
  524. var lifter2 = "?url=";
  525. var lifterLen2 = lifter2.length;
  526. var js = "javascript:"
  527. var jsLen = js.length;
  528. var as = document.getElementsByTagName("a");
  529. for (var i = 0; i < as.length; i++)
  530. {
  531. var urlLink = as[i].href;
  532. if (urlLink.indexOf(lifter) == 0)
  533. {
  534. urlLink = urlLink.substr(lifterLen);
  535. if (urlLink.indexOf(lifter2) == 0)
  536. {
  537. urlLink = urlLink.substr(lifterLen2);
  538. }
  539. as[i].href = urlLink;
  540. }
  541. else if (patt.test(url) && urlLink.indexOf(js) == 0)
  542. {
  543. if (as[i].getAttribute('onclick') == null)
  544. {
  545. urlLink = decodeURIComponent(urlLink.substr(jsLen));
  546. as[i].setAttribute('onclick', urlLink + "; return false;");
  547. }
  548. }
  549. }
  550. }
  551. var cleanLifterTimeoutId = 0;
  552. function cleanLifterTimeout()
  553. {
  554. clearTimeout(cleanLifterTimeoutId);
  555. cleanLifterTimeoutId = setTimeout(cleanLifter, 1000);
  556. }
  557. attachOnReady(cleanLifter);
  558. if (pattHome.test(url))
  559. {
  560. document.addEventListener("DOMNodeInserted", cleanLifterTimeout);
  561. }
  562. }
  563. if (enableCleanLink) cleanLinkLifter();
  564.  
  565. /** Hide Steam's menu & EnhancedSteam's menu on top
  566. */
  567. function hideSteamMenuTimeout(tm)
  568. {
  569. GM_addStyle(".header_installsteam_btn_content , .header_installsteam_btn { display: none; }");
  570. GM_addStyle("#enhanced_pulldown { display: none; }");
  571. // fix market transaction display
  572. GM_addStyle("#market_transactions .transactionRowTitle { display: inline-block; padding-right: 5px; }");
  573. /*
  574. setTimeout(function()
  575. {
  576. var as = document.querySelectorAll(".header_installsteam_btn_content , .header_installsteam_btn");
  577. for (var i = 0; i < as.length; i++)
  578. {
  579. as[i].style.display = "none";
  580. }
  581. }, tm);
  582. attachOnLoad(function ()
  583. {
  584. setTimeout(function()
  585. {
  586. var aE = document.getElementById("enhanced_pulldown");
  587. if (aE != null)
  588. {
  589. aE.style.display = "none";
  590. }
  591. }, tm);
  592. });
  593. */
  594. }
  595. if (enableHideSteamMenu) hideSteamMenuTimeout(0);
  596.  
  597. /** Hide EnhancedSteam's price on Badge page
  598. */
  599. function hideEnhancedBadgePrice()
  600. {
  601. GM_addStyle(".es_card_search { display: none !important; } ");
  602. /*
  603. document.addEventListener("DOMNodeInserted", onNodeInserted);
  604. function onNodeInserted(e)
  605. {
  606. try
  607. {
  608. var node = e.target;
  609. if (node.classList.contains("es_card_search"))
  610. {
  611. debug("hideEnhanced: " + node.innerHTML);
  612. node.style.display = "none";
  613. }
  614. }
  615. catch (ex)
  616. {
  617. }
  618. }
  619. */
  620. }
  621. function hideEnhancedBadgePriceTimeout(tm)
  622. {
  623. var url = document.documentURI;
  624. var patt = /^http[s]?:\/\/steamcommunity.com\/(id|profiles)\/[^\/]+\/gamecards\/[0-9]+/i;
  625.  
  626. if (patt.test(url))
  627. {
  628. setTimeout(hideEnhancedBadgePrice, tm);
  629. }
  630. }
  631. if (enableHideEnhancedBadgePrice) hideEnhancedBadgePriceTimeout(0);
  632.  
  633. // ===== End Cleaner =====
  634.  
  635. // ===== Main =====
  636.  
  637. /** Disable autoplay on Greenlight page while autoplay option is on
  638. */
  639. function disableGreenlightAutoplay()
  640. {
  641. var iframes = document.getElementsByTagName("iframe");
  642. for (var i in iframes)
  643. {
  644. if (iframes[i].className == "highlight_flash_player_notice")
  645. {
  646. iframes[i].src = iframes[i].src.replace("autoplay=1", "autoplay=0");
  647. }
  648. }
  649. }
  650. function disableGreenlightAutoplayTimeout(tm)
  651. {
  652. var url = document.documentURI;
  653. var patt = /^http:\/\/steamcommunity.com\/sharedfiles\/filedetails\//i;
  654.  
  655. if (patt.test(url))
  656. {
  657. attachOnLoad(function ()
  658. {
  659. setTimeout(disableGreenlightAutoplay, tm);
  660. });
  661. }
  662. }
  663. if (enableGreenlightNoAutoplay) disableGreenlightAutoplayTimeout(0);
  664.  
  665. /** Move button in Edit Profile page to right
  666. */
  667. function moveMenuEditProfile()
  668. {
  669. GM_addStyle(
  670. ".group_content_bodytext { position: fixed; top: 400px; margin-left: 680px; line-height: 34px; z-index: 10; } "
  671. + ".rightcol { position: fixed; top: 230px; margin-left: 658px; z-index: 10; } "
  672. + ".saved_changes_msg { width: 610px; } "
  673. );
  674. }
  675. function moveMenuEditProfileTimeout(tm)
  676. {
  677. var url = document.documentURI;
  678. var patt = /^http[s]?:\/\/steamcommunity.com\/(id|profiles)\/[^\/]+\/edit/i;
  679.  
  680. if (patt.test(url))
  681. {
  682. setTimeout(moveMenuEditProfile, tm);
  683. }
  684. }
  685. if (enableMoveMenuEditProfile) moveMenuEditProfileTimeout(0);
  686.  
  687. /** Add small button on friend section in Badge page to view friends' Badge page for comparing cards
  688. * Reduce height of Review textbox
  689. */
  690. function linkBadgeToFriend()
  691. {
  692. var url = document.documentURI;
  693. var pattHead = /^http[s]?:\/\/steamcommunity.com\/(id|profiles)\/[^\/]*/i;
  694. var urlTail = url.replace(pattHead, "");
  695. var pattProfile = /^http[s]?:\/\/steamcommunity.com\/(id|profiles)/i;
  696.  
  697. var styleCorrect = "";
  698. // fix long card name show incorrect column of cards
  699. styleCorrect += ".badge_card_set_card .badge_card_set_text { width: 220px; } ";
  700. // fix Firefox show incorrect column of friends' avatar
  701. styleCorrect += ".persona { line-height: 16px; } ";
  702. // fix EnhancedSteam show incorrect size of next badge progress
  703. styleCorrect += ".gamecard_badge_progress .badge_info { width: 250px !important; } ";
  704. GM_addStyle(styleCorrect);
  705. var els = document.getElementsByTagName("div");
  706. for (var i in els)
  707. {
  708. if (els[i].className == "badge_friends_have_earned_friends"
  709. || els[i].className == "badge_friendwithgamecard")
  710. {
  711. var as = els[i].getElementsByTagName("a");
  712. var limit = 1;
  713. var curLimit = 0;
  714.  
  715. for (var j in as)
  716. {
  717. var a = as[j];
  718. if (pattProfile.test(a.href))
  719. {
  720. var badgeUrl = a.href + urlTail;
  721.  
  722. if (els[i].className == "badge_friends_have_earned_friends"
  723. || !a.parentNode.classList.contains("playerAvatar"))
  724. {
  725. a.href = badgeUrl;
  726. }
  727.  
  728. if (curLimit < limit && els[i].className == "badge_friendwithgamecard")
  729. {
  730. elActs = els[i].getElementsByClassName("badge_friendwithgamecard_actions");
  731. for (var k in elActs)
  732. {
  733. elActs[k].innerHTML = elActs[k].innerHTML
  734. + " <a class='btn_grey_grey btn_medium' title=\"View friend\'s badge\" href='"
  735. + badgeUrl
  736. + "'><img style='height:16px; opacity:0.66'"
  737. + " src='http://cdn4.store.steampowered.com/public/images/ico/ico_cards.png'></a> ";
  738. curLimit += 1;
  739. }
  740. }
  741. }
  742. } // end for
  743. }
  744. }
  745. }
  746. function linkBadgeToFriendTimeout(tm)
  747. {
  748. var url = document.documentURI;
  749. var patt = /^http[s]?:\/\/steamcommunity.com\/(id|profiles)\/[^\/]+\/gamecards\/[0-9]+/i;
  750.  
  751. if (patt.test(url) && !isErrorCard())
  752. {
  753. setTimeout(linkBadgeToFriend, tm);
  754. }
  755. }
  756. if (enableLinkBadgeToFriend) linkBadgeToFriendTimeout(100);
  757.  
  758. /** Add button on top of Store page to view Badge page
  759. */
  760. function linkStoreToBadge()
  761. {
  762. var url = document.documentURI;
  763. var patt = /^http[s]?:\/\/store.steampowered.com\/app\//i;
  764. var pattEnd = /[^0-9].*$/i;
  765. var app = url.replace(patt, "").replace(pattEnd, "");
  766.  
  767. var aOwner = document.querySelector("#global_actions > .user_avatar");
  768. var isLoggedIn = aOwner != null;
  769. var ownerUrl = isLoggedIn ? aOwner.href.substr(0, aOwner.href.length - 1) : "http://steamcommunity.com/my";
  770. var isOwned = document.querySelector(".game_area_already_owned") != null;
  771.  
  772. var urlCard = "http://store.steampowered.com/search/?category2=29";
  773. var titleCard = "Steam Trading Cards";
  774. var urlDlc = "http://store.steampowered.com/search/?category2=21";
  775. var titleDlc = "Downloadable Content";
  776. var urlAch = "http://store.steampowered.com/search/?category2=22";
  777. var titleAch = "Steam Achievement";
  778. var isBadge = false;
  779. var isBadgeMap = false;
  780. var isAch = false;
  781. var as = document.querySelectorAll(".game_area_details_specs a");
  782. for (var i = 0; i < as.length; i++)
  783. {
  784. if (appDlcs.indexOf(app) > -1 || as[i].href == urlDlc || as[i].textContent == titleDlc)
  785. {
  786. isBadge = false;
  787. isAch = false;
  788. break;
  789. }
  790. else if (as[i].href == urlCard || as[i].textContent == titleCard)
  791. {
  792. isBadge = true;
  793. }
  794. else if (as[i].href == urlAch || as[i].textContent == titleAch)
  795. {
  796. isAch = true;
  797. }
  798. }
  799. if (!isBadge)
  800. {
  801. if (appCards.indexOf(app) > -1)
  802. {
  803. isBadge = true;
  804. }
  805. else if (appCardMaps[app] != null)
  806. {
  807. isBadge = true;
  808. isBadgeMap = true;
  809. }
  810. }
  811. if (isBadge)
  812. {
  813. var appCard = app;
  814. if (isBadgeMap)
  815. {
  816. appCard = appCardMaps[app];
  817. }
  818. var divs = document.getElementsByClassName("apphub_OtherSiteInfo");
  819. for (var i = 0; i < divs.length; i++)
  820. {
  821. divs[i].innerHTML = divs[i].innerHTML
  822. + " &nbsp;<a class=\"btnv6_blue_hoverfade btn_medium\""
  823. + " href=\"" + ownerUrl + "/gamecards/" + appCard + "/\">"
  824. + "<span>Trading Cards</span></a>";
  825. }
  826. }
  827. if (false && isAch)
  828. {
  829. var urlAchLink = (isLoggedIn && isOwned ? ownerUrl + "/stats/appid/" : "http://steamcommunity.com/stats/")
  830. + app + "/achievements/";
  831. var divCommu = document.querySelector(".communitylink .block_content_inner");
  832. if (divCommu != null)
  833. {
  834. var aAch = ' <a class="linkbar" href="' + urlAchLink + '">'
  835. + '<div class="rightblock" style="margin-top: 3px;"><img src="http://cdn4.store.steampowered.com/public/images/ico/ico_achievements.png"'
  836. + ' align="top" border="0" style="margin-right: -9px; height: 20px; margin-top: -5px;"></div>'
  837. + 'View Steam Achievements</a>';
  838. divCommu.innerHTML = divCommu.innerHTML + aAch;
  839. }
  840. /*var divDemo = document.querySelector("#demo_block > div");
  841. if (divDemo != null)
  842. {
  843. var divAch = '<div class="demo_area_button"><a class="game_area_wishlist_btn" href="'
  844. + urlAchLink + '">View Steam Achievements</a></div>';
  845. divDemo.innerHTML = divAch + divDemo.innerHTML;
  846. }*/
  847. }
  848. var txtRec = document.getElementById("game_recommendation");
  849. if (txtRec != null)
  850. {
  851. // reduce height of review textbox
  852. txtRec.style.height = "16px";
  853. txtRec.onfocus = function(){txtRec.style.height="150px";};
  854. }
  855. }
  856. function linkStoreToBadgeTimeout(tm)
  857. {
  858. var url = document.documentURI;
  859. var patt = /^http[s]?:\/\/store.steampowered.com\/app\//i;
  860.  
  861. if (patt.test(url))
  862. {
  863. setTimeout(linkStoreToBadge, tm);
  864. }
  865. }
  866. if (enableLinkStoreToBadge) linkStoreToBadgeTimeout(100);
  867.  
  868. /** Add button in Forum page to view Badge page
  869. * Mark topic to determine visited links
  870. */
  871. function linkForumToBadge()
  872. {
  873. var url = document.documentURI;
  874. var pattAppHead = /^http[s]?:\/\/steamcommunity.com\/app\//i;
  875. var pattAppTail = /[^0-9]+.*/i;
  876. var app = url.replace(pattAppHead, "").replace(pattAppTail, "");
  877.  
  878. var aOwner = document.querySelector("div.user_avatar > div.playerAvatar > a");
  879. var isLoggedIn = aOwner != null;
  880. var ownerUrl = isLoggedIn ? aOwner.href : "http://steamcommunity.com/my";
  881.  
  882. var divs = document.getElementsByClassName("apphub_OtherSiteInfo");
  883. for (var j = 0; j < divs.length; j++)
  884. {
  885. var aBadge = " <a class='btn_darkblue_white_innerfade btn_medium' href='"
  886. + ownerUrl + "/gamecards/" + app
  887. + "/'><span>Trading Cards</span></a> ";
  888. divs[j].innerHTML = divs[j].innerHTML + aBadge;
  889. }
  890. function markTopic()
  891. {
  892. var as = document.getElementsByClassName("forum_topic_overlay");
  893. for (var i = 0; i < as.length; i++)
  894. {
  895. // mark topic
  896. as[i].style.borderLeft = "3px solid";
  897. }
  898. }
  899. markTopic();
  900. document.addEventListener("DOMNodeInserted", markTopic);
  901. }
  902. function linkForumToBadgeTimeout(tm)
  903. {
  904. var url = document.documentURI;
  905. var patt = /^http:\/\/steamcommunity.com\/app\/[0-9]+\/tradingforum\//i;
  906.  
  907. if (patt.test(url))
  908. {
  909. setTimeout(linkForumToBadge, tm);
  910. }
  911. }
  912. if (enableLinkForumToBadge) linkForumToBadgeTimeout(100);
  913.  
  914. /** Add buttons in Badge page to view Trading Forum, Store, friend's Inventory and my Badge page
  915. */
  916. function linkBadgeToForum()
  917. {
  918. var url = document.documentURI;
  919.  
  920. var pattAppHead = /^http[s]?:\/\/steamcommunity.com\/(id|profiles)\/[^\/]+\/gamecards\//i;
  921. var pattAppTail = /[^0-9]+.*/i;
  922. var app = url.replace(pattAppHead, "").replace(pattAppTail, "");
  923. GM_addStyle(".sbh_badge_menu_right { float: right; margin-left: 5px; } ");
  924.  
  925. var divs = document.getElementsByClassName("gamecards_inventorylink");
  926. if (divs.length > 0)
  927. {
  928. var aStoreUrl = "http://store.steampowered.com/app/" + app + "/";
  929. var aForumUrl = "http://steamcommunity.com/app/" + app + "/tradingforum/";
  930. var aCustom = " <a class='btn_grey_grey btn_small_thin sbh_badge_menu_right' href='" + aStoreUrl + "'>"
  931. + " <span>Visit Store Page</span></a> "
  932. + " <a class='btn_grey_grey btn_small_thin sbh_badge_menu_right' href='" + aForumUrl + "'>"
  933. + " <span>Visit Trade Forum</span></a> ";
  934.  
  935. divs[0].innerHTML = divs[0].innerHTML + aCustom;
  936. }
  937.  
  938. var aOwner = document.querySelector("div.user_avatar > div.playerAvatar > a");
  939. var isLoggedIn = aOwner != null;
  940. var ownerUrl = isLoggedIn ? aOwner.href : "http://steamcommunity.com/my";
  941.  
  942. var aFriend = document.querySelector(".profile_small_header_name > a");
  943. var isFriendExist = aFriend != null;
  944. var friendUrl = isFriendExist ? aFriend.href : "http://steamcommunity.com/my";
  945. var friendName = isFriendExist ? aFriend.textContent.trim() : "my"
  946. var friendNameOwner = isFriendExist ? friendName + "'s" : friendName;
  947.  
  948. var isOwner = isLoggedIn && ownerUrl == friendUrl;
  949.  
  950. if (!isOwner)
  951. {
  952. var divInv;
  953. if (divs.length > 0)
  954. {
  955. divInv = divs[0];
  956. }
  957. else
  958. {
  959. divInv = document.createElement("div");
  960. divInv.classList.add("gamecards_inventorylink");
  961. var divBadge = document.querySelector(".badge_detail_tasks");
  962. if (divBadge != null)
  963. {
  964. divBadge.insertBefore(divInv, divBadge.firstChild);
  965. }
  966. }
  967. var aFrInvUrl = friendUrl + "/inventory/#753_6";
  968. var aOwnUrl = url.replace(pattAppHead, ownerUrl + "/gamecards/");
  969. divInv.innerHTML = divInv.innerHTML
  970. + "<a class='btn_grey_grey btn_small_thin' href='" + aFrInvUrl + "'><span>View cards in "
  971. + friendNameOwner + " Inventory</span></a> "
  972. + " <a class='btn_grey_grey btn_small_thin' href='" + aOwnUrl + "'><span>View my Progress</span></a> ";
  973.  
  974. }
  975. }
  976. function linkBadgeToForumTimeout(tm)
  977. {
  978. var url = document.documentURI;
  979. var patt = /^http[s]?:\/\/steamcommunity.com\/(id|profiles)\/[^\/]+\/gamecards\/[0-9]+/i;
  980.  
  981. if (patt.test(url) && !isErrorCard())
  982. {
  983. setTimeout(linkBadgeToForum, tm);
  984. }
  985. }
  986. if (enableLinkBadgeToForum) linkBadgeToForumTimeout(1);
  987.  
  988. /** Add button in Market page to view Badge and Store page
  989. */
  990. function linkMarketToBadge()
  991. {
  992. var url = document.documentURI;
  993.  
  994. var pattAppHead = /^http[s]?:\/\/steamcommunity.com\/market\/listings\/753\//i;
  995. var pattAppTail = /[^0-9]+.*/i;
  996. var pattNumber = /[0-9]+/;
  997. var app = url.replace(pattAppHead, "").replace(pattAppTail, "");
  998.  
  999. var aOwner = document.querySelector("div.user_avatar > div.playerAvatar > a");
  1000. var isLoggedIn = aOwner != null;
  1001. var ownerUrl = isLoggedIn ? aOwner.href : "http://steamcommunity.com/my";
  1002.  
  1003. GM_addStyle(
  1004. "#market_buynow_dialog_purchase > span:nth-child(1) { line-height: 80px; padding: 0px 50px 0px 50px !important; } "
  1005. + "#market_buynow_dialog { width: 850px; } "
  1006. + ".market_listing_table_header { margin: 0px; } "
  1007. + ".market_listing_row { margin-top: 2px; } "
  1008. );
  1009. var div_tabL = document.querySelectorAll("div.market_large_tab_well");
  1010. for (var i = 0; i < div_tabL.length; i++)
  1011. {
  1012. // reduce height of header
  1013. div_tabL[i].style.height = "50px";
  1014. }
  1015. var div_tabLB = document.querySelectorAll("div.market_large_tab_well_gradient");
  1016. for (var i = 0; i < div_tabLB.length; i++)
  1017. {
  1018. div_tabLB[i].style.height = "65px";
  1019. }
  1020.  
  1021. var div_store = document.getElementById("largeiteminfo_game_name");
  1022. if (div_store != null)
  1023. {
  1024. div_store.innerHTML = "<a href='http://store.steampowered.com/app/" + app + "/'>"
  1025. + div_store.innerHTML + "</a>";
  1026. }
  1027.  
  1028. var isFoil = false;
  1029. var ele_name = document.getElementById("largeiteminfo_item_name");
  1030. if (ele_name != null)
  1031. {
  1032. isFoil = (ele_name.innerHTML.search("Foil") > -1);
  1033. ele_name.innerHTML = "<a href='" + ownerUrl + "/gamecards/" + app
  1034. + (isFoil ? "/?border=1" : "/") + "'>" + ele_name.innerHTML + "</a>";
  1035. }
  1036.  
  1037. var ele_icon = document.getElementsByClassName("item_desc_game_icon");
  1038. for (var i = 0; i < ele_icon.length; i++)
  1039. {
  1040. ele_icon[i].innerHTML = "<a href='http://store.steampowered.com/app/" + app + "/'>"
  1041. + ele_icon[i].innerHTML + "</a>";
  1042. }
  1043.  
  1044. var div_nav = document.getElementsByClassName("market_large_tab_well");
  1045. for (var j = 0; j < div_nav.length; j++)
  1046. {
  1047. var aBadge = ' <div class="apphub_OtherSiteInfo" '
  1048. + 'style="position: relative; float: right; right: 2px; top: 2px;"> '
  1049. + '<a style="position: relative; z-index: 1;" class="btn_darkblue_white_innerfade btn_medium" '
  1050. + 'href="#" onclick="document.getElementById(\'pricehistory\').style.display = \'inherit\'; '
  1051. + 'document.querySelector(\'.pricehistory_zoom_controls\').style.display = \'inherit\'; return false; " >'
  1052. + '<span>Show History</span></a> &nbsp;'
  1053. + '<a style="position: relative; z-index: 1;" class="btn_darkblue_white_innerfade btn_medium" '
  1054. + 'href="http://store.steampowered.com/app/' + app + '"><span>Store Page</span></a> &nbsp;'
  1055. + '<a class="btn_darkblue_white_innerfade btn_medium" '
  1056. + 'href="' + ownerUrl + '/gamecards/' + app + (isFoil ? "/?border=1" : "/")
  1057. + '"><span>Trading Cards</span></a></div>';
  1058. div_nav[j].innerHTML = div_nav[j].innerHTML + aBadge;
  1059. GM_addStyle(
  1060. "#pricehistory, .pricehistory_zoom_controls { display: none } "
  1061. );
  1062. }
  1063. var span_list = document.querySelectorAll("div.market_listing_row > div:nth-child(3) > span:nth-child(1) > span:nth-child(1)");
  1064. for (var i = 0; i < span_list.length; i++)
  1065. {
  1066. if (!pattNumber.test(span_list[i].textContent))
  1067. {
  1068. span_list[i].parentElement.parentElement.parentElement.style.display = "none";
  1069. }
  1070. }
  1071. }
  1072. function linkMarketToBadgeTimeout(tm)
  1073. {
  1074. var url = document.documentURI;
  1075. var patt = /^http:\/\/steamcommunity.com\/market\/listings\/753\/[0-9]+/i;
  1076.  
  1077. if (patt.test(url) && !isErrorMarket())
  1078. {
  1079. setTimeout(linkMarketToBadge, tm);
  1080. }
  1081. }
  1082. if (enableLinkMarketToBadge) linkMarketToBadgeTimeout(100);
  1083.  
  1084. /** Add price of each cards in Badge page and link to Market page
  1085. */
  1086. function linkBadgeToMarket()
  1087. {
  1088. GM_addStyle(".div_market_price { padding-top: 1px; }");
  1089. var url = document.documentURI;
  1090.  
  1091. var pattAppHead = /^http[s]?:\/\/steamcommunity.com\/(id|profiles)\/[^\/]+\/gamecards\//i;
  1092. var pattAppTail = /[^0-9]+.*/i;
  1093. var app = url.replace(pattAppHead, "").replace(pattAppTail, "");
  1094. var isFoil = url.indexOf("border=1") > -1;
  1095. var urlExternal = "http://www.steamcardexchange.net/index.php?gamepage-appid-" + app;
  1096. var urlMarket = "http://steamcommunity.com/market/listings/753/";
  1097. var priceCards = new Array();
  1098. var priceUrls = new Array();
  1099. updatePrice();
  1100.  
  1101. var isCacheExpire = checkCacheExpire(app);
  1102. if (isCacheExpire || !enableCache)
  1103. {
  1104. setTimeout(function ()
  1105. {
  1106. GM_xmlhttpRequest({
  1107. method: "GET",
  1108. url: urlExternal,
  1109. onload: getExternalPrice,
  1110. });
  1111. }, 0);
  1112. }
  1113.  
  1114. function getExternalPrice(res)
  1115. {
  1116. try
  1117. {
  1118. var pattNumCard = /Card [0-9]+ of /i;
  1119. var pattMarket = /^http:\/\/steamcommunity.com\/market\/listings\/753\//i;
  1120. var pattPrice = /(Price: |Last seen: )/i;
  1121.  
  1122. var aOwner = document.querySelector("div.user_avatar > div.playerAvatar > a");
  1123. var isLoggedIn = aOwner != null;
  1124. var ownerUrl = isLoggedIn ? aOwner.href : "http://steamcommunity.com/my";
  1125.  
  1126. var aFriend = document.querySelector(".profile_small_header_name > a");
  1127. var isFriendExist = aFriend != null;
  1128. var friendUrl = isFriendExist ? aFriend.href : "http://steamcommunity.com/my";
  1129. var friendName = isFriendExist ? aFriend.textContent.trim() : "my"
  1130. var friendNameOwner = isFriendExist ? friendName + "'s" : friendName;
  1131.  
  1132. var isOwner = isLoggedIn && ownerUrl == friendUrl;
  1133.  
  1134. var divTempID = randTempID();
  1135. createDivTemp(divTempID, res.responseText);
  1136. try
  1137. {
  1138. //debug("ID: "+divTempID);
  1139. var divTemp = document.getElementById(divTempID);
  1140. var numCard = 0;
  1141. try
  1142. {
  1143. var spanNumber = divTemp.getElementsByClassName("card-number")[0];
  1144. if (spanNumber == null)
  1145. {
  1146. debug("Warning: can't get price");
  1147. return;
  1148. }
  1149. numCard = parseInt(spanNumber.textContent.replace(pattNumCard, ""));
  1150. }
  1151. catch (e)
  1152. {
  1153. debug("Ex: " + e);
  1154. }
  1155. var offsetCard = isFoil ? numCard : 0;
  1156. var curCard = 0;
  1157.  
  1158. var isCacheExpire = checkCacheExpire(app);
  1159.  
  1160. priceCards = new Array();
  1161. priceUrls = new Array();
  1162.  
  1163. var as = divTemp.getElementsByClassName("button-blue");
  1164. for (var i = 0; i < as.length; i++)
  1165. {
  1166. if (pattMarket.test(as[i].href))
  1167. {
  1168. if (curCard < numCard * 2)
  1169. {
  1170. var cPrice = as[i].textContent.replace(pattPrice, "").trim();
  1171. var cUrl = as[i].href.replace(urlMarket, "");
  1172.  
  1173. var indexCard = curCard - offsetCard;
  1174. if (indexCard >= 0 && indexCard < numCard)
  1175. {
  1176. priceCards[indexCard] = cPrice;
  1177. priceUrls[indexCard] = cUrl;
  1178. }
  1179.  
  1180. // cache
  1181. if (enableCache && isCacheExpire)
  1182. {
  1183. setCacheTime(app);
  1184. if (curCard < numCard)
  1185. {
  1186. setCachePrice(app, false, curCard, cPrice);
  1187. setCacheUrl(app, false, curCard, cUrl);
  1188. }
  1189. else // foil
  1190. {
  1191. setCachePrice(app, true, curCard - numCard, cPrice);
  1192. setCacheUrl(app, true, curCard - numCard, cUrl);
  1193. }
  1194. }
  1195.  
  1196. curCard += 1;
  1197. }
  1198. else
  1199. {
  1200. break;
  1201. }
  1202. }
  1203. }
  1204. }
  1205. catch (e)
  1206. {
  1207. debug("Ex: " + e);
  1208. }
  1209. removeDivTemp(divTempID);
  1210.  
  1211. updatePrice();
  1212.  
  1213. debugTime("getExternalPrice");
  1214. }
  1215. catch (e)
  1216. {
  1217. debug("Ex: " + e);
  1218. }
  1219. }
  1220.  
  1221. function updatePrice()
  1222. {
  1223. var pattNum = /[0-9\.]+/;
  1224. var colorUp = "#CC0000";
  1225. var colorDown = "#009900";
  1226.  
  1227. if (enableCache)
  1228. {
  1229. priceCards = new Array();
  1230. priceUrls = new Array();
  1231. for (var i = 0; i < 15; i++)
  1232. {
  1233. var p = getCachePrice(app, isFoil, i);
  1234. var u = getCacheUrl(app, isFoil, i);
  1235. if (p != 0 && u != 0)
  1236. {
  1237. priceCards[i] = p;
  1238. priceUrls[i] = u;
  1239. }
  1240. else
  1241. {
  1242. break;
  1243. }
  1244. }
  1245. }
  1246.  
  1247. var texts = document.getElementsByClassName("badge_card_set_card");
  1248. var numCard = texts.length;
  1249. var priceSet = 0;
  1250. for (var j = 0; j < texts.length; j++)
  1251. {
  1252. var pUrl = priceUrls[j] ? urlMarket + priceUrls[j] : "";
  1253. var pCard = priceCards[j] ? priceCards[j] : "-";
  1254. var pOnClick = priceCards[j] ? "" : " onclick='return false;' ";
  1255. var pDiff = "";
  1256. var pCardOld = "";
  1257. var divTexts = texts[j].querySelectorAll("div.badge_card_set_text");
  1258. var divText = divTexts[divTexts.length - 1];
  1259. var divMarkets = texts[j].getElementsByClassName("div_market_price");
  1260. var divMarket;
  1261. if (divMarkets.length == 0)
  1262. {
  1263. divMarket = document.createElement("div");
  1264. divMarket.classList.add("div_market_price");
  1265. divMarket.style.cssFloat = "right";
  1266. divText.appendChild(divMarket);
  1267. }
  1268. else
  1269. {
  1270. divMarket = divMarkets[0];
  1271. var as = divMarket.getElementsByTagName("a");
  1272. if (as.length > 0)
  1273. {
  1274. var pOld = as[0].textContent;
  1275. var pValOld = pOld.match(pattNum);
  1276. if (pValOld != null)
  1277. {
  1278. //debug("oldPrice[" + j + "]: "+ pValOld);
  1279. pCardOld = "title='Cache Price: " + pOld + "'";
  1280. var pVal = pCard.match(pattNum);
  1281. pVal = pVal ? pVal : 0;
  1282. priceSet += parseFloat(pVal);
  1283. var pValDiff = (parseFloat(pVal) - parseFloat(pValOld)).toFixed(2);
  1284. if(pValDiff > 0)
  1285. {
  1286. pDiff = "<span style='cursor: help; color: " + colorUp + ";' "
  1287. + pCardOld + ">+" + pValDiff + "</span>";
  1288. }
  1289. else if (pValDiff < 0)
  1290. {
  1291. pDiff = "<span style='cursor: help; color: " + colorDown + ";' "
  1292. + pCardOld + ">" + pValDiff + "</span>";
  1293. }
  1294. else
  1295. {
  1296. pCardOld = "";
  1297. }
  1298. }
  1299. }
  1300. }
  1301.  
  1302. divMarket.innerHTML = pDiff + " <a href='" + pUrl + "' " + pOnClick + " title='Lowest Price'>" + pCard + "</a>";
  1303. } // end for
  1304. if (priceSet > 0)
  1305. {
  1306. debug("priceSet: " + priceSet);
  1307. }
  1308. }
  1309. }
  1310. function linkBadgeToMarketTimeout(tm)
  1311. {
  1312. var url = document.documentURI;
  1313. var patt = /^http[s]?:\/\/steamcommunity.com\/(id|profiles)\/[^\/]+\/gamecards\/[0-9]+/i;
  1314.  
  1315. if (patt.test(url) && !isErrorCard())
  1316. {
  1317. setTimeout(linkBadgeToMarket, tm);
  1318. }
  1319. }
  1320. if (enableLinkBadgeToMarket) linkBadgeToMarketTimeout(0);
  1321.  
  1322. /** Compare my cards and friend's cards in Badge page
  1323. * Mark color of my cards count (Green) and friend's cards count (Blue)
  1324. */
  1325. function compareBadge()
  1326. {
  1327. var url = document.documentURI;
  1328.  
  1329. var pattAppHead = /^http[s]?:\/\/steamcommunity.com\/(id|profiles)\/[^\/]+\/gamecards\//i;
  1330. var pattAppTail = /[^0-9]+.*/i;
  1331. var app = url.replace(pattAppHead, "").replace(pattAppTail, "");
  1332.  
  1333. {
  1334. try
  1335. {
  1336. var pattNumCard = /Card [0-9]+ of /i;
  1337. var pattMarket = /^http:\/\/steamcommunity.com\/market\/listings\/753\//i;
  1338. var pattPrice = /Price: /i;
  1339.  
  1340. var isFoil = url.indexOf("border=1") > -1;
  1341.  
  1342. var aOwner = document.querySelector("div.user_avatar > div.playerAvatar > a");
  1343. var isLoggedIn = aOwner != null;
  1344. var ownerUrl = isLoggedIn ? aOwner.href : "http://steamcommunity.com/my";
  1345.  
  1346. var aFriend = document.querySelector(".profile_small_header_name > a");
  1347. var isFriendExist = aFriend != null;
  1348. var friendUrl = isFriendExist ? aFriend.href : "http://steamcommunity.com/my";
  1349. var friendName = isFriendExist ? aFriend.textContent.trim() : "my"
  1350. var friendNameOwner = isFriendExist ? friendName + "'s" : friendName;
  1351.  
  1352. var isOwner = isLoggedIn && ownerUrl == friendUrl;
  1353.  
  1354. //debug("ownerUrl: "+ownerUrl);
  1355. //debug("friendUrl: "+friendUrl);
  1356.  
  1357. var texts = document.getElementsByClassName("badge_card_set_card");
  1358. var numCard = texts.length;
  1359.  
  1360. //debug("isOwner: "+isOwner);
  1361. //debug("numCard: "+numCard);
  1362.  
  1363. for (var j = 0; j < numCard; j++)
  1364. {
  1365. var divQty = texts[j].querySelector("div.badge_card_set_text_qty");
  1366. var numQty = "(0)";
  1367. if (divQty != null)
  1368. {
  1369. numQty = divQty.textContent.trim();
  1370. }
  1371. else
  1372. {
  1373. divQty = document.createElement("div");
  1374. divQty.classList.add("badge_card_set_text_qty");
  1375. divQty.innerHTML = numQty;
  1376.  
  1377. var divCtn = texts[j].querySelector("div.game_card_ctn");
  1378. if (divCtn != null)
  1379. {
  1380. var divTexts = texts[j].querySelectorAll("div.badge_card_set_text");
  1381. if (divTexts.length < 2)
  1382. {
  1383. texts[j].insertBefore(divQty, divCtn.nextSibling);
  1384. }
  1385. else
  1386. {
  1387. divTexts[0].insertBefore(divQty, divTexts[0].firstChild);
  1388. }
  1389. }
  1390. }
  1391. //debug("numQty: "+numQty);
  1392. } // end for
  1393.  
  1394. var colorOwner = "#8CBE0F";
  1395. var colorFriend = "#5491CF";
  1396. var colorZeroOwner = "#557309";
  1397. var colorZeroFriend = "#355C82";
  1398. var countCardAll = 0;
  1399.  
  1400. var divQtys = document.querySelectorAll("div.badge_card_set_text_qty");
  1401. for (var k = 0; k < divQtys.length; k++)
  1402. {
  1403. var num = divQtys[k].textContent.trim().replace(/[\(\)]/gi, "");
  1404. countCardAll += parseInt(num);
  1405. divQtys[k].innerHTML = "";
  1406.  
  1407. var spanNum = document.createElement("span");
  1408. spanNum.classList.add("span_card_qty");
  1409. spanNum.style.cursor = "help";
  1410. spanNum.innerHTML = " (" + num + ") ";
  1411. divQtys[k].insertBefore(spanNum, null);
  1412.  
  1413. if (isOwner)
  1414. {
  1415. spanNum.classList.add("span_card_qty_owner");
  1416. spanNum.style.color = num > "0" ? colorOwner : colorZeroOwner;
  1417. spanNum.title = "My cards: " + num;
  1418. }
  1419. else
  1420. {
  1421. spanNum.classList.add("span_card_qty_friend");
  1422. spanNum.style.color = num > "0" ? colorFriend : colorZeroFriend;
  1423. spanNum.title = friendNameOwner + " cards: " + num;
  1424. }
  1425. }
  1426. debug("countCard: " + countCardAll);
  1427. debug("maxSet: " + parseInt(countCardAll / numCard));
  1428.  
  1429. if (!isOwner)
  1430. {
  1431. var pattProfile = /^http[s]?:\/\/steamcommunity.com\/(id|profiles)\/[^\/]*/i;
  1432. var urlExternal = url.replace(pattProfile, ownerUrl);
  1433. //debug("urlExternal: "+urlExternal);
  1434.  
  1435. setTimeout(function ()
  1436. {
  1437. GM_xmlhttpRequest({
  1438. method: "GET",
  1439. url: urlExternal,
  1440. onload: compareCard,
  1441. });
  1442. }, 0);
  1443.  
  1444. function compareCard(res)
  1445. {
  1446. var divTempID = randTempID();
  1447. createDivTemp(divTempID, res.responseText);
  1448. try
  1449. {
  1450. //debug("ID: "+divTempID);
  1451. var divTemp = document.getElementById(divTempID);
  1452.  
  1453. var owner_texts = divTemp.getElementsByClassName("badge_card_set_card");
  1454. var owner_numCard = owner_texts.length;
  1455.  
  1456. if (numCard == owner_numCard)
  1457. {
  1458. var owner_numQtys = new Array();
  1459.  
  1460. for (var i = 0; i < owner_texts.length; i++)
  1461. {
  1462. var owner_divQty = owner_texts[i].querySelector("div.badge_card_set_text_qty");
  1463. if (owner_divQty != null)
  1464. {
  1465. owner_numQtys[i] = owner_divQty.textContent.trim().replace(/[\(\)]/gi, "");
  1466. }
  1467. else
  1468. {
  1469. owner_numQtys[i] = "0";
  1470. }
  1471. //debug("owner_numQtys[i]: "+owner_numQtys[i]);
  1472. } // end for
  1473.  
  1474. var friend_divQtys = document.querySelectorAll("div.badge_card_set_text_qty");
  1475. for (var k = 0; k < friend_divQtys.length; k++)
  1476. {
  1477. var owner_spanNum = friend_divQtys[k].querySelector("span_card_qty_owner");
  1478. if (owner_spanNum == null)
  1479. {
  1480. owner_spanNum = document.createElement("span");
  1481. owner_spanNum.classList.add("span_card_qty");
  1482. owner_spanNum.style.cursor = "help";
  1483. owner_spanNum.classList.add("span_card_qty_owner");
  1484. owner_spanNum.style.color = owner_numQtys[k] > "0" ? colorOwner : colorZeroOwner;
  1485. owner_spanNum.title = "My cards: " + owner_numQtys[k];
  1486. friend_divQtys[k].insertBefore(owner_spanNum, friend_divQtys[k].firstChild);
  1487. }
  1488. owner_spanNum.innerHTML = " (" + owner_numQtys[k] + ") ";
  1489. }
  1490. }
  1491. }
  1492. catch (e)
  1493. {
  1494. debug("Ex: " + e);
  1495. }
  1496. removeDivTemp(divTempID);
  1497. debugTime("compareBadge");
  1498. }
  1499. }
  1500. }
  1501. catch (e)
  1502. {
  1503. debug("Ex: " + e);
  1504. }
  1505. }
  1506. }
  1507. function compareBadgeTimeout(tm)
  1508. {
  1509. var url = document.documentURI;
  1510. var patt = /^http[s]?:\/\/steamcommunity.com\/(id|profiles)\/[^\/]+\/gamecards\/[0-9]+/i;
  1511.  
  1512. if (patt.test(url) && !isErrorCard())
  1513. {
  1514. setTimeout(compareBadge, tm);
  1515. }
  1516. }
  1517. if (enableCompareBadge) compareBadgeTimeout(0);
  1518.  
  1519. function editTitle()
  1520. {
  1521. try
  1522. {
  1523. var titleOld = document.title;
  1524. var titleNew = titleOld;
  1525. var titleNoti = "";
  1526. var pattSale = /[0-9]+%/i;
  1527. if (enableSwapTitle)
  1528. {
  1529. var splitSpace = titleOld.split(" ");
  1530. if (splitSpace.length > 1)
  1531. {
  1532. if (pattSale.test(splitSpace[1]))
  1533. {
  1534. splitSpace.splice(0, 1);
  1535. splitSpace.splice(1, 1);
  1536. titleOld = splitSpace.join(" ");
  1537. }
  1538. }
  1539. var split = titleOld.split("::").reverse();
  1540. for (var i = 0; i < split.length; i++)
  1541. {
  1542. split[i] = split[i].trim();
  1543. }
  1544. titleNew = split.join(" :: ");
  1545. document.title = titleNew;
  1546. var divH = document.querySelector("#header_notification_area");
  1547. if (divH != null)
  1548. {
  1549. divH.addEventListener('mouseover', function() {
  1550. document.title = titleNew;
  1551. });
  1552. }
  1553. }
  1554. if (enableShowTitleNoti)
  1555. {
  1556. var noti = document.querySelector("#header_notification_link");
  1557. if (noti != null)
  1558. {
  1559. function updateTitleNoti()
  1560. {
  1561. var notiNum = noti.textContent.trim();
  1562. if (notiNum != "")
  1563. {
  1564. debug("updateTitleNoti: "+notiNum);
  1565. titleNoti = "("+notiNum+") ";
  1566. }
  1567. else
  1568. {
  1569. titleNoti = "";
  1570. }
  1571. if (document.title != titleNoti + titleNew)
  1572. {
  1573. debug("changeTitle: "+notiNum);
  1574. document.title = titleNoti + titleNew;
  1575. }
  1576. }
  1577. updateTitleNoti();
  1578. /*
  1579. var timeoutID = -1;
  1580. noti.addEventListener("DOMSubtreeModified", function (e) {
  1581. debug("DOMSubtreeModified");
  1582. try
  1583. {
  1584. clearTimeout(timeoutID);
  1585. }
  1586. catch (ex)
  1587. {
  1588. }
  1589. updateTitleNoti();
  1590. });
  1591. noti.addEventListener("DOMNodeInserted", function (e) {
  1592. debug("DOMNodeInserted");
  1593. try
  1594. {
  1595. clearTimeout(timeoutID);
  1596. }
  1597. catch (ex)
  1598. {
  1599. }
  1600. updateTitleNoti();
  1601. });
  1602. noti.addEventListener("DOMNodeRemoved", function (e) {
  1603. debug("DOMNodeRemoved");
  1604. timeoutID = setTimeout(updateTitleNoti,100);
  1605. });
  1606. */
  1607. }
  1608. }
  1609. }
  1610. catch (ex)
  1611. {
  1612. debug("editTitle: "+ex);
  1613. }
  1614. }
  1615. function editTitleAttach()
  1616. {
  1617. attachOnReady(editTitle);
  1618. }
  1619. if (enableSwapTitle || enableShowTitleNoti) editTitleAttach();
  1620.  
  1621. /** Resize trade window that is larger than 768px
  1622. */
  1623. function resizeTradeWindow()
  1624. {
  1625. if (window.innerHeight < 800)
  1626. {
  1627. GM_addStyle("#mainContent { transform: scale(0.8, 0.8); transform-origin: 50% 0px 0px; }");
  1628. if (window.innerWidth > 1000)
  1629. {
  1630. //window.resizeBy(-240,0);
  1631. //window.moveBy(200,0);
  1632. }
  1633. }
  1634. }
  1635. function resizeTradeWindowTimeout(tm)
  1636. {
  1637. var url = document.documentURI;
  1638. var patt = /^http[s]?:\/\/steamcommunity.com\/(tradeoffer|trade)\//i;
  1639.  
  1640. if (patt.test(url))
  1641. {
  1642. setTimeout(resizeTradeWindow, tm);
  1643. }
  1644. }
  1645. if (enableResizeTradeWindow) resizeTradeWindowTimeout(0);
  1646. /** Add link in profile page
  1647. */
  1648. function linkProfile()
  1649. {
  1650. GM_addStyle(".achievement_progress_bar_ctn { width: 118px; margin-left: 4px; } ");
  1651. var url = document.documentURI;
  1652. var urlOwner = url;
  1653. if (urlOwner[urlOwner.length-1] != "/")
  1654. {
  1655. urlOwner = urlOwner + "/";
  1656. }
  1657. var urlName = urlOwner + "namehistory/";
  1658. var urlPost = urlOwner + "posthistory/";
  1659. var labelName = "Name History";
  1660. var labelPost = "Post History";
  1661. var arrUrl = ["", urlName, urlPost];
  1662. var arrLbl = ["", labelName, labelPost];
  1663. var divOuter = document.querySelector(".profile_item_links");
  1664. if (divOuter != null)
  1665. {
  1666. for (var i = 0; i < arrUrl.length; i++)
  1667. {
  1668. var div = document.createElement("div");
  1669. if (div != null)
  1670. {
  1671. div.className = "profile_count_link";
  1672. div.innerHTML = '<a href="' + arrUrl[i] + '"><span class="count_link_label">'
  1673. + arrLbl[i] + '</span> <span class="profile_count_link_total"> </span></a>';
  1674. divOuter.appendChild(div);
  1675. }
  1676. }
  1677. }
  1678. }
  1679. function linkProfileReady()
  1680. {
  1681. var url = document.documentURI;
  1682. var patt = /^http[s]?:\/\/steamcommunity.com\/(id|profiles)\/[^\/]+\/?$/i;
  1683.  
  1684. if (patt.test(url))
  1685. {
  1686. attachOnReady(linkProfile);
  1687. }
  1688. }
  1689. if (enableLinkProfile) linkProfileReady();
  1690. /** Set all checkbox to checked
  1691. */
  1692. function setAllCheckBox()
  1693. {
  1694. var ids = ["market_buynow_dialog_accept_ssa", "market_sell_dialog_accept_ssa", "accept_ssa", "verify_country_only"];
  1695. for (var i = 0; i < ids.length; i++)
  1696. {
  1697. var input = document.getElementById(ids[i]);
  1698. if (input != null)
  1699. {
  1700. input.checked = true;
  1701. }
  1702. }
  1703. }
  1704. function setAllCheckBoxReady()
  1705. {
  1706. var url = document.documentURI;
  1707. var pattMarket = /^http:\/\/steamcommunity.com\/market\/listings\/[0-9]+/i;
  1708. var pattInv = /^http[s]?:\/\/steamcommunity.com\/(id|profiles)\/[^\/]+\/inventory/i;
  1709. var pattCart = /^http[s]?:\/\/store.steampowered.com\/checkout/i;
  1710. if (pattMarket.test(url) || pattInv.test(url) || pattCart.test(url))
  1711. {
  1712. attachOnReady(setAllCheckBox);
  1713. }
  1714. }
  1715. if (enableSetAllCheckBox) setAllCheckBoxReady();
  1716. /** Scroll store page to easy view
  1717. */
  1718. function storeFocus()
  1719. {
  1720. var divHead = document.querySelector(".breadcrumbs > .blockbg, .breadcrumbs > a");
  1721. if (divHead != null)
  1722. {
  1723. divHead.scrollIntoView();
  1724. }
  1725. }
  1726. function storeFocusReady()
  1727. {
  1728. var url = document.documentURI;
  1729. var patt = /^http[s]?:\/\/store.steampowered.com\/(app|sub)\//i;
  1730. if (patt.test(url))
  1731. {
  1732. attachOnReady(storeFocus);
  1733. }
  1734. }
  1735. if (enableStoreFocus) storeFocusReady();
  1736. /** Hide queue in already owned in store page
  1737. */
  1738. function storeHideSection()
  1739. {
  1740. var divOwn = document.querySelector(".already_owned_actions");
  1741. if (divOwn != null)
  1742. {
  1743. GM_addStyle(
  1744. ".game_area_already_owned { margin-top: 10px !important; } "
  1745. + ".queue_ctn { display: none; } "
  1746. + "#review_container, .reviewPostedDescription, .review_box > .thumb { display: none; } "
  1747. + ".sbh_margin_left { margin-left: 5px; } "
  1748. );
  1749. var html = ""
  1750. html += ' <a class="btnv6_blue_hoverfade btn_medium right sbh_margin_left" onclick="'
  1751. + "var sbhQueue = document.querySelector('.queue_ctn');"
  1752. + "if (sbhQueue != null) { sbhQueue.style.display = 'inherit'; sbhQueue = null;} "
  1753. + "this.style.display = 'none'; return false;"
  1754. + '"><span>Show Follow</span></a> ';
  1755. var divReview = document.querySelector("#review_container, .reviewPostedDescription");
  1756. if (divReview != null)
  1757. {
  1758. html += ' <a class="btnv6_blue_hoverfade btn_medium right sbh_margin_left" onclick="'
  1759. + "var sbhReview = document.querySelector('#review_container, .reviewPostedDescription'); "
  1760. + "if (sbhReview != null) { sbhReview.style.display = 'inherit'; sbhReview = null; } "
  1761. + "var sbhReviewThumb = document.querySelector('.review_box > .thumb'); "
  1762. + "if (sbhReviewThumb != null) { sbhReviewThumb.style.display = 'inherit'; sbhReviewThumb = null; } "
  1763. + "this.style.display = 'none'; return false;"
  1764. + '"><span>Show Review</span></a> ';
  1765. }
  1766. divOwn.innerHTML += html;
  1767. }
  1768. }
  1769. function storeHideSectionReady()
  1770. {
  1771. var url = document.documentURI;
  1772. var patt = /^http[s]?:\/\/store.steampowered.com\/app\//i;
  1773. if (patt.test(url))
  1774. {
  1775. attachOnReady(storeHideSection);
  1776. }
  1777. }
  1778. if (enableStoreHideSection) storeHideSectionReady();
  1779. // ===== End Main =====
  1780.  
  1781. attachOnReady(function()
  1782. {
  1783. debugTime("ready");
  1784. });
  1785.  
  1786. attachOnLoad(function()
  1787. {
  1788. debugTime("load");
  1789. });
  1790. function testEvent()
  1791. {
  1792. /*document.addEventListener("DOMCharacterDataModified", function (e) {
  1793. debugTime("DOMCharacterDataModified");
  1794. });
  1795. document.querySelector("#header_notification_link").addEventListener("DOMSubtreeModified", function (e) {
  1796. debugTime("DOMSubtreeModified");
  1797. });*/
  1798. }
  1799. attachOnLoad(testEvent);
  1800. })();