Improved Steam Achievements

Improves the appearance of Steam achievements on Steam pages and also on Achievement Stats pages.

  1. // ==UserScript==
  2. // @name Improved Steam Achievements
  3. // @namespace http://greasyfork.org/users/2240-doodles
  4. // @author Doodles
  5. // @version 3
  6. // @description Improves the appearance of Steam achievements on Steam pages and also on Achievement Stats pages.
  7. // @include *://www.achievementstats.com/*
  8. // @include *://achievementstats.com/*
  9. // @include *://steamcommunity.com/*
  10. // @exclude *://steamcommunity.com/*xml=1*
  11. // @exclude *://steamcommunity.com/*tab=leaderboards*
  12. // @exclude *://steamcommunity.com/*/leaderboards/*
  13. // @run-at document-end
  14. // @require https://ajax.googleapis.com/ajax/libs/jquery/1.11.3/jquery.min.js
  15. // @require https://ajax.googleapis.com/ajax/libs/jqueryui/1.11.4/jquery-ui.min.js
  16. // @require https://cdnjs.cloudflare.com/ajax/libs/jquery.tablesorter/2.27.1/js/jquery.tablesorter.js
  17. // @grant GM_getValue
  18. // @grant GM_setValue
  19. // @updateVersion 3
  20. // ==/UserScript==
  21. this.$ = this.jQuery = jQuery.noConflict(true);
  22. $(document).ready(function () {
  23. 'use strict';
  24. // =======================================================================================================================
  25. // Prototype Functions
  26. String.prototype.isaReplaceAll = function(f, r) {
  27. return this.split(f).join(r);
  28. };
  29. String.prototype.isaRemoveEnd = function(end) {
  30. return (this.length < end.length || this.substring(this.length - end.length) != end) ? this : this.substring(0, this.length - end.length);
  31. };
  32. Number.prototype.toSuffixedString = function() {
  33. var i = this;
  34. var suffixes = ['th', 'st', 'nd', 'rd', 'th', 'th', 'th', 'th', 'th', 'th', 'th', 'th', 'th', 'th'];
  35. var iStr = i.toString();
  36. i = (i > 99) ? parseInt(iStr.substring(iStr.length - 2), 10) : i;
  37. i = (i > 13) ? parseInt(iStr.substring(iStr.length - 1), 10) : i;
  38. return iStr + suffixes[i];
  39. };
  40. String.prototype.padTwo = function() {
  41. return (this.length == 1) ? '0' + this : this;
  42. };
  43. Number.prototype.padTwo = function() {
  44. return (this < 10) ? '0' + this.toString() : this.toString();
  45. };
  46. Date.prototype.isaToString = function() {
  47. return this.getFullYear().toString() + '/' + (1 + this.getMonth()).padTwo() + '/' + this.getDate().padTwo() + ' ' + this.getHours().padTwo() + ':' + this.getMinutes().padTwo();
  48. };
  49. String.prototype.lastPart = function(s) {
  50. var p = this.split(s);
  51. return p[p.length - 1];
  52. };
  53. // =======================================================================================================================
  54. // Data Variables
  55. var defaultTitleDelim = ' - ';
  56. var defaultLinkDelim = ' | ';
  57. var backTile = 'data:image/gif;base64,R0lGODlhAwAJAJEAABoaGiIiIhISEgAAACH/C1hNUCBEYXRhWE1QPD94cGFja2V0IGJlZ2luPSLvu78iIGlkPSJXNU0wTXBDZWhpSHpyZVN6TlRjemtjOWQiPz4gPHg6eG1wbWV0YSB4bWxuczp4PSJhZG9iZTpuczptZX' +
  58. 'RhLyIgeDp4bXB0az0iQWRvYmUgWE1QIENvcmUgNS4zLWMwMTEgNjYuMTQ1NjYxLCAyMDEyLzAyLzA2LTE0OjU2OjI3ICAgICAgICAiPiA8cmRmOlJERiB4bWxuczpyZGY9Imh0dHA6Ly93d3cudzMub3JnLzE5OTkvMDIvMjItcmRmLXN5bnRheC1ucy' +
  59. 'MiPiA8cmRmOkRlc2NyaXB0aW9uIHJkZjphYm91dD0iIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtbG5zOnhtcE1NPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvbW0vIiB4bWxuczpzdFJlZj0iaHR0cDovL2' +
  60. '5zLmFkb2JlLmNvbS94YXAvMS4wL3NUeXBlL1Jlc291cmNlUmVmIyIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M2IChXaW5kb3dzKSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDo0NjAwMUJCRTEyQzMxMUU1QjQ1REZBQkU2QU' +
  61. 'VFQUJDMCIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDo0NjAwMUJCRjEyQzMxMUU1QjQ1REZBQkU2QUVFQUJDMCI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjQ2MDAxQkJDMTJDMzExRTVCNDVERkFCRTZBRU' +
  62. 'VBQkMwIiBzdFJlZjpkb2N1bWVudElEPSJ4bXAuZGlkOjQ2MDAxQkJEMTJDMzExRTVCNDVERkFCRTZBRUVBQkMwIi8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+Af/+/fz7+vn49/' +
  63. 'b19PPy8fDv7u3s6+rp6Ofm5eTj4uHg397d3Nva2djX1tXU09LR0M/OzczLysnIx8bFxMPCwcC/vr28u7q5uLe2tbSzsrGwr66trKuqqainpqWko6KhoJ+enZybmpmYl5aVlJOSkZCPjo2Mi4qJiIeGhYSDgoGAf359fHt6eXh3dnV0c3JxcG9ubWxram' +
  64. 'loZ2ZlZGNiYWBfXl1cW1pZWFdWVVRTUlFQT05NTEtKSUhHRkVEQ0JBQD8+PTw7Ojk4NzY1NDMyMTAvLi0sKyopKCcmJSQjIiEgHx4dHBsaGRgXFhUUExIREA8ODQwLCgkIBwYFBAMCAQAAIfkEAAAAAAAsAAAAAAMACQAAAgeMYHiXrW8KADs=';
  65. var arrowDown = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAYAAAB24g05AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD' +
  66. '0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPH' +
  67. 'JkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxucz' +
  68. 'p4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2' +
  69. 'luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6QjUwMUY4NzEzNDFBMTFFNTlEM0E5MkY5MEUwMzBGRTciIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6QjUwMUY4NzIzNDFBMTFFNTlEM0E5MkY5MEUwMzBGRTciPiA8eG1wTU06RGVyaX' +
  70. 'ZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpCNTAxRjg2RjM0MUExMUU1OUQzQTkyRjkwRTAzMEZFNyIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpCNTAxRjg3MDM0MUExMUU1OUQzQTkyRjkwRTAzMEZFNyIvPiA8L3JkZjpEZXNjcm' +
  71. 'lwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PtTTibEAAAFdSURBVHjaYmRgYGAEYi4g5gTib1CMD3BB8XeYWmY1E0fj6uUXdgHZNkDMi0czSM4GpBakB6SXCeSCnz+/S4uo6rtWrbu1homJGWSIEBAzIWkEsY' +
  72. 'VAciA1ILUgPSC9YEV//vxh+/oP6C4ZVfHqfe/XKxk7RgCFpYCYBYqlQGIgOZAakFqQHpjJ/3///fPtM1AQhH9x8LKHTt031Ty2rBQopwPCIDZIDCQHUwfSA9LLCA1E9ZD55zaKqBmqIXv45rYFJ0G0uleCObL4m1vnb61JNPIHKWGEinEDsbZNy9puWf' +
  73. 'sgO3xR8PjgukNHaoJBrrsKxF+ZoeK/gfjto32rjv1iZGLj0bc3/vmfgQEdX1nQNPt8b2YtUO0NaDRiAFYglhO28iuy2fH1l93+//9BGMQGiYHkoGrwAlDAirDwCfvrLn/4EoRBbJAYWtSCASMeg/iAWBLKfg7En7ApAggwAF08i46C7tfuAAAAAElFTk' +
  74. 'SuQmCC';
  75. var arrowUp = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAALCAYAAAB24g05AAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD' +
  76. '0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPH' +
  77. 'JkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxucz' +
  78. 'p4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2' +
  79. 'luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6Rjg5RTY1MDEzNDFBMTFFNTk0NUU4NTQxM0I4NDFBOUQiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6Rjg5RTY1MDIzNDFBMTFFNTk0NUU4NTQxM0I4NDFBOUQiPiA8eG1wTU06RGVyaX' +
  80. 'ZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpGODlFNjRGRjM0MUExMUU1OTQ1RTg1NDEzQjg0MUE5RCIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpGODlFNjUwMDM0MUExMUU1OTQ1RTg1NDEzQjg0MUE5RCIvPiA8L3JkZjpEZXNjcm' +
  81. 'lwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PrqW0q0AAAFySURBVHjaYmTADbiAWBTKfg3E3xiIBIxAzA/EDhWLT18EYRAbKsZISDMzEIuJyCiHN2x/+rH/zP//IAxig8RAclA1KBpggA2IZfTcIxMSpuyezM' +
  82. 'IjwPn7PwMDCDNx8bKbBmUEvnt699PLu1ceQr3zF9kADiBWdcztrnHI6y38zcTM9AuoERmDxFQdg53YOHmEH5zafQOo/hMQ/2GE+kvRs3vLXHkrbwdk5z09u+8BiJY2dlJAFn94bOuB7aU+yUDmfSaQAbwyqsoCFt4OH/8xMMDwuY2zN23Oc44FYRAbWQ' +
  83. '6kFqQHpJcFSDAxcfPzffoHNf7///9XJ+V1P1g3ZQ6Q9wgkdKorrfjl7YvXdfInlzEwMoJjAqQHRIHYLLwaZgF2+///t9z45huvukkSUEwKJI7kahBbEiQHUgNSC9IDU8PMZ+xqrbfyyS0g2w2IBXHENyNUzg2kFqQHpBcWiLxAzA3En4H4C4G0wgNV/x' +
  84. 'WkHiDAAPxMjVutShxmAAAAAElFTkSuQmCC';
  85. var settingsIcon = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABsAAAAbCAYAAACN1PRVAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA2ZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD' +
  86. '0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPH' +
  87. 'JkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIH' +
  88. 'htbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDpDMkMwRT' +
  89. 'FGNjE5MzRFNTExOTRGQjk5NTdFM0Y0NjI3OCIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDo3NjZDMjgzMzM3NkUxMUU1ODcxNUJCRjhEOUUzRERDQSIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDo3NjZDMjgzMjM3NkUxMUU1ODcxNUJCRjhEOU' +
  90. 'UzRERDQSIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M2IChXaW5kb3dzKSI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjhCQjBDNDI5NkUzN0U1MTE5RjE5QzI1QTgzNDMyMkE5IiBzdFJlZj' +
  91. 'pkb2N1bWVudElEPSJ4bXAuZGlkOkMyQzBFMUY2MTkzNEU1MTE5NEZCOTk1N0UzRjQ2Mjc4Ii8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+kBEuTwAABWBJREFUeNq8VgtMU1cY9r' +
  92. 'a3T1ootS3QNryqUEqx2PoCRB3OF8vYMnAbGdkcU5ksczpli5htxi06QTLdMl0kmmw+YjIm2cZmptNZDCgTpwiICqQFoVSh8mhpe3v72DnmXHJXisFs2Um+e57/+e7/n///z8ECgcCM/6vg8INh2HTX8wCiAcQADoB+VE+vPEEzJgAH1VRJeL/aWH/gsp' +
  93. '3YdeauiScUpdPmGQCsoPX/KIwQY1BNIYBmzYaPi0GdAiCAxEKxbJY0Tj0P5wnYktik+PSc/JVgPAyAC5C4rPC9tUwWOxW0I0LtHYqMmZK5Wlt24vrpVRt3fb31WOP38llpeWA8a3FB6Qa+WMbzgQ5E8sIVL4MqE2BxcUVNdd7miu+2H28+Y1hVmIG0nH' +
  94. 'xmk/4AZ0ulqrRkHzhNZVqGel1l7Tce17hHlpAi9tKsnrq8QF92uvWkl/T4lGq9FE7JVGmqSEWiGjSNk0wGzyzIQaC2qW8fMdYkzF2S9LQeZ7vf9ehgkT6PcNqbQNc7lRkx1IcgTa1Xu6EWT4ue9mu9gMhJ2x8LNiMHZ3NjZCptvHNkiBMuU6RpVhRmkz' +
  95. 'STATN6e29e7rB2tjQ7RwaHhBK5MkZtmB+ry1IxmPjEhkr90mTVwpXPDZk7pGGRMvJRX1ev2zEKQ8RNmVGZv7fmQJzhmVwf6QkwcRbOi5jJpjYYsZhG66s/qWw9e/wn0B2EmqOwiF5UVLYuo+iDjXyRhEOtd9uHSZJwkUCBGZb2JuPprbmbwHAPpZkgOn' +
  96. '3JcqZQzKOCxIO0Ihyj5LmD23Z3GmtPgu4QckSqPLx6orLK5/f7l5R+vpnSkCGIZHEAYFuauigbhdLEmY3euVRbMzYy5CbRb1O41/hLIyCqQxr5gvwBOkD/tVNV3/bcaugMlnURLp+p+eLvcH86me3CvpLddTvXbrd2tw1DrSAIn39GX0vDJagBgH8KB4' +
  97. 'SE1r7WK1coOQibxez8bc/6PXXlBWVIfoLMA2Dp/+tSw4PuNjMl4PIQ/lGLyYLmn1SI8eFBK51ssOduf+e5U9AiZjhPJ4POIJfpsjME8Zo4SsCHczC2OEo8VfDTkwMzLEJEJ+NExcnAeRlQ4mbRyWbO23Z4Z9ZnP1SFJc4RUwIkxsAiUxbA1BNJj5cQKU' +
  98. '8inD13Hp2MF6uOyNr7437Dlq92wHk6mShqaf4rWISURxeAkGbm5YQnaBeBNeEhCB8TKZYV5Ebqc3TBsgyRjC9f8dob6EqaIHM8bG2sd7tdpMsxRrpdTh8MaAhcohDoPjy6L3yWbjVYF4vcmIsye2JU5vOvJm/cWx7ghOGUDEG4/Wgfr62r5QZY56TnRi' +
  99. '4vJiFOmDhH4xl+wGKFizWa7UfKuBIFn1LBZTXbbdfO/WG7cdFI2AaG+HKVQqzPeVYyf1UmWyTlUutI+7Cn44vSL8H6ZrY42uvs7+p0mNq6ICE9ETPQxQc7yclbDh1SvLBp8aTL1ksG/F6Pj8HhMTFwpsHzA2eP/dlR8VYJaHagcKEQoHsZNfj4xuWr58' +
  100. 'eTIf2OhQHgUwUdOzYlCv0wGRyboS5PXLamWMudbVBSmdxxv9MOMOb1ByZl+XFrjwPASfV56gWx0pWvp4QKl1BkAa/LYbH3dJig8PBNY9vtHbnrWzakFz04f6KJTjRQV228VWIouvPRi6Wjt5vuwTHngHkAisF9pvPggSaIYHD4+pg3P30XtLXoDSIUZb' +
  101. '9Umn7e6597IRDQ/eok+eoFhdQcgE75zoFyjlyVheKS8TSvKxxdIzjNCpqko+13tD/bidmHr98E/SRa7OHoqceaKgGEehY8qcCXlBwFOMzkFiqG/u278T8vfwswANrMfI9dB/UpAAAAAElFTkSuQmCC';
  102. var settingsIconHover = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABsAAAAbCAYAAACN1PRVAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAA2ZpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD' +
  103. '0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPH' +
  104. 'JkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wTU09Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9tbS8iIH' +
  105. 'htbG5zOnN0UmVmPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvc1R5cGUvUmVzb3VyY2VSZWYjIiB4bWxuczp4bXA9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC8iIHhtcE1NOk9yaWdpbmFsRG9jdW1lbnRJRD0ieG1wLmRpZDpDMkMwRT' +
  106. 'FGNjE5MzRFNTExOTRGQjk5NTdFM0Y0NjI3OCIgeG1wTU06RG9jdW1lbnRJRD0ieG1wLmRpZDpCODE3QjlGRDM3NkUxMUU1QkIwNUNDMjVEN0NBN0ZEMCIgeG1wTU06SW5zdGFuY2VJRD0ieG1wLmlpZDpCODE3QjlGQzM3NkUxMUU1QkIwNUNDMjVEN0' +
  107. 'NBN0ZEMCIgeG1wOkNyZWF0b3JUb29sPSJBZG9iZSBQaG90b3Nob3AgQ1M2IChXaW5kb3dzKSI+IDx4bXBNTTpEZXJpdmVkRnJvbSBzdFJlZjppbnN0YW5jZUlEPSJ4bXAuaWlkOjhCQjBDNDI5NkUzN0U1MTE5RjE5QzI1QTgzNDMyMkE5IiBzdFJlZj' +
  108. 'pkb2N1bWVudElEPSJ4bXAuZGlkOkMyQzBFMUY2MTkzNEU1MTE5NEZCOTk1N0UzRjQ2Mjc4Ii8+IDwvcmRmOkRlc2NyaXB0aW9uPiA8L3JkZjpSREY+IDwveDp4bXBtZXRhPiA8P3hwYWNrZXQgZW5kPSJyIj8+Z/YQbwAABW5JREFUeNq8VgtMU1cYpu' +
  109. '0tLdACLaU85VWhLbSCvBniGGPOlI0xxTE2Nh0SHYQ93MTER4ZT94pjc5oxo05jNhY2MYwpcTNGrExYBygO5FmhvIqTV0pLKb3t7c7Be8m1XIhmy07y3XvOf+453/2f59BsNpvD/9UQ+KDRaI/6vROANwAfwAAwgr8frS2jGQOAhb+JFnz8vPL6tR793L' +
  110. 'n67n6uq3sUaZ4OwLT7/qFGp5BBNbkA4fk7PsgHbykABxLzBMKVASslsSwXjqN/SFhQasbGdUDuAsAGCMkpeGcTk+kYAfpulHtTaIYkpK5POn2p5U79EIYdr2noFEnkrwB5Wv57+3/6fdhmI/BheWUzkK8HSD90oqqurn/OcvbKX+r0rNz1uFUW+2yRkO' +
  111. 'noGSCRi63Am5LoJMnBU9XHZ40z5sBQKd9C+rcURXb0mSttFajZbA2TR3tCWaBYLvJZESIBXeUik0HN7AIEqh/xxTll1aqEtWGPG3EjGvVkoSI602jQq8DQspTPaPgYAm2/+cddFGjxuOhobRoEREbS/jR7M7IcWWyfALEsaHpynOXh7Sdfk5mbgpJMZj' +
  112. 'LOWDqa6jv7O2436ybHxvlevv4r5TFx0phkEQNBFjaUJjwpXp2yLmNI3enpLhCiWo160KjXwRQxEWb0LymvOiJLekphQc02BsJEuDwPR2KD+0P9usovSw8rq7/7BQzHoOZ4AHi/sK1kS9abu7a58gQLAWHQTaFm0ywKFHDoaVUpP3pDUQjEA4RmnNC4tU' +
  113. '+zXPlOxAoUe/AGf4WePvT+gabL1RVgOA5gJZn+fs2Jw2VWDMNyd336NoPxQEMWl8eEgP2QyMQUPJUWfKZr/K26amJy3GQGpiOj6WptAyC6iGtktYsHGAAjF0+Vnb3TfKPXfq1hdtba2nD1CtyfTDZxZt/2A0eLN+3UdLdPEc42WzGHrpYb16AGANgSAQ' +
  114. 'gJ73XfbGwkB8rosMZ4cnfBx8eKs0vw9QtkZgBtt+rajYHudo0ZbAthNM1hwF9afH65NqebGLtHrIMYvts9orrwA7SIBs6TyWAw+IpiU5IEovBAwgwYk0XjeHjxl0r+h+oAx82dbEKuT6AwKDIxBi/cTDKZx4bSb/a+9tX5MkHYKj6xAKXRaX7y+CQwzy' +
  115. 'PnC0V9FXhLV8eSyXjBErfNX9d8nrXv2G44TyZzl6RvzGG6ezqRTQERmpqZ5hUqSwTfuFIQzhPJ1mUrAuLTIu3XOvKEzrKMVzfjR9ICmaHvVsN1I8gNg34aNc4arYSjnYR+nMwD337mLY6ExTUAD2M2XtlDxKnPv5z27id7aGwXhFgzazJh+D6W4a7bt2' +
  116. 'AGkWsj290vOFAYtip8ZuJvppMbP1yx/0QJV+jnTKig02r0fQ2X6zSqq0rD2Og4b4XILyghLT0k+dknnHme7IVKMz1lvnSo6KhuRNPMEXhbJgfVvWPqdjUkJBdiOn7wwYH4mb3l5VEvFa6xdxBmQW1W1GxFWE4MGp2+yI9tP5/+89fSrdtBtxNPFwI2cp' +
  117. 'QRwvkTVxARF4RSHeIMJg0AmS/nFPNuwVIv/IdR+9ykOqmR8Kx8mYckxh+eXRDjA716gGkLZnMgZASmtAMGACMxFkTEB0iee11KlS5UZLa5GYN2rK+zHy4ebFa2XyhWFFTmROV11H6vIhO1nT+p/DE3Jq92R1aRtk3VM08+ohkF6kxR6k1xLYAmcEPYzt' +
  118. 'ExhQffAn0ZfgfhBqVtKNraZMEKWmy2LQ1G1DMiPpeYA4hM3Hlkj6u/KBnPS/rj3K4Q/BhBSFYIf/Hcna68ev1cZkVLKxiHkXIPwa96zKUKANW1YLkGb1K+eILDSq4lcujf3hv/8/aPAAMA9bWbSWlT7cIAAAAASUVORK5CYII=';
  119. var closeIcon = 'data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAAA8AAAAPCAYAAAA71pVKAAAAGXRFWHRTb2Z0d2FyZQBBZG9iZSBJbWFnZVJlYWR5ccllPAAAAyJpVFh0WE1MOmNvbS5hZG9iZS54bXAAAAAAADw/eHBhY2tldCBiZWdpbj0i77u/IiBpZD' +
  120. '0iVzVNME1wQ2VoaUh6cmVTek5UY3prYzlkIj8+IDx4OnhtcG1ldGEgeG1sbnM6eD0iYWRvYmU6bnM6bWV0YS8iIHg6eG1wdGs9IkFkb2JlIFhNUCBDb3JlIDUuMy1jMDExIDY2LjE0NTY2MSwgMjAxMi8wMi8wNi0xNDo1NjoyNyAgICAgICAgIj4gPH' +
  121. 'JkZjpSREYgeG1sbnM6cmRmPSJodHRwOi8vd3d3LnczLm9yZy8xOTk5LzAyLzIyLXJkZi1zeW50YXgtbnMjIj4gPHJkZjpEZXNjcmlwdGlvbiByZGY6YWJvdXQ9IiIgeG1sbnM6eG1wPSJodHRwOi8vbnMuYWRvYmUuY29tL3hhcC8xLjAvIiB4bWxucz' +
  122. 'p4bXBNTT0iaHR0cDovL25zLmFkb2JlLmNvbS94YXAvMS4wL21tLyIgeG1sbnM6c3RSZWY9Imh0dHA6Ly9ucy5hZG9iZS5jb20veGFwLzEuMC9zVHlwZS9SZXNvdXJjZVJlZiMiIHhtcDpDcmVhdG9yVG9vbD0iQWRvYmUgUGhvdG9zaG9wIENTNiAoV2' +
  123. 'luZG93cykiIHhtcE1NOkluc3RhbmNlSUQ9InhtcC5paWQ6REU2NUE2RkYzODQxMTFFNUJGMTc4MDk5QkNBOUVBNjkiIHhtcE1NOkRvY3VtZW50SUQ9InhtcC5kaWQ6REU2NUE3MDAzODQxMTFFNUJGMTc4MDk5QkNBOUVBNjkiPiA8eG1wTU06RGVyaX' +
  124. 'ZlZEZyb20gc3RSZWY6aW5zdGFuY2VJRD0ieG1wLmlpZDpERTY1QTZGRDM4NDExMUU1QkYxNzgwOTlCQ0E5RUE2OSIgc3RSZWY6ZG9jdW1lbnRJRD0ieG1wLmRpZDpERTY1QTZGRTM4NDExMUU1QkYxNzgwOTlCQ0E5RUE2OSIvPiA8L3JkZjpEZXNjcm' +
  125. 'lwdGlvbj4gPC9yZGY6UkRGPiA8L3g6eG1wbWV0YT4gPD94cGFja2V0IGVuZD0iciI/PriqgcMAAAE5SURBVHjanJK/SgNBEIfvTsEiBEwhYuUL+BCm0U5JEREUjRBOEAQfQ9JrkkNQxEpQBME/ZdQHsLK3sjIpQooQw/kN7Mlk3CYZ+Ji9m/n9bnfnwj' +
  126. 'RNg0kjzMRxHC+TtuAgSZKBbaQekU7gnvrDn5hCkfUNFOAK9mj4UcKQ1JAl9KBM/TFy9SMnlNiGcwTTSlh3Qomc6w8ycQWe1S7F4BLhHDmBfVV7gx175pzb+qpq/IRFI1xjy50RsTK4hRXP5Y4I/4mdwSzpAxbU6zYsIfzSvZHnCzWYN+/EsIbxlHfO7q' +
  127. 'tNdasSfZhRzzLGCjsY6jmL46kRyhkP4dhcohhUMehn2z4zwhdYp+Fdfgh4MmO80GduwdCtX6GEUC4pIHdJG8agZecsjruwieDb82/nSddwR73pHdU48SvAAF0zfh0+f5wAAAAAAElFTkSuQmCC';
  128. var colWidUnlockPercent = '158';
  129. var colWidUnlockPoint = '110';
  130. var colWidUnlockDate = '180';
  131. var colWidUnlockLink = '95';
  132. var titleDone = false;
  133. // =======================================================================================================================
  134. // Stored Data Variables
  135. var titleDelim = GM_getValue('isaDataTitleDelim', defaultTitleDelim);
  136. var linkDelim = GM_getValue('isaDataLinkDelim', defaultLinkDelim);
  137. var meName = GM_getValue('isaDataMeName', false);
  138. var meSteamId = GM_getValue('isaDataMeSteamId', false);
  139. var meUrlBit = GM_getValue('isaDataMeUrlBit', false);
  140. var achPeople = [];
  141. pushPeople(meName, meSteamId, meUrlBit);
  142. function pushPeople(name, steamid, urlbit){
  143. if (achPeople === false || !$.isArray(achPeople)) {
  144. achPeople = [];
  145. }
  146. if(steamid !== false || urlbit !== false) {
  147. var alreadyInList = false;
  148. for (var i = 0; i < achPeople.length; i++) {
  149. var person = achPeople[i];
  150. if((person[1] !== false && person[1] == steamid) || (person[2] !== false && person[2] == urlbit)) {
  151. alreadyInList = true;
  152. break;
  153. }
  154. }
  155. if(!alreadyInList){
  156. achPeople.push([name, steamid, urlbit]);
  157. }
  158. }
  159. }
  160. // =======================================================================================================================
  161. // Functions
  162. function urlContains(urlfragment) {
  163. return document.URL.indexOf(urlfragment) != -1;
  164. }
  165. function htmlDateDifference(to, from) {
  166. if (to === false || from === false) {
  167. return '';
  168. }
  169. var ss = Math.floor((to - from) / 1000);
  170. var yy = Math.floor(ss / 31536000); //60 / 60 / 24 / 365
  171. ss -= yy * 31536000;
  172. var dd = Math.floor(ss / 86400); //60 / 60 / 24
  173. ss -= dd * 86400;
  174. var hh = Math.floor(ss / 3600); //60 / 60
  175. ss -= hh * 3600;
  176. var mm = Math.floor(ss / 60); //60
  177. ss -= mm * 60;
  178. var timeDesc = '<span title="Time between this and the previous achievement." class="isaSpanSmallBold ';
  179. if (yy > 0) {
  180. return timeDesc + 'isaSpanRed2">' + yy + ((yy == 1) ? 'year ' : 'years ') + dd + ((dd == 1) ? 'day ' : 'days ') + hh + 'h ' + mm + 'm ' + ss + 's</span>';
  181. } else if (dd > 0) {
  182. return timeDesc + 'isaSpanRed2">' + dd + ((dd == 1) ? 'day ' : 'days ') + hh + 'h ' + mm + 'm ' + ss + 's</span>';
  183. } else if (hh > 0) {
  184. return timeDesc + 'isaSpanYel2">' + hh + 'h ' + mm + 'm ' + ss + 's</span>';
  185. } else if (mm > 0) {
  186. return timeDesc + 'isaSpanBlu">' + mm + 'm ' + ss + 's</span>';
  187. } else if (ss > 0) {
  188. return timeDesc + 'isaSpanBlu">' + ss + 's</span>';
  189. } else {
  190. return timeDesc + 'isaSpanGre">Same Time as Previous</span>';
  191. }
  192. }
  193. function textTimeAgo(dateUnlocked) {
  194. if (dateUnlocked === false) {
  195. return '';
  196. }
  197. var ss = Math.floor((Date.now() - dateUnlocked.getTime()) / 1000);
  198. var yy = Math.floor(ss / 31536000); //60 / 60 / 24 / 365
  199. ss -= yy * 31536000;
  200. var dd = Math.floor(ss / 86400); //60 / 60 / 24
  201. ss -= dd * 86400;
  202. var hh = Math.floor(ss / 3600); //60 / 60
  203. ss -= hh * 3600;
  204. var mm = Math.floor(ss / 60); //60
  205. ss -= mm * 60;
  206. if (yy > 0) {
  207. return yy + ((yy == 1) ? 'year ' : 'years ') + dd + ((dd == 1) ? 'day ' : 'days ') + hh + 'h ' + mm + 'm ' + ss + 's ago';
  208. } else if (dd > 0) {
  209. return dd + ((dd == 1) ? 'day ' : 'days ') + hh + 'h ' + mm + 'm ' + ss + 's ago';
  210. } else if (hh > 0) {
  211. return hh + 'h ' + mm + 'm ' + ss + 's ago';
  212. } else if (mm > 0) {
  213. return mm + 'm ' + ss + 's ago';
  214. } else if (ss > 0) {
  215. return ss + 's ago';
  216. } else {
  217. return 'just now';
  218. }
  219. }
  220. function htmlFromUl(ul) {
  221. var liHtml = [];
  222. $(ul).find('li').each(function () { liHtml.push($(this).html()); });
  223. return liHtml.join(linkDelim);
  224. }
  225. function htmlAstatsPoint(value) {
  226. if (!(value > 0)) {
  227. return '<span class="isaSpanRed" title="Unachieved: No one recorded on AStats has this achievement.">' + value + '</span>';
  228. } else if (value >= 3) {
  229. return '<span class="isaSpanRed" title="Hard: 3+">' + value + '</span>';
  230. } else if (value >= 2) {
  231. return '<span class="isaSpanYel" title="Moderate: 2-2.99">' + value + '</span>';
  232. } else if (value >= 1) {
  233. return '<span class="isaSpanBlu" title="Easy: 1-1.99">' + value + '</span>';
  234. } else {
  235. return '<span class="isaSpanGre" title="Simple: 0-0.99">' + value + '</span>';
  236. }
  237. }
  238. function htmlSteamAchProgress(str) {
  239. var numbs = str.trim().split(' / ');
  240. var value = numbs[0].isaReplaceAll(',', '') / numbs[1].isaReplaceAll(',', '');
  241. if (value <= 0.33) {
  242. return '<span class="isaSpanRed isaSpanSmallBold">Progress: ' + str + '</span>';
  243. } else if (value <= 0.66) {
  244. return '<span class="isaSpanYel isaSpanSmallBold">Progress: ' + str + '</span>';
  245. } else if (value < 1) {
  246. return '<span class="isaSpanBlu isaSpanSmallBold">Progress: ' + str + '</span>';
  247. } else {
  248. return '<span class="isaSpanGre isaSpanSmallBold">Progress: ' + str + '</span>';
  249. }
  250. }
  251. function domPercentCell(cell, percent) {
  252. var hslHue = Math.floor(2 * parseInt(percent, 10));
  253. $(cell).css({ 'background-color': 'hsl(' + hslHue + ', 60%, 20%)', 'background': 'linear-gradient(hsl(' + hslHue + ', 60%, 20%), hsl(' + hslHue + ', 60%, 15%))' }).text(percent);
  254. }
  255. function textDateFixSteam(str) {
  256. var parts1 = str.replace('Unlocked ', '').split(' @ ');
  257. var parts2 = parts1[0].split(',');
  258. var parts3 = parts2[0].split(' ');
  259. var parts4 = parts1[1].split(':');
  260. var ye = parts2.length == 2 ? parts2[1].trim() : new Date().getFullYear();
  261. var da = (parts3[0] < 10) ? '0' + parts3[0].trim() : parts3[0].trim();
  262. var month = ['jan', 'feb', 'mar', 'apr', 'may', 'jun', 'jul', 'aug', 'sep', 'oct', 'nov', 'dec'].indexOf(parts3[1].trim().toLowerCase()) + 1;
  263. var mo = (month < 10) ? '0' + month : month;
  264. var mi = parts4[1].trim().substring(0, 2);
  265. var timecode = parts4[1].trim().substring(2, 4);
  266. var ho = parts4[0].trim();
  267. if (timecode == 'am') {
  268. if(ho == '12'){
  269. ho = '00';
  270. }else if(ho.length == 1) {
  271. ho = '0' + ho;
  272. }
  273. } else if (ho != '12') {
  274. ho = (parseInt(ho, 10) + 12).toString();
  275. }
  276. return ye + '/' + mo + '/' + da + ' ' + ho + ':' + mi;
  277. }
  278. function htmlPercentStr(str, value) {
  279. if (value <= 0.33) {
  280. return '<span class="isaSpanRed">' + str + '</span>';
  281. } else if (value <= 0.66) {
  282. return '<span class="isaSpanYel">' + str + '</span>';
  283. } else if (value < 1) {
  284. return '<span class="isaSpanBlu">' + str + '</span>';
  285. } else {
  286. return '<span class="isaSpanGre">' + str + '</span>';
  287. }
  288. }
  289. function textStringToDate(str) {
  290. if (!str || $.trim(str) === '') {
  291. return false;
  292. }
  293. var parts1 = str.split(' ');
  294. var parts2 = parts1[0].split('/');
  295. var parts3 = parts1[1].split(':');
  296. if (parts3.length == 3) {
  297. return new Date(parts2[0], parts2[1] - 1, parts2[2], parts3[0], parts3[1], parts3[2]); //new Date(year, month, day, hours, minutes, seconds, milliseconds);
  298. } else {
  299. return new Date(parts2[0], parts2[1] - 1, parts2[2], parts3[0], parts3[1]);
  300. }
  301. }
  302. function domDateColumn(rows, column, detailCell) {
  303. if (typeof(detailCell)==='undefined') { detailCell = false; }
  304. if (rows.length > 1) {
  305. rows.sort(function(a, b) {
  306. var aText = $(a).find('td:eq(' + column + ') > span:eq(0)').text().trim();
  307. var bText = $(b).find('td:eq(' + column + ') > span:eq(0)').text().trim();
  308. if (aText == bText) {
  309. return 0;
  310. }
  311. var aNum = 0;
  312. if (aText == 'Locked') {
  313. aNum = 99999999999999;
  314. } else if (aText == 'Unlocked') {
  315. aNum = 88888888888888;
  316. } else if (aText == 'Unlocked Pre-Tracking') {
  317. aNum = 0;
  318. } else {
  319. aNum = aText.isaReplaceAll('/', '').isaReplaceAll(':', '').isaReplaceAll(' ', '');
  320. }
  321. var bNum = 0;
  322. if (bText == 'Locked') {
  323. bNum = 99999999999999;
  324. } else if (bText == 'Unlocked') {
  325. bNum = 88888888888888;
  326. } else if (bText == 'Unlocked Pre-Tracking') {
  327. bNum = 0;
  328. } else {
  329. bNum = bText.isaReplaceAll('/', '').isaReplaceAll(':', '').isaReplaceAll(' ', '');
  330. }
  331. return aNum - bNum;
  332. });
  333. if (detailCell !== false) {
  334. var timesCheck1 = [], timesCheck2 = [], times = 0, duplicateTimes = 0;
  335. $(rows).each(function() {
  336. var rowTime = $(this).find('td:eq(' + column + ')').text();
  337. if (rowTime != 'Locked' && rowTime != 'Unlocked' && rowTime != 'Unlocked Pre-Tracking') {
  338. times++;
  339. if (jQuery.inArray(rowTime, timesCheck1) == -1) {
  340. timesCheck1.push(rowTime);
  341. } else {
  342. duplicateTimes++;
  343. if (jQuery.inArray(rowTime, timesCheck2) == -1) {
  344. timesCheck2.push(rowTime);
  345. }
  346. }
  347. }
  348. });
  349. duplicateTimes += timesCheck2.length;
  350. var ratio = duplicateTimes / times;
  351. if (ratio >= 0.5) {
  352. var dupPercent = Math.round((duplicateTimes * 10000) / times) / 100;
  353. var dupPercentStr = duplicateTimes + ' / ' + times + ' (' + dupPercent + '%) duplicate times';
  354. var percentSpan = '';
  355. if (ratio >= 0.9) {
  356. percentSpan = '<span class="isaSpanRed">' + dupPercentStr + '</span>';
  357. } else if (ratio > 0.75) {
  358. percentSpan = '<span class="isaSpanOra">' + dupPercentStr + '</span>';
  359. } else {
  360. percentSpan = '<span class="isaSpanYel">' + dupPercentStr + '</span>';
  361. }
  362. $(detailCell).append('<div class="isaStat" title="Possible cheater">' + percentSpan + '</div>');
  363. }
  364. }
  365. for (var i = rows.length - 1; i >= 1; i--) {
  366. var dateLaterString = $(rows[i]).find('td:eq(' + column + ') > span:eq(0)').text();
  367. var dateFirstString = $(rows[i - 1]).find('td:eq(' + column + ') > span:eq(0)').text();
  368. var skipFirst = dateFirstString == 'Locked' || dateFirstString == 'Unlocked' || dateFirstString == 'Unlocked Pre-Tracking';
  369. var skipLater = dateLaterString == 'Locked' || dateLaterString == 'Unlocked' || dateLaterString == 'Unlocked Pre-Tracking';
  370. if (!(skipFirst || skipLater)) {
  371. $(rows[i]).find('td:eq('+column+')').append('<br />' + htmlDateDifference(textStringToDate(dateLaterString), textStringToDate(dateFirstString)));
  372. }
  373. }
  374. for (var i = 0, l = rows.length - 1; i <= l; i++) {
  375. var dateString = $(rows[i]).find('td:eq(' + column + ') > span:eq(0)').text();
  376. if (dateString != 'Locked' && dateString != 'Unlocked' && dateString != 'Unlocked Pre-Tracking') {
  377. $(rows[i]).find('td:eq(' + column + ') span:eq(0)').attr('title', 'Date-Time Unlocked (' + textTimeAgo(textStringToDate(dateString)) + ')');
  378. }
  379. }
  380. var rank = 1;
  381. var marked = 0;
  382. var lastDate = '';
  383. for (var i = 0, l = rows.length; i < l; i++) {
  384. var thisDate = $(rows[i]).find('td:eq(' + column + ') > span:eq(0)').text();
  385. if (thisDate == 'Locked' || thisDate == 'Unlocked') {
  386. // do nothing
  387. } else if (thisDate == 'Unlocked Pre-Tracking') {
  388. marked++;
  389. } else if (thisDate == lastDate) {
  390. $(rows[i]).find('td:eq(' + column + ')').append('<br /><span title="Place in the unlock history this achievement was unlocked.">' + rank.toSuffixedString() + '</span>');
  391. marked++;
  392. } else {
  393. rank = marked + 1;
  394. $(rows[i]).find('td:eq(' + column + ')').append('<br /><span title="Place in the unlock history this achievement was unlocked.">' + rank.toSuffixedString() + '</span>');
  395. marked++;
  396. lastDate = thisDate;
  397. }
  398. }
  399. } else if (rows.length == 1 && $(rows[0]).find('td').length > 1) {
  400. var cell = $(rows[0]).find('td:eq(' + column + ')');
  401. var dateString = $(cell).find('span:eq(0)').text();
  402. if (dateString != 'Locked' && dateString != 'Unlocked' && dateString != 'Unlocked Pre-Tracking') {
  403. $(cell).find('span:eq(0)').attr('title', 'Date-Time Unlocked (' + textTimeAgo(textStringToDate(dateString)) + ')');
  404. $(cell).append('<br /><span title="Place in the unlock history this achievement was unlocked.">1st</span>');
  405. }
  406. }
  407. }
  408. function jsRowHighlight(table) {
  409. if (typeof(table)==='undefined') { table = 'table#isaSecondTable'; }
  410. $(table).find('tbody > tr').hover(
  411. function () { $(this).addClass('isaHoverHighlight'); },
  412. function () { $(this).removeClass('isaHoverHighlight'); }
  413. );
  414. }
  415. function jsOptionsMenuSave() {
  416. var temp1 = $('#isaSettingsDialog input:eq(0)').val().trim();
  417. meName = (temp1 == '' ? false : temp1);
  418. var temp2 = $('#isaSettingsDialog input:eq(1)').val().trim();
  419. meSteamId = (temp2 == '' ? false : temp2);
  420. var temp3 = $('#isaSettingsDialog input:eq(2)').val().trim();
  421. meUrlBit = (temp3 == '' ? false : temp3);
  422. titleDelim = $('#isaSettingsDialog input:eq(3)').val();
  423. linkDelim = $('#isaSettingsDialog input:eq(4)').val();
  424.  
  425. GM_setValue('isaDataMeName', meName);
  426. GM_setValue('isaDataMeSteamId', meSteamId);
  427. GM_setValue('isaDataMeUrlBit', meUrlBit);
  428. GM_setValue('isaDataTitleDelim', titleDelim);
  429. GM_setValue('isaDataLinkDelim', linkDelim);
  430. }
  431. function jsOptionsMenuReset() {
  432. $('#isaSettingsDialog input:eq(0)').val('');
  433. $('#isaSettingsDialog input:eq(1)').val('');
  434. $('#isaSettingsDialog input:eq(2)').val('');
  435. $('#isaSettingsDialog input:eq(3)').val(defaultTitleDelim);
  436. $('#isaSettingsDialog input:eq(4)').val(defaultLinkDelim);
  437. }
  438. // =======================================================================================================================
  439. // Link HTML Functions
  440. function htmlLinksProfile(steamProfileId64) {
  441. var html = '<span>Steam:</span> ';
  442. html += '<a title="Steam Profile" href="http://steamcommunity.com/profiles/' + steamProfileId64 + '">Profile</a>' + linkDelim;
  443. html += '<a title="Games" href="http://steamcommunity.com/profiles/' + steamProfileId64 + '/games/">Games</a>' + linkDelim;
  444. html += '<a title="Games - All" href="http://steamcommunity.com/profiles/' + steamProfileId64 + '/games?tab=all">All Games</a>' + linkDelim;
  445. html += '<a title="Screenshots" href="http://steamcommunity.com/profiles/' + steamProfileId64 + '/screenshots/?appid=0&sort=newestfirst&browsefilter=myfiles&view=grid">Screenshots</a>' + linkDelim;
  446. html += '<a title="Videos" href="http://steamcommunity.com/profiles/' + steamProfileId64 + '/videos/">Videos</a>' + linkDelim;
  447. html += '<a title="Artwork" href="http://steamcommunity.com/profiles/' + steamProfileId64 + '/images/">Artwork</a>' + linkDelim;
  448. html += '<a title="Reviews" href="http://steamcommunity.com/profiles/' + steamProfileId64 + '/recommended/">Reviews</a>' + linkDelim;
  449. html += '<a title="Guides" href="http://steamcommunity.com/profiles/' + steamProfileId64 + '/myworkshopfiles/?section=guides">Guides</a>' + linkDelim;
  450. html += '<a title="Workshop Items" href="http://steamcommunity.com/profiles/' + steamProfileId64 + '/myworkshopfiles/">Workshop Items</a>' + linkDelim;
  451. html += '<a title="Greenlight Items" href="http://steamcommunity.com/profiles/' + steamProfileId64 + '/myworkshopfiles/?section=greenlight">Greenlight Items</a>' + linkDelim;
  452. html += '<a title="Friends" href="http://steamcommunity.com/profiles/' + steamProfileId64 + '/friends/">Friends</a>' + linkDelim;
  453. html += '<a title="Groups" href="http://steamcommunity.com/profiles/' + steamProfileId64 + '/groups/">Groups</a>' + linkDelim;
  454. html += '<a title="Inventory" href="http://steamcommunity.com/profiles/' + steamProfileId64 + '/inventory/">Inventory</a>' + linkDelim;
  455. html += '<a title="All Comments" href="http://steamcommunity.com/profiles/' + steamProfileId64 + '/allcomments">All Comments</a>' + linkDelim;
  456. html += '<a title="Name History" href="http://steamcommunity.com/profiles/' + steamProfileId64 + '/namehistory">Name History</a>' + linkDelim;
  457. html += '<a title="Friends in Common" href="http://steamcommunity.com/profiles/' + steamProfileId64 + '/friendscommon">Friends in Common</a>' + linkDelim;
  458. html += '<a title="Groups in Common" href="http://steamcommunity.com/profiles/' + steamProfileId64 + '/groupscommon">Groups in Common</a>' + linkDelim;
  459. html += '<a title="Badges" href="http://steamcommunity.com/profiles/' + steamProfileId64 + '/badges/">Badges</a>' + linkDelim;
  460. html += '<a title="Wishlist" href="http://steamcommunity.com/profiles/' + steamProfileId64 + '/wishlist/">Wishlist</a>';
  461. html += '<br /><span>Third Party:</span> ';
  462. html += '<a title="SteamRep" href="http://steamrep.com/profiles/' + steamProfileId64 + '">SteamRep</a>' + linkDelim;
  463. html += '<a title="SteamDB" href="http://steamdb.info/calculator/?player=' + steamProfileId64 + '">SteamDB</a>' + linkDelim;
  464. html += '<a title="Achievement Stats" href="http://www.achievementstats.com/index.php?action=profile&playerId=' + steamProfileId64 + '">Achievement Stats</a>' + linkDelim;
  465. html += '<a title="astats.nl" href="http://astats.astats.nl/astats/User_Info.php?steamID64=' + steamProfileId64 + '">astats.nl</a>';
  466. return html;
  467. }
  468. function htmlLinksGameShort(steamAppId, gameName, steamProfileId64, steamUrlBit) {
  469. if (typeof(steamUrlBit)==='undefined' || steamUrlBit === false) { steamUrlBit = steamAppId; }
  470. if (typeof(steamProfileId64)==='undefined') { steamProfileId64 = false; }
  471. var html = '';
  472. html += '<a title="Steam Store" href="http://store.steampowered.com/app/' + steamAppId + '">Steam Store</a>' + linkDelim;
  473. html += '<a title="Steam Hub" href="http://steamcommunity.com/app/' + steamAppId + '">HUB</a>' + linkDelim;
  474. html += '<a title="Steam Achievements" href="http://steamcommunity.com/stats/' + steamUrlBit + '/achievements">Achievements</a>' + linkDelim;
  475. if (steamProfileId64 !== false) {
  476. html += '<a title="Player Achievements on Steam" href="http://steamcommunity.com/profiles/' + steamProfileId64 + '/stats/' + steamUrlBit + '/achievements">Player</a>' + linkDelim;
  477. }
  478. html += '<a title="Steam Hub Guides" href="http://steamcommunity.com/app/' + steamAppId + '/guides/">Steam Guides</a>' + linkDelim;
  479. html += '<a title="AchievementStats.com" href="http://www.achievementstats.com/index.php?action=games&gameId=' + steamAppId + '">Achievement Stats</a>' + linkDelim;
  480. html += '<a title="AStats.nl" href="http://astats.astats.nl/astats/Steam_Game_Info.php?AppID=' + steamAppId + '">AStats</a>' + linkDelim;
  481. html += '<a title="SteamDB.info" href="http://steamdb.info/app/' + steamAppId + '/">SteamDB</a>';
  482. return html;
  483. }
  484. function htmlLinksGameLong(gameAppId, gameName, steamUrlBit, steamProfiles) {
  485. if (typeof(steamUrlBit)==='undefined' || steamUrlBit === false) { steamUrlBit = gameAppId; }
  486. if (typeof(steamProfiles)==='undefined') { steamProfiles = false; }
  487. var html = '<span>Steam:</span> ';
  488. html += '<a title="Steam Store" href="http://store.steampowered.com/app/' + gameAppId + '">Store</a>' + linkDelim;
  489. html += '<a title="Steam DLC" href="http://store.steampowered.com/dlc/' + gameAppId + '">DLC</a>' + linkDelim;
  490. html += '<a title="Steam Store - Similar items" href="http://store.steampowered.com/recommended/morelike/app/' + gameAppId + '">Similar</a>' + linkDelim;
  491. html += '<a title="Steam HUB" href="http://steamcommunity.com/app/' + gameAppId + '">Hub</a>' + linkDelim;
  492. html += '<a title="Steam Forum" href="http://store.steampowered.com/forum/' + gameAppId + '">Forum</a>' + linkDelim;
  493. html += '<a title="News on Steam" href="http://store.steampowered.com/news/?appids=' + gameAppId + '">News</a>' + linkDelim;
  494. html += '<a title="Steam Market Search" href="http://steamcommunity.com/market/search?q=' + gameName + '">Market</a>' + linkDelim;
  495. html += '<span>Achievements:</span> ';
  496. html += '<a title="" href="http://steamcommunity.com/stats/' + steamUrlBit + '/achievements">Global</a>';
  497. if (steamProfiles !== false && $.isArray(steamProfiles)) {
  498. for (var i = 0; i < steamProfiles.length; i++) {
  499. var person = steamProfiles[i];
  500. if(person[1] !== false || person[2] !== false) {
  501. var nameLabelA = person[0] === false ? 'Me' : person[0];
  502. var nameLabelB = person[0] === false ? 'My' : person[0] + '\'s';
  503. var tempUrlBit = person[2] !== false ? 'id/' + person[2] : 'profiles/' + person[1];
  504. html += linkDelim + '<a title="' + nameLabelB + ' Achievements on Steam" href="http://steamcommunity.com/' + tempUrlBit + '/stats/' + steamUrlBit + '/achievements">' + nameLabelA + ' on Steam</a>';
  505. html += linkDelim + '<a title="' + nameLabelB + ' XML Unlock History" href="http://steamcommunity.com/' + tempUrlBit + '/stats/' + steamUrlBit + '/achievements?xml=1">' + nameLabelB + ' XML</a>';
  506. if (person[1] !== false) {
  507. html += linkDelim + '<a title="' + nameLabelB + ' Achievements on Astats" href="http://www.achievementstats.com/index.php?action=profile&playerId=' + person[1] + '&mode=history&gameId=' +
  508. gameAppId + '">' + nameLabelA + ' on Astats</a>';
  509. }
  510. }
  511. }
  512. }
  513. html += '<br /><span>Steam HUB:</span> ';
  514. html += '<a title="Steam Hub" href="http://steamcommunity.com/app/' + gameAppId + '/">Steam Hub</a>' + linkDelim;
  515. html += '<a title="Steam Hub Discussions" href="http://steamcommunity.com/app/' + gameAppId + '/discussions/">Discussions</a>' + linkDelim;
  516. html += '<a title="Steam Hub Screenshots" href="http://steamcommunity.com/app/' + gameAppId + '/screenshots/">Screenshots</a>' + linkDelim;
  517. html += '<a title="Steam Hub Artwork" href="http://steamcommunity.com/app/' + gameAppId + '/images/">Artwork</a>' + linkDelim;
  518. html += '<a title="Steam Hub Videos" href="http://steamcommunity.com/app/' + gameAppId + '/videos">Videos</a>' + linkDelim;
  519. html += '<a title="Steam Hub News" href="http://steamcommunity.com/app/' + gameAppId + '/news">News</a>' + linkDelim;
  520. html += '<a title="Steam Hub Announcements" href="http://steamcommunity.com/app/' + gameAppId + '/announcements">Announcements</a>' + linkDelim;
  521. html += '<a title="Steam Hub Guides" href="http://steamcommunity.com/app/' + gameAppId + '/guides/">Guides</a>' + linkDelim;
  522. html += '<a title="Steam Hub Reviews" href="http://steamcommunity.com/app/' + gameAppId + '/reviews/">Reviews</a>';
  523. html += '<br /><span>Third Party:</span> ';
  524. html += '<a title="AchievementStats.com" href="http://www.achievementstats.com/index.php?action=games&gameId=' + gameAppId + '">Achievement Stats</a>' + linkDelim;
  525. html += '<a title="Official Site for the Game" href="http://store.steampowered.com/appofficialsite/' + gameAppId + '">Official Site</a>' + linkDelim;
  526. html += '<a title="AStats.nl" href="http://astats.astats.nl/astats/Steam_Game_Info.php?AppID=' + gameAppId + '">AStats</a>' + linkDelim;
  527. html += '<a title="SteamDB.info" href="http://steamdb.info/app/' + gameAppId + '/">SteamDB</a>' + linkDelim;
  528. html += '<a title="Steam Card Exchange" href="http://www.steamcardexchange.net/index.php?gamepage-appid-' + gameAppId + '">Card Exchange</a>' + linkDelim;
  529. html += '<a title="SteamCharts.com" href="http://steamcharts.com/app/' + gameAppId + '">SteamCharts</a>' + linkDelim;
  530. html += '<a title="SteamGraph.net" href="http://steamgraph.net/index.php?action=graph&appid=' + gameAppId + '&from=0">SteamGraph</a>' + linkDelim;
  531. html += '<a title="SteamSpy" href="http://steamspy.com/app/' + gameAppId + '">SteamSpy</a>' + linkDelim;
  532. html += '<a title="PC Gaming Wiki" href="http://pcgamingwiki.com/api/appid.php?appid=' + gameAppId + '">PC Gaming Wiki</a>' + linkDelim;
  533. html += '<a title="News RSS Feed (by getoffmalawn.com)" href="http://www.getoffmalawn.com/steamnews/' + gameAppId + '.atom">RSS News</a>' + linkDelim;
  534. html += '<a title="GameFAQs.com Search" href="http://www.gamefaqs.com/search/index.html?platform=19&game=' + gameName + '">GameFAQ Search</a>' + linkDelim;
  535. html += '<a title="HowLongToBeat Search" href="http://howlongtobeat.com/?q=' + gameName + '">HowLongToBeat Search</a>' + linkDelim;
  536. html += '<a title="IsThereAnyDeal.com Search" href="http://isthereanydeal.com/#/search:' + gameName + ';/scroll:%23gamelist">IsThereAnyDeal</a>';
  537. return html;
  538. }
  539. function htmlLinksDLC(game, dlc) {
  540. var html = '<span>Steam:</span> ';
  541. html += '<a href="http://store.steampowered.com/app/' + dlc + '">Store</a>' + linkDelim;
  542. html += '<a href="http://store.steampowered.com/dlc/' + game + '">DLC</a>' + linkDelim;
  543. html += '<a href="http://steamcommunity.com/app/' + game + '">Hub</a>' + linkDelim;
  544. html += '<a href="http://steamcommunity.com/stats/' + game + '/achievements">Achievements</a>' + linkDelim;
  545. html += '<span>Third Party:</span> ';
  546. html += '<a title="AchievementStats.com" href="http://www.achievementstats.com/index.php?action=games&gameId=' + game + '">Achievement Stats</a>' + linkDelim;
  547. html += '<a title="AStats.nl" href="http://astats.astats.nl/astats/Steam_Game_Info.php?AppID=' + game + '">AStats</a>' + linkDelim;
  548. html += '<a title="Steam DB" href="http://steamdb.info/app/' + dlc + '/">SteamDB.info</a>' + linkDelim;
  549. html += '<a title="Steam DB" href="http://steamdb.info/app/' + game + '/">SteamDB.info (Parent Game)</a>' + linkDelim;
  550. html += '<a title="PC Gaming Wiki" href="http://pcgamingwiki.com/api/appid.php?appid=' + game + '">PC Gaming Wiki</a>';
  551. return html;
  552. }
  553. function htmlLinksAch(game, achName, useLabel, gameAppId) {
  554. if (typeof(useLabel)==='undefined') { useLabel = false; }
  555. if (typeof(gameAppId)==='undefined') { gameAppId = false; }
  556. var html = '';
  557. if (useLabel) {
  558. html += '<span>Guide Search:</span> ';
  559. }
  560. html += '<a title="Search for a Guide on Google" href="http://www.google.com/#q=%22' + game + '%22 %22' + achName + '%22">Google</a>';
  561. html += (useLabel ? linkDelim : '<br />');
  562. html += '<a title="Search for a Guide on YouTube" href="https://www.youtube.com/results?search_query=%22' + game + '%22 %22' + achName + '%22">YouTube</a>';
  563. if (gameAppId !== false) { //http://steamcommunity.com/app/200900/guides/?searchText=Pea+Shooter&browsefilter=trend&requiredtags[]=-1
  564. html += (useLabel ? linkDelim : '<br />');
  565. html += '<a title="Search Steam Guides" href="http://steamcommunity.com/app/' + gameAppId + '/guides/?searchText=' + achName + '&browsefilter=trend&requiredtags[]=-1">Guides</a>';
  566. }
  567. return html;
  568. }
  569. // =======================================================================================================================
  570. // Universal Stuff: SLG Styles, Custom Tablesort Parser, Title Edit Var
  571. $('<style></style>').prop('type', 'text/css').html('' +
  572. '#isaPageWrap { background-color:#222222; padding:10px; border-top:1px solid #000000; background-image: url(' + backTile + '); }' +
  573. 'div.isaTableSpacer {height:10px;} .isaWidth100 { width:100%; }' +
  574. 'h2.isaPageTitleFirst, h2.isaPageTitle { color:#3c9fe5; margin:0; padding:8px 0 2px 0; text-align:center; font-size:24px; font-weight:bold; } ' +
  575. 'form.isaSmallButton {display:block; float:right;} form.isaSmallButton input {display:inline-block; font-size:10px; margin:0 0 0 0;}' +
  576. 'span.isaSpanSmallBold { font-weight:bold; font-size:12px; }' +
  577. 'span.isaSpanRed { color:#ff6161; } span.isaSpanRed2 { color:#f66666; }' +
  578. 'span.isaSpanYel { color:#ffff5e; } span.isaSpanYel2 { color:#d3d325; }' +
  579. 'span.isaSpanBlu { color:#7fb3e9; } span.isaSpanBlu2 { color:#2591ff; }' +
  580. 'span.isaSpanOra { color:#ffae00; } span.isaSpanGre { color:#a6d36a; }' +
  581. 'span.isaSpanPin { color:#ff68e8; }' +
  582. 'table.isaTable { background-color:#000000; border-collapse:separate; border-spacing:1px; }' +
  583. 'table.isaTable td { background-color:#333333; background: linear-gradient(#3A3A3A,#333333); vertical-align:top; padding:2px 4px 3px 4px; color:#EEEEEE;font-size:14px;}' +// border:1px solid #555555;
  584. 'table.isaTable td a:link, table.isaTable td a:visited { color:#7fb3e9;text-decoration: none; } ' +
  585. 'table.isaTable td a:hover, table.isaTable td a:active { color:#ffffff;text-decoration: underline; } ' +
  586. 'table.isaTable th { font-size:16px;background-color:#555555;background:linear-gradient(#5C5C5C,#555555);text-align:center;padding:4px;text-shadow:1px 1px 2px #000000;white-space:nowrap;color:#daf0ff; }' +
  587. 'table.isaTable th a:link, table.isaTable th a:visited { text-decoration: none; } table.isaTable th a:hover, table.isaTable th a:active { text-decoration: underline; } ' +
  588. 'table.isaTable td.isaGameImage { text-align:center; padding:3px; vertical-align:top; width:184px; }' +
  589. 'table.isaTable td.isaGameIcon { text-align:center; padding:3px; vertical-align:top; width:64px; }' +
  590. 'table.isaTable td.isaGameImage img, table.isaTable td.isaGameIcon img { border:1px solid #676767; }' +
  591. 'table.isaTable td.isaTitleCell { background-color:#555555; background: linear-gradient(#5C5C5C,#555555); padding:2px 2px 4px 5px; font-size:24px; font-weight:bold; color:#ffffff; text-shadow:2px 2px 4px #000000; }' +
  592. 'table.isaTable td.isaTitleCell a:link, table.isaTable td.isaTitleCell a:visited { text-decoration: none; color:#24a4ff; }' +
  593. 'table.isaTable td.isaTitleCell a:hover, table.isaTable td.isaTitleCell a:active { text-decoration: underline; }' +
  594. 'table.isaTable td.isaTitleCell div.isaTitleAppend { display:inline-block;padding:0 0 0 15px; font-weight:normal; }' +
  595. 'table.isaTable td.isaLinkContainer { color:#4d4d4d; font-size:12px; text-shadow:1px 1px 2px #000000; padding:3px 5px 3px 5px; } ' +
  596. 'table.isaTable td.isaLinkContainerMid { text-align:center; vertical-align:middle;color:#4d4d4d; font-size:12px; text-shadow:1px 1px 2px #000000; padding:3px 5px 3px 5px; } ' +
  597. 'table.isaTable td.isaLinkContainer span, table.isaTable td.isaLinkContainerMid span { color:#cccccc; font-weight:bold; } ' +
  598. 'table.isaTable td.isaLinkContainerDark { text-align:center; vertical-align:middle;color:#777777; font-size:12px; text-shadow:1px 1px 2px #000000; padding:3px 5px 3px 5px; } ' +
  599. 'table.isaTable td.isaLinkContainerDark a:link, table.isaTable td.isaLinkContainerDark a:visited { color:#777777;text-decoration: none; } ' +
  600. 'table.isaTable td.isaLinkContainerDark a:hover,table.isaTable td.isaLinkContainerDark a:active { color:#FFFFFF;text-decoration: underline; } ' +
  601. 'table.isaTable td.isaStatsCell { padding:4px 0 0 4px; font-size:14px; }' +
  602. 'table.isaTable td.isaStatsCell div.isaStat { display:inline-block;margin:0 4px 4px 0; padding:2px 7px 2px 5px; color:#beffb9; font-weight:bold; }' +
  603. 'table.isaTable td.isaStatsCell div.isaStat span { color:#CCCCCC; font-weight:normal; }' +
  604. 'table.isaTable td.isaListGameImage { padding:3px; width:184px; }' +
  605. 'table.isaTable td.isaListAchImage { padding:3px; width:64px; }' +
  606. 'table.isaTable td.isaListAchImage img, table.isaTable td.isaListGameImage img { border:none;padding:0;margin:0;display:block; }' +
  607. 'table.isaTable td.isaListAchs { padding:5px;width:256px; }' +
  608. 'table.isaTable td.isaListNumber { padding:2px 4px 2px 4px;vertical-align:middle;text-align:center; }' +
  609. 'table.isaTable td.isaListBigNumber { padding:2px 4px 2px 4px;vertical-align:middle;text-align:center;font-weight:bold;font-size:24px; }' +
  610. 'table.isaTable td.isaListSmall { font-size:12px; }' + 'table.isaTable td.isaListSmaller { font-size:10px; }' +
  611. 'table.isaTable td.isaEvenPadding { padding:3px; }' +
  612. 'table.isaTable td.isaStatsLarge { padding:2px 0 0 5px; font-size:18px; font-weight:bold; text-shadow:2px 2px 4px #000000; }' +
  613. 'table.isaTable td.isaStatsLarge div.isaStat { display:inline-block;padding:0 15px 2px 0; color:#cae4ff; font-weight:bold; }' +
  614. 'table.isaTable td.isaListTitle { font-weight:bold;font-size:16px;color:#b9e2ff; }' +
  615. 'table.isaTable td.isaListTitle a:link, table.isaTable td.isaListTitle a:visited {color:#b9e2ff;text-decoration:none;}' +
  616. 'table.isaTable td.isaListTitle a:hover, table.isaTable td.isaListTitle a:active {color:#2591ff;text-decoration:underline;}' +
  617. 'table.isaTable td.isaListAchDetail { font-size:12px;color:#cccccc;text-shadow:1px 1px 1px #000000; }' +
  618. 'table.isaTable td.isaListAchDetail h3 { padding:0 0 1px 0;margin:0;font-weight:bold;font-size:16px;color:#b9e2ff; }' +
  619. 'table.isaTable td.isaListAchDetail h3 a:link, table.isaTable td.isaListAchDetail h3 a:visited {color:#b9e2ff;text-decoration:none;}' +
  620. 'table.isaTable td.isaListAchDetail h3 a:hover, table.isaTable td.isaListAchDetail h3 a:active {color:#2591ff;text-decoration:underline;}' +
  621. 'table.isaTable td.isaListAchDetail span { display:inline-block; padding-top:1px; }' +
  622. 'table.isaTable tr.isaAchBroken td {background-color:#572424; background: linear-gradient(#632929,#572424);}' +
  623. 'table.isaTable tr.isaAchSeasonal td {background-color:#492e16; background: linear-gradient(#533418,#492e16);}' +
  624. 'table.isaTable tr.isaAchNonRecurring td, table.isaTable tr.isaAchTemporary td {background-color:#38380a; background: linear-gradient(#40400b,#38380a);}' +
  625. 'table.isaTable tr.isaAchMonetary td {background-color:#5f2356; background: linear-gradient(#5f2356,#541e4b);}' +
  626. 'table.isaTable td.isaListShadow { box-shadow:inset 0 0 10px 0 #222; }' +
  627. 'table.isaTable td.isaListTextShadow { text-shadow:2px 2px 4px #000000; }' +
  628. 'table.isaTable td.isaListAchUnlocked { background-color:#243d26; background: linear-gradient(#243d26,#29452b);text-shadow:1px 1px 1px #000000; }' +
  629. 'table.isaTable td.isaBlackedOut { background-color:#111111; background: linear-gradient(#1A1A1A,#111111); color:#777777;font-size:12px; }' +
  630. 'table.isaTable td.isaHideCell, table.isaTable tr.isaHideCell { display:none; } div.isaActionDiv { cursor:pointer; }' +
  631. 'table.isaTable tr.isaHoverHighlight td {box-shadow:0px 0px 10px rgba(255, 255, 255, 0.2) inset;} ' +
  632. 'table.isaTable tr.isaHoverHighlight td.isaListAchDetail, table.isaTable tr.isaHoverHighlight td.isaListAchDetail h3 {text-shadow:1px 1px 1px #000000;} ' +
  633. 'table.isaTable th.tablesorter-headerAsc { background:url("'+arrowDown+'") right 5px center no-repeat, linear-gradient(to bottom,#5C5C5C,#555555); }' +
  634. 'table.isaTable th.tablesorter-headerDesc { background:url("'+arrowUp+'") right 5px center no-repeat, linear-gradient(to bottom,#5C5C5C,#555555); }' +
  635. 'div#isaSettingsContainer { padding:2px 2px 0 0; float: right; display:block; }' +
  636. 'div#isaSettingsButton { width:27px; height:27px; display:block;background-image: url("'+settingsIcon+'");cursor:pointer; }' +
  637. '.ui-corner-all {border-radius: 0 !important;}' +
  638. '.ui-dialog { z-index:403 !important; background-color:#333333;color:#EEEEEE;font-size:14px; border:1px solid #000000;box-shadow: 5px 5px 5px rgba(0, 0, 0, 0.5);font-family: Arial,Helvetica,Verdana,sans-serif !important;}' +
  639. '.ui-dialog-titlebar {font-size:16px;background-color:#555555;background:linear-gradient(#5C5C5C,#555555);padding:4px 4px 4px 7px;text-shadow:1px 1px 2px #000000;color:#daf0ff;'+
  640. 'font-weight:bold; border:none !important;}' +
  641. '.ui-dialog-titlebar-close {float:right;width:19px;height:19px; background-color:#333333 !important; border:1px solid #222222 !important;background-image:url("'+closeIcon+
  642. '") !important;background-position:center !important; background-repeat:no-repeat !important; }' +
  643. '.ui-dialog-titlebar-close:hover {background-color:#0c3551 !important; border:1px solid #333333 !important;} .ui-dialog-titlebar-close span { display: none; }' +
  644. '.ui-dialog-content {background: linear-gradient(#3A3A3A,#333333);padding:5px;text-shadow:1px 1px 1px #000000;border:none !important;}' +
  645. '.ui-dialog-content input, .ui-dialog-content textarea {color:#ffffff;background-color:rgba(0, 0, 0, 0.2);border:1px solid #000;border-radius:3px;font-size:12px;font-family: "Courier New", Courier, monospace;margin:0px;}' +
  646. '.ui-dialog-content fieldset {border:1px solid #000000;} .ui-dialog-content fieldset:not(:first-child) {margin-top:8px;}' +
  647. '.ui-dialog-content legend { padding:2px 4px 2px 4px;font-weight:bold;}' +
  648. '.ui-dialog-buttonpane {padding:2px 7px 7px 7px;background-color:none !important;background:none !important;border:none; } .ui-dialog-buttonset {text-align:right;}' +
  649. '.ui-dialog-buttonset button {margin-left:5px;background: #174a6b !important;text-shadow: 1px 1px 0px #000000;color: #ffffff !important;padding: 2px 10px 2px 10px !important;border: solid #1f628d 1px !important;' +
  650. 'font-family:Arial,Helvetica,Verdana,sans-serif !important;}' +
  651. '.ui-dialog-buttonset button:hover {background: #3395d7 !important;}' +
  652. '.ui-widget-overlay { position:absolute;top:0;left:0;width:100%;height:100%;background-color:#000000;opacity:.60;filter:Alpha(Opacity=60);background-image:none !important;}' +
  653. 'div.isaSettingsSetting { height:24px;vertical-align:top; }' +
  654. 'div.isaSettingsSetting label { float:left; }' +
  655. 'div.isaSettingsSetting input { float:right; }' +
  656. 'div.isaSettingsText { height:94px;vertical-align:top; }' +
  657. 'div.isaSettingsText label { float:left; }' +
  658. 'div.isaSettingsText textarea { float:right; }' +
  659. '').appendTo('head');
  660. $.tablesorter.addParser({
  661. id: 'isaDate', is: function (s) { return false; },
  662. format: function (s, table, cell, cellIndex) {
  663. s = $(cell).find('span:eq(0)').text();
  664. if (s == 'Locked') { return 99999999999999; }
  665. if (s == 'Unlocked') { return 88888888888888; }
  666. if (s == 'Unlocked Pre-Tracking') { return 0; }
  667. s = s.isaReplaceAll('/', '').isaReplaceAll(':', '').isaReplaceAll(' ', '');
  668. return s;
  669. }, type: 'numeric'
  670. });
  671. $.tablesorter.addParser({
  672. id: 'isaAstatsPoint', is: function (s) { return false; },
  673. format: function (s) {
  674. if (!(s > 0)) { return 99; }
  675. return s;
  676. }, type: 'numeric'
  677. });
  678. $('body').append('<div id="isaSettingsDialog" title="Improved Steam Achievements - Settings"><fieldset style="width:600px;"><legend>My Details:</legend>' +
  679. '<div class="isaSettingsSetting"><label for="isaMyName">Name</label><input name="isaMyName" type="text" id="isaMyName" style="width:470px;" /></div>' +
  680. '<div class="isaSettingsSetting"><label for="isaMySteamId">Steam 64 ID:</label><input name="isaMySteamId" type="text" id="isaMySteamId" style="width:470px;" /></div>' +
  681. '<div class="isaSettingsSetting"><label for="isaMySteamBit">Steam URL Bit:</label><input name="isaMySteamBit" type="text" id="isaMySteamBit" style="width:470px;" /></div>' +
  682. '</fieldset><fieldset style="width:600px;"><legend>Deliminators:</legend>' +
  683. '<div class="isaSettingsSetting"><label for="isaDelimTitle">Title Deliminator:</label><input name="isaDelimTitle" type="text" id="isaDelimTitle" style="width:470px;" /></div>' +
  684. '<div class="isaSettingsSetting"><label for="isaDelimLink">Link Deliminator:</label><input name="isaDelimLink" type="text" id="isaDelimLink" style="width:470px;" /></div>' +
  685. '</fieldset></div>');
  686. $('#isaSettingsDialog input:eq(0)').val((meName === false ? '' : meName));
  687. $('#isaSettingsDialog input:eq(1)').val((meSteamId === false ? '' : meSteamId));
  688. $('#isaSettingsDialog input:eq(2)').val((meUrlBit === false ? '' : meUrlBit));
  689. $('#isaSettingsDialog input:eq(3)').val(titleDelim);
  690. $('#isaSettingsDialog input:eq(4)').val(linkDelim);
  691. $('#isaSettingsDialog').dialog({
  692. modal:true, resizable: false, autoOpen: false, width: 634, position: { my: "center top", at: "center top+120", of: window },
  693. buttons: [
  694. { text: "Reset To Defaults", click: function() { jsOptionsMenuReset(); } },
  695. { text: "Save Settings", click: function() { jsOptionsMenuSave(); } },
  696. { text: "Close", click: function() { $( this ).dialog( "close" ); } }
  697. ]
  698. });
  699. var settingsButton = $('<div id="isaSettingsContainer"><div id="isaSettingsButton" title="Improved Steam Achievements - Settings"></div></div>');
  700. $(settingsButton).find('#isaSettingsButton').click(function() {$('#isaSettingsDialog').dialog('open');});
  701. $(settingsButton).find('#isaSettingsButton').hover(
  702. function() { $(this).css('background-image', 'url('+settingsIconHover+')');},
  703. function() { $(this).removeAttr('style'); }
  704. );
  705. // =======================================================================================================================
  706. // Achievement Stats Pages - Changes to All Astats Pages
  707. if (urlContains('achievementstats.com') && window.top == window.self) {
  708. $('body').css('font-family', 'Arial');
  709. //$('body').children().not(':first-child').wrapAll('<div id="isaPageWrap" />');
  710. $('div#menuBar').nextAll().not('script').not('link').wrapAll('<div id="isaPageWrap" />');
  711. //$('table').addClass('isaTable');
  712. // ===================================================================================================================
  713. // Achievement Stats - Profile Page
  714. if (urlContains('action=profile') && urlContains('playerId=') && window.location.search.substring(1).split('&').length == 2) {
  715. // Get Info and Elements
  716. var formButton = $('#isaPageWrap > :first-child').detach();
  717. var titleProfileName = $('#isaPageWrap > :first-child').detach().text();
  718. var ul = $('#isaPageWrap > :first-child').detach();
  719. var featureImage = $('#isaPageWrap > :first-child').detach();
  720. var pieChart = $('#isaPageWrap > :first-child').detach().removeAttr('style').css({ 'width': '260px' });
  721. var statsTable = $('#isaPageWrap > :first-child').detach();
  722. if ($('#isaPageWrap > :first-child').text().indexOf('summary') != -1) {
  723. $('#isaPageWrap > :first-child').remove();
  724. $('#isaPageWrap > :first-child').remove();
  725. }
  726. var steamProfileId64 = document.URL.split('playerId=')[1].split('&')[0].split('?')[0].split('#')[0];
  727. $('#isaPageWrap > :first-child').remove();
  728. $('#isaPageWrap > :first-child').css('margin', '3px');
  729. $('#isaPageWrap > table:eq(0)').attr('id', 'isaSecondTable').removeAttr('style').addClass('isaTable isaWidth100');
  730. $(featureImage).removeAttr('style').find('img').removeAttr('style');
  731. $(formButton).removeAttr('style').addClass('isaSmallButton');
  732. $(formButton).find('input').removeAttr('style').attr('value', 'queue profile for update').attr('title', 'Queue this Profile for Update');
  733. // Make Header Table
  734. var isaTopTable = $('<table class="isaTable isaWidth100" id="isaTopTable">' +
  735. '<tr><td rowspan="5" class="isaGameImage"></td><td class="isaTitleCell"></td><td rowspan="5"></td></tr>' +
  736. '<tr><td class="isaStatsLarge"></td></tr><tr><td class="isaLinkContainer"></td></tr><tr><td class="isaLinkContainer"></td></tr><tr><td class="isaStatsCell"></td></tr></table>');
  737. $(isaTopTable).find('td:eq(0)').append(featureImage);
  738. $(isaTopTable).find('td:eq(1)').text(titleProfileName).attr('title', titleProfileName + ' - Profile');
  739. $(isaTopTable).find('td:eq(1)').prepend(settingsButton);
  740. $(isaTopTable).find('td:eq(2)').append(pieChart).css({ 'width':'264px', 'vertical-align':'top', 'overflow':'hidden' });
  741. $(isaTopTable).find('td:eq(4)').html(htmlLinksProfile(steamProfileId64));
  742. $(isaTopTable).find('td:eq(5)').html('<span>Achievement Stats Controls: </span> ' + htmlFromUl(ul));
  743. $(isaTopTable).find('td:eq(5)').append(formButton);
  744. $(statsTable).find('tr').each(function() {
  745. var statLabel = $(this).find('th:eq(0)').text().trim();
  746. var statText = $(this).find('td:eq(0)').html();
  747. if (statLabel == 'Achievements') {
  748. var statTextParts = statText.split('(');
  749. statTextParts[0] = statTextParts[0].trim();
  750. if (statTextParts[0].length > 0) {
  751. $(isaTopTable).find('td:eq(3)').append('<div class="isaStat" title="Total Achievements Unlocked">' + statTextParts[0] + ' achieved</div>');
  752. $(isaTopTable).find('td:eq(3)').append('<div class="isaStat" title="Total Astats Points Earned">' + statTextParts[1].replace(' points)', '') + ' points</div>');
  753. } else {
  754. $(isaTopTable).find('td:eq(3)').append('<div class="isaStat" title="Total Achievements Unlocked"><span class="isaSpanRed">0 achieved</span></div>');
  755. $(isaTopTable).find('td:eq(3)').append('<div class="isaStat" title="Total Astats Points Earned"><span class="isaSpanRed">0 points</span></div>');
  756. }
  757. } else if (statLabel == 'Completion rate') {
  758. statText = statText.replace(' ', '').replace('%', '');
  759. var statPercent = statText / 100;
  760. $(isaTopTable).find('td:eq(3)').append('<div class="isaStat" title="The average percentage of achievements earned per game/DLC.">' + htmlPercentStr(statText + '% average completion', statPercent) + '</div>');
  761. } else {
  762. $(isaTopTable).find('td:eq(6)').append('<div class="isaStat"><span>' + statLabel + ':</span> ' + statText + '</div>');
  763. }
  764. });
  765. var detailLastUpdated = $('table#isaSecondTable').next().detach().text().trim();
  766. if (detailLastUpdated.length > 0) { // profiles not yet crawled have this detail blank (length zero)
  767. $(isaTopTable).find('td:eq(6)').append('<div class="isaStat">' + detailLastUpdated + '</div>');
  768. }
  769. $(isaTopTable).find('td:eq(6)').append('<div class="isaStat">' + $('table#isaSecondTable').next().detach().text() + '</div>');// Next automatic update
  770. // Append and Title
  771. $('#isaPageWrap').prepend(isaTopTable);
  772. document.title = titleProfileName + titleDelim + 'Profile';
  773. titleDone = true;
  774. // Second Table thead Adjustment
  775. $('table#isaSecondTable').prepend('<thead></thead>');
  776. $('table#isaSecondTable > thead').append($('table#isaSecondTable > tbody > tr:lt(2)').detach());
  777. $('table#isaSecondTable > thead > tr:eq(0)').append('<th rowspan="2">Links</th>');
  778. $('table#isaSecondTable > thead > tr:eq(0) > th:eq(3)').css('width', '40px');
  779. $('table#isaSecondTable > thead > tr:eq(0) > th:eq(4)').css('width', '230px');
  780. $('table#isaSecondTable > thead > tr:eq(1) > th:eq(1)').css('width', '40px');
  781. $('table#isaSecondTable > thead > tr:eq(1) > th:eq(2)').css('width', '60px');
  782. $('table#isaSecondTable > thead > tr:eq(1) > th:eq(4)').css('width', '40px');
  783. $('table#isaSecondTable > thead > tr:eq(1) > th:eq(5)').css('width', '60px');
  784. // Second Table tbody Adjustment
  785. var completedGames = 0;
  786. if ($('table#isaSecondTable > tbody > tr:eq(0) > td').length > 1) {
  787. $('table#isaSecondTable > tbody > tr').each(function (index) {
  788. if ($(this).find('td:eq(6)').text() == '0') {
  789. completedGames++;
  790. }
  791. var gameAppId = $(this).find('td:eq(1) > a').attr('href').split('gameId=')[1];
  792. var gameName = $(this).find('td:eq(1) > a').text();
  793. var newCell = $('<td class="isaLinkContainer"></td>').html(htmlLinksGameShort(gameAppId, gameName, steamProfileId64, false));
  794. $(this).append(newCell);
  795. $(this).find('td:eq(0)').addClass('isaListGameImage');
  796. $(this).find('td:eq(1)').addClass('isaListTitle');
  797. $(this).find('td:eq(2)').addClass('isaListAchs');
  798. $(this).find('td:eq(3)').addClass('isaListNumber');
  799. $(this).find('td:eq(4)').addClass('isaListNumber');
  800. $(this).find('td:eq(5)').addClass('isaListAchs');
  801. $(this).find('td:eq(6)').addClass('isaListNumber');
  802. $(this).find('td:eq(7)').addClass('isaListNumber');
  803. $(this).find('td:eq(8)').addClass('isaListNumber');
  804. });
  805. $('table#isaTopTable td:eq(3)').append('<div class="isaStat" title="Games where this player has gotten every achievement.">' +
  806. (completedGames > 0 ? '<span class="isaSpanGre">' + completedGames : '<span class="isaSpanRed">0') + ' completed</span></div>');
  807. jsRowHighlight('table#isaSecondTable');
  808. } else {
  809. $('table#isaSecondTable > tbody > tr:eq(0) > td:eq(0)').attr('colspan','10');
  810. }
  811. }
  812. // ===================================================================================================================
  813. // Achievement Stats - Game Page / DLC Page
  814. if (urlContains('action=games') && urlContains('gameId=') && window.location.search.substring(1).split('&').length == 2) {
  815. var titleGameName = '';
  816. $('#isaPageWrap > form > table:eq(0)').attr('id', 'isaSecondTable').removeAttr('style').addClass('isaTable isaWidth100');
  817. if ($('#isaPageWrap > form').length == 3) { // Game Page
  818. // Get Info and Elements
  819. //alert("sdsadsdf");
  820. var formButton = $('#isaPageWrap > :first-child').detach();
  821. titleGameName = $('#isaPageWrap > :first-child').detach().text();
  822. var featureImage = $('#isaPageWrap > :first-child').detach().find('a:eq(0)');
  823. var dlcElement = $('#isaPageWrap > :first-child').is('p') ? $('#isaPageWrap > :first-child').detach() : false;
  824. var ulElement = $('#isaPageWrap > :first-child').detach();
  825. var detailCompletionTime = $('#isaPageWrap > :first-child').detach().text();
  826. var detail = $('#isaPageWrap > :first-child').find('table > caption:eq(0)').detach().text();
  827. var detailAchCount = detail.split(' achievements ')[0];
  828. var detailAchPoints = detail.split('worth of ')[1].split(' points')[0];
  829. var gameId = document.URL.split('gameId=')[1].split('&')[0].split('?')[0].split('#')[0];
  830. var detailDlcUpdated = $('#isaPageWrap > form:eq(0)').next().detach().text();
  831. var detailNextUpdate = $('#isaPageWrap > form:eq(0)').next().detach().text();
  832. $(featureImage).removeAttr('style').find('img').removeAttr('style');
  833. $(formButton).removeAttr('style').addClass('isaSmallButton');
  834. $(formButton).find('input').removeAttr('style').attr('value', 'update dlc').attr('title', 'Queue this Game for DLC Update');
  835. // Make Header Table
  836. var isaTopTable = $('<table class="isaTable isaWidth100" id="isaTopTable">' +
  837. '<tr><td rowspan="5" class="isaGameImage"></td><td class="isaTitleCell"></td></tr>' +
  838. '<tr><td class="isaStatsLarge"></td></tr><tr><td class="isaLinkContainer"></td></tr><tr><td class="isaLinkContainer"></td></tr><tr><td class="isaStatsCell"></td></tr></table>');
  839. $(isaTopTable).find('td:eq(0)').append(featureImage);
  840. $(isaTopTable).find('td:eq(1)').text(titleGameName).attr('title', 'Achievements for ' + titleGameName);
  841. $(isaTopTable).find('td:eq(1)').prepend(settingsButton);
  842. $(isaTopTable).find('td:eq(2)').append('<div class="isaStat">' + detailAchCount + ' achievement'+ (detailAchCount == 1 ? '' : 's') + '</div>');
  843. $(isaTopTable).find('td:eq(2)').append('<div class="isaStat" title="Astats Point Value of all Achievements">' + detailAchPoints + ' points</div>');
  844. $(isaTopTable).find('td:eq(3)').html(htmlLinksGameLong(gameId, titleGameName, false, achPeople));
  845. $(isaTopTable).find('td:eq(4)').html('<span>Achievement Stats Controls: </span> ' + htmlFromUl(ulElement)).append(formButton);
  846. $(isaTopTable).find('td:eq(5)').append('<div class="isaStat"><span>Average Time Needed for Completion: </span> ' + detailCompletionTime.replace('average hours needed for completion.', '') + 'hours</div>');
  847. $(isaTopTable).find('td:eq(5)').append('<div class="isaStat"><span>DLC Last Updated:</span> ' + detailDlcUpdated.split('updated on')[1] + '</div>');
  848. $(isaTopTable).find('td:eq(5)').append('<div class="isaStat"><span>Next Automatic Update:</span> ' + detailNextUpdate.split('update on')[1] + '</div>');
  849. if (dlcElement !== false) {
  850. $(isaTopTable).find('td:eq(0)').attr('rowspan', '6');
  851. $(isaTopTable).find('tr:eq(1)').after('<tr><td></td></tr>');
  852. $(isaTopTable).find('td:eq(3)').addClass('isaEvenPadding').html(dlcElement.html());
  853. }
  854. // Append and Title
  855. $('#isaPageWrap').prepend('<div class="isaTableSpacer"></div>');
  856. $('#isaPageWrap').prepend(isaTopTable);
  857. document.title = titleGameName + titleDelim + 'Game';
  858. titleDone = true;
  859. } else { // DLC Page
  860. // Get Info and Elements
  861. titleGameName = $('#isaPageWrap > :first-child').detach().text();
  862. var featureImage = $('#isaPageWrap > :first-child').detach().find('a:eq(0)');
  863. var parentGame = $('#isaPageWrap > :first-child').detach();
  864. var ulElement = $('#isaPageWrap > :first-child').detach();
  865. var detail = $('#isaPageWrap > :first-child').find('table > caption:eq(0)').detach().text();
  866. var detailAchCount = detail.split(' achievements ')[0];
  867. var detailAchPoints = detail.split('worth of ')[1].split(' points')[0];
  868. var gameId = parentGame.find('a').attr('href').split('gameId=')[1].split('&')[0].split('?')[0].split('#')[0];
  869. var dlcId = document.URL.split('gameId=')[1].split('&')[0].split('?')[0].split('#')[0];
  870. // Make Header Table
  871. var isaTopTable = $('<table class="isaTable isaWidth100" id="isaTopTable">' +
  872. '<tr><td rowspan="5" class="isaGameImage"></td><td class="isaTitleCell"></td></tr>' +
  873. '<tr><td class="isaStatsLarge"></td></tr><tr><td class="isaEvenPadding"></td></tr><tr><td class="isaLinkContainer"></td></tr><tr><td class="isaLinkContainer"></td></tr></table>');
  874. $(featureImage).removeAttr('style').find('img').removeAttr('style');
  875. $(isaTopTable).find('td:eq(0)').append(featureImage);
  876. $(isaTopTable).find('td:eq(1)').append(document.createTextNode(titleGameName)).attr('title', 'Achievements for ' + titleGameName);
  877. $(isaTopTable).find('td:eq(1)').prepend(settingsButton);
  878. $(isaTopTable).find('td:eq(2)').append('<div class="isaStat">DLC</div>');
  879. $(isaTopTable).find('td:eq(2)').append('<div class="isaStat">' + detailAchCount + ' achievement'+ (detailAchCount == 1 ? '' : 's') + '</div>');
  880. $(isaTopTable).find('td:eq(2)').append('<div class="isaStat" title="Astats Point Value of all Achievements">' + detailAchPoints + ' points</div>');
  881. $(isaTopTable).find('td:eq(3)').html(parentGame.html());
  882. $(isaTopTable).find('td:eq(4)').html(htmlLinksDLC(gameId, dlcId));
  883. $(isaTopTable).find('td:eq(5)').html('<span>Achievement Stats Controls: </span> ' + htmlFromUl(ulElement));
  884. // Append and Title
  885. $('#isaPageWrap').prepend('<div class="isaTableSpacer"></div>');
  886. $('#isaPageWrap').prepend(isaTopTable);
  887. document.title = titleGameName + titleDelim + 'DLC';
  888. titleDone = true;
  889. }
  890. // More Info to Header Table
  891. var brokenCount = $('table#isaSecondTable > tbody > tr.broken').length;
  892. if (brokenCount > 0) {
  893. $('table#isaTopTable td:eq(2)').append('<div class="isaStat" title="Broken Achievements cannot be unlocked."><span class="isaSpanRed">' +
  894. brokenCount + ' broken achievement' + (brokenCount == 1 ? '' : 's') + '</span></div>');
  895. }
  896. var seasonalCount = $('table#isaSecondTable > tbody > tr.seasonal').length;
  897. if (seasonalCount > 0) {
  898. $('table#isaTopTable td:eq(2)').append('<div class="isaStat" title="Seasonal Achievements can only be unlocked unlocked at certain times."><span class="isaSpanYel">' +
  899. seasonalCount + ' seasonal achievement' + (seasonalCount == 1 ? '' : 's') + '</span></div>');
  900. }
  901. var nonrecurringCount = $('table#isaSecondTable > tbody > tr.nonrecurring').length;
  902. if (nonrecurringCount > 0) {
  903. $('table#isaTopTable td:eq(2)').append('<div class="isaStat" title="Non-Recurring Achievements were unlockable for a certain time, but that time has passed."><span class="isaSpanOra">' +
  904. nonrecurringCount + ' non-recurring achievement' + (nonrecurringCount == 1 ? '' : 's') + '</span></div>');
  905. }
  906. var temporaryCount = $('table#isaSecondTable > tbody > tr.temporary').length;
  907. if (temporaryCount > 0) {
  908. $('table#isaTopTable td:eq(2)').append('<div class="isaStat" title="Temporary Achievements are planned to be removed of changed."><span class="isaSpanYel">' +
  909. temporaryCount + ' temporary achievement' + (temporaryCount == 1 ? '' : 's') + '</span></div>');
  910. }
  911. var monetaryCount = $('table#isaSecondTable > tbody > tr.monetary').length;
  912. if (monetaryCount > 0) {
  913. $('table#isaTopTable td:eq(2)').append('<div class="isaStat" title="Monetary Achievements require a purchase to unlock."><span class="isaSpanPin">' +
  914. monetaryCount + ' monetary achievement' + (monetaryCount == 1 ? '' : 's') + '</span></div>');
  915. }
  916. // Second Table thead Adjustment
  917. $('<th rowspan="2">Links</th>').insertAfter($('table#isaSecondTable > thead > tr:eq(0) > th:eq(3)'));
  918. $('table#isaSecondTable > thead > tr:eq(0) > th:eq(2)').detach().insertAfter($('table#isaSecondTable > thead > tr:eq(0) > th:eq(3)'));//move crawled th
  919. $('table#isaSecondTable > thead > tr:eq(0) > th:eq(1)').remove();// remove desc th
  920. $('table#isaSecondTable > thead > tr > th:eq(0)').removeAttr('class');
  921. $('table#isaSecondTable > thead > tr > th:eq(1)').css('width', colWidUnlockPoint + 'px').removeAttr('class').attr('data-sorter', 'isaAstatsPoint');
  922. $('table#isaSecondTable > thead > tr > th:eq(2)').css('width', colWidUnlockLink + 'px').attr('data-sorter', 'false');
  923. $('table#isaSecondTable > thead > tr > th:eq(3)').css('width', '110px').removeAttr('class').attr('data-sorter', 'false');
  924. $('table#isaSecondTable > thead > tr > th:eq(4)').css('width', '96px').removeAttr('class').attr('data-sorter', 'false');
  925. // Second Table tbody Adjustment
  926. if ($('table#isaSecondTable > tbody > tr:eq(0) > td').length > 1) {
  927. $('table#isaSecondTable > tbody > tr').each(function (index) {
  928. //[pic][title/desc][points][links][crawled][report]
  929. // data
  930. var achTitle = $(this).find('td:eq(1) > a').text();
  931. var achDescr = $(this).find('td:eq(2)').text();
  932. var achPoint = $(this).find('td:eq(4)').text();
  933. var achId = $(this).find('td:eq(5) input').attr('value');
  934. var achTitleHtml = $(this).find('td:eq(1)').html();
  935. // cells
  936. $(this).find('td:eq(2)').remove();
  937. $(this).find('td:eq(2)').detach().insertAfter($(this).find('td:eq(2)'));
  938. $('<td></td>').insertAfter($(this).find('td:eq(2)'));
  939. // content
  940. $(this).find('td:eq(1)').html('<h3>' + achTitleHtml + '</h3>' + achDescr);
  941. $(this).find('td:eq(2)').html(htmlAstatsPoint(achPoint));
  942. $(this).find('td:eq(3)').html(htmlLinksAch(titleGameName, achTitle));
  943. $(this).find('td:eq(4)').html($(this).find('td:eq(4)').text().split(' ').join('<br />'));
  944. //styles
  945. $(this).find('td:eq(0)').addClass('isaListAchImage');
  946. $(this).find('td:eq(1)').addClass('isaListAchDetail');
  947. $(this).find('td:eq(2)').addClass('isaListBigNumber isaListTextShadow isaListShadow').removeAttr('style');
  948. $(this).find('td:eq(3)').addClass('isaLinkContainerDark');
  949. $(this).find('td:eq(4)').addClass('isaLinkContainerDark');
  950. $(this).find('td:eq(5)').addClass('isaListNumber');
  951. // row styles and content
  952. var attr = $(this).attr('class');
  953. if (typeof attr !== typeof undefined && attr !== false) {
  954. if (attr == "broken") {
  955. $(this).removeClass('broken').addClass('isaAchBroken');
  956. $(this).find('td:eq(1)').append('<br /><span class="isaSpanRed isaSpanSmallBold">Note: This achievement is Broken</span>');
  957. } else if (attr == 'seasonal') {
  958. $(this).removeClass('seasonal').addClass('isaAchSeasonal');
  959. $(this).find('td:eq(1)').append('<br /><span class="isaSpanOra isaSpanSmallBold">Note: This achievement is Seasonal</span>');
  960. } else if (attr == 'nonrecurring') {
  961. $(this).removeClass('nonrecurring').addClass('isaAchNonRecurring');
  962. $(this).find('td:eq(1)').append('<br /><span class="isaSpanYel isaSpanSmallBold">Note: This achievement is Non-recurring</span>');
  963. } else if (attr == 'temporary') {
  964. $(this).removeClass('temporary').addClass('isaAchTemporary');
  965. $(this).find('td:eq(1)').append('<br /><span class="isaSpanYel isaSpanSmallBold">Note: This achievement is Temporary</span>');
  966. } else if (attr == 'monetary') {
  967. $(this).removeClass('monetary').addClass('isaAchMonetary');
  968. $(this).find('td:eq(1)').append('<br /><span class="isaSpanPin isaSpanSmallBold">Note: This achievement is Monetary</span>');
  969. }
  970. }
  971. });
  972. jsRowHighlight('table#isaSecondTable');
  973. $('table#isaSecondTable').tablesorter({
  974. headers: {
  975. 0: { sortInitialOrder: 'asc' }, 1: { sortInitialOrder: 'asc' }
  976. }
  977. });
  978. }
  979. }
  980. // ===================================================================================================================
  981. // Achievement Stats - Achievement Page
  982. if (urlContains('action=games') && urlContains('achievementId=') && window.location.search.substring(1).split('&').length == 2) {
  983. // Get Info and Elements
  984. var featureImage = $('#isaPageWrap > :nth-child(2)').detach().find('a:eq(0)');
  985. var iconsAndText = $('#isaPageWrap > :nth-child(2)').detach();
  986. var picNo = $(iconsAndText).find(':first-child').detach().removeAttr('style');
  987. var picYes = $(iconsAndText).find(':first-child').detach().removeAttr('style');
  988. var achText = $(iconsAndText).html().split('<br>');
  989. var achTitle = achText[0].replace('<b>', '').replace('</b>', '');
  990. var achDet = achText[1];
  991. var achValue = achText[2].replace('(', '').replace(')', '').split('poi')[0].trim();
  992. var markedAs = $('#isaPageWrap > :nth-child(2)').is('form') ? $('#isaPageWrap > :nth-child(2)').detach() : false;
  993. var markedAsCalender = $('#isaPageWrap > :nth-child(2)').is('p') ? $('#isaPageWrap > :nth-child(2)').detach() : false;
  994. var ul = $('#isaPageWrap > :nth-child(2)').detach();
  995. var gameId = $(featureImage).attr('href').split('gameId=')[1].split('&')[0].split('?')[0].split('#')[0];
  996. var gameName = $(featureImage).attr('title');
  997. $(featureImage).removeAttr('style').find('img').removeAttr('style');
  998. $('#isaPageWrap > table:eq(0)').attr('id', 'isaSecondTable').addClass('isaTable');
  999. // Make Header Table
  1000. var isaTopTable = $('<table class="isaTable isaWidth100" id="isaTopTable">' +
  1001. '<tr><td rowspan="5" class="isaGameIcon"></td><td rowspan="5" class="isaGameIcon"></td><td class="isaTitleCell"></td><td rowspan="5" class="isaGameImage"></td></tr>' +
  1002. '<tr><td></td></tr><tr><td class="isaLinkContainer"></td></tr><tr><td class="isaLinkContainer"></td></tr><tr><td class="isaLinkContainer"></td></tr></table>');
  1003. $(isaTopTable).find('td:eq(0)').append(picYes);
  1004. $(isaTopTable).find('td:eq(1)').append(picNo);
  1005. $(isaTopTable).find('td:eq(2)').html(achTitle + ' (' + htmlAstatsPoint(achValue) + ' points</span>)').attr('title', 'Achievement');
  1006. $(isaTopTable).find('td:eq(2)').prepend(settingsButton);
  1007. $(isaTopTable).find('td:eq(3)').append(featureImage);
  1008. $(isaTopTable).find('td:eq(4)').text(achDet);
  1009. $(isaTopTable).find('td:eq(5)').html(htmlLinksAch(gameName, achTitle, true));
  1010. $(isaTopTable).find('td:eq(6)').html('<span>Achievement Stats Controls: </span> ' + htmlFromUl(ul));
  1011. $(isaTopTable).find('td:eq(7)').html(htmlLinksGameLong(gameId, gameName, false, achPeople));
  1012. if (markedAs !== false) {
  1013. markedAs = $(markedAs).find('ul > li').text().trim();
  1014. $(isaTopTable).find('td:eq(4)').append('<br />');
  1015. if (markedAs == 'Broken') {
  1016. $(isaTopTable).find('td:eq(4)').append('<span class="isaSpanRed isaSpanSmallBold" title="Broken Achievements cannot be unlocked.">Note: This achievement is marked as Broken.</span>');
  1017. } else if (markedAs == 'Seasonal') {
  1018. $(isaTopTable).find('td:eq(4)').append('<span class="isaSpanOra isaSpanSmallBold" title="Seasonal Achievements can only be unlocked unlocked at certain times.">Note: This achievement is marked as Seasonal.</span>');
  1019. } else if (markedAs == 'Non-recurring') {
  1020. $(isaTopTable).find('td:eq(4)').append('<span class="isaSpanYel isaSpanSmallBold" title="Non-Recurring Achievements were unlockable for a certain time, but that time has passed.">Note: This achievement is marked as Non-Recurring.</span>');
  1021. } else if (markedAs == 'Temporary') {
  1022. $(isaTopTable).find('td:eq(4)').append('<span class="isaSpanYel isaSpanSmallBold" title="Temporary Achievements are planned to be removed of changed.">Note: This achievement is marked as Temporary.</span>');
  1023. } else if (markedAs == 'Monetary') {
  1024. $(isaTopTable).find('td:eq(4)').append('<span class="isaSpanPin isaSpanSmallBold" title="Monetary Achievements require a purchase to unlock.">Note: This achievement is marked as Monetary.</span>');
  1025. } else {
  1026. $(isaTopTable).find('td:eq(4)').append('<span class="isaSpanRed isaSpanSmallBold">Note: This achievement is marked as ' + markedAs + '.</span>');
  1027. }
  1028. if (markedAsCalender !== false) {
  1029. $(isaTopTable).find('td:eq(4)').append('<br />');
  1030. $(isaTopTable).find('td:eq(4)').append($(markedAsCalender).children().not('br'));
  1031. }
  1032. }
  1033. // Append and Title
  1034. $('#isaPageWrap > :first-child').after('<div class="isaTableSpacer"></div>');
  1035. $('#isaPageWrap > :first-child').after(isaTopTable);
  1036. document.title = achTitle + titleDelim + 'Achievement';
  1037. titleDone = true;
  1038. }
  1039. // ===================================================================================================================
  1040. // Achievement Stats - Player Unlock History Page
  1041. if (urlContains('action=profile') && urlContains('playerId=') && urlContains('mode=history') && urlContains('gameId=') && window.location.search.substring(1).split('&').length == 4) {
  1042. $('#isaPageWrap > table:eq(0)').attr('id', 'isaSecondTable').addClass('isaTable isaWidth100');
  1043. $('#isaPageWrap > table:eq(1)').attr('id', 'isaLockedTable');
  1044. var thereIsUnlocked = $('table#isaSecondTable > tbody > tr:eq(1) > td').length != 1;
  1045. var thereIsLocked = $('table#isaLockedTable > tbody > tr:eq(1) > td').length != 1;
  1046. if (thereIsUnlocked || thereIsLocked) {
  1047. // Get Info and Elements
  1048. var featureImage = thereIsUnlocked ? $('#isaPageWrap > table:eq(0) > tbody > tr:eq(1) > td:eq(0) > :first-child') : $('table#isaLockedTable > tbody > tr:eq(1) > td:eq(0) > :first-child');
  1049. var titleGameName = $(featureImage).find('img:eq(0)').attr('title');
  1050. var gameAppId = $(featureImage).attr('href').split('gameId=')[1];
  1051. var formButton = $('#isaPageWrap > :first-child').detach(); // put this somewhere
  1052. var titleCellHtml = $('#isaPageWrap > :first-child').detach();
  1053. var playTime = $('#isaPageWrap > :first-child').detach().text().split(' playing')[0];
  1054. $('#isaPageWrap > h3:eq(0)').remove();
  1055. var rssHistoryButton = $(titleCellHtml).find('a:eq(1)').removeAttr('style').css({ 'dislay': 'inline-block', 'margin-left':'15px' });//.css({ 'float':'right' });
  1056. var playerName = $(titleCellHtml).find('a:eq(0)').text();
  1057. var playerId64 = $(titleCellHtml).find('a:eq(0)').attr('href').split('playerId=')[1];
  1058. pushPeople(playerName, playerId64, false);
  1059. $(featureImage).removeAttr('style').find('img').removeAttr('style');
  1060. // Make Header Table
  1061. var isaTopTable = $('<table class="isaTable isaWidth100" id="isaTopTable">' +
  1062. '<tr><td rowspan="4" class="isaGameImage"></td><td class="isaTitleCell"></td></tr>' +
  1063. '<tr><td class="isaStatsLarge"></td></tr><tr><td class="isaLinkContainer"></td></tr><tr class="isaHideCell"><td class="isaLinkContainer"></td></tr></table>');
  1064. $(isaTopTable).find('td:eq(0)').append(featureImage).append(formButton);
  1065. $(isaTopTable).find('td:eq(1)').text(titleGameName).append(rssHistoryButton);
  1066. $(isaTopTable).find('td:eq(1)').prepend(settingsButton);
  1067. var titleAppend = $('<div class="isaTitleAppend isaActionDiv">' + playerName + '\'s Unlock History</div>');
  1068. $(titleAppend).insertBefore(rssHistoryButton);
  1069. $(titleAppend).click(function () { $('table#isaTopTable tr:eq(3)').toggleClass('isaHideCell'); });
  1070. $(titleAppend).hover(function () { $(this).css({ 'text-decoration': 'underline', 'color': '#00c6ff' }); }, function () { $(this).removeAttr('style'); });
  1071. $(isaTopTable).find('td:eq(3)').html(htmlLinksGameLong(gameAppId, titleGameName, false, achPeople));
  1072. $(isaTopTable).find('td:eq(4)').html(htmlLinksProfile(playerId64));
  1073. // Append and Title
  1074. $('#isaPageWrap').prepend('<div class="isaTableSpacer"></div>');
  1075. $('#isaPageWrap').prepend(isaTopTable);
  1076. document.title = playerName + titleDelim + titleGameName + titleDelim + 'Unlock History';
  1077. titleDone = true;
  1078. // Adjust Second Table
  1079. $('table#isaSecondTable').prepend('<thead></thead>');
  1080. $('table#isaSecondTable > thead').append($('table#isaSecondTable > tbody > tr:eq(0)').detach());
  1081. $('table#isaSecondTable > thead > tr > th:eq(0)').remove();
  1082. $('table#isaSecondTable > thead > tr').append('<th style="width:' + colWidUnlockLink + 'px;" data-sorter="false">Links</th>');
  1083. $('table#isaSecondTable > thead > tr > th:eq(1)').css('width', colWidUnlockPoint + 'px').attr('data-sorter', 'isaAstatsPoint');
  1084. $('table#isaSecondTable > thead > tr > th:eq(2)').css('width', colWidUnlockDate + 'px').attr('data-sorter', 'isaDate');
  1085. var achCount = 0;
  1086. var achLockd = 0;
  1087. if (thereIsUnlocked) {
  1088. var rowsUnlocked = $('table#isaSecondTable > tbody > tr');
  1089. for (var i = 0, l = rowsUnlocked.length - 1; i < l; i += 2) {
  1090. $(rowsUnlocked[i]).find('td:eq(0)').remove(); // game image
  1091. $(rowsUnlocked[i]).find('td:eq(0)').addClass('isaListAchImage').removeAttr('rowspan'); //ach icon
  1092. var achTitle = $(rowsUnlocked[i]).find('td:eq(1)').text();
  1093. var achDetail = $(rowsUnlocked[i + 1]).find('td:eq(0)').text();
  1094. $(rowsUnlocked[i]).find('td:eq(1)').addClass('isaListAchDetail').html('<h3>' + achTitle + '</h3>' + achDetail);
  1095. $(rowsUnlocked[i]).find('td:eq(2)').addClass('isaListBigNumber isaListShadow isaListTextShadow').removeAttr('rowspan').removeAttr('style');
  1096. $(rowsUnlocked[i]).find('td:eq(2)').html(htmlAstatsPoint($(rowsUnlocked[i]).find('td:eq(2)').text()));
  1097. $(rowsUnlocked[i]).find('td:eq(3)').addClass('isaListNumber isaListShadow isaListAchUnlocked').removeAttr('rowspan');
  1098. $(rowsUnlocked[i]).append($('<td class="isaLinkContainerDark isaListShadow"></td>').html(htmlLinksAch(titleGameName, achTitle)));
  1099.  
  1100. var achTime = $(rowsUnlocked[i]).find('td:eq(3)').text().trim();
  1101. if (achTime == '') {
  1102. $(rowsUnlocked[i]).find('td:eq(3)').html('<span title="This achievement was unlocked before Steam began tracking the date and time achievements are unlocked.">Unlocked Pre-Tracking</span>');
  1103. } else {
  1104. var achTimeParts1 = $(rowsUnlocked[i]).find('td:eq(3)').text().split(' ');
  1105. var achTimeParts2 = achTimeParts1[0].split('/');
  1106. $(rowsUnlocked[i]).find('td:eq(3)').html('<span>' + achTimeParts2[2] + '/' + achTimeParts2[1] + '/' + achTimeParts2[0] + ' ' + achTimeParts1[1] + '</span>');
  1107. }
  1108. achCount++;
  1109. }
  1110. $('table#isaSecondTable > tbody > tr:odd').remove();
  1111. } else {
  1112. $('table#isaSecondTable > tbody > tr:eq(0)').remove();
  1113. }
  1114. if (thereIsLocked) {
  1115. var rowsLocked = $('table#isaLockedTable > tbody > tr');
  1116. for (var i = 1, l = rowsLocked.length - 1; i < l; i += 2) {
  1117. var achTitle = $(rowsLocked[i]).find('td:eq(2)').text();
  1118. var achDetail = $(rowsLocked[i + 1]).find('td:eq(0)').text();
  1119. $(rowsLocked[i]).find('td:eq(0)').remove(); //game pic
  1120. $(rowsLocked[i]).find('td:eq(0)').addClass('isaListAchImage').removeAttr('rowspan'); // ach icon
  1121. $(rowsLocked[i]).find('td:eq(1)').addClass('isaListAchDetail');
  1122. $(rowsLocked[i]).find('td:eq(1)').html('<h3>' + achTitle + '</h3>' + achDetail);
  1123. $(rowsLocked[i]).find('td:eq(2)').addClass('isaListBigNumber isaListShadow isaListTextShadow').removeAttr('rowspan').removeAttr('style');
  1124. $(rowsLocked[i]).find('td:eq(2)').html(htmlAstatsPoint($(rowsLocked[i]).find('td:eq(2)').text()));
  1125. $(rowsLocked[i]).append('<td class="isaListNumber isaListShadow isaListTextShadow"><span>Locked</span></td>');
  1126. $(rowsLocked[i]).append($('<td class="isaLinkContainerDark isaListShadow"></td>').html(htmlLinksAch(titleGameName, achTitle)));
  1127. $('table#isaSecondTable > tbody').append(rowsLocked[i]);
  1128. achLockd++;
  1129. }
  1130. }
  1131. $('table#isaLockedTable').remove();
  1132. domDateColumn($('table#isaSecondTable > tbody > tr'), 3, $('table#isaTopTable td:eq(2)'));
  1133. jsRowHighlight('table#isaSecondTable');
  1134. // More Info to Header Table
  1135. var achTotal = achCount + achLockd;
  1136. var percentStr = achCount + ' / ' + achTotal + ' (' + (Math.round((achCount * 10000) / achTotal) / 100) + '%) completed';
  1137. $('table#isaTopTable td:eq(2)').prepend('<div class="isaStat" title="Total Time ' + playerName + ' has played this game.">' + playTime + '</div>');
  1138. $('table#isaTopTable td:eq(2)').prepend('<div class="isaStat">' + htmlPercentStr(percentStr, achCount / achTotal) + '</div>');
  1139. $('table#isaTopTable td:eq(2)').prepend('<div class="isaStat">' + achTotal + ' achievements</div>');
  1140. // TableSort Second Table
  1141. $('table#isaSecondTable').tablesorter({
  1142. headers: {
  1143. 0: { sortInitialOrder: 'asc' },
  1144. 1: { sortInitialOrder: 'asc' },
  1145. 2: { sortInitialOrder: 'asc' }
  1146. }
  1147. });
  1148. } else {
  1149. $('#isaPageWrap > h2:eq(0)').addClass('isaPageTitleFirst');
  1150. $('#isaPageWrap > h3:eq(0)').remove();
  1151. $('table#isaSecondTable > tbody > tr:eq(0) > th:eq(0)').remove();
  1152. $('table#isaSecondTable > tbody > tr:eq(1) > td:eq(0)').attr('colspan', '4');
  1153. $('table#isaLockedTable').remove();
  1154. }
  1155. }
  1156. // ===================================================================================================================
  1157. // Title
  1158. if (titleDone === false) {
  1159. var newTitle = document.title;
  1160. newTitle = newTitle.replace('Achievement Stats &raquo; ', '').replace('Achievement Stats » ', '');
  1161. newTitle = newTitle.isaReplaceAll(' &raquo; ', titleDelim).isaReplaceAll(' » ', titleDelim);
  1162. document.title = newTitle;
  1163. }
  1164. }
  1165. // =======================================================================================================================
  1166. if (urlContains('steamcommunity.com')){
  1167. var loggedInSteam64 = false;
  1168. var steamLoggedName = '';
  1169. if($('script:contains("g_steamID")').length > 0){
  1170. var tempStr = $('script:contains("g_steamID"):eq(0)').text().split('g_steamID = "');
  1171. if(tempStr.length == 2){
  1172. loggedInSteam64 = tempStr[1].split('"')[0];
  1173. }
  1174. }
  1175. var steamLoggedIn = loggedInSteam64 != false;
  1176. if(steamLoggedIn){
  1177. var str = $('a.menuitem.supernav.username');
  1178. if (str.length > 0){
  1179. str = (str.length == 1) ? $(str).first() : $(str).eq(1);
  1180. steamLoggedName = $(str).text();
  1181. var tempUrl = $(str).attr('href').split('/home')[0];
  1182. if (tempUrl.indexOf('/id/') != -1) {
  1183. pushPeople(steamLoggedName,loggedInSteam64,tempUrl.split('/id/')[1]);
  1184. }else{
  1185. pushPeople(steamLoggedName,loggedInSteam64,false);
  1186. }
  1187. }else{
  1188. steamLoggedIn = false;
  1189. }
  1190. }
  1191. // ===================================================================================================================
  1192. // Global Achievements Page - Can have Player Stats on it
  1193. if (urlContains('steamcommunity.com/stats/') || urlContains('steamcommunity.com//stats/')) {
  1194. $('div.pagecontent:eq(0)').children().slice(0, 2).wrapAll('<div id="isaPageWrap" />');
  1195. // Get Info and Elements
  1196. var titleGameName = $('#isaPageWrap > :first-child > div > h1:eq(0)').text();
  1197. var featureImage = $('#isaPageWrap > :first-child > div > div > div > a:eq(0)');
  1198. $('#isaPageWrap > :first-child').remove();
  1199. $(featureImage).removeAttr('style').find('img').removeAttr('style');
  1200. var gameId = $(featureImage).attr('href').split('/app/')[1].split('/')[0].split('?')[0];
  1201. var steamUrlBit = document.URL.split('/stats/')[1].split('/')[0].split('?')[0];
  1202. var steamLoggedGameOwned = $('#headerContentLeft').text().split('do not own this').length != 2;
  1203. var steamLoggedGotAchData = $('div.compareImg').length > 0;
  1204. // Make Header Table
  1205. var isaTopTable = $('<table class="isaTable isaWidth100" id="isaTopTable">' +
  1206. '<tr><td rowspan="5" class="isaGameImage"></td><td class="isaTitleCell"></td></tr>' +
  1207. '<tr><td class="isaStatsLarge"></td></tr><tr><td class="isaLinkContainer"></td></tr></tr><tr class="isaHideCell"><td class="isaLinkContainer"></td></tr>'+
  1208. '<tr class="isaHideCell"><td class="isaLinkContainer"></td></tr></table>');
  1209. $(isaTopTable).find('td:eq(0)').append(featureImage);
  1210. $(isaTopTable).find('td:eq(1)').text(titleGameName).attr('title', 'Global Achievement Stats for ' + titleGameName);
  1211. $(isaTopTable).find('td:eq(1)').prepend(settingsButton);
  1212. $(isaTopTable).find('td:eq(3)').html(htmlLinksGameLong(gameId, titleGameName, steamUrlBit, achPeople));
  1213. // Make Second Table
  1214. var isaSecondTable = $('<table class="isaTable isaWidth100" id="isaSecondTable" style="margin-bottom:7px;"><thead><tr><th colspan="2">Achievement</th>' +
  1215. '<th style="width:' + colWidUnlockPercent + 'px;" title="Global Completion Percentage">Global Percent</th>' +
  1216. '<th style="width:' + colWidUnlockDate + 'px;" title="Has this player unlocked the achievement\u000ADate Format: YYYY/MM/DD" data-sorter="'+(steamLoggedGameOwned ? 'isaDate' : false)+'">Unlocked</th>' +
  1217. '<th style="width:' + colWidUnlockLink + 'px;" data-sorter="false">Links</th></tr></thead><tbody></tbody></table>');
  1218. // Append and Title
  1219. $('#isaPageWrap').prepend(isaSecondTable);
  1220. $('#isaPageWrap').prepend('<div class="isaTableSpacer"></div>');
  1221. $('#isaPageWrap').prepend(isaTopTable);
  1222. document.title = titleGameName + titleDelim + ((steamLoggedGotAchData) ? 'Me' + titleDelim + 'Unlock History' : 'Game');
  1223. titleDone = true;
  1224. // Tabs Cell
  1225. var tabs = $('div#tabs > div.tab').not('#achievementsTabOff').not('#achievementsTabOn');
  1226. if(tabs.length > 0){
  1227. $(isaTopTable).find('tr:eq(4)').removeClass('isaHideCell');
  1228. var aHtml = [];
  1229. $(tabs).find('a').each(function () { aHtml.push($(this).parent().html()); });
  1230. var aHtmlJoined = '<span>Other Tabs: </span> ' + aHtml.join(linkDelim);
  1231. $(isaTopTable).find('td:eq(5)').html(aHtmlJoined);
  1232. }
  1233. // Second Table Data
  1234. var achievements = $('div.achieveRow');
  1235. var achCount = 0;
  1236. var achTotal = $(achievements).length;
  1237. if ($(achievements).length > 0) {
  1238. $.each(achievements, function (index, value) {
  1239. var newRow = $('<tr><td class="isaListAchImage"></td><td class="isaListAchDetail"></td><td class="isaListBigNumber isaListShadow isaListTextShadow"></td>' +
  1240. '<td class="isaListNumber isaListShadow"></td><td class="isaLinkContainerDark isaListShadow"></td></tr>');
  1241. var image = $(value).find('div.achieveImgHolder > img:eq(0)');
  1242. var title = $(value).find('div.achieveTxtHolder > div.achieveTxt > h3:eq(0)').text();
  1243. var description = $(value).find('div.achieveTxtHolder > div.achieveTxt > h5:eq(0)').text();
  1244. var percent = $(value).find('div.achieveTxtHolder > div.achievePercent:eq(0)').text();
  1245. $(newRow).find('td:eq(0)').append(image);
  1246. $(newRow).find('td:eq(1)').html('<h3>' + title + '</h3>' + description);
  1247. $(newRow).find('td:eq(4)').html(htmlLinksAch(titleGameName, title, false, gameId));
  1248. domPercentCell($(newRow).find('td:eq(2)'), percent);
  1249. var compare = $(value).find('div.compareImg');
  1250. if ($(compare).length > 0) {
  1251. if ($(compare).find('img:eq(0)').attr('src') == $(image).attr('src')) {
  1252. $(newRow).find('td:eq(3)').addClass('isaListAchUnlocked').html('<span>Unlocked</span>');
  1253. achCount++;
  1254. } else {
  1255. $(newRow).find('td:eq(3)').html('<span>Locked</span>');
  1256. }
  1257. } else if (!steamLoggedGameOwned) {
  1258. $(newRow).find('td:eq(3)').addClass('isaBlackedOut').html('<span>You don\'t own this game</span>');
  1259. }
  1260. $('table#isaSecondTable > tbody:eq(0)').append(newRow);
  1261. });
  1262. if (!steamLoggedIn) {
  1263. $('table#isaSecondTable > tbody:eq(0) tr > td:nth-child(4)').addClass('isaBlackedOut').html('<span>Not Logged In</span>');
  1264. }
  1265. } else {
  1266. $('table#isaSecondTable > tbody:eq(0)').append('<tr><td colspan="5"><div align="center">No Achievements</div></td></tr>');
  1267. }
  1268. $('#isaPageWrap > :nth-child(4)').remove(); // remove achievement data div once all data has been obtained
  1269. jsRowHighlight('table#isaSecondTable');
  1270. // More Info to Header Table and Title Append JS
  1271. $('table#isaTopTable td:eq(2)').append('<div class="isaStat">' + achTotal + ' achievements</div>');
  1272. if (steamLoggedGotAchData) {
  1273. var steamLoggedPercent = Math.round((achCount * 10000) / achTotal) / 100;
  1274. var steamLoggedPercentStr = achCount + ' / ' + achTotal + ' (' + steamLoggedPercent + '%) completed';
  1275. $('table#isaTopTable td:eq(2)').append('<div class="isaStat">' + htmlPercentStr(steamLoggedPercentStr, achCount / achTotal) + '</div>');
  1276. var titleAppend = $('<div class="isaTitleAppend isaActionDiv">My Unlock History</div>');
  1277. $('table#isaTopTable td:eq(1)').append(titleAppend);
  1278. if (steamLoggedIn) {
  1279. $('table#isaTopTable td:eq(4)').html(htmlLinksProfile(loggedInSteam64));
  1280. $(titleAppend).click(function () { $('table#isaTopTable tr:eq(3)').toggleClass('isaHideCell'); });
  1281. $(titleAppend).hover(function () { $(this).css({ 'text-decoration': 'underline', 'color': '#00c6ff' }); }, function () { $(this).removeAttr('style'); });
  1282. }
  1283. }
  1284. // TableSort
  1285. $('table#isaSecondTable').tablesorter({ sortInitialOrder: "asc" });
  1286. // AJAX: Player Unlock Dates
  1287. if (steamLoggedGotAchData && steamLoggedIn) {
  1288. $.ajax({
  1289. type: 'GET', url: 'http://steamcommunity.com/profiles/' + loggedInSteam64 + '/stats/' + steamUrlBit + '/achievements?xml=1', dataType: 'xml',
  1290. success: function (data) {
  1291. var visibilityState = $(data).find('playerstats > visibilityState');
  1292. if (visibilityState.length > 0 && $(visibilityState).text() == '3') {
  1293. //var hoursStat = $(data).find('playerstats > stats > hoursPlayed').text();
  1294. //$('table#isaTopTable td:eq(2)').append('<div class="isaStat" title="Playtime the past two weeks.">' + hoursStat + ' hours</div>');
  1295. $(data).find('playerstats > achievements > achievement').each(function () {
  1296. var achName = $(this).find('name').text();
  1297. var h3 = $('table#isaSecondTable > tbody > tr > td:nth-child(2) > h3').filter(function() { return achName == $(this).text(); });
  1298. if ($(this).attr('closed') == '1') {
  1299. var timeUnlocked = $(this).find('unlockTimestamp');
  1300. if (h3) {
  1301. if (timeUnlocked) {
  1302. $(h3).parent().next().next().html('<span>' + new Date($(timeUnlocked).text() * 1000).isaToString() + '</span>');
  1303. } else {
  1304. $(h3).parent().next().next().html('<span title="This achievement was unlocked before Steam began tracking the date and time achievements are unlocked.">Unlocked Pre-Tracking</span>');
  1305. }
  1306. }
  1307. } else {
  1308. //$(h3).parent().next().next().removeClass('isaListAchUnlocked').html('<span>Locked</span>');
  1309. // maybe xml file isnt updated yet? why show achievement as "locked" when its unlocked...
  1310. }
  1311. });
  1312. domDateColumn($('table#isaSecondTable > tbody > tr'), 3, $('table#isaTopTable td:eq(2)'));
  1313. $('table#isaSecondTable').trigger('updateRows');
  1314. }
  1315. },
  1316. error: function () { }, timeout: 5000
  1317. });
  1318. }
  1319. }
  1320. // ===================================================================================================================
  1321. // Player Achievement Unlock History for a Game
  1322. if (((urlContains('steamcommunity.com/id/') || urlContains('steamcommunity.com//id/')) && urlContains('/stats/')) || (urlContains('steamcommunity.com/profiles/') || urlContains('steamcommunity.com//profiles/')) && urlContains('/stats/')) {
  1323. // Get Info and Elements
  1324. var funnyPage = ($('div.pagecontent:eq(0)').length == 0);
  1325. var comparePage = (urlContains('/compare') && steamLoggedIn && $('a:contains("Remove comparison view")').length > 0);
  1326. if(funnyPage === true){
  1327. $('#BG_top,#BG_bottom').wrapAll('<div id="isaPageWrap" />');
  1328. var titleGameName = $('#isaPageWrap > :first-child > h2:eq(0)').text().isaRemoveEnd(' Stats');
  1329. var featureImage = $('#isaPageWrap > :first-child > div > div > div > a:eq(0)');
  1330. var titleProfileName = $('#isaPageWrap > :first-child > h1:eq(0)').text();
  1331. if(comparePage){
  1332. titleProfileName = $('#isaPageWrap > :first-child > h1:eq(0)').clone().find('span').remove().end().text();
  1333. titleProfileName = titleProfileName.trim().isaRemoveEnd(' vs');
  1334. }
  1335. var profileUrl = $('#isaPageWrap > :first-child > div > div > div > a:eq(1)').attr('href');
  1336. var profileUrlType = (profileUrl.indexOf('/profiles/') != -1);
  1337. var profileUrlBit = profileUrlType ? profileUrl.split('/profiles/')[1] : profileUrl.split('/id/')[1];
  1338. $('#isaPageWrap > :first-child').remove();
  1339. var steamAppId = $(featureImage).attr('href').split('/app/')[1].split('/')[0].split('?')[0].split('#')[0];
  1340. var steamUrlBit = urlContains('/stats/appid/') ? document.URL.split('/stats/appid/')[1].split('/')[0].split('?')[0] : document.URL.split('/stats/')[1].split('/')[0].split('?')[0];
  1341. $(featureImage).removeAttr('style').find('img').removeAttr('style');
  1342. }else{
  1343. $('div.pagecontent:eq(0)').children().slice(0, 2).wrapAll('<div id="isaPageWrap" />');
  1344. var titleGameName = $('#isaPageWrap > :first-child > div > div > a > span:eq(1)').text().isaRemoveEnd(' Stats');
  1345. var featureImage = $('#isaPageWrap > :first-child > div > div > div > a:eq(0)');
  1346. var titleProfileName = $('#isaPageWrap > :first-child > div > div > span> a:eq(0)').text();
  1347. var profileUrl = $('#isaPageWrap > :first-child > div > div > span> a:eq(0)').attr('href');
  1348. var profileUrlType = (profileUrl.indexOf('/profiles/') != -1);
  1349. var profileUrlBit = profileUrlType ? profileUrl.split('/profiles/')[1] : profileUrl.split('/id/')[1];
  1350. $('#isaPageWrap > :first-child').remove();
  1351. var steamAppId = $(featureImage).attr('href').split('/app/')[1].split('/')[0].split('?')[0].split('#')[0];
  1352. var steamUrlBit = urlContains('/stats/appid/') ? document.URL.split('/stats/appid/')[1].split('/')[0].split('?')[0] : document.URL.split('/stats/')[1].split('/')[0].split('?')[0];
  1353. $(featureImage).removeAttr('style').find('img').removeAttr('style');
  1354. }
  1355. if (profileUrlType) {
  1356. pushPeople(titleProfileName,profileUrlBit,false);
  1357. }else{
  1358. pushPeople(titleProfileName,false,profileUrlBit);
  1359. }
  1360. if (comparePage){
  1361. var achSummary = $('#topSummaryAchievements').text().split(' of ');
  1362. var achCount = achSummary[0];
  1363. var achTotal = achSummary[1].split(' (')[0];
  1364. var achCount2 = achSummary[1].split('earned:')[1];
  1365. var achTotal2 = achSummary[2].split(' (')[0];
  1366. var avatarLeft = $('div.topAvatarsLeft > div > div > a:eq(0)');
  1367. var avatarRight = $('div.topAvatarsRight > div > div > a:eq(0)');
  1368. var compareRemovalLink = $('a:contains("Remove comparison view"):eq(0)');
  1369. $('div.topAvatarsLeft').remove();
  1370. $('div.topAvatarsRight').remove();
  1371. // Make Header Table - Apply Some Data
  1372. var isaTopTable = $('<table class="isaTable isaWidth100" id="isaTopTable">' +
  1373. '<tr><td rowspan="5" class="isaListAchImage"></td><td class="isaTitleCell"></td><td rowspan="5" class="isaListAchImage"></td></tr>' +
  1374. '<tr><td class="isaStatsLarge"></td></tr><tr><td class="isaLinkContainer"></td></tr><tr class="isaHideCell"><td class="isaLinkContainer"></td></tr>' +
  1375. '<tr class="isaHideCell"><td class="isaLinkContainer"><span>Other Tabs: </span> </td></tr></table>');
  1376. $(isaTopTable).find('td:eq(0)').append(avatarLeft);
  1377. $(isaTopTable).find('td:eq(1)').append(titleGameName + ' - ' + titleProfileName + ' vs. ' + steamLoggedName + ' (me) - Unlock History Compared - ');
  1378. $(isaTopTable).find('td:eq(1)').append(compareRemovalLink);
  1379. $(isaTopTable).find('td:eq(1)').prepend(settingsButton);
  1380. $(isaTopTable).find('td:eq(2)').append(avatarRight);
  1381. $(isaTopTable).find('td:eq(3)').append('<div class="isaStat">' + achTotal + ' achievements</div>');
  1382. $(isaTopTable).find('td:eq(4)').html(htmlLinksGameLong(steamAppId, titleGameName, steamUrlBit, achPeople));
  1383. var percent = Math.round((achCount * 10000) / achTotal) / 100;
  1384. var percentStr = titleProfileName + ': ' + achCount + ' / ' + achTotal + ' (' + percent + '%) completed';
  1385. $(isaTopTable).find('td:eq(3)').append('<div class="isaStat">' + htmlPercentStr(percentStr, achCount / achTotal) + '</div>');
  1386. var percent2 = Math.round((achCount2 * 10000) / achTotal2) / 100;
  1387. var percentStr2 = steamLoggedName + ' (me): ' + achCount2 + ' / ' + achTotal2 + ' (' + percent2 + '%) completed';
  1388. $(isaTopTable).find('td:eq(3)').append('<div class="isaStat">' + htmlPercentStr(percentStr2, achCount2 / achTotal2) + '</div>');
  1389. if ($('#personalAchieve div.achieveImgHolder').length < achTotal) {
  1390. $(isaTopTable).find('td:eq(3) > div.isaStat:eq(0)').append('&nbsp;<span class="isaSpanRed">(' + (achTotal - $('#personalAchieve div.achieveImgHolder').length) + ' hidden)</span>');
  1391. }
  1392. // Make Second Table
  1393. var isaSecondTable = $('<table class="isaTable isaWidth100" id="isaSecondTable" style="margin-bottom:7px;"><thead><tr>' +
  1394. '<th colspan="2">Achievement</th>' +
  1395. '<th style="width:' + colWidUnlockPercent + 'px;" title="Global Completion Percentage">Global Percent</th>' +
  1396. '<th style="width:' + colWidUnlockDate + 'px;" data-sorter="isaDate" title="Has this player unlocked the achievement\u000ADate Format: YYYY/MM/DD">'+titleProfileName+' Unlocked</th>' +
  1397. '<th style="width:' + colWidUnlockDate + 'px;" data-sorter="isaDate" title="Has this player unlocked the achievement\u000ADate Format: YYYY/MM/DD">'+steamLoggedName+' (me) Unlocked</th>' +
  1398. '<th style="width:' + colWidUnlockLink + 'px;" data-sorter="false">Links</th></tr></thead><tbody></tbody></table>');
  1399. // Append and Title
  1400. $('#isaPageWrap').prepend(isaSecondTable);
  1401. $('#isaPageWrap').prepend('<div class="isaTableSpacer"></div>');
  1402. $('#isaPageWrap').prepend(isaTopTable);
  1403. document.title = titleGameName + titleDelim + titleProfileName + titleDelim + 'Unlock History';
  1404. titleDone = true;
  1405. // Tabs Cell
  1406. var tabs = $('div#tabs > div.tab').not( "#personalAchieveTabOff" ).not( "#personalAchieveTabOn" );
  1407. if(tabs.length > 0){
  1408. $(isaTopTable).find('tr:eq(5)').removeClass('isaHideCell');
  1409. var aHtml = [];
  1410. $(tabs).find('a').each(function () { aHtml.push($(this).parent().html()); });
  1411. var aHtmlJoined = '<span>Other Tabs: </span> ' + aHtml.join(linkDelim);
  1412. $(isaTopTable).find('td:eq(6)').html(aHtmlJoined);
  1413. }
  1414. // Second Table Data
  1415. if ($('#personalAchieve div.achieveImgHolder').length > 0) {
  1416. var achChildren = $('#personalAchieve div.achieveRow');
  1417. for (var i = 0, k = achChildren.length; i < k; i++) {
  1418. var achChild = achChildren[i];
  1419. var newRow = $('<tr><td class="isaListAchImage"></td><td class="isaListAchDetail"></td><td class="isaListBigNumber isaListShadow isaListTextShadow"></td>' +
  1420. '<td class="isaListNumber isaListShadow"></td><td class="isaListNumber isaListShadow"></td><td class="isaLinkContainerDark isaListShadow"></td></tr>');
  1421. var image = $(achChild).find('div:eq(0) img:eq(0)');
  1422. var details = $(achChild).find('div:eq(1)');
  1423. var unlocked = $(details).find('div.achieveUnlockTime');
  1424. var title = $(details).find('div.achieveTxt > h3:eq(0)').text();
  1425. var description = $(details).find('div.achieveTxt > h5:eq(0)').text();
  1426. var progress = $(details).find('div.achievementProgressBar');
  1427. $(newRow).find('td:eq(0)').append(image);
  1428. $(newRow).find('td:eq(1)').html('<h3>' + title + '</h3>' + description);
  1429. $(newRow).find('td:eq(5)').html(htmlLinksAch(titleGameName, title, false, steamAppId));
  1430. if ($(progress).length > 0) {
  1431. progress = $(progress).text();
  1432. $(newRow).find('td:eq(1)').append('<br />');
  1433. $(newRow).find('td:eq(1)').append(progress);
  1434. }
  1435. $(newRow).find('td:eq(2)').text('-');//percent cell
  1436. if (unlocked.length > 0) {
  1437. var unlockedParts = $(unlocked).first().html().split('<br>');
  1438.  
  1439. var unlocked1 = unlockedParts[0].trim();
  1440. if(unlocked1.indexOf('Unlocked') != -1){
  1441. unlocked1 = textDateFixSteam(unlocked1);
  1442. $(newRow).find('td:eq(3)').append('<span>' + unlocked1 + '</span>');
  1443. $(newRow).find('td:eq(3)').addClass('isaListAchUnlocked');
  1444. }else{
  1445. $(newRow).find('td:eq(3)').append('<span>Locked</span>');
  1446. }
  1447.  
  1448. var unlocked2 = unlockedParts[1].trim();
  1449. if(unlocked2.indexOf('Unlocked') != -1){
  1450. unlocked2 = $(unlocked2).text();
  1451. unlocked2 = textDateFixSteam(unlocked2);
  1452. $(newRow).find('td:eq(4)').append('<span>' + unlocked2 + '</span>');
  1453. $(newRow).find('td:eq(4)').addClass('isaListAchUnlocked');
  1454. }else{
  1455. $(newRow).find('td:eq(4)').append('<span>Locked</span>');
  1456. }
  1457. } else {
  1458. $(newRow).find('td:eq(3)').append('<span>Locked</span>');
  1459. $(newRow).find('td:eq(4)').append('<span>Locked</span>');
  1460. }
  1461. $('table#isaSecondTable > tbody:eq(0)').append(newRow);
  1462. }
  1463. } else {
  1464. $('table#isaSecondTable > tbody:eq(0)').append('<tr><td colspan="6"><div align="center">No Achievements</div></td></tr>');
  1465. }
  1466. $('#isaPageWrap > :nth-child(4)').remove();
  1467. jsRowHighlight('table#isaSecondTable');
  1468. // TableSort
  1469. $('table#isaSecondTable').tablesorter({
  1470. headers: {
  1471. 0: { sortInitialOrder: 'asc' },
  1472. 1: { sortInitialOrder: 'desc' },
  1473. 2: { sortInitialOrder: 'asc' },
  1474. 3: { sortInitialOrder: 'asc' }
  1475. }
  1476. });
  1477. // Adjust Second Table - Date Column
  1478. domDateColumn($('table#isaSecondTable > tbody > tr'), 3);
  1479. domDateColumn($('table#isaSecondTable > tbody > tr'), 4);
  1480. // AJAX: Global Percent Cells
  1481. $.ajax({
  1482. type: 'GET', url: 'http://steamcommunity.com/stats/' + steamUrlBit + '/achievements', dataType: 'html',
  1483. success: function (data) {
  1484. $(data).find('#mainContents > div.achieveRow').each(function () {
  1485. var percent = $(this).find('div.achievePercent').text();
  1486. var achName = $(this).find('div.achieveTxt > h3').text().trim();
  1487. var h3 = $('table#isaSecondTable > tbody > tr > td:nth-child(2) > h3').filter(function() { return achName == $(this).text().trim(); });
  1488. if (h3) {
  1489. domPercentCell($(h3).parent().next(), percent);
  1490. }
  1491. });
  1492. $('table#isaSecondTable').trigger('updateRows');
  1493. }, error: function () { }, timeout: 5000
  1494. });
  1495. }else{
  1496. var achSummary = $('#topSummaryAchievements').text().split(' of ');
  1497. var achCount = achSummary[0];
  1498. var achTotal = achSummary[1].split(' (')[0];
  1499. // Make Header Table - Apply Some Data
  1500. var isaTopTable = $('<table class="isaTable isaWidth100" id="isaTopTable">' +
  1501. '<tr><td rowspan="5" class="isaGameImage"></td><td class="isaTitleCell"></td></tr>' +
  1502. '<tr><td class="isaStatsLarge"></td></tr><tr><td class="isaLinkContainer"></td></tr><tr class="isaHideCell"><td class="isaLinkContainer"></td></tr>' +
  1503. '<tr class="isaHideCell"><td class="isaLinkContainer"><span>Other Tabs: </span> </td></tr></table>');
  1504. $(isaTopTable).find('td:eq(0)').append(featureImage);
  1505. $(isaTopTable).find('td:eq(1)').append(titleGameName + '<div class="isaTitleAppend">' + titleProfileName + '\'s Unlock History</div>');
  1506. if (urlContains('/compare')){
  1507. if (steamLoggedIn){
  1508. $(isaTopTable).find('td:eq(1)').append('<span> - You cannot compare to yourself</span>');
  1509. }else{
  1510. $(isaTopTable).find('td:eq(1)').append('<span> - You must be logged in to compare</span>');
  1511. }
  1512. }
  1513. $(isaTopTable).find('td:eq(1)').prepend(settingsButton);
  1514. $(isaTopTable).find('td:eq(3)').html(htmlLinksGameLong(steamAppId, titleGameName, steamUrlBit, achPeople));
  1515. $(isaTopTable).find('td:eq(2)').append('<div class="isaStat">' + achTotal + ' achievements</div>');
  1516. var percent = Math.round((achCount * 10000) / achTotal) / 100;
  1517. var percentStr = achCount + ' / ' + achTotal + ' (' + percent + '%) completed';
  1518. $(isaTopTable).find('td:eq(2)').append('<div class="isaStat">' + htmlPercentStr(percentStr, achCount / achTotal) + '</div>');
  1519. if ($('#personalAchieve div.achieveImgHolder').length < achTotal) {
  1520. $(isaTopTable).find('td:eq(2) > div.isaStat:eq(0)').append('&nbsp;<span class="isaSpanRed">(' + (achTotal - $('#personalAchieve div.achieveImgHolder').length) + ' hidden)</span>');
  1521. }
  1522. // Make Second Table
  1523. var isaSecondTable = $('<table class="isaTable isaWidth100" id="isaSecondTable" style="margin-bottom:7px;"><thead><tr>' +
  1524. '<th colspan="2">Achievement</th>' +
  1525. '<th style="width:' + colWidUnlockPercent + 'px;" title="Global Completion Percentage">Global Percent</th>' +
  1526. '<th style="width:' + colWidUnlockDate + 'px;" data-sorter="isaDate" title="Has this player unlocked the achievement\u000ADate Format: YYYY/MM/DD">Unlocked</th>' +
  1527. '<th style="width:' + colWidUnlockLink + 'px;" data-sorter="false">Links</th></tr></thead><tbody></tbody></table>');
  1528. // Append and Title
  1529. $('#isaPageWrap').prepend(isaSecondTable);
  1530. $('#isaPageWrap').prepend('<div class="isaTableSpacer"></div>');
  1531. $('#isaPageWrap').prepend(isaTopTable);
  1532. document.title = titleGameName + titleDelim + titleProfileName + titleDelim + 'Unlock History';
  1533. titleDone = true;
  1534. // Tabs Cell
  1535. var tabs = $('div#tabs > div.tab').not( "#personalAchieveTabOff" ).not( "#personalAchieveTabOn" );
  1536. if(tabs.length > 0){
  1537. $(isaTopTable).find('tr:eq(4)').removeClass('isaHideCell');
  1538. var aHtml = [];
  1539. $(tabs).find('a').each(function () { aHtml.push($(this).parent().html()); });
  1540. var aHtmlJoined = '<span>Other Tabs: </span> ' + aHtml.join(linkDelim);
  1541. $(isaTopTable).find('td:eq(5)').html(aHtmlJoined);
  1542. }
  1543. // Second Table Data
  1544. if ($('#personalAchieve div.achieveImgHolder').length > 0) {
  1545. var achChildren = $('#personalAchieve').children();
  1546. var doingUnlocked = $('#personalAchieve > br').length == 3;
  1547. var brFound = false;
  1548. for (var i = 0, k = achChildren.length; i < k; i++) {
  1549. var achChild = achChildren[i];
  1550. if ($(achChild).is('div') && $(achChild).find('.achieveHiddenBox').length == 0) {
  1551. var newRow = $('<tr><td class="isaListAchImage"></td><td class="isaListAchDetail"></td><td class="isaListBigNumber isaListShadow isaListTextShadow"></td>' +
  1552. '<td class="isaListNumber isaListShadow"></td><td class="isaLinkContainerDark isaListShadow"></td></tr>');
  1553. var image = $(achChild).find('div:eq(0) img:eq(0)');
  1554. var details = $(achChild).find('div:eq(1)');
  1555. var unlocked = $(details).find('div.achieveUnlockTime');
  1556. var title = $(details).find('div.achieveTxt > h3:eq(0)').text();
  1557. var description = $(details).find('div.achieveTxt > h5:eq(0)').text();
  1558. var progress = $(details).find('div.achievementProgressBar');
  1559. $(newRow).find('td:eq(0)').append(image);
  1560. $(newRow).find('td:eq(1)').html('<h3>' + title + '</h3>' + description);
  1561. $(newRow).find('td:eq(4)').html(htmlLinksAch(titleGameName, title, false, steamAppId));
  1562. if ($(progress).length > 0) {
  1563. progress = $(progress).text();
  1564. $(newRow).find('td:eq(1)').append('<br />');
  1565. $(newRow).find('td:eq(1)').append(htmlSteamAchProgress(progress));
  1566. }
  1567. $(newRow).find('td:eq(2)').text('-');//percent cell
  1568. if (unlocked.length > 0) {
  1569. unlocked = $(unlocked).text();
  1570. unlocked = textDateFixSteam(unlocked);
  1571. $(newRow).find('td:eq(3)').append('<span>' + unlocked + '</span>');
  1572. $(newRow).find('td:eq(3)').addClass('isaListAchUnlocked');
  1573. } else {
  1574. if (doingUnlocked && !brFound) {
  1575. $(newRow).find('td:eq(3)').addClass('isaListAchUnlocked');
  1576. $(newRow).find('td:eq(3)').append('<span title="This achievement was unlocked before Steam began tracking the date and time achievements are unlocked.">Unlocked Pre-Tracking</span>');
  1577. } else {
  1578. $(newRow).find('td:eq(3)').append('<span>Locked</span>');
  1579. }
  1580. }
  1581. $('table#isaSecondTable > tbody:eq(0)').append(newRow);
  1582. } else if (doingUnlocked) {
  1583. if ($(achChild).is('br')) {
  1584. brFound = true;
  1585. }
  1586. }
  1587. }
  1588. } else {
  1589. $('table#isaSecondTable > tbody:eq(0)').append('<tr><td colspan="5"><div align="center">No Achievements</div></td></tr>');
  1590. }
  1591. $('#isaPageWrap > :nth-child(4)').remove();
  1592. jsRowHighlight('table#isaSecondTable');
  1593. // TableSort
  1594. $('table#isaSecondTable').tablesorter({
  1595. headers: {
  1596. 0: { sortInitialOrder: 'asc' },
  1597. 1: { sortInitialOrder: 'desc' },
  1598. 2: { sortInitialOrder: 'asc' }
  1599. }
  1600. });
  1601. // Adjust Second Table - Date Column
  1602. domDateColumn($('table#isaSecondTable > tbody > tr'), 3, $('table#isaTopTable td:eq(2)'));
  1603. // AJAX: Global Percent Cells
  1604. $.ajax({
  1605. type: 'GET', url: 'http://steamcommunity.com/stats/' + steamUrlBit + '/achievements', dataType: 'html',
  1606. success: function (data) {
  1607. $(data).find('#mainContents > div.achieveRow').each(function () {
  1608. var percent = $(this).find('div.achievePercent').text();
  1609. var achName = $(this).find('div.achieveTxt > h3').text().trim();
  1610. var h3 = $('table#isaSecondTable > tbody > tr > td:nth-child(2) > h3').filter(function() { return achName == $(this).text().trim(); });
  1611. if (h3) {
  1612. domPercentCell($(h3).parent().next(), percent);
  1613. }
  1614. });
  1615. $('table#isaSecondTable').trigger('updateRows');
  1616. }, error: function () { }, timeout: 5000
  1617. });
  1618. // AJAX: Get Steam 64 ID
  1619. if (profileUrlType) {
  1620. $('table#isaTopTable td:eq(4)').html(htmlLinksProfile(profileUrlBit));
  1621. var titleAppend = $(isaTopTable).find('div.isaTitleAppend:eq(0)').addClass('isaActionDiv');
  1622. $(titleAppend).click(function () { $('table#isaTopTable tr:eq(3)').toggleClass('isaHideCell'); });
  1623. $(titleAppend).hover(function () { $(this).css({ 'text-decoration': 'underline', 'color': '#00c6ff' }); }, function () { $(this).removeAttr('style'); });
  1624. if (meSteamId !== false && profileUrlBit != meSteamId) {
  1625. pushPeople(titleProfileName,profileUrlBit,false);
  1626. $('table#isaTopTable td:eq(3)').html(htmlLinksGameLong(steamAppId, titleGameName, steamUrlBit, achPeople));
  1627. }
  1628. } else {
  1629. $.ajax({
  1630. type: 'GET', url: 'http://steamcommunity.com/id/' + profileUrlBit + '/?xml=1', dataType: 'xml',
  1631. success: function (data) {
  1632. var steamID64 = $(data).find('profile > steamID64').text();
  1633. $('table#isaTopTable td:eq(4)').html(htmlLinksProfile(steamID64));
  1634. var titleAppend = $('table#isaTopTable div.isaTitleAppend:eq(0)').addClass('isaActionDiv');
  1635. $(titleAppend).click(function () { $('table#isaTopTable tr:eq(3)').toggleClass('isaHideCell'); });
  1636. $(titleAppend).hover(function () { $(this).css({ 'text-decoration': 'underline', 'color': '#00c6ff' }); }, function () { $(this).removeAttr('style'); });
  1637. if (meSteamId !== false && steamID64 != meSteamId) {
  1638. pushPeople(titleProfileName,steamID64,profileUrlBit);
  1639. $('table#isaTopTable td:eq(3)').html(htmlLinksGameLong(steamAppId, titleGameName, steamUrlBit, achPeople));
  1640. }
  1641. }, error: function () { }, timeout: 5000
  1642. });
  1643. }
  1644. }
  1645. }
  1646. // ===================================================================================================================
  1647. // Title
  1648. if (!titleDone) {
  1649. document.title = document.title.replace('Steam Community :: ', '').replace(' :: ', titleDelim);
  1650. }
  1651. }
  1652. // =======================================================================================================================
  1653. // End Brace for document.ready function
  1654. });