Google Images direct links 2

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

À partir de 2023-09-13. Voir la dernière version.

Vous devrez installer une extension telle que Tampermonkey, Greasemonkey ou Violentmonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey ou Violentmonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey ou Violentmonkey pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey ou Userscripts pour installer ce script.

Vous devrez installer une extension telle que Tampermonkey pour installer ce script.

Vous devrez installer une extension de gestionnaire de script utilisateur pour installer ce script.

(J'ai déjà un gestionnaire de scripts utilisateur, laissez-moi l'installer !)

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension telle que Stylus pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

Vous devrez installer une extension du gestionnaire de style pour utilisateur pour installer ce style.

(J'ai déjà un gestionnaire de style utilisateur, laissez-moi l'installer!)

// ==UserScript==
// @name		Google Images direct links 2
// @version		2.4.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.*/
// @require		https://openuserjs.org/src/libs/sizzle/GM_config.js
// @run-at		document-start
// @grant		GM_xmlhttpRequest
// @grant		GM_getValue
// @grant		GM_setValue
// @grant		GM_registerMenuCommand
// @grant		GM_openInTab
// @connect		*
// ==/UserScript==

/* eslint no-unused-vars: "off", no-implicit-globals: "off", curly: "off" */
/* globals GM_config, trustedTypes */

var newTabByDefault = true;
var updateInterval = 1000;
var maxtries = 100;
var selector = `.rg_di.rg_bx a.rg_l img:not(.linksdone),
#islrg div.isv-r a.wXeWr.islib img:not(.linksdone),
#islrg .islrc div a.islib img:not(.linksdone)
`;
// selector = "img";
var idle = true;

GM_config.init(
{
	'id': 'MyConfig',
	'title': GM_info.script.name + ' Settings',
	'fields': {
		'newTabByDefault': {
			'label': '<b>Open Links in new tab by default</b> <br /><i>ON:</i> Opens images in new tab; hold <kbd>Ctrl</kbd> to open directly <br /><i>OFF:</i> Opens images directly; hold <kbd>Ctrl</kbd> to open in new tab',
			'type': 'checkbox',
			'default': newTabByDefault
		}
	},
	'css': `
	#MyConfig .field_label{
		font-weight: normal;
		font-size: 13px;
	}
	#MyConfig kbd{
		border: 1px solid #ccc;
		background: #eee;
		border-radius: 3px;
		padding: 1px 3px;
		font-family: consolas, monospace;
	}`
});
GM_registerMenuCommand(GM_info.script.name + ' Settings', function(){
	GM_config.open();
});

// Custom TrustedTypes handling: Google's policies are giving us trouble in some configs.
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 !== 'undefined' && 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);
}
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");
	});
}

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=");
	
	newTabByDefault = GM_config.get("newTabByDefault");
	var openInNew = e.which==2;
	
	if(newTabByDefault){
		if(!e.ctrlKey)
			openInNew = true;
	}
	else{
		if(e.ctrlKey)
			openInNew = true;
	}
	
	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){
			GM_openInTab(piclink);
		}
		else{
			location.href = piclink;
		}
	}
}

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

setInterval(updatePage, updateInterval);

updatePage();