Guest User

Dota 2 Lounge item price displayer

a guest
Jun 26th, 2014
797
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // ==UserScript==
  2. // @name Dota 2 Lounge item price displayer
  3. // @namespace http://www.enygma.ro
  4. // @version 2.1
  5. // @author Enygma
  6. // @description Displays an item's lowest price offer from the Steam community market, provides a helper popup to copy an item's name by clicking the panel under it, and adds a button to quickly open the Steam market listing for an item. Inspired by the "Steam Market Price Matcher" script by tomatolicious available at http://userscripts.org/scripts/source/154071.user.js
  7. // @license GPL version 3 or any later version; http://www.gnu.org/copyleft/gpl.html
  8. // @include /^http(s)?://(www.)?dota2lounge.com/*/
  9. // @updateURL http://userscripts.org/scripts/source/182588.user.js
  10. // @downloadURL http://userscripts.org/scripts/source/182588.user.js
  11. // @grant GM_xmlhttpRequest
  12. // @grant GM_addStyle
  13. // ==/UserScript==
  14.  
  15. // Main event listener for hovering items.
  16. document.addEventListener("mouseover", function (event) {
  17. var itemElement = getItemElement(event);
  18. if (!itemElement) {
  19. return;
  20. }
  21.  
  22. attachExtraPanelAndListeners(itemElement);
  23. getLowestPrice(itemElement);
  24. })
  25.  
  26. // Generic item placeholder names used by the d2l website and not existing in the Steam Market.
  27. var genericItemPlaceholderNames = ["Offers", "Any Common", "Any Uncommon", "Any Rare", "Any Mythical", "Any Legendary",
  28. "Any Ancient", "Any Immortal", "Real Money", "+ More", "Any Set"];
  29.  
  30. // Get the hovered item, if any.
  31. var getItemElement = function(mouseEvent) {
  32. var targetElement = mouseEvent.target;
  33. var itemElement = null;
  34.  
  35. // Hover either the item element or its picture (child element).
  36. if (hasClass(targetElement, "item")) {
  37. itemElement = targetElement;
  38. } else if (hasClass(targetElement.parentNode, "item")) {
  39. itemElement = targetElement.parentNode;
  40. } else {
  41. return null;
  42. }
  43.  
  44. // Avoid returning empty item slots.
  45. var itemNameElement = itemElement.querySelector(".name");
  46. if (!itemNameElement) {
  47. return null;
  48. }
  49.  
  50. // Avoid returning d2l generic item placeholders.
  51. var itemName = getItemName(itemElement);
  52. if (genericItemPlaceholderNames.indexOf(itemName) > -1) {
  53. return null;
  54. }
  55.  
  56. return itemElement;
  57. }
  58.  
  59. // Add to the specified item element an extra panel that contains the price information and a click handler to facilitate copying the item's name
  60. var attachExtraPanelAndListeners = function(itemElement) {
  61. var itemNamePanel = itemElement.querySelector(".name");
  62. // If the extra panel already exists, stop here.
  63. var extraPanel = itemNamePanel.querySelector(".extraPanel");
  64. if (extraPanel) {
  65. return;
  66. }
  67.  
  68. // Otherwise, create our own panel to append...
  69. extraPanel = document.createElement('div');
  70. extraPanel.innerHTML = "<span class='scriptStatus'>Ready</span>" +
  71. "<button type='button' class='extraButton refreshButton' title='Refresh'/>" +
  72. "<button type='button' class='extraButton steamMarketListingsButton' title='Show listings for the item on Steam Market'/>";
  73. extraPanel.setAttribute("class", "extraPanel");
  74.  
  75. // ...and append it.
  76. itemNamePanel.appendChild(extraPanel);
  77. // Set click event handler for the item's name panel so that the item name can be copied to the clipboard easier.
  78. itemNamePanel.addEventListener("click", copyItemNameHandler, false);
  79. // Set click event handler for the refresh button that re-fetches the item's price.
  80. var refreshButton = extraPanel.querySelector(".refreshButton");
  81. refreshButton.addEventListener("click", function(event) {
  82. event.stopPropagation()
  83. getLowestPrice(itemElement, true);
  84. }, false);
  85. // Set click event handler for the Steam market listings button that opens in a new tab.
  86. var steamMarketListingsButton = extraPanel.querySelector(".steamMarketListingsButton");
  87. steamMarketListingsButton.addEventListener("click", function(event) {
  88. event.stopPropagation()
  89. showSteamMarketListings(itemElement);
  90. }, false);
  91. }
  92.  
  93. // Get the lowest price for an item from the Steam market.
  94. var getLowestPrice = function(itemElement, override) {
  95. var itemNameElement = itemElement.querySelector(".name");
  96. // Don`t try to get the price if we've already retrieved it.
  97. if (!override && itemNameElement.querySelector(".scriptStatus").innerHTML != "Ready") {
  98. return;
  99. }
  100.  
  101. itemNameElement.querySelector(".scriptStatus").innerHTML = "Loading...";
  102. var url = getSteamMarketListingsURL(itemElement);
  103. GM_xmlhttpRequest({
  104. method: "GET",
  105. url: url,
  106. onload: function (response) {
  107. var httpResponse = response.responseText;
  108. var match = lowestPriceWithFeeRegExp.exec(httpResponse);
  109. var priceWithFee = "<span class='" + (match ?
  110. "itemMarketable'>" + match[1] :
  111. "itemNotMarketable'>Not Marketable")
  112. + "</span>";
  113. match = lowestPriceWithoutFeeRegExp.exec(httpResponse);
  114. var priceWithoutFee = match ? match[1] + " - without fee (seller receives)" : "";
  115. itemNameElement.querySelector(".scriptStatus").innerHTML = "<span title='" + priceWithoutFee + "'>" + priceWithFee + "</span>";
  116. }
  117. });
  118. }
  119.  
  120. // Computes the URL used to access the Steam market listings for a given item.
  121. var getSteamMarketListingsURL = function(itemElement) {
  122. var itemName = getItemName(itemElement);
  123. var itemNameEncoded = encodeURIComponent(itemName);
  124. // Dota2 app ID on Steam's community market website.
  125. var appID = 570;
  126. var url = "http://steamcommunity.com/market/listings/" + appID + "/" + itemNameEncoded + "/";
  127.  
  128. return url;
  129. }
  130.  
  131. // Extract the item's name from a DOM item element.
  132. var getItemName = function(itemElement) {
  133. var itemNameElement = itemElement.querySelector(".name");
  134. var itemName = itemNameElement.querySelector("b").innerHTML.trim();
  135.  
  136. return itemName;
  137. }
  138.  
  139. // Cached RegExps used to read the item's value from the Steam page.
  140. var lowestPriceWithFeeRegExp = /<span class="market_listing_price market_listing_price_with_fee">\s*(.*?)\s*<\/span>/i;
  141. var lowestPriceWithoutFeeRegExp = /<span class="market_listing_price market_listing_price_without_fee">\s*(.*?)\s*<\/span>/i;
  142.  
  143. // Event handler to facilitate copying an item's name.
  144. var copyItemNameHandler = function(event) {
  145. var clickedElement = event.target;
  146.  
  147. // Avoid executing this handler if the "Remove item" button is clicked in a trade.
  148. if (excludedTags.indexOf(clickedElement.tagName) > -1 || excludedTags.indexOf(clickedElement.parentNode.tagName) > -1) {
  149. return;
  150. }
  151.  
  152. // Stop the element's parent (item) from getting the click event. This stops the item from being selected.
  153. event.stopPropagation();
  154.  
  155. // Make sure we select the item name element.
  156. var itemNameElement = clickedElement;
  157. while (!hasClass(itemNameElement, "name")) {
  158. itemNameElement = itemNameElement.parentNode;
  159. }
  160.  
  161. // Get and display the item's name.
  162. var itemName = itemNameElement.querySelector("b").innerHTML.trim();
  163. window.prompt("Press CTRL+C to copy the item's name:", itemName);
  164. }
  165.  
  166. // Tags that, if clicked on in an item name panel, should not execute the copyItemNameHandler.
  167. var excludedTags = ["A", "IMG"];
  168.  
  169. // Opens a new tab with the Steam market listings of a given item.
  170. var showSteamMarketListings = function(itemElement) {
  171. var url = getSteamMarketListingsURL(itemElement);
  172. var win = window.open(url, "_blank");
  173. if (win) {
  174. // Browser has allowed it to be opened.
  175. win.focus();
  176. } else {
  177. // Broswer has blocked it.
  178. alert('Please allow popups for this site in order to open the Steam market listings.');
  179. }
  180. }
  181.  
  182. // Helper method to check if an element has the specified class name.
  183. var hasClass = function(element, cls) {
  184. return element && (" " + element.className + " ").indexOf( " " + cls + " " ) > -1;
  185. }
  186.  
  187. // Style.
  188. GM_addStyle(".itemNotMarketable { color : red } .itemMarketable { color: green } .extraButton { margin-left: 0.3em; vertical-align: top; margin-top: -0.1em; border: 0; padding: 0; width: 16px; height: 16px; }");
  189. GM_addStyle(".refreshButton { background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAABOUlEQVQ4jc2RsUoDQRCGv32CXECzdjaWRiOCVSA+RdqAL6BFesUXOPUFbCWKJ2thkcRgxCa3cJUEQuCwExRjCi1sxiKXsElO6wz81e58888/sPhlESwxlhNaeP/+zRnO/wCMNaBDIbVZG/ztppLcLYdpgK3uSFgGc05WAnbX7pTcD5FCQ8lyMDOlQ4mQaO8lcRI6Q7wATxsGR32k9YUc9RFtiL1gZsoTq1jk7D3JxLEeFNtKLj6ZqNhWkppHSOvxO3GRFlb3J3mc2VEb/I2mktM3Jtp5UKINgUuProYJoMO+C8jWyGhDXO0hl0Ok2hutma2RcR1UsMjx6ySoA9fJkqGUryu5+UDydSW5azbn1wiJyjFSjp3bO4lrg19opJzacZEhJMIi688juYBkFT+9eRpUGYOmbr6Q9QvwBrFqSdh8NgAAAABJRU5ErkJggg==) no-repeat left center; }");
  190. GM_addStyle(".steamMarketListingsButton { background: url(data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAAAXNSR0IArs4c6QAAAAZiS0dEAP8A/wD/oL2nkwAAAAlwSFlzAAALEwAACxMBAJqcGAAAAAd0SU1FB9sIBhUuIxK7S5QAAAFbSURBVDjLY7x27QaDoYGhOQMDwwkGHEBEVJiBgYGBwcLalOHE0dMMb16/ZWBgYGA4f+E8IwM7G+d/fDg4LPD/8VNH/yOD46eO/ufh5P3Pzsb5H68B0tIycM08nLxwDDOEKANgmheumf3//////xeumQ0XJ2hAcFgg3ABkAOPHRsf9Z2LAA0rr8+HsRWvnwGl+IX6EIly29/T0wG3ctm0bShjk5mcjvBAcFojT7/hAbHQcxACYQElx6f+S4tL/e/bvxKtx4rT+/9LSMnDLGLApkpaWwTCopLgUq1cZcNkE88bxU0dRbETHTLDQxQUcbFzgSRcbYEmLymPYE3qYIbsqiWFq2zyGyOgIuOTJawcZCAEWBgYGhlWrV0PieMlCBhkZWQYGBgaGtbuWMKyZt5U4A2CGyCvKMaxZv5KBgYGBYc28DQzLVywnaADjlcvXGYyNjf4zkAHOnj3HDAAt54OFwXNyhAAAAABJRU5ErkJggg==) no-repeat left center; }");
RAW Paste Data