// ==UserScript== // @name Youtube Music Genius Lyrics // @description Show lyrics/songtexts from genius.com on Youtube music next to music videos // @license GPL-3.0-or-later; http://www.gnu.org/licenses/gpl-3.0.txt // @copyright 2020, cuzi (https://github.com/cvzi) // @author cuzi // @supportURL https://github.com/cvzi/Youtube-Music-Genius-Lyrics-userscript/issues // @version 1 // @require https://greasyfork.org/scripts/406698-geniuslyrics/code/GeniusLyrics.js?version=825578 // @grant GM.xmlHttpRequest // @grant GM.setValue // @grant GM.getValue // @grant unsafeWindow // @connect genius.com // @include https://music.youtube.com/* // @namespace https://greasyfork.org/users/20068 // @downloadURL none // ==/UserScript== /* global GM, genius, unsafeWindow, geniusLyrics */ // eslint-disable-line no-unused-vars 'use strict' var lyricsWidth = '40%' function addCss () { // Spotify document.head.appendChild(document.createElement('style')).innerHTML = ` #lyricscontainer { position:fixed; right:0px; margin:0px; padding:0px; background:#000; color:#fff; z-index:101; font-size:1.4rem; border:none; border-radius:none; } .lyricsiframe { opacity:0.1; transition:opacity 2s; margin:0px; padding:0px; } .lyricsnavbar { font-size : 0.7em; text-align:right; padding-right:10px; background:#212121; } .lyricsnavbar span,.lyricsnavbar a:link,.lyricsnavbar a:visited { color:#d5d5d5; text-decoration:none; transition:color 400ms; } .lyricsnavbar a:hover,.lyricsnavbar span:hover { color:#fff; text-decoration:none; } .loadingspinner { color:white; font-size:1em; line-height:2.5em; } .loadingspinnerholder { z-index:101; background-color:transparent; position:absolute; top:120px; right:100px; cursor:progress } .lorem {padding:10px 0px 0px 15px; font-size: 1.4rem;line-height: 2.2rem;letter-spacing: 0.3rem;} .lorem .white {background:black;color:black} .lorem .gray {background:#7f7f7f;color:#7f7f7f} #lyricscontainer.geniusSearch { background:#212121; } #lyricscontainer.geniusSearch a:link, #lyricscontainer.geniusSearch a:visited{ color:#909090; transition:color 300ms; text-decoration:none; font-size:16px } #lyricscontainer.geniusSearch a:hover{ color:white; } .geniussearchinput { background-color:#212121; color:white; border:1px solid #333; font-size:17px; padding:7px; min-width: 60%; } ` } function calcContainerWidthTop () { const playerPage = document.querySelector('ytmusic-player-page#player-page') const bar = document.querySelector('#lyricscontainer .lyricsnavbar') const dim = playerPage.getBoundingClientRect() const left = dim.left + dim.width const top = dim.top - (bar ? bar.getBoundingClientRect().height : 11) return [left, top] } function setFrameDimensions (container, iframe) { const bar = container.querySelector('.lyricsnavbar') const ytmusicPlayerBarDim = document.querySelector('ytmusic-player-bar').getBoundingClientRect() const progressContainer = document.getElementById('progressContainer') const width = iframe.style.width = container.clientWidth - 1 + 'px' const height = iframe.style.height = window.innerHeight - 2 - (bar ? bar.getBoundingClientRect().height : 11) - container.getBoundingClientRect().top - (progressContainer ? progressContainer.getBoundingClientRect().height : 3) - ytmusicPlayerBarDim.height + 'px' if (genius.option.themeKey === 'spotify') { iframe.style.backgroundColor = 'black' } else { iframe.style.backgroundColor = '' } return [width, height] } function onResize () { window.setTimeout(function () { genius.option.resizeOnNextRun = true }, 200) } function resize () { const container = document.getElementById('lyricscontainer') const iframe = document.getElementById('lyricsiframe') if (!container) { return } const [left, top] = calcContainerWidthTop() container.style.top = top + 'px' container.style.left = left + 'px' if (iframe) { setFrameDimensions(container, iframe) } } function getCleanLyricsContainer () { let container const playerPage = document.querySelector('ytmusic-player-page#player-page') const playerPageDiv = playerPage.querySelector('.ytmusic-player-page') playerPage.style.width = `calc(100% - ${lyricsWidth})` playerPageDiv.dataset.paddingRight = window.getComputedStyle(playerPageDiv).paddingRight playerPageDiv.style.paddingRight = '0px' const [left, top] = calcContainerWidthTop() if (!document.getElementById('lyricscontainer')) { container = document.createElement('div') container.id = 'lyricscontainer' document.body.appendChild(container) } else { container = document.getElementById('lyricscontainer') container.innerHTML = '' } container.style = '' container.style.top = top + 'px' container.style.left = left + 'px' container.className = '' return document.getElementById('lyricscontainer') } function hideLyrics () { document.querySelectorAll('.loadingspinner').forEach((spinner) => spinner.remove()) if (document.getElementById('lyricscontainer')) { document.getElementById('lyricscontainer').remove() } const playerPage = document.querySelector('ytmusic-player-page#player-page') const playerPageDiv = playerPage.querySelector('.ytmusic-player-page') playerPage.style.width = '' playerPageDiv.style.paddingRight = playerPageDiv.dataset.paddingRight addLyricsButton() } var checkFullscreenIV function addLyricsButton () { if (document.getElementById('showlyricsbutton')) { return } const top = calcContainerWidthTop()[1] const b = document.createElement('div') b.setAttribute('id', 'showlyricsbutton') b.setAttribute('style', 'position:absolute;top:' + (top + 2) + 'px;right:0px;color:#ffff64;cursor:pointer;background:black;border-radius:50%;margin:auto;text-align:center;font-size:15px;line-height:15px;') b.setAttribute('title', 'Load lyrics from genius.com') b.appendChild(document.createTextNode('🅖')) b.addEventListener('click', function onShowLyricsButtonClick () { genius.option.autoShow = true // Temporarily enable showing lyrics automatically on song change genius.iv.main = window.setInterval(main, 2000) addLyrics(true) }) document.body.appendChild(b) window.clearInterval(checkFullscreenIV) checkFullscreenIV = window.setInterval(function () { if (document.getElementById('showlyricsbutton')) { document.getElementById('showlyricsbutton').style.display = document.fullscreenElement ? 'none' : 'block' } }, 1000) } var lastSong = null function addLyrics (force, beLessSpecific) { const titleNode = document.querySelector('.ytmusic-player-bar .title.ytmusic-player-bar') const artistNodes = document.querySelectorAll('.ytmusic-player-bar.subtitle a[href*="channel/"]') if (!titleNode || !titleNode.textContent || artistNodes.length === 0) { // No song is playing lastSong = null hideLyrics() return } let songTitle = titleNode.textContent const songArtistsArr = Array.from(artistNodes).map(e => e.textContent) const song = songArtistsArr.join(', ') + ' - ' + songTitle + '#' + genius.option.themeKey + '@' + lyricsWidth if (lastSong === song && document.getElementById('lyricscontainer')) { // Same video id and same theme and lyrics are showing -> stop here return } else { lastSong = song } songTitle = songTitle.replace('"', '').replace('[', '').replace(']', '').replace('(', '').replace(')', '').replace('|', '') songTitle = songTitle.replace(/\W+$/, '') songTitle = songTitle.replace(/^\W+/, '') songTitle = songTitle.trim() let feat = songTitle.indexOf(' feat') if (feat !== -1) { songTitle = songTitle.substring(0, feat).trim() } feat = songTitle.indexOf(' ft') if (feat !== -1) { songTitle = songTitle.substring(0, feat).trim() } const musicIsPlaying = document.querySelector('#play-pause-button #icon svg g path') && document.querySelector('#play-pause-button #icon svg g path').getAttribute('d').startsWith('M6') genius.f.loadLyrics(force, beLessSpecific, songTitle, songArtistsArr, musicIsPlaying) } function showSearchField (query) { const b = getCleanLyricsContainer() b.style.border = '1px solid black' b.style.borderRadius = '3px' b.style.padding = '5px' b.appendChild(document.createTextNode('Search genius.com: ')) b.style.paddingRight = '15px' const input = b.appendChild(document.createElement('input')) input.className = 'geniussearchinput' input.placeholder = 'Search genius.com...' const span = b.appendChild(document.createElement('span')) span.style = 'cursor:pointer' span.appendChild(document.createTextNode(' \uD83D\uDD0D')) if (query) { input.value = query } else if (genius.current.artists) { input.value = genius.current.artists } input.addEventListener('change', function onSearchLyricsButtonClick () { if (input.value) { genius.f.searchByQuery(input.value, b) } }) input.addEventListener('keyup', function onSearchLyricsKeyUp (ev) { if (ev.keyCode === 13) { ev.preventDefault() if (input.value) { genius.f.searchByQuery(input.value, b) } } }) span.addEventListener('click', function onSearchLyricsKeyUp (ev) { if (input.value) { genius.f.searchByQuery(input.value, b) } }) document.body.appendChild(b) input.focus() } function listSongs (hits, container, query) { if (!container) { container = getCleanLyricsContainer() } container.classList.add('geniusSearch') // Back to search button const backToSearchButton = document.createElement('a') backToSearchButton.href = '#' backToSearchButton.appendChild(document.createTextNode('Back to search')) backToSearchButton.addEventListener('click', function backToSearchButtonClick (ev) { ev.preventDefault() if (query) { showSearchField(query) } else if (genius.current.artists) { showSearchField(genius.current.artists + ' ' + genius.current.title) } else { showSearchField() } }) const separator = document.createElement('span') separator.setAttribute('class', 'second-line-separator') separator.setAttribute('style', 'padding:0px 3px') separator.appendChild(document.createTextNode('•')) // Hide button const hideButton = document.createElement('a') hideButton.href = '#' hideButton.appendChild(document.createTextNode('Hide')) hideButton.addEventListener('click', function hideButtonClick (ev) { ev.preventDefault() hideLyrics() }) // List search results const trackhtml = '