LibraryThing Sort and Re-link on Combine/Separate Pages

Adds the ability to alphabetically sort editions and changes "separate" links so you can open them in a new window/tab.

  1. // ==UserScript==
  2. // @name LibraryThing Sort and Re-link on Combine/Separate Pages
  3. // @namespace https://gf.qytechs.cn/en/users/14131-brightcopy-edited
  4. // @description Adds the ability to alphabetically sort editions and changes "separate" links so you can open them in a new window/tab.
  5. // @include http://*.librarything.tld/combine.php*
  6. // @include http://*.librarything.tld/work/*/editions*
  7. // @include http://*.librarything.com/combine.php*
  8. // @include http://*.librarything.com/work/*/editions*
  9. // @license Public Domain
  10. // @version 2
  11. // @grant none
  12. // ==/UserScript==
  13.  
  14. var TEXT_ASCENDING = '(sort ascending)';
  15. var TEXT_DESCENDING = '(sort descending)';
  16.  
  17. var sepLinks = document.querySelectorAll('a[onclick^="c_sw"]');
  18.  
  19. for (var i = 0; i < sepLinks.length; i++) {
  20. var elem = sepLinks[i];
  21. var onclick = elem.getAttribute('onclick');
  22. var href = onclick.replace(
  23. /c_sw\((\d+), *(\d+)\)/, '/work_separate.php?book=$1&work=$2');
  24. elem.removeAttribute('onclick');
  25. elem.setAttribute('href', href);
  26. // this prevents the combination page from checking the checkbox
  27. // when we simply clicked on separate
  28. addEvent(elem, 'click', separateClick, false);
  29. }
  30.  
  31. function separateClick(e) {
  32. stopBubbling(e);
  33. return false;
  34. }
  35.  
  36. var elems = document.getElementsByClassName("combinetable")[0].getElementsByTagName("h2");
  37. for (var j = 0; j < elems.length; j++) {
  38. var elem = elems[j];
  39. var parent = elem.parentNode;
  40.  
  41. var span = document.createElement('span');
  42. span.setAttribute('style', 'float:right');
  43. span.className = 'smaller';
  44. var a = document.createElement('a');
  45. a.appendChild(document.createTextNode(TEXT_ASCENDING));
  46. addEvent(a, 'click', sortClick, false);
  47. span.appendChild(document.createTextNode(' '));
  48. span.appendChild(a);
  49.  
  50. elem.appendChild(span)
  51.  
  52. // this is for the editions page
  53. if (elem.nodeName == 'TD')
  54. break;
  55. }
  56.  
  57. function sortClick(e) {
  58. stopBubbling(e);
  59.  
  60. var a = getTarget(e);
  61. var node =
  62. // this is editions
  63. a.parentNode.parentNode.nodeName == 'TD'
  64. ? document.getElementById('editions')
  65. : a.parentNode.parentNode.parentNode;
  66. if (getTextContent(a) == TEXT_ASCENDING) {
  67. sortElems(node, compareNodesAscending);
  68. setTextContent(a, TEXT_DESCENDING);
  69. }
  70. else {
  71. sortElems(node, compareNodesDescending);
  72. setTextContent(a, TEXT_ASCENDING);
  73. }
  74. }
  75.  
  76. function compareNodesAscending(node1, node2) {
  77. if (node1.istr < node2.istr)
  78. return -1
  79. else if (node1.istr > node2.istr)
  80. return 1
  81. else if (node1.str < node2.str)
  82. return -1
  83. else if (node1.str > node2.str)
  84. return 1
  85. else
  86. return 0;
  87. }
  88.  
  89. function compareNodesDescending(node1, node2) {
  90. return compareNodesAscending(node2, node1);
  91. }
  92.  
  93. function sortElems(item, compare) {
  94. var ps = [];
  95. var step = item.nodeName == 'TD' ? 1 : 3;
  96. for (var i = 0; i < item.childNodes.length; i += step) {
  97. var node = item.childNodes[i];
  98.  
  99. if (step == 1 && node.nodeName == 'P' && node.hasChildNodes()
  100. || step == 3 && node.nodeName == '#text') {
  101. var txt = node.textContent.replace(/ +/g, ' ')
  102. .replace(/[\s\/.,"'?!;:#$%&()*+<>=@\^_{}~`|[\]-]+/g, '');
  103. ps.push({
  104. node:node,
  105. str:txt,
  106. istr:txt.toLowerCase()
  107. });
  108. }
  109. }
  110. ps.sort(compare);
  111.  
  112. for (i = 0; i < ps.length; i++) {
  113. var nodes = [ps[i].node];
  114. if (step == 3) {
  115. nodes.push(nodes[0].nextSibling);
  116. nodes.push(nodes[1].nextSibling);
  117. }
  118. var parent = nodes[0].parentNode;
  119.  
  120. for (var j = 0; j < nodes.length; j++) {
  121. parent.removeChild(nodes[j]);
  122. parent.appendChild(nodes[j]);
  123. }
  124. }
  125. }
  126.  
  127.  
  128. function addEvent(node, eventType, callback, useCapture) {
  129. if (node.addEventListener) {
  130. node.addEventListener(eventType, callback, useCapture);
  131. return true;
  132. }
  133. else if (node.attachEvent)
  134. return node.attachEvent('on' + eventType, callback);
  135. else
  136. node['on' + eventType] = callback;
  137. }
  138.  
  139. function getTarget(e) {
  140. if (!e)
  141. var e = window.event;
  142. var targ;
  143.  
  144. if (e.target)
  145. targ = e.target;
  146. else if (e.srcElement)
  147. targ = e.srcElement;
  148. if (targ.nodeType == 3) // defeat Safari bug
  149. targ = targ.parentNode;
  150. return targ;
  151. }
  152.  
  153. function stopBubbling(e) {
  154. if (!e)
  155. e = window.event;
  156. e.cancelBubble = true;
  157. if (e.stopPropagation)
  158. e.stopPropagation();
  159. }
  160.  
  161. function setTextContent(node, text) {
  162. if (node.innerText)
  163. node.innerText = text
  164. else if (node.textContent)
  165. node.textContent = text;
  166. }
  167.  
  168. function getTextContent(node, text) {
  169. return node.innerText || node.textContent;
  170. }

QingJ © 2025

镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址