// ==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();