Amalib_TDU

東京電機大学の図書館とAmazonの検索をリンク

  1. // ==UserScript==
  2. // @name Amalib_TDU
  3. // @namespace https://twitter.com/akameco
  4. // @description 東京電機大学の図書館とAmazonの検索をリンク
  5. // @author akameco
  6. // @include http://www.amazon.co.jp/*
  7. // @include http://lib.mrcl.dendai.ac.jp/*
  8. // @include https://lib.mrcl.dendai.ac.jp/*
  9. // @version 1.00
  10. // @grant GM_xmlhttpRequest
  11. // ==/UserScript==
  12. (function () {
  13.  
  14. /*
  15. * ユーティリティ関数
  16. */
  17. // エレメント作成
  18. let createElement = function(tag,attr,content) {
  19. let dom = document.createElement(tag);
  20. for (let key in attr) {
  21. dom.setAttribute(key,attr[key]);
  22. }
  23. if(content){
  24. dom.textContent = content;
  25. }
  26. return dom;
  27. };
  28.  
  29. /*
  30. * amazon
  31. */
  32. let Amazon = {
  33. info: {
  34. _isbn: '',
  35. _title: '',
  36. _press: '',
  37. _response: '',
  38. _btAsinTitle: '',
  39. _res: null,
  40. setIsbn: function () {
  41. document.body.parentNode.innerHTML
  42. .match(/name=\"ASIN\" value=\"([0-9A-Z]{10})([\/\-_a-zA-Z0-9]*)/i);
  43. this._isbn = RegExp.$1;
  44. },
  45. get isbn() {
  46. return this._isbn;
  47. },
  48. setTitle: function() {
  49. this._title = document.getElementById('btAsinTitle').firstChild.textContent.slice(0,-1);
  50. },
  51. get title() {
  52. return this._title;
  53. },
  54. setPress: function() {
  55. document.body.innerHTML.match(/出版社:<\/b> (.+?) \(/);
  56. this._press = RegExp.$1;
  57. },
  58. get press() {
  59. return this._press;
  60. },
  61. setPrice: function() {
  62. let text = document.querySelectorAll('#actualPriceValue .priceLarge')[0].textContent;
  63. this._price = text.replace(/¥ /,"").replace("\n","").replace(",","");
  64. },
  65. get price() {
  66. return this._price;
  67. },
  68. setBtAsinTitle: function() {
  69. this._btAsinTitle = document.getElementById('btAsinTitle').parentNode;
  70.  
  71. },
  72. get btAsinTitle() {
  73. return this._btAsinTitle;
  74. },
  75. setRes: function(response) {
  76. // 一度ノードに変換しないとdom操作ができない
  77. let html = document.createElement('div');
  78. html.innerHTML = response;
  79. this._res = html;
  80. },
  81. get res() {
  82. return this._res;
  83. }
  84. },
  85.  
  86. /*
  87. * 初期化
  88. */
  89. init: function() {
  90. Amazon.info.setIsbn();
  91. Amazon.info.setTitle();
  92. Amazon.info.setPress();
  93. Amazon.info.setPrice();
  94. Amazon.info.setBtAsinTitle();
  95. },
  96.  
  97. // 図書館情報
  98. library: {
  99. setPlace: function() {
  100. // localStorage.removeItem('place');
  101. let places = ['千住','千葉','鳩山'];
  102. if(localStorage.getItem('place') == null) {
  103. let div = createElement('div',{id:'selectLib'});
  104. let text = createElement('div',{id: 'readme'});
  105. text.innerHTML =
  106. 'このプラグインは東京電機大学図書館の蔵書状況を表示します。<br>' +
  107. '最初に下のリンクからキャンパスの場所を設定してください。<br>' +
  108. '不具合・要望等があったら' +
  109. '<a href="http://twitter.com/akameco" target="_blank">赤芽(Twitter)</a>' +
  110. 'までお気軽に。<br>';
  111. for (let i=0; i < places.length; ++i) {
  112. let element = createElement('a',{href:'javascript:void(0)'},places[i]);
  113. element.addEventListener('click',function (event) {
  114. localStorage.setItem('place',event.target.text);
  115. // 現在表示されているものを削除
  116. let p = document.querySelector('.parseasinTitle').children;
  117. for (let j=1,len = p.length; j < len; ++j){
  118. Amazon.info.btAsinTitle.removeChild(p[1]);
  119. }
  120. // 再描写
  121. Amazon.disp.link();
  122. let e = Amazon.info.res.querySelector('.flst_head');
  123. if(e != null){
  124. Amazon.disp.bookLink();
  125. }else{
  126. Amazon.disp.orderLink();
  127. }
  128. },false);
  129. div.appendChild(element);
  130. }
  131. text.appendChild(div);
  132. Amazon.info.btAsinTitle.appendChild(text);
  133. }
  134. },
  135. // 図書館の場所
  136. get home() {
  137. return localStorage.getItem('place');
  138. }
  139. },
  140.  
  141. // 表示
  142. disp: {
  143. // 図書館へのリンク
  144. link: function() {
  145. let div = createElement('div',{id:'tdu_link'});
  146. let link = createElement('a',{
  147. href: 'https://lib.mrcl.dendai.ac.jp/webopac/ctlsrh.do?isbn_issn=' +
  148. Amazon.info.isbn,
  149. target: '_blank'},
  150. '図書館検索'
  151. );
  152. div.appendChild(link);
  153. Amazon.info.btAsinTitle.appendChild(div);
  154. },
  155.  
  156. // ロード状態の表示
  157. loading: function() {
  158. let div = createElement('div',{id:'loading'},'NOW LOADING...');
  159. Amazon.info.btAsinTitle.appendChild(div);
  160. },
  161.  
  162. // ロード表示の削除
  163. removeLoading: function() {
  164. let element = document.getElementById('loading');
  165. element.parentNode.removeChild(element);
  166. },
  167.  
  168. // 購入依頼のリンク作成
  169. orderLink: function() {
  170. let link = 'https://lib.mrcl.dendai.ac.jp/webopac/odridf.do?isbn=' +
  171. Amazon.info.isbn +
  172. '&title=' +
  173. encodeURIComponent(Amazon.info.title) +
  174. '&press=' +
  175. encodeURIComponent(Amazon.info.press) +
  176. '&price=' +
  177. Amazon.info.price;
  178. let a = createElement('a',{href: link,target:'_blank',id: 'order'},'購入依頼');
  179. Amazon.info.btAsinTitle.appendChild(a);
  180. },
  181.  
  182. // 各図書館の蔵書状況の表示
  183. bookLink: function() {
  184. let div = createElement('div',{id:'tduBooks'});
  185. // 要素の調査
  186. let tbody = Amazon.info.res.querySelectorAll('.flst_head')[0].parentNode;
  187. for (let i=1,len = tbody.children.length; i < len; ++i) {
  188. let element = createElement('div');
  189. let tr = tbody.children[i];
  190. // 所蔵館・状態・返却期限日(配架済 or 貸出中)
  191. let library = {
  192. place: tr.children[3].firstChild.firstChild.nodeValue,
  193. state: tr.children[8].firstChild.firstChild.nodeValue,
  194. priod: tr.children[9].firstChild.firstChild.nodeValue
  195. };
  196.  
  197. if(library.place == Amazon.library.home) {
  198. element.setAttribute('id','myhome');
  199. }
  200. if(library.state == '貸出中') {
  201. element.innerHTML = library.place + ' ' +
  202. library.state + ' ' +
  203. '返却期限 ' + library.priod;
  204. }else{
  205. element.innerHTML = library.place + ' ' + library.state;
  206. }
  207. div.appendChild(element);
  208. }
  209. Amazon.info.btAsinTitle.appendChild(div);
  210. }
  211. },
  212.  
  213. // 関数定義
  214. checkCategory: function() {
  215. let category = document.querySelector('.nav-category-button').firstChild.innerHTML;
  216. if(category == '本') {
  217. return true;
  218. }
  219. return false;
  220. },
  221.  
  222. // 蔵書のページ確認
  223. checkPage: function (response) {
  224. Amazon.info.setRes(response);
  225. let element = Amazon.info.res.querySelector('.flst_head');
  226. if (element != null) {
  227. Amazon.disp.bookLink();
  228. }else{
  229. Amazon.disp.orderLink();
  230. }
  231. },
  232.  
  233. // HTTPRequestにより蔵書情報取得
  234. request: function () {
  235. let link = 'http://lib.mrcl.dendai.ac.jp/webopac/ctlsrh.do?isbn_issn=' +
  236. Amazon.info.isbn;
  237. GM_xmlhttpRequest({
  238. method: 'GET',
  239. url: link,
  240. onload: function(xhr) {
  241. Amazon.disp.removeLoading();
  242. Amazon.library.setPlace();
  243. Amazon.checkPage(xhr.responseText);
  244. }
  245. });
  246. },
  247.  
  248. // css定義
  249. style: function() {
  250. let style = "\
  251. #tduBooks{\
  252. background: none;\
  253. color: #333333;\
  254. font-size: 16px;\
  255. display:table;\
  256. margin: 1px 15px 0;\
  257. }\
  258. #tduBooks div{\
  259. margin: 1px 15px;\
  260. }\
  261. div#tdu_link{\
  262. display: table;\
  263. margin: 2px 2px 2px;\
  264. }\
  265. div#tdu_link a{\
  266. margin: 10px 5px;\
  267. font-size: 16px;\
  268. }\
  269. #loading{\
  270. display: table;\
  271. font-size: 16px;\
  272. color: #333333;\
  273. margin: 0px 15px;\
  274. padding: 2px 15px\
  275. }\
  276. #myhome {\
  277. color:#009900;\
  278. font-weight: bold;\
  279. }\
  280. #order {\
  281. display: table;\
  282. font-size: 16px;\
  283. margin: 5px 15px;\
  284. padding: 2px 15px\
  285. }\
  286. #readme{\
  287. border-style: solid;\
  288. border-radius: 10px;\
  289. border-width: 1px;\
  290. display: table;\
  291. font-size: 15px;\
  292. color: #333333;\
  293. margin: 10px 15px;\
  294. padding: 10px 15px;\
  295. }\
  296. #selectLib{\
  297. margin: 10px 15px;\
  298. padding: 2px 15px;\
  299. display: table;\
  300. font-size: 18px;\
  301. }\
  302. #selectLib a{\
  303. margin: 0px 5px;\
  304. }\
  305. ";
  306. let head = document.getElementsByTagName('head')[0];
  307. let element = window.document.createElement('style');
  308. element.type = "text/css";
  309. element.textContent = style;
  310. head.appendChild(element);
  311. },
  312.  
  313. open: function() {
  314. if(!Amazon.checkCategory()) {
  315. return;
  316. }
  317. if(Amazon.info.isbn) {
  318. Amazon.request();
  319. Amazon.disp.link();
  320. Amazon.disp.loading();
  321. Amazon.style();
  322. }
  323. }
  324. };
  325.  
  326. /*
  327. * 電機大学図書館
  328. */
  329. let Library = {
  330.  
  331. // URLをオブジェクトにして返却
  332. get parames() {
  333. if(1 < window.location.search.length) {
  334. let parameters = window.location.search.substring(1).split('&');
  335. let result = {};
  336. for (let i=0,len = parameters.length; i < len; ++i) {
  337. let element = parameters[i].split('=');
  338. result[decodeURIComponent(element[0])] = decodeURIComponent(element[1]);
  339. }
  340. return result;
  341. }
  342. return null;
  343. },
  344.  
  345. login: function () {
  346. let loginbutton = null;
  347. let pass=false;
  348. let form = document.forms[0];
  349. form.setAttribute('autocomplete','on');
  350. for (let j=0; formelement=form.getElementsByTagName('input')[j]; ++j) {
  351. if(formelement.type == 'password' && formelement.value) {
  352. pass = true;
  353. break;
  354. }
  355. }
  356. for (let j=0; formelement=form.getElementsByTagName('input')[j]; ++j) {
  357. if (formelement.type == 'image' && pass) {
  358. loginbutton = formelement;
  359. break;
  360. }
  361. }
  362. if(loginbutton) {
  363. loginbutton.focus();
  364. loginbutton.click();
  365. }
  366. },
  367.  
  368. checkHasBook: function() {
  369. let err = document.body.innerHTML.match('指定された条件に該当する資料がありません');
  370. if (err) {
  371. Library.openOrderPage();
  372. }
  373. },
  374.  
  375. openOrderPage: function() {
  376. let w;
  377. document.svcodrform.action='https://' +
  378. window.location.host +
  379. '/webopac/odrexm.do' +
  380. window.location.search;
  381. document.svcodrform.mode.value='new';
  382. document.svcodrform.reqType.value='_NEW';
  383. document.svcodrform.loginType.value='once';
  384. w = window.open('','_self');
  385. document.svcodrform.submit();
  386. w.focus();
  387. },
  388.  
  389. // formのactionにパラメータ追加
  390. setForm: function() {
  391. let form = document.forms[0];
  392. form.action = '/webopac/odridf.do' + window.location.search;
  393. Library.login();
  394. },
  395.  
  396. // システムメッセージが表示されたか確認
  397. checkErr: function() {
  398. let err = document.body.innerHTML.match('OP-2010-E');
  399. if(err) {
  400. let url = 'http://lib.mrcl.dendai.ac.jp/webopac/ctlsrh.do' +
  401. window.location.search;
  402. window.open(url,'_self');
  403. }else{
  404. Library.input();
  405. }
  406. },
  407.  
  408. // フォームに自動入力
  409. input: function () {
  410. let tds = document.querySelectorAll('table.opt_frame tbody tr td input');
  411. let values = {
  412. 'bibtr': Library.parames['title'],
  413. 'bibpb': Library.parames['press'],
  414. 'isbn' : Library.parames['isbn'],
  415. 'bibpr': Library.parames['price']
  416. };
  417. for (let i=0; i < tds.length; ++i) {
  418. let td = tds[i].getAttribute('name');
  419. for(let name in values) {
  420. if(td == name) {
  421. tds[i].value = values[name];
  422. }
  423. }
  424. }
  425. },
  426.  
  427. // isbnのみか他のパラメータがあるかチェック
  428. checkParam: function() {
  429. let parameters = window.location.search.substring(1).split('&');
  430. if(parameters.length < 4){
  431. return false;
  432. }
  433. return true;
  434. },
  435.  
  436. start: {
  437. '/webopac/ctlsrh.do': function () {
  438. if(Library.checkParam()) {
  439. Library.checkHasBook();
  440. }
  441. },
  442. '/webopac/odridf.do': function () {
  443. Library.checkErr();
  444. },
  445. '/webopac/odrexm.do': function () {
  446. if(Library.checkParam()) {
  447. Library.setForm();
  448. }else{
  449. Library.login();
  450. }
  451. },
  452. '/webopac/rsvexm.do':function () {
  453. Library.login();
  454. }
  455. }
  456. };
  457.  
  458. // urlを確認
  459. let checkHost = {
  460. 'www.amazon.co.jp': function () {
  461. Amazon.init();
  462. Amazon.open();
  463. },
  464. 'lib.mrcl.dendai.ac.jp': function () {
  465. let path = window.location.pathname;
  466. Library.start[path]();
  467. }
  468. };
  469.  
  470. window.onload = function () {
  471. let host = window.location.host;
  472. try{
  473. let f = checkHost[host];
  474. if(f == undefined) return;
  475. f();
  476. }catch(err){
  477. console.log(err);
  478. }
  479. return;
  480. };
  481. })();