1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
|
// ==UserScript==
// @name YouTube to Invidious video link replacer
// @description Replace video links in the youtube site to their Invidious equivalents
//
// @version 1.1
// @license MIT
// @author Syndamia
//
// @source https://gitlab.com/Syndamia/userscripts/-/blob/main/youtube-invidious-link-replacer.js
// @supportURL https://gitlab.com/Syndamia/userscripts/-/issues
// @homepage https://gitlab.com/Syndamia/userscripts/
// @icon https://upload.wikimedia.org/wikipedia/commons/a/a0/Invidious-logo.svg
//
// @namespace Syndamia
// @match *://www.youtube.com/*
// @run-at document-start
// ==/UserScript==
const invidiousInstance = 'yewtu.be';
// Wait for ytd-app element to appear
const ytdObserver = new MutationObserver(function(mutations) {
/* Detect when ytd-app element is present */
// Thanks https://stackoverflow.com/a/45267350/12036073
if (document.getElementsByTagName('ytd-app').length > 0) {
disableCertainClickEventListeners(); // Refer to function for information
/* When you open a link in YouTube, the site doesn't fully reload, but the ytd-app element
* (which contains the whole UI) is updated (and the website URL also updates).
* Also, YouTube's infinite scroll updates the ytd-app element, so the best way to detect
* when we need to fix links is when ytd-app changes.
*/
const observer = new MutationObserver(replaceAnchors);
observer.observe(document.getElementsByTagName('ytd-app')[0], { childList: true, attributes: true, subtree: true, });
ytdObserver.disconnect();
}
});
ytdObserver.observe(document, {attributes: false, childList: true, characterData: false, subtree:true});
function replaceAnchors() {
for (var anchor of document.getElementsByTagName('ytd-app')[0].getElementsByTagName('a')) {
if (anchor.href.indexOf('www.youtube.com/watch') > 0) {
anchor.href = anchor.href.replace('www.youtube.com/watch', invidiousInstance + '/watch');
}
}
}
/* As already meantioned, opening a link in YouTube doesn't work like clicking on a normal anchor,
* it updates the ytd-app element and website URL. When clicking on a video, a special eventListener(s)
* handles loading the YouTube video page and if we don't disable it(them), even with anchors that href to
* a page outside YouTube, we'll still load the YouTube video as normal.
*/
function disableCertainClickEventListeners() {
/* It's not enough to only override the HTMLAnchorElement addEventListener function,
* from testing it seems that there are other elements that also have the appropriate event listeners
* which trigger opening of the YouTube player
*/
// Thanks https://stackoverflow.com/a/57437878/12036073
HTMLElement.prototype.oldaddEventListener = HTMLElement.prototype.addEventListener;
HTMLElement.prototype.addEventListener = function(event, handler, placeholder) {
if (event === 'click') {
/* The functions that actually handles clicking on videos to open player is this:
* (c){if(a[b])a[b](c,c.detail);else console.warn("listener method `"+b+"` not defined")}
* As far as I have tested, '_handleNative$$module$third_party$javascript$polymer$v2$polymer$lib$utils$gestures' and functions like:
* (a){a.target===this.liveBadge.element&&(this.api.seekTo(Infinity),this.api.playVideo())}
* don't play a direct role in the click video -> open player process.
*/
if (handler.toString().indexOf('c', 7) === 9 && this.tagName !== 'YT-ICON-BUTTON') { // The second condition allows some buttons to work
return;
}
}
this.oldaddEventListener(event, handler, placeholder);
}
}
|