您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Search YouTube without interrupting the video, by loading the search results in the related video bar
当前为
// ==UserScript== // @name Youtube - Search While Watching Video // @version 1.0.0 // @description Search YouTube without interrupting the video, by loading the search results in the related video bar // @author Cpt_mathix // @include https://www.youtube.com* // @license GPL version 2 or any later version; http://www.gnu.org/licenses/gpl-2.0.txt // @require https://cdnjs.cloudflare.com/ajax/libs/JavaScript-autoComplete/1.0.4/auto-complete.min.js // @namespace https://gf.qytechs.cn/users/16080 // @grant none // @noframes // ==/UserScript== (function() { var script = { ytplayer: null, search_timeout: null, search_suggestions: [], debug: false }; // callback function for search results window.search_callback = search_callback; // youtube search parameters const GeoLocation = window.yt.config_.INNERTUBE_CONTEXT_GL; const HostLanguage = window.yt.config_.INNERTUBE_CONTEXT_HL; // reload script on page change using youtube spf events (http://youtube.github.io/js/documentation/events/) window.addEventListener("spfdone", function(e) { if (script.debug) { console.log("new page loaded"); } clearSearchRequests(); if (isPlayerAvailable()) { startScript(2); } }); main(); function main() { injectCSS(); if (isPlayerAvailable()) { if (script.debug) { console.log("player available"); } startScript(5); } else { if (script.debug) { console.log("player unavailable"); } } } function startScript(retry) { script.ytplayer = getVideoPlayer(); if (script.debug) { console.log("ytplayer: ", script.ytplayer); } if (script.ytplayer) { if (script.debug) { console.log("initializing search"); } initSearch(); } else if (retry > 0) { // fix conflict with Youtube+ script setTimeout( function() { startScript(retry--); }.bind(retry), 1000); } } // *** VIDEO & PLAYER *** // // video object function ytVideo(title, id, html, anchor, author, time, stats, thumb) { this.title = title; this.id = id; this.html = html; this.buttonAnchor = anchor; this.author = author; this.time = time; this.stats = stats; this.iurlhq = thumb; this.iurlmq = thumb; } function getVideoPlayer() { return document.getElementById('movie_player'); } function isPlayerAvailable() { // available on video pages without playlist or live chat return /https:\/\/www\.youtube\.com\/watch\?v=.*/.test(document.location.href) && !getVideoInfoFromUrl(document.location.href, "list") && document.getElementById('live-chat-iframe') === null; } function getVideoInfoFromUrl(url, info) { if (url.indexOf("?") === -1) { return null; } var urlVariables = url.split("?")[1].split("&"), varName; for (var i = 0; i < urlVariables.length; i++) { varName = urlVariables[i].split("="); if (varName[0] === info) { return varName[1] === undefined ? null : varName[1]; } } } // *** SEARCH *** // // initialize search function initSearch() { if (!document.getElementById('masthead-queue-search')) { var anchor = document.querySelector('#watch7-sidebar-modules > div:nth-child(2)'); var html = "<input id=\"masthead-queue-search\" class=\"search-term yt-uix-form-input-bidi\" type=\"text\" placeholder=\"Search\">"; anchor.insertAdjacentHTML("afterbegin", html); var input = document.getElementById('masthead-queue-search'); // suggestion dropdown init new autoComplete({ selector: '#masthead-queue-search', minChars: 1, delay: 250, source: function(term, suggest) { suggest(script.search_suggestions); }, onSelect: function(event, term, item) { sendSearchRequest(term); } }); input.addEventListener("keydown", function(event) { const ENTER = 13; const BACKSPACE = 8; if (this.value !== "" && event.keyCode === ENTER) { sendSearchRequest(this.value); } else if (this.value !== "" && event.keyCode === BACKSPACE) { searchSuggestions(this.value); } else { searchSuggestions(this.value + event.key); } }); input.addEventListener("click", function(event) { this.select(); }); } } // callback from search suggestions attached to window function search_callback(data) { var raw = data[1]; // extract relevant data from json script.search_suggestions = raw.map(function(array) { return array[0]; // change 2D array to 1D array with only suggestions }); } // get search suggestions function searchSuggestions(value) { if (script.search_timeout !== null) { clearTimeout(script.search_timeout); } // only allow 1 search request every 100 milliseconds script.search_timeout = setTimeout( function() { if (script.debug) { console.log("search request send"); } var scriptElement = document.createElement("script"); scriptElement.type = "text/javascript"; scriptElement.className = "search-request"; scriptElement.src = "https://clients1.google.com/complete/search?client=youtube&hl=" + HostLanguage + "&gl=" + GeoLocation + "&gs_ri=youtube&ds=yt&q=" + encodeURIComponent(value) + "&callback=search_callback"; document.head.appendChild(scriptElement); }.bind(value), 100); } // send search request function sendSearchRequest(value) { if (script.debug) { console.log("searching for " + value); } document.getElementById('masthead-queue-search').blur(); // close search suggestions dropdown var nextPage = document.getElementById('watch-more-related-button'); if (nextPage !== null) { nextPage.remove(); } // removing the "More Suggestions" link script.search_suggestions = []; // clearing the search suggestions var xmlHttp = new XMLHttpRequest(); xmlHttp.onreadystatechange = function() { if (xmlHttp.readyState == 4 && xmlHttp.status == 200) { var container = document.implementation.createHTMLDocument().documentElement; container.innerHTML = xmlHttp.responseText; processSearch(container); } }; xmlHttp.open("GET", "https://www.youtube.com/results?q=" + encodeURIComponent(value), true); // true for asynchronous xmlHttp.send(null); } function clearSearchRequests() { var requests = document.getElementsByClassName('search-request'); if (requests) { for (var i = requests.length - 1; i >= 0; i--) { requests[i].remove(); } } } // process search request function processSearch(value) { var videoList = value.getElementsByClassName('item-section')[0]; // remove current videos (and replace with searched videos later) var ul = document.getElementById('watch-related'); var li = ul.querySelectorAll('li.video-list-item'); if (li) { for (var i = li.length - 1; i >= 0; i--) { li[i].remove(); } } // insert searched videos var videos = videoList.querySelectorAll('.yt-lockup-video'); for (var j = videos.length - 1; j >= 0; j--) { var video = videos[j]; if (video.querySelector('.yt-badge-live') === null) { try { var videoId = video.dataset.contextItemId; var videoTitle = video.querySelector('.yt-lockup-title > a').title; var videoStats = video.querySelector('.yt-lockup-meta').innerHTML; var videoTime = video.querySelector('.video-time') ? video.querySelector('.video-time').textContent : "0"; var author = video.querySelector('.yt-lockup-byline') ? video.querySelector('.yt-lockup-byline').textContent : ""; var videoThumb = video.querySelector('div.yt-lockup-thumbnail img').dataset.thumb || video.querySelector('div.yt-lockup-thumbnail img').src; var videoObject = new ytVideo(videoTitle, videoId, null, null, author, videoTime, videoStats, videoThumb); if (script.debug) { console.log(videoObject); } ul.insertAdjacentHTML("afterbegin", videoQueueHTML(videoObject).html); } catch (error) { console.error("failed to process video " + error.message, video); } } } } // *** HTML & CSS *** // function videoQueueHTML(video) { var strVar=""; strVar += "<li class=\"video-list-item related-list-item show-video-time related-list-item-compact-video\">"; strVar += " <div class=\"related-item-dismissable\">"; strVar += " <div class=\"content-wrapper\">"; strVar += " <a href=\"\/watch?v=" + video.id + "\" class=\"yt-uix-sessionlink content-link spf-link spf-link\" rel=\"spf-prefetch\" title=\"" + video.title + "\">"; strVar += " <span dir=\"ltr\" class=\"title\">" + video.title + "<\/span>"; strVar += " <span class=\"stat author\">" + video.author + "<\/span>"; strVar += " <div class=\"yt-lockup-meta stat\">" + video.stats + "<\/div>"; strVar += " <\/a>"; strVar += " <\/div>"; strVar += " <div class=\"thumb-wrapper\">"; strVar += " <a href=\"\/watch?v=" + video.id + "\" class=\"yt-uix-sessionlink thumb-link spf-link spf-link\" rel=\"spf-prefetch\" tabindex=\"-1\" aria-hidden=\"true\">"; strVar += " <span class=\"yt-uix-simple-thumb-wrap yt-uix-simple-thumb-related\" tabindex=\"0\" data-vid=\"" + video.id + "\">"; strVar += " <img aria-hidden=\"true\" alt=\"\" src=\"" + video.iurlhq + "\">"; strVar += " <\/span>"; strVar += " <\/a>"; strVar += " <span class=\"video-time\">"+ video.time +"<\/span>"; strVar += " <button class=\"yt-uix-button yt-uix-button-size-small yt-uix-button-default yt-uix-button-empty yt-uix-button-has-icon no-icon-markup addto-button video-actions spf-nolink hide-until-delayloaded addto-watch-later-button yt-uix-tooltip\" type=\"button\" onclick=\";return false;\" title=\"Watch Later\" role=\"button\" data-video-ids=\"" + video.id + "\" data-tooltip-text=\"Watch Later\"><\/button>"; strVar += " <\/div>"; strVar += " <\/div>"; strVar += "<\/li>"; video.html = strVar; return video; } // injecting css function injectCSS() { var css = ` .autocomplete-suggestions { text-align: left; cursor: default; border: 1px solid #ccc; border-top: 0; background: #fff; box-shadow: -1px 1px 3px rgba(0,0,0,.1); position: absolute; display: none; z-index: 9999; max-height: 254px; overflow: hidden; overflow-y: auto; box-sizing: border-box; } .autocomplete-suggestion { position: relative; padding: 0 .6em; line-height: 23px; white-space: nowrap; overflow: hidden; text-overflow: ellipsis; font-size: 1.02em; color: #333; } .autocomplete-suggestion b { font-weight: normal; color: #b31217; } .autocomplete-suggestion.selected { background: #f0f0f0; } .yt-uix-simple-thumb-wrap > img { top: 0px; width: 168px; height: 94px; } #masthead-queue-search { outline: none; width: 95%; padding: 5px 5px; margin: 0 4px; } `; var style = document.createElement("style"); style.type = "text/css"; if (style.styleSheet){ style.styleSheet.cssText = css; } else { style.appendChild(document.createTextNode(css)); } document.documentElement.appendChild(style); } })();
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址