Steve5451

Blockland Embedder 3.5

May 25th, 2014
47,503
0
Never
Not a member of Pastebin yet? Sign Up, it unlocks many cool features!
  1. // ==UserScript==
  2. // @name Blockland Embedder
  3. // @version 3.5
  4. // @updateURL http://pastebin.com/raw.php?i=V8uRXppr
  5. // @downloadURL http://pastebin.com/raw.php?i=V8uRXppr
  6. // @include https://forum.blockland.us*
  7. // @description Embed YouTube, vid.me, Soundcloud, gifv, various video, and audio links on BLF.
  8. // @author Steve5451
  9. // @grant none
  10. // @noframes
  11. // ==/UserScript==
  12.  
  13. const autoplay = true; // Whether to start playing the media after clicking embed. false to disable. note: NOT auto-embed.
  14.  
  15. // ----------------------------- You probably shouldn't touch anything below ----------------------- //
  16.  
  17. var links = document.getElementsByTagName("a"),
  18.     embedButtons = [], // Get a list of links.
  19.  
  20.     resize = {
  21.         dragging: false,
  22.         element: null,
  23.  
  24.         startX: 0,
  25.         startY: 0,
  26.  
  27.         original: {
  28.             x: 0,
  29.             y: 0
  30.         }
  31.     },
  32.  
  33.     videoSize;
  34.  
  35. const defaultVideoSize = {
  36.     width: 640,
  37.     height: 360
  38. };
  39.  
  40. if(localStorage.videoSize) {
  41.     try {
  42.         videoSize = JSON.parse(localStorage.videoSize);
  43.     } catch(error) {
  44.         console.error(error);
  45.         videoSize = defaultVideoSize;
  46.         localStorage.videoSize = JSON.stringify(defaultVideoSize);
  47.     }
  48. } else {
  49.     videoSize = defaultVideoSize;
  50.     localStorage.videoSize = JSON.stringify(defaultVideoSize);
  51. }
  52.  
  53. for(var i = 0; i < links.length; i++) { // For each link
  54.     var href = links[i].getAttribute("href"); // Get URL of link.
  55.  
  56.     if(!href) continue;
  57.  
  58.     // Say hello to the else if stack to end all else if stacks.
  59.     // A switch (or maybe a lovely little object key checking) would be preferred but doesn't offer both the includes() and endsWith() checks that I do.
  60.     if(href.includes("youtube.com/watch")) { // This is a YouTube video
  61.         if(href.includes("?v="))
  62.             var vidId  = href.split("?v=")[1].split("&")[0]; // Get the YouTube video ID
  63.         else if(href.includes("&v="))
  64.             var vidId = href.split("&v=")[1].split("&")[0];
  65.  
  66.         var getParams = href.split(/[?&]/g); // Get the GET params in the URL
  67.         for(var a = 0; a < getParams.length; a++) {
  68.             if(getParams[a].startsWith("t=")) { // This is specifying a start time
  69.                 vidId += "?t=" + getParams[a].substr(2); // Add to the media ID
  70.                 break;
  71.             }
  72.         }
  73.  
  74.         embedMedia(vidId, links[i], "youtubeExpand"); // And pass it on to this function
  75.     } else if(href.includes("youtu.be/")) { // This is another type of YouTube link.
  76.         let vidId = href.substr(href.lastIndexOf("/") + 1);
  77.  
  78.         embedMedia(vidId, links[i], "youtubeExpand");
  79.     } else if(href.includes("vid.me/")) { // vid.me
  80.         let vidId = href.substr(href.lastIndexOf("vid.me/") + 7);
  81.  
  82.         embedMedia(vidId, links[i], "vidmeExpand");
  83.     } else if(href.includes("soundcloud.com/")) { // This is a SoundCloud link.
  84.         let scId = href.replace(' ','');
  85.  
  86.         embedMedia(scId, links[i], "soundcloudExpand");
  87.  
  88.         /*} else if(href && href.includes("vocaroo.com/i/")) { // This is a Vocaroo link. DROPPED UNTIL VOCAROO SUPPORTS HTTPS.
  89.         var vocId = href.substr(href.indexOf('/i/'));
  90.  
  91.         embedMedia(vocId, links[i], 'vocarooExpand'); */
  92.     } else if(href.endsWith(".gifv")) { // This is an Imgur gifv.
  93.         embedMedia(href, links[i], "gifv");
  94.     } else if(href.endsWith(".mp4") || href.endsWith(".webm") || href.endsWith(".avi") || href.endsWith(".mkv")) {
  95.         embedMedia(href, links[i], "genericVideo");
  96.     } else if(href.endsWith(".mp3") || href.endsWith(".ogg") || href.endsWith(".wav") || href.endsWith(".wma") || href.endsWith(".oga") || href.endsWith(".opus") || href.endsWith(".m4a") || href.endsWith(".aac")) {
  97.         embedMedia(href, links[i], "genericAudio");
  98.     }
  99. }
  100.  
  101. function embedMedia(medId, thisItem, embedType) { // This will create a button next to links.
  102.     let newButton = document.createElement("input");
  103.     newButton.type = "button";
  104.     newButton.class = "embedMedia";
  105.     newButton.id = embedType;
  106.     newButton.value = "Embed";
  107.     newButton.style.marginLeft = newButton.style.marginRight = "5px";
  108.     newButton.setAttribute("medId", medId);
  109.     newButton.setAttribute("expanded", "false");
  110.  
  111.     thisItem.parentNode.insertBefore(newButton, thisItem.nextSibling);
  112.  
  113.     newButton.onclick = embedClick;
  114. }
  115.  
  116. function embedClick() {
  117.     if(this.getAttribute("expanded") === "false") { // It's not expanded.
  118.         var thisId = this.getAttribute("id"),
  119.             newDiv = document.createElement("div");
  120.  
  121.         switch(thisId) {
  122.             case "youtubeExpand":
  123.                 var medId = this.getAttribute("medId"), // Let's get the id of the video including any GET params.
  124.                     pureUrl = medId.split('?')[0].split("#")[0]; // Remove extra info after video ID.
  125.  
  126.                 if(medId.includes("?t=") || medId.includes("&t=") || medId.includes("#t=")) { // This video starts at a specified time.
  127.                     let startTime = medId.replace("?t=","?start=").replace("&t=","&start=").replace("#t=","&start=").split('start=')[1].split('&')[0]; // Used a dorky method of considering both the possibility of ?t, &t and #t, converted, then replaced. Using this to isolate the start time.
  128.  
  129.                     if(startTime.indexOf('s') !== -1) // We've got an s in our time, which means it's using minute second format instead of just seconds. Let's convert.
  130.                         startTime = convertTime(startTime); // Convert it.
  131.  
  132.                     pureUrl += "?start=" + startTime; // Add the start time param to the video id.
  133.                 }
  134.  
  135.                 newDiv.style.width = videoSize.width + "px";
  136.                 newDiv.style.height = videoSize.height + "px";
  137.  
  138.                 newDiv.setAttribute("class", "media-container");
  139.  
  140.                 newDiv.innerHTML = '<iframe width="100%" height="100%" style="position: relative; z-index: 2;" src="//www.youtube.com/embed/' + pureUrl + (pureUrl.includes("?") ? "&" : "?") + 'autoplay=' + (autoplay ? "1" : "0") + '" frameborder="0" allowfullscreen></iframe>';
  141.                 this.parentNode.insertBefore(newDiv, this.nextSibling); // Append video.
  142.  
  143.                 makeResizable(newDiv);
  144.  
  145.                 break;
  146.  
  147.             case "vidmeExpand":
  148.                 var medId = this.getAttribute("medId"), // Let's get the id of the video including any GET params.
  149.                     pureUrl = medId.split('?')[0].split("#")[0];
  150.  
  151.                 newDiv.style.width = videoSize.width + "px";
  152.                 newDiv.style.height = videoSize.height + "px";
  153.  
  154.                 newDiv.setAttribute("class", "media-container");
  155.  
  156.                 newDiv.innerHTML = '<iframe src="https://vid.me/e/' + pureUrl + '" width="100%" height="100%" style="position: relative; z-index: 2;" frameborder="0" allowfullscreen webkitallowfullscreen mozallowfullscreen scrolling="no"></iframe>';
  157.                 this.parentNode.insertBefore(newDiv, this.nextSibling); // Append video.
  158.  
  159.                 makeResizable(newDiv);
  160.  
  161.                 break;
  162.  
  163.             case "soundcloudExpand":
  164.                 newDiv.innerHTML = '<iframe width="100%" height="100%" scrolling="no" frameborder="no" src="https://w.soundcloud.com/player/?url=' + this.getAttribute("medId") + '&amp;color=ff5500&amp;auto_play=' + (autoplay ? "true" : "false") + '&amp;hide_related=false&amp;show_artwork=true"></iframe>';
  165.                 this.parentNode.insertBefore(newDiv, this.nextSibling);
  166.  
  167.                 break;
  168.                 /*case "vocarooExpand":
  169.                     newDiv.innerHTML = '<div style="width: 300px; background-color: #CAFF70; text-align: center; border-radius: 6px; margin-top: 3px; margin-bottom: 3px; padding-top: 5px; padding-bottom: 5px;"><embed src="http://vocaroo.com/mediafoo.swf?playMediaID=' + this.getAttribute("medId") + '&amp;autoplay=1" width="220" height="140" type="application/x-shockwave-flash" pluginspage="http://get.adobe.com/flashplayer/"></div>';
  170.                     this.parentNode.insertBefore(newDiv, this.nextSibling);
  171.  
  172.                     break;*/
  173.  
  174.             case "gifv":
  175.                 var vidUrl = this.getAttribute("medId").replace("gifv","mp4"); // Imgur's gifv's are just mp4's and thankfully they will allow us to change the extension so our browsers recognize it.
  176.  
  177.                 newDiv.innerHTML = '<video style="" ' + (autoplay ? "autoplay" : "") + ' loop><source src="' + vidUrl + '" type="video/mp4"/></video>';
  178.                 this.parentNode.insertBefore(newDiv, this.nextSibling);
  179.  
  180.                 break;
  181.  
  182.             case "genericVideo":
  183.                 newDiv.style.width = videoSize.width + "px";
  184.                 newDiv.style.height = videoSize.height + "px";
  185.  
  186.                 newDiv.setAttribute("class", "media-container");
  187.  
  188.                 newDiv.innerHTML = '<video style="background-color: #000;" width="100%" height="100%" ' + (autoplay ? "autoplay" : "") + ' controls><source src="' + this.getAttribute("medId") + '"/></video>';
  189.                 this.parentNode.insertBefore(newDiv, this.nextSibling);
  190.  
  191.                 makeResizable(newDiv);
  192.  
  193.                 break;
  194.  
  195.             case "genericAudio":
  196.                 newDiv.innerHTML = '<audio ' + (autoplay ? "autoplay" : "") + ' controls><source src="' + this.getAttribute("medId") + '"/></audio>';
  197.                 this.parentNode.insertBefore(newDiv, this.nextSibling);
  198.  
  199.                 break;
  200.         }
  201.  
  202.         this.setAttribute("value","Remove");
  203.         this.setAttribute("expanded", "true");
  204.     } else { // It's already expanded, let's remove it.
  205.         this.nextSibling.remove();
  206.         this.setAttribute("value","Embed");
  207.         this.setAttribute("expanded", "false");
  208.     }
  209. }
  210.  
  211. document.body.onselectstart = function(event) { // override onselect so we don't select stuff while resizing the video. only half works with youtube videos cause iframes are a bitch
  212.     if(event.target.constructor.name !== "HTMLDivElement" || event.target.getAttribute) return true; // not our resize div, allow selection
  213.  
  214.     var className = event.target.getAttribute("class"); // get class of target
  215.     return !(event.target.getAttribute("class") === "video-resize" || event.target.tagName.toLowerCase() === "iframe" || className === "media-container" || className === "media-cover"); // if it's our resize div return false, otherwise allow.
  216. };
  217.  
  218. function makeResizable(element) {
  219.     element.style.padding = "2px";
  220.     element.style.position = "relative"; // to position the resizer in the bottom left we need to make the position relative
  221.  
  222.     var resizePoint = document.createElement("div"); // this is what we grab on to.
  223.     resizePoint.setAttribute("class", "video-resize");
  224.     resizePoint.style.position = "absolute";
  225.     resizePoint.style.bottom = "-10px"; // 10px outside the box
  226.     resizePoint.style.right = "-10px";
  227.     resizePoint.style.width = "30px";
  228.     resizePoint.style.height = "30px";
  229.     resizePoint.style.zIndex = "1"; // make it layer below the video
  230.     resizePoint.style.cursor = "nwse-resize"; // diagonal <--> arrow thingy
  231.  
  232.     var cover = document.createElement("div"); // covers the iframe. a hack to avoid the iframe from stealng the mousemove event.
  233.     cover.setAttribute("class", "media-cover");
  234.     cover.style.display = "none"; // hidden
  235.     cover.style.backgroundColor = "rgba(0,0,0,0.3)"; // might as well make some use of it. dim the video while we resize it, sure.
  236.  
  237.     cover.style.position = "absolute";
  238.     cover.style.top = "0px";
  239.     cover.style.left = "0px";
  240.  
  241.     cover.style.width = "100%";
  242.     cover.style.height = "100%";
  243.  
  244.     cover.style.zIndex = "3"; // above everything
  245.  
  246.     resizePoint.onmousedown = function(event) { // when clicking down to drag
  247.         if(resize.dragging === true) return; // return if already resizing
  248.  
  249.         cover.style.display = "block"; // unhide the cover
  250.         element.style.background = "#f00"; // red outline to show that we're resizing
  251.  
  252.         resize.element = element; // create a reference to our resize element
  253.  
  254.         resize.startX = event.clientX; //store starting resize positions
  255.         resize.startY = event.clientY;
  256.  
  257.         resize.original.x = parseInt(resize.element.style.width.slice(0, -2)); // remove "px" from the size
  258.         resize.original.y = parseInt(resize.element.style.height.slice(0, -2));
  259.  
  260.         resize.dragging = true;
  261.  
  262.         document.body.style.overflow = "hidden"; // prevents scrolling
  263.  
  264.         window.onmouseup = function() {
  265.             window.onmouseup = null; // kill the events
  266.             window.onmousemove = null;
  267.  
  268.             resize.dragging = false;
  269.             cover.style.display = "none"; // hide stuff
  270.             element.style.background = "none";
  271.             document.body.style.overflow = "auto";
  272.  
  273.             localStorage.videoSize = JSON.stringify(videoSize); // store new video size
  274.         };
  275.  
  276.         window.onmousemove = function(event) { // when moving whilst resizing
  277.             var x = resize.original.x + (event.clientX - resize.startX), // get position
  278.                 y = resize.original.y + (event.clientY - resize.startY);
  279.  
  280.             if(x < 320 || y < 180) {
  281.                 x = 320; // minimum size of 320x180
  282.                 y = 180;
  283.             }
  284.  
  285.             if(x >= y) y = x * 0.5625; // scale to 16:9 aspect ratio
  286.             else x = y * 0.5625;
  287.  
  288.             videoSize.width = x; // store width & height
  289.             videoSize.height = y;
  290.  
  291.             resize.element.style.width = x + "px"; // set size
  292.             resize.element.style.height = y + "px";
  293.         };
  294.     };
  295.  
  296.     element.appendChild(resizePoint); // append elements
  297.     element.appendChild(cover);
  298. }
  299.  
  300. function convertTime(timeString) { // Credit to Foxscotch/Night Fox for this regex match to convert minute and second time to second format. eg. 2m35s to 155.
  301.     let result = timeString.match(/(?:(\d+)h)?(?:(\d+)m)?(?:(\d+)s)?/),
  302.         seconds = (result[3] ? parseInt(result[3]) : 0);
  303.  
  304.     if(result[2]) seconds += parseInt(result[2]) * 60; // Add any minutes.
  305.     if(result[1]) seconds += parseInt(result[1]) * 60 * 60; // Add any hours.
  306.  
  307.     return seconds || 0;
  308. }
  309.  
  310. /*
  311. Changelog:
  312. 1.0   - Initial release
  313. 1.1   - Soundcloud support
  314. 2.0   - Remake
  315. 2.1   - Vocaroo support
  316. 2.2   - Imgur album support
  317. 3.0   - Removed jQuery dependancy
  318. 3.1   - Starts YouTube videos at a certain time when specified.
  319. 3.2   - YouTube start times fix, gifv, mp4, and webm support.
  320. 3.2.1 - SSL support.
  321. 3.2.2 - SSL support for Imgur embedding.
  322. 3.2.3 - Bugfix
  323. 3.2.4 - Recognizes #t= as the start time.
  324. 3.3   - Audio support, Vocaroo dropped until https, optimizations.
  325. 3.3.1 - Bugfix
  326. 3.3.2 - Imgur album support dropped. It was broken and it's much nicer using the site anyway.
  327. 3.4   - Added the ability to resize videos and added support for more media formats.
  328. 3.5   - Added vid.me support.
  329. */
Advertisement
Add Comment
Please, Sign In to add comment