// ==UserScript== // @name Volume & Speed Slider BB Collaborate // @namespace thihxm // @match *://*.bbcollab.com/collab/ui/session/* // @match *://*.bbcollab.com/guest/* // @downloadURL https://gist.githubusercontent.com/thihxm/d29042cdeb01fa68a09ead18d01f397f/raw/VolumeSliderBBCollab.js // @run-at document-idle // @grant none // @version 2.0.3 // @author thihxm // @description Adiciona um slider de volume nas aulas ao vivo do BlackBoard Collaborate e um controle de velocidade nas gravações // ==/UserScript== (function() { 'use strict'; const head = document.querySelector('head'); const body = document.querySelector('body'); const style = document.createElement('style'); style.type = 'text/css'; const css = '#custom-bbcollab-volume-slider-wrapper {'+ 'position: relative;'+ '}'+ '#custom-bbcollab-volume-slider-value {'+ 'position: absolute;'+ 'top: -150%;'+ 'opacity: 0;'+ 'transition: opacity 0.2s linear;'+ '}'+ '#custom-bbcollab-volume-slider-value span {'+ 'width: 30px;'+ 'height: 24px;'+ 'line-height: 24px;'+ 'text-align: center;'+ 'background: #0575ff;'+ 'color: #fff;'+ 'font-size: 12px;'+ 'display: block;'+ 'position: absolute;'+ 'left: 50%;'+ 'transform: translate(-50%, 0);'+ 'border-radius: 6px;'+ '}'+ '#custom-bbcollab-volume-slider-value span:before {'+ 'content: "";'+ 'position: absolute;'+ 'width: 0;'+ 'height: 0;'+ 'border-top: 10px solid #0575ff;'+ 'border-left: 5px solid transparent;'+ 'border-right: 5px solid transparent;'+ 'top: 100%;'+ 'left: 50%;'+ 'margin-left: -5px;'+ 'margin-top: -1px;'+ '}'+ '#custom-bbcollab-speed-changer {'+ 'position: relative;'+ '}'+ '#custom-bbcollab-speed-slider-wrapper {'+ 'position: absolute;'+ 'z-index: 10;'+ 'visibility: visible;'+ 'border: 1px solid #cdcdcd;'+ 'border-radius: .125rem;'+ 'background-color: #fff;'+ 'font-size: .875rem;'+ 'box-shadow: 0 0 0 4px rgba(38,38,38,.075);'+ 'padding: 0;'+ 'display: flex;'+ 'flex-direction: row;'+ 'align-items: center;'+ 'height: 1.875rem;'+ 'width: 8.875rem;'+ 'margin-top: -2rem;'+ 'color: #262626;'+ 'outline: none!important;'+ 'top: calc(50% - 8.875rem / 2);'+ 'left: calc(50% - 8.875rem / 2);'+ 'transform: rotate(-90deg);'+ '}'+ '#custom-bbcollab-speed-slider-wrapper.isHidden {'+ 'visibility: hidden;'+ 'display: none;'+ '}'+ '#custom-bbcollab-speed-slider {'+ 'transform: translateX(-50%);'+ 'left: 50%;'+ 'position: relative;'+ '}'+ '#custom-bbcollab-speed-slider-value {'+ 'position: absolute;'+ 'top: 150%;'+ 'opacity: 0;'+ 'transition: opacity 0.2s linear;'+ '}'+ '#custom-bbcollab-speed-slider-value span {'+ 'width: 40px;'+ 'height: 24px;'+ 'line-height: 24px;'+ 'text-align: center;'+ 'background: #0575ff;'+ 'color: #fff;'+ 'font-size: 12px;'+ 'display: block;'+ 'position: absolute;'+ 'left: 50%;'+ 'transform: translate(-50%, 0) rotate(90deg);'+ 'border-radius: 6px;'+ '}'+ '#custom-bbcollab-speed-slider-value span:before {'+ 'content: "";'+ 'position: absolute;'+ 'width: 0;'+ 'height: 0;'+ 'border-top: 10px solid #0575ff;'+ 'border-left: 5px solid transparent;'+ 'border-right: 5px solid transparent;'+ 'top: 50%;'+ 'right: 100%;'+ 'margin-right: -1px;'+ 'margin-top: -5px;'+ 'transform: rotate(90deg);'+ '}'; style.appendChild(document.createTextNode(css)); head.appendChild(style); const waitForEl = (selector, callback) => { const element = document.querySelector(selector); if (element) { callback(element); } else { setTimeout(function() { waitForEl(selector, callback); }, 100); } }; const changeVolume = (volume) => { document.querySelectorAll('audio').forEach(audioEl => { audioEl.volume = volume; }); document.querySelectorAll('video').forEach(videoEl => { videoEl.volume = volume; }); } const handleVolumeChange = (volumeSlider, volumeValueDisplay) => { volumeSlider.addEventListener('input', e => { const slider = e.target; const sliderValue = e.target.value; const newValue = Number( (sliderValue - slider.min) * 100 / (slider.max - slider.min) ); const newPosition = 10 - (newValue * 0.2); volumeValueDisplay.innerHTML = `${Math.floor(sliderValue * 100)}`; volumeValueDisplay.style.left = `calc(${newValue}% + (${newPosition}px))`; localStorage.setItem('thihxm/bb_volume', sliderValue * 100); changeVolume(sliderValue); }); } const toggleVolumeTooltipEvents = (volumeSlider, volumeValueDisplay) => { volumeSlider.addEventListener('mouseup', e => { volumeValueDisplay.style.opacity = 0; }); volumeSlider.addEventListener('mousedown', e => { volumeValueDisplay.style.opacity = 1; }); } if (body) { if (window.location.pathname.includes("playback")) { const playback_volume_slider_selector = '.playback-controls .playback-controls__volume-slider'; waitForEl(playback_volume_slider_selector, playback_volume_slider => { const speedChangerWrapper = document.createElement('div'); const speedSliderButton = document.createElement('button'); const speedSliderWrapper = document.createElement('div'); const speedSlider = document.createElement('input'); const speedValueDisplay = document.createElement('div'); const buttonIcon = document.createElement('bb-svg-icon'); const buttonTooltip = document.createElement('span'); const buttonTooltipContent = document.createElement('span'); buttonIcon.classList.add('playback-controls__icon'); buttonIcon.innerHTML = ''; buttonTooltip.classList.add('tooltip'); buttonTooltip.classList.add('tip-top-right'); buttonTooltip.setAttribute('role', 'tooltip'); buttonTooltipContent.classList.add('tooltip-content'); buttonTooltipContent.innerHTML = 'Velocidade de reprodução'; buttonTooltip.appendChild(buttonTooltipContent); speedChangerWrapper.id = 'custom-bbcollab-speed-changer'; speedSliderButton.id = 'speed-dropdown-toggle'; speedSliderButton.classList.add('playback-controls__button'); speedSliderButton.classList.add('button'); speedSliderButton.classList.add('has-tooltip'); speedSliderButton.appendChild(buttonIcon); speedSliderButton.appendChild(buttonTooltip); speedSliderWrapper.id = 'custom-bbcollab-speed-slider-wrapper'; speedSliderWrapper.classList.add('isHidden'); speedValueDisplay.id = 'custom-bbcollab-speed-slider-value'; speedSlider.id = 'custom-bbcollab-speed-slider'; speedSlider.type = 'range'; speedSlider.min = 0.25; speedSlider.max = 5; speedSlider.step = 0.25; speedSlider.value = 1; document.addEventListener('click', e => { if (speedSliderButton.contains(e.target)) { speedSliderWrapper.classList.toggle('isHidden'); } else if (!speedSliderWrapper.contains(e.target)) { speedSliderWrapper.classList.add('isHidden'); } }); speedSlider.addEventListener('input', e => { const slider = e.target; const sliderValue = e.target.value; const newValue = Number( (sliderValue - slider.min) * 100 / (slider.max - slider.min) ); const newPosition = 12 - (newValue * 0.25); speedValueDisplay.innerHTML = `${sliderValue}x`; speedValueDisplay.style.left = `calc(${newValue}% + (${newPosition}px))`; document.querySelector('video').playbackRate = sliderValue; }); speedSlider.addEventListener('mouseup', e => { speedValueDisplay.style.opacity = 0; }); speedSlider.addEventListener('mousedown', e => { speedValueDisplay.style.opacity = 1; }); speedSliderWrapper.appendChild(speedSlider); speedSliderWrapper.appendChild(speedValueDisplay); speedChangerWrapper.appendChild(speedSliderButton); speedChangerWrapper.appendChild(speedSliderWrapper); playback_volume_slider.parentNode.insertBefore(speedChangerWrapper, playback_volume_slider.nextSibling); }); } else { const volumeSliderWrapper = document.createElement('div'); const volumeSlider = document.createElement('input'); const volumeValueDisplay = document.createElement('div'); const volume = (localStorage.getItem('thihxm/bb_volume')/100) || 1; volumeSliderWrapper.id = 'custom-bbcollab-volume-slider-wrapper'; volumeValueDisplay.id = 'custom-bbcollab-volume-slider-value'; volumeSlider.id = 'custom-bbcollab-volume-slider'; volumeSlider.type = 'range' volumeSlider.min = 0; volumeSlider.max = 1; volumeSlider.step = 0.02; volumeSlider.value = volume; handleVolumeChange(volumeSlider, volumeValueDisplay); toggleVolumeTooltipEvents(volumeSlider, volumeValueDisplay); changeVolume(volume); volumeSliderWrapper.appendChild(volumeValueDisplay); volumeSliderWrapper.appendChild(volumeSlider); const observer = new MutationObserver(function(mutations) { mutations.forEach(function(mutation) { const addedNodes = mutation.addedNodes; addedNodes.forEach(newNode => { const nodeName = newNode.nodeName.toLowerCase(); if (nodeName === 'audio' || nodeName === 'video') { const volumeSlider = document.querySelector('#custom-bbcollab-volume-slider'); console.log('New Audio/Video Element'); newNode.volume = volume; handleVolumeChange(volumeSlider, volumeValueDisplay); toggleVolumeTooltipEvents(volumeSlider, volumeValueDisplay); } }); }); var controlsContainer = document.querySelector('.controls-container'); if (controlsContainer && volumeSliderWrapper.parentNode != controlsContainer) { controlsContainer.appendChild(volumeSliderWrapper); return; } }); const observerConfig = { childList: true, subtree: true, }; document.addEventListener("DOMContentLoaded", () => { const newValue = Number( (volumeSlider.value - volumeSlider.min) * 100 / (volumeSlider.max - volumeSlider.min) ); const newPosition = 10 - (newValue * 0.2); volumeValueDisplay.innerHTML = `${Math.floor(volumeSlider.value * 100)}`; volumeValueDisplay.style.left = `calc(${newValue}% + (${newPosition}px))`; }); observer.observe(body, observerConfig); } } })();