-
Notifications
You must be signed in to change notification settings - Fork 3
/
revised-35760-yt-url-at-time.user.js
181 lines (159 loc) · 5.2 KB
/
revised-35760-yt-url-at-time.user.js
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
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
// ==UserScript==
// @name yt-url-at-time
// @namespace mechalynx/yt-url-at-time
// @license MIT
// @grant none
// @description On youtube, use alt+` to set the url to the current timestamp, for easy bookmarking
// @include https://www.youtube.com/*
// @version 0.2.7.001
// @copyright 2017, MechaLynx (https://github.com/MechaLynx)
// @run-at document-idle
// @author MechaLynx
// ==/UserScript==
// jshint esversion: 6
/**
*
* This is the modified version from https://greasyfork.org/scripts/35760-yt-url-at-time/
*
* MIT, credit to "MechaLynx"
*
*/
// `video` element utility
var video = {
get currentTime() {
const element = document.querySelector('#movie_player video, #movie_player audio.video-stream.html5-main-video');
return Math.floor(element.currentTime);
},
get _timehash() {
var secs = this.currentTime || 0;
return [(h = ~~(secs / 3600)) && h + 'h' || null,
(m = ~~(secs % 3600 / 60)) && m + 'm' || null,
(s = ~~(secs % 3600 % 60)) && s + 's'].join('');
},
get _plaintimehash() {
return `${this.currentTime}`;
},
// get timehash() {
// return 't=' + `${this._timehash}`;
// },
// get plaintimehash() {
// return 't=' + `${this._plaintimehash}`
// },
// get notimehash() {
// return window.location.origin +
// window.location.pathname +
// window.location.search +
// window.location.hash.replace(/#t=[^=#&]*/g, '');
// },
getURL(precise) {
// const hash = precise ? `${video.notimehash}&${video.plaintimehash}` : `${video.notimehash}&${video.timehash}`;
const uo = new URL(window.location.href.replace(/#t=[^=#&]*/g, ''));
uo.searchParams.set('t', `${precise ? this._plaintimehash : this._timehash}`);
return uo.toString();
}
};
// Keep looking for the time indicator span, until it's found
// The `load` event is insufficient
var wait_for_page = window.setInterval(function () {
var current_time_element = document.querySelector('.ytp-time-current');
if (current_time_element) {
window.clearInterval(wait_for_page);
// Add CSS for time indicator span
let time_style = document.createElement('style');
time_style.setAttribute('name', "yt-url-at-time");
time_style.innerHTML = `
.url-at-time-element-hover:hover{
cursor: pointer;
}
.url-at-time-clipboard-helper{
position: absolute;
top: 0;
left: 0;
padding: none;
margin: none;
border: none;
width: 0;
height: 0;
}
`;
document.body.appendChild(time_style);
// Toggle the class so that it doesn't look clickable
// during ads, which would be confusing
current_time_element.onmouseover = function () {
if (document.querySelector('.videoAdUi')) {
current_time_element.classList.remove('url-at-time-element-hover');
} else {
current_time_element.classList.add('url-at-time-element-hover');
}
};
current_time_element.addEventListener('click', function (e) {
if (e.altKey) {
hashmodifier(true);
} else {
hashmodifier(false);
}
if (e.ctrlKey) {
copy_url_to_clipboard();
}
});
}
}, 1000);
// Add the timestamp to the URL
var hashmodifier = function (precise = false) {
if (/^(\/live\/|\/watch)/.test(location.pathname) && document.querySelector('.videoAdUi') === null) {
const hash = video.getURL(precise);
history.replaceState(history.state, '', hash);
}
};
var copy_url_to_clipboard = function (attempt_to_restore = false) {
// Current focus and selection cannot be restored
// since clicking on the timer causes the movie player to be focused
// clearing the selection and changing the active element before we arrive here
// However, attempting to restore them is meaningful if called through a hotkey
if (attempt_to_restore) {
var selection = document.getSelection();
var current_selection = selection.getRangeAt(0);
var current_focus = document.activeElement;
}
// Add invisible textarea to allow copying the generated URL to clipboard
let clipboard_helper = document.createElement('textarea');
clipboard_helper.classList.add('url-at-time-clipboard-helper');
document.body.appendChild(clipboard_helper);
clipboard_helper.value = window.location.href;
clipboard_helper.select();
clipboard_helper.setSelectionRange(0, clipboard_helper.value.length);
document.execCommand('copy');
document.body.removeChild(clipboard_helper);
if (attempt_to_restore) {
current_focus.focus();
// https://gist.github.com/dantaex/543e721be845c18d2f92652c0ebe06aa
selection.empty();
selection.addRange(current_selection);
}
};
var _alt = false;
var _q = false;
// Listen for the hotkey
document.addEventListener('keydown', z => {
// if you want to change the hotkey
// you can use this: http://mechalynx.github.io/keypress/
// or another tester if you don't like this one
if (z.code === 'KeyQ') {
_q = true;
}
if (z.altKey && z.code === 'Backquote') {
hashmodifier(_alt);
_alt = true;
}
if (_q && _alt) {
copy_url_to_clipboard(true);
}
});
document.addEventListener('keyup', z => {
if (!z.altKey) {
_alt = false;
}
if (z.code === "KeyQ") {
_q = false;
}
});