LT Copy Book (fixed 2022-02-27) - LibraryThing

Copies book data and automatically pastes it to a manual entry.

目前为 2022-02-27 提交的版本,查看 最新版本

  1. // ==UserScript==
  2. // @name LT Copy Book (fixed 2022-02-27) - LibraryThing
  3. // @namespace http://userscripts.org/users/brightcopy
  4. // @description Copies book data and automatically pastes it to a manual entry.
  5. // @include http*://*.librarything.tld/work*/details/*
  6. // @include http*://*.librarything.tld/addnew.php
  7. // @grant GM_setValue
  8. // @grant GM_getValue
  9. // @grant GM_deleteValue
  10. // @version 2.1
  11. // ==/UserScript==
  12.  
  13. var ltcbTitle = { key:'ltcbTitle' , id:'bookedit_title' , field:'form_title' };
  14. var ltcbAuthor = { key:'ltcbAuthor' , id:'bookedit_authorunflip' , field:'form_authorunflip' };
  15. var ltcbDate = { key:'ltcbDate' , id:'bookedit_date' , field:'form_date' };
  16. var ltcbPublication = { key:'ltcbPublication' , id:'bookedit_publication' , field:'form_publication' };
  17. var ltcbISBN = { key:'ltcbISBN' , id:'bookedit_ISBN' , field:'form_ISBN' };
  18. var ltcbLCCN = { key:'ltcbLCCN' , id:'bookedit_lccallnumber' , field:'form_lccallnumber' };
  19. var ltcbDewey = { key:'ltcbDewey' , id:'bookedit_dewey' , field:'form_dewey' };
  20. var ltcbLanguage = { key:'ltcbLanguage' , id:'bookedit_lang' , field:'field_lang' };
  21. var ltcbLanguage2 = { key:'ltcbLanguage2' , id:'bookedit_lang2' , field:'field_lang2' };
  22. var ltcbLanguageO = { key:'ltcbLanguageO' , id:'bookedit_lang_original' , field:'field_lang_original' };
  23. //var ltcbVolumes = { key:'ltcbVolumes' , id:'bookedit_numVolumes' , field:'numVolumes' , path:'//td[text()="Number of Volumes"]/../td[@class="bookeditfield"]'};
  24. //var ltcbPages = { key:'ltcbPages' , id:'bookedit_pagecount' , field:'pagecount' , path:'//td[text()="Pages"]/../td[@class="bookeditfield"]'};
  25.  
  26. var ltcbCollection = { key:'ltcbCollection' };
  27. var ltcbAddToLibrary = { key:'ltcbAddToLibrary' };
  28. var ltcbAddToWishlist = { key:'ltcbAddToWishlist' };
  29.  
  30. var ltcbOtherAuthorCount = { key:'ltcbOtherAuthorCount' };
  31. var ltcbOtherAuthorRole = { key:'ltcbOtherAuthorRole' , field:'person_role-' };
  32. var ltcbOtherAuthorName = { key:'ltcbOtherAuthorName' , field:'person_name-' };
  33. var ltcbAuthorRole = { key:'ltcbAuthorRole' , field:'person_role_main' };
  34.  
  35. function getById(setting) {
  36. var e = document.getElementById(setting.id);
  37. return e ? e.textContent : '';
  38. }
  39.  
  40. function save(setting, callback) {
  41. var value = getById(setting);
  42. if (callback)
  43. value = callback(value);
  44. GM_setValue(setting.key, value);
  45. }
  46.  
  47. function setNonGreen(setting) {
  48. var e = document.getElementById(setting.id);
  49. var value = (e && e.innerHTML == e.textContent) ? e.textContent : '';
  50. GM_setValue(setting.key, value);
  51. }
  52.  
  53. function load(form, setting, opt) {
  54. var key = setting.key + (opt != undefined ? opt : '');
  55. var field = setting.field + (opt != undefined ? opt : '');
  56. var value = GM_getValue(key);
  57. var elem = form.elements.namedItem(field);
  58.  
  59. // console.log('load: ' + key + ', ' + field + ', ' + value);
  60. if (elem)
  61. elem.value = value;
  62. }
  63.  
  64. function loadRole(form, setting, opt) {
  65. if (!loadOption(form, setting, opt)) {
  66. var key = setting.key + (opt != undefined ? opt : '');
  67. var field = setting.field + (opt != undefined ? opt : '');
  68. var menu = form.elements.namedItem(field);
  69. if (menu) {
  70. var value = GM_getValue(key);
  71. var lastoption = menu.options.length;
  72. menu.options[lastoption - 2] = new Option(value, value);
  73. menu.options[lastoption - 1] = new Option("--------------", "");
  74. menu.options[lastoption] = new Option("Other...", "");
  75. menu.options.selectedIndex = lastoption - 2;
  76. }
  77. }
  78. }
  79.  
  80. function loadOption(form, setting, opt) {
  81. var key = setting.key + (opt != undefined ? opt : '');
  82. var field = setting.field + (opt != undefined ? opt : '');
  83. var value = GM_getValue(key);
  84.  
  85. var select = form.elements.namedItem(field);
  86. if (select == null)
  87. return false;
  88. var option = $x1('option[text() = "' + value + '"]', select);
  89.  
  90. if (option) {
  91. select.value = option.value;
  92. return true;
  93. }
  94. else
  95. return false;
  96. }
  97.  
  98. function fixAuthorName(value) {
  99. var newvalue = value.replace(
  100. /^(.+) ([^ ,]+),? (JR|SR|III|IV|V|VI|VII|VIII|IX)(.?)$/i, '$2, $1, $3$4');
  101. if (newvalue != value)
  102. value = newvalue;
  103. else
  104. value = value.replace(/^(.+) ([^ ]+)$/, '$2, $1');
  105.  
  106. return value;
  107. }
  108.  
  109. function addToLibraryClick(e) {
  110. addToClick(1);
  111. }
  112.  
  113. function addToWishlistClick() {
  114. addToClick(4)
  115. }
  116.  
  117. function fixLang(value) {
  118. if (value == '')
  119. value = '(blank)';
  120. return value;
  121. }
  122.  
  123. function addToClick(c) {
  124. GM_setValue(ltcbCollection.key, c);
  125. save(ltcbTitle);
  126. save(ltcbPublication);
  127. save(ltcbLanguage, fixLang);
  128. save(ltcbLanguage2, fixLang);
  129. save(ltcbLanguageO, fixLang);
  130.  
  131. save(ltcbDate,
  132. function (value) {
  133. if (value == '?')
  134. value = '';
  135. return value;
  136. }
  137. );
  138.  
  139. save(ltcbISBN,
  140. function (value) {
  141. return (value + ' / ').split(' / ')[0];
  142. }
  143. );
  144.  
  145. var authorTD = document.getElementById(ltcbAuthor.id);
  146. if (authorTD) {
  147. GM_setValue(ltcbAuthor.key, fixAuthorName(authorTD.firstChild.textContent));
  148.  
  149. var elem = authorTD.lastChild;
  150. if (elem.nodeType == 3) //Node.TEXT_NODE
  151. GM_setValue(ltcbAuthorRole.key, elem.textContent.replace(/^ \((.+)\)$/, '$1'))
  152. else
  153. GM_setValue(ltcbAuthorRole.key, '');
  154. }
  155. // fields with possible green text
  156. setNonGreen(ltcbLCCN);
  157. setNonGreen(ltcbDewey);
  158. // Other Authors
  159. var others = $x("//div[@class='bookeditPerson']/span[@class='book_langLabel']");
  160. GM_setValue(ltcbOtherAuthorCount.key, others.snapshotLength);
  161. for (var i = 0; i < others.snapshotLength; i++) {
  162. var role = others.snapshotItem(i);
  163. var roleText = role.textContent;
  164. GM_setValue(ltcbOtherAuthorRole.key + i, roleText.substring(0, roleText.length - 3));
  165. var author = role.nextSibling;
  166. while (author && author.tagName != 'SPAN') {
  167. author = author.nextSibling;
  168. }
  169. if (author)
  170. GM_setValue(ltcbOtherAuthorName.key + i, author.textContent);
  171. }
  172. }
  173.  
  174. function createAddTo(id, text, bg) {
  175. return '<span class="ltbtn ltbtn-inline-block sp16 ltbtn-ff3 " style="margin-left: 0.5em;">'+
  176. '<a id="' + id + '" href="/addnew.php">'+
  177. '<div class="ltbtn-outer-box ltbtn-inline-block">'+
  178. '<div class="ltbtn-inner-box ltbtn-inline-block">'+
  179. '<div class="ltbtn-pos">'+
  180. '<div class="ltbtn-top-shadow"></div>' +
  181. '<div class="ltbtn-content">'+
  182. '<div style="margin-right: 2px;" class="ltbtn-body ">'+
  183. '<span style="background-position: ' + bg + ';" class="sp_c sp16 "></span>'+
  184. 'Copy to ' + text +
  185. '</div>'+
  186. '</div>'+
  187. '</div>'+
  188. '</div>'+
  189. '</div>'+
  190. '</a>' +
  191. '</span>';
  192. }
  193.  
  194. function readData() {
  195. if (document.getElementById('ltcbButtons') == null) {
  196. // Create Buttons
  197. var elem = $x1('//div[@class="book_bitHeadContent"]/table[@class="book_bitTable"]/tbody/tr');
  198.  
  199. if (elem) {
  200. var td = document.createElement('td');
  201. var div = document.createElement('div');
  202. div.setAttribute('style', 'float: right');
  203. div.setAttribute('id', 'ltcbButtons');
  204. td.appendChild(div);
  205. elem.appendChild(td);
  206. div.innerHTML =
  207. '<span style="font-size: 9px; font-weight: normal;">' +
  208. createAddTo(ltcbAddToLibrary.key, 'your library', '-17px -68px') +
  209. createAddTo(ltcbAddToWishlist.key, 'your wishlist', '-34px -68px') +
  210. '</span>';
  211. document.getElementById(ltcbAddToLibrary.key).addEventListener('click', addToLibraryClick, false);
  212. document.getElementById(ltcbAddToWishlist.key).addEventListener('click', addToWishlistClick, false);
  213. }
  214. }
  215. }
  216.  
  217. /* ===== Click on an element (borrowed from Facebook Fixer, @namespace http://userscripts.org/people/14536) ===== */
  218. function click(elm) {
  219. var evt = document.createEvent('MouseEvents');
  220. evt.initMouseEvent('click', true, true, window, 0, 1, 1, 1, 1, false, false, false, false, 0, null);
  221. elm.dispatchEvent(evt);
  222. }
  223. function writeData() {
  224. var collection = GM_getValue(ltcbCollection.key);
  225. if (collection != undefined) {
  226. var f = document.getElementById('book_editForm');
  227. //$x1('//td[@id="bookedit_tags"]//input[@value=' + collection + ']').checked = true;
  228.  
  229. if (collection != 1) { // your library
  230. try {
  231. $x1('//td[@id="bookedit_tags"]//input[@value=1]').checked = false;
  232. click($x1('//div[@class="collectionListFooter"]/span[@id!=""]').firstChild);
  233. } catch (e) {
  234. console.log(e);
  235. }
  236. }
  237.  
  238. load(f, ltcbTitle);
  239. load(f, ltcbAuthor);
  240. load(f, ltcbDate);
  241. load(f, ltcbPublication);
  242. load(f, ltcbISBN);
  243. load(f, ltcbLCCN);
  244. load(f, ltcbDewey);
  245.  
  246. loadRole(f, ltcbAuthorRole);
  247.  
  248. var otherAuthorCount = GM_getValue(ltcbOtherAuthorCount.key);
  249.  
  250. if (otherAuthorCount)
  251. unsafeWindow.pcount = 1;
  252. for (var i = 0; i < otherAuthorCount; i++) {
  253. if (i)
  254. unsafeWindow.addPerson();
  255. load(f, ltcbOtherAuthorName, i);
  256. loadRole(f, ltcbOtherAuthorRole, i);
  257. }
  258. writeLangs();
  259. }
  260. }
  261.  
  262. var langLoadCalled = false;
  263.  
  264. function writeLangs() {
  265. var f = document.getElementById('book_editForm');
  266. var success = loadOption(f, ltcbLanguage)
  267. && loadOption(f, ltcbLanguage2) && loadOption(f, ltcbLanguageO);
  268. if (success)
  269. GM_deleteValue(ltcbCollection.key);
  270. else {
  271. if (!langLoadCalled) {
  272. langLoadCalled = true;
  273. unsafeWindow.book_updateLangMenus.call(unsafeWindow, 1);
  274. }
  275. // console.log('setting timeout');
  276. setTimeout(writeLangs, 100);
  277. }
  278. }
  279.  
  280. function $x(x, t, r) {
  281. if (t && t.nodeType)
  282. var h = r, r = t, t = h;
  283. var d = r ? r.ownerDocument || r : r = document, p;
  284. switch (t) {
  285. case XPathResult.NUMBER_TYPE:
  286. p = 'numberValue';
  287. break;
  288. case XPathResult.STRING_TYPE:
  289. p = 'stringValue';
  290. break;
  291. case XPathResult.BOOLEAN_TYPE:
  292. p = 'booleanValue';
  293. break;
  294. case XPathResult.ANY_UNORDERED_NODE_TYPE:
  295. case XPathResult.FIRST_ORDERED_NODE_TYPE:
  296. p = 'singleNodeValue';
  297. break;
  298. default:
  299. return d.evaluate(x, r, null,
  300. t || XPathResult.ORDERED_NODE_SNAPSHOT_TYPE, null);
  301. }
  302. var result = d.evaluate(x, r, null, t, null);
  303. if (result != null)
  304. result = result[p];
  305. return result;
  306. }
  307.  
  308. function $x1(x, r) {
  309. return $x(x, XPathResult.ANY_UNORDERED_NODE_TYPE, r)
  310. }
  311.  
  312. try {
  313. // find the values from the screen
  314. if (window.location.pathname.substring(0, '/work/'.length) == '/work/')
  315. readData()
  316. else if (window.location.pathname == '/addnew.php')
  317. writeData()
  318. } catch (e) {
  319. console.log(e);
  320. }