decembre

[TS] Citrus GFork v.1.1.49 Fix by KONF + new require

Jan 29th, 2022
434
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // ==UserScript==
  2. // @name                [TS] Citrus GFork v.1.1.49 Fix by KONF (Marqued)  + Decembre fix (New Repos for TSLibrary - Generic (Archive))
  3. // @namespace           TimidScript
  4. // @version             1.1.49
  5. // @date                2019-04-18
  6. // @description         NOW with version number in Listing!! Advance table view for Greasy Fork. Fixes display bugs. 100 scripts display at a time, favoured user count, remembers last sort order used on Script Listing, "My" Profile Listing, and third Party Listing. Able to distinguish between, Library, Unlisted and Deleted scripts using text icons. Beside FireFox, it now supports Opera and Chrome.
  7. // @author              TimidScript
  8. // @homepageURL         https://github.com/TimidScript
  9. // @copyright           © 2014+ TimidScript, Some Rights Reserved.
  10. // @license             https://github.com/TimidScript/UserScripts/blob/master/license.txt
  11. // @include             https://greasyfork.org/*
  12. // @require https://greasyfork.org/scripts/439327-tslibrary-generic-archive/code/TSLibrary%20-%20Generic%20(Archive).js
  13. // @require             https://greasyfork.org/scripts/19968-tslibrary-generic/code/TSLibrary%20-%20Generic.js
  14. // @resource MonkeyIcon https://i.imgur.com/RqikjW1.jpg
  15. // @resource FontAS     https://github.com/TimidScript/UserScripts/raw/master/resources/fonts/FontAwesome.css
  16. // @homeURL             https://greasyfork.org/en/scripts/4336
  17. // @grant               GM_getValue
  18. // @grant               GM_setValue
  19. // @grant               GM_deleteValue
  20. // @grant               GM_listValues
  21. // @grant               GM_xmlhttpRequest
  22. // @grant               GM_info
  23. // @grant               GM_getMetadata
  24. // @grant               GM_registerMenuCommand
  25. // @grant               GM_setClipboard
  26. // @grant               GM_getResourceURL
  27. // @grant               GM_getResourceText
  28. // @icon                data:image/png;base64,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
  29.  
  30. // ==/UserScript==
  31.  
  32.  
  33. /* License + Copyright Notice
  34. ********************************************************************************************
  35. License can be found at: https://github.com/TimidScript/UserScripts/blob/master/license.txt
  36. Below is a copy of the license the may not be up-to-date.
  37.  
  38. Copyright © TimidScript, Some Rights Reserved.
  39.  
  40. Redistribution and use in source and binary forms, with or without modification, are permitted provided that the
  41. following conditions are met:
  42.  
  43. 1) GPL-3 License is met that does not conflict with the rest of the license (http://www.gnu.org/licenses/gpl-3.0.en.html)
  44. 2) This notice must be included
  45. 3) Due credits and link to original author's homepage (included in this notice).
  46. 4) Notify the original author of redistribution
  47. 5) Clear clarification of the License and Notice to the end user
  48. 6) Do not upload on OpenUserJS.org or any other site that infringes on this license
  49.  
  50. TimidScript's Homepages:  GitHub:      https://github.com/TimidScript
  51.                           GreasyFork:  https://greasyfork.org/users/1455
  52. */
  53. /* Information
  54.  
  55.  
  56.  
  57. Suggestions
  58.  - Install record similar to OUJS-1
  59.  - Highlight your username in the forum
  60.  - Highlight your scripts in the forum
  61.  
  62. Unnecessary, unused Code:
  63.     getScriptHTML
  64.     getScriptJSON
  65.     makeStruct
  66.  
  67. TODO: Clean up the code
  68.  
  69. ********************************************************************************************
  70.     Version History
  71. ----------------------------------------------
  72. 1.1.49 2019-04-18
  73.  - Bugfix for Author data-script-author-name -->  data-script-authors.
  74.  - Bugfix in search
  75. 1.1.48 2017-03-18
  76.  - Bugfix: Fixed code that got broken due Changes in layout
  77.  - Add Code search support
  78. 1.1.47 2017-02-03
  79.  - Quickfix: Correctly handle libraries page
  80. 1.1.46 2017-02-02
  81.  - Changed the styling and layout
  82.  - Added library link
  83. 1.1.45.1 2017-01-07
  84.  - Quickfix in CSS
  85. 1.1.45 2017-01-07
  86.  - Change to the Header background-image
  87. 1.1.44 2016-12-16
  88.  - Table view added to feedback listing
  89.  - Sort to favourites added
  90. 1.1.43
  91.  - BugFix: Relevance when searching was not being supported. Now it is always the default in a search
  92.  - BugFix: Search bugs
  93.  - BugFix: Image size to fit parent element (script preview)
  94.  - BugFix: JSON structure has changed
  95.  - Monkey icon is now resource. Should have been years ago
  96.  - Changed the styling of the script preview
  97.  - Stores version numbers, so no longer does a JSON version call if version is up-to-date.
  98.  - Purge all stored script version details if older the 90 days
  99.  - Relative date in the discussion
  100. 1.1.42.1 (2016-10-22)
  101.  - Hotfix: Settings not being stored as I changed the stored name
  102. 1.1.42 (2016-10-22)
  103.  - Depreciated, Obsolete, Defunct and now Unsupported are checked first in description and then version. If it
  104.  is present the script is tagged with "No Longer Supported" orange tag to signify that it is no longer maintained.
  105.  It is recommended to use the keywords in the script description tag rather than version
  106.  - Removed filters and re-implemented the sorting algorithm
  107.  - Settings button added again. Can be found near the monkey icon. It toggles between relative date format and standard date format. Default is relative.
  108.  - Fixed the numbering of listing which must have gotten broken along the way
  109.  - The behaviour of script column sorting is now similar to default
  110.  - New script search button that automatically does partial word search to yield more results. Toggle through settings.
  111.  - Toggle between standard and relative date format is done through settings.
  112. 1.1.41 (2016-10-14)
  113.  - Relative date added
  114.  - Removed date format settings
  115. 1.1.40 (2016-10-14)
  116.  - Bugfix: When editting post the reply type is now stored
  117.  - Added a settings link to change the date format
  118. 1.1.39 (2016-09-03)
  119.  - Added Copy button to library page
  120. 1.1.38 (2016-05-27)
  121.  - Altered the license
  122. 1.1.37 (2016-05-25)
  123.  - Moving to GreasyFork and preparing to remove OUJS files
  124. 1.1.36 (2016-04-10)
  125.  - updateURL added
  126. 1.1.35 (2016-04-03)
  127.  - Changed license to GPL-3
  128. 1.1.34 (2016-02-27)
  129.  - Bug Fix: Displays version number in third party profiles
  130.  - Removed toggle For Deleted scripts
  131.  - Added discussion even when not logged in
  132. 1.1.33 (2015-10-05)
  133.  - Replaced base64 bmp icon with png version
  134. 1.1.32 (2015-07-04)
  135.  - Added overflow style to code tag
  136. 1.1.31 (2015-06-27)
  137.  - Using URI (base64) for script icon
  138. 1.1.30 (2015-06-08)
  139.  - Bug Fix: "Report Bug" and "Review" review button always visible even when there is no need.
  140. 1.1.29 (2015-06-08)
  141.  - Using json to populate the table. This allows the extraction of version number.
  142.  - Changed the feedback system rating interface. Review by default is hidden.
  143.  - Supporting of versions "Obselete", "Depreciated", and "Defunct" similar to the script "OUJS-1"
  144. 1.0.28b (2015-04-04)
  145.  - Bug fix to handle site searches
  146. 1.0.27 (2014-12-28)
  147.  - Bug fix to changes made in 1.0.25
  148.  - Changed the sets into a menu. CSS provided by decembre.
  149. 1.0.26 (2014-12-27)
  150.  - pre tag bug fix
  151. 1.0.25 (2014-12-27)
  152.  - decembre's request to show favourite sets to script listing
  153. script-list-set
  154.  - Bug Fix to support URL local syntax
  155. 1.0.24 (2014-12-06)
  156.  - Bug Fix in script paging
  157.  - Bug Fix due to changes in url flags. Change sort flag from "fans" to "ratings"
  158.  - Add total rating and provided total score also
  159.  - Added counter to the number of users that favoured the script, in feedback tab
  160. 1.0.23 (2014-11-29)
  161.  - Add styling for forum blockquote tag
  162.  - Changes to deal with new GF layout
  163. 1.0.22 (2014-11-07)
  164.  - Fix to handle changes in forum URL (localization added)
  165.  - Add more fonts colours to the forum to distinguish between different types of usernames/links.
  166. 1.0.21 (2014-10-31)
  167.  - Support for Opera now added. Dozen of browsers open causes confusion.
  168. 1.0.20 (2014-10-31)
  169.  - Change table header "Fans" to "Score"
  170.  - Slight changes to forum CSS
  171.  - Support for Opera and Chrome added.
  172. 1.0.19 (2014-10-23)
  173.  - Removed sign-out button as it has been added with today's site update
  174. 1.0.18 (2014-10-23)
  175.  - Bug fix to accommodate new site changes to the URL syntax (localization added)
  176. 1.0.17 (2014-10-18)
  177.  - Changed the framing of images to suite smaller images better
  178.  - Credit link now points to my GF profile rather than OUJS
  179.  - Added sign-out near the name
  180.  - Bug fix: add script table only when need
  181. 1.0.16 (2014-09-29)
  182.  - Got rid of the flashing timer
  183. 1.0.15 (2014-09-29)
  184.  - Fixed the issue that 1.0.14 supposedly had fixed
  185.  - Appreciation notice added
  186. 1.0.14 (2014-09-22)
  187.  - Re-fixed profile table sort :?
  188. 1.0.13 (2014-09-19)
  189.  - Fix in profile table sort
  190. 1.0.12 (2014-09-19)
  191.  - Bug fix in sorting of lists with search. Not using global flag when matching regex
  192. 1.0.11 (2014-09-16)
  193.  - Bug fix in search listing introduced in version 1.0.10
  194. 1.0.10 (2014-09-16)
  195.  - Bug Fix: Daily installs sort order
  196.  - Click on separator to toggle deleted script display
  197. 1.0.9 (2014-09-07)
  198.  - Added new CSS  for <code> and <pre> elements
  199. 1.0.8 (2014-08-03)
  200.  - Author name next to title
  201. 1.0.7 (2014-08-29)
  202.  - Added GM_update
  203.  - Added script numbers to table
  204. 1.0.6 (2014-08-21)
  205.  - Bug Fix for sorting
  206. 1.0.5 (2014-08-21)
  207.  - Small CSS fix provided by decembre (https://greasyfork.org/forum/discussion/comment/4182)
  208. 1.0.4 (2014-08-20)
  209.  - Bug Fix: Author not being displayed
  210.  - Bug Fix: Handle missing elements in user profile
  211. 1.0.3 (2014-08-20)
  212.  - Link to my homepage
  213.  - By default deleted scripts are hidden now
  214.  - Stole some CSS from OUJS ^_^
  215.  - Added a frame around images and max-width
  216.  - Few small bug fixes
  217. 1.0.2 (2014-08-19)
  218.  - Changes to CSS, including smaller font
  219.  - Changed the interface
  220.  - Added filter on user profile
  221.  - Changed the behaviour of column click. If clicked it goes to first page as oppose to remaining on the same page
  222.  - Increased number of scripts returned to 100
  223.  - Citrified, orangified and crucified the forum. ( ̄ _ゝ ̄)
  224.  - Small bug fixes
  225. 1.0.1 (2014-08-18)
  226.  - Initial release. Released as good enough. May contain bugs but good for general usage.
  227.  
  228. **********************************************************************************************/
  229.  
  230. (function ()
  231. {
  232.     var scripts = new Array(),
  233.         pathname = decodeURIComponent(document.location.pathname);
  234.  
  235.     TSL.addStyle("OverFlowCode", ".Comment .Message p {overflow-x:auto;}");
  236.     TSL.addStyle("FontAwesomeCSS", GM_getResourceText("FontAS"));
  237.  
  238.     OrangifyPage();
  239.     if (pathname.match(/(\w|-)+\/forum\/(post|discussion)\//) && document.getElementById("Form_Rating"))
  240.     {
  241.         TSL.addStyle("", ".choiceButtons {text-align:center; width: 80px;}");
  242.  
  243.         var po = document.querySelector(".PostOptions, .CommentOptions"),
  244.             lbl = po.querySelector("label"),
  245.             options = po.querySelectorAll(".RadioLabel"),
  246.             hld = document.createElement("div"),
  247.             btn1 = document.createElement("input"),
  248.             btn2 = document.createElement("input");
  249.  
  250.         btn1.className = btn2.className = "choiceButtons  Button";
  251.         btn1.value = "Report bug"; btn1.style.marginRight = "4px";
  252.         btn2.value = "Review";
  253.  
  254.         btn1.onclick = function (e)
  255.         {
  256.             btn1.style.color = "#2DCD05";
  257.             btn2.style.color = "";
  258.  
  259.             options[0].setAttribute("style", "margin-top: 5px !important;");
  260.             options[4].removeAttribute("style");
  261.  
  262.             options[1].setAttribute("style", "display: none !important;"); //options[1].style.display = "none !important";
  263.             options[2].setAttribute("style", "display: none !important;");
  264.             options[3].setAttribute("style", "display: none !important;");
  265.             lbl.setAttribute("style", "display: none !important;");
  266.  
  267.             if (e) options[0].click();
  268.         }
  269.  
  270.         btn2.onclick = function (e)
  271.         {
  272.             btn1.style.color = "";
  273.             btn2.style.color = "#2DCD05";
  274.  
  275.             options[0].setAttribute("style", "display: none !important;");
  276.             options[4].setAttribute("style", "display: none !important;");
  277.  
  278.             options[1].removeAttribute("style");
  279.             options[2].removeAttribute("style");
  280.             options[3].removeAttribute("style");
  281.             lbl.removeAttribute("style");
  282.  
  283.             if (e) options[3].click();
  284.         }
  285.  
  286.         hld.appendChild(btn1);
  287.         hld.appendChild(btn2);
  288.         po.insertBefore(hld, po.firstElementChild);
  289.  
  290.         //for (var i = 0; i < options.length; i++) console.log(options[i].firstElementChild.checked);
  291.         if (options[0].firstElementChild.checked || options[4].firstElementChild.checked) btn1.click(false);
  292.         else btn2.click(false);
  293.     }
  294.     else if (pathname.match(/\/[\w-]+\/scripts\/\d+/)) //Script Page
  295.     {
  296.         TSL.addStyle("", "#script-content {background-color: #F9ECDB; margin: 0; padding-bottom: 5px;} #script-links > li:hover { background-color: yellow; } .current {background-color: #F9ECDB !important;}");
  297.         TSL.addStyle("", ".install-link {background-color: #F7A207;} .install-help-link {background-color: #F9C565 !important;} #script-meta {padding-bottom:5px;} #script-feedback-suggestion, #script-meta {padding-left:5px;padding-right:5px;}");
  298.         TSL.addStyle("", "#additional-info {padding: 5px 0;} #additional-info, #additional-info > div {background-color: white;} #additional-info > h3 {padding: 5px 0; margin:0;} #additional-info > div.script-author-description {margin: 0 0;}");
  299.         TSL.addStyle("", "header:first-child {background-color:white; padding: 5px 10px;}");
  300.         TSL.addStyle("", ".fa-sort-alpha-asc[on] {color:blue; background-color: yellow;} .fa-sort-alpha-asc {margin-left: 5px;cursor:pointer; padding: 0 3px;} .fa-sort-alpha-asc:hover {background-color: brown; color: yellow;}");
  301.  
  302.         var notice = document.createElement("div");
  303.         notice.textContent = "Show your appreciation to the author by favouring the script and giving positive feedback";
  304.         notice.setAttribute("style", "padding: 3px 10px; border-radius: 4px; background-color: yellow; text-align: center;");
  305.  
  306.         if (pathname.match(/\/scripts\/[^\/]+\/feedback/i))
  307.         {
  308.             el = document.querySelector("#script-content");
  309.             if (el) el.insertBefore(notice, el.firstElementChild);
  310.  
  311.             el = document.querySelector(".inline-list");
  312.  
  313.             var count = el.querySelectorAll("li").length;
  314.  
  315.             var users = [];
  316.             var els = document.querySelectorAll(".inline-list li");
  317.             for (var i = 0; i < els.length; i++)
  318.             {
  319.                 els[i].setAttribute("position", i)
  320.                 users.push(els[i]);
  321.             }
  322.  
  323.             el = document.getElementById("feedback-favoriters");
  324.             el.innerHTML += " (<span style='color: #F00;'>" + count + "</span>";
  325.             el.innerHTML += '<i class="fa fa-sort-alpha-asc"></i>)';
  326.             el.lastElementChild.onclick = function (e)
  327.             {
  328.                 this.enabled = (this.enabled !== true);
  329.                 GM_setValue("Feedback Sorted", this.enabled);
  330.                 var il = document.querySelector(".inline-list");
  331.                 if (this.enabled)
  332.                 {
  333.  
  334.                     this.setAttribute("on", "");
  335.                     users.sort(function (a, b)
  336.                     {
  337.                         if (a.firstElementChild.textContent.toLowerCase() > b.firstElementChild.textContent.toLowerCase()) return 1;
  338.                         else return -1;
  339.                     });
  340.                     for (var i = 0; i < users.length; i++) il.appendChild(users[i]);
  341.                 }
  342.                 else
  343.                 {
  344.                     this.removeAttribute("on");
  345.                     users.sort(function (a, b)
  346.                     {
  347.                         if (parseInt(a.getAttribute("position")) > parseInt(b.getAttribute("position"))) return 1;
  348.                         else return -1;
  349.                     });
  350.                     for (var i = 0; i < users.length; i++) il.appendChild(users[i]);
  351.                 }
  352.             };
  353.             if (GM_getValue("Feedback Sorted", false)) document.querySelector(".fa-sort-alpha-asc").click();
  354.  
  355.             var els = document.querySelectorAll("#discussions > li");
  356.             if (GM_getValue("Feedback Table View", false) && els.length > 0)
  357.             {
  358.                 el = document.getElementById("discussions");
  359.                 var tab = document.createElement("table");
  360.                 tab.id = "DiscussionsTab";
  361.                 el.parentElement.insertBefore(tab, el);
  362.  
  363.                 TSL.addStyle("FeedbackTable", '#DiscussionsTab {width:100%; border-spacing: 0; border-collapse: collapse;}' //border:1px solid black;
  364.                     + '#DiscussionsTab tr {border-bottom: 1px solid gray;}'
  365.                     + '#DiscussionsTab div[class^=discussion] {height: 16px; width: 16px; margin: 0 5px; background-size: height: 16px; width: 16px;}'
  366.                     + '#DiscussionsTab .discussion-question {background-image: url(/images/circle-blue.png);}'
  367.                     + '#DiscussionsTab .discussion-alien {background-image: url(/images/circle-alien.png);}'
  368.                     + '#DiscussionsTab .discussion-good {background-image: url(/images/circle-green.png);}'
  369.                     + '#DiscussionsTab .discussion-ok {background-image: url(/images/circle-yellow.png);}'
  370.                     + '#DiscussionsTab .discussion-bad {background-image: url(/images/circle-red.png);}'
  371.                     + '#discussions {display:none;}'
  372.                     );
  373.  
  374.                 for (var i = 0, l, t, m, r, c, d; i < els.length; i++)
  375.                 {
  376.                     l = els[i].querySelectorAll("a"),
  377.                     t = els[i].querySelectorAll("time"),
  378.                     m = els[i].innerHTML.match(/<\/a>\s+([^<]+)\s+/g); //Too hard to extract the information for different languages one cannot speak
  379.  
  380.                     r = tab.insertRow(-1);
  381.  
  382.                     c = r.insertCell(-1);
  383.                     d = document.createElement("div");
  384.                     d.className = els[i].className;
  385.                     c.appendChild(d);
  386.  
  387.                     c = r.insertCell(-1);
  388.                     d = document.createElement("div");
  389.                     d.appendChild(l[0].cloneNode(true));
  390.                     c.appendChild(d);
  391.                     d = document.createElement("div");
  392.                     d.appendChild(l[1].cloneNode(true));
  393.                     d.innerHTML += "<span> >> </span>"
  394.                     d.appendChild(t[0]);
  395.                     c.appendChild(d);
  396.  
  397.                     if (l.length == 3)
  398.                     {
  399.                         c = r.insertCell(-1);
  400.  
  401.                         d = document.createElement("div");
  402.                         d.appendChild(l[2].cloneNode(true));
  403.                         c.appendChild(d);
  404.  
  405.                         d = document.createElement("div");
  406.                         d.appendChild(t[1]);
  407.                         c.appendChild(d);
  408.                     }
  409.                 }
  410.             }
  411.         }
  412.         else
  413.         {
  414.             var el = document.querySelector("#install-area");
  415.             if (el) el.appendChild(notice);
  416.         }
  417.     }
  418.     else if (!/\/scripts\/libraries/.test(location.pathname) && pathname.match(/\/[\w-]+\/scripts/)) //Script Listing
  419.     {
  420.         console.info("Script Listing");
  421.         document.body.setAttribute("PageType", "ListingPage");
  422.         getScripts();
  423.  
  424.         if (scripts.length > 0)
  425.         {
  426.             var isRelativeSearch = pathname.match(/scripts\/search/i) != null;
  427.             createScriptTable(pathname.match(/scripts\/search/i) != null);
  428.             populateScriptTable();
  429.  
  430.  
  431.             if (document.getElementById("script-table"))
  432.             {
  433.                 document.body.insertBefore(document.getElementById("script-table"), document.getElementById("main-header").nextElementSibling);
  434.                 //document.querySelector("#script-table tr td:nth-child(2)").appendChild(document.getElementById("UserSets"));
  435.  
  436.                 if (isRelativeSearch)
  437.                 {
  438.                     el = document.createElement("div");
  439.                     el.setAttribute("style", "text-align: right; padding: 1px 50px");
  440.                     el.appendChild(document.createElement("span"));
  441.                     document.body.insertBefore(el, document.getElementById("script-table"));
  442.  
  443.                     el = el.firstElementChild;
  444.                     el.id = "RelativeSearch";
  445.                     el.setAttribute("tag", "");
  446.                     el.textContent = "Relative Search";
  447.                     el.onclick = onTableHeaderClick;
  448.  
  449.                     TSL.addStyle("RelativeSearchCSS", '#RelativeSearch {display: inline-block; background-color:orange; border-radius: 3px; padding: 3px 20px; text-align: center; width: 300px;cursor:pointer;}');
  450.                 }
  451.  
  452.                 if (document.getElementById("UserSets"))
  453.                 {
  454.                     TSL.addStyle("TheBlackLagoon", "#UserSets {position: absolute !important;display: inline-table !important;float: none !important;left: 30px !important;top: 68px!important;padding: 2px 5px;background-color: yellow;border-radius: 5px;z-index: 200!important;visibility: hidden!important;opacity: 1!important;}"
  455.                                + "#UserSets:hover {visibility: visible!important;opacity: 1!important;}"
  456.                                + '#UserSets:before {content: "Sets ▼" !important; position: absolute !important;display: inline-block !important;left: 40px !important;top: -20px!important;margin: 2px 10px;padding: 1px 10px!important;background-color: yellow;border-radius: 5px;z-index: 200!important;visibility:visible!important;opacity: 1!important;}'
  457.                                + "#UserSets li {position: relative !important;display: inline !important;float: left!important;clear: both!important;min-width: 200px!important;margin-bottom: 2px!important;padding: 2px 8px;background-color: white;border-radius: 2px; text-align:left;}"
  458.                                );
  459.  
  460.                     TSL.addStyle("TheBlackLagoon", "#UserSets, #UserSets:before {position: absolute;top: 4px;float: left;background-color: #FFC763;border-radius: 5px;z-index: 200;opacity:1;}"
  461.                     + "#UserSets {display: inline-table;left:10px;padding: 2px 5px;visibility: hidden;}"
  462.                     + "#UserSets:hover {visibility: visible;opacity: 1;}"
  463.                     + '#UserSets:before {display: inline-block;left: 40px;top:-18px;content: "Sets ▼";padding: 1px 10px;visibility: visible;}'
  464.                     + "#UserSets li {position: relative;display: inline;float: left;clear: both;min-width: 200px;margin-bottom: 2px;padding: 2px 8px;background-color: white;border-radius: 2px; text-align:left;}"
  465.                     );
  466.  
  467.                     try
  468.                     {
  469.                         document.querySelector("[tag=name]").appendChild(document.getElementById("UserSets"));
  470.                     } catch(e) {};
  471.                 }
  472.  
  473.  
  474.  
  475.                 //TODO: Need to fix the Sets filter in listing search
  476.                 //var header = document.querySelectorAll("#script-table thead td")[1],
  477.                 //    sets = document.getElementById("UserSets");
  478.  
  479.                 //header.appendChild(sets);
  480.             }
  481.  
  482.             selectSortOrder("ListingPage", isRelativeSearch);
  483.  
  484.             TSL.removeNode("browse-script-list");
  485.         }
  486.     }
  487.     else if (document.URL.match(/\/users\/(\w|-)+/)) //Authors Profile Page
  488.     {
  489.         var pageType = (document.getElementById("control-panel")) ? "PersonalProfile" : "UserProfile";
  490.         document.body.setAttribute("PageType", pageType);
  491.         document.body.setAttribute("ProfilePage", "");
  492.  
  493.         getScripts();
  494.         OrangifyUserPage();
  495.  
  496.         if (scripts.length > 0)
  497.         {
  498.             createScriptTable();
  499.             populateScriptTable();
  500.  
  501.             selectSortOrder(pageType);
  502.         }
  503.     }
  504.  
  505.  
  506.     //Purge script details older than 90 days
  507.     var now = Date.now(), names = GM_listValues();
  508.     for (var i = 0; i < names.length; i++)
  509.     {
  510.         if (! /^Script:\d+/.test(names[i])) continue;
  511.  
  512.         //If greater than 30 days remove    1000*60*60*24=86400000
  513.         if ((now - JSON.parse(GM_getValue(names[i])).timestamp) / 86400000 > 90) GM_deleteValue(names[i]);
  514.     }
  515.  
  516.     /* Base CSS styling
  517.     ---------------------------------------------------------------------------*/
  518.     function OrangifyPage()
  519.     {
  520.         //#region Adding CSS Styles E3E2E2
  521.         TSL.addStyle("CitrusGF_Main", "body {font-size: 14px;} .pagination {text-align:center;}"
  522.                       + "#main-header, #Head {background-color: orange !important; background-image: none !important;} #Head a, #site-nav a {color: yellow !important;}"
  523.                       + ".current, .HomepageTitle, .Active a {border-color: orange !important;}"
  524.                       + "#site-name {text-decoration: underline; color: white;}"
  525.                       + "#title-image {height: 50px; border-radius: 20px; margin-left: 5px;}"
  526.                       + "#title-text {font-size: 40px; color:black; font-family:'Open Sans',sans-serif; font-weight: 400; margin: 0 10px; line-height: 48px;}"
  527.                       + "#title-subtext {color: yellow !important; font-size: 10px; text-decoration: none; position: absolute; left: 210px; top: 43px; font-weight: 400 !important;}"
  528.                       + "#settings-subtext {color: yellow !important; font-size: 10px; text-decoration: none; position: absolute; left: 70px; top: 43px; font-weight: 400 !important;}"
  529.                       + "#nav-user-info {top: 3px;}"
  530.                       + "pre {background-color: #FFFF99; padding: 5px; margin-left: 30px; padding: 5px 10px;}"
  531.                       + "code {padding: 2px 4px; font-size: 90%; color: #C7254E; background-color: #F9F2F4; white-space: nowrap; border-radius: 4px; font-family: Menlo,Monaco,Consolas,'Courier New',monospace;}"
  532.                       + "pre > code {white-space: pre; background-color: transparent;}"
  533.                       + "#CForkSettings {position: fixed; top: 150px; background:white; border: 5px groove orangered; width: 400px;}"
  534.                       + "#CForkSettings > div {margin: 5px 10px}"
  535.                       + "#CForkSettings > footer {background-color:orange; padding: 1px 5px;text-align:right;}"
  536.                       + "#CForkSettings label {cursor: default;}"
  537.                       + ".preview-result {background-color: white; border-top: 10px ridge black;}"
  538.                       + ".preview-result img {max-width: 98%;}"
  539.                       + "#script-table, [ProfilePage] > .width-constraint {display: block; margin: 5px auto; max-width:1000px;min-width:700px;border-radius: 0;box-shadow: 0 0 2px gray;}"
  540.                       + "#script-search > input[type=submit], .sidebar-search > input[type=submit] {cursor:pointer;}"
  541.                       );
  542.  
  543.         TSL.addStyle("CitrusGF_ScriptPage", "#additional-info img {max-width: 98%; border: 1px solid orange; box-shadow: 5px 5px 2px #888888; margin: 5px 0; padding: 2px; color: yellow; }");
  544.  
  545.         if (document.location.pathname.match(/[\w-]+\/forum\//i))
  546.         {
  547.             TSL.addStyle("CitrusGF_Forum", "body:not(.Settings) a:not(.Button) { color: #F19E06; }"
  548.                 + "body a.Username { color: #E17205 !important; }"
  549.                 + ".QuoteAuthor a[href*='forum/profile/'] { color: #FB4507 !important;}"
  550.                 + "a[href*='forum/profile/'] { color: #25C614 !important; font-weight: 600;}"
  551.                 + "code {padding: 1px 3px; border-radius: 3px; border: 1px solid; background-color: #F9EBD2; color: #EB5100; margin: 0;}"
  552.                 + "#title-subtext {top: 45px;}"
  553.                 + "blockquote {background-color: #FFFFA4; margin: 5px 0px 5px 30px; padding: 5px;}"
  554.                 );
  555.         }
  556.         //#endregion
  557.  
  558.  
  559.         var el = document.querySelector(".sidebar-search");
  560.         if (el)
  561.         {
  562.             TSL.addStyle("SSSearch", ".sidebar-search {display:inline-block;vertical-align: unset;} .sidebar-search input[name=q] {width:164px; margin:0 !important; width: 164px !important;}"
  563.                 + ".sidebar-search > input {line-height:16px;font-size:14px;} .sidebar-search [value='✱'] {right:20px !important;}");
  564.  
  565.             document.querySelector("#site-nav nav").appendChild(el);
  566.         }
  567.  
  568.         var sname = document.getElementById("site-name");
  569.         sname.innerHTML = "";
  570.  
  571.         var link = document.createElement("a");
  572.         link.href = "/";
  573.         link.innerHTML = '<img id="title-image" src="' + GM_getResourceURL("MonkeyIcon") + '" />'
  574.                         + '<span id="title-text">Greasy Fork&nbsp;</span>'
  575.                         + '<span id="settings-subtext">Settings</span>'
  576.                         + '<a id="title-subtext" href="/users/1455-timidscript">100% Citrusy Goodness by <b>TimidScript</b></span>';
  577.         sname.appendChild(link);
  578.  
  579.         var li = document.createElement("li");
  580.         link = document.createElement("a")
  581.         link.textContent = "Libraries";
  582.         link.href = "/scripts/libraries";
  583.         link.style.marginRight = "20px";
  584.         li.appendChild(link);
  585.         document.querySelector("nav").insertBefore(li, document.querySelector("nav").firstElementChild);
  586.  
  587.         var scriptsearch = document.querySelector("#script-search, .sidebar-search");
  588.         if (scriptsearch)
  589.         {
  590.             var el = document.createElement("input");
  591.             el.type = "submit";
  592.             el.value = "✱";
  593.             el.title = "Partial Search";
  594.             el.onclick = function (e)
  595.             {
  596.                
  597.                 e.stopImmediatePropagation();
  598.                 //var search = document.querySelector("#script-search [type=search], .sidebar-search [type=search]");
  599.                 var search = document.querySelector("[type=search]");
  600.                 search.value = "*" + search.value.trim() + "*";
  601.                 search.value = search.value.replace(/^\*\*|\*\*$/g, "*");                
  602.             }
  603.  
  604.             if (GM_getValue("Use Original Search")) scriptsearch.appendChild(el);
  605.             else scriptsearch.insertBefore(el, scriptsearch.lastElementChild);
  606.         }
  607.  
  608.         document.getElementById("settings-subtext").onclick = function (e)
  609.         {
  610.             e.stopImmediatePropagation();
  611.             if (document.getElementById("CForkSettings")) return false;
  612.  
  613.             var settings = document.createElement("settings");
  614.             settings.id = "CForkSettings";
  615.             settings.innerHTML = '<div><input type="checkbox"><label> Use standard date format (e.g. 2016-01-30) rather than relative (e.g. 5 days ago)</label></div>'
  616.                         + '<div><input type="checkbox"><label> Disable partial search set as default search option</label></div>'
  617.                         + '<div><input type="checkbox"><label> Enable feedback table view</label></div>'
  618.                         + '<footer><button>Accept</button></footer>';
  619.  
  620.  
  621.             settings.style.left = ((document.body.clientWidth / 2) - 200) + "px";
  622.             document.body.appendChild(settings);
  623.             var lbls = settings.querySelectorAll("label");
  624.  
  625.             lbls[0].onclick = lbls[1].onclick = lbls[2].onclick = function (e) { this.previousElementSibling.click(); };
  626.  
  627.             var ipts = settings.querySelectorAll("input"), btn = settings.querySelector("button");
  628.  
  629.             if (GM_getValue("Use Standard Date Format", false)) ipts[0].checked = "checked";
  630.             if (GM_getValue("Use Original Search", false)) ipts[1].checked = "checked";
  631.             if (GM_getValue("Feedback Table View", false)) ipts[2].checked = "checked";
  632.  
  633.             btn.onclick = function (e)
  634.             {
  635.                 if (ipts[0].checked) GM_setValue("Use Standard Date Format", true); else GM_deleteValue("Use Standard Date Format");
  636.                 if (ipts[1].checked) GM_setValue("Use Original Search", true); else GM_deleteValue("Use Original Search");
  637.                 if (ipts[2].checked) GM_setValue("Feedback Table View", true); else GM_deleteValue("Feedback Table View");
  638.                 document.location.reload();
  639.                 TSL.removeNode(settings);
  640.             }
  641.  
  642.             return false;
  643.         };
  644.  
  645.         var require = document.querySelector("#script-content > p > code");
  646.         if (require && require.textContent.match("@require"))
  647.         {
  648.             var copyBar = document.createElement("div");
  649.             var copyBtn = document.createElement("button");
  650.             copyBtn.textContent = "Copy To Clipboard";
  651.             require.parentElement.insertBefore(copyBar, require.nextElementSibling);
  652.             require.setAttribute("style", "display:block;");
  653.             copyBtn.setAttribute("style", "margin-right:10px");
  654.  
  655.             copyBar.appendChild(copyBtn);
  656.             copyBar.appendChild(createRadio("Short URL"));
  657.             copyBar.appendChild(createRadio("Long URL"));
  658.             copyBar.appendChild(createRadio("Current Ver."));
  659.  
  660.             var scriptID = require.textContent.match(/\/scripts\/(\d+)/)[1];
  661.             var radios = copyBar.querySelectorAll("input");
  662.  
  663.             radios[0].setAttribute("requireURL", "// @require https://greasyfork.org/scripts/" + scriptID + "/code/" + scriptID + ".js");
  664.             radios[1].setAttribute("requireURL", require.textContent.replace(/\?\w+=\d+/, ""));
  665.             radios[2].setAttribute("requireURL", require.textContent);
  666.  
  667.             radios[0].onclick = radios[1].onclick = radios[2].onclick = function (e)
  668.             {
  669.                 for (var i = 0; i < radios.length; i++)
  670.                 {
  671.                     if (this != radios[i]) radios[i].checked = false;
  672.                 }
  673.  
  674.                 require.textContent = this.getAttribute("requireURL");
  675.             }
  676.  
  677.             copyBtn.onclick = function ()
  678.             {
  679.                 GM_setClipboard(require.textContent);
  680.             }
  681.  
  682.             radios[1].click();
  683.         }
  684.  
  685.  
  686.         if (pathname.match(/\/[\w-]+\/scripts/) && document.querySelector("#script-list-set ul")) //Script Listing
  687.         {
  688.             TSL.addStyle("TheBlackLagoon", "#UserSets {display: block; background-color: yellow; margin: 2px 10px; border-radius: 5px; padding: 2px 10px;}"
  689.                 + "#UserSets li {display: inline-block; padding: 2px 8px; background-color: white; border-radius: 2px;}"
  690.                 + "#UserSets li + li {margin-left: 1px}"
  691.                 );
  692.  
  693.             var sets = document.querySelector("#script-list-set ul");
  694.             var mh = document.getElementById("main-header");
  695.             sets.id = "UserSets";
  696.  
  697.             //document.body.insertBefore(sets, document.getElementById("main-header").nextElementSibling);
  698.             document.body.appendChild(sets);
  699.         }
  700. // decembre OK - TEST USER CSS - to SEE LANGUAGE PANEL
  701. //        TSL.removeNode("script-list-option-groups");
  702.  
  703.         function createRadio(text)
  704.         {
  705.             var option = document.createElement("div");
  706.             option.setAttribute("style", "display:inline-block; margin-right:10px;width:140px;")
  707.             var radio = document.createElement("input");
  708.             radio.type = "radio";
  709.             var lbl = document.createElement("label");
  710.             lbl.textContent = text;
  711.  
  712.             option.appendChild(radio);
  713.             option.appendChild(lbl);
  714.             return option;
  715.         }
  716.     }
  717.  
  718.     function disco(i)
  719.     {
  720.         notice.style.backgroundColor = (i % 2) ? "transparent" : "yellow";
  721.         if (i < 18) setTimeout(disco, 500, ++i);
  722.     }
  723.  
  724.     /* Styling for user page
  725.     ---------------------------------------------------------------------------*/
  726.     function OrangifyUserPage()
  727.     {
  728.         TSL.addStyle("CitrusGF_Shared", ".text-content {border: 0; box-shadow:0 0 0;padding:0;} #user-profile {background-color:#F9ECDB; margin: 0 15px}"
  729.             + "body > .width-constraint {background-color:white; margin: 5px auto;padding: 2px 10px;} #control-panel {margin-top: 15px;}"
  730.             );
  731.         TSL.addStyle("", "#user-control-panel, #control-panel h3 {margin: 0; padding: 0;}  #user-control-panel a {text-decoration: none;} #user-control-panel li:hover {background-color: #FBEACA;}"
  732.             + "#user-control-panel > li {background-color: #f5f2f2;border: 1px solid #404040;border-radius: 5px;box-shadow: 3px 3px 2px #888888;display: inline-block;margin: 2px 5px;min-width: 150px;padding: 2px 5px;text-align: center;}"
  733.             );
  734.         TSL.addStyle("CitrusGF_OUJS", 'code {padding: 2px 4px;font-size: 90%;color: #C7254E;background-color: #F9F2F4;white-space: nowrap;border-radius: 4px;font-family: Menlo,Monaco,Consolas,"Courier New",monospace; }');
  735.  
  736.  
  737.  
  738.         var el = document.getElementById("user-script-sets");
  739.         if (el) el.parentElement.className = "white-panel";
  740.  
  741.         el = document.getElementById("user-script-list");
  742.         if (el) TSL.removeNode(el.parentElement);
  743.  
  744.         el = document.getElementById("user-deleted-script-list");
  745.         if (el) TSL.removeNode(el.parentElement);
  746.  
  747.         //Get discussions
  748.         el = document.querySelector("#user-discussions-on-scripts-written");
  749.         if (el)
  750.         {
  751.             document.querySelector("body > .width-constraint").appendChild(el);
  752.             return;
  753.         }
  754.         //https://greasyfork.org/en/forum/discussions.json?script_author=1455
  755.         var userId = document.URL.match(/\/users\/(\d+)/)[1],
  756.             localURL = document.URL.replace(/\/users\/.+/, ""),
  757.             disURL = localURL + "/forum/discussions.json?script_author=" + userId;
  758.  
  759.         GM_xmlhttpRequest({
  760.             url: disURL,
  761.             method: "GET",
  762.             headers: { "User-agent": navigator.userAgent, "Accept": "text/xml" },
  763.             onload: function (xhr)
  764.             {
  765.                 if (xhr.status == 200)
  766.                 {
  767.                     var data = JSON.parse(xhr.responseText);
  768.                     if (typeof data !== "object" || data.CountDiscussions == 0) return;
  769.                     console.log(data);
  770.  
  771.                     var discussions = document.createElement("section");
  772.                     discussions.id = "user-discussions-on-scripts-written";
  773.                     discussions.innerHTML = '<h3>Discussions on scripts <a href="/en/forum/discussions/feed.rss?script_author="' + userId + '"><img src="/assets/feed-icon-14x14-ea341336588040dc7046d3423511d63d.png" alt="RSS Feed" rel="nofollow"></a></h3><ul class="discussion-list"></ul>';
  774.                     document.querySelector("body > .width-constraint").appendChild(discussions);
  775.  
  776.                     var list = discussions.querySelector("ul");
  777.  
  778.                     for (var i = 0, post, item; i < data.Discussions.length && i < 10; i++)
  779.                     {
  780.                         post = data.Discussions[i];
  781.  
  782.                         item = document.createElement("li");
  783.                         item.class = "discussion-question";
  784.                         item.innerHTML = '<a href="' + localURL + '/scripts/' + post.ScriptID + '">' + post.DiscussionAboutName + '</a> : '
  785.                             + '<a href="' + post.Url + '">' + post.Name + '</a> by '
  786.                             + '<a href="' + localURL + "/forum/profile/" + post.FirstUserID + "/" + post.FirstName + '">' + post.FirstName + '</a> '
  787.                             + '<time datetime="' + post.FirstDate + '">(' + getRelativeDate(post.FirstDate) + ')</time>, last comment by '
  788.                             + '<a href="' + localURL + "/forum/profile/" + post.LastUserID + "/" + post.LastName + '">' + post.LastName + '</a> '
  789.                             + '<time datetime="' + post.LastDate + '">(' + getRelativeDate(post.LastDate) + ')</time>';
  790.  
  791.  
  792.                         list.appendChild(item);
  793.                     }
  794.                 }
  795.                 else callback(xhr, null);
  796.  
  797.                 function getRelativeDate(date)
  798.                 {
  799.                     var ms = Date.now() - parseInt(new Date(date).getTime()),
  800.                         secs = Math.floor(ms / (1000)) % 60,
  801.                         mins = Math.floor(ms / (60 * 1000)) % 60,
  802.                         hrs = Math.floor(ms / (60 * 60 * 1000)) % 24,
  803.                         days = Math.floor(ms / (60 * 60 * 1000 * 24) % 7),
  804.                         weeks = Math.floor(ms / (60 * 60 * 1000 * 24) / 7);
  805.  
  806.                     if (weeks) return date.replace(/\s+.+/, "");
  807.                     if (days) return days + "day" + isPlural(days) + " and " + hrs + "hr" + isPlural(hrs);
  808.                     if (hrs) return hrs + "hr" + isPlural(hrs) + " and " + mins + "min" + isPlural(mins);
  809.                     if (mins) return mins + "min" + isPlural(mins) + " and " + secs + "sec" + isPlural(secs);
  810.                     return secs + "sec" + isPlural(secs);
  811.  
  812.                     function isPlural(val)
  813.                     {
  814.                         if (val == 1) return "";
  815.  
  816.                         return "s";
  817.                     }
  818.                 }
  819.             }
  820.         });
  821.     }
  822.  
  823.  
  824.     /* Gets the scripts from document
  825.     ---------------------------------------------------------------------------*/
  826.     function getScripts(doc)
  827.     {
  828.         if (!doc) doc = document;
  829.         var ids = ["user-script-list", "user-deleted-script-list", "browse-script-list"];
  830.         scripts = new Array();
  831.  
  832.         for (var i = 0, el, deleted, list; i < ids.length; i++)
  833.         {
  834.             el = doc.getElementById(ids[i]);
  835.             if (!el) continue;
  836.  
  837.             deleted = ids[i].indexOf("deleted") > 0;
  838.             list = el.children;
  839.             for (var j = 0, stamp; j < list.length; j++)
  840.             {
  841.                 var li = list[j];
  842.  
  843. // Fix by KONF
  844.                 if (li.classList.contains('ad-entry')) continue;
  845.  
  846.                 var script = new Object();
  847.                 script.name = li.getAttribute("data-script-name");
  848.                 script.id = li.getAttribute("data-script-id");
  849.                 script.author = li.getAttribute("data-script-authors");
  850.                 script.authorID = script.author.match(/"(\d+)":"(.+)"/)[1];
  851.                 script.author = script.author.match(/"(\d+)":"(.+)"/)[2];
  852.                 script.description = li.getElementsByClassName("description")[0].textContent.trim();
  853.                 script.rating = li.getAttribute("data-script-rating-score");
  854.                 script.ratings = (li.querySelector("dd.script-list-ratings")) ? li.querySelector("dd.script-list-ratings").innerHTML : "";
  855.                 script.installsDaily = li.getAttribute("data-script-daily-installs");
  856.                 script.installsTotal = li.getAttribute("data-script-total-installs");
  857. //Fix by KONF
  858. /* OLD
  859.                 script.dateCreated = li.getAttribute("data-script-created-date") + "|" + li.querySelector(".script-list-created-date time").textContent;
  860.                 script.dateUpdated = li.getAttribute("data-script-updated-date") + "|" + li.querySelector("dd.script-list-updated-date span").textContent;
  861.                 script.dateUpdated = li.getAttribute("data-script-updated-date") + "|" + li.querySelector(".script-list-updated-date time").
  862. */
  863.                 script.dateCreated = li.getAttribute("data-script-created-date") + "|" + li.querySelector("dd.script-list-created-date span").textContent;
  864.                 script.dateUpdated = li.getAttribute("data-script-updated-date") + "|" + li.querySelector("dd.script-list-updated-date span").textContent;
  865.                 script.type = li.getAttribute("data-script-type");
  866.                 script.defunct = /defunct|depreciated|obselete|unsupported/i.test(script.description);
  867.                 script.deleted = deleted;
  868.                 scripts.push(script);
  869.  
  870.                 stamp = GM_getValue("Script:" + script.id, false);
  871. //Fix by KONF
  872. /* OLD
  873.  
  874.                     if (li.querySelector(".script-list-updated-date time").getAttribute("datetime") != stamp.datetime) stamp.version = "";
  875.                     if (li.querySelector(".script-list-updated-date time").getAttribute("datetime") != stamp.datetime) stamp.version = "";
  876.  
  877. */
  878.                 if (stamp)
  879.                 {
  880.                     stamp = JSON.parse(stamp);
  881.                     if (li.querySelector("dd.script-list-updated-date span").getAttribute("datetime") != stamp.datetime) stamp.version = "";
  882.                     else script.version = stamp.version;
  883.                 }
  884.                 else stamp = { datetime: li.querySelector("dd.script-list-updated-date span").getAttribute("datetime"), version: "", timestamp: "" };
  885.  
  886.                 stamp.timestamp = Date.now();
  887.                 GM_setValue("Script:" + script.id, JSON.stringify(stamp));
  888.             }
  889.         }
  890.     }
  891.  
  892.  
  893.     /* Creates scripts table (relative search)
  894.     ---------------------------------------------------------------------------*/
  895.     function createScriptTable(isRelativeSearch)
  896.     {
  897.         var scriptTable = document.createElement("table");
  898.         scriptTable.id = "script-table";
  899.         var thead = scriptTable.createTHead();
  900.         var row = thead.insertRow(-1);
  901.  
  902.         var headers = ["Name", "Ratings", "Daily", "Total", "Created", "Updated"];
  903.         var tags = ["name", "ratings", (isRelativeSearch ? "daily_installs" : ""), "total_installs", "created", "updated"];
  904.  
  905.         cell = row.insertCell(-1);
  906.         cell.textContent = "#";
  907.  
  908.         var cell;
  909.         for (var i = 0; i < headers.length; i++)
  910.         {
  911.             cell = row.insertCell(-1);
  912.             cell.innerHTML = headers[i];
  913.             cell.onclick = onTableHeaderClick;
  914.             cell.setAttribute("tag", tags[i]);
  915.         }
  916.  
  917.         cell = row.cells[1];
  918.  
  919.         //scriptTable.createTBody();
  920.         scriptTable.appendChild(document.createElement("tbody"));
  921.         document.body.appendChild(scriptTable);
  922.  
  923.         TSL.addStyle("CitrusGS_Table", "body {background-color: #EFEFB1; margin: 0;} body {background-color:whitesmoke;}"
  924.             //+ "#script-table {display: block; margin: 0 5px 5px 5px; }"
  925.             + "pagination {text-align:center;}"
  926.             + "#script-table thead td {background-color: orange; border-radius: 0 0 5px 5px; box-shadow: 3px 3px 2px #888888;position:relative;}"
  927.             + "#user-discussions-on-scripts-written > h3 {margin-bottom: 3px;}"
  928.             + "#script-table thead td:hover {cursor:pointer; background-color: yellow;}"
  929.             + "#script-table thead td:first-child:hover {cursor:default; background-color: orange;}"
  930.             + "#script-table td {white-space: nowrap;width: auto; padding: 2px 5px; text-align:center;}"
  931.             + "#script-table td:nth-child(0), #script-table td:nth-child(1), #script-table td:nth-child(2)  {white-space: normal;}"
  932.             //+ "#script-table thead tr td:nth-child(3) {width: 120px; display: block;}"
  933.             //+ ".total-rating-count {display: inline-block; min-width: 1em; text-align: center; padding: 0px 0.25em; border-radius: 10px;}"
  934.             + ".total-rating-count, .good-rating-count, .ok-rating-count, .bad-rating-count {display: inline-block; min-width: 1em; padding: 1px 3px; border-radius: 3px;}"
  935.             + ".total-rating-count {background-color: rgba(0, 0, 255, 0.1);}"
  936.             + "#script-table tbody td {background-color: #FFFBDB;}"
  937.             + "#script-table tbody td:first-child{background-color: #F9D5A6;}"
  938.             + "#script-table tbody td:nth-child(2){width: 99%; background-color: white;text-align:left;}"
  939.             + "#script-table tbody tr:hover td {background-color: yellow;}"
  940.             + ".loadingSort {background-color: #FDFDC3 !important;}"
  941.             + ".type-library, .type-unlisted, .type-deleted, .type-defunct {font-size:smaller; display: inline-block; border-radius: 3px; padding: 0 5px; border: 1px solid black;}"
  942.             + ".type-library, .type-unlisted, .type-deleted, .type-defunct {box-shadow: 2px 2px 1px #888888; margin: 2px 5px 3px 0;}"
  943.             + "#script-table tbody [library] td:nth-of-type(3) {background-color:lightgray;}"
  944.             + ".type-library {background-color: #CEFD8A;}"
  945.             + ".type-deleted {background-color: #F77A7A;}"
  946.             + ".type-defunct {background-color: #FF8600;}"
  947.             + ".type-unlisted, .filterU {background-color: #CEE7F3;}"
  948.             + ".type-library:before {content: 'Library';}"
  949.             + ".type-deleted:before {content: 'Deleted';}"
  950.             + ".type-unlisted:before {content: 'Unlisted';}"
  951.             + ".type-defunct:before {content: 'No Longer Supported';}"
  952.             + "#notice {margin:5px 5px 0 5px; background-color: #FDBB45;padding: 3px 5px; color: blue;}"
  953.             + "thetitle {margin-bottom: 3px;} .theauthor{font-size:small;}"
  954.         );
  955.  
  956.         TSL.addStyle("Al28dj21", ".thetitle a {margin-right: 2px !important;}");
  957.         TSL.addStyle("Al28dj23", ".theversion {font-size: xsmall; margin-right: 4px;}");
  958.         TSL.addStyle("Al28dj24", "tr[library] td:nth-child(2) {background-color: #F2FBEA !important;}");
  959.         TSL.addStyle("Al28dj25", "tr[unlisted] td:nth-child(2) {background-color: #F4FBFF !important;}");
  960.         TSL.addStyle("Al28dj27", "tr[deleted] td:nth-child(2) {background-color: #FDF7F7 !important;}");
  961.     }
  962.  
  963.     /* Populate the table with scripts
  964.     ---------------------------------------------------------------------------*/
  965.     function populateScriptTable(clear)
  966.     {
  967.         //populateScriptTable0(true); return;
  968.  
  969.         var tbody = document.getElementById("script-table").getElementsByTagName("tbody")[0];
  970.         if (clear) tbody.innerHTML = "";
  971.         if (scripts.length == 0) return;
  972.  
  973.         for (var i = 0; i < scripts.length; i++)
  974.         {
  975.             var script = getScriptHTML(i);
  976.  
  977.             row = tbody.insertRow(-1);
  978.             row.id = "s" + script.id;
  979.             cell = row.insertCell(-1);
  980.  
  981.             cell.textContent = "##";
  982.  
  983.             cell = row.insertCell(-1);
  984.             var el = document.createElement("div");
  985.             el.className = "thetitle";
  986.             el.innerHTML = "<a href='https://greasyfork.org/scripts/"
  987.                             + script.id + "' style='margin-right: 10px;'><b>" + script.name + "</b></a><span class='theversion'></span>";
  988.  
  989.             if (script.type == "library") AddScriptTag("library");
  990.             else if (script.type == "unlisted") AddScriptTag("unlisted");
  991.             else row.setAttribute("public", 0);
  992.  
  993.             if (script.deleted) AddScriptTag("deleted");
  994.             if (script.defunct) AddScriptTag("defunct");
  995.  
  996.  
  997.             // If page listing add author detail
  998.             if (document.body.getAttribute("PageType") == "ListingPage")
  999.             {
  1000.                 el.innerHTML += '<span class="theauthor"><span>by </span><a href="https://greasyfork.org/users/' + script.authorID + '">' + script.author + '</a></span>';
  1001.             }
  1002.             cell.appendChild(el);
  1003.  
  1004.             el = document.createElement("div");
  1005.             el.textContent = script.description;
  1006.             cell.appendChild(el);
  1007.             cell = row.insertCell(-1);
  1008.             if (script.type != "library")
  1009.             {
  1010.                 cell.innerHTML = script.ratings + '<span class="total-rating-count">' + script.rating + '</span>';
  1011.                 cell.title = "Favoured plus Good Feedback, OK Feedback, Bad Feedback, Total Score (" + script.rating + ")";
  1012.             }
  1013.             row.insertCell(-1).textContent = script.installsDaily;
  1014.             row.insertCell(-1).textContent = script.installsTotal;
  1015.             row.insertCell(-1).textContent = GM_getValue("Use Standard Date Format", false) ? script.dateCreated.split("|")[0] : script.dateCreated.split("|")[1];
  1016.             row.insertCell(-1).textContent = GM_getValue("Use Standard Date Format", false) ? script.dateUpdated.split("|")[0] : script.dateUpdated.split("|")[1];
  1017.  
  1018.             function AddScriptTag(tag)
  1019.             {
  1020.                 el.innerHTML += '<span class="type-' + tag + '" />';
  1021.                 row.setAttribute(tag, "");
  1022.             }
  1023.  
  1024.             if (script.version) addScriptVersion(script);
  1025.         }
  1026.  
  1027.         OrganizeTableByCategory();
  1028.  
  1029.         function getScriptHTML(idx)
  1030.         {
  1031.             var properties = "name id author authorID description rating ratings installsDaily installsTotal dateCreated dateUpdated type deleted";
  1032.             return makeStruct(properties, scripts[idx]);
  1033.         }
  1034.     }
  1035.  
  1036.     function addScriptVersion(script)
  1037.     {
  1038.         var el = document.querySelector("#s" + script.id + " .thetitle .theversion");
  1039.  
  1040.         if (!el) return;
  1041.         el.innerHTML = "(<b>" + script.version + "</b>)";
  1042.  
  1043.         if (/defunct|depreciated|obselete|unsupported/i.test(script.version))
  1044.         {
  1045.             el.innerHTML += '<span class="type-defunct" />';
  1046.             el.parentElement.parentElement.setAttribute("defunct", "");
  1047.         }
  1048.  
  1049.         stamp = JSON.parse(GM_getValue("Script:" + script.id));
  1050.         stamp.version = script.version;
  1051.         GM_setValue("Script:" + script.id, JSON.stringify(stamp));
  1052.     }
  1053.  
  1054.     function numberScriptListing()
  1055.     {
  1056.         var rows = document.querySelectorAll("#script-table > tbody > tr");
  1057.  
  1058.         if (!rows) return;
  1059.  
  1060.         var offset = 1, len = rows.length.toString().length;
  1061.  
  1062.         if (document.body.getAttribute("PageType") == "ListingPage")
  1063.         {
  1064.             var page = 1, limit = 100, m = document.location.search.match(/(?:\?|&)page=(\d+)/);
  1065.             if (m) page = parseInt(m[1]);
  1066.  
  1067.             m = document.location.search.match(/per_page=(\d+)/);
  1068.             if (m) limit = parseInt(m[1]);
  1069.  
  1070.             console.log(page, limit);
  1071.             offset += limit * (page - 1);
  1072.         }
  1073.  
  1074.         for (var i = 0; i < rows.length; i++)
  1075.         {
  1076.             rows[i].firstElementChild.textContent = (i + offset).toString().lPad("0", len);
  1077.         }
  1078.     }
  1079.  
  1080.     function OrganizeTableByCategory()
  1081.     {
  1082.         if (document.body.getAttribute("PageType") == "ListingPage")
  1083.         {
  1084.             numberScriptListing();
  1085.             return;
  1086.         }
  1087.  
  1088.         var tbody = document.getElementById("script-table").getElementsByTagName("tbody")[0];
  1089.  
  1090.         var rows = tbody.children;
  1091.         for (var i = 0, n; i < rows.length - 1; i++)
  1092.         {
  1093.             n = i;
  1094.             for (var j = i + 1; j < rows.length; j++)
  1095.             {
  1096.                 if (getPosValue(rows[n]) > getPosValue(rows[j])) n = j;
  1097.             }
  1098.             if (n != i) tbody.insertBefore(rows[n], rows[i]);
  1099.         }
  1100.  
  1101.  
  1102.         numberScriptListing();
  1103.  
  1104.         function getPosValue(el)
  1105.         {
  1106.             var v = 0;
  1107.             if (el.hasAttribute("unlisted")) v += 4;
  1108.             if (el.hasAttribute("defunct")) v += 1;
  1109.             if (el.hasAttribute("library")) v += 2;
  1110.  
  1111.             if (el.hasAttribute("deleted")) v += 6;
  1112.  
  1113.             return v;
  1114.         }
  1115.     }
  1116.  
  1117.     /*
  1118.     ---------------------------------------------------------------------------*/
  1119.     function selectSortOrder(pageType, isRelativeSearch)
  1120.     {
  1121.         var tag = (isRelativeSearch) ? "" : GM_getValue(pageType, "updated");
  1122.  
  1123.         var m = document.URL.match(/[\?&]sort=(\w+)/);
  1124.         var tagURL = (m) ? m[1] : "";
  1125.  
  1126.         var page = document.URL.match(/[\?&]page=(\d+)/);
  1127.  
  1128.         TSL.addStyle("SelectedSortColumn", "[tag='" + tagURL + "'] {background-color: yellow !important;}");
  1129.  
  1130.         if (!isRelativeSearch && !page && (tagURL != tag || (document.URL.indexOf("per_page=100") < 0)))
  1131.         {
  1132.             document.querySelector(("[tag='" + tag + "']")).click();
  1133.             return;
  1134.         }
  1135.         getScriptVersionNumbers();
  1136.     }
  1137.  
  1138.     /*  Table header is clicked, get the correct script sorting
  1139.     ---------------------------------------------------------------------------*/
  1140.     function onTableHeaderClick(e)
  1141.     {
  1142.         if (document.querySelector("loadingSort")) return;
  1143.         this.className = "loadingSort";
  1144.  
  1145.         getScriptListing(this.getAttribute("tag"), true);
  1146.     }
  1147.  
  1148.     /*   Get script page
  1149.     ---------------------------------------------------------------------------*/
  1150.     function getScriptListing(tag, removePage)
  1151.     {
  1152.         var isListingPage = (document.body.getAttribute("PageType") == "ListingPage");
  1153.  
  1154.         if (/\/code-search\?/i.test(document.URL)) url = document.URL.match(/.+\/code-search\?/)[0] + "per_page=100";
  1155.         else if (isListingPage) url = document.URL.match(/https:\/\/greasyfork.org\/[\w-]+\/scripts(\/by-site\/[\w\.\-_]+|\/search)?/)[0] + "?per_page=100";
  1156.         else url = document.URL.replace(/\?.+/, "?");
  1157.  
  1158.         var m = document.URL.match(/[^=\?&]+=[^&]+/g);
  1159.         if (m)
  1160.             for (var i = 0; i < m.length; i++)
  1161.             {
  1162.                 //if (!m[i].match(/^(per_page|sort)/) && !(firstPage && m[i].match(/^page/))) url += "&" + m[i];
  1163.                 if (!m[i].match(/^(per_page|sort)/)) url += "&" + m[i];
  1164.             }
  1165.  
  1166.         if (tag) url += "&sort=" + tag;
  1167.         if (removePage) url = url.replace(/[\?&]page=\d+/, "");
  1168.  
  1169.         url = url.replace(/\?&/, "?");
  1170.         url = url.replace(/\?$/, "");
  1171.  
  1172.         if (url.indexOf("?") < 0) url = url.replace("&", "?");
  1173.  
  1174.         console.warn("getScriptListing IN: " + url)
  1175.         GM_xmlhttpRequest({
  1176.             url: url,
  1177.             method: "GET",
  1178.             timeout: 15000,
  1179.             headers: {
  1180.                 "User-agent": navigator.userAgent,
  1181.                 "Host": "greasyfork.org",
  1182.                 "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
  1183.                 "Accept-Language": "en-US,en;q=0.5"
  1184.             },
  1185.             onload: function (xhr)
  1186.             {
  1187.                 if (xhr.status == 200)
  1188.                 {
  1189.                     GM_setValue(document.body.getAttribute("PageType"), tag);
  1190.  
  1191.                     TSL.addStyle("SelectedSortColumn", "[tag='" + tag + "'] {background-color: yellow !important;}");
  1192.  
  1193.                     //stackoverflow.com/questions/19193335/change-the-url-in-browser-bar-without-reloading-page
  1194.                     window.history.pushState(null, "", xhr.finalUrl); //Change document URL
  1195.  
  1196.                     scripts = new Array();
  1197.                     //var doc = new DOMParser().parseFromString(xhr.responseText, 'text/xml');
  1198.  
  1199.                     var doc = document.implementation.createHTMLDocument('MPIV');
  1200.                     doc.documentElement.innerHTML = xhr.responseText;
  1201.  
  1202.                     TSL.removeNode(document.getElementsByClassName("pagination")[0]);
  1203.  
  1204.                     var pager = doc.getElementsByClassName("pagination")[0];
  1205.  
  1206.                     if (pager)
  1207.                     {
  1208.                         document.body.insertBefore(pager, document.getElementById("script-table").nextElementSibling);
  1209.                     }
  1210.  
  1211.                     getScripts(doc);
  1212.                     populateScriptTable(true);
  1213.                     getScriptVersionNumbers();
  1214.                 }
  1215.  
  1216.                 TSL.removeClass(document.querySelector(".loadingSort"), "loadingSort")
  1217.                 console.warn("getScriptListing OUT: " + url);
  1218.             }
  1219.         });
  1220.     }
  1221.  
  1222.     function getScriptVersionNumbers()
  1223.     {
  1224.         //No need to do a JSON call as the stored information is already up-to-date
  1225.         if (document.querySelectorAll(".theversion").length == document.querySelectorAll(".theversion b").length) return;
  1226.  
  1227.         var jsonURL = document.URL.replace(/(\?|$)/, ".json$1");
  1228.         console.log("JSON: " + jsonURL);
  1229.  
  1230.         //Get version number
  1231.         GM_xmlhttpRequest({
  1232.             url: jsonURL,
  1233.             method: "GET",
  1234.             timeout: 15000,
  1235.             headers: {
  1236.                 "User-agent": navigator.userAgent,
  1237.                 "Host": "greasyfork.org",
  1238.                 "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8",
  1239.                 "Accept-Language": "en-US,en;q=0.5"
  1240.             },
  1241.             onload: function (xhr)
  1242.             {
  1243.                 if (xhr.status == 200)
  1244.                 {
  1245.                     var data = JSON.parse(xhr.responseText), scripts;
  1246.                     //console.log(data);
  1247.                     if (typeof data !== "object") return;
  1248.                     scripts = data.all_listable_scripts || data;
  1249.  
  1250.                     for (var i = 0, script; i < scripts.length; i++)
  1251.                     {
  1252.                         script = scripts[i];
  1253.                         addScriptVersion(script);
  1254.                     }
  1255.  
  1256.                     OrganizeTableByCategory();
  1257.                 }
  1258.             }
  1259.         });
  1260.     }
  1261.  
  1262.     function getScriptJSON(obj)
  1263.     {
  1264.         var properties = "bad_ratings code_updated_at code_url contribution_amount contribution_url created_at daily_installs description fan_score good_ratings id license locale name namespace ok_ratings redistributable support_url total_installs url version";
  1265.         return makeStruct(properties, obj);
  1266.     }
  1267.  
  1268.     function makeStruct(keys, obj)
  1269.     {
  1270.         if (!obj) obj = {};
  1271.  
  1272.         var names = keys.split(" ").sort();
  1273.         for (var i = 0; i < names.length; i++)
  1274.         {
  1275.             obj[names[i]] = obj[names[i]];
  1276.         }
  1277.  
  1278.         return obj;
  1279.     }
  1280. })();
  1281.  
  1282.  
Add Comment
Please, Sign In to add comment