slow! / Simple Video Audio Blocker

// ==UserScript==
// @name Simple Video Audio Blocker
// @version 1.7.2
// @description Block loading of videos/audio (flash or html5) at the site being visited.  Click to enable once, alt-c to enable for site permanently.
// @include *
// @license     GPL-3.0
// @updateURL https://openuserjs.org/meta/slow!/Simple_Video_Audio_Blocker.meta.js
// @run-at   document-start
// @require     https://code.jquery.com/jquery-3.2.1.js
// @require     https://code.jquery.com/ui/1.12.1/jquery-ui.js
// @require     https://raw.githubusercontent.com/SloaneFox/code/master/gm4-polyfill-1.0.1.js
// @require     https://raw.githubusercontent.com/SloaneFox/code/master/sfs-utils-0.1.4.js
// @grant       GM_getValue
// @grant       GM_setValue
// @grant       GM.getValue
// @grant       GM.setValue
// @grant       GM_registerMenuCommand
// ==/UserScript==

try{
	console.log("Start of svab script, document.readyState:",document.readyState,"vids?:",document.getElementsByTagName("video").length);
	var allow_site, pagekey, menu, orig_vol=0.33;
	if (!environInit(main.bind(this))) document.addEventListener("DOMContentLoaded",main);
	async function main(e) {try{
		await init_globs();
		if(allow_site) { console.info("Site has previously been given permission to run videos."); setupUI("allowed"); return; }
		var vids=$("video");                   // See mdn obj HTMLMediaElement.
		vids.each(pauseVideo);
		log("Handle vids",document.readyState,"#vids",vids.length);
		if(vids.length) {
			setupStyle();
			setupUI("vids");
			let doc=$(document);
			doc.keydown(function(e){
				if(e.which==27)  {
					$(".svab-overlay").click();
					doc.off("keydown");
				}
			});
		}
		vids.each(blockVids);
	} catch(e){logError("Error in main()",window.parent==window);} };
	
	function blockVids(i,vid) {
		var jvid=$(vid);
		//log("Vid readyState:",vid.readyState,"Vid i=",i,objInfo(jvid),", prev:",objInfo(jvid.prev()),", next",objInfo(jvid.next()),"src",jvid.attr("src"));
		jvid.on("playing volumechange",function(e) {try{
			this.pause();
      var vol=this.volume;
      log("Playing/vol events",vol);
			if(vol!=0) orig_vol=vol;;
			pauseVideo(0,this);
		} catch(e){logError("playing event handler",e);}	});
		overlayVid(jvid);
	}; 

	function pauseVideo(i,v) {
    //$(v).on("playing",e=>v.pause());
    v.volume=0;
		v.autoplay=false;
		v.defaultMuted=true;
		var timeranges=v.seekable, nRanges=timeranges.length;
		if(v.readyState<3) {return;}                                                         // needs 3 to be playable, that at at min 2 frames.
		v.pause();
		v.currentTime=v.duration-1;
		log("pauseVideo().  Got timeranges",timeranges,"len",nRanges, "readystate:",v.readyState,"Video duration/seekend",v.duration,"/",v.seekable.end(nRanges-1));            // duration and end same, a float in seconds
	}
	function overlayVid(jv,v=jv[0]) {
		jv.addClass("svab-target");
		//log("is parent visible:",jv.parent().is(":visible"));
		jv.parent().addClass("svab-container");
		jv.after("<div class=svab-overlay/>");
		var overlay=$(".svab-overlay");
		overlay.click({jv:jv,v:v},clear);
		overlay.on("mouseover mouseout mouseenter mousemove",e=>false);
		jv.parentsUntil("body").each((i,el)=>{ 
			var jel=$(el);
			var  opacity=jel.css("opacity"), width=jel.width(),height=jel.height(), changed;
			if(opacity!=1 ) { jel.css("opacity",1); changed=true;}
			if(width==0||height==0) { jel.width("90%");jel.height("90%"); changed=true; }
			if(changed) { 
				jel.attr("svab_change",opacity+"-"+width+"-"+height); 
				//log("changed",opacity,width,height,jel[0]);
			}
		});
	}
	function clear (e){try{
		var jv=e.data.jv,v=e.data.v;
		//log("Click on overlay. this is:", this," e ",e,"vol:",v.volume);
		jv.off("playing volumechange");
		v.currentTime=0;
		v.muted=false;
    v.volume=orig_vol;
		setTimeout(x=>v.play(),1000); // why?
		jv.removeClass("svab-target");
		jv.parent().removeClass("svab-container");
		$(this).remove(); 
		jv.click();
	} catch(e){logError("clearing block",e);}}
	
	function setupStyle() {
		
		var img="data:image/gif;base64,R0lGODlhFgAWAOfQAAABAAACAAAHCg4HBRoeICEjICIkITJETj1CRDZESTNFTzRGUEFFRzlHTDZIUjdJUzhKVDpLVjtNV0BOUz1PWUlNTz5QWj9RW0FTXUZUWkNVX0RWYE9UVkRXYUpYXkdZZExbYU1cYktdaE9eY05ga09hbFJhZlNiZ01jc1FjbVRjaFZkalRncVNqeltpb2NoaltqcE9tfFFvfl5tc1dufmdrblxueV1velRygWRzeV10hGV0el91hmZ1e2B2h2d2fHB0d1p5iFt6iWZ4g2p5f2h6hWx7gXB/hXGAhnh/h3KBh3uAg3qBiXSDiXGEj3WEinaFi3CGl3eGjHuKkH6KioKJkX2MknqNmXuOmn+OlICPlYGQloOSmIaSk4STmYWUmoaVm4eWnIiXnYSYo4mYnpKXmYqZoIaapYuaoYibpoyboo2co5Obo46epI+fpZCgppGhp5WhopOjqZSkqpilpZOmspamrJenrZqqsJursZyssp2ttKOstJ6utZ+vtqGwt6KxuKOzuaqyuqS0uqW1u66zta21vae3vbG2uK+3v6m5v7C4wKq6wLO4u7G5wq+8va29xLa7vrO8xK6+xbG+v7W+xrTAwba/x7m/wbnBybzBw73CxLXFy77Dxb/ExrfHzcDFyLjIzsLHysPIy8DJ0cTJzMXKzcTN1cfNz8bO1snO0MrP0cjQ2MvQ0snR2szR1MrS283S1c7T1s/U19DV2NHX2dLY2tTZ29Xa3Nbb3dfc39jd4Nne4drf4tvg49zi5N/k5uDl6OPo6+Tp7OXq7ebs7uft7+nu8Ovw8+7w7ezx9PL08fP18vD2+Pb49Pf59v///////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////////yH5BAEKAP8ALAAAAAAWABYAAAj+AP8JHCgQVy1WqUJNIsiQ4a1dwYYVE8aLlaI6DQmykjXMmbNlypAZKwbs05goGTmxUvZMmTFhwHzx2qWrFyksQRgqIuWM2TFhzXjdqiXrVatVqzo58UEQEDFmxoLx4mDrVyxVpkSB8qQJD4+BaVI5KybVVwADhWppzVQpUiJBWGgIPHOMWDBfuHYFCDBgCS1PlhYZGqTHzY1/QvIku4trlq29eytMqkQIkJ47bIaw0HGImK9ctV7Jgry3AB1IevDIEVMkBY5JwHLRioVqFem9AmromdOGyxASMgzxovVKlShTt/cy0POGjJUcImLImdUK1ahOoJIDCfRGDZcnLj6ytLhSapTWS5lIE6jyp42aMFOMmOjwzwYiTJssPZIEGcEdPG2QAUYWSsxA3z8oWNHIIoscwsheL+wWYBhbSLHDCBcMlIIYfPzxhx4BUEGIHGsIqAUUP6hAAUEisFBGHHbYwcQdcJTIhRVN7LCCBREwtEEJSXTxhRtheKHFFE0QMUMIEzyQEQYauGCEEkocYUQPM5yQAQQNZDSQBBZ4AMIIIGQwgQMJeNmQAw4soMABaWYUEAA7";
		var svab_style=GM_addStyle(`
			.svab-container             { width: 100%;height: 100%; position: relative !important; z-index:2147483635 !important;}
			.svab-target, .svab-overlay { width: 100%;  height: 100%;  position: absolute;  top: 0;  left: 0; z-index:2147483640; }
			.svab-overlay               { z-index: 2147483647 !important; } 
        `);
		if(svab_style) svab_style.id="svab-style"; else log("Old addStyle",GM_addStyle.toString());
		GM_addStyle(`
		.svab-overlay { 
						background:url(`+img+`); border:6px double silver; box-sizing: border-box;
						min-width:50px;min-height:50px;
						background-repeat: no-repeat;background-position: center; cursor:pointer;
						background-color: #381714; display: inline-block;
					  }
    `);	
		// Outline of HTML:
		// <div class="svab-container">
		//   <div class="svab-target">a</div>
		//   <div class="svab-overlay background=..."> </div>
		// </div>

	} //End setupStyle()

	function setupUI() {
		menu=GM.registerMenuCommand("Toggle video blocking for website [on]",function(){try{
			allow_site^=true;
			GM.setValue(pagekey,allow_site);
			if(allow_site) $(".svab-overlay").click();
			else $("video").each(blockVids);
			setLabel();
		} catch(e){logError("toggle vid",e);} }); 
		setLabel();
		// GM.registerMenuCommand("Adjust",async function(){
		// 	if (!this.reply) this.reply=await GM.getValue("adjust_reply","");
		// 	while(true) {
		// 		var reply=prompt("Give cmd",this.reply||"");
		// 		if(!reply) break;
		// 		alert(eval(reply));
		// 		this.reply=reply;
		// 		GM.setValue("adjust_reply",reply);
		// 	}
		// });
	}

	function setLabel() {
		if(menu && menu.tagName) {
			var m=$(menu), label=m.attr("label");
			label=label.replace(/\[.*/, allow_site? "[off]." : "[on].");
			m.attr("label",label);
		}
	}

	async function init_globs() {
		pagekey=location.host;
		allow_site=await GM.getValue(pagekey,false);
	}
} catch(e){ console.log("SVAB script",e);}

// function fastEvent() {
// 	$("video").each((i,el)=>{
// 		el.defaultMuted=true;el.volume=0; el.autoplay=false; el.pause();
// 		el.addEventListener("playing",function(e){this.pause();});
// 		el.addEventListener("volumechange",function(e){
// 			if(this.volume==0) return;
// 			this.volume=0; this.pause();
// 			log(this,"=this========== Volume changed to:",v,this.volume); //usu. vol changes to 1.
// 		});
// 	});
// 	console.log("DOMContentLoaded event #vids:",$("video").length);
// }

function environInit(cback) { // returns false if GM environment is there, otherwise it calls main when ready and immediately returns true.
	this.plat_chrome=false; this.plat_msedge=false;        //chrome standalone, ie, not under tamper in chrome.	// this.plat_msedge=/Edge[\d./]+$/i.test(navigator.userAgent);
	if (/Chrome/.test(navigator.userAgent)) this.plat_chrome=true;
	this.plat_mac = /^Mac/.test(navigator.platform);

	try { this.nonGMmode= (typeof GM == "undefined"); } // || "Barychelidae"!=GM_getValue("arachnoidal","Barychelidae"); }
	catch(e) { this.nonGMmode=true; }; //eg, chromium stadalone

	//this.nonjQ = !window.jQuery || parseFloat(jQuery.fn.jquery) < 3.1;
	
	if (nonGMmode){ // chromium bare, ie, w/o tamper.
		console.info("SVAB userscript in non GM_ mode at "+location.href, "typeof GM:",typeof GM, "nonGMmode",nonGMmode);
		this.unsafeWindow=window;
		this.old_GM_getValue=this.GM_getValue;
		try { localStorage["anothervariable"]=32; }	catch(e) {
			window.nostorage=true;
			if(!iframe) console.error("No local storage, no GM storage, use Tampermonkey to include this script on page:",location.href);
			window.localStorage={};
		}
		if(!window.nostorage) console.log("Have local storage",localStorage.anothervariable);
		this.GM_getValue=function(a,b) { return localStorage[a]||b; };
		this.GM_setValue=function(a,b) { localStorage[a]=b; };
		this.GM_getResourceURL=function(url) {
			var ext="Dbl"; if (url.endsWith("Orig")) ext=".orig"; else if (url.endsWith("Xsm")) ext="ExSm"; else if (url.endsWith("Trpl")) ext="Trpl";
			return "https://raw.githubusercontent.com/SloaneFox/imgstore/master/whiteCurtains"+ ext +".jpg";
		};
		//this.GM_registerMenuCommand=x=>null;
		this.GM_addStyle=function(cssSheet) { $("head").append("<style>"+cssSheet+"</style>"); };
		this.uneval=function(x) { return "("+JSON.stringify(x)+")";  }; //Diff is that uneval brackets string and json excludes code only data allowed in json.
		var xhr_queue=[], xhr=new XMLHttpRequest();
		xhr.onload=x=> { //arrow function means this remains window not xhr (as a function would).
			console.log(xhr.responseURL,"onload to eval in window, jQuery in window? ",!!window.jQuery,!!window.$,!!this.jQuery);
			var synop=(xhr.response||"").substr(0,40);
			try {
				eval.call(window,xhr.response); } catch(e) {  console.error("Can't eval Error:"+e,".  Response:",xhr.response?xhr.response.substr(0,60)+"[60chars]":"No response text",x,xhr,", Queue:",xhr_queue); }
			if (xhr_queue.length) {  xhr.open('GET', xhr_queue.shift()); xhr.send(); }
			else cback(); //////////////////
//			else if (!iframe) main.call(window); //////////////////
		};
		xhr.onerror=e=> {
			console.log("W/e XHR Error: "+e,", E:",e,"XHR:",xhr,"After error queue:",xhr_queue);
			if (xhr_queue.length) xhr.open('GET', xhr_queue.shift()); xhr.send();
		};
		var jq_versions_prior={ 
			core: parseFloat(this.$ && this.$.fn && this.$.fn.jquery) || 0,
			ui: parseFloat(this.$ && this.$.ui && this.$.ui.version) || 0 
		};
		
		if(jq_versions_prior.core < 1.7)
			xhr_queue.push("https://code.jquery.com/jquery-1.7.2.js");
		if(jq_versions_prior.ui < 1.12)
			xhr_queue.push("https://code.jquery.com/ui/1.12.1/jquery-ui.js");
		xhr_queue.push("https://raw.githubusercontent.com/SloaneFox/code/master/gm4-polyfill.js");
		xhr_queue.push("https://raw.githubusercontent.com/SloaneFox/code/master/gm-popup-menus-1.3.7.js");
		xhr_queue.push("https://raw.githubusercontent.com/SloaneFox/code/master/sfs-utils-0.1.4.js");
		xhr.open('GET', xhr_queue.shift()); xhr.send();
		return true; 
	} else return false;              //if (nonGM || nonJQ)
}//End environInit()