-
Notifications
You must be signed in to change notification settings - Fork 6
/
Copy pathYouTube - Auto Buffer & Auto HD.user.js
697 lines (613 loc) · 26.7 KB
/
YouTube - Auto Buffer & Auto HD.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
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
413
414
415
416
417
418
419
420
421
422
423
424
425
426
427
428
429
430
431
432
433
434
435
436
437
438
439
440
441
442
443
444
445
446
447
448
449
450
451
452
453
454
455
456
457
458
459
460
461
462
463
464
465
466
467
468
469
470
471
472
473
474
475
476
477
478
479
480
481
482
483
484
485
486
487
488
489
490
491
492
493
494
495
496
497
498
499
500
501
502
503
504
505
506
507
508
509
510
511
512
513
514
515
516
517
518
519
520
521
522
523
524
525
526
527
528
529
530
531
532
533
534
535
536
537
538
539
540
541
542
543
544
545
546
547
548
549
550
551
552
553
554
555
556
557
558
559
560
561
562
563
564
565
566
567
568
569
570
571
572
573
574
575
576
577
578
579
580
581
582
583
584
585
586
587
588
589
590
591
592
593
594
595
596
597
598
599
600
601
602
603
604
605
606
607
608
609
610
611
612
613
614
615
616
617
618
619
620
621
622
623
624
625
626
627
628
629
630
631
632
633
634
635
636
637
638
639
640
641
642
643
644
645
646
647
648
649
650
651
652
653
654
655
656
657
658
659
660
661
662
663
664
665
666
667
668
669
670
671
672
673
674
675
676
677
678
679
680
681
682
683
684
685
686
687
688
689
690
691
692
693
694
695
696
697
// ==UserScript==
// @name YouTube Auto Buffer & Auto HD
// @namespace http://userscripts.org/users/23652
// @description Buffers the video without autoplaying and puts it in HD if the option is on. For Firefox, Opera, & Chrome
// @icon https://raw.github.com/joesimmons/YouTube---Auto-Buffer---Auto-HD/master/media/logo-64x64.png
// @include http://*.youtube.com/*
// @include http://youtube.com/*
// @include https://*.youtube.com/*
// @include https://youtube.com/*
// @copyright JoeSimmons
// @author JoeSimmons
// @version 1.2.87
// @license GPL version 3 or any later version; http://www.gnu.org/copyleft/gpl.html
// @require http://userscripts.org/scripts/source/49700.user.js?name=GM_config
// @require https://raw.github.com/joesimmons/jsl/master/versions/jsl-1.3.0.js
// @require http://userscripts.org/scripts/source/186053.user.js?name=YouTube_Button_Container
//@require http://usocheckup.dune.net/49366.js
// @grant GM_info
// @grant GM_getValue
// @grant GM_log
// @grant GM_openInTab
// @grant GM_registerMenuCommand
// @grant GM_setValue
// @grant GM_xmlhttpRequest
// ==/UserScript==
/* CHANGELOG
1.2.87 (1/22/2014)
- fixed odd internal error that made the player not show
- fixed problem with "Red Bar" not being disabled properly
1.2.86 (12/21/2013)
- fixed Large player button (as far as I can tell)
- added Automatic quality option (the YouTube default)
- switched the DASH option default to enabled
this is really what the script was made for... auto-buffering
1.2.85 (12/11/2013)
- added a script icon
- added a "Player Color Scheme" option
- fixed bug with SPF not being de-activated properly in non-Firefox browsers
- fixed volume bug
- fixed adding time in url bug. it will now skip to the right portion of the video
- changed internal name of the "Activation Mode" option. shouldn't affect the user
- the script doesn't add any javascript to the page anymore
it uses onYouTubePlayerReady to detect when the player is ready;
it's much more performant than an interval
1.2.84 (10/31/2013)
- added primitive type checking when copying ytplayer.config.args into the flashvars.
this fixes the issue with Flashgot and possibly other add-ons
- fixed non-activation by moving the _spf_state check to the top of init.
this disables SPF on every YouTube page now, and should make the script activate correctly
- changed all RegExp test methods to match. match seems more consistent.
I've had cases where test doesn't work, but match does
1.2.83 (10/28/2013)
- added auto HD, volume, and more activation modes for html5 (thanks to youtube updating its API)
- changed the default quality to 1080p
- changed the wording of some options
- changed the "Disable Dash Playback" option to false for default
- disabled SPF (aka Red Bar feature) completely until I get playlists working better
- changed the setPref prototype function to a regular function
1.2.82 (9/5/2013)
- added support for older Firefox versions (tested on 3.6)
- added a new option to disable 'dash' playback (videos loading in blocks/pieces)
- re-added ad removal feature (experimental for now)
1.2.81
- fixed HTML5 support. YT changed tag names so the script got confused
- made a few minor performance tweaks
- fixed 'play symbol in title' bug in autobuffer mode (it would show playing, even though it's paused/buffering)
1.2.80
- switched to JSL.setInterval for consistency and drift accommodation
- visual tweaks to:
msg().
the rest of the page now dims while the msg box is visible
changed the spacing of most of the elements
changed the font sizes and the font (Arial)
added a close button instead of requiring a double click
made it auto-open the options screen when the msg is closed
GM_config.
made the background color more mellow and moved the section title near the middle
1.2.79
- adjusted to the new play symbol in the youtube title feature
- Changed margins on the settings button when in footer
- Switched JSL/pushState checking order.
Previously in 1.2.78, if JSL didn't exist or wasn't @required, the script
would still loop every 500ms to re-set the pushState method, even though the
script wasn't going to be running.
I switched that so that JSL has to exist before the script does anything.
1.2.78
- Fixed bug where options button wasn't getting added to the footer with the new Red Bar YT feature
1.2.77
- Adapted to the new YouTube feature that uses HTML5's history.pushState to load videos
- Small fixes here and there
- Excluded (with RegExp) pages without videos on them
- Fixed GM_config.log()
- Declared all variables at the beginning of functions
- Made finding the video player a little more reliable
- Make 'autoplay on playlists' work with HTML5 videos
1.2.76
- Added new quality option ('1080p+' - for anything higher than 1080p)
1.2.75
- Added a new option (to move option button to page footer)
- Added a new option (to autoplay on playlists regardless of auto[play/buffer] setting)
- Added a first time user message box
- Fixed bug with GM_config's [set/get]Value functions. Chrome/Opera were not using localStorage before this update
1.2.74
- Adapted to YouTube's new layout
1.2.73
- Added compatibility for user pages
1.2.72
- Made it fully working again in Opera & Chrome
- Switched from setInterval to setTimeout due to instability
- Added an anonymous function wrapper
1.2.71
- Added compatibility for HTML5
*/
// run the script in an IIFE, to hide its variables from the global scope
(function (undefined) {
'use strict';
var aBlank = ['', '', ''],
URL = location.href,
navID = 'watch7-user-header',
rYoutubeUrl = /^https?:\/\/([^\.]+\.)?youtube\.com\//,
// rYoutubeBlacklistedUrl = /^https?:\/\/([^\.]+\.)?youtube\.com\/(feed\/(?!subscriptions)|account|inbox|my_|tags|view_all|analytics)/i,
rList = /[?&]list=/i,
rPlaySymbol = /^\u25B6\s*/,
script_name = 'YouTube - Auto-Buffer & Auto-HD',
tTime = (URL.match(/[&#?]t=([sm0-9]+)/) || aBlank)[1],
ads = [
'supported_without_ads',
'ad3_module',
'adsense_video_doc_id',
'allowed_ads',
'baseUrl',
'cafe_experiment_id',
'afv_inslate_ad_tag',
'advideo',
'ad_device',
'ad_channel_code_instream',
'ad_channel_code_overlay',
'ad_eurl',
'ad_flags',
'ad_host',
'ad_host_tier',
'ad_logging_flag',
'ad_preroll',
'ad_slots',
'ad_tag',
'ad_video_pub_id',
'aftv',
'afv',
'afv_ad_tag',
'afv_instream_max',
'afv_ad_tag_restricted_to_instream',
'afv_video_min_cpm',
'prefetch_ad_live_stream'
],
hasMainBeenRun, nav, uw, wait_intv;
function toNum(a) {
return parseInt(a, 10);
}
// msg by JoeSimmons
function msg(infoObject) {
var box_id_name = 'script_msg',
box = document.getElementById(box_id_name),
rLinebreaks = /[\r\n]/g,
title = typeof infoObject.title === 'string' && infoObject.title.length > 3 ? infoObject.title : 'Message Box by JoeSimmons.';
// add BR tags to line breaks
infoObject.text = infoObject.text.replace(rLinebreaks, '<br />\n');
function msg_close(event) {
event.preventDefault();
document.getElementById(box_id_name).style.display = 'none';
if (typeof infoObject.onclose === 'function') {
infoObject.onclose();
}
}
if (box == null) {
JSL.addStyle('' +
'@keyframes blink { ' +
'50% { color: #B95C00; } ' +
'}\n\n' +
'#' + box_id_name + ' .msg-header { ' +
'animation: blink 1s linear infinite normal; ' +
'}' +
'');
document.body.appendChild(
JSL.create('div', {id : box_id_name, style : 'position: fixed; top: 0; left: 0; width: 100%; height: 100%; z-index: 999999; background-color: rgba(0, 0, 0, 0.6);'}, [
// main box
JSL.create('div', {id : box_id_name + '_box', style : 'position: absolute; top: 25%; left: 25%; width: 50%; height: 50%; padding-top: 50px; background-color: #E9E9E9; border: 3px double #006195;'}, [
// header
JSL.create('div', {style : 'margin: 0 auto; padding-bottom: 40px; color: #F07800; font-size: 21pt; font-family: Arial, Verdana, "Myriad Pro"; font-weight: normal; text-shadow: 2px 2px 4px #C7C7C7; text-align: center;', 'class' : 'msg-header', textContent : title}),
// text (message)
JSL.create('div', {innerHTML : infoObject.text, style : 'text-align: center; margin: 0 auto; padding-top: 39px; border-top: 1px solid #B0B0B0; color: #000000; font-size: 11pt; font-family: Arial, Verdana, "Myriad Pro"; font-weight: normal; text-shadow: 0 0 8px #AEAEAE;'}),
// close button
JSL.create('div', {style : 'position: absolute; bottom: 20px; left: 0; width: 100%; text-align: center;'}, [
JSL.create('input', {id : box_id_name + '_close', type : 'button', value : 'Close Message', onclick : msg_close, style : 'margin: 0 auto; padding: 2px 20px; font-size: 11pt; font-family: Arial, Verdana, "Myriad Pro"; font-weight: normal;'})
])
])
])
);
} else {
box.innerHTML += infoObject.text;
}
}
// will return true if the value is a primitive value
function isPrimitiveType(value) {
switch (typeof value) {
case 'string': case 'number': case 'boolean': case 'undefined': {
return true;
}
case 'object': {
return !value;
}
}
return false;
}
function setPref(str, values) {
var i, value, rQuery;
for (i = 0; value = values[i]; i += 1) {
// (several lines for readability)
rQuery = new RegExp('[?&]?' + value[0] + '=[^&]*');
str = str.replace(rQuery, '') + '&' + value[0] + '=' + value[1];
str = str.replace(/^&+|&+$/g, '');
}
return str;
}
// unwraps the element so we can use its methods freely
function unwrap(elem) {
if (elem) {
if ( typeof XPCNativeWrapper === 'function' && typeof XPCNativeWrapper.unwrap === 'function' ) {
return XPCNativeWrapper.unwrap(elem);
} else if (elem.wrappedJSObject) {
return elem.wrappedJSObject;
}
}
return elem;
}
function fixPlaySymbol() {
document.title = document.title.replace(rPlaySymbol, '');
}
// grabs the un-wrapped player
function getPlayer() {
var doc = uw.document;
return doc.getElementById('c4-player') || doc.getElementById('movie_player');
}
// adds the Options button below the video
function addButton() {
var footer = GM_config.get('footer') === true,
footerHolder = document.getElementById('footer-main');
addButtonToContainer('Auto-Buffer Options', function () { GM_config.open(); }, 'autobuffer-options');
if (footer && footerHolder) {
footerHolder.appendChild( document.getElementById('autobuffer-options') );
}
}
// this function sets up the script
function init() {
hasMainBeenRun = false;
// get the raw window object of the YouTube page
uw = typeof unsafeWindow !== 'undefined' ? unsafeWindow : unwrap(window);
// temporary fix to disable SPF aka the "red bar" feature
if (uw._spf_state && uw._spf_state.config) {
uw._spf_state.config['navigate-limit'] = 0;
uw._spf_state.config['navigate-part-received-callback'] = function (targetUrl) {
location.href = targetUrl;
};
}
uw.onYouTubePlayerReady = function onYouTubePlayerReady(player) {
if (typeof player === 'object' && hasMainBeenRun === false) {
window.postMessage('YTAB__ready', '*');
}
};
JSL.waitFor({
selector : '#c4-player, #movie_player',
verifier : function (elem) {
elem = unwrap( elem[0] );
return typeof elem.stopVideo === 'function';
},
done : function () {
if (hasMainBeenRun === false) {
main();
}
}
});
}
// this is the main function. it does all the autobuffering, quality/volume changing, annotation hiding, etc
function main() {
var player = getPlayer(),
parent = player.parentNode,
alreadyBuffered = false,
time = 0,
args, arg, buffer_intv, fv, isHTML5, playerClone,
playIfPlaylist, val, userOpts;
// don't let main() run again unless a new video is loaded
hasMainBeenRun = true;
// remove the player out of the document temporarily while other things are being done,
// to reduce the time the player may be playing the video
parent.removeChild(player);
// set up the user options object
userOpts = {
activationMode : GM_config.get('activationMode'),
disableDash : GM_config.get('disableDash') === true,
hideAnnotations : GM_config.get('hideAnnotations') === true,
hideAds : GM_config.get('hideAds') === true,
quality : GM_config.get('autoHD'),
theme : GM_config.get('theme'),
volume : GM_config.get('volume')
};
// set up other variables
playerClone = player.cloneNode(true);
fv = player.getAttribute('flashvars');
isHTML5 = !!document.querySelector('video.html5-main-video');
playIfPlaylist = !!URL.match(rList) && GM_config.get('autoplayplaylists') === true;
if (uw.ytplayer && uw.ytplayer.config && uw.ytplayer.config.args) {
args = uw.ytplayer.config.args;
}
// set the volume to the user's preference
if (userOpts.volume != 1000) {
player.setVolume(userOpts.volume);
}
if (isHTML5) {
if (player.getPlaybackQuality() !== userOpts.quality) {
player.setPlaybackQuality(userOpts.quality);
}
if (!playIfPlaylist) {
if (userOpts.activationMode === 'buffer') {
player.pauseVideo();
} else if (userOpts.activationMode === 'none') {
player.stopVideo();
}
}
} else {
// copy 'ytplayer.config.args' into the flash vars
if (args) {
for (arg in args) {
val = args[arg];
if ( args.hasOwnProperty(arg) && isPrimitiveType(val) ) {
fv = setPref(fv, [ [ arg, encodeURIComponent(val) ] ]);
}
}
}
// ad removal
if (userOpts.hideAds) {
fv = fv.replace(new RegExp('(&|[&?])?(' + ads.join('|') + ')=[^&]*', 'g'), '');
/*
fv = setPref(fv,
ads.map(function (ad) {
return [ad, ''];
})
);
*/
}
// disable DASH playback
if (userOpts.disableDash) {
fv = setPref(fv, [
['dashmpd', ''],
['dash', '0']
]);
}
// edit the flashvars
fv = setPref(fv, [
['vq', userOpts.quality], // set the quality
['autoplay', (userOpts.activationMode !== 'none' || playIfPlaylist) ? '1' : '0' ], // enable/disable autoplay
['iv_load_policy', userOpts.hideAnnotations ? '3' : '1' ], // enable/disable annotations
['theme', userOpts.theme], // use light/dark theme
// some "just-in-case" settings
['enablejsapi', '1'], // enable JS API
['jsapicallback', 'onYouTubePlayerReady'], // enable JS ready callback
['fs', '1'], // enable fullscreen button, just in-case
['modestbranding', '1'], // hide YouTube logo in player
['disablekb', '0'] // enable keyboard controls in player
]);
// handle video starting time
if ( tTime.match(/\d+m/) ) {
time += toNum( tTime.match(/(\d+)m/)[1] ) * 60;
}
if ( tTime.match(/\d+s/) ) {
time += toNum( tTime.match(/(\d+)s/)[1] );
}
if ( tTime.match(/^\d+$/) ) {
time += toNum(tTime);
}
if (time <= 3) {
// if no time is in the url, check the player's time
try {
// sometimes causes a weird error.
// it will say getCurrentTime isn't a function,
// even though the typeof is "function",
// and alerting its value says [native code]
time = player.getCurrentTime();
} catch (e) {}
if (time <= 3) {
time = 0;
}
}
fv = setPref( fv, [ ['start', time] ] );
// set the new player's flashvars
playerClone.setAttribute('flashvars', fv);
// replace the original player with the modified clone
parent.appendChild(playerClone);
if (userOpts.activationMode === 'buffer' && playIfPlaylist === false) {
// handle auto-buffering
buffer_intv = JSL.setInterval(function () {
var player = getPlayer();
if (player && typeof player.getPlayerState === 'function') {
JSL.clearInterval(buffer_intv);
// pause the video so it can buffer
player.pauseVideo();
// seek back to beginning if time elapsed is not much
if (player.getCurrentTime() <= 3) {
player.seekTo(0);
}
// adjust to the 'play symbol in title' feature
window.setTimeout(fixPlaySymbol, 1000);
}
}, 100);
} else if (userOpts.activationMode === 'none') {
// adjust to the 'play symbol in title' feature
window.setTimeout(fixPlaySymbol, 1500);
}
}
// show the first time user message, then set it to never show again
if (GM_config.getValue('yt-autobuffer-autohd-first', 'yes') === 'yes') {
msg({
text : 'Welcome to "' + script_name + '".\n\n\n\n' +
'There is an options button below the video.\n\n\n\n' +
'The options screen will automatically open when you close this message.',
title : '"' + script_name + '" Message',
onclose : function () { GM_config.open(); }
});
GM_config.setValue('yt-autobuffer-autohd-first', 'no');
}
}
// make sure the page is not in a frame
// & is on a YouTube page (the @include works most of the time, but this is 100%)
// & isn't on a blacklisted YouTube page
if ( window !== window.top || !URL.match(rYoutubeUrl) /*|| URL.match(rYoutubeBlacklistedUrl)*/ ) { return; }
// quit if JSL/GM_config is non-existant
if (typeof JSL === 'undefined' || typeof GM_config === 'undefined' || typeof addButtonToContainer === 'undefined') {
return alert('' +
'A @require is missing.\n\n' +
'Either you\'re not using the correct plug-in, or @require isn\'t working.\n\n' +
'Please review the script\'s main page to see which browser & add-on to use.' +
'');
}
// add a user-script command
if (typeof GM_registerMenuCommand === 'function') {
GM_registerMenuCommand('"' + script_name + '" Options', GM_config.open);
}
// init GM_config
GM_config.init('"' + script_name + '" Options', {
activationMode : {
section : ['Main Options'],
label : 'Activation Mode',
type : 'select',
options : {
'buffer' : 'Auto Buffer (aka Auto Pause)',
'play' : 'Auto Play',
'none' : 'Stop Loading Immediately'
},
'default' : 'buffer'
},
autoHD : {
label : 'Auto HD',
type : 'select',
options : {
'default' : 'Automatic (default)',
'tiny' : '144p',
'small' : '240p',
'medium' : '360p',
'large' : '480p',
'hd720' : '720p (HD)',
'hd1080' : '1080p (HD)',
'hd1440' : '1440p (HD)',
'highres' : 'Original (highest)'
},
'default' : 'hd1080'
},
disableDash : {
label : 'Disable DASH Playback',
type : 'checkbox',
'default' : true,
title : '"DASH" loads the video in blocks/pieces; disrupts autobuffering -- Note: Qualities are limited when disabled'
},
hideAds : {
label : 'Disable Ads',
type : 'checkbox',
'default' : true,
title : 'Should disable advertisements. AdBlock is better, though. Get that instead'
},
hideAnnotations : {
label : 'Disable Annotations',
type : 'checkbox',
'default' : false
},
theme : {
section : ['Other Options'],
label : 'Player Color Scheme',
type : 'select',
options : {
'dark' : 'Dark Theme',
'light' : 'Light Theme'
},
'default' : 'dark'
},
volume : {
label : 'Set volume to: ',
type : 'select',
options : {
'1000' : 'Don\'t Change',
'0' : 'Off',
'5' : '5%',
'10' : '10%',
'20' : '20%',
'25' : '25% (quarter)',
'30' : '30%',
'40' : '40%',
'50' : '50% (half)',
'60' : '60%',
'70' : '70%',
'75' : '75% (three quarters',
'80' : '80%',
'90' : '90%',
'100' : '100% (full)',
},
title : 'What to set the volume to',
'default' : '1000'
},
autoplayplaylists : {
label : 'Autoplay on Playlists (override)',
type : 'checkbox',
'default' : false,
title : 'This will enable autoplay on playlists, regardless of the "Activation Mode" option'
},
footer : {
label : 'Options Button In Footer',
type : 'checkbox',
'default' : false,
title : 'This will make the options button show at the bottom of the page in the footer'
}
}, '' +
'body { ' +
'background-color: #DDDDDD !important; ' +
'color: #434343 !important; ' +
'font-family: Arial, Verdana, sans-serif !important; ' +
'}' +
'#config_header { ' +
'font-size: 16pt !important; ' +
'}' +
'.config_var { ' +
'margin-left: 20% !important; ' +
'margin-top: 20px !important; ' +
'}' +
'#header { ' +
'margin-bottom: 40px !important; ' +
'margin-top: 20px !important; ' +
'}' +
'.indent40 { ' +
'margin-left: 20% !important; ' +
'}' +
'.config_var * { ' +
'font-size: 10pt !important; ' +
'}' +
'.section_header_holder { ' +
'border-bottom: 1px solid #BBBBBB !important; ' +
'margin-top: 14px !important; ' +
'}' +
'.section_header { ' +
'background-color: #BEDBFF !important; ' +
'color: #434343 !important; ' +
'margin-left: 20% !important; ' +
'margin-top: 8px !important; ' +
'padding: 2px 200px !important; ' +
'text-decoration: none !important; ' +
'}' +
'.section_kids { ' +
'margin-bottom: 14px !important; ' +
'}' +
'.saveclose_buttons { ' +
'font-size: 14pt !important; ' +
'}' +
'#buttons_holder { ' +
'padding-right: 50px; ' +
'}' +
'', {
close : function () {
JSL('#c4-player, #movie_player').css('visibility', 'visible');
JSL('#lights_out').hide();
},
open : function () {
JSL('#c4-player, #movie_player').css('visibility', 'hidden');
JSL('#lights_out').show('block');
JSL('#GM_config').css('height', '80%').css('width', '80%');
}
});
// this is for the "lights out" feature of GM_config
JSL.runAt('interactive', function () {
JSL(document.body).append('div', {
id : 'lights_out',
style : 'display: none; position: fixed; top: 0; left: 0; width: 100%; height: 100%; z-index: 999998; background: rgba(0, 0, 0, 0.72);'
});
// call the function that sets up everything
init();
});
// add a message listener for when the unsafeWindow function fires a message
window.addEventListener('message', function (msg) {
if (msg.data === 'YTAB__ready') {
main();
}
}, false);
// wait for an element that can hold the options button to load,
// then run our add button function
JSL.waitFor({
selector : '#watch7-headline, #gh-overviewtab div.c4-spotlight-module-component, #footer-main',
done : addButton
});
}());