Steam Badge Helper

Add various features to Steam focus on Trading Cards and Badges

当前为 2016-06-23 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name Steam Badge Helper
  3. // @namespace iFantz7E.SteamBadgeHelper
  4. // @version 1.28
  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. // @run-at document-start
  14. // @grant GM_getValue
  15. // @grant GM_setValue
  16. // @grant GM_listValues
  17. // @grant GM_deleteValue
  18. // @grant GM_xmlhttpRequest
  19. // @grant GM_addStyle
  20. // @icon http://store.steampowered.com/favicon.ico
  21. // @copyright 2014, 7-elephant
  22. // ==/UserScript==
  23.  
  24. // http://userscripts.org/scripts/show/186163
  25. // https://greasyfork.org/en/scripts/5348-steam-badge-helper
  26.  
  27. (function ()
  28. {
  29. var timeStart = new Date();
  30.  
  31. // ===== Config =====
  32.  
  33. var enableDebug = false;
  34. var enableDebugConsole = true;
  35. var enableCleanLink = true;
  36. var enableGreenlightNoAutoplay = true;
  37. var enableMoveGreenlitHeader = true;
  38. var enableLinkBadgeToFriend = true;
  39. var enableLinkStoreToBadge = true;
  40. var enableLinkForumToBadge = true;
  41. var enableLinkBadgeToForum = true;
  42. var enableLinkMarketToBadge = true;
  43. var enableLinkBadgeToMarket = true;
  44. var enableLinkInventoryToBadge = true;
  45. var enableLinkProfile = true;
  46. var enableCompareBadge = true;
  47. var enableAlwaysClearCache = false;
  48. var enableCleanSteamMenu = true;
  49. var enableHideEnhancedBadgePrice = true;
  50. var enableAutoscrollSearch = true;
  51. var enableSwapTitle = true;
  52. var enableShowTitleNoti = false;
  53. var enableResizeTradeWindow = true;
  54. var enableMoveMenuEditProfile = true;
  55. var enableRefreshError = true;
  56. var enableSetAllCheckBox = true;
  57. var enableStoreFocus = true;
  58. var enableStoreHideSection = true;
  59. var enableAutoExploreQueue = true;
  60. var enableSkipAgeCheck = true;
  61. var enableCache = true;
  62. var enableDebugCache = false;
  63. var timeCacheExpireSec = 300;
  64.  
  65. var appCards = ["286120", "203990", "32200", "259720", "245550", "306410", "249610", "291130"
  66. , "218640", "268420", "46500", "102200", "301680", "273770", "264320", "339290", "340280"
  67. , "273830", "303850", "346200", "353980", "296070", "380770", "294190", "258200", "15700"
  68. , "92800", "267920", "257890", "314700", "448010"];
  69. var appCardMaps = {"202970": "202990", "234510": "35450"};
  70.  
  71. var appDlcs = // Exclude
  72. [
  73. "230889", "256576", "256611", "258643", "222606", "222615", "222618", "277751"
  74. ];
  75.  
  76. // ===== End Config =====
  77.  
  78. // ===== Cache =====
  79.  
  80. var tmpl_time = "badge_{APP}_time";
  81. var tmpl_price = "badge_{APP}_{SET}_{NUM}_price";
  82. var tmpl_url = "badge_{APP}_{SET}_{NUM}_url";
  83. var tmpl_owned = "badge_{APP}_{SET}_{NUM}_owned";
  84.  
  85. function clearCache()
  86. {
  87. var keep = ["counter"];
  88. var cache = GM_listValues()
  89. debug("clearCache: " + cache.length);
  90. for (var i = 0; i < cache.length; i++)
  91. {
  92. if (keep.indexOf(cache[i]) < 0)
  93. {
  94. GM_deleteValue(cache[i]);
  95. }
  96. }
  97. }
  98. if (enableAlwaysClearCache) clearCache();
  99.  
  100. function debugCache()
  101. {
  102. var cache = GM_listValues()
  103. if (enableDebugCache)
  104. {
  105. debug("debugCache: ");
  106. if (cache != null) for (var i = 0; i < cache.length; i++)
  107. {
  108. debug("-> " + cache[i] + ": " + GM_getValue(cache[i], 0));
  109. }
  110. }
  111. debug("debugCache: " + (cache == null ? 0 : cache.length));
  112. }
  113. setTimeout(debugCache, 0);
  114.  
  115. function generateCacheName(tmpl, app, isFoil, number)
  116. {
  117. var name = tmpl.replace("{APP}", app);
  118. if (isFoil != null)
  119. {
  120. var set = isFoil ? "F1" : "N1";
  121. name = name.replace("{SET}", set);
  122. }
  123. if (number != null)
  124. {
  125. name = name.replace("{NUM}", number);
  126. }
  127. return name;
  128. }
  129. function generateCacheNameTime(app)
  130. {
  131. return generateCacheName(tmpl_time, app);
  132. }
  133. function generateCacheNamePrice(app, isFoil, number)
  134. {
  135. return generateCacheName(tmpl_price, app, isFoil, number);
  136. }
  137. function generateCacheNameUrl(app, isFoil, number)
  138. {
  139. return generateCacheName(tmpl_url, app, isFoil, number);
  140. }
  141. function generateCacheNameOwned(app, isFoil, number)
  142. {
  143. return generateCacheName(tmpl_owned, app, isFoil, number);
  144. }
  145.  
  146. function getCacheTime(app)
  147. {
  148. var name = generateCacheNameTime(app);
  149. return GM_getValue(name, 0);
  150. }
  151. function getCacheTimeDiff(app)
  152. {
  153. return getUnixTimestamp() - getCacheTime(app);
  154. }
  155. function setCacheTime(app)
  156. {
  157. var name = generateCacheNameTime(app);
  158. GM_setValue(name, getUnixTimestamp());
  159. }
  160. function checkCacheExpire(app)
  161. {
  162. var cacheDiff = getCacheTimeDiff(app);
  163. var isCacheExpire = cacheDiff < 0 || cacheDiff > timeCacheExpireSec;
  164.  
  165. debug("cacheTimeDiff: " + cacheDiff + "s");
  166. debug("isCacheExpire: " + isCacheExpire);
  167.  
  168. return isCacheExpire;
  169. }
  170.  
  171. function getCachePrice(app, isFoil, number)
  172. {
  173. var name = generateCacheNamePrice(app, isFoil, number);
  174. return GM_getValue(name, 0);
  175. }
  176. function setCachePrice(app, isFoil, number, data)
  177. {
  178. var name = generateCacheNamePrice(app, isFoil, number);
  179. GM_setValue(name, data);
  180. }
  181.  
  182. function getCacheUrl(app, isFoil, number)
  183. {
  184. var name = generateCacheNameUrl(app, isFoil, number);
  185. return GM_getValue(name, 0);
  186. }
  187. function setCacheUrl(app, isFoil, number, data)
  188. {
  189. var name = generateCacheNameUrl(app, isFoil, number);
  190. GM_setValue(name, data);
  191. }
  192.  
  193. function getCacheOwned(app, isFoil, number)
  194. {
  195. var name = generateCacheNameOwned(app, isFoil, number);
  196. return GM_getValue(name, 0);
  197. }
  198. function setCacheOwned(app, isFoil, number, data)
  199. {
  200. var name = generateCacheNameOwned(app, isFoil, number);
  201. GM_setValue(name, data);
  202. }
  203.  
  204. // ===== End Cache =====
  205.  
  206. // ===== Helper =====
  207.  
  208. setTimeout(function ()
  209. {
  210. var counter = GM_getValue('counter', 0);
  211. GM_setValue('counter', ++counter);
  212. }, 0);
  213.  
  214. function debug(msg)
  215. {
  216. try
  217. {
  218. msg = msg ? (new String(msg)).trim().replace(/\s\s/gi, "").replace(/\s/gi, " ") : "";
  219.  
  220. if (enableDebugConsole)
  221. console.log(msg);
  222.  
  223. if (enableDebug)
  224. {
  225. var divDebugID = "div_debug_7e";
  226. var divDebugOuterID = divDebugID + "_outer";
  227. var divOut = document.getElementById(divDebugOuterID);
  228. var div = document.getElementById(divDebugID);
  229.  
  230. var isExistOuter = divOut != null;
  231. if (!isExistOuter)
  232. {
  233. divOut = document.createElement("div");
  234. divOut.id = divDebugOuterID;
  235. divOut.style = "font-family:'Courier New', Courier; font-size: 11px; z-index: 999999; padding: 3px; text-align: left;"
  236. + " border: 3px solid orange; color: black; background-color: rgba(255,255,255,0.9);"
  237. + " position: fixed; top: 3px; left: 3px; overflow-x:hidden; overflow-y:scroll; resize: both;";
  238. divOut.style.width = "150px";
  239. divOut.style.height = "100px";
  240.  
  241. if (div == null)
  242. {
  243. div = document.createElement("div");
  244. div.id = divDebugID;
  245. div.style.minWidth = "1000px";
  246. div.innerHTML = "<span style='font-weight: bold; line-height: 18px;'>Debug:</span>";
  247. }
  248. divOut.appendChild(div);
  249. document.body.appendChild(divOut);
  250. }
  251. div.innerHTML = div.innerHTML + " <br/> " + msg;
  252. divOut.scrollTop = divOut.scrollHeight;
  253. }
  254. }
  255. catch (e)
  256. {
  257. console.log("Ex: " + e);
  258. }
  259. }
  260.  
  261. function debugTime(header)
  262. {
  263. header = header ? (new String(header)) + ": " : "";
  264. var ms = (new Date()) - timeStart;
  265. debug(header + ms + "ms");
  266. }
  267. function getUnixTimestamp()
  268. {
  269. return parseInt((new Date()) / 1000);
  270. }
  271.  
  272. function randNum()
  273. {
  274. return parseInt(Math.random() * 900000 + 100000);
  275. }
  276.  
  277. function randTempID()
  278. {
  279. return "id_temp_7e_" + randNum();
  280. }
  281.  
  282. function createDivTemp(id, html)
  283. {
  284. var div = document.getElementById(id);
  285. if (div == null)
  286. {
  287. div = document.createElement("div");
  288. div.id = id;
  289. document.body.appendChild(div);
  290. }
  291. div.style.display = "none";
  292. div.style.zIndex = "-999999";
  293.  
  294. // remove all external sources
  295. var pattScript = /(<(script|meta|link|style|title)[^>]*>|<\/(script|meta|link|style|title)>)/gi;
  296. html = html.replace(pattScript, "");
  297.  
  298. // replace http to https
  299. //html = html.replace(/http:\/\//ig, "https://");
  300.  
  301. div.innerHTML = html;
  302. }
  303.  
  304. function removeDivTemp(id)
  305. {
  306. var ele = document.getElementById(id);
  307. ele.parentNode.removeChild(ele);
  308. }
  309.  
  310. function attachOnLoad(callback)
  311. {
  312. window.addEventListener("load", function (e) {
  313. callback();
  314. });
  315. }
  316.  
  317. function attachOnReady(callback)
  318. {
  319. document.addEventListener("DOMContentLoaded", function (e) {
  320. if (document.readyState === "interactive")
  321. {
  322. callback();
  323. }
  324. });
  325. }
  326.  
  327. function reload()
  328. {
  329. window.location = window.location.href;
  330. }
  331. var isVisible = (function()
  332. {
  333. var stateKey;
  334. var eventKey;
  335. var keys =
  336. {
  337. hidden: "visibilitychange",
  338. webkitHidden: "webkitvisibilitychange",
  339. mozHidden: "mozvisibilitychange",
  340. msHidden: "msvisibilitychange"
  341. };
  342. for (stateKey in keys)
  343. {
  344. if (stateKey in document)
  345. {
  346. eventKey = keys[stateKey];
  347. break;
  348. }
  349. }
  350. return function(c)
  351. {
  352. if (c)
  353. {
  354. document.addEventListener(eventKey, c);
  355. }
  356. return !document[stateKey];
  357. }
  358. })();
  359.  
  360. function isError()
  361. {
  362. var url = document.documentURI;
  363. var retVal =
  364. url.indexOf("/api") < 0
  365. && url.indexOf("api.") < 0
  366. && url.indexOf("/priceoverview") < 0
  367. && url.indexOf("/render") < 0
  368. && url.indexOf("?xml=") < 0
  369. && url.indexOf("/login/") < 0
  370. && url.indexOf("/widget/") < 0
  371. && window.location == window.parent.location
  372. &&
  373. (
  374. (
  375. document.querySelector("body.headerless_page"
  376. + ", body.flat_page"
  377. + ", #main"
  378. + ", #supernav"
  379. + ", table.tborder"
  380. + ", #headerrow"
  381. + ", #global_header"
  382. + ", .page_header_ctn"
  383. + ", .search_page"
  384. + ", #bigpicture_about"
  385. + ", #ig_bottom"
  386. + ", #feedHeaderContainer"
  387. + ", img[alt='Steam']"
  388. + ", .waitforauth"
  389. + ", .no_header"
  390. + ", .mobileBody") == null
  391. )
  392. ||
  393. (
  394. document.querySelector(".profile_fatalerror_message"
  395. + ", #error_msg") != null
  396. //|| document.querySelector("#error_box") != null
  397. //|| document.querySelector("#message") != null
  398. )
  399. );
  400. return retVal;
  401. }
  402.  
  403. function isErrorCard()
  404. {
  405. var retVal = document.querySelectorAll("#message > p.returnLink").length > 0;
  406. return retVal;
  407. }
  408.  
  409. function isErrorMarket()
  410. {
  411. var retVal = document.querySelectorAll("#searchResultsTable > .market_listing_table_message").length > 0
  412. ;//&& document.querySelector("#hover_content") == null);
  413. return retVal;
  414. }
  415.  
  416. function getQueryByName(name)
  417. {
  418. name = name.replace(/[\[]/, "\\[").replace(/[\]]/, "\\]");
  419. var regex = new RegExp("[\\?&]" + name + "=([^&#]*)"),
  420. results = regex.exec(location.search);
  421. return results == null ? "" : decodeURIComponent(results[1].replace(/\+/g, " "));
  422. }
  423.  
  424. function insertBeforeElement(newNode, referenceNode)
  425. {
  426. referenceNode.parentNode.insertBefore(newNode, referenceNode);
  427. }
  428.  
  429. function insertAfterElement(newNode, referenceNode)
  430. {
  431. referenceNode.parentNode.insertBefore(newNode, referenceNode.nextSibling);
  432. }
  433.  
  434. function clickToSelect(ele)
  435. {
  436. if (ele != null)
  437. {
  438. var range = document.createRange();
  439. range.setStartBefore(ele.firstChild);
  440. range.setEndAfter(ele.lastChild);
  441.  
  442. var sel = window.getSelection();
  443. sel.removeAllRanges();
  444. sel.addRange(range);
  445. }
  446. }
  447.  
  448. // ===== End Helper =====
  449.  
  450.  
  451. // ===== Cleaner =====
  452.  
  453. /** Auto refresh when error
  454. */
  455. function refreshError()
  456. {
  457. if(isError())
  458. {
  459. debug("refreshError: activated");
  460. setTimeout(reload, 3000);
  461. }
  462. }
  463. function refreshErrorCard()
  464. {
  465. if(isErrorCard())
  466. {
  467. debug("refreshErrorCard: activated");
  468. setTimeout(reload, 3000);
  469. }
  470. }
  471. function refreshErrorMarket()
  472. {
  473. if(isErrorMarket())
  474. {
  475. debug("refreshErrorMarket: activated");
  476. setTimeout(reload, 3000);
  477. }
  478. }
  479. function refreshErrorTimeout(tm)
  480. {
  481. function refresh()
  482. {
  483. var url = document.documentURI;
  484. var pattCard = /^http[s]?:\/\/steamcommunity.com\/(id|profiles)\/[^\/]+\/gamecards\/[0-9]+/i;
  485. var pattTrade = /^http[s]?:\/\/steamcommunity.com\/(id|profiles)\/[^\/]+\/tradeoffers\//i;
  486. var pattMarket = /^http[s]?:\/\/steamcommunity.com\/market\/listings\/[0-9]+/i;
  487.  
  488. if (url.indexOf("#") < 0 && url.indexOf("json") < 0 && url.indexOf("xml") < 0)
  489. {
  490. setTimeout(refreshError, tm);
  491.  
  492. if (pattCard.test(url) || pattTrade.test(url))
  493. {
  494. setTimeout(refreshErrorCard, tm);
  495. }
  496.  
  497. if (pattMarket.test(url))
  498. {
  499. setTimeout(refreshErrorMarket, tm);
  500. }
  501. }
  502. }
  503. attachOnLoad(refresh);
  504. }
  505. if (enableRefreshError) refreshErrorTimeout(3000);
  506.  
  507. /** Remove unnessary parameters in URL
  508. */
  509. function cleanLink()
  510. {
  511. var url = document.documentURI;
  512. var pattApp = /^http[s]?:\/\/store.steampowered.com\/(app|sub)\/[0-9]+/i;
  513. var pattBadge = /^http[s]?:\/\/steamcommunity.com\/(id|profiles)\/[^\/]+\/gamecards\/[0-9]+/i;
  514. var pattFork = /^http[s]?:\/\/store\.(.+steampowered|steamgames)\.com\//i;
  515. var pattParam = /\/\?.*$/
  516. var pattParamCC = /\/\?cc\=.*$/
  517. var isSameSite = true;
  518. var urlNew = url;
  519.  
  520. if (pattApp.test(url))
  521. {
  522. var urlNews = url.match(pattApp);
  523. if (urlNews != null)
  524. {
  525. var urlTail = url.replace(pattApp, "");
  526.  
  527. if (urlTail == "")
  528. {
  529. urlNew = urlNews[0] + "/";
  530. }
  531. else if (urlTail != "/")
  532. {
  533. if (!pattParamCC.test(urlTail) && pattParam.test(urlTail))
  534. {
  535. urlNew = urlNews[0] + "/";
  536. }
  537. }
  538. }
  539. }
  540. else if (pattBadge.test(url))
  541. {
  542. var urlNews = url.match(pattBadge);
  543. if (urlNews != null)
  544. {
  545. var urlTail = url.replace(pattBadge, "");
  546.  
  547. if (urlTail.charAt(0) != "/")
  548. {
  549. urlNew = urlNews[0] + "/" + urlTail;
  550. }
  551. }
  552. }
  553. else if (pattFork.test(url))
  554. {
  555. urlNew = url.replace(pattFork, "http://store.steampowered.com/");
  556. isSameSite = false;
  557. }
  558.  
  559. if (urlNew != url)
  560. {
  561. debug("cleanLink: activated");
  562. if (isSameSite)
  563. {
  564. try
  565. {
  566. window.history.replaceState(null, null, urlNew);
  567. }
  568. catch (ex)
  569. {
  570. window.location.replace(urlNew);
  571. }
  572. }
  573. else
  574. {
  575. window.location.replace(urlNew);
  576. }
  577. }
  578. }
  579. function cleanLinkAttach()
  580. {
  581. attachOnReady(function()
  582. {
  583. cleanLink();
  584. });
  585. }
  586. if (enableCleanLink) cleanLinkAttach();
  587.  
  588. /** Change search parameter to page 1 to determine visited links
  589. */
  590. function cleanLinkSearch()
  591. {
  592. var pattSearch = /snr=1_7_7_230_150_[0-9]+/i
  593.  
  594. var as = document.querySelectorAll("a.search_result_row");
  595. for (var j = 0; j < as.length; j++)
  596. {
  597. var urlSearch = as[j].href;
  598. urlSearch = urlSearch.replace(pattSearch, "snr=1_7_7_230_150_1");
  599. as[j].href = urlSearch;
  600. }
  601.  
  602. document.addEventListener("DOMNodeInserted", onNodeInserted);
  603. function onNodeInserted(e)
  604. {
  605. try
  606. {
  607. var node = e.target;
  608. if (node.classList.contains("search_result_row"))
  609. {
  610. var urlSearch = node.href;
  611. urlSearch = urlSearch.replace(pattSearch, "snr=1_7_7_230_150_1");
  612. node.href = urlSearch;
  613. }
  614.  
  615. var count = document.querySelectorAll(".search_result_row").length;
  616. var divs = document.querySelectorAll(".search_pagination_left");
  617. for (var i = 0; i < divs.length; i++)
  618. {
  619. var oldVals = divs[i].innerHTML.match(/[0-9]+/g);
  620. var oldVal = oldVals[oldVals.length > 0 ? oldVals.length-1 : 0];
  621. divs[i].innerHTML = "showing " + count + " of " + oldVal;
  622. }
  623. }
  624. catch (ex)
  625. {
  626. }
  627. }
  628.  
  629. if (enableAutoscrollSearch)
  630. {
  631. var divButton = document.createElement("div");
  632. divButton.classList.add("btn_client_small");
  633. divButton.id = "divAutoscroll";
  634. divButton.style = "position: fixed; right: 20px; bottom: 20px; z-index:3;";
  635. 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>";
  636. document.body.appendChild(divButton);
  637. }
  638. }
  639. function cleanLinkSearchAttach(tm)
  640. {
  641. var url = document.documentURI;
  642. var patt = /^http[s]?:\/\/store.steampowered.com\/search\//i;
  643.  
  644. if (patt.test(url))
  645. {
  646. attachOnLoad(function()
  647. {
  648. setTimeout(cleanLinkSearch, tm);
  649. });
  650. }
  651. }
  652. if (enableCleanLink) cleanLinkSearchAttach(100);
  653.  
  654. /** Remove link lifter in URL
  655. */
  656. function cleanLinkLifter()
  657. {
  658. var url = document.documentURI;
  659. var patt = /^http[s]?:\/\/steamcommunity.com\//i;
  660. var pattHome = /^http[s]?:\/\/steamcommunity.com\/(id|profiles)\/[^\/]+\/home/i;
  661.  
  662. function cleanLifter()
  663. {
  664. var lifter = "https://steamcommunity.com/linkfilter/";
  665. var lifterLen = lifter.length;
  666. var lifter2 = "?url=";
  667. var lifterLen2 = lifter2.length;
  668. var js = "javascript:"
  669. var jsLen = js.length;
  670.  
  671. var as = document.getElementsByTagName("a");
  672. for (var i = 0; i < as.length; i++)
  673. {
  674. var urlLink = as[i].href;
  675. if (urlLink.indexOf(lifter) == 0)
  676. {
  677. urlLink = urlLink.substr(lifterLen);
  678. if (urlLink.indexOf(lifter2) == 0)
  679. {
  680. urlLink = urlLink.substr(lifterLen2);
  681. }
  682. as[i].href = urlLink;
  683. }
  684. else if (patt.test(url) && urlLink.indexOf(js) == 0)
  685. {
  686. if (as[i].getAttribute('onclick') == null)
  687. {
  688. urlLink = decodeURIComponent(urlLink.substr(jsLen));
  689. as[i].setAttribute('onclick', urlLink + "; return false;");
  690. }
  691. }
  692. }
  693. }
  694.  
  695. var cleanLifterTimeoutId = 0;
  696.  
  697. function cleanLifterTimeout()
  698. {
  699. clearTimeout(cleanLifterTimeoutId);
  700. cleanLifterTimeoutId = setTimeout(cleanLifter, 1000);
  701. }
  702.  
  703. attachOnReady(cleanLifter);
  704.  
  705. if (pattHome.test(url))
  706. {
  707. document.addEventListener("DOMNodeInserted", cleanLifterTimeout);
  708. }
  709. }
  710. if (enableCleanLink) cleanLinkLifter();
  711.  
  712. /** Clean Steam's menu on top
  713. */
  714. function cleanSteamMenuTimeout(tm)
  715. {
  716. GM_addStyle(
  717. " .header_installsteam_btn_content , .header_installsteam_btn { display: none; } " // Steam header
  718. + " #enhanced_pulldown { display: none; } " // Enhanced Steam header
  719. + " #soe-t-menu { display: none !important; } " // SOE header
  720. );
  721.  
  722. attachOnReady(function ()
  723. {
  724. setTimeout(function()
  725. {
  726. var soe_menu = document.querySelector("#soe-t-menu");
  727. if (soe_menu != null)
  728. {
  729. soe_menu.textContent = "SOE";
  730.  
  731. var parent = soe_menu.parentElement;
  732. for (var i = 0; i < parent.childNodes.length; i++)
  733. {
  734. var node = parent.childNodes[i];
  735. if (node.nodeName == "#text" && node.nodeValue.toString().trim() == "|")
  736. {
  737. node.parentElement.removeChild(node);
  738. break;
  739. }
  740. }
  741.  
  742. soe_menu.parentElement.parentElement.insertBefore(soe_menu, null);
  743. }
  744. }, tm);
  745. });
  746.  
  747. var menu = document.querySelector("#account_pulldown");
  748. if (menu != null)
  749. {
  750. menu.addEventListener('mouseover', function() {
  751. GM_addStyle(
  752. " #enhanced_pulldown { display: inline-block !important; } " // Enhanced Steam header
  753. + " #soe-t-menu { display: inline-block !important; } " // SOE header
  754. );
  755. });
  756. }
  757.  
  758. // fix market transaction display // temp
  759. GM_addStyle("#market_transactions .transactionRowTitle { display: inline-block; padding-right: 5px; }");
  760.  
  761. /*
  762. setTimeout(function()
  763. {
  764. var as = document.querySelectorAll(".header_installsteam_btn_content , .header_installsteam_btn");
  765. for (var i = 0; i < as.length; i++)
  766. {
  767. as[i].style.display = "none";
  768. }
  769. }, tm);
  770.  
  771. attachOnLoad(function ()
  772. {
  773. setTimeout(function()
  774. {
  775. var aE = document.getElementById("enhanced_pulldown");
  776. if (aE != null)
  777. {
  778. aE.style.display = "none";
  779. }
  780. }, tm);
  781. });
  782. */
  783. }
  784. if (enableCleanSteamMenu) cleanSteamMenuTimeout(0);
  785.  
  786. /** Hide EnhancedSteam's price on Badge page
  787. */
  788. function hideEnhancedBadgePrice()
  789. {
  790. GM_addStyle(".es_card_search, .es_item_action { display: none !important; } ");
  791. /*
  792. document.addEventListener("DOMNodeInserted", onNodeInserted);
  793. function onNodeInserted(e)
  794. {
  795. try
  796. {
  797. var node = e.target;
  798. if (node.classList.contains("es_card_search"))
  799. {
  800. debug("hideEnhanced: " + node.innerHTML);
  801. node.style.display = "none";
  802. }
  803. }
  804. catch (ex)
  805. {
  806. }
  807. }
  808. */
  809. }
  810. function hideEnhancedBadgePriceTimeout(tm)
  811. {
  812. var url = document.documentURI;
  813. var patt = /^http[s]?:\/\/steamcommunity.com\/(id|profiles)\/[^\/]+\/(gamecards\/[0-9]+|inventory)/i;
  814.  
  815. if (patt.test(url))
  816. {
  817. setTimeout(hideEnhancedBadgePrice, tm);
  818. }
  819. }
  820. if (enableHideEnhancedBadgePrice) hideEnhancedBadgePriceTimeout(0);
  821.  
  822. // ===== End Cleaner =====
  823.  
  824. // ===== Main =====
  825.  
  826. /** Disable autoplay on Greenlight page while autoplay option is on
  827. */
  828. function disableGreenlightAutoplay()
  829. {
  830. var iframes = document.getElementsByTagName("iframe");
  831. for (var i in iframes)
  832. {
  833. if (iframes[i].className == "highlight_flash_player_notice")
  834. {
  835. iframes[i].src = iframes[i].src.replace("autoplay=1", "autoplay=0");
  836. }
  837. }
  838. }
  839. function disableGreenlightAutoplayTimeout(tm)
  840. {
  841. var url = document.documentURI;
  842. var patt = /^http[s]?:\/\/steamcommunity.com\/sharedfiles\/filedetails\//i;
  843.  
  844. if (patt.test(url))
  845. {
  846. attachOnLoad(function ()
  847. {
  848. setTimeout(disableGreenlightAutoplay, tm);
  849. });
  850. }
  851. }
  852. if (enableGreenlightNoAutoplay) disableGreenlightAutoplayTimeout(0);
  853.  
  854. /** Move Greenlit header to match voting section of Greenlight item
  855. */
  856. function moveGreenlitHeader()
  857. {
  858. var eleGreenlit = document.querySelector(".flag");
  859. var eleArea = document.querySelector(".workshopItemPreviewArea");
  860. if (eleGreenlit != null && eleArea != null)
  861. {
  862. eleArea.appendChild(eleGreenlit.parentElement.parentElement);
  863. }
  864. }
  865. function moveGreenlitHeaderReady(tm)
  866. {
  867. var url = document.documentURI;
  868. var patt = /^http[s]?:\/\/steamcommunity.com\/sharedfiles\/filedetails\//i;
  869.  
  870. if (patt.test(url))
  871. {
  872. attachOnReady(function ()
  873. {
  874. moveGreenlitHeader();
  875. });
  876. }
  877. }
  878. if (enableMoveGreenlitHeader) moveGreenlitHeaderReady();
  879.  
  880. /** Move button in Edit Profile page to right
  881. */
  882. function moveMenuEditProfile()
  883. {
  884. GM_addStyle(
  885. ".group_content_bodytext { position: fixed; top: 400px; margin-left: 680px; line-height: 34px; z-index: 10; } "
  886. + ".rightcol { position: fixed; top: 230px; margin-left: 658px; z-index: 10; } "
  887. + ".saved_changes_msg { width: 610px; } "
  888. + ".showcase_stat .value { z-index: 2; position: relative; } "
  889. );
  890. }
  891. function moveMenuEditProfileTimeout(tm)
  892. {
  893. var url = document.documentURI;
  894. var patt = /^http[s]?:\/\/steamcommunity.com\/(id|profiles)\/([^\/]+\/edit)?/i;
  895.  
  896. if (patt.test(url))
  897. {
  898. setTimeout(moveMenuEditProfile, tm);
  899. }
  900. }
  901. if (enableMoveMenuEditProfile) moveMenuEditProfileTimeout(0);
  902.  
  903. /** Add small button on friend section in Badge page to view friends' Badge page for comparing cards
  904. * Reduce height of Review textbox
  905. */
  906. function linkBadgeToFriend()
  907. {
  908. var url = document.documentURI;
  909. var pattHead = /^http[s]?:\/\/steamcommunity.com\/(id|profiles)\/[^\/]*/i;
  910. var urlTail = url.replace(pattHead, "");
  911. //var pattProfile = /^http[s]?:\/\/steamcommunity.com\/(id|profiles)\/[^\/]+[\/]?$/i;
  912.  
  913. // Correct style
  914. {
  915. var styleCorrect = "";
  916.  
  917. // fix long card name show incorrect column of cards
  918. styleCorrect += ".badge_card_set_card .badge_card_set_text { max-width: 220px; } ";
  919.  
  920. // fix Firefox show incorrect column of friends' avatar
  921. styleCorrect += ".persona { line-height: 16px; } ";
  922.  
  923. // fix EnhancedSteam show incorrect size of next badge progress
  924. styleCorrect += ".gamecard_badge_progress .badge_info { width: 250px !important; } ";
  925.  
  926. // fix oversize friend action button
  927. styleCorrect += ".badge_friendwithgamecard_actions .btn_medium { padding-bottom: 0px !important;"
  928. + " width: 26px !important; text-align: center !important; } ";
  929.  
  930. // fix card name display over counter
  931. styleCorrect += ".badge_card_set_text_qty { z-index: 2 !important; position: relative !important; } ";
  932.  
  933. // fix card drop counter is behind button and reposition
  934. styleCorrect += ".badge_title_stats_content { margin-top: -4px; } ";
  935. if (document.querySelector(".badge_title_playgame") != null)
  936. {
  937. styleCorrect += ".badge_title_stats_content { padding-right: 45px; } ";
  938. }
  939.  
  940. GM_addStyle(styleCorrect);
  941. }
  942.  
  943. // Link to friends
  944. {
  945. var els = document.querySelectorAll(".badge_friends_have_earned_friends, .badge_friendwithgamecard");
  946. for (var i = 0; i < els.length; i++)
  947. {
  948. var as = els[i].querySelectorAll(".playerAvatar a, a.persona");
  949. var limit = 1;
  950. var curLimit = 0;
  951.  
  952. for (var j = 0; j < as.length; j++)
  953. {
  954. var a = as[j];
  955. //if (pattProfile.test(a.href))
  956. {
  957. var badgeUrl = a.href + urlTail;
  958.  
  959. if (els[i].classList.contains("badge_friends_have_earned_friends")
  960. || !a.parentNode.classList.contains("playerAvatar"))
  961. {
  962. a.href = badgeUrl;
  963. }
  964.  
  965. if (curLimit < limit && els[i].classList.contains("badge_friendwithgamecard"))
  966. {
  967. elActs = els[i].getElementsByClassName("badge_friendwithgamecard_actions");
  968. for (var k = 0; k < elActs.length; k++)
  969. {
  970. var eleA = document.createElement("a");
  971. eleA.classList.add("btn_grey_grey");
  972. eleA.classList.add("btn_medium");
  973. eleA.setAttribute("title", "View friend's badge");
  974. eleA.setAttribute("href", badgeUrl);
  975. eleA.innerHTML = "<img style='height:16px; opacity:0.66'"
  976. + " src='http://cdn4.store.steampowered.com/public/images/ico/ico_cards.png'></a> ";
  977.  
  978. elActs[k].appendChild(eleA);
  979.  
  980. curLimit += 1;
  981. } // end for k
  982. }
  983. }
  984. } // end for j
  985. } // end for i
  986. }
  987.  
  988. // Sort friends
  989. {
  990. setTimeout(function()
  991. {
  992. var eleSections = document.querySelectorAll(".badge_friendswithgamecards_section");
  993. for (var i = 0; i < eleSections.length; i++)
  994. {
  995. var keyArr = new Array();
  996. var valArr = new Array();
  997.  
  998. var eleFriends = eleSections[i].querySelectorAll(".badge_friendwithgamecard");
  999. for (var j = 0; j < eleFriends.length; j++)
  1000. {
  1001. var elePersona = eleFriends[j].querySelector(".persona");
  1002. if (elePersona != null)
  1003. {
  1004. var key = "";
  1005.  
  1006. if (elePersona.classList.contains("in-game"))
  1007. {
  1008. key = "01";
  1009. }
  1010. else if (elePersona.classList.contains("online"))
  1011. {
  1012. key = "02";
  1013. }
  1014. else
  1015. {
  1016. key = "03";
  1017. }
  1018.  
  1019. var key = key + "___" + elePersona.textContent.trim().toLowerCase()
  1020. + "___" + elePersona.getAttribute("data-miniprofile");
  1021. keyArr.push(key);
  1022. valArr[key] = eleFriends[j];
  1023. eleSections[i].removeChild(eleFriends[j]);
  1024. }
  1025. } // end for j
  1026.  
  1027. keyArr.sort();
  1028.  
  1029. for (var j = keyArr.length - 1; j > -1 ; j--)
  1030. {
  1031. eleSections[i].insertBefore(valArr[keyArr[j]], eleSections[i].firstChild);
  1032. } // end for j
  1033.  
  1034. } // end for i
  1035. }, 100);
  1036. }
  1037. }
  1038. function linkBadgeToFriendAttach()
  1039. {
  1040. var url = document.documentURI;
  1041. var patt = /^http[s]?:\/\/steamcommunity.com\/(id|profiles)\/[^\/]+\/gamecards\/[0-9]+/i;
  1042.  
  1043. if (patt.test(url) && !isErrorCard())
  1044. {
  1045. attachOnLoad(linkBadgeToFriend);
  1046. }
  1047. }
  1048. if (enableLinkBadgeToFriend) linkBadgeToFriendAttach();
  1049.  
  1050. /** Add button on top of Store page to view Badge page
  1051. */
  1052. function linkStoreToBadge()
  1053. {
  1054. var url = document.documentURI;
  1055. var patt = /^http[s]?:\/\/store.steampowered.com\/app\//i;
  1056. var pattEnd = /[^0-9].*$/i;
  1057. var app = url.replace(patt, "").replace(pattEnd, "");
  1058.  
  1059. var aOwner = document.querySelector("#global_actions > .user_avatar");
  1060. var isLoggedIn = aOwner != null;
  1061. var ownerUrl = isLoggedIn ? aOwner.href.substr(0, aOwner.href.length - 1) : "http://steamcommunity.com/my";
  1062. var isOwned = document.querySelector(".game_area_already_owned") != null;
  1063.  
  1064. var urlCard = "category2=29";
  1065. var titleCard = "Steam Trading Cards";
  1066. var urlDlc = "category1=21";
  1067. var titleDlc = "Downloadable Content";
  1068. var urlAch = "category2=22";
  1069. var titleAch = "Steam Achievement";
  1070.  
  1071. var isBadge = false;
  1072. var isBadgeMap = false;
  1073. var isAch = false;
  1074.  
  1075. var as = document.querySelectorAll(".game_area_details_specs a");
  1076. for (var i = 0; i < as.length; i++)
  1077. {
  1078. if (appDlcs.indexOf(app) > -1 || as[i].href.indexOf(urlDlc) > -1 || as[i].textContent == titleDlc)
  1079. {
  1080. isBadge = false;
  1081. isAch = false;
  1082. break;
  1083. }
  1084. else if (as[i].href.indexOf(urlCard) > -1 || as[i].textContent == titleCard)
  1085. {
  1086. isBadge = true;
  1087. }
  1088. else if (as[i].href.indexOf(urlAch) > -1 || as[i].textContent == titleAch)
  1089. {
  1090. isAch = true;
  1091. }
  1092. }
  1093.  
  1094. if (appCardMaps[app] != null)
  1095. {
  1096. isBadge = true;
  1097. isBadgeMap = true;
  1098. }
  1099. else if (!isBadge)
  1100. {
  1101. if (appCards.indexOf(app) > -1)
  1102. {
  1103. isBadge = true;
  1104. }
  1105. }
  1106.  
  1107. if (isBadge)
  1108. {
  1109. var appCard = app;
  1110. if (isBadgeMap)
  1111. {
  1112. appCard = appCardMaps[app];
  1113. }
  1114.  
  1115. var divs = document.getElementsByClassName("apphub_OtherSiteInfo");
  1116. for (var i = 0; i < divs.length; i++)
  1117. {
  1118. divs[i].innerHTML = divs[i].innerHTML
  1119. + " &nbsp;<a class=\"btnv6_blue_hoverfade btn_medium\""
  1120. + " href=\"" + ownerUrl + "/gamecards/" + appCard + "/\">"
  1121. + "<span>Trading Cards</span></a>";
  1122. }
  1123. }
  1124.  
  1125. if (false && isAch)
  1126. {
  1127. var urlAchLink = (isLoggedIn && isOwned ? ownerUrl + "/stats/appid/" : "http://steamcommunity.com/stats/")
  1128. + app + "/achievements/";
  1129.  
  1130. var divCommu = document.querySelector(".communitylink .block_content_inner");
  1131. if (divCommu != null)
  1132. {
  1133. var aAch = ' <a class="linkbar" href="' + urlAchLink + '">'
  1134. + '<div class="rightblock" style="margin-top: 3px;"><img src="http://cdn4.store.steampowered.com/public/images/ico/ico_achievements.png"'
  1135. + ' align="top" border="0" style="margin-right: -9px; height: 20px; margin-top: -5px;"></div>'
  1136. + 'View Steam Achievements</a>';
  1137. divCommu.innerHTML = divCommu.innerHTML + aAch;
  1138. }
  1139.  
  1140. /*var divDemo = document.querySelector("#demo_block > div");
  1141. if (divDemo != null)
  1142. {
  1143. var divAch = '<div class="demo_area_button"><a class="game_area_wishlist_btn" href="'
  1144. + urlAchLink + '">View Steam Achievements</a></div>';
  1145.  
  1146. divDemo.innerHTML = divAch + divDemo.innerHTML;
  1147. }*/
  1148. }
  1149.  
  1150. var txtRec = document.getElementById("game_recommendation");
  1151. if (txtRec != null)
  1152. {
  1153. // reduce height of review textbox
  1154. txtRec.style.height = "16px";
  1155. txtRec.onfocus = function(){txtRec.style.height="150px";};
  1156. }
  1157.  
  1158. // Move early access zone
  1159. {
  1160. var eleEa = document.querySelector(".early_access_header");
  1161. if (eleEa != null)
  1162. {
  1163. var elePurchase = document.querySelector("#game_area_purchase");
  1164. if (elePurchase != null)
  1165. {
  1166. insertBeforeElement(elePurchase, eleEa);
  1167. }
  1168. }
  1169. }
  1170.  
  1171. // Redirect Steam run
  1172. {
  1173. var eleCart = document.querySelector(".btn_addtocart a");
  1174. if (eleCart != null)
  1175. {
  1176. if (eleCart.href.indexOf("ShowGotSteamModal") > -1)
  1177. {
  1178. eleCart.href = eleCart.href.replace("javascript:ShowGotSteamModal('", "")
  1179. .replace(/\',.*$/i, "");
  1180. }
  1181. }
  1182. }
  1183.  
  1184. if (!isLoggedIn)
  1185. {
  1186. var eleLoginMain = document.querySelector("a.global_action_link[href*='/login/']");
  1187. var eleLoginQueue = document.querySelector(".queue_actions_ctn a[href*='/login/']");
  1188. if (eleLoginMain != null && eleLoginQueue != null)
  1189. {
  1190. eleLoginMain.setAttribute("href", eleLoginQueue.getAttribute("href"));
  1191. }
  1192. }
  1193.  
  1194. GM_addStyle(".game_area_dlc_row, .tab_item { display: inherit !important; } "
  1195. + " .game_purchase_action_bg { white-space: normal !important; } ");
  1196. }
  1197. function linkStoreToBadgeAttach(tm)
  1198. {
  1199. var url = document.documentURI;
  1200. var patt = /^http[s]?:\/\/store.steampowered.com\/(app|sub)\//i;
  1201.  
  1202. if (patt.test(url))
  1203. {
  1204. attachOnLoad(function()
  1205. {
  1206. setTimeout(linkStoreToBadge, tm);
  1207. });
  1208. }
  1209. }
  1210. if (enableLinkStoreToBadge) linkStoreToBadgeAttach(100);
  1211.  
  1212. /** Add button in Forum page to view Badge page
  1213. * Mark topic to determine visited links
  1214. */
  1215. function linkForumToBadge()
  1216. {
  1217. var url = document.documentURI;
  1218. var pattAppHead = /^http[s]?:\/\/steamcommunity.com\/app\//i;
  1219. var pattAppTail = /[^0-9]+.*/i;
  1220. var app = url.replace(pattAppHead, "").replace(pattAppTail, "");
  1221.  
  1222. var aOwner = document.querySelector("#global_actions > a.user_avatar");
  1223. var isLoggedIn = aOwner != null;
  1224. var ownerUrl = isLoggedIn ? aOwner.href.substr(0, aOwner.href.length - 1) : "http://steamcommunity.com/my";
  1225.  
  1226. var divs = document.getElementsByClassName("apphub_OtherSiteInfo");
  1227. for (var j = 0; j < divs.length; j++)
  1228. {
  1229. var aBadge = " <a class='btn_darkblue_white_innerfade btn_medium' href='"
  1230. + ownerUrl + "/gamecards/" + app
  1231. + "/'><span>Trading Cards</span></a> ";
  1232. divs[j].innerHTML = divs[j].innerHTML + aBadge;
  1233. }
  1234.  
  1235. function markTopic()
  1236. {
  1237. var as = document.getElementsByClassName("forum_topic_overlay");
  1238. for (var i = 0; i < as.length; i++)
  1239. {
  1240. // mark topic
  1241. as[i].style.borderLeft = "3px solid";
  1242. }
  1243. }
  1244. markTopic();
  1245. document.addEventListener("DOMNodeInserted", markTopic);
  1246. }
  1247. function linkForumToBadgeTimeout(tm)
  1248. {
  1249. var url = document.documentURI;
  1250. var patt = /^http[s]?:\/\/steamcommunity.com\/app\/[0-9]+\/tradingforum\//i;
  1251.  
  1252. if (patt.test(url))
  1253. {
  1254. setTimeout(linkForumToBadge, tm);
  1255. }
  1256. }
  1257. if (enableLinkForumToBadge) linkForumToBadgeTimeout(100);
  1258.  
  1259. /** Add buttons in Badge page to view Trading Forum, Store, friend's Inventory and my Badge page
  1260. */
  1261. function linkBadgeToForum()
  1262. {
  1263. var url = document.documentURI;
  1264.  
  1265. var pattAppHead = /^http[s]?:\/\/steamcommunity.com\/(id|profiles)\/[^\/]+\/gamecards\//i;
  1266. var pattAppTail = /[^0-9]+.*/i;
  1267. var app = url.replace(pattAppHead, "").replace(pattAppTail, "");
  1268.  
  1269. GM_addStyle(".sbh_badge_menu_right { float: right; margin-left: 5px; } ");
  1270.  
  1271. var divs = document.getElementsByClassName("gamecards_inventorylink");
  1272. if (divs.length > 0)
  1273. {
  1274. var aStoreUrl = "http://store.steampowered.com/app/" + app + "/";
  1275. var aForumUrl = "http://steamcommunity.com/app/" + app + "/tradingforum/";
  1276. var aCustom = " <a class='btn_grey_grey btn_small_thin sbh_badge_menu_right' href='" + aStoreUrl + "'>"
  1277. + " <span>Visit Store Page</span></a> "
  1278. + " <a class='btn_grey_grey btn_small_thin sbh_badge_menu_right' href='" + aForumUrl + "'>"
  1279. + " <span>Visit Trade Forum</span></a> ";
  1280.  
  1281. divs[0].innerHTML = divs[0].innerHTML + aCustom;
  1282. }
  1283.  
  1284. var aOwner = document.querySelector("#global_actions > a.user_avatar");
  1285. var isLoggedIn = aOwner != null;
  1286. var ownerUrl = isLoggedIn ? aOwner.href.substr(0, aOwner.href.length - 1) : "http://steamcommunity.com/my";
  1287.  
  1288. var aFriend = document.querySelector(".profile_small_header_name > a");
  1289. var isFriendExist = aFriend != null;
  1290. var friendUrl = isFriendExist ? aFriend.href : "http://steamcommunity.com/my";
  1291. var friendName = isFriendExist ? aFriend.textContent.trim() : "my"
  1292. var friendNameOwner = isFriendExist ? friendName + "'s" : friendName;
  1293.  
  1294. var isOwner = isLoggedIn && ownerUrl == friendUrl;
  1295.  
  1296. if (!isOwner)
  1297. {
  1298. var divInv;
  1299. if (divs.length > 0)
  1300. {
  1301. divInv = divs[0];
  1302. }
  1303. else
  1304. {
  1305. divInv = document.createElement("div");
  1306. divInv.classList.add("gamecards_inventorylink");
  1307. var divBadge = document.querySelector(".badge_detail_tasks");
  1308. if (divBadge != null)
  1309. {
  1310. divBadge.insertBefore(divInv, divBadge.firstChild);
  1311. }
  1312. }
  1313. var aFrInvUrl = friendUrl + "/inventory/#753_6";
  1314. var aOwnUrl = url.replace(pattAppHead, ownerUrl + "/gamecards/");
  1315. divInv.innerHTML = divInv.innerHTML
  1316. + "<a class='btn_grey_grey btn_small_thin' href='" + aFrInvUrl + "'><span>View cards in "
  1317. + friendNameOwner + " Inventory</span></a> "
  1318. + " <a class='btn_grey_grey btn_small_thin' href='" + aOwnUrl + "'><span>View my Progress</span></a> ";
  1319.  
  1320. }
  1321. }
  1322. function linkBadgeToForumAttach()
  1323. {
  1324. var url = document.documentURI;
  1325. var patt = /^http[s]?:\/\/steamcommunity.com\/(id|profiles)\/[^\/]+\/gamecards\/[0-9]+/i;
  1326.  
  1327. if (patt.test(url) && !isErrorCard())
  1328. {
  1329. attachOnLoad(linkBadgeToForum);
  1330. }
  1331. }
  1332. if (enableLinkBadgeToForum) linkBadgeToForumAttach();
  1333.  
  1334. /** Add button in Market page to view Badge and Store page
  1335. */
  1336. function linkMarketToBadge()
  1337. {
  1338. var url = document.documentURI;
  1339.  
  1340. var pattAppHead = /^http[s]?:\/\/steamcommunity.com\/market\/listings\/753\//i;
  1341. var pattAppTail = /[^0-9]+.*/i;
  1342. var pattNumber = /[0-9]+/;
  1343. var app = url.replace(pattAppHead, "").replace(pattAppTail, "");
  1344.  
  1345. var aOwner = document.querySelector("#global_actions > a.user_avatar");
  1346. var isLoggedIn = aOwner != null;
  1347. var ownerUrl = isLoggedIn ? aOwner.href.substr(0, aOwner.href.length - 1) : "http://steamcommunity.com/my";
  1348.  
  1349. GM_addStyle(
  1350. "#market_buynow_dialog_purchase > span:nth-child(1) { line-height: 80px; padding: 0px 50px 0px 50px !important; } "
  1351. + "#market_buynow_dialog { width: 850px; } "
  1352. + ".market_listing_table_header { margin: 0px; } "
  1353. + ".market_listing_row { margin-top: 2px; } "
  1354. + ".market_listing_row > .market_listing_es_lowest:nth-child(3) { visibility: hidden; } "
  1355. + ".market_listing_row > .market_listing_es_lowest:nth-child(8) { display: none; } "
  1356. + ".es_market_lowest_button { display: none; } "
  1357. );
  1358.  
  1359. var div_tabL = document.querySelectorAll("div.market_large_tab_well");
  1360. for (var i = 0; i < div_tabL.length; i++)
  1361. {
  1362. // reduce height of header
  1363. div_tabL[i].style.height = "50px";
  1364. }
  1365. var div_tabLB = document.querySelectorAll("div.market_large_tab_well_gradient");
  1366. for (var i = 0; i < div_tabLB.length; i++)
  1367. {
  1368. div_tabLB[i].style.height = "65px";
  1369. }
  1370.  
  1371. var div_store = document.getElementById("largeiteminfo_game_name");
  1372.  
  1373. if (div_store != null)
  1374. {
  1375. div_store.innerHTML = "<a href='http://store.steampowered.com/app/" + app + "/'>"
  1376. + div_store.innerHTML + "</a>";
  1377. }
  1378.  
  1379. var isFoil = false;
  1380. var ele_name = document.getElementById("largeiteminfo_item_name");
  1381. if (ele_name != null)
  1382. {
  1383. isFoil = (ele_name.innerHTML.search("Foil") > -1);
  1384. ele_name.innerHTML = "<a href='" + ownerUrl + "/gamecards/" + app
  1385. + (isFoil ? "/?border=1" : "/") + "'>" + ele_name.innerHTML + "</a>";
  1386. }
  1387.  
  1388. var ele_icon = document.getElementsByClassName("item_desc_game_icon");
  1389. for (var i = 0; i < ele_icon.length; i++)
  1390. {
  1391. ele_icon[i].innerHTML = "<a href='http://store.steampowered.com/app/" + app + "/'>"
  1392. + ele_icon[i].innerHTML + "</a>";
  1393. }
  1394.  
  1395. var div_nav = document.getElementsByClassName("market_large_tab_well");
  1396. for (var j = 0; j < div_nav.length; j++)
  1397. {
  1398. var aBadge = ' <div class="apphub_OtherSiteInfo" '
  1399. + 'style="position: relative; float: right; right: 2px; top: 2px;"> '
  1400. + '<a style="position: relative; z-index: 1;" class="btn_darkblue_white_innerfade btn_medium" '
  1401. + 'href="#" onclick="document.getElementById(\'pricehistory\').style.display = \'inherit\'; '
  1402. + 'document.querySelector(\'.pricehistory_zoom_controls\').style.display = \'inherit\'; return false; " >'
  1403. + '<span>Show History</span></a> &nbsp;'
  1404. + '<a style="position: relative; z-index: 1;" class="btn_darkblue_white_innerfade btn_medium" '
  1405. + 'href="http://store.steampowered.com/app/' + app + '"><span>Store Page</span></a> &nbsp;'
  1406. + '<a class="btn_darkblue_white_innerfade btn_medium" '
  1407. + 'href="' + ownerUrl + '/gamecards/' + app + (isFoil ? "/?border=1" : "/")
  1408. + '"><span>Trading Cards</span></a></div>';
  1409. div_nav[j].innerHTML = div_nav[j].innerHTML + aBadge;
  1410. GM_addStyle(
  1411. "#pricehistory, .pricehistory_zoom_controls { display: none } "
  1412. );
  1413. }
  1414.  
  1415. var span_list = document.querySelectorAll("div.market_listing_row > div:nth-child(3) > span:nth-child(1) > span:nth-child(1)");
  1416. for (var i = 0; i < span_list.length; i++)
  1417. {
  1418. if (!pattNumber.test(span_list[i].textContent))
  1419. {
  1420. span_list[i].parentElement.parentElement.parentElement.style.display = "none";
  1421. }
  1422. }
  1423.  
  1424. // preview bg in profile
  1425. {
  1426. if (ownerUrl != "http://steamcommunity.com/my")
  1427. {
  1428. var aImg = document.querySelector("#largeiteminfo_item_actions > a");
  1429. if (aImg != null)
  1430. {
  1431. var img = aImg.href;
  1432. if (/\.jpg$/i.test(img))
  1433. {
  1434. var urlPreview = ownerUrl + "?previewbg=" + img;
  1435.  
  1436. var a = document.createElement("a");
  1437. a.classList.add("btn_small");
  1438. a.classList.add("btn_grey_white_innerfade");
  1439. a.setAttribute("target", "_blank");
  1440. a.href = urlPreview;
  1441. a.innerHTML = '<span>Preview in Profile</span>';
  1442. aImg.parentElement.appendChild(a);
  1443. }
  1444. }
  1445. }
  1446. }
  1447. }
  1448. function linkMarketToBadgeAttach()
  1449. {
  1450. var url = document.documentURI;
  1451. var patt = /^http[s]?:\/\/steamcommunity.com\/market\/listings\/753\/[0-9]+/i;
  1452.  
  1453. if (patt.test(url) && !isErrorMarket())
  1454. {
  1455. attachOnLoad(linkMarketToBadge);
  1456. }
  1457. }
  1458. if (enableLinkMarketToBadge) linkMarketToBadgeAttach();
  1459.  
  1460. /** Add price of each cards in Badge page and link to Market page
  1461. */
  1462. function linkBadgeToMarket()
  1463. {
  1464. GM_addStyle(
  1465. ".div_market_price { float: right; } " // padding-top: 1px; display: inline-block; padding-left: 90px;
  1466. + ".gamecard_badge_craftbtn_ctn .badge_craft_button { width: 160px !important; } "
  1467. );
  1468.  
  1469. var url = document.documentURI;
  1470.  
  1471. var pattAppHead = /^http[s]?:\/\/steamcommunity.com\/(id|profiles)\/[^\/]+\/gamecards\//i;
  1472. var pattAppTail = /[^0-9]+.*/i;
  1473. var app = url.replace(pattAppHead, "").replace(pattAppTail, "");
  1474. var isFoil = url.indexOf("border=1") > -1;
  1475. var urlExternal = "http://www.steamcardexchange.net/index.php?gamepage-appid-" + app;
  1476. var urlMarket = "http://steamcommunity.com/market/listings/753/";
  1477.  
  1478. var priceCards = new Array();
  1479. var priceUrls = new Array();
  1480.  
  1481. updatePrice();
  1482.  
  1483. var isCacheExpire = checkCacheExpire(app);
  1484. if (isCacheExpire || !enableCache)
  1485. {
  1486. setTimeout(function ()
  1487. {
  1488. GM_xmlhttpRequest({
  1489. method: "GET",
  1490. url: urlExternal,
  1491. onload: getExternalPrice,
  1492. });
  1493. }, 0);
  1494. }
  1495.  
  1496. function getExternalPrice(res)
  1497. {
  1498. try
  1499. {
  1500. var pattNumCard = /Card [0-9]+ of /i;
  1501. var pattMarket = /^http[s]?:\/\/steamcommunity.com\/market\/listings\/753\//i;
  1502. var pattPrice = /(Price: |Last seen: )/i;
  1503.  
  1504. var aOwner = document.querySelector("#global_actions > a.user_avatar");
  1505. var isLoggedIn = aOwner != null;
  1506. var ownerUrl = isLoggedIn ? aOwner.href.substr(0, aOwner.href.length - 1) : "http://steamcommunity.com/my";
  1507.  
  1508. var aFriend = document.querySelector(".profile_small_header_name > a");
  1509. var isFriendExist = aFriend != null;
  1510. var friendUrl = isFriendExist ? aFriend.href : "http://steamcommunity.com/my";
  1511. var friendName = isFriendExist ? aFriend.textContent.trim() : "my"
  1512. var friendNameOwner = isFriendExist ? friendName + "'s" : friendName;
  1513.  
  1514. var isOwner = isLoggedIn && ownerUrl == friendUrl;
  1515.  
  1516. var divTempID = randTempID();
  1517. createDivTemp(divTempID, res.responseText);
  1518. try
  1519. {
  1520. //debug("ID: "+divTempID);
  1521. var divTemp = document.getElementById(divTempID);
  1522. var numCard = 0;
  1523. try
  1524. {
  1525. var spanNumber = divTemp.getElementsByClassName("element-count")[0];
  1526. if (spanNumber == null)
  1527. {
  1528. debug("Warning: can't get price");
  1529. return;
  1530. }
  1531. numCard = parseInt(spanNumber.textContent.replace(pattNumCard, ""));
  1532. }
  1533. catch (e)
  1534. {
  1535. debug("Ex: " + e);
  1536. }
  1537.  
  1538. var offsetCard = isFoil ? numCard : 0;
  1539. var curCard = 0;
  1540.  
  1541. var isCacheExpire = checkCacheExpire(app);
  1542.  
  1543. priceCards = new Array();
  1544. priceUrls = new Array();
  1545.  
  1546. var as = divTemp.getElementsByClassName("button-blue");
  1547. for (var i = 0; i < as.length; i++)
  1548. {
  1549. if (pattMarket.test(as[i].href))
  1550. {
  1551. if (curCard < numCard * 2)
  1552. {
  1553. var cPrice = as[i].textContent.replace(pattPrice, "").trim();
  1554. var cUrl = as[i].href.replace(urlMarket, "");
  1555.  
  1556. var indexCard = curCard - offsetCard;
  1557. if (indexCard >= 0 && indexCard < numCard)
  1558. {
  1559. priceCards[indexCard] = cPrice;
  1560. priceUrls[indexCard] = cUrl;
  1561. }
  1562.  
  1563. // cache
  1564. if (enableCache && isCacheExpire)
  1565. {
  1566. setCacheTime(app);
  1567. if (curCard < numCard)
  1568. {
  1569. setCachePrice(app, false, curCard, cPrice);
  1570. setCacheUrl(app, false, curCard, cUrl);
  1571. }
  1572. else // foil
  1573. {
  1574. setCachePrice(app, true, curCard - numCard, cPrice);
  1575. setCacheUrl(app, true, curCard - numCard, cUrl);
  1576. }
  1577. }
  1578.  
  1579. curCard += 1;
  1580. }
  1581. else
  1582. {
  1583. break;
  1584. }
  1585. }
  1586. }
  1587. }
  1588. catch (e)
  1589. {
  1590. debug("Ex: " + e);
  1591. }
  1592. removeDivTemp(divTempID);
  1593.  
  1594. updatePrice();
  1595.  
  1596. debugTime("getExternalPrice");
  1597. }
  1598. catch (e)
  1599. {
  1600. debug("Ex: " + e);
  1601. }
  1602. }
  1603.  
  1604. function updatePrice()
  1605. {
  1606. var pattNum = /[0-9\.]+/;
  1607. var colorUp = "#CC0000";
  1608. var colorDown = "#009900";
  1609.  
  1610. if (enableCache)
  1611. {
  1612. priceCards = new Array();
  1613. priceUrls = new Array();
  1614.  
  1615. for (var i = 0; i < 15; i++)
  1616. {
  1617. var p = getCachePrice(app, isFoil, i);
  1618. var u = getCacheUrl(app, isFoil, i);
  1619. if (p != 0 && u != 0)
  1620. {
  1621. priceCards[i] = p;
  1622. priceUrls[i] = u;
  1623. }
  1624. else
  1625. {
  1626. break;
  1627. }
  1628. }
  1629. }
  1630.  
  1631. var texts = document.getElementsByClassName("badge_card_set_card");
  1632. var numCard = texts.length;
  1633. var priceSet = 0;
  1634.  
  1635. for (var j = 0; j < texts.length; j++)
  1636. {
  1637. var pUrl = priceUrls[j] ? urlMarket + priceUrls[j] : "";
  1638. var pCard = priceCards[j] ? priceCards[j] : "-";
  1639. var pOnClick = priceCards[j] ? "" : " onclick='return false;' ";
  1640. var pDiff = "";
  1641. var pCardOld = "";
  1642.  
  1643. var divTexts = texts[j].querySelectorAll("div.badge_card_set_text");
  1644. var divText = divTexts[divTexts.length - 1];
  1645. var divMarkets = texts[j].getElementsByClassName("div_market_price");
  1646. var divMarket;
  1647. if (divMarkets.length == 0)
  1648. {
  1649. divMarket = document.createElement("div");
  1650. divMarket.classList.add("div_market_price");
  1651. //divMarket.classList.add("badge_card_set_text_qty");
  1652. divText.appendChild(divMarket);
  1653.  
  1654. var divClear = document.createElement("div");
  1655. divClear.style.clear = "right";
  1656. divText.appendChild(divClear);
  1657.  
  1658. divText.style.whiteSpace = "normal";
  1659. }
  1660. else
  1661. {
  1662. divMarket = divMarkets[0];
  1663. var as = divMarket.getElementsByTagName("a");
  1664. if (as.length > 0)
  1665. {
  1666. var pOld = as[0].textContent;
  1667. var pValOld = pOld.match(pattNum);
  1668. if (pValOld != null)
  1669. {
  1670. //debug("oldPrice[" + j + "]: "+ pValOld);
  1671.  
  1672. pCardOld = "title='Cache Price: " + pOld + "'";
  1673.  
  1674. var pVal = pCard.match(pattNum);
  1675. pVal = pVal ? pVal : 0;
  1676.  
  1677. priceSet += parseFloat(pVal);
  1678.  
  1679. var pValDiff = (parseFloat(pVal) - parseFloat(pValOld)).toFixed(2);
  1680. if(pValDiff > 0)
  1681. {
  1682. pDiff = "<span style='cursor: help; color: " + colorUp + ";' "
  1683. + pCardOld + ">+" + pValDiff + "</span>";
  1684. }
  1685. else if (pValDiff < 0)
  1686. {
  1687. pDiff = "<span style='cursor: help; color: " + colorDown + ";' "
  1688. + pCardOld + ">" + pValDiff + "</span>";
  1689. }
  1690. else
  1691. {
  1692. pCardOld = "";
  1693. }
  1694. }
  1695. }
  1696. }
  1697.  
  1698. divMarket.innerHTML = pDiff + " <a href='" + pUrl + "' " + pOnClick + " title='Lowest Price'>" + pCard + "</a>";
  1699. } // end for
  1700.  
  1701. if (priceSet > 0)
  1702. {
  1703. debug("priceSet: " + priceSet);
  1704. }
  1705. }
  1706. }
  1707. function linkBadgeToMarketAttach()
  1708. {
  1709. var url = document.documentURI;
  1710. var patt = /^http[s]?:\/\/steamcommunity.com\/(id|profiles)\/[^\/]+\/gamecards\/[0-9]+/i;
  1711.  
  1712. if (patt.test(url) && !isErrorCard())
  1713. {
  1714. attachOnLoad(linkBadgeToMarket);
  1715. }
  1716. }
  1717. if (enableLinkBadgeToMarket) linkBadgeToMarketAttach();
  1718.  
  1719. /** Compare my cards and friend's cards in Badge page
  1720. * Mark color of my cards count (Green) and friend's cards count (Blue)
  1721. */
  1722. function compareBadge()
  1723. {
  1724. var url = document.documentURI;
  1725.  
  1726. var pattAppHead = /^http[s]?:\/\/steamcommunity.com\/(id|profiles)\/[^\/]+\/gamecards\//i;
  1727. var pattAppTail = /[^0-9]+.*/i;
  1728. var app = url.replace(pattAppHead, "").replace(pattAppTail, "");
  1729.  
  1730. {
  1731. try
  1732. {
  1733. var pattNumCard = /Card [0-9]+ of /i;
  1734. var pattMarket = /^http[s]?:\/\/steamcommunity.com\/market\/listings\/753\//i;
  1735. var pattPrice = /Price: /i;
  1736.  
  1737. var isFoil = url.indexOf("border=1") > -1;
  1738.  
  1739. var aOwner = document.querySelector("#global_actions > a.user_avatar");
  1740. var isLoggedIn = aOwner != null;
  1741. var ownerUrl = isLoggedIn ? aOwner.href.substr(0, aOwner.href.length - 1) : "http://steamcommunity.com/my";
  1742.  
  1743. var aFriend = document.querySelector(".profile_small_header_name > a");
  1744. var isFriendExist = aFriend != null;
  1745. var friendUrl = isFriendExist ? aFriend.href : "http://steamcommunity.com/my";
  1746. var friendName = isFriendExist ? aFriend.textContent.trim() : "my"
  1747. var friendNameOwner = isFriendExist ? friendName + "'s" : friendName;
  1748.  
  1749. var isOwner = isLoggedIn && ownerUrl == friendUrl;
  1750.  
  1751. //debug("ownerUrl: "+ownerUrl);
  1752. //debug("friendUrl: "+friendUrl);
  1753.  
  1754. var texts = document.getElementsByClassName("badge_card_set_card");
  1755. var numCard = texts.length;
  1756.  
  1757. //debug("isOwner: "+isOwner);
  1758. //debug("numCard: "+numCard);
  1759.  
  1760. for (var j = 0; j < numCard; j++)
  1761. {
  1762. var divQty = texts[j].querySelector("div.badge_card_set_text_qty");
  1763. var numQty = "(0)";
  1764. if (divQty != null)
  1765. {
  1766. numQty = divQty.textContent.trim();
  1767. }
  1768. else
  1769. {
  1770. divQty = document.createElement("div");
  1771. divQty.classList.add("badge_card_set_text_qty");
  1772. divQty.innerHTML = numQty;
  1773.  
  1774. var divCtn = texts[j].querySelector("div.game_card_ctn");
  1775. if (divCtn != null)
  1776. {
  1777. var divTexts = texts[j].querySelectorAll("div.badge_card_set_text");
  1778. if (divTexts.length < 2)
  1779. {
  1780. texts[j].insertBefore(divQty, divCtn.nextSibling);
  1781. }
  1782. else
  1783. {
  1784. divTexts[0].insertBefore(divQty, divTexts[0].firstChild);
  1785. }
  1786. }
  1787. }
  1788. //debug("numQty: "+numQty);
  1789. } // end for
  1790.  
  1791. var colorOwner = "#8CBE0F";
  1792. var colorFriend = "#5491CF";
  1793. var colorZeroOwner = "#557309";
  1794. var colorZeroFriend = "#355C82";
  1795.  
  1796. var countCardAll = 0;
  1797.  
  1798. var divQtys = document.querySelectorAll("div.badge_card_set_text_qty");
  1799. for (var k = 0; k < divQtys.length; k++)
  1800. {
  1801. var num = divQtys[k].textContent.trim().replace(/[\(\)]/gi, "");
  1802. countCardAll += parseInt(num);
  1803.  
  1804. divQtys[k].innerHTML = "";
  1805.  
  1806. var spanNum = document.createElement("span");
  1807. spanNum.classList.add("span_card_qty");
  1808. spanNum.style.cursor = "help";
  1809. spanNum.innerHTML = " (" + num + ") ";
  1810. divQtys[k].insertBefore(spanNum, null);
  1811.  
  1812. if (isOwner)
  1813. {
  1814. spanNum.classList.add("span_card_qty_owner");
  1815. spanNum.style.color = num > "0" ? colorOwner : colorZeroOwner;
  1816. spanNum.title = "My cards: " + num;
  1817. }
  1818. else
  1819. {
  1820. spanNum.classList.add("span_card_qty_friend");
  1821. spanNum.style.color = num > "0" ? colorFriend : colorZeroFriend;
  1822. spanNum.title = friendNameOwner + " cards: " + num;
  1823. }
  1824. }
  1825.  
  1826. debug("countCard: " + countCardAll);
  1827. debug("maxSet: " + parseInt(countCardAll / numCard));
  1828.  
  1829. if (!isOwner)
  1830. {
  1831. var pattProfile = /^http[s]?:\/\/steamcommunity.com\/(id|profiles)\/[^\/]*/i;
  1832. var urlExternal = url.replace(pattProfile, ownerUrl);
  1833. //debug("urlExternal: "+urlExternal);
  1834.  
  1835. setTimeout(function ()
  1836. {
  1837. GM_xmlhttpRequest({
  1838. method: "GET",
  1839. url: urlExternal,
  1840. onload: compareCard,
  1841. });
  1842. }, 0);
  1843.  
  1844. function compareCard(res)
  1845. {
  1846. var divTempID = randTempID();
  1847. createDivTemp(divTempID, res.responseText);
  1848. try
  1849. {
  1850. //debug("ID: "+divTempID);
  1851. var divTemp = document.getElementById(divTempID);
  1852.  
  1853. var owner_texts = divTemp.getElementsByClassName("badge_card_set_card");
  1854. var owner_numCard = owner_texts.length;
  1855.  
  1856. if (numCard == owner_numCard)
  1857. {
  1858. var owner_numQtys = new Array();
  1859.  
  1860. for (var i = 0; i < owner_texts.length; i++)
  1861. {
  1862. var owner_divQty = owner_texts[i].querySelector("div.badge_card_set_text_qty");
  1863. if (owner_divQty != null)
  1864. {
  1865. owner_numQtys[i] = owner_divQty.textContent.trim().replace(/[\(\)]/gi, "");
  1866. }
  1867. else
  1868. {
  1869. owner_numQtys[i] = "0";
  1870. }
  1871. //debug("owner_numQtys[i]: "+owner_numQtys[i]);
  1872. } // end for
  1873.  
  1874. var friend_divQtys = document.querySelectorAll("div.badge_card_set_text_qty");
  1875. for (var k = 0; k < friend_divQtys.length; k++)
  1876. {
  1877. var owner_spanNum = friend_divQtys[k].querySelector("span_card_qty_owner");
  1878. if (owner_spanNum == null)
  1879. {
  1880. owner_spanNum = document.createElement("span");
  1881. owner_spanNum.classList.add("span_card_qty");
  1882. owner_spanNum.style.cursor = "help";
  1883. owner_spanNum.classList.add("span_card_qty_owner");
  1884. owner_spanNum.style.color = owner_numQtys[k] > "0" ? colorOwner : colorZeroOwner;
  1885. owner_spanNum.title = "My cards: " + owner_numQtys[k];
  1886. friend_divQtys[k].insertBefore(owner_spanNum, friend_divQtys[k].firstChild);
  1887. }
  1888. owner_spanNum.innerHTML = " (" + owner_numQtys[k] + ") ";
  1889. }
  1890. }
  1891. }
  1892. catch (e)
  1893. {
  1894. debug("Ex: " + e);
  1895. }
  1896. removeDivTemp(divTempID);
  1897. debugTime("compareBadge");
  1898. }
  1899. }
  1900. }
  1901. catch (e)
  1902. {
  1903. debug("Ex: " + e);
  1904. }
  1905. }
  1906.  
  1907. // Add clickable card name
  1908. {
  1909. GM_addStyle(
  1910. " .sbh_cardName { color: #999; } "
  1911. );
  1912.  
  1913. var eleTexts = document.querySelectorAll(".badge_card_set_card");
  1914. for (var i = 0; i < eleTexts.length; i++)
  1915. {
  1916. var eleText = eleTexts[i].querySelector(".badge_card_set_text");
  1917. for (var j = 0; j < eleText.childNodes.length; j++)
  1918. {
  1919. if (eleText.childNodes[j].nodeName == "#text")
  1920. {
  1921. var text = eleText.childNodes[j].textContent.trim();
  1922. if (text != "")
  1923. {
  1924. var eleSpan = document.createElement("div");
  1925. eleSpan.classList.add("sbh_cardName");
  1926. eleSpan.textContent = text;
  1927. eleText.replaceChild(eleSpan, eleText.childNodes[j]);
  1928.  
  1929. eleSpan.addEventListener("click", function (e)
  1930. {
  1931. var ele = e.target;
  1932. clickToSelect(ele);
  1933. });
  1934.  
  1935. j = eleText.childNodes.length;
  1936. }
  1937. }
  1938. }
  1939. }
  1940. }
  1941. }
  1942. function compareBadgeAttach()
  1943. {
  1944. var url = document.documentURI;
  1945. var patt = /^http[s]?:\/\/steamcommunity.com\/(id|profiles)\/[^\/]+\/gamecards\/[0-9]+/i;
  1946.  
  1947. if (patt.test(url) && !isErrorCard())
  1948. {
  1949. attachOnLoad(compareBadge);
  1950. }
  1951. }
  1952. if (enableCompareBadge) compareBadgeAttach();
  1953.  
  1954. /** Link items in inventory to store and badge page
  1955. */
  1956. function linkInventoryToBadge()
  1957. {
  1958. if (isError())
  1959. return;
  1960.  
  1961. GM_addStyle
  1962. (
  1963. " .view_inventory_page .item.activeInfo "
  1964. + "{ background-image: none !important; background-color: #9B9B9B !important; border: 1px solid #C9C9C9; } "
  1965. + " .descriptor { max-height: 100px; overflow-y: auto; } "
  1966. + " .inventory_iteminfo .item_desc_content { padding-top: 225px !important; padding-bottom: 0px !important; }"
  1967. );
  1968. if (getQueryByName("modal") == "1")
  1969. {
  1970. GM_addStyle
  1971. (
  1972. " .inventory_page_left { padding-bottom: 400px; } "
  1973. + " .descriptor, .item_scrap_actions { display: none; } "
  1974. + " #market_sell_dialog_accept > span { line-height: 30px; } "
  1975. + " #market_sell_dialog_confirm_buttons > .market_dialog_bottom_buttons { margin-top: 110px; } "
  1976. + " #market_sell_dialog_ok { min-width: 150px; } "
  1977. );
  1978. }
  1979. }
  1980. function linkInventoryToBadgeAttach()
  1981. {
  1982. var url = document.documentURI;
  1983. var patt = /^http[s]?:\/\/steamcommunity.com\/(id|profiles)\/[^\/]+\/inventory/i;
  1984.  
  1985. if (patt.test(url))
  1986. {
  1987. attachOnLoad(linkInventoryToBadge);
  1988. }
  1989. }
  1990. if (enableLinkInventoryToBadge) linkInventoryToBadgeAttach();
  1991.  
  1992. function editTitle()
  1993. {
  1994. try
  1995. {
  1996. var titleOld = document.title;
  1997. var titleNew = titleOld;
  1998. var titleNoti = "";
  1999. var pattSale = /[0-9]+%/i;
  2000. var intervalTitle = null;
  2001.  
  2002. if (enableSwapTitle)
  2003. {
  2004. var splitSpace = titleOld.split(" ");
  2005. if (splitSpace.length > 1)
  2006. {
  2007. if (pattSale.test(splitSpace[1]))
  2008. {
  2009. splitSpace.splice(0, 1);
  2010. splitSpace.splice(1, 1);
  2011. titleOld = splitSpace.join(" ");
  2012. }
  2013. }
  2014. var split = titleOld.split("::").reverse();
  2015. for (var i = 0; i < split.length; i++)
  2016. {
  2017. split[i] = split[i].trim();
  2018. }
  2019. titleNew = split.join(" :: ");
  2020. document.title = titleNew;
  2021. }
  2022.  
  2023. var divH = document.querySelector("#header_notification_area");
  2024. if (divH != null)
  2025. {
  2026. divH.addEventListener('mouseover', function() {
  2027. clearInterval(intervalTitle);
  2028. document.title = titleNew;
  2029. });
  2030. }
  2031.  
  2032. if (enableShowTitleNoti)
  2033. {
  2034. function updateTitleNoti()
  2035. {
  2036. var noti = document.querySelector("#header_notification_link");
  2037. if (noti != null)
  2038. {
  2039. var notiNum = noti.textContent.trim();
  2040. if (notiNum != "" && notiNum != "0")
  2041. {
  2042. //debug("updateTitleNoti: "+notiNum);
  2043. titleNoti = "("+notiNum+") ";
  2044. }
  2045. else
  2046. {
  2047. titleNoti = "";
  2048. }
  2049. if (document.title != titleNoti + titleNew)
  2050. {
  2051. //debug("changeTitle: "+notiNum);
  2052. document.title = titleNoti + titleNew;
  2053. }
  2054. }
  2055. }
  2056.  
  2057. intervalTitle = setInterval(updateTitleNoti, 1000);
  2058.  
  2059. {
  2060. /*
  2061. var timeoutID = -1;
  2062.  
  2063. noti.addEventListener("DOMSubtreeModified", function (e) {
  2064. debug("DOMSubtreeModified");
  2065. try
  2066. {
  2067. clearTimeout(timeoutID);
  2068. }
  2069. catch (ex)
  2070. {
  2071. }
  2072. updateTitleNoti();
  2073. });
  2074.  
  2075. noti.addEventListener("DOMNodeInserted", function (e) {
  2076. debug("DOMNodeInserted");
  2077. try
  2078. {
  2079. clearTimeout(timeoutID);
  2080. }
  2081. catch (ex)
  2082. {
  2083. }
  2084. updateTitleNoti();
  2085. });
  2086.  
  2087. noti.addEventListener("DOMNodeRemoved", function (e) {
  2088. debug("DOMNodeRemoved");
  2089. timeoutID = setTimeout(updateTitleNoti,100);
  2090. });
  2091. */
  2092. }
  2093. }
  2094. }
  2095. catch (ex)
  2096. {
  2097. debug("editTitle: "+ex);
  2098. }
  2099. }
  2100. function editTitleAttach()
  2101. {
  2102. attachOnReady(editTitle);
  2103. }
  2104. if (enableSwapTitle || enableShowTitleNoti) editTitleAttach();
  2105.  
  2106. /** Resize trade window that is larger than 768px
  2107. */
  2108. function resizeTradeWindow()
  2109. {
  2110. if (window.innerHeight < 800)
  2111. {
  2112. //GM_addStyle("#mainContent { transform: scale(0.8, 0.8); transform-origin: 50% 0px 0px; }");
  2113.  
  2114. if (window.innerWidth > 1000)
  2115. {
  2116. //window.resizeBy(-240,0);
  2117. //window.moveBy(200,0);
  2118. }
  2119. }
  2120.  
  2121. var ele = document.querySelector("#trade_escrow_header, .trade_partner_info_block");
  2122. if (ele != null)
  2123. {
  2124. ele.scrollIntoView();
  2125. }
  2126.  
  2127. // Fix blank box in Firefox
  2128. {
  2129. setInterval(function ()
  2130. {
  2131. if (isVisible())
  2132. {
  2133. var ele = document.querySelector("#inventory_displaycontrols");
  2134. if (ele != null)
  2135. {
  2136. if (ele.offsetHeight > 200)
  2137. {
  2138. if (ele.style.float != "left")
  2139. {
  2140. ele.style.float = "left";
  2141. }
  2142. }
  2143. else
  2144. {
  2145. if (ele.style.float != "")
  2146. {
  2147. ele.style.float = "";
  2148. }
  2149. }
  2150. }
  2151. }
  2152. }, 1000);
  2153. }
  2154. }
  2155. function resizeTradeWindowAttach(tm)
  2156. {
  2157. var url = document.documentURI;
  2158. var patt = /^http[s]?:\/\/steamcommunity.com\/(tradeoffer|trade)\//i;
  2159.  
  2160. if (patt.test(url))
  2161. {
  2162. attachOnLoad(function ()
  2163. {
  2164. setTimeout(resizeTradeWindow, tm);
  2165. });
  2166. }
  2167. }
  2168. if (enableResizeTradeWindow) resizeTradeWindowAttach(100);
  2169.  
  2170. /** Add link in profile page
  2171. */
  2172. function linkProfile()
  2173. {
  2174. GM_addStyle(".achievement_progress_bar_ctn { width: 118px; margin-left: 4px; } ");
  2175.  
  2176. var aOwner = document.querySelector("#global_actions > a.user_avatar");
  2177. var isLoggedIn = aOwner != null;
  2178. var url = document.documentURI;
  2179. var urlOwner = url;
  2180.  
  2181. if (urlOwner[urlOwner.length-1] != "/")
  2182. {
  2183. urlOwner = urlOwner + "/";
  2184. }
  2185.  
  2186. var urlName = urlOwner + "namehistory/";
  2187. var urlPost = urlOwner + "posthistory/";
  2188. var labelName = "Name History";
  2189. var labelPost = "Post History";
  2190. var arrUrl = ["", urlName, urlPost];
  2191. var arrLbl = ["", labelName, labelPost];
  2192.  
  2193. var divOuter = document.querySelector(".profile_item_links");
  2194. if (divOuter != null)
  2195. {
  2196. for (var i = 0; i < arrUrl.length; i++)
  2197. {
  2198. var div = document.createElement("div");
  2199. if (div != null)
  2200. {
  2201. div.className = "profile_count_link";
  2202. div.innerHTML = '<a href="' + arrUrl[i] + '"><span class="count_link_label">'
  2203. + arrLbl[i] + '</span> <span class="profile_count_link_total"> </span></a>';
  2204.  
  2205. divOuter.appendChild(div);
  2206. }
  2207. }
  2208. }
  2209.  
  2210. // preview bg in profile
  2211. function previewBg()
  2212. {
  2213. var bg = getQueryByName("previewbg");
  2214. if (bg != "")
  2215. {
  2216. var divBg = document.querySelector("div.has_profile_background");
  2217. if (divBg != null)
  2218. {
  2219. divBg.style.backgroundImage = "url('" + bg + "')";
  2220. }
  2221.  
  2222. var divBgIn = document.querySelector("div.profile_background_image_content");
  2223. if (divBgIn != null)
  2224. {
  2225. divBgIn.style.backgroundImage = "url('" + bg + "')";
  2226. }
  2227. }
  2228. }
  2229. attachOnLoad(previewBg);
  2230. // Focus profile
  2231. if (isLoggedIn)
  2232. {
  2233. var eleTarget = document.querySelector(".no_header");
  2234. if (eleTarget != null)
  2235. {
  2236. eleTarget.scrollIntoView();
  2237. }
  2238. }
  2239. }
  2240. function linkProfileReady()
  2241. {
  2242. var url = document.documentURI;
  2243. var patt = /^http[s]?:\/\/steamcommunity.com\/(id|profiles)\/[^\/]+(\/?\?.*)?\/?$/i;
  2244.  
  2245. if (patt.test(url))
  2246. {
  2247. attachOnReady(linkProfile);
  2248. }
  2249. }
  2250. if (enableLinkProfile) linkProfileReady();
  2251.  
  2252. /** Set all checkbox to checked
  2253. */
  2254. function setAllCheckBox()
  2255. {
  2256. var eles = document.querySelectorAll("#market_buynow_dialog_accept_ssa"
  2257. + ", #market_sell_dialog_accept_ssa, #accept_ssa, #verify_country_only, #market_buyorder_dialog_accept_ssa");
  2258. for (var i = 0; i < eles.length; i++)
  2259. {
  2260. eles[i].checked = true;
  2261. }
  2262. }
  2263. function setAllCheckBoxReady()
  2264. {
  2265. var url = document.documentURI;
  2266. var pattMarket = /^http[s]?:\/\/steamcommunity.com\/market\/listings\/[0-9]+/i;
  2267. var pattInv = /^http[s]?:\/\/steamcommunity.com\/(id|profiles)\/[^\/]+\/inventory/i;
  2268. var pattCart = /^http[s]?:\/\/store.steampowered.com\/checkout/i;
  2269.  
  2270. if (pattMarket.test(url) || pattInv.test(url) || pattCart.test(url))
  2271. {
  2272. attachOnReady(setAllCheckBox);
  2273. }
  2274. }
  2275. if (enableSetAllCheckBox) setAllCheckBoxReady();
  2276.  
  2277. /** Scroll store page to easy view
  2278. */
  2279. function storeFocus()
  2280. {
  2281. // Store focus
  2282. {
  2283. var eleAccount = document.querySelector("#account_pulldown");
  2284. if (eleAccount != null)
  2285. {
  2286. var divHead = document.querySelector(".breadcrumbs > .blockbg, "
  2287. + " .breadcrumbs > a, div.auction_block:nth-child(1), .market_listing_nav > a");
  2288. if (divHead != null)
  2289. {
  2290. divHead.scrollIntoView();
  2291. }
  2292. }
  2293. }
  2294.  
  2295. // Click to select app name
  2296. {
  2297. var eleName = document.querySelector(".apphub_AppName, .pageheader");
  2298. if (eleName != null)
  2299. {
  2300. eleName.addEventListener("click", function (e)
  2301. {
  2302. var ele = e.target;
  2303. clickToSelect(ele);
  2304. });
  2305. }
  2306. }
  2307. }
  2308. function storeFocusAttach()
  2309. {
  2310. var url = document.documentURI;
  2311. var patt = /^http[s]?:\/\/(store.steampowered.com\/(app|sub)\/|steamcommunity.com\/(auction\/item\/|sharedfiles\/filedetails\/\?id=|market\/listings\/))/i;
  2312.  
  2313. if (patt.test(url))
  2314. {
  2315. attachOnReady(storeFocus);
  2316. }
  2317. }
  2318. if (enableStoreFocus) storeFocusAttach();
  2319.  
  2320. function autoExploreQueue()
  2321. {
  2322. var url = document.documentURI;
  2323. var pattApp = /^http[s]?:\/\/store.steampowered.com\/app/i;
  2324. var pattExplore = /^http[s]?:\/\/store.steampowered.com\/explore/i;
  2325.  
  2326. // Auto explore queue in app
  2327. if (pattApp.test(url))
  2328. {
  2329. GM_addStyle(
  2330. " .sbh_autoQueueOption { float: right; padding-right: 3px; } "
  2331. + " #sbh_autoQueue { vertical-align: text-top; } "
  2332. );
  2333.  
  2334. // Clean url in next queue
  2335. {
  2336. var eleQueue = document.querySelector("#next_in_queue_form");
  2337. if (eleQueue != null)
  2338. {
  2339. var action = eleQueue.getAttribute("action");
  2340. if (action[action.length] != "/")
  2341. {
  2342. action += "/";
  2343. eleQueue.setAttribute("action", action);
  2344. }
  2345. }
  2346. }
  2347. function autoQueue()
  2348. {
  2349. var tm = 3000;
  2350. debug("AutoQueue: Next in " + tm + "ms");
  2351. setTimeout(function ()
  2352. {
  2353. var eleCheck = document.querySelector("#sbh_autoQueue");
  2354. if (eleCheck != null && eleCheck.checked)
  2355. {
  2356. var ele = document.querySelector(".btn_next_in_queue");
  2357. if (ele != null)
  2358. {
  2359. GM_setValue("storeAutoQueueLast", getUnixTimestamp());
  2360. ele.click();
  2361. }
  2362. }
  2363. }, tm);
  2364. }
  2365.  
  2366. var eleDes = document.querySelector(".queue_controls_description");
  2367. if (eleDes != null)
  2368. {
  2369. var eleSpan = document.createElement("span");
  2370. eleSpan.classList.add("sbh_autoQueueOption");
  2371.  
  2372. var eleInput = document.createElement("input");
  2373. eleInput.id = "sbh_autoQueue";
  2374. eleInput.setAttribute("type", "checkbox");
  2375. eleInput.setAttribute("value", "auto");
  2376.  
  2377. if (GM_getValue("storeAutoQueue", 0) == "true")
  2378. {
  2379. eleInput.checked = true;
  2380.  
  2381. var ele = document.querySelector(".btn_next_in_queue");
  2382. if (ele != null)
  2383. {
  2384. autoQueue();
  2385. }
  2386. }
  2387.  
  2388. eleInput.addEventListener("click", function (e)
  2389. {
  2390. var ele = e.target;
  2391. if (ele.checked)
  2392. {
  2393. GM_setValue("storeAutoQueue", "true");
  2394. autoQueue();
  2395. }
  2396. else
  2397. {
  2398. GM_setValue("storeAutoQueue", "false");
  2399. }
  2400. });
  2401.  
  2402. var eleLabel = document.createElement("label");
  2403. eleLabel.setAttribute("for", "sbh_autoQueue");
  2404. eleLabel.textContent = " Auto Explore Queue";
  2405.  
  2406. eleSpan.appendChild(eleInput);
  2407. eleSpan.appendChild(eleLabel);
  2408. eleDes.appendChild(eleSpan);
  2409. }
  2410. else
  2411. {
  2412. // Session lost
  2413. if (GM_getValue("storeAutoQueue", 0) == "true")
  2414. {
  2415. var aOwner = document.querySelector("#global_actions > .user_avatar");
  2416. var isLoggedIn = aOwner != null;
  2417. if (!isLoggedIn)
  2418. {
  2419. // Auto reload every 10s within 2 minutes
  2420. var tmExpireShort = 120;
  2421. var tmReloadShort = 10000;
  2422. // Auto reload every 30s within 10 minutes
  2423. var tmExpireLong = 600;
  2424. var tmReloadLong = 30000;
  2425. var tmReload = 0;
  2426. var tmDiff = getUnixTimestamp() - GM_getValue("storeAutoQueueLast", 0);
  2427. if (tmDiff < tmExpireShort)
  2428. {
  2429. tmReload = tmReloadShort;
  2430. }
  2431. else if (tmDiff < tmReloadLong)
  2432. {
  2433. tmReload = tmExpireLong;
  2434. }
  2435. if (tmReload > 0)
  2436. {
  2437. debug("AutoQueue: Refresh in " + tmReload + "ms");
  2438. setTimeout(reload, tmReload);
  2439. }
  2440. }
  2441. }
  2442. }
  2443. }
  2444.  
  2445. // Auto explore queue in explore
  2446. if (pattExplore.test(url))
  2447. {
  2448. if (GM_getValue("storeAutoQueue", 0) == "true")
  2449. {
  2450. var eleText = document.querySelector(".subtext");
  2451. if (eleText != null && /[0-9]/.test(eleText.textContent.trim()))
  2452. {
  2453. setTimeout(function ()
  2454. {
  2455. var ele = document.querySelector("#refresh_queue_btn");
  2456. if (ele != null)
  2457. {
  2458. ele.click();
  2459. }
  2460. }, 3000);
  2461. }
  2462. }
  2463.  
  2464. }
  2465. }
  2466. function autoExploreQueueAttach()
  2467. {
  2468. var url = document.documentURI;
  2469. var patt = /^http[s]?:\/\/store.steampowered.com\/(app|explore)/i;
  2470.  
  2471. if (patt.test(url))
  2472. {
  2473. // Fix for slow connection
  2474. var didAutoExploreQueue = false;
  2475. var attemptAutoExploreQueue = 0;
  2476. var tmAutoExploreQueue = setInterval(function()
  2477. {
  2478. console.log("AutoQueue: Slow connection");
  2479. didAutoExploreQueue = true;
  2480. autoExploreQueue();
  2481. if (document.querySelector("#sbh_autoQueue") != null)
  2482. {
  2483. clearInterval(tmAutoExploreQueue);
  2484. }
  2485. else
  2486. {
  2487. if (attemptAutoExploreQueue > 10)
  2488. {
  2489. console.log("AutoQueue: Auto refresh from slow connection");
  2490. reload();
  2491. }
  2492. attemptAutoExploreQueue++;
  2493. }
  2494. }, 5000);
  2495. attachOnReady(function()
  2496. {
  2497. if (!didAutoExploreQueue || document.querySelector("#sbh_autoQueue") == null)
  2498. {
  2499. clearInterval(tmAutoExploreQueue);
  2500. autoExploreQueue();
  2501. }
  2502. });
  2503. }
  2504. }
  2505. if (enableAutoExploreQueue) autoExploreQueueAttach();
  2506.  
  2507. function skipAgeCheck()
  2508. {
  2509. setTimeout(function ()
  2510. {
  2511. var ele = document.querySelector(".btns.agegate_text_container > a");
  2512. if (ele != null)
  2513. {
  2514. ele.click();
  2515. }
  2516. }, 3000);
  2517. }
  2518. function skipAgeCheckAttach()
  2519. {
  2520. var url = document.documentURI;
  2521. var patt = /^http[s]?:\/\/store.steampowered.com\/app\/[0-9]+\/agecheck/i;
  2522.  
  2523. if (patt.test(url))
  2524. {
  2525. attachOnReady(skipAgeCheck);
  2526. }
  2527. }
  2528. if (enableSkipAgeCheck) skipAgeCheckAttach();
  2529.  
  2530. /** Hide queue in already owned in store page
  2531. */
  2532. function storeHideSection()
  2533. {
  2534. var divOwn = document.querySelector(".already_owned_actions");
  2535. if (divOwn != null)
  2536. {
  2537. GM_addStyle(
  2538. ".game_area_already_owned { margin-top: 10px !important; } "
  2539. + ".queue_ctn { display: none; } "
  2540. + "#review_container, .reviewPostedDescription, .review_box > .thumb { display: none; } "
  2541. + ".sbh_margin_left { margin-left: 5px; } "
  2542. + ".game_area_play_stats { min-height: 50px; } "
  2543. + "#review_container { margin-top: 30px; } "
  2544. );
  2545.  
  2546. var html = ""
  2547.  
  2548. html += ' <a class="btnv6_blue_hoverfade btn_medium right sbh_margin_left" onclick="'
  2549. + "var sbhQueue = document.querySelector('.queue_ctn');"
  2550. + "if (sbhQueue != null) { sbhQueue.style.display = 'inherit'; sbhQueue = null;} "
  2551. + "this.style.display = 'none'; return false;"
  2552. + '"><span>Show Follow</span></a> ';
  2553.  
  2554. var divReview = document.querySelector("#review_container, .reviewPostedDescription");
  2555. if (divReview != null)
  2556. {
  2557. html += ' <a class="btnv6_blue_hoverfade btn_medium right sbh_margin_left" onclick="'
  2558. + "var sbhReview = document.querySelector('#review_container, .reviewPostedDescription'); "
  2559. + "if (sbhReview != null) { sbhReview.style.display = 'inherit'; sbhReview = null; } "
  2560. + "var sbhReviewThumb = document.querySelector('.review_box > .thumb'); "
  2561. + "if (sbhReviewThumb != null) { sbhReviewThumb.style.display = 'inherit'; sbhReviewThumb = null; } "
  2562. + "this.style.display = 'none'; return false;"
  2563. + '"><span>Show Review</span></a> ';
  2564. }
  2565.  
  2566. divOwn.innerHTML += html;
  2567. }
  2568. }
  2569. function storeHideSectionReady()
  2570. {
  2571. var url = document.documentURI;
  2572. var patt = /^http[s]?:\/\/store.steampowered.com\/app\//i;
  2573.  
  2574. if (patt.test(url))
  2575. {
  2576. attachOnReady(storeHideSection);
  2577. }
  2578. }
  2579. if (enableStoreHideSection) storeHideSectionReady();
  2580.  
  2581. // ===== End Main =====
  2582.  
  2583. attachOnReady(function()
  2584. {
  2585. debugTime("ready");
  2586. });
  2587.  
  2588. attachOnLoad(function()
  2589. {
  2590. debugTime("load");
  2591. });
  2592.  
  2593. function testEvent()
  2594. {
  2595. /*
  2596. document.querySelector("#header_notification_link").addEventListener("DOMCharacterDataModified", function (e) {
  2597. debugTime("DOMCharacterDataModified");
  2598. });
  2599.  
  2600. document.querySelector("#header_notification_link").addEventListener("DOMSubtreeModified", function (e) {
  2601. debugTime("DOMSubtreeModified");
  2602. });
  2603. {
  2604. // select the target node
  2605. var target = document.querySelector("#header_notification_link");
  2606. // create an observer instance
  2607. var observer = new MutationObserver(function(mutations)
  2608. {
  2609. mutations.forEach(function(mutation)
  2610. {
  2611. debugTime("mutation: " + mutation.type);
  2612. });
  2613. });
  2614. // pass in the target node, as well as the observer options
  2615. observer.observe(target,
  2616. {
  2617. childList: true,
  2618. attributes: true,
  2619. characterData: true,
  2620. subtree: true,
  2621. attributeOldValue: true,
  2622. characterDataOldValue: true,
  2623. });
  2624. // later, you can stop observing
  2625. //observer.disconnect();
  2626. }
  2627. */
  2628. }
  2629. attachOnLoad(testEvent);
  2630.  
  2631. })();