One Click Copy URIs

Adds buttons to text links and videos to copy the linked URI to clipboard in one click.

  1. // ==UserScript==
  2. // @name One Click Copy URIs
  3. // @namespace http://github.com/kba
  4. // @version 0.2
  5. // @description Adds buttons to text links and videos to copy the linked URI to clipboard in one click.
  6. // @author kba
  7. // @match */*
  8.  
  9. // @grant GM_setValue
  10. // @grant GM_getValue
  11. // @grant GM_registerMenuCommand
  12. // @grant GM_log
  13.  
  14. // @require https://greasyfork.org/libraries/GM_config/20131122/GM_config.js
  15. // @require https://code.jquery.com/jquery-2.2.0.js
  16. // @require https://cdnjs.cloudflare.com/ajax/libs/clipboard.js/1.5.8/clipboard.min.js
  17.  
  18. // ==/UserScript==
  19. /* jshint -W097, esnext:true */
  20. /* globals GM_log, GM_setValue, GM_getValue, GM_registerMenuCommand, GM_config, Clipboard, $ */
  21. 'use strict';
  22.  
  23. // Setup configuration
  24. GM_config.init({
  25. 'id': 'one-click-copy',
  26. 'title': 'Configure OneClickCopy',
  27. 'fields': {
  28.  
  29. 'auto_video': {
  30. 'label': 'Add Copy Button to all videos?',
  31. 'type': 'checkbox',
  32. 'default': false,
  33. },
  34.  
  35. 'timeout': {
  36. 'label': 'Delay in ms before adding button to video',
  37. 'type': 'number',
  38. 'default': 1500,
  39. },
  40.  
  41. 'auto_text': {
  42. 'label': 'Add Copy Button to all Text links?',
  43. 'type': 'checkbox',
  44. 'default': false,
  45. },
  46.  
  47. "include_links": {
  48. 'label': 'Selectors to find text links. First matching selector is used.',
  49. 'type': 'textarea',
  50. 'rows': 5,
  51. 'width': 30,
  52. 'default': [
  53. '#content a[href]',
  54. 'a[href]'
  55. ].join("\n"),
  56. },
  57.  
  58.  
  59. "skip_parents": {
  60. 'label': 'Skip text links that are children of parents matching these selectors',
  61. 'type': 'textarea',
  62. 'rows': 10,
  63. 'width': 30,
  64. 'default': [
  65. 'header',
  66. '#header',
  67. 'footer',
  68. '#footer',
  69. '#tags',
  70. '*[id*=tags]',
  71. '*[class*=tags]',
  72. '#categories',
  73. '*[id*=categories]',
  74. '*[class*=categories]',
  75. '#navigation',
  76. '.nav',
  77. '*[role="navigation"]',
  78. ].join("\n"),
  79. },
  80.  
  81. },
  82.  
  83. });
  84.  
  85. // Helper to add inline CSS rules
  86. function addCSSRules(rules) {
  87. var style = document.createElement("style");
  88. style.innerHTML = rules.replace(/;/g, '!important ;');
  89. document.head.appendChild(style);
  90. }
  91.  
  92. // Add CSS
  93. $('head').append($('<style>').append(`
  94.  
  95. .gm-link-tools {
  96. position: relative;
  97. display: inline-block;
  98. line-height: 1;
  99. padding: 0 2px;
  100. cursor: copy;
  101. font-size: 150%;
  102. opacity: 1;
  103. vertical-align: middle;
  104. background: gray;
  105. color: white;
  106. height: initial;
  107. width: initial;
  108. z-index: 1001;
  109. }
  110.  
  111. .gm-link-tools > span {
  112. display: block;
  113. overflow:hidden;
  114. max-height:100%;
  115. }
  116.  
  117. .gm-link-tools.copied {
  118. color: #6f5;
  119. }
  120.  
  121. `));
  122.  
  123. // The rules that determine which links are skipped
  124. var skip_parents = GM_config.get('skip_parents').split(/\n/g);
  125. var excludeMatchers = {
  126. 'numeric': function($link) { return /^\d+$/.test($link.html()); },
  127. 'image': function($link) { return $("img", $link).length; },
  128. 'parent': function($link) {
  129. for (var i = 0 ; i < skip_parents.length ; i++) {
  130. if ($link.parents(skip_parents[i]).length > 0) {
  131. return skip_parents[i];
  132. }
  133. }
  134. },
  135. };
  136.  
  137. // Create the button
  138. function createCopyLink(href) {
  139. return $(`
  140. <a data-clipboard-text="${href}" title="Copy to Clipboard" class="gm-link-tools">
  141. <span>∀</span>
  142. </a>
  143. `);
  144. }
  145.  
  146. // Add clipboard functionality to copy button and add after element
  147. function appendClipboardLink($el, $copyLink) {
  148. var clipboard = new Clipboard($copyLink[0]);
  149. clipboard.on('success', function(e) {
  150. $copyLink.addClass("copied");
  151. $copyLink.html('<span>✔</span>');
  152. return false;
  153. });
  154. clipboard.on('error', function(e) {
  155. $copyLink.addClass("failed");
  156. $copyLink.html('<span>X</span>');
  157. });
  158. $("<span>")
  159. .on('click tap mousedown touchstart', function(evt) {
  160. evt.stopPropagation();
  161. return false;
  162. })
  163. .append($copyLink)
  164. .insertAfter($el);
  165. }
  166.  
  167. //
  168. // Text Links
  169. //
  170.  
  171. function clippifyLink(){
  172. /* jshint validthis:true */
  173. var $link = $(this);
  174. for (var rule in excludeMatchers) {
  175. var result = excludeMatchers[rule]($link);
  176. if (result) {
  177. GM_log(`SKIP ${rule}/${result}: '${$link.text()}'`);
  178. return;
  179. }
  180. }
  181. var href = $link[0].href;
  182. var $copyLink = createCopyLink(href);
  183. appendClipboardLink($link, $copyLink);
  184. }
  185.  
  186. function clippifyLinks(){
  187. var links;
  188. var includeLinks = GM_config.get('include_links').split(/\n/g);
  189. for (var i = 0 ; i < includeLinks.length ; i++) {
  190. links = $(includeLinks[i]);
  191. if (links.length > 0) {
  192. break;
  193. }
  194. }
  195. $(links).each(clippifyLink);
  196. }
  197.  
  198. //
  199. // Videos
  200. //
  201.  
  202. function clippifyVideo() {
  203. /* jshint validthis:true */
  204. var $video = $(this);
  205. var src = $video[0].currentSrc;
  206. if (! src) return;
  207. var $copyLink = createCopyLink(src);
  208. appendClipboardLink($video, $copyLink);
  209. }
  210.  
  211. function clippifyVideos() {
  212. $("video").each(clippifyVideo);
  213. }
  214.  
  215. //
  216. // Setup menu commands
  217. //
  218. GM_registerMenuCommand('Configure One-Click-Copy', GM_config.open.bind(GM_config), 'c');
  219. GM_registerMenuCommand("Text Links: Add Copy Button", clippifyLinks, "l");
  220. GM_registerMenuCommand("Videos: Add Copy Button", clippifyVideos, "v");
  221.  
  222. //
  223. // Automate adding buttons
  224. //
  225. if (GM_config.get('auto_video')) {
  226. setTimeout(function() {
  227. $("video").one('progress', clippifyVideo);
  228. }, GM_config.get('timeout'));
  229. }
  230. if (GM_config.get('auto_text')) {
  231. setTimeout(function() {
  232. clippifyLinks();
  233. }, GM_config.get('timeout'));
  234. }
  235.  
  236.  
  237.  
  238.  
  239.  
  240.  
  241. // vim: set noet ts=4 sw=4 :