Steam Badge Helper

Add various features to Steam focus on Trading Cards and Badges

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

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