Library Helper

A userscript that display links between different libraries and book stores.

目前為 2019-10-11 提交的版本,檢視 最新版本

  1. // ==UserScript==
  2. // @name Library Helper
  3. // @namespace https://gf.qytechs.cn/en/users/263753-chihchun
  4. // @version 0.1
  5. // @description A userscript that display links between different libraries and book stores.
  6. // @author Rex Tsai <rex.cc.tsai@gmail.com>
  7. // @match https://www.books.com.tw/products/*
  8. // @match http://book.tpml.edu.tw/webpac/bookDetail.do*
  9. // @match https://books.google.com.tw/books*
  10. // @match https://www.kobo.com/tw/zh/ebook*
  11. // @match https://www.taaze.tw/goods/*
  12. // @grant none
  13. // @require https://cdnjs.cloudflare.com/ajax/libs/js-yaml/3.13.1/js-yaml.min.js
  14. // @run-at document-idle
  15. // ==/UserScript==
  16.  
  17. (function() {
  18. 'use strict';
  19. var yaml = `
  20. books.com.tw:
  21. matches:
  22. - "https://www.books.com.tw/products/*"
  23. metadata:
  24. title: "//h1"
  25. origtitle: "//h2/a[contains(@href,'https://search.books.com.tw/search/query/cat/all/key')]"
  26. isbn: "//li[contains(text(),'ISBN')]"
  27. price: "//ul[@class='price']/li/em"
  28. sellingprice: "//b[@itemprop='price']"
  29. authors: "//a[contains(@href,'adv_author')]"
  30. publishdate: "//li[contains(text(),'出版日期')]"
  31. tpml.edu.tw:
  32. matches:
  33. - "http://book.tpml.edu.tw/webpac/bookDetail.do*"
  34. metadata:
  35. title: "//h3"
  36. authors: "//a[contains(@href,'search_field=PN')]"
  37. books.google.com.tw:
  38. matches:
  39. - "https://books.google.com.tw/books*"
  40. metadata:
  41. title: '//h1[@class="booktitle"]/span[@class="fn"]'
  42. authors: "//a[contains(@href,'q=inauthor')]"
  43. kobo.com:
  44. matches:
  45. - "https://www.kobo.com/tw/zh/ebook*"
  46. metadata:
  47. title: '//span[@class="title product-field"]'
  48. authors: '//a[@class="contributor-name"]'
  49. taaze.tw:
  50. matches:
  51. - "https://www.taaze.tw/goods/*"
  52. metadata:
  53. title: "//meta[@name='title']/@content"
  54. isbn: "//meta[@property='books:isbn']/@content"
  55. authors: "//div[@class='authorBrand']//a[contains(@href,'rwd_searchResult.html?keyType%5B%5D=2')]"
  56. `;
  57.  
  58. var keywords = ['title', 'authors', 'origtitle', 'isbn'];
  59. var urls = {
  60. "博客來": "https://search.books.com.tw/search/query/key/",
  61. "Kobo": "https://www.kobo.com/tw/zh/search?query=",
  62. "GooglePlay": "https://play.google.com/store/search?c=books&q=",
  63. "AmazonCN": "https://www.amazon.cn/s?rh=n%3A116169071&k=",
  64. "Goodreads": "https://www.goodreads.com/search?q=",
  65. "TPML": "http://book.tpml.edu.tw/webpac/bookSearchList.do?search_field=FullText&search_input=",
  66. "Google": "https://www.google.com/search?tbm=bks&q=",
  67. "讀冊": "https://www.taaze.tw/rwd_searchResult.html?keyword%5B%5D="
  68. };
  69.  
  70. parse_metadata();
  71.  
  72. function parse_metadata() {
  73. var rules = jsyaml.load(yaml);
  74. var data = {};
  75.  
  76. // parse the metadata
  77. for (var domain in rules) {
  78. rules[domain]['matches'].forEach(function (match) {
  79. if(document.URL.match(match)) {
  80. var metadata = rules[domain]['metadata'];
  81. for (var key in metadata) {
  82. data[key] = evaluate(metadata[key]);
  83. }
  84. return;
  85. }
  86. })
  87. }
  88.  
  89. // Links to other websites
  90. if(Object.keys(data).length > 0) {
  91. var dialog = inject();
  92. for (var service in urls) {
  93. var url = urls[service];
  94. var html = `<div>${service}: `;
  95. keywords.forEach(function(key) {
  96. if(data[key] != undefined) {
  97. data[key].forEach(function(keyword) {
  98. var href = url + encodeURI(keyword);
  99. html += `<a href="${href}" target="_blank">${keyword}</a> `;
  100. })
  101. }
  102. })
  103. html += "</div>";
  104. dialog.insertAdjacentHTML('beforeend', html)
  105. }
  106. }
  107. }
  108.  
  109.  
  110. function inject () {
  111. var div = document.createElement('div');
  112. div.id = "libraryhelper";
  113. div.className = "libraryhelper";
  114. div.textContent = 'Library helper';
  115. // Make the DIV element draggable:
  116. dragElement(div);
  117. document.body.appendChild(div);
  118.  
  119. var style = document.createElement('style');
  120. style.innerHTML = `
  121. div.libraryhelper {
  122. color: blueviolet;
  123. border: 1px solid #d3d3d3;
  124. background-color: rgba(255, 255, 255, 0.4);
  125.  
  126. position: fixed;
  127. top: 150px;
  128. right: 0px;
  129.  
  130. width: 30vw;
  131. height: 50vh;
  132. padding: 10px;
  133.  
  134. overflow-x: scroll;
  135. cursor: move;
  136. z-index: 9999;
  137. }
  138. `;
  139. document.head.appendChild(style);
  140. return div;
  141. }
  142.  
  143.  
  144. function dragElement(elmnt) {
  145. var pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0;
  146. if (document.getElementById(elmnt.id + "header")) {
  147. // if present, the header is where you move the DIV from:
  148. document.getElementById(elmnt.id + "header").onmousedown = dragMouseDown;
  149. } else {
  150. // otherwise, move the DIV from anywhere inside the DIV:
  151. elmnt.onmousedown = dragMouseDown;
  152. }
  153.  
  154. function dragMouseDown(e) {
  155. e = e || window.event;
  156. e.preventDefault();
  157. // get the mouse cursor position at startup:
  158. pos3 = e.clientX;
  159. pos4 = e.clientY;
  160. document.onmouseup = closeDragElement;
  161. // call a function whenever the cursor moves:
  162. document.onmousemove = elementDrag;
  163. }
  164.  
  165. function elementDrag(e) {
  166. e = e || window.event;
  167. e.preventDefault();
  168. // calculate the new cursor position:
  169. pos1 = pos3 - e.clientX;
  170. pos2 = pos4 - e.clientY;
  171. pos3 = e.clientX;
  172. pos4 = e.clientY;
  173. // set the element's new position:
  174. elmnt.style.top = (elmnt.offsetTop - pos2) + "px";
  175. elmnt.style.left = (elmnt.offsetLeft - pos1) + "px";
  176. }
  177.  
  178. function closeDragElement() {
  179. // stop moving when mouse button is released:
  180. document.onmouseup = null;
  181. document.onmousemove = null;
  182. }
  183. }
  184.  
  185. function evaluate(xpath, doc = document.documentElement) {
  186. var evaluator = new XPathEvaluator();
  187. var result = evaluator.evaluate(xpath, doc, null, XPathResult.ANY_TYPE, null);
  188. var node = null;
  189. var texts = [];
  190.  
  191. while(node = result.iterateNext()) {
  192. var text;
  193.  
  194. if (node instanceof Attr) {
  195. text = node.value
  196. } else {
  197. text = node.innerText;
  198. }
  199. if(text == undefined) {
  200. console.error(xpath + " not found on " + document.URL);
  201. continue;
  202. }
  203. // fixing up content
  204. text = text.replace("ISBN:", "").
  205. replace("出版日期:", "");
  206. texts.push(text);
  207. }
  208. return texts;
  209. }
  210. })();
  211.  

QingJ © 2025

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