NOTICE: By continued use of this site you understand and agree to the binding Terms of Service and Privacy Policy.
// ==UserScript== // @name Google Images direct link // @namespace https://github.com/Lorentz83 // @description Adds direct links to images and pages in google image search // @include http*://images.google.*/images* // @include http*://www.google.*/images* // @include http*://www.google.*/webhp* // @include http*://www.google.*/search?* // @include http*://www.google.*/imgres* // @include http*://images.google.*/search?* // @include https://encrypted.google.com/search?* // @version 7.1 // @grant none // @icon https://raw.githubusercontent.com/Lorentz83/userscripts/master/GoogleImageDirectLink/icon.png // @updateURL https://greasyfork.org/scripts/3187-google-images-direct-link/code/Google%20Images%20direct%20link.meta.js // @downloadURL https://greasyfork.org/scripts/3187-google-images-direct-link/code/Google%20Images%20direct%20link.user.js // @supportURL https://github.com/Lorentz83/userscripts // @license GPLv2; http://www.gnu.org/licenses/ // ==/UserScript== /** * This program is free software: you can redistribute it and/or modify * it under the terms of the GNU General Public License as published by * the Free Software Foundation, either version 2 of the License, or * (at your option) any later version. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. * * You should have received a copy of the GNU General Public License * along with this program. If not, see <http://www.gnu.org/licenses/>. */ var addCss = function ( /* args... */) { var css = new Array(arguments.length); for (var i = 0; i < arguments.length; i++) { css[i] = arguments[i]; } var style = document.createElement('style'); style.type = 'text/css'; style.appendChild(document.createTextNode(css.join('\n'))); document.head.appendChild(style); } var parseUrl = function (url) { var pos = url.indexOf('?'); if (pos < 0) { return {}; } var qparms = url.substring(pos + 1); var rawparams = qparms.split('&'); var par = {}; for (var i = 0; i < rawparams.length; i++) { var p = rawparams[i].split('='); var key = decodeURIComponent(p[0]); var value = decodeURIComponent(p[1]); par[key] = value; } return par; } var getImageLinks = function (url) { var param = parseUrl(url); return { toImgHref: param['imgurl'], toPageHref: param['imgrefurl'] }; } var stopEvent = function (event) { event.stopPropagation(); } var fixImageBox = function (div) { if (div.dataset.fixed) { return; } div.dataset.fixed = true; // useful objects var a = div.getElementsByTagName('a')[0]; var span = div.querySelector('span.rg_ilmn'); var links = getImageLinks(a.href); //mirror style to container div.style.height = a.style.height; div.style.width = a.style.width; div.style.left = a.style.left; //replace image anchor var newA = document.createElement('a'); newA.style = a.style; while (a.childNodes.length) { newA.appendChild(a.firstChild); } newA.href = links.toImgHref; a.parentNode.replaceChild(newA, a); a = newA; //create the new container var newContainer = document.createElement('div'); div.appendChild(newContainer); newContainer.className = 'newCont'; newContainer.appendChild(a); newContainer.appendChild(span.parentNode); //create the link to the website var spanLink = document.createElement('a'); spanLink.style.color = '#fff'; spanLink.textContent = span.textContent; spanLink.href = links.toPageHref; while (span.firstChild) { span.removeChild(span.firstChild); } span.appendChild(spanLink); span.addEventListener('click', stopEvent, false); } var waitLink = { _conf: { attributes: true, attributeFilter: ['href'] }, _observer: new MutationObserver(function (mutations) { mutations.forEach(function (mutation) { if (mutation.target.parentNode != null) { waitLink.prepareImageFix(mutation.target.parentNode) } }); }), _watch: function (a) { waitLink._observer.observe(a, waitLink._conf); }, reset: function () { waitLink._observer.disconnect(); }, prepareImageFix: function (div) { var as = div.getElementsByTagName('a'); if (as.length > 0) { if (as[0].href != '') { fixImageBox(div); } else { waitLink._watch(as[0]); } } } } // when the page loads, the first bunch of images are included directly in the html, // the others are loaded asynchronously. This function fixs the first set. var fixInitialImages = function () { var container = document.getElementById('rg_s'); if (container === null) { console.log('Cannot find the image container, is it a visually similar search?'); return; } var divs = container.children for (var i = 0; i < divs.length; i++) { var div = divs.item(i); waitLink.prepareImageFix(div); } } // img preview in google search or visually similar (only links to page) // this function fixes the bunch of images at the top of a search (both visually similar and web) var fixSearchPreview = function(){ var images = document.getElementsByClassName('bicc'); if (images.length) { console.log('This appear to be a visually similar search') } for (var i = 0 ; i<images.length ; i++) { var div = images[i]; var anchor = div.getElementsByTagName('a'); var img = div.getElementsByTagName('img'); if ( img.length == 1 && !div.classList.contains('imgPrev') ) { div.className += ' imgPrev'; //div.style.border = '4em solid black'; var link = img[0].title; var a = document.createElement('a'); a.href = link; a.classList.add('imgSiteLnk'); a.textContent = link.split('/')[2]; div.appendChild(a); } } } var newSearchObserver = new MutationObserver(function (mutations) { mutations.forEach(function (mutation) { if (mutation.target.id=='irc_bg') { // a big preview has been opened (i.e. clicking on a preview in a visually similar search) var hash = parseUrl('?'+document.location.hash); var name = hash['#imgrc']; var els = document.getElementsByName(name); if ( els.length > 0 ) { var redirectTo = els.item(0).parentNode.href; if (redirectTo) { document.location.replace(redirectTo); return; } else { console.log('Error, a big preview has been opened, but no url to redirect has been found'); } } } if (mutation.target.id === 'rg_s') { // just other images have been loaded for (var i = 0; i < mutation.addedNodes.length; i++) { var newNode = mutation.addedNodes.item(i); if (newNode.classList && newNode.classList.contains('rg_el')) { waitLink.prepareImageFix(newNode); } } } if (mutation.target.id === 'rg') { // a new search has been done waitLink.reset(); fixInitialImages(); fixSearchPreview(); } }); }); // normal usage var biggerContainer = document.getElementById('center_col'); newSearchObserver.observe(biggerContainer, {childList: true,subtree: true}); fixInitialImages(); fixSearchPreview(); // visually similar search img preview (oly links to image) // these are the small images aside the page snippets var similars = document.querySelectorAll('div#ires div.th a'); for (var i = 0 ; i < similars.length ; i++){ var a = similars[i]; var href = getImageLinks(a.href); var newA = document.createElement('a'); newA.href = href.toImgHref; newA.appendChild(a.firstChild); a.parentNode.replaceChild(newA, a); } addCss( '.newCont { min-height: 30px; position: relative; height:100%; overflow: hidden; }', '.newCont>a { display: block; width: 100%; text-align: center; }', '.newCont>a>img { display: inline-block; }', '.newCont > a :not(img) { display: none; visibility: hidden; }', '.newCont .rg_ilmbg { display: none; left:0; }', '.newCont:hover .rg_ilmbg { display: block; }', '.newCont .rg_anbg, .newCont .rg_an { display: block; visibility: visible; text-align: left;}', 'a.imgSiteLnk {', ' background-color: rgba(0, 0, 0, 0.77);', ' bottom: 0;', ' color: #fff !important;', ' display: block;', ' line-height: normal;', ' position: absolute;', ' width: 100%; ', ' display: none;', ' overflow: hidden; text-overflow: ellipsis; white-space: nowrap;', '}', '.imgPrev:hover .imgSiteLnk { display: block }' );