(function() { // Declare variables let slugInputTag, ytThumbImgMenu, ytEnhancerMenu; // Menu systems let ytThumbnailBttn, ytMaxDefaultImg, ytHqDefaultImg, // Buttons & Images ytLoopBttn, ytFloatBttn, ytAMaxDefaultImg, ytAHqDefaultImg; let mastHead, mainContentArea, playerWindow; // Youtube Player container let video, containerOfPlyrWndow, poppedContainer; // Video accessor let part, videoSlug, temp; // Image part let videoTimeLength, videoTimeCurent, ytRangeStart, ytRangeEnd, ytdVideoIntervalLoop; let loopingInterval = false; let count = 0; let OSName = ""; // Options for the observer (which mutations to observe) const config = { attributes: true }; const preSetupProc = () => { if (navigator.appVersion.indexOf("Win")!=-1) OSName = "Windows"; if (navigator.appVersion.indexOf("Mac")!=-1) OSName = "MacOS"; if (navigator.appVersion.indexOf("X11")!=-1) OSName = "UNIX"; if (navigator.appVersion.indexOf("Linux")!=-1) OSName ="Linux"; video = document.getElementsByTagName("video")[0]; // Video Controler slugInputTag = document.createElement("INPUT"); ytRangeEnd = document.createElement("INPUT"); slugInputTag.id = "slugCopyZone"; ytRangeEnd.id = "rangeEndID"; slugInputTag.type = "text"; ytRangeEnd.type = "text"; // We need to wait for info to load before getting full duration setTimeout(function () { videoTimeLength = document.getElementsByClassName("ytp-time-duration")[0].innerHTML; if (!document.getElementById("rangeEndID")) { } else { ytRangeEnd = document.getElementById("rangeEndID"); } ytRangeEnd.value = videoTimeLength; }, 1000); if (!document.getElementById("slugCopyZone")) { document.body.appendChild(slugInputTag); } else { slugInputTag = document.getElementById("slugCopyZone"); } slugInputTag.value = video.baseURI.slice(32, 32+11); } const setupProc = () => { poppedContainer = document.createElement("DIV"); ytThumbImgMenu = document.createElement("DIV"); ytEnhancerMenu = document.createElement("DIV"); ytThumbnailBttn = document.createElement("IMG"); ytDownloadBttn = document.createElement("IMG"); ytLoopBttn = document.createElement("IMG"); ytFloatBttn = document.createElement("IMG"); ytMaxDefaultImg = document.createElement("IMG"); ytHqDefaultImg = document.createElement("IMG"); ytMqDefaultImg = document.createElement("IMG"); ytSdDefaultImg = document.createElement("IMG"); ytAMaxDefaultImg = document.createElement("A"); ytAHqDefaultImg = document.createElement("A"); ytAMedDefaultImg = document.createElement("A"); ytASdDefaultImg = document.createElement("A"); ytIfrm = document.createElement("IFRAME"); // Loop range controls ytRangeSection = document.createElement("SECTION"); ytRangeStart = document.createElement("INPUT"); // Get nodes for page work containerOfPlyrWndow = document.getElementById("player-container"); // Container of actual player - Used for floating window part = "https://img.youtube.com/vi/"; // Append to nodes as required ytThumbnailBttn.title = "Video Thumbnails..."; ytLoopBttn.title = "Start Loop..."; ytFloatBttn.title = "Float Video Container"; ytRangeStart.title = "Loop Range Start"; ytRangeEnd.title = "Loop Range End"; ytRangeStart.type = "text"; ytRangeStart.value = "0:00"; // Insert ytEnhancerMenu.appendChild(ytThumbnailBttn); ytEnhancerMenu.appendChild(ytLoopBttn); ytEnhancerMenu.appendChild(ytRangeSection); ytEnhancerMenu.appendChild(ytFloatBttn); if (OSName.includes("MacOS") || OSName.includes("UNIX") || OSName.includes("Linux")) { console.log("System supports downloader..."); console.log("OS is : " + OSName); ytEnhancerMenu.appendChild(ytDownloadBttn); } ytRangeSection.append(ytRangeStart); ytRangeSection.append(ytRangeEnd); document.body.appendChild(poppedContainer); document.body.appendChild(ytThumbImgMenu); document.body.appendChild(ytEnhancerMenu); ytAMaxDefaultImg.appendChild(ytMaxDefaultImg); ytAHqDefaultImg.appendChild(ytHqDefaultImg); ytAMedDefaultImg.appendChild(ytMqDefaultImg); ytASdDefaultImg.appendChild(ytSdDefaultImg); ytThumbImgMenu.appendChild(ytAMaxDefaultImg); ytThumbImgMenu.appendChild(ytAHqDefaultImg); ytThumbImgMenu.appendChild(ytAMedDefaultImg); ytThumbImgMenu.appendChild(ytASdDefaultImg); poppedContainer.appendChild(ytIfrm); // Set onclick actions ytThumbnailBttn.addEventListener("click", showThumbImageVew); ytLoopBttn.addEventListener("click", setLoop); ytFloatBttn.addEventListener("click", toggleFloat); ytDownloadBttn.addEventListener("click", downloadVideo); video.addEventListener("wheel", manageVolume); // Observer target for fullscreen action... targetNode = document.getElementsByTagName('ytd-app')[0]; // Create an observer instance linked to the callback function const observer = new MutationObserver(mutationcallback); // Start observing the target node for configured mutations observer.observe(targetNode, config); // Dragable window for floating video dragVideo(poppedContainer); ytThumbnailBttn.src = browser.extension.getURL("/icons/thumbnailOff.png"); ytLoopBttn.src = browser.extension.getURL("/icons/loopFalse.png"); ytFloatBttn.src = browser.extension.getURL("/icons/floatPlayer.png"); ytDownloadBttn.src = browser.extension.getURL("/icons/downloadVid.png"); // Set trget of Thumbnails of video ytAMaxDefaultImg.target = "_blank"; ytAHqDefaultImg.target = "_blank"; ytAMedDefaultImg.target = "_blank"; ytASdDefaultImg.target = "_blank"; // Theming & Apply Styles ytThumbImgMenu.className = "ytThumbMenuStyle"; ytMaxDefaultImg.className = "thumbImageStyle"; ytHqDefaultImg.className = "thumbImageStyle"; ytMqDefaultImg.className = "thumbImageStyle"; ytSdDefaultImg.className = "thumbImageStyle"; ytEnhancerMenu.className = "ytMenuStyle"; ytThumbnailBttn.className = "imageStyle"; ytLoopBttn.className = "imageStyle"; ytFloatBttn.className = "imageStyle"; ytDownloadBttn.className = "imageStyle"; ytEnhancerMenu.id = "enhancerMenuIDRef"; poppedContainer.id = "draggable"; ytRangeStart.id = "rangeStartID"; ytRangeEnd.id = "rangeEndID"; poppedContainer.style.display = "none"; ytEnhancerMenu.style.display = "block"; slugInputTag.style.display = "block"; ytIfrm.setAttribute("allow", "accelerometer; autoplay; encrypted-media; gyroscope; picture-in-picture"); ytIfrm.setAttribute("frameborder", "0"); ytIfrm.setAttribute("autoplay", ""); ytIfrm.setAttribute("allowfullscreen", "true"); ytIfrm.setAttribute("width", "650px"); ytIfrm.setAttribute("height", "400px"); } // Functions // Callback function to execute when mutations are observed const mutationcallback = (mutationsList, observer) => { for(let mutation of mutationsList) { if (mutation.type === 'attributes') { controlManager(mutation.target); } } }; const controlManager = (elm) => { attrib = elm.getAttribute('masthead-hidden_'); if (attrib == null) { // if out of fullscreen ytEnhancerMenu.style.display = "block"; slugInputTag.style.display = "block"; } else { // if fullscreen ytEnhancerMenu.style.display = "none"; slugInputTag.style.display = "none"; } } const downloadVideo = () => { browser.runtime.sendMessage( { "url": video.baseURI } ); } const showThumbImageVew = (e) => { videoSlug = video.baseURI.slice(32, 32+11); // Used for setting up thumbnails if (ytThumbImgMenu.style.display == "block") { ytThumbImgMenu.style.display = "none"; ytThumbnailBttn.src = browser.extension.getURL("/icons/thumbnailOff.png"); } else { ytAMaxDefaultImg.href = part + videoSlug + "/maxresdefault.jpg"; ytAHqDefaultImg.href = part + videoSlug + "/hqdefault.jpg"; ytAMedDefaultImg.href = part + videoSlug + "/mqdefault.jpg"; ytASdDefaultImg.href = part + videoSlug + "/sddefault.jpg"; ytMaxDefaultImg.src = part + videoSlug + "/maxresdefault.jpg"; ytHqDefaultImg.src = part + videoSlug + "/hqdefault.jpg"; ytMqDefaultImg.src = part + videoSlug + "/mqdefault.jpg"; ytSdDefaultImg.src = part + videoSlug + "/sddefault.jpg"; ytMaxDefaultImg.title = "Max Resolution Default"; ytHqDefaultImg.title = "High Quality Default"; ytMqDefaultImg.title = "Medium Quality Default"; ytSdDefaultImg.title = "Standard Quality Default"; ytThumbnailBttn.src = browser.extension.getURL("/icons/thumbnailOn.png"); ytThumbImgMenu.style.display = "block"; } return; } const setLoop = (e) => { let start = ytRangeStart.value.trim(); let end = ytRangeEnd.value.trim(); if (loopingInterval) { console.log("Unsetting interval for loop check..."); clearInterval(ytdVideoIntervalLoop); loopingInterval = false; ytLoopBttn.title = "Start Loop..."; ytLoopBttn.src = browser.extension.getURL("/icons/loopFalse.png"); return ; } if (start.includes("0:00") && end.includes(videoTimeLength)) { if (video.loop == false) { console.log("Setting default loop marker..."); video.loop = true; ytLoopBttn.title = "Stop Loop..."; ytLoopBttn.src = browser.extension.getURL("/icons/loopTrue.png"); } else { console.log("Unsetting default loop marker..."); video.loop = false; ytLoopBttn.title = "Start Loop..."; ytLoopBttn.src = browser.extension.getURL("/icons/loopFalse.png"); } return ; } else { const getTotalSize = (array) => { let size = 0.0; let hours = 0.0; let minutes = 0.0; let seconds = 0.0; if (array.length === 2) { minutes = parseFloat(array[0]) * 60.0; seconds = parseFloat(array[1]); size = minutes + seconds; } else if (array.length === 3) { hours = parseFloat(array[0]) * 3600.0; minutes = parseFloat(array[1]) * 60.0; seconds = parseFloat(array[2]); size = hours + minutes + seconds; } return size; } const checkLoopStuff = () => { videoTimeCurent = video.currentTime; if (videoTimeCurent > totalEnd || videoTimeCurent < totalStart) { video.currentTime = totalStart; } } // Make sure start and end are proper let totalStart = getTotalSize(start.split(":")); let totalEnd = getTotalSize(end.split(":")); if (totalStart < 0.0 || totalStart > video.duration) { return ; } if (totalEnd < 0.0 || totalEnd > video.duration) { return ; } // Setup interval check for 1 sec and compare value of current pos to end ytLoopBttn.title = "Stop Loop..."; ytLoopBttn.src = browser.extension.getURL("/icons/loopTrue.png"); loopingInterval = true; console.log("Setting interval for loop check..."); ytdVideoIntervalLoop = setInterval(checkLoopStuff, 1000); } } const toggleFloat = () => { let mainPlayer = document.getElementById("player-container-outer"); var ifrmBody = (ytIfrm.contentWindow || ytIfrm.contentDocument); if (ifrmBody.document) ifrmBody = ifrmBody.document; if (poppedContainer.style.display == "none"){ video.pause(); mainPlayer.style.display = "none"; ytIfrm.src = "https://www.youtube.com/embed/" + video.baseURI.slice(32, 32+11) + "?autoplay=1&start=" + Math.floor(video.currentTime); poppedContainer.style.display = "block"; } else { video.currentTime = ifrmBody.getElementsByTagName("video")[0].currentTime; poppedContainer.style.display = "none"; mainPlayer.style.display = ""; ytIfrm.src = ""; video.play(); } } const setVideoStyle = (w, h, pr) => { let elm = document.getElementsByClassName("ytp-right-controls")[0]; video.style.width = w; video.style.height = h; elm.style.paddingRight = pr; console.log("W: " + w + "\nH: " + h + "\npr: " + pr); console.log(video.style); } const manageVolume = (e) => { let delta; e.preventDefault(); // Keep page from scrolling while in video area // Detect scroll direction if (e.wheelDelta) delta = e.wheelDelta; else delta = -1 * e.deltaY; // Vol UP || Vol DOWN if (delta > 0) video.volume += 0.05; else if (delta < 0) video.volume -= 0.05; } const dragVideo = (elmnt) => { let pos1 = 0, pos2 = 0, pos3 = 0, pos4 = 0; elmnt.onmousedown = dragMouseDown; function dragMouseDown(e) { e = e || window.event; pauseEvent(e); // get the mouse cursor position at startup: pos3 = e.clientX; pos4 = e.clientY; document.onmouseup = closeDragElement; // call a function whenever the cursor moves: document.onmousemove = elementDrag; } const elementDrag = (e) => { e = e || window.event; pauseEvent(e); // calculate the new cursor position: pos1 = pos3 - e.clientX; pos2 = pos4 - e.clientY; pos3 = e.clientX; pos4 = e.clientY; // set the element's new position: elmnt.style.top = (elmnt.offsetTop - pos2) + "px"; elmnt.style.left = (elmnt.offsetLeft - pos1) + "px"; } const closeDragElement = (e) => { // stop moving when mouse button is released: document.onmouseup = null; document.onmousemove = null; } const pauseEvent = (e) => { if(e.stopPropagation) e.stopPropagation(); if(e.preventDefault) e.preventDefault(); e.cancelBubble = true; e.returnValue = false; return false; } } const checkPg = () => { if (!document.getElementById("enhancerMenuIDRef")) { let existCondition = setInterval(function() { if (document.getElementById("masthead-container")) { clearInterval(existCondition); preSetupProc(); setupProc(); count = 0; } else { if (count == 12) { // ~ 6 sec through half sec loops count = 0; clearInterval(existCondition); } else { count++; } } }, 500); // check every 500ms } else { preSetupProc(); } } // Start init checkPg(); }());