-
Notifications
You must be signed in to change notification settings - Fork 0
/
yt-url-at-time.user.js
159 lines (143 loc) · 4.82 KB
/
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
// ==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
// @copyright 2017, MechaLynx (https://github.com/MechaLynx)
// @updateURL https://openuserjs.org/meta/MechaLynx/yt-url-at-time.meta.js
// @downloadURL https://openuserjs.org/src/scripts/MechaLynx/yt-url-at-time.user.js
// @run-at document-idle
// @author MechaLynx
// ==/UserScript==
// jshint esversion: 6
// Matches time hashes for the purpose of removing them
// note that I don't like my regexp here...
var re_timehash = /#t=(?:[0-9]*\.?[0-9]*|(?:[0-9]*(?:h|m|s))*)*/g;
// `video` element utility
var video = {
get element() {
return document.querySelector('#movie_player video');
},
get timehash() {
var secs = this.element.currentTime;
return '#t=' + [(h = ~~(secs / 3600)) && h + 'h' || null,
(m = ~~(secs % 3600 / 60)) && m + 'm' || null,
(s = ~~(secs % 3600 % 60)) && s + 's'].join('');
},
get plaintimehash() {
return '#t=' + this.element.currentTime;
},
get notimehash() {
return window.location.origin +
window.location.pathname +
window.location.search +
window.location.hash.replace(re_timehash, '');
}
};
// 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 ( location.href.match(/.*watch.*/) && document.querySelector('.videoAdUi') === null){
precise ? history.replaceState(false, false, video.notimehash + video.plaintimehash) : history.replaceState(false, false, video.notimehash + video.timehash);
}
};
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;
}
});