E-Hentai/Exhentai Galleries Sortable Front/Search Page Table + 2 New Columns: Length & Size

Script adds two new columns to table on front/search page, size in MB and length, both are using the EH API. Script also makes columns in table sortable by clicking on column name.

目前为 2016-03-25 提交的版本。查看 最新版本

  1. // ==UserScript==
  2. // @name E-Hentai/Exhentai Galleries Sortable Front/Search Page Table + 2 New Columns: Length & Size
  3. // @namespace https://sleazyfork.org/en/users/34516-cqzyiqbq
  4. // @description Script adds two new columns to table on front/search page, size in MB and length, both are using the EH API. Script also makes columns in table sortable by clicking on column name.
  5. // @include /^http://(g\.e-|ex|r\.e-)hentai\.org/(\?f_.*|)$/
  6. // @license WTFPL v2
  7. // @grant GM_addStyle
  8. // @version 0.05
  9. // @require http://code.jquery.com/jquery-2.2.2.min.js
  10. // ==/UserScript==
  11. /*
  12. @licstart
  13.  
  14. DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
  15. Version 2, December 2004
  16.  
  17. Copyright (C) 2004 Sam Hocevar <sam@hocevar.net>
  18.  
  19. Everyone is permitted to copy and distribute verbatim or modified
  20. copies of this license document, and changing it is allowed as long
  21. as the name is changed.
  22.  
  23. DO WHAT THE FUCK YOU WANT TO PUBLIC LICENSE
  24. TERMS AND CONDITIONS FOR COPYING, DISTRIBUTION AND MODIFICATION
  25.  
  26. 0. You just DO WHAT THE FUCK YOU WANT TO.
  27.  
  28. @licend
  29. */
  30. //New columns, (1) is the position of new column in table
  31. var c = $("table.itg tr:first td").length;
  32. $('table.itg').find('tr').each(function(){
  33. $(this).find('th').eq(1).after('<th>Size MB</th>');
  34. $(this).find('th').eq(1).after('<th>Length</th>');
  35. $("tr th:not([style]").attr("style" ,"white-space:nowrap");
  36. $(this).find('td').eq(1).after('<td> </td>');
  37. $("tr td:not([class]").attr("class","itx");
  38. $(this).find('td').eq(1).after('<td> </td>');
  39. $("tr td:not([class]").attr("class","itz");
  40. });
  41. //Sorting part
  42. $('th').click(function(){
  43. var table = $(this).parents('table').eq(0)
  44. var rows = table.find('tr:gt(0)').toArray().sort(comparer($(this).index()))
  45. this.asc = !this.asc
  46. if (!this.asc){rows = rows.reverse()}
  47. for (var i = 0; i < rows.length; i++){table.append(rows[i])}
  48. });
  49. function comparer(index) {
  50. return function(a, b) {
  51. var valA = getCellValue(a, index), valB = getCellValue(b, index)
  52. return $.isNumeric(valA) && $.isNumeric(valB) ? valA - valB : valA.localeCompare(valB)
  53. }
  54. }
  55. function getCellValue(row, index){
  56. return $(row).children('td').eq(index).html()
  57. }
  58. //takes filesize and filecount values from EH API
  59. var apiurl = "http://g.e-hentai.org/api.php";
  60. var apimax = 25;
  61. (function(classes) {
  62. var reqs = get_reqs(classes, apimax);
  63. reqs.forEach(function(elems) {
  64. var ids = elems.map(function(e) {
  65. var anchor = (e.getElementsByClassName('it5')[0]).firstElementChild;
  66. var ref = anchor.href.split('/');
  67. return [ref[4], ref[5]];
  68. });
  69. var gdata = { "method" : "gdata", "gidlist" : ids };
  70. send_req(gdata, elems, apiurl);
  71. });
  72. })(['gtr0','gtr1']);
  73. function get_reqs(classes, maxlen) {
  74. var elems = classes.map(function(x) {
  75. return Array.prototype.slice.call(document.getElementsByClassName(x));
  76. });
  77. var all = elems[0];
  78. for (var i=1; i < elems.length; i++) all = all.concat(elems[i]);
  79. var api_reqs = [];
  80. for (var i=0; i<all.length; i+=maxlen) api_reqs.push(all.slice(i, i+maxlen));
  81. return api_reqs;
  82. }
  83. function addfcount(elem, metadata) {
  84. var itds = elem.getElementsByClassName('itx'),
  85. filesize = "";
  86. if ("undefined" !== typeof metadata.error) {
  87. console.error('gallery-filesize: no filesize in ' + metadata.gid);
  88. filesize += "error";
  89. } else {
  90. filesize += String(((parseInt(metadata.filesize,10))/1024/1024).toFixed(2));
  91. }
  92. itds[0].firstChild.nodeValue += filesize;
  93. var itds = elem.getElementsByClassName('itz'),
  94. filecount = "";
  95. if ("undefined" !== typeof metadata.error) {
  96. console.error('gallery-size: no filecount in ' + metadata.gid);
  97. filecount += "error";
  98. } else {
  99. filecount += "" + String(metadata.filecount);
  100. }
  101. itds[0].firstChild.nodeValue += filecount;
  102. }
  103. function send_req(gdata, elems, aurl) {
  104. var req = new XMLHttpRequest();
  105. req.onreadystatechange = (function() {
  106. if (4 === req.readyState) {
  107. if (200 !== req.status) {
  108. console.error('gallery-size: cannot send request to ' + aurl);
  109. } else {
  110. var apirsp = JSON.parse(req.responseText);
  111. elems.forEach(function(e,i,arr) { addfcount(e,apirsp.gmetadata[i]); });
  112. }
  113. }
  114. });
  115. req.open("POST", aurl, true);
  116. req.send(JSON.stringify(gdata));
  117. }