C2B-UT

my youtube panel and hotkeys script (beta version) Work in progress!!

You will need to install an extension such as Tampermonkey, Greasemonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Violentmonkey to install this script.

You will need to install an extension such as Tampermonkey or Userscripts to install this script.

You will need to install an extension such as Tampermonkey to install this script.

You will need to install a user script manager extension to install this script.

(I already have a user script manager, let me install it!)

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install an extension such as Stylus to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

You will need to install a user style manager extension to install this style.

(I already have a user style manager, let me install it!)

// ==UserScript==
// @name         C2B-UT
// @namespace    http://your.homepage/
// @version      0.1
// @description  my youtube panel and hotkeys script (beta version) Work in progress!!
// @author       [email protected]
// @match        https://www.youtube.com/watch
// @grant        none
// ==/UserScript==

// match        https://www.youtube.com/user/kvn/videos

debugger;
//window.asdfasdf = 12341234;
//window.onfocus = function(){
//    console.log(111122);
//}
//var parent = document.body || document.head || document.documentElement;
//var q = document.createElement('div');
//q.className = "aaaa";
//q.innerHTML = `
//<div style="position:fixed;cursor: pointer;right:0;top: 50px;background: #929292;color: black;min-height:10px;min-width:10px;z-index: 99;padding: 2px;list-style-type: disc;list-style-position: outside;">
//asdfasdfasdf
//</div>
//`
//parent.appendChild(q);

function closest(self, selector) {
    if (!self) return null;
    for(var p=self.parentNode; p!=null; p=p.parentNode)
        if (p.className && ~p.className.split(' ').indexOf(selector))
            return p;
   	return null;
}
function closestType(self, selector) {
    if (!self) return null;
    for(var p=self.parentNode; p!=null; p=p.parentNode)
        if (p.type == selector || p.nodeName == selector.toUpperCase())
            return p;
   	return null;
}
function closestId(self, selector) {
    if (!self) return null;
    for(var p=self.parentNode; p!=null; p=p.parentNode)
        if (p.getAttribute && p.getAttribute('id') == selector)
            return p;
   	return null;
}
function getOffset( el, abs=false ) {
    var _x = 0;
    var _y = 0;
    var _el = el;
    while( el && !isNaN( el.offsetLeft ) && !isNaN( el.offsetTop ) ) {
        _x += el.offsetLeft - el.scrollLeft;
        _y += el.offsetTop - el.scrollTop;
        el = el.offsetParent;
    }
    if (!abs) {
        _y += document.body.scrollTop;
        _x += document.body.scrollLeft;
    }
    return { top: _y, left: _x, height: _el.offsetHeight, width: _el.offsetWidth, bottom: _y+_el.offsetHeight, right: _x+_el.offsetWidth };
}
var OFFS = 50;
var OFFSbot = 120;
function onScreen(i, abs=false){
    //var p = getOffset(i, false);
    var p = getOffset(i, true);
    //p.top -= document.body.scrollTop;
    //return p.top >= OFFS && p.top+i.clientHeight <= document.body.clientHeight-OFFS+2; // +2 for precision errors
    var h = i.clientHeight;
    var H = document.body.clientHeight;
    //if (abs) return p.top >= 0 && p.top + i.offsetHeight <= H;
    return !(p.top > H || p.bottom < 0);
    
    if (abs) return !(p.top > H || p.bottom < 0);
    
    var d = Math.min(p.top+h, H-OFFS+2) - Math.max(p.top,OFFS);
    //return d >= h*0.6 || d >= H*0.7;
    return !(d >= h*0.6 || d >= H*0.7);
}
function toScreen(i){
    //var p = getOffset(i, false);
    debugger;
    var p = getOffset(i, true);
    //p.top -= document.body.scrollTop;
    //if (p.top >= OFFS && p.top+i.clientHeight <= document.body.clientHeight-OFFS) return; // alr!
    var h = i.clientHeight;
    var H = document.body.clientHeight;
    if (p.top+h > H-OFFS) // lower
        document.body.scrollTop += p.top+h - (H-OFFS);
    else if (p.top < OFFS*2)
        document.body.scrollTop += p.top - OFFS*2;
    return;
    
    var a = getOffset(i);
    if (p.top+i.clientHeight > document.body.clientHeight-OFFS) // lower
        document.body.scrollTop = a.top+i.clientHeight - document.body.clientHeight + OFFS + OFFSbot;
    else
        document.body.scrollTop = a.top - OFFS*2;
}
function beep() {
    var snd = new Audio("data:audio/wav;base64,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qJrx4KOQjahZxWbcZgztj2c49nKmkId44S71j0c8eV9yDK6uPRzx5X18eDvjvQ6yKo9ZSS6l//8elePK/Lf//IInrOF/FvDoADYAGBMGb7FtErm5MXMlmPAJQVgWta7Zx2go+8xJ0UiCb8LHHdftWyLJE0QIAIsI+UbXu67dZMjmgDGCGl1H+vpF4NSDckSIkk7Vd+sxEhBQMRU8j/12UIRhzSaUdQ+rQU5kGeFxm+hb1oh6pWWmv3uvmReDl0UnvtapVaIzo1jZbf/pD6ElLqSX+rUmOQNpJFa/r+sa4e/pBlAABoAAAAA3CUgShLdGIxsY7AUABPRrgCABdDuQ5GC7DqPQCgbbJUAoRSUj+NIEig0YfyWUho1VBBBA//uQZB4ABZx5zfMakeAAAAmwAAAAF5F3P0w9GtAAACfAAAAAwLhMDmAYWMgVEG1U0FIGCBgXBXAtfMH10000EEEEEECUBYln03TTTdNBDZopopYvrTTdNa325mImNg3TTPV9q3pmY0xoO6bv3r00y+IDGid/9aaaZTGMuj9mpu9Mpio1dXrr5HERTZSmqU36A3CumzN/9Robv/Xx4v9ijkSRSNLQhAWumap82WRSBUqXStV/YcS+XVLnSS+WLDroqArFkMEsAS+eWmrUzrO0oEmE40RlMZ5+ODIkAyKAGUwZ3mVKmcamcJnMW26MRPgUw6j+LkhyHGVGYjSUUKNpuJUQoOIAyDvEyG8S5yfK6dhZc0Tx1KI/gviKL6qvvFs1+bWtaz58uUNnryq6kt5RzOCkPWlVqVX2a/EEBUdU1KrXLf40GoiiFXK///qpoiDXrOgqDR38JB0bw7SoL+ZB9o1RCkQjQ2CBYZKd/+VJxZRRZlqSkKiws0WFxUyCwsKiMy7hUVFhIaCrNQsKkTIsLivwKKigsj8XYlwt/WKi2N4d//uQRCSAAjURNIHpMZBGYiaQPSYyAAABLAAAAAAAACWAAAAApUF/Mg+0aohSIRobBAsMlO//Kk4soosy1JSFRYWaLC4qZBYWFRGZdwqKiwkNBVmoWFSJkWFxX4FFRQWR+LsS4W/rFRb/////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////VEFHAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAU291bmRib3kuZGUAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAMjAwNGh0dHA6Ly93d3cuc291bmRib3kuZGUAAAAAAAAAACU=");  
    snd.play();
}
function findAncestor (el, cls) {
    while ((el = el.parentElement) && !el.classList.contains(cls));
    return el;
}
function getDescendantWithClass(element, clName) {
    var children = element.childNodes;
    for (var i = 0; i < children.length; i++)
        if (children[i].className &&
            children[i].className.split(' ').indexOf(clName) >= 0)
            return children[i];
    for (var i = 0; i < children.length; i++) {
        var match = getDescendantWithClass(children[i], clName);
        if (match !== null)
            return match;
    }
    return null;
}
function getCookie(name) {
  var matches = document.cookie.match(new RegExp("(?:^|; )" + name.replace(/([\.$?*|{}\(\)\[\]\\\/\+^])/g, '\\$1') + "=([^;]*)"));
  return matches ? decodeURIComponent(matches[1]) : undefined;
}
function setCookie(name, value, options) {
  options = options || {};
  var expires = options.expires;
  if (typeof expires == "number" && expires) {
    var d = new Date();
    d.setTime(d.getTime() + expires * 1000);
    expires = options.expires = d;
  }
  if (expires && expires.toUTCString)
    options.expires = expires.toUTCString();
  value = encodeURIComponent(value);
  var updatedCookie = name + "=" + value;
  for (var propName in options) {
    updatedCookie += "; " + propName;
    var propValue = options[propName];
    if (propValue !== true)
      updatedCookie += "=" + propValue;
  }
  document.cookie = updatedCookie;
}
function cleanArray(arr) {
    for (var i=0; i < arr.length; i++)
        if (!arr[i]) {
            arr.splice(i, 1);
            i--;
        }
    return arr;
}
function isInput() {
    if (!document.activeElement) return false;
    return ~['TEXTAREA','INPUT'].indexOf(document.activeElement.tagName) || (document.activeElement.className && ~['comment-simplebox-text'].indexOf(document.activeElement.className));
}
//yt-uix-button yt-uix-button-size-default yt-uix-button-default load-more-button yt-uix-load-more comment-section-renderer-paginator yt-uix-sessionlink yt-uix-load-more-loading
//yt-uix-button-content
//load-more-loading
//yt-spinner
//yt-uix-button yt-uix-button-size-default yt-uix-button-default load-more-button yt-uix-load-more comment-section-renderer-paginator yt-uix-sessionlink
loader = {
	prev_count: -1,
	count: -1,
	changed: Number.MAX_VALUE,
	delay: 500, // ms
	wait: 19000, // ms
	over: 20000, // ms
	_timeout: null,
	_update: null,
	_check: null,
    _stop: false,
    scroll: 0,
    find: function(query, _filter){
        var q = document.getElementsByClassName(query); 
        q = Array.prototype.filter.call(q, function(i){ return i.offsetParent });
        if (_filter) q = Array.prototype.filter.call(q, _filter);
        return q; },
    texts: function(over){
        //var a = loader.find('load-more-text', function(i){ return i.offsetParent });
        //console.log('init loading of all texts...', a.length);
        //for(var i=0; i<a.length; i++) a[i].click();
        var a = loader.find('yt-uix-button-content', function(i){ return /^(Читать дальше)|(Read more)$/.test(i.textContent) });
        console.log('init loading of all texts...', a.length);
        for(var i=0; i<a.length; i++) a[i].click();
        //for(var i=0; i<a.length; i++)
        //    if (a[i].offsetParent != null && /^(Читать дальше)|(Read more)$/.test(a[i].textContent)) a[i].click();
        loader.scroll = Math.max(loader.scroll, getOffset(loader.find('comment-section-renderer-items')[0]).top - 200);
        window.scrollTo(0,loader.scroll);
        video.stopped(); // ui handler =)
        if (loader._stop) alert('stopped!');
        else alert(over?'timeout!':'done!'); },
    btn: function(_main = false){
        if (_main) return loader.find('comment-section-renderer-paginator')[0];
        var q = loader.find('yt-uix-load-more');
        if (q.length) q = q.filter(function(i){ return !~i.className.indexOf('comment-section-renderer-paginator') });
        if (q.length) return q[0];
        return loader.find('comment-section-renderer-paginator')[0]; },
        //return loader.find('yt-uix-load-more')[0]; },
        //return loader.find('yt-uix-load-more', function(i){return i.className.indexOf('yt-uix-button-link') == -1})[0]; },
	loaded: function(){
        return !loader.btn(true); },
	timeout: function(silent){
		clearTimeout(loader._timeout); loader._timeout = null;
		clearInterval(loader._update); loader._update = null;
		loader.changed = Number.MAX_VALUE;
		loader.prev_count = -1;
		loader.count = -1;
		if (!silent) console.log('loader timeout!');
		loader.texts(true); 
        loader._stop = false; 
        video.stopped(); // (double) call ui handler =)
    },
	reset_timeout: function(){
		clearTimeout(loader._timeout);
		loader._timeout = setTimeout(loader.timeout, loader.over); },
	update: function(){
		var c = loader.find('comment-thread-renderer').length;
        window.scrollTo(0,document.body.scrollHeight);
		console.log(c);
		if (c != loader.count) {
			console.log('changed ' + loader.count + ' to ' + c);
			loader.count = c;
			loader.changed = +new Date;
			loader.reset_timeout(); }
		else if (loader._stop || (+new Date - loader.changed >= loader.wait) && loader.loaded()) {
			loader.reset_timeout();
			window.scrollTo(0,document.body.scrollHeight);
			if (loader.loaded() || loader._stop || c == loader.prev_count) {
				console.log('all pages are loaded!', c);
				loader.timeout(true); }
			else {
				console.log('load next page...');
				loader.btn().click();
				loader.prev_count = c;
				loader.changed = +new Date; }}
		else if (!loader.loaded())
            loader.btn().click(); },
	start: function(){
        if (loader._update) {
            console.log('alr inp!');
            return; }
        console.log('start loading pages!');
		loader._update = setInterval(loader.update, loader.delay);
		loader._timeout = setTimeout(loader.timeout, loader.over);
        loader.scroll = document.body.scrollTop;
		window.scrollTo(0,document.body.scrollHeight);
        video.started(); // ui handler =)
        if (loader.btn())
            loader.btn().click();
    },
	stop: function(){
        if (loader._stop)
            console.log('alr stopping...');
        else
            console.log('stopping...');
        loader._stop = true; },
    start_stop: function(){
        if (loader._update)
            loader.stop();
        else
            loader.start();
    }
}

video = {
    panel: function(){
        var q = document.getElementsByClassName('mUTP')[0];
        if (!q) q = video.createPanel();
        return q;
    },
    createPanel: function(){
        var q = document.createElement('div');
        var p = document.getElementById('page-container');
        q.className = "mUTP";
        q.innerHTML = `
<div style="position:fixed;cursor: pointer;right:0;top: 50px;background: #929292;color: black;min-height:10px;min-width:10px;z-index: 99;padding: 2px;list-style-type: disc;list-style-position: outside;">
<form id="myUTE" style="
    position: absolute;
    left: 0;
    top: 0;
    transform: translateX(-100%);
    width: 200px;
    height: calc(100% - 20px);
    background: #6D6D6D;
    padding: 10px;
    visibility: hidden;
">
 <textarea type="text" name="firstname" style="
    /* margin: 7px; */
    width: calc(100% - 4px);
    height: calc(100% - 38px);
    margin-bottom: 5px;
    color: black !important;
"></textarea>
	<button onclick="video.favsClose()" style="font-size: 22px; line-height: 19px;"
			class="yt-uix-button yt-uix-button-size-default yt-uix-button-default yt-uix-button-empty yt-uix-tooltip"
			type="button" aria-pressed="false" aria-haspopup="true" data-tooltip-text="Закрыть без сохранения"
			aria-labelledby="yt-uix-tooltip222-arialabel">✘
	</button>
	<button onclick="video.favsSave()"
			style="font-size: 22px;line-height: 19px;width: 155px;margin-left: 6px;margin-right: -10px;"
			class="yt-uix-button yt-uix-button-size-default yt-uix-button-default yt-uix-button-empty yt-uix-tooltip"
			type="button" aria-pressed="false" aria-haspopup="true" data-tooltip-text="Сохранить"
			aria-labelledby="yt-uix-tooltip222-arialabel">✔
	</button>
</form>
<div id="myUTad"
	 style="position: absolute;left: 0px;top: 0px;transform: translateX(-100%);padding: 8px 10px;visibility: hidden;background: rgb(51, 255, 0);">
	Добавлено!
</div>
<div id="myUTre"
	 style="position: absolute;left: 0px;top: 0px;transform: translateX(-100%);padding: 8px 10px;visibility: hidden;background: rgb(255, 118, 118);">
	Удалено!
</div>
	<div style="
    padding: 0px 5px;
    background: rgba(122, 0, 255, 0.25);
">
		<div style="
    border-bottom: 1px rgba(0, 0, 0, 0.25) solid;
    color: white;
" onclick="video.onHeader(0)" oncontextmenu="video.onPrev(0)">✎ я
		</div>
		<div id="mUTC" style="
    position: absolute;
    right: 0;
    top: 0;
    margin: 3px 7px;
    color: rgba(255, 255, 255, 0.22);
    pointer-events: none;
">-
		</div>
		<div onclick="video.onLine(0,0)" oncontextmenu="video.onPrev(0,0)">
			<div>ветка:<span id="mUT00" style="
    font-weight: bold;
    margin-left: 3px;
    float: right;
">-</span>
			</div>
		</div>
		<div onclick="video.onLine(0,1)" oncontextmenu="video.onPrev(0,1)">
			<div>ответ:<span id="mUT01" style="
    font-weight: bold;
    margin-left: 3px;
    float: right;
">-</span>
			</div>
		</div>
	</div>
	<div style="
    padding: 0px 5px;
    background: rgba(0, 255, 0, 0.25);
">
		<div style="
    border-bottom: 1px rgba(0, 0, 0, 0.25) solid;
    color: white; position: relative;
            " onclick="video.onHeader(1)" oncontextmenu="video.onPrev(1)"><span>★ избр.</span>

			<div id="mUTF" style="
    position: absolute;
    right: 0;
    top: 0;
    margin: 1px -4px 1px 0px;
    padding: 0 5px;
    color: rgba(255, 255, 255, 0.22);
" onclick="video.editFavs()" class="yt-uix-button-size-default yt-uix-button-default yt-uix-button-empty yt-uix-tooltip"
				 type="button" aria-pressed="false" aria-haspopup="true" data-tooltip-text="Избранное"
				 aria-labelledby="yt-uix-tooltip45-arialabel" title="Избранное">-
			</div>
		</div>
		<div onclick="video.onLine(1,0)" oncontextmenu="video.onPrev(1,0)">
			<div>ветка:<span id="mUT10" style="
    font-weight: bold;
    margin-left: 3px;
    float: right;
">-</span>
			</div>
		</div>
		<div onclick="video.onLine(1,1)" oncontextmenu="video.onPrev(1,1)">
			<div>ответ:<span id="mUT11" style="
    font-weight: bold;
    margin-left: 3px;
    float: right;
">-</span>
			</div>
		</div>
	</div>
	<div style="
    padding: 0px 5px;
    background: rgba(255, 224, 0, 0.25);
">
		<div style="
    border-bottom: 1px rgba(0, 0, 0, 0.25) solid;
    color: white;
" onclick="video.onHeader(2)" oncontextmenu="video.onPrev(3)">♡ лайк
		</div>
		<div onclick="video.onLine(2,0)" oncontextmenu="video.onPrev(2,0)">
			<div>ветка:<span id="mUT20" style="
    font-weight: bold;
    margin-left: 3px;
    float: right;
">-</span>
			</div>
		</div>
		<div onclick="video.onLine(2,1)" oncontextmenu="video.onPrev(2,1)">
			<div>ответ:<span id="mUT21" style="
    font-weight: bold;
    margin-left: 3px;
    float: right;
">-</span>
			</div>
		</div>
	</div>
	<div style="
    padding: 0px 5px;
">
		<div style="
    border-bottom: 1px rgba(0, 0, 0, 0.25) solid;
    color: white;
" onclick="video.onHeader(3)" oncontextmenu="video.onPrev(2)">☺ прочие
		</div>
		<div onclick="video.onLine(3,0)" oncontextmenu="video.onPrev(3,0)">
			<div>ветка:<span id="mUT30" style="
    font-weight: bold;
    margin-left: 3px;
    float: right;
">-</span>
			</div>
		</div>
		<div onclick="video.onLine(3,1)" oncontextmenu="video.onPrev(3,1)">
			<div>ответ:<span id="mUT31" style="
    font-weight: bold;
    margin-left: 3px;
    float: right;
">-</span>
			</div>
		</div>
	</div>

	<div style="
    padding: 7px 5px 5px 5px;
            ">
		<button onclick="video.start()" style="font-size: 22px; line-height: 19px;"
				class="yt-uix-button yt-uix-button-size-default yt-uix-button-default yt-uix-button-empty yt-uix-tooltip"
				type="button" aria-pressed="false" aria-haspopup="true" data-tooltip-text="Загрузить (f9)"
				aria-labelledby="yt-uix-tooltip174-arialabel">⟳
		</button>
		<button onclick="video.parse()" style="font-size: 22px; line-height: 19px;"
				class="yt-uix-button yt-uix-button-size-default yt-uix-button-default yt-uix-button-empty yt-uix-tooltip"
				type="button" aria-pressed="false" aria-haspopup="true" data-tooltip-text="Повторный анализ И сортировка (f10)"
				aria-labelledby="yt-uix-tooltip25-arialabel">⚑
		</button>
		<!--♻⚑♺⚐✔ ✇☢∎⛔ http://xahlee.info/comp/unicode_transport_and_map_symbols.html -->
<br>
<button onclick="video.leaveLong()"
		style="font-size: 12px;line-height: 13px;max-height: 14px;padding: 0 16.6px;margin-top: 3px;"
		class="yt-uix-button yt-uix-button-size-default yt-uix-button-default yt-uix-button-empty yt-uix-tooltip"
		type="button" aria-pressed="false" aria-haspopup="true" data-tooltip-text="Оставить только длинные 20 мин (F2)"
		aria-labelledby="yt-uix-tooltip48-arialabel">⌛
</button>
<button onclick="video.removeWatched()"
		style="font-size: 12px;line-height: 13px;max-height: 14px;padding: 0 12.2px;margin-left: 0.2px;margin-top: 3px;"
		class="yt-uix-button yt-uix-button-size-default yt-uix-button-default yt-uix-button-empty yt-uix-tooltip"
		type="button" aria-pressed="false" aria-haspopup="true" data-tooltip-text="Убрать просмотренные (Shift+F2)"
		aria-labelledby="yt-uix-tooltip48-arialabel">✂
</button>
	</div>
	<div id="mUTS" style="
    font-size: 22px;
    line-height: 19px;
    position: absolute;
    left: 0;
    top: 0;
    width: 100%;
    height: 100%;
    background: rgba(0, 0, 0, 0.73);
    visibility: hidden;
">
		<button onclick="video.stop()"
				style="font-size: 42px;/* line-height: 19px; */position: absolute;left: 0;top: 0;width: calc(100% - 40px);height: calc(100% - 40px);margin: 20px;"
				class="yt-uix-button yt-uix-button-size-default yt-uix-button-default yt-uix-button-empty yt-uix-tooltip"
				type="button" aria-pressed="false" aria-haspopup="true" data-tooltip-text="Остановить загрузку"
				aria-labelledby="yt-uix-tooltip174-arialabel">
			<div style="
    transform: rotate(-90deg) translate3d(-150%,0,0);
    transform-origin: center center;
">
				<div id="mUTA" style="transform: rotate(0deg) translateY(-6px); display: inline-block; transform-origin: 52% 32%; font-size: 28px;">⌛</div>
<div style="
    transform: translate(10px,-5px);
    display: inline-block;
">стоп</div>
			</div>
		</button>
	</div>
</div>
`;
        q.children[0].style.top = p.offsetTop+"px";
        p.appendChild(q);
        video.initStart();
        video.registerClickHandler();
        //video.favs = JSON.parse(getCookie('myUTfavs') || '[]');
        var fv = document.getElementById('mUTF');
        fv.innerText = video.favs.length;
        return q;
    },
    initTimer: null,
    initCount: -1,
    initHandler: function(){
        var q = document.getElementsByClassName('comment-section-renderer-items')[0];
        if (!q) return; // still not loaded
        var c = q.children.length;
        if (c != video.initCount) {
            video.initCount = c;
            return; } // some loaded, wait 4 more
        // done loading
        //debugger;
        clearInterval(video.initTimer);
        video.initTimer = null;
        if (!loader._update) // not loading now?
            video.parse(null,true,true); // silent 1st time parse
    },
    initStart: function(){
        video.initTimer = setInterval(video.initHandler, 1000);
    },
    dom: null,
    current: null,
    animTimer: null,
    animValue: null,
    animStart: function(){
        video.animValue = 0;
        video.animTimer = setInterval(video.animHandler,10);
    },
    animStop: function(){
        clearInterval(video.animTimer);
        video.animTimer = null;
    },
    animHandler: function(){
        video.animValue += 3;
        var a = document.getElementById('mUTA');
        a.style.transform = 'rotate('+video.animValue+'deg) translateY(-6px)';
    },
    adornment: function(i, n,j){
        if (n == null) {
            i.style['background'] = '';
            if (!j) { // branch:
                i.nextElementSibling.style['border-left'] = '';
                i.nextElementSibling.style['padding-left'] = ''; }
            return;
        }
        //var clr = ['rgba(122, 0, 255, 0.25)', 'rgba(0, 255, 0, 0.25)', 'rgba(255, 224, 0, 0.25)'];
        var clr = ['rgba(122, 0, 255, 0.16)', 'rgba(0, 255, 0, 0.16)', 'rgba(255, 197, 0, 0.16)'];
        i.style['background'] = clr[n];
        if (!j) { // branch:
            i.nextElementSibling.style['border-left'] = '4px '+clr[n]+' solid';
            i.nextElementSibling.style['padding-left'] = '6px'; }
    },
    likesAdornment: function(q) {
        // likes progressbars:
        //debugger;
        for(var i in q){
            var j = q[i];
            var c = j.querySelector('.comment-renderer-like-count.on');
            if (!c || !c.offsetParent)
                c = j.querySelector('.comment-renderer-like-count.off');
            if (c && c.offsetParent) {
                var n = +c.innerText;
                var b = j.querySelector('.mutpb');
                if (!b) {
                    b = document.createElement('div');
                    /* b.innerHtml = `<div class="mutpb" style="
    position: absolute;
    bottom: 0;
    left: 0;
    height: 2px;
    width: 0%;
    pointer-events: none;
    background: rgba(255, 0, 0, 0.68);
"></div>`; */
                    b.className = 'mutpb';
                    b.style.position = 'absolute';
                    b.style.bottom = '0';
                    b.style.left = '0';
                    b.style.height = '2px';
                    b.style.width = '0%';
                    b.style['pointer-events'] = 'none';
                    b.style.background = 'rgba(255, 0, 0, 0.68)';
                    j.insertBefore(b, j.firstChild);
                    //b = b.firstChild;
                }
                var l = '255,0,0';
                var x = 1000;
                if (n <= 50){ x = 50; l = '255,255,0'; }
                else if (n <= 100){ x = 100; l = '0,255,0'; }
                b.style.background = 'rgba(' + l + ', 0.68)';
                b.style.width = n * 100.0 / x + '%';
                j.style.position = 'relative';
            }
        }
    },
    delayParseTimer: null,
    delayParseThrottle: 0,
    delayParseCount: -1,
    delayParseCount0: -1,
    delayParseCounter: -1,
    delayParseCounterINIT: 100, // 100 ms * 100 = 10 sec
    delayParseCounterMAX: 10, // 100 ms * 10 = 1 sec
    delayParseFunction: null,
    delayParseHandler: function(){
        var c = video.delayParseCount;
        video.delayParseCount = video.delayParseFunction();
        if (c == video.delayParseCount) {
            var max = video.delayParseCounterMAX;
            if (c == video.delayParseCount0) max = video.delayParseCounterINIT;
            if (++video.delayParseCounter > max) {
                console.log('delayParseHandler --- timeout!', max);
                clearInterval(video.delayParseTimer);
                video.delayParseTimer = null;
                // operate:
                video.parse(true, true, true);
            }
        } else { 
            console.log('delayParseHandler --- reset counter', c, video.delayParseCounter);
            video.delayParseCounter = 0; } // reset counter
        // continue waiting
    },
    delayParse: function(counter){
        if (video.delayParseTimer) clearInterval(video.delayParseTimer);
        video.delayParseFunction = counter;
        video.delayParseThrottle = 0;
        video.delayParseCounter = 0;
        video.delayParseCount0 = video.delayParseCount = video.delayParseFunction();
        video.delayParseTimer = setInterval(video.delayParseHandler, 100);
        console.log('delayParseHandler --- start');
    },
    parse: function(force, silent, noReorder){
        //debugger;
        var pause = document.getElementById('mUTS');
        var was = pause.style.visibility == 'visible';
        console.log('video.parse', was);
        if (!was) {
            //pause.style.visibility = 'visible';
            //pause.children[0].style.visibility = 'hidden'; 
        }
        
        var bd = document.getElementById('watch-discussion');
        if (bd.children[0].children[0].className == 'action-panel-loading') {
            window.scrollTo(0, getOffset(bd).top - 200);
            setTimeout(video.parse, 200);
            return; // wait 4 loading
        }
        
        if (!was && force) {
            setTimeout(function(){video.parse(false, silent, noReorder)}, 100);
            return; // allow ui redraw
        }
        
        video.dom = {0:{0:[],1:[]}, 1:{0:[],1:[]}, 2:{0:[],1:[]}, 3:{0:[],1:[]}};
        var me = document.getElementsByClassName('yt-masthead-picker-name')[0].textContent;
        var favs = video.favs;
        var root = function(i){ return ~i.parentNode.className.indexOf("comment-thread-renderer") };
        var my = function(i){ return i.getAttribute('data-author-name') == me };
        var fv = function(i){ return favs.indexOf(i.getAttribute('data-author-name')) != -1 };
        var n0 = function(i){ return video.dom[0][0].indexOf(i) == -1 && video.dom[1][0].indexOf(i) == -1 };
        var n1 = function(i){ return video.dom[0][1].indexOf(i) == -1 && video.dom[1][1].indexOf(i) == -1 };
        var lk = function(i){ return i.getAttribute('data-action-on') == 1 };
        var lroot = function(i){ return i.parentNode.parentNode.parentNode.parentNode.className == "comment-thread-renderer" };
        video.dom[0][0] = loader.find('comment-renderer', function(i){return my(i) && root(i)});
        video.dom[0][1] = loader.find('comment-renderer', function(i){return my(i) && !root(i)});
        video.dom[1][0] = loader.find('comment-renderer', function(i){return fv(i) && root(i)});
        video.dom[1][1] = loader.find('comment-renderer', function(i){return fv(i) && !root(i)});
        video.dom[2][0] = loader.find('comment-renderer liked', function(i){return root(i)});
        video.dom[2][1] = loader.find('comment-renderer liked', function(i){return !root(i)});
        video.dom[3][0] = loader.find('comment-renderer', function(i){return n0(i) && root(i)});
        video.dom[3][1] = loader.find('comment-renderer', function(i){return n1(i) && !root(i)});
        //video.dom[3][0] = loader.find('sprite-like', function(i){return lk(i) && lroot(i)});
        //video.dom[3][1] = loader.find('sprite-like', function(i){return lk(i) && !lroot(i)});
        document.getElementById('mUT00').innerText = video.dom[0][0].length;
        document.getElementById('mUT01').innerText = video.dom[0][1].length;
        document.getElementById('mUT10').innerText = video.dom[1][0].length;
        document.getElementById('mUT11').innerText = video.dom[1][1].length;
        document.getElementById('mUT20').innerText = video.dom[2][0].length;
        document.getElementById('mUT21').innerText = video.dom[2][1].length;
        document.getElementById('mUT30').innerText = video.dom[3][0].length;
        document.getElementById('mUT31').innerText = video.dom[3][1].length;
        
        // resort
        var p = document.getElementsByClassName('comment-section-renderer-items')[0];
        var q = null;
        var f = function(n,j){
            var c = video.dom[n][j];
            for(var i=0; i<c.length; i++) {
                //var v = c[i].parentNode;
                //if (j) v = v.parentNode.parentNode.parentNode;
                var v = closest(c[i],'comment-thread-renderer');
                
                // order
                if (!noReorder) {
                    if (!q) {
                        if (p.children[1] != v) p.insertBefore(v, p.children[1]); }
                    else if (q.nextElementSibling != v) p.insertBefore(v, q.nextElementSibling); 
                }
                q = v;
                
                // adornment
                video.adornment(c[i],n,j);
                //var clr = ['rgba(122, 0, 255, 0.25)', 'rgba(0, 255, 0, 0.25)', 'rgba(255, 224, 0, 0.25)'];
//                var clr = ['rgba(122, 0, 255, 0.16)', 'rgba(0, 255, 0, 0.16)', 'rgba(255, 197, 0, 0.16)'];
//                c[i].style['background'] = clr[n];
//                if (!j) { // branch:
//                    c[i].nextElementSibling.style['border-left'] = '4px '+clr[n]+' solid';
//                    c[i].nextElementSibling.style['padding-left'] = '6px'; }
            }
        }
        f(0,0);
        f(0,1);
        f(1,0);
        f(1,1);
        f(2,0);
        f(2,1);
        
        // likes progressbars:
        //debugger;
        q = loader.find('comment-renderer-footer');
        video.likesAdornment(q);
/* b.innerHtml = `<div class="mutpb" style="
    position: absolute;
    bottom: 0;
    left: 0;
    height: 2px;
    width: 0%;
    pointer-events: none;
    background: rgba(255, 0, 0, 0.68);
"></div>`; */
/*        for(var i in q){
            var j = q[i];
            var c = j.querySelector('.comment-renderer-like-count.on');
            if (!c || !c.offsetParent)
                c = j.querySelector('.comment-renderer-like-count.off');
            if (c && c.offsetParent) {
                var n = +c.innerText;
                var b = j.querySelector('.mutpb');
                if (!b) {
                    b = document.createElement('div');
                    b.className = 'mutpb';
                    b.style.position = 'absolute';
                    b.style.bottom = '0';
                    b.style.left = '0';
                    b.style.height = '2px';
                    b.style.width = '0%';
                    b.style['pointer-events'] = 'none';
                    b.style.background = 'rgba(255, 0, 0, 0.68)';
                    j.insertBefore(b, j.firstChild);
                    //b = b.firstChild;
                }
                var l = '255,0,0';
                var x = 1000;
                if (n <= 50){ x = 50; l = '255,255,0'; }
                else if (n <= 100){ x = 100; l = '0,255,0'; }
                b.style.background = 'rgba(' + l + ', 0.68)';
                b.style.width = n * 100.0 / x + '%';
                j.style.position = 'relative';
            }
        }*/
        
        if (!was){
            console.log('video.parse - restore visibility');
            debugger;
            //pause.children[0].style.visibility = 'hidden';
            //pause.style.visibility = 'hidden'; // done!
        }
        console.log('parsed.');
        
        //document.getElementById('movie_player').focus(); // focus bug fix        
        
//        video.dom[0][0] = loader.find('comment-renderer', function(i){return i.getAttribute('data-author-name') == me && i.parentNode.className == "comment-thread-renderer"});
//        video.dom[0][1] = loader.find('comment-renderer', function(i){return i.getAttribute('data-author-name') == me && i.parentNode.className != "comment-thread-renderer"});
//        video.dom[1][0] = loader.find('comment-renderer', function(i){return favs.indexOf(i.getAttribute('data-author-name')) != -1 && i.parentNode.className == "comment-thread-renderer"});
//        video.dom[1][1] = loader.find('comment-renderer', function(i){return favs.indexOf(i.getAttribute('data-author-name')) != -1 && i.parentNode.className != "comment-thread-renderer"});
//        video.dom[2][0] = loader.find('comment-renderer', function(i){return video.dom[0][0].indexOf(i) == -1 && video.dom[1][0].indexOf(i) == -1 && i.parentNode.className == "comment-thread-renderer"});
//        video.dom[2][1] = loader.find('comment-renderer', function(i){return video.dom[0][1].indexOf(i) == -1 && video.dom[1][1].indexOf(i) == -1 && i.parentNode.className != "comment-thread-renderer"});
        
//        loader.find('comment-renderer')[0].getAttribute('data-author-name')
        //...
    },
    get: function(g,l) {
        if (!video.dom) parse();
        var q = video.dom[g];
        if (!q) return null;
        return l != null ? q[l] : q;
    },
    onHeader: function(g) {
        var i = video.dom[g][0][0];
        var j = video.dom[g][1][0];
        if (!i && j)  i = j;
        else if (i && j && getOffset(i).top > getOffset(j).top) i = j;
        if (i) toScreen(i);
        video.setCurrent(i);
        document.getElementById('mUTC').innerText = i ? '0' : "-";
    },
    setCurrent: function(cur) {
        if (!cur) {
            beep(); // none!
            if (video.current) {
                video.current.style['border-left'] = '';
                video.current.style['padding-left'] = '';
            }
            video.current = null;
        } else {
            toScreen(cur);
            if (video.current) {
                video.current.style['border-left'] = '';
                video.current.style['padding-left'] = '';
            }
            video.current = cur;
            video.current.style['border-left'] = '6px orange solid';
            video.current.style['padding-left'] = '6px';
        }
    },
    setCur: function(cur,col) {
        if (!~cur || cur==null)
            video.setCurrent();
        else
            video.setCurrent(col[cur]);
        document.getElementById('mUTC').innerText = !~cur ? "-" : (cur+1)+'/'+col.length;
    },
    onPrev: function(g,l) {
        video.onPrev.caller.arguments[0].preventDefault();
        var col = video.dom[g][l];
        var cur = col.indexOf(video.current);
        if (~cur && !onScreen(video.current)) cur = -1; // cur is off screen!
        if (~cur) {
            if (--cur < 0) {
                cur = col.length-1;
                beep(); // over!
            }
        } else if (col.length) {
            for (var i=col.length-1; i >= 0; i--)
                if (onScreen(col[i])){
                    cur = i;
                    break; }
            if (!~cur) {
                cur = col.length-1;
                beep(); // over!
            }
        }
        video.setCur(cur,col);
    },
    onLine: function(g,l) {
        var col = video.dom[g][l];
        var cur = col.indexOf(video.current);
        if (~cur && !onScreen(l ? video.current : closest(video.current, 'comment-thread-renderer'))) cur = -1; // cur is off screen!
        if (~cur) {
            if (++cur >= col.length) {
                cur = 0;
                beep(); // over!
            }
        } else if (col.length) {
            for (var i=0; i < col.length; i++)
                if ((!l && onScreen(col[i])) || onScreen(l ? col[i] : closest(col[i], 'comment-thread-renderer'))){
                    cur = i+1;
                    if (cur >= col.length) cur = -1;
                    break; }
            if (!~cur) {
                cur = 0;
                beep(); // over!
            }
        }
        video.setCur(cur,col);
/*        if (!~cur) {
            beep(); // none!
            if (video.current)
                video.current.style['border-left'] = '';
        } else {
            toScreen(col[cur]);
            if (video.current)
                video.current.style['border-left'] = '';
            video.current = col[cur];
            video.current.style['border-left'] = '4px orange solid';
        }
        document.getElementById('mUTC').innerText = !~cur ? "-" : cur+'/'+col.length;*/
    },
    start: function(orStop){
        var pause = document.getElementById('mUTS');
        if (pause.style.visibility == 'visible') {
            if (orStop) video.stop();
            else beep();
            return; // alr!
        }
        console.log('video.start');
        pause.style.visibility = 'visible';
        loader.start();
    },
    stop: function(){
        if (loader._stop) {
            beep();
            return; // alr!
        }
        console.log('video.stop');
        loader.stop();
    },
    stopped: function(){
        var pause = document.getElementById('mUTS');
        console.log('video.stopped');
        pause.style.visibility = 'hidden';
        video.animStop();
        video.parse(); // parse loaded data
    },
    started: function(){
        video.animStart();
    },
    leaveLong: function() {
        if(document.querySelectorAll("#channels-browse-content-grid").length)
        {
            console.log(1);
            Array.prototype.forEach.call(
                document.querySelectorAll(".channels-content-item"), 
                function(x){ 
                    if(Date.parse("1/1/1 " + x.querySelector(".video-time")
                                  .textContent.replace(/(\d+:\d+)(:\d)?/,function(s,p1,p2){return p2 == null ? "0:"+s : s; })
                                 ) <= Date.parse("1/1/1 00:20:00"))
                        document.querySelector("#channels-browse-content-grid").removeChild(x); });
        }
        else
        {
            console.log(2);
            Array.prototype.forEach.call(
                document.querySelectorAll(".browse-list-item-container"), 
                function(x){ 
                    if(Date.parse("1/1/1 " + x.querySelector(".video-time")
                                  .textContent.replace(/(\d+:\d+)(:\d)?/,function(s,p1,p2){return p2 == null ? "0:"+s : s; })
                                 ) <= Date.parse("1/1/1 00:20:00"))
                        document.querySelector("#browse-items-primary").removeChild(x); });
        }
    },
    removeWatched: function() {
        Array.prototype.forEach.call(
            document.querySelectorAll(".watched-badge"), 
            function(x){ (closest(x,'channels-content-item') || closest(x,'feed-item-container')).remove(); });
    },
    seek: function(e, right){
        var q = document.querySelector("video");
        if (!q) return;
        var v = right ? 1 : 2;
        if (e.shiftKey && e.ctrlKey) v = 90;
        else if (e.shiftKey) v = 30;
        else if (e.ctrlKey) v = 10;
        else if (e.altKey) v = 1 / 29.97;
        else if (document.activeElement == q.parentElement.parentElement) return; // yt player will handle...
        var k = (right == false) ? -1 : 1;
        q.currentTime += k * v * q.playbackRate; // .getCurrentTime()
        return true;
    },
    playPause: function (shiftKey){
        var q = document.querySelector("video");
        if (!q) return;
        var r = q.getBoundingClientRect();
        console.log(r.top + ' < ' + (30-r.height));
        if ((!shiftKey && r.top < 30-r.height) || document.activeElement == q.parentElement.parentElement) return;
        if (q.paused) q.play();
        else q.pause();
        return true;
    },
    fullScreen: function(){
        //if (document.activeElement && ~['textarea','input'].indexOf(document.activeElement.type))
        if (isInput()) 
            return; // text input in process =)
        document.getElementsByClassName('ytp-fullscreen-button')[0].click();
        return true;
        var ev = document.createEvent('KeyboardEvent');
        var key = 70; // f
        //ev.initKeyboardEvent('keypress', true, true, window, null, key);
        //ev.initKeyboardEvent("keypress", true, true, window,
        //          0, 0, 0, 0,
        //        key, key);
        //ev.initKeyboardEvent('keydown', true, true, window, false, false, false, false, 13, 0);
        ev.initKeyboardEvent("keydown", true, true, document.defaultView, key, key, "", "", false, "");
        document.dispatchEvent(ev);
        return true;
    },
    toggleSpeed: function(mul){
        var q = document.querySelector("video");
        if (!q) return;
        if (mul)
            q.playbackRate = q.playbackRate == 2.7 ? 1 : 2.7;
        else
            q.playbackRate = q.playbackRate == 1 ? 2 : 1;
        /*q = document.querySelector(".appbar-guide-notification");
        q.getElementsByClassName('appbar-guide-notification-text-content')[0].textContent = 'Скорость: ' + q.playbackRate;
        q.style.height = 'initial';
        setTimeout(function(){
            q.style.height = '';
        }, 500);*/
        return true;
    },
    myCommentsBefore: [],
    myCommentsCounter: 0,
    myCommentsCounterMAX: 100,
    myCommentsTimer: null,
    myCommentsThread: null,
    click_e: null,
    clickHandler: function(e){
        if (loader._update) return; // inp!
        console.log('clickHandler', e);
        if (!e.target || !e.target.className) return;
        if (~e.target.className.indexOf('comment-simplebox-submit')) {
            debugger;
            if (video.myCommentsTimer) clearInterval(video.myCommentsTimer);
            video.myCommentsThread = findAncestor(e.target, 'comment-thread-renderer');
            //document.getElementsByClassName('comment-thread-renderer')[0];
            //video.myCommentsCounter = document.querySelector(".comment-thread-renderer").getElementsByClassName('comment-renderer');
            var me = document.getElementsByClassName('yt-masthead-picker-name')[0].textContent;
            var q = function(){ return video.myCommentsThread.querySelectorAll('.comment-renderer[data-author-name="'+me+'"]') };
            video.myCommentsBefore = q();
            video.myCommentsCounter = 0;
            video.myCommentsTimer = setInterval(function(){
                var e = q();
                if (++video.myCommentsCounter <= video.myCommentsCounterMAX
                    && e.length <= video.myCommentsBefore.length) {
                    console.log('wait my post submit - continue waiting...');
                    return; } // continue waiting...
                // stop waiting
                clearInterval(video.myCommentsTimer);
                video.myCommentsTimer = null;
                video.myCommentsBefore = [];
                video.myCommentsThread = null;
                if (video.myCommentsCounter >= video.myCommentsCounterMAX)
                    console.log('wait my post submit - TIMEOUT!');
                video.myCommentsCounter = 0;
                // posted! - parse:
                q = Array.prototype.filter.call(e, function(i){ return !~video.myCommentsBefore.indexOf(i) });
                console.log('post submitted!', q);
                var root = function(i){ return ~i.parentNode.className.indexOf("comment-thread-renderer") };
                var my = function(i){ return i.getAttribute('data-author-name') == me };
                video.dom[0][1] = loader.find('comment-renderer', function(i){return my(i) && !root(i)});
                document.getElementById('mUT01').innerText = video.dom[0][1].length;
                video.adornment(q[0],0,1);
            }, 300);
            return;
        }
        
        var t = closest(e.target, 'comment-thread-renderer');
        var t2 = closest(e.target, 'comment-replies-renderer-expander-down');
        if (t && (t2 || ~e.target.className.indexOf('comment-replies-renderer-expander-down'))) {
            var q = findAncestor(e.target, 'comment-thread-renderer');
            video.delayParse(function(){ return q.querySelectorAll('.comment-renderer').length });
            return;
        } else
            console.log('nope', e.target, t);
        
        if (e.target.className == 'yt-uix-expander-collapsed-body')
            e.target.querySelector('.load-more-button').click();
        
        if (!~e.target.className.indexOf('sprite-like')) return;
        var v = !e.target.getAttribute('data-action-on');
        var q = findAncestor(e.target, 'comment-renderer');
//        console.log('!!!!!!', v, e.target, e);
        if (e.shiftKey || (video.click_e && video.click_e.shiftKey))
            video.setFav(q.getAttribute('data-author-name'), v);
        var root = function(i){ return ~i.parentNode.className.indexOf("comment-thread-renderer") };
        var n = root(q) ? 0 : 1;
        setTimeout(function(){
            if (!v) {
                var x = video.dom[2][n].indexOf(q);
                if (~x) video.dom[2][n].splice(x,1);
            } else
                video.dom[2][n] = loader.find('comment-renderer liked', function(i){return !n == !!root(i)});
            document.getElementById('mUT20').innerText = video.dom[2][0].length;
            document.getElementById('mUT21').innerText = video.dom[2][1].length;
            if (v) video.adornment(q,2,n);
            else {
                var x = null;
                if (~video.dom[0][0].indexOf(q) || ~video.dom[0][1].indexOf(q)) x = 0;
                if (~video.dom[1][0].indexOf(q) || ~video.dom[1][1].indexOf(q)) x = 1;
                video.adornment(q, x,n);
            }
        }, 100);
    },
    mousedownHandler: function(e){
        if (!e.target || e.which != 2 || e.target.nodeName == 'A' || closestType(e.target, 'a')) return;
        if (e.target.getAttribute('id') == 'channels-browse-content-grid' || // grid view
            e.target.parentNode.parentNode.getAttribute('id') == 'browse-items-primary' || // grid view outer
            (!closestType(e.target, 'a') && e.target.nodeName != 'A' && closestId(e.target, 'browse-items-primary'))) // list view
        { // load more
            document.querySelector(".load-more-button").click();
            e.preventDefault();
            return; 
        }
        var q = findAncestor(e.target, 'comment-renderer');
        if (!q) return;
        var l = getDescendantWithClass(q, 'sprite-like');
        if (!l) return;
        // middle button!
//        console.log('!!!!!!!!!!!!!!!!!!!!!!!!!!!!', e, q, l);
        //var q = e.target
        video.click_e = e;
        l.click();
        video.click_e = null;
        e.preventDefault();
    },
    registerClickHandler: function(e){
        var q = document.getElementById('watch-discussion') || document.getElementById('content');
        q.addEventListener('click',video.clickHandler,true);
        q.addEventListener('mousedown',video.mousedownHandler,true);
    },
    //favs: ['Ирина Ляшенко', 'Марго Павлова'],
    favs: JSON.parse(getCookie('myUTfavs') || '[]'),
    applyFavs: function(arr, old){
        setCookie('myUTfavs', JSON.stringify(video.favs), {expires: 154000000000, domain:'www.youtube.com'}); // 100 years
        var q = document.getElementById('mUTF');
        q.innerText = video.favs.length;
        // ui
        video.parse(null, true, true);
        if(!old) return;
        // reset adornment
        var p = document.getElementsByClassName('comment-section-renderer-items')[0];
        q = null;
        var f = function(n,j){
            var c = video.dom[n][j];
            for(var i=0; i<c.length; i++) {
                var v = c[i].parentNode;
                if (j) v = v.parentNode.parentNode.parentNode;
                // adornment
                var s = v.getAttribute('data-author-name');
                if (~arr.indexOf(s) == ~old.indexOf(s)) continue;
                c[i].style['background'] = '';
                if (!j) { // branch:
                    c[i].nextElementSibling.style['border-left'] = '';
                    c[i].nextElementSibling.style['padding-left'] = ''; }
            }
        }
        f(1,0);
        f(1,1);
    },
    setFav: function(name,add){
        var x = video.favs.indexOf(name);
        var s = false;
        if (add && !~x) { video.favs.push(name); s=true;}
        else if (~x){ video.favs.splice(x,1); s=true;}
        if (!s) return;
        video.applyFavs();
        var q = document.getElementById(add ? 'myUTad' : 'myUTre');
        q.style.visibility = 'visible';
        setTimeout(function(){q.style.visibility = 'hidden'}, 3000);
    },
    editFavs: function(){
        var q = document.getElementById('myUTE');
        var t = q.children[0];
        t.value = video.favs.join('\n');
        q.style.visibility = 'visible';
        t.focus();
    },
    favsClose: function(){
        var q = document.getElementById('myUTE');
        q.style.visibility = 'hidden';
    },
    favsSave: function(){
        var q = document.getElementById('myUTE');
        var t = q.children[0];
        video.favs = cleanArray(t.value.split('\n'));
        video.favsClose();
        video.applyFavs();
    },
    pageScroll: function(up){
        if (!document.activeElement) return;
        if (!~['movie_player','player-api'].indexOf(document.activeElement.getAttribute('id'))) return;
        var v = document.body.scrollTop + (up?-1:1) * document.body.clientHeight * 0.8;
        document.body.scrollTop = v;
        return true;
    }
}

function doc_keyUp(e) {
    console.log('----------------- monkey press: ' + e.keyCode);
    if (window.event && e.keyCode == 113 && !e.shiftKey && !e.ctrlKey && !e.altKey) { // f2
        video.leaveLong();
		e.keyCode = 0;
		e.returnValue = false;
        e.preventDefault();
        //return false;
    }
    if (window.event && e.keyCode == 113 && e.shiftKey && !e.ctrlKey && !e.altKey) { // +f2
		video.removeWatched();
        e.preventDefault();
    }
    if (window.event && e.keyCode == 115 && !e.shiftKey && !e.ctrlKey && !e.altKey) { // f4
		document.querySelector(".load-more-button").click();
        e.preventDefault();
    }
//    if (window.event && e.keyCode == 120 && !e.shiftKey && !e.ctrlKey && !e.altKey) // f9
//        loader.start_stop();
    if (window.event && e.keyCode == 120 && !e.shiftKey && !e.ctrlKey && !e.altKey) { // f9
        video.start(true);
        e.preventDefault();
    }
    if (window.event && e.keyCode == 121 && !e.shiftKey && !e.ctrlKey && !e.altKey) { // f10
        video.parse();
        e.preventDefault();
    }
    //if (!document.activeElement || (!~['textarea','input'].indexOf(document.activeElement.type) && (!document.activeElement.className || !~['comment-simplebox-text'].indexOf(document.activeElement.className)))) {
    if (!isInput()) {
        // NO text input in process =)
        if (window.event && e.keyCode == 37) // left
            if(video.seek(e, false))
                e.preventDefault();
        if (window.event && e.keyCode == 39) // right
            if(video.seek(e, true))
                e.preventDefault();
        if (window.event && e.keyCode == 38) { // up
            var q = document.querySelector("video");
            if (q && !q.paused && !e.shiftKey) {
                q.volume += 0.04;
                e.preventDefault(); }
            else if (e.shiftKey) {
                document.body.scrollTop -= 150;
                e.preventDefault(); }}
        if (window.event && e.keyCode == 40) { // down
            var q = document.querySelector("video");
            if (q && !q.paused && !e.shiftKey) {
                q.volume -= 0.04;
                e.preventDefault(); }
            else if (e.shiftKey) {
                document.body.scrollTop += 150;
                e.preventDefault(); }}
        if (window.event && e.keyCode == 32) // space
            if(video.playPause(e.shiftKey))
                e.preventDefault();
        if (window.event && e.keyCode == 13) // enter
            return video.fullScreen();
        if (window.event && e.keyCode == 33) // pgup
            if (video.pageScroll(true))
                e.preventDefault();
        if (window.event && e.keyCode == 34) // pgdn
            if (video.pageScroll(false))
                e.preventDefault();
        if (window.event && e.keyCode == 119) // NumUp
            if (video.toggleSpeed(false))
                e.preventDefault();
        if (window.event && e.keyCode == 38 && e.ctrlKey) // ^NumUp
            if (video.toggleSpeed(true))
                e.preventDefault();
    }

//    if (window.event && e.keyCode == 121 && !e.shiftKey && !e.ctrlKey && !e.altKey) // f10
//        video.panel();
}

var sidebarBottom = 0;
function _onscroll(e) {
    console.log('scroll');
    clearTimeout(onscrollTimer);
    onscrollTimer = null;
    var s = document.getElementById('watch7-sidebar');
    if (!s) return;
    var c = document.getElementById('watch7-content');
    if (!sidebarBottom) sidebarBottom = getOffset(s).top + s.offsetHeight;
    var h = sidebarBottom - document.body.scrollTop - 35 < 0;
    if (h != (s.style.display == 'none')){
        if (h) {
            s.style.display = 'none';
            c.style.width = 'calc(100% - 100px)'; }
        else {
            s.style.display = '';
            c.style.width = ''; }
        console.log('hide sidebar', h); 
    }
    var l = loader.btn(true);
    if (l && onScreen(l, true) && !loader._update) {
        console.log('---------- auto-click load more');
        l.click();
        video.delayParse(function(){ return document.getElementById("comment-section-renderer-items").children.length}); }
}
var onscrollTimer = null;
function onscroll(e) {
    if (onscrollTimer) clearTimeout(onscrollTimer);
    onscrollTimer = setTimeout(_onscroll, 300);
}

/*function _onclick(e) {
    console.log('click');
    clearTimeout(onclickTimer);
    onclickTimer = null;
}
var onclickTimer = null;
function onclick(e) {
    if (e.which != 1) return;
    if (onclickTimer) clearTimeout(onclickTimer);
    onclickTimer = setTimeout(_onclick, 300);
}*/

console.log('----------------- monkey start! ' + window.location.href);
//setInterval(function(){console.log('aaaa')}, 100);
//setTimeout(function(){console.log('bbbb')}, 10000);
document.addEventListener('keydown', doc_keyUp, false);
document.addEventListener('scroll', onscroll, false);
//document.addEventListener('mousedown', onclick, false);
video.panel(); // init
//document.getElementById('movie_player').focus(); // focus bug fix