hosta list links

Userscript to add a few helpful links to each listed hosta

目前为 2015-12-26 提交的版本。查看 最新版本

  1. // ==UserScript==
  2. // @name hosta list links
  3. // @namespace hostalists
  4. // @include http*://www.hostalists.org/*
  5. // @version 1
  6. // @grant none
  7. // @description Userscript to add a few helpful links to each listed hosta
  8. // ==/UserScript==
  9.  
  10.  
  11. (function() {
  12. const HOSTA_LIST_ITEM_SELECTOR = 'h1 ~ table li, h1 ~ ul li';
  13. const MAX_NAME_LENGTH = 30;
  14. const SEARCH_TOKEN = '%s';
  15. const SEARCHES = {
  16. GOOGLE: {
  17. label: 'G',
  18. title: 'Google',
  19. url: 'https://www.google.com/search?q="%s" hosta',
  20. },
  21. GOOGLE_IMAGES: {
  22. label: 'img',
  23. title: 'Google Images',
  24. url: 'https://www.google.com/search?q="%s" hosta&tbm=isch',
  25. },
  26. HOSTA_LIBRARY: {
  27. label: 'HL',
  28. title: 'Hosta Library',
  29. url: 'https://www.google.com/search?q="%s"+site%3Ahostalibrary.org&btnI=1',
  30. },
  31. FRANSEN: {
  32. label: 'Fr',
  33. title: 'Fransen',
  34. url: 'https://www.google.com/search?q="%s"+site%3Ahostaparadise.com&btnI=1',
  35. },
  36. GARDENWEB: {
  37. label: 'GW',
  38. title: 'GardenWeb forums',
  39. url: 'https://www.google.com/search?q="%s" hosta+site%3Aforums.gardenweb.com&btnI=1',
  40. },
  41. };
  42. const LIST_ITEM_CLASS = 'link-decorated-hosta-li';
  43. const COMMON_CLASS_NAME = 'helper-link';
  44. const EXPANDED_CLASS = 'expanded';
  45. const STYLE = `
  46. .${LIST_ITEM_CLASS} {
  47. cursor: pointer;
  48. cursor: alias;
  49. }
  50. .${LIST_ITEM_CLASS} > .${COMMON_CLASS_NAME} {
  51. color: #006B45;
  52. display: none;
  53. }
  54. .${LIST_ITEM_CLASS}:hover > .${COMMON_CLASS_NAME},
  55. .${LIST_ITEM_CLASS}.${EXPANDED_CLASS} > .${COMMON_CLASS_NAME} {
  56. display: inline;
  57. }
  58. `;
  59. //////////////
  60. activate();
  61. //////////////
  62. function activate() {
  63. var listItems = document.querySelectorAll(HOSTA_LIST_ITEM_SELECTOR);
  64. addLinks(listItems);
  65. addClickHandler();
  66. addStyle();
  67. }
  68. function addLinks(hostaListItems) {
  69. for (var i = 0, listItem; listItem = hostaListItems[i]; i++) {
  70. var hosta = listItem.innerHTML.replace(/^\s*('|")|('|")\s*$/g, '');
  71. var links = makeLinks(hosta);
  72. for (var j = 0, link; link = links[j]; j++) {
  73. listItem.innerHTML += ' ';
  74. listItem.appendChild(link);
  75. }
  76. listItem.className += ` ${LIST_ITEM_CLASS}`;
  77. }
  78. function makeLinks(hostaName) {
  79. var links = [];
  80. if (!isHostaName(hostaName)) return links;
  81. for (var searchKey in SEARCHES) {
  82. if (!SEARCHES.hasOwnProperty(searchKey)) continue;
  83. var search = SEARCHES[searchKey];
  84. var url = search.url.replace(SEARCH_TOKEN, encodeURIComponent(hostaName));
  85. var link = makeLink( search.label, search.title, url );
  86. links.push(link);
  87. }
  88. return links;
  89. }
  90.  
  91. function makeLink(label, title, url) {
  92. var a = document.createElement('a');
  93. var siteClass = title.replace(/ /g, '-').toLowerCase();
  94. a.className = `${COMMON_CLASS_NAME} ${siteClass}`;
  95. a.href = url;
  96. a.title = title;
  97. a.target = '_blank';
  98. a.innerHTML = label;
  99. return a;
  100. }
  101. function isHostaName(term) {
  102. if (term.length > MAX_NAME_LENGTH) return false; // too long
  103. if (term.indexOf('<') != -1) return false; // contains HTML
  104. if (term.indexOf('.') != -1) return false; // contains a sentence
  105. return true;
  106. }
  107. }
  108. function addClickHandler() {
  109. document.body.addEventListener('click', function(event) {
  110. if (event.target.className.indexOf(LIST_ITEM_CLASS) == -1) return;
  111. if (event.target.className.indexOf(EXPANDED_CLASS) != -1) {
  112. event.target.className = event.target.className.replace(EXPANDED_CLASS, '');
  113. } else {
  114. event.target.className += ` ${EXPANDED_CLASS}`;
  115. event.target.className = event.target.className.replace(' ', ' ');
  116. }
  117. });
  118. }
  119. function addStyle() {
  120. var styleBlock = document.createElement('style');
  121. styleBlock.innerHTML = STYLE;
  122. document.head.appendChild(styleBlock);
  123. }
  124. })();