Greasy Fork is available in English.

[TS] Citrus GFork

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.

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