Reddit Inline YouTube Viewer

Add an inline expand button for YouTube links like RES does for images.

  1. // ==UserScript==
  2. // @name Reddit Inline YouTube Viewer
  3. // @namespace reddit_youtube_expando
  4. // @description Add an inline expand button for YouTube links like RES does for images.
  5. // @include http://*.reddit.com/*
  6. // @include https://*.reddit.com/*
  7. // @match http://*.reddit.com/*
  8. // @match https://*.reddit.com/*
  9. // @version 1.3
  10. // @grant none
  11. // ==/UserScript==
  12.  
  13. // This work is licensed under the Creative Commons Attribution 2.0 Generic License.
  14. // To view a copy of this license, visit http://creativecommons.org/licenses/by/2.0/.
  15.  
  16. // This version of the regex can scrub some technicaly invalid links into valid ones, but I'm not sure
  17. // the list of video ID characters is correct.
  18. var youtubeLinkRegex = new RegExp("(?:^https?://(?:www\\.)?youtube\\.com/watch\\?(?:.*&)*v=([a-zA-Z0-9\\-_]+)[^#]*(?:#t=(.*$))?)|(?:^http://youtu.be/([a-zA-Z0-9\\-_]+))")
  19.  
  20. /*
  21. // Flash Embed
  22. var starTimeRegex = new RegExp("(?:(\\d+)m)?(\\d+)s")
  23. function addYouTubeEmbed(videoID, startTime) {
  24. var videoURL = "http://www.youtube.com/v/" + videoID
  25. if (startTime) {
  26. starTimeResult = starTimeRegex.exec(startTime)
  27. if (starTimeResult) {
  28. minutes = parseInt(starTimeResult[1])
  29. if (!minutes) {
  30. minutes = 0
  31. }
  32. seconds = parseInt(starTimeResult[2])
  33. seconds += minute * 60
  34. videoURL = videoURL + "&start=" + seconds
  35. }
  36. }
  37. var embedDiv = document.createElement("div")
  38. var embedObject = document.createElement("object")
  39. embedObject.setAttribute("type", "application/x-shockwave-flash")
  40. embedObject.setAttribute("style", "width:450px; height:366px; float: left")
  41. embedObject.setAttribute("data", videoURL)
  42. var paramElm = document.createElement("param")
  43. paramElm.setAttribute("name", "movie")
  44. paramElm.setAttribute("value", videoURL)
  45. embedObject.appendChild(paramElm)
  46. embedDiv.appendChild(embedObject)
  47. return embedDiv
  48. }
  49. */
  50.  
  51.  
  52. // IFrame Embed
  53. function addYouTubeEmbed(videoID, startTime) {
  54. var embedDiv = document.createElement("div")
  55. var embedObject = document.createElement("iframe")
  56. embedObject.setAttribute("class", "youtube-player")
  57. embedObject.setAttribute("type", "text/html")
  58. embedObject.setAttribute("width", "450")
  59. embedObject.setAttribute("height", "366")
  60. embedObject.setAttribute("allowfullscreen", "allowfullscreen")
  61. embedObject.setAttribute("mozallowfullscreen", "mozallowfullscreen")
  62. embedObject.setAttribute("webkitallowfullscreen", "webkitallowfullscreen")
  63.  
  64. linkProto = ('https:' == document.location.protocol ? 'https:' : 'http:')
  65.  
  66. if (startTime) {
  67. embedObject.setAttribute("src", linkProto + "//www.youtube.com/embed/" + videoID + "#t=" + startTime)
  68. }
  69. else {
  70. embedObject.setAttribute("src", linkProto + "//www.youtube.com/embed/" + videoID)
  71. }
  72. embedObject.setAttribute("frameborder", "0")
  73. embedDiv.appendChild(embedObject)
  74. return embedDiv
  75. }
  76.  
  77. var commentExpandoStyle = "vertical-align:top !important; float: none; width: 23px; height: 23px;" +
  78. "max-width: 23px; max-height: 23px; display: inline-block;" +
  79. "margin-right: 6px; cursor: pointer; padding: 0px;"
  80.  
  81. function addButtons(postDiv) {
  82. var innerLinks = Array.prototype.slice.call(postDiv.getElementsByTagName("a"));
  83. for (var j in innerLinks) {
  84. //innerLinks[j].className += " youtubeScanned"
  85. linkResult = youtubeLinkRegex.exec(innerLinks[j].href)
  86. if (linkResult) {
  87. innerLinks[j].className = innerLinks[j].className + " youtubeLinkFound"
  88. function genClickFunc() {
  89. // Capture these values with closure for the button function
  90. var theDiv = document.createElement("div")
  91. var embedObject = null
  92. // videoID from a youtube.com link || from a youtu.be link
  93. var videoID = linkResult[1] || linkResult[3]
  94. var startTime = linkResult[2]
  95. theDiv.setAttribute("class", "expando-button collapsed video")
  96. theDiv.setAttribute("style", commentExpandoStyle)
  97. var clickFunc = function () {
  98. if(theDiv.className.indexOf("collapsed") != -1) {
  99. theDiv.setAttribute("class", "expando-button expanded video")
  100. if (!embedObject) {
  101. embedObject = addYouTubeEmbed(videoID, startTime)
  102. }
  103. theDiv.parentNode.insertBefore(embedObject, theDiv.nextSibling)
  104. }
  105. else {
  106. theDiv.setAttribute("class", "expando-button collapsed video")
  107. theDiv.parentNode.removeChild(embedObject)
  108. }
  109. }
  110. innerLinks[j].parentNode.insertBefore(theDiv, innerLinks[j].nextSibling)
  111. theDiv.addEventListener('click', clickFunc, true)
  112. }
  113. genClickFunc()
  114. }
  115. }
  116. }
  117.  
  118. var mdElements = document.getElementsByClassName("md")
  119.  
  120. // Find all user created comment sections
  121. for (var i in mdElements) {
  122. if (mdElements[i].tagName == 'DIV') {
  123. addButtons(mdElements[i]);
  124. }
  125. }
  126.  
  127. // hasClass, stolen from the Reddit Enhancement Suite
  128. function hasClass(ele,cls) {
  129. if ((typeof(ele) == 'undefined') || (ele == null)) {
  130. console.log(arguments.callee.caller);
  131. return false;
  132. }
  133. return ele.className.match(new RegExp('(\\s|^)'+cls+'(\\s|$)'));
  134. }
  135.  
  136. // Add a listener for the DOMNodeInserted event so we can expand emotes in new comments
  137. // created by either a reply or by clicking "load more comments" in large threads.
  138. function handleInsertion( event ) {
  139. // The actual even we see will be the insertion of the outer "thing" div
  140. if ((event.target.tagName == 'DIV') && (hasClass(event.target, "thing"))) {
  141. var mdElements = event.target.getElementsByClassName("md")
  142. for (var i in mdElements) {
  143. if (mdElements[i].tagName == 'DIV') {
  144. addButtons(mdElements[i]);
  145. }
  146. }
  147. }
  148. }
  149.  
  150. document.body.addEventListener('DOMNodeInserted', handleInsertion, false);