Direct Youtube Description External Links

Provides direct links for external URLs posted in Youtube video descriptions.

  1. // ==UserScript==
  2. // @name Direct Youtube Description External Links
  3. // @version 0.1
  4. // @description Provides direct links for external URLs posted in Youtube video descriptions.
  5. // @include /^https?\:\/\/(www|encrypted)\.youtube\./
  6. // @author re11ding
  7. // @license GPL version 2 or any later version; http://www.gnu.org/licenses/gpl-2.0.txt
  8. // @grant GM_addStyle
  9. // @run-at document-start
  10. // @credit zanetu and his Direct Google Images script as a useful baseline guide
  11. // @noframes
  12. // @namespace https://greasyfork.org/users/393964
  13. // ==/UserScript==
  14.  
  15. //do not run in frames or iframes
  16. if(window.top == window.self) {
  17. var RE = /redirect.+?(http.+?)(\&|$)/i;
  18.  
  19. function dd(url) {
  20. var d1 = decodeURIComponent(url), d2;
  21. try {
  22. d2 = decodeURIComponent(d1);
  23. }
  24. catch(malformed) {
  25. return d1;
  26. }
  27. return d2;
  28. }
  29.  
  30. function closest(element, matchFunction, maxLevel) {
  31. var max = undefined === maxLevel ? Number.POSITIVE_INFINITY : parseInt(maxLevel) + 1;
  32. if(max > 0 && 'function' === typeof matchFunction) {
  33. for(; element && max--; element = element.parentNode) {
  34. if(matchFunction(element)) {
  35. return element;
  36. }
  37. }
  38. }
  39. return null;
  40. }
  41.  
  42. function handleChange() {
  43. var a = document.getElementsByTagName('a');
  44. for(var i = a.length - 1; i >= 0; i--) {
  45. modifyYoutubeLink(a[i]);
  46. }
  47. a = [];
  48. }
  49.  
  50. function modifyYoutubeLink(element) {
  51. if(element && element.href) {
  52. var m = element.href.match(RE);
  53. if(m && m[1]) {
  54. element.href = dd(m[1]);
  55. }
  56. }
  57. }
  58.  
  59. function monitor() {
  60. MutationObserver = window.MutationObserver || window.WebKitMutationObserver;
  61. if(MutationObserver) {
  62. var observer = new MutationObserver(handleChange);
  63. observer.observe(document.documentElement, {childList: true, subtree: true});
  64. }
  65. //for chrome v18-, firefox v14-, internet explorer v11-, opera v15- and safari v6-
  66. else {
  67. setInterval(handleChange, 500);
  68. }
  69. handleChange();
  70. }
  71. //in case user clicks too early
  72. var m = location.href.match(RE);
  73. if(m && m[1]) {
  74. location.replace(dd(m[1]));
  75. }
  76.  
  77. //"@run-at document-start" is not fully supported
  78. if('interactive' == document.readyState || 'complete' == document.readyState) {
  79. monitor();
  80. }
  81. else {
  82. document.addEventListener('DOMContentLoaded', monitor, false);
  83. }
  84. }