Google Images direct links 2

Add direct links to the picture to the Google Image Search results.

// ==UserScript==
///////////////// In case it fails to update in TamperMonkey, visit  https://www.benjamin-philipp.com/fff/userScripts/Google_Images_Direct_Links_2.user.js  directly ////////
// @name		Google Images direct links 2
// @version		2.3.1
// @description Add direct links to the picture to the Google Image Search results.
// @namespace	Google
// @author		Benjamin Philipp <dev [at - please don't spam] benjamin-philipp.com>
// @include		/^https?:\/\/(www\.)*google\.[a-z\.]{2,5}\/search.*tbm=isch.*/
// @run-at		document-start
// @grant		GM_xmlhttpRequest
// @connect		*
// ==/UserScript==


var updateInterval = 1000;
var maxtries = 100;
var selector = ".rg_di.rg_bx a.rg_l:not(.linksdone), #islrg div.isv-r a.wXeWr.islib:not(.linksdone), #islrg .islrc div a.wXeWr.islib:not(.linksdone)";
selector = "img";
var idle = true;
var needsTrustedHTML = false;
var passThroughFunc = function(string, sink){
	return string;
}
var TTPName = "toast";
var TP = {createHTML: passThroughFunc, createScript: passThroughFunc, createScriptURL: passThroughFunc};
try{
	if(typeof window.isSecureContext !== 'unfefined' && window.isSecureContext){
		if (window.trustedTypes && window.trustedTypes.createPolicy){
			if(trustedTypes.defaultPolicy){
				console.log("TT Default Policy exists");
				TP = trustedTypes.defaultPolicy; // Is the default policy permissive enough? If it already exists, best not to overwrite it
			}
			else{
				TP = window.trustedTypes.createPolicy(TTPName, TP);
			}
			console.log("TP is now", TP);
			needsTrustedHTML = true;
		}
		else{
			console.log("Uh-oh");
		}
	}
}catch(e){
	console.log(e);
}
console.log(document.querySelector("#directLinkStyles"));
function updatePage()
{
	if(document.querySelector("#directLinkStyles") == null){
		console.log("TP:", TP);
		let c = document.createElement("STYLE");
		c.id = "directLinkStyles";
		c.innerHTML = trustedHTML("\
		.linkToTarget{\
			box-shadow: 3px 5px 10px rgba(0,0,0,0.5); \
			cursor: default;\
			position: absolute; \
			right:0; top:0; \
			opacity: 0; \
			background-color: rgba(255,255,255,0.5);\
			transition: background-color 0.5s, opacity 0.5s \
		}\
		.failed .linkToTargetlink{\
			color: rgba(230,100,100)!important; \
		}\
		a:hover .linkToTarget{\
			opacity: 0.6; \
		}\
		a:hover .linkToTarget:hover{\
			opacity: 1; \
		} \
		.linksdone:hover .linkToTarget{\
			cursor: pointer;\
		}\
		.linkToTargetLink{\
			color: rgba(155,177,233, 1)!important; \
			font-size: 22pt; \
			display: block; \
			font-weight: bold; \
			text-decoration: none!important;\
			transition: color 0.5s, font-size 0.5s, padding 0.5s; \
		}\
		.temp .linkToTargetLink{\
			color: rgba(200,200,200)!important; \
		}\
		.linkToTargetLink:hover{\
			color: rgba(155,177,233, 1)!important; \
			padding:8px; \
			font-size: 30pt; \
		} \
		html body#yDmH0d div#islmp div#islrg div.islrc div.isv-r a.islib:hover{\
			overflow: visible;\
			z-index: 100;\
		}\
		</style>");
		
		document.querySelector("head").appendChild(c);
	}
	document.querySelectorAll(selector).forEach(function(e){
		if(e.classList.contains("linksdone")) // Why is the selector not working??
		   return;
		var c = document.createElement("DIV");
		c.className="linkToTarget";
		c.innerHTML = trustedHTML("<a class='linkToTargetLink'>↗️</a>");
		e.parentElement.appendChild(c);
		c.querySelector("a.linkToTargetLink").onclick = clickLink;
		e.classList.add("linksdone");
		console.log("Should be done??", e);
	});
}

function clickLink(e){
	e.stopPropagation();
	e.preventDefault();
	var t = e.target;
	
	waitForLink(t, e);
	return false;
}

function waitForLink(t, e){
	var tp = t.parentElement.closest("a");
	console.log(tp);
	var imin = tp.href.indexOf("imgurl=");
	var openInNew = e.ctrlKey || e.which==2;
	if(imin<0)
	{
		var $e = tp;
		var restries = tp.getAttribute("resTries")?tp.getAttribute("resTries")*1+1:1;
		if(restries==1){
			$e.click();
//			tp.querySelector("img")?.click();
			tp.querySelector("img").click();
			setTimeout(function(){
				$e.click();
			}, 200);
			
//			$(tp).find("img").contextmenu();
//			$(tp).trigger({
//				type: 'mousedown',
//				which: 2
//			});
//			waitfor("#islsp a[aria-label='Close']", function(o){
//				$(o).click(); // somehow doesn't close the details view either
//			});
		}
		
//		console.log("try", restries);
		tp.setAttribute("resTries", restries);

		if(tp.getAttribute("resTries")*1>=maxtries){
			console.log("This Link won't come up with a good fragment: " + tp.querySelector("img").src);
			tp.classList.add("linksdone");
			tp.classList.add("failed");
			tp.querySelector(".linkToTarget span").innerHTML = TP.createHTML("x");
			return true;
		}
		
		if(!tp.classList.contains("linkswait")){
			tp.classList.add("linkswait");
			tp.querySelector(".linkToTarget").classList.add("temp");
			tp.querySelector(".linkToTarget a").innerHTML = TP.createHTML("...");
		}
//			console.log("Not ready");
		setTimeout(function(){
			console.log("try again");
			waitForLink(t, e);
		}, 200);
		
		return true;
	}
	else{
		console.log("got link");
		var linkconts = tp.href.substr(imin+7);
		var piclink = linkconts.substr(0,linkconts.indexOf("&"));
		var reflink = linkconts.substr(linkconts.indexOf("imgrefurl=")+10);
		reflink = decodeURIComponent(reflink.substr(0, reflink.indexOf("&")));
		piclink = decodeURIComponent(piclink);
		tp.classList.remove("linkswait");
		let tl = tp.querySelector(".linkToTarget");
		if(tl){
			tl.classList.remove("temp");
			tl.querySelector("a.linkToTargetLink").href = piclink;
		}
		else
			console.log("Link not found?", tp);
		tp.classList.add("linksdone");
		if(e.which == 3)
			return false; // Don't open new tab on right click
		
		if(openInNew){
			window.open(piclink);
		}
		else{
			location.href = piclink;
		}
	}
}

// function waitfor(sel, cb, cbfail, delay, maxtries){
// 	if(delay===undefined)
// 		delay = 500;
// 	if(maxtries===undefined)
// 		maxtries = 50;
// 	var r = document.querySelectorAll(sel);
// 	if(r.length<=0){
// //		console.log("Not loaded yet: " + sel);
// 		if(cbfail!==undefined){
// 			if (cbfail() !== false){
// 				if(maxtries>1)
// 					setTimeout(function(){
// 						waitfor(sel, cb, cbfail, delay, maxtries-1);
// 					}, delay);
// 			}
// 			else{
// //				console.log("cbfail returned false, no retry");
// 			}
// 		}else{
// 			if(maxtries>1)
// 				setTimeout(function(){
// 					waitfor(sel, cb, cbfail, delay, maxtries-1);
// 				}, delay);
// 		}
// 		return;
// 	}
// 	cb(r);
// }

function trustedHTML(string){
	const TT = TP.createHTML(string);
	console.log(typeof TT, TT);
	return TT;
}

setInterval(updatePage, updateInterval);

updatePage();