Open Procyon-b opened 4 years ago
google.com.br was not working so i add this:
const lang = { br: 'Ver imagem',
srch = { br: 'Pesquisar por imagem',
When I try google.com.br
with chrome configured to use portuguese/brazil as the main language, I receive google image results in portuguese with this script correctly identifying the language.
The script gets it from the tag <html lang="pt" ...>
:
const pgL=document.documentElement.lang;
Looking at the source code of the results' page, what do you see as the "lang" attribute of the html tag?
I don't think that adding {br: ...}
to the 2 objects has fixed your issue. It's probably that the page had a temporary problem. But I'll wait to see what parameter you get to confirm this.
Appears that way without the const lang = { br: 'Ver imagem', srch = { br: 'Pesquisar por imagem',
and that way with the parameters
Looking at the source code of the results' page, what do you see as the "lang" attribute of the html tag?
source code <!doctype html><html lang="pt"
I don’t know why it happens, but it works when I put the const lang = {br: 'See image' parameters, srch = {br: 'Search by image',
. I always had to put these parameters
Do you see any error message in the console when using the unmodified script? With the logic implemented, even if it can't find a matching definition for the language used, it defaults to "en". But from what I see in your screenshot, it fails to display the modifications. So the script fails somewhere...
What browser are you using ?
Do you see any error message in the console when using the unmodified script?
No
What browser are you using ?
Chromium Versão 74.0.3729.169 (Versão oficial) Arch Linux 32 32 bits
I tested it on firefox 69.0.1 (32-bit) with the code unmodified and it worked.
Do you think that if I clear the cache it could work?
I pretty sure clearing won't solve the issue. The problem is that, whatever the language is, the script should run correctly. The button and the link should appear. In your case they don't when you haven't edited the script. I'll look at it, and make a special version with console comments, to understand what is happening.
Which extension are you using to run the script? Tampermonkey?
How have you installed the script?
Cut and paste from this issue? Or from the raw file in my fork?
I'm wondering if something could be lost/broken in a cut & paste regarding the utf8 chars. This could be the reason, unless you leave all other language strings untouched when adding {br:
.
Which extension are you using to run the script?
Violentmonkey
How have you installed the script?
I installed from the url Google Search "View Image" Button
Cut and paste from this issue? Or from the raw file in my fork?
raw file from your fork
it's weird because it works on firefox but it doesn't work on chromium
I've tried wth Violentmonkey in a test profile, and I have no problem with the script. Really weird. We've already seen users having problem running the script when google was using new/test layouts. But it's not your case, since modifying the script "solves" the problem.
Are there different values for the counter displayed on VM icon with and without your modification?
I can suggest some more tests:
I created a new profile and it worked!
OK, Now, fixing your problem...
Fix for the color of "search by image" link. (darkgray on black background isn't really visible ;) )
Since this is a small fix, I'll update my fork immediately.
// @version 1.5.0.12
look below for lastest version
Thanks man! I hated that Google has removed 2 such a useful things - original opening and size dimensions, and today I've restored both of it using two simple userscripts. Why have I tolerated it all that time?
It is sad, that "updates" not always bring some good stuff, but sometimes ruin old good stuff, but it is great there are people that can bring back what is useful)
I don't know why they are always messing up with their layout and features. After the image page they also changed the text search result blocs layout. I also had to fix that. :)
We've a saying in french, something like "it's changing for changing". (no other purpose than the change itself)
Salut Marc @Procyon-b
This is not working for me with that new "Side Panel" layout on Google. I'm using Violent Monkey in Firefox 77. Could it be the issue where CSP is preventing script injection? VM says the script is active, but no Show button :-(
Best Regards,
Salut @B00ze64 I've tested with FF 77.0.1 and VM 2.12.7, and everything works as expected. What do you call "Side Panel" ? Is it the current layout that you can see in the screenshots above, or has google introduced a new layout?
Salut @Procyon-b, alors suite a ton commentaire, je teste avec un nouveau profil, et ça marche! Ah ben maudit! Alors je re-teste avec mes 2 autres profils et ça marche aussi! Je te dis, hier ça fonctionnait pas, estie! lol. C'est plein de situations comme ça avec Firefox, des fois y'a des trucs qui fonctionnent pas pour aucune raison apparente. Merci de continuer à mettre à jour ton script, c'est pas facile d'en trouver un à jour. Y'a 50 FORKs du script ici, et pas un (sauf le tiens) est gardé à jour. PS: Tu pourrais activer les "Issues" sur ton Fork, tant qu'à utiliser le issue tracker de quelqu'un d'autre. PPS: Le "Side Panel" c'est le "nouveau" layout de Google où l'image apparaît à la droite - pour moi c'est nouveau parce que je fais des recherches d'images seulement quelques fois par année. Allez, merci encore! A+
EDIT: For all English Speakers -> No worries, script works, my bad.
C'est plein de situations comme ça avec Firefox, des fois y'a des trucs qui fonctionnent pas pour aucune raison apparente. Je sais bien que dans chrome l'explication peut être qu'un extension à priorité sur une autre et peut contrecarrer le fonctionnement de l'autre. J'imagine que le même genre de problème est aussi probable dans FF.
J'ai aussi déjà eu (dans chrome) des problèmes (avec tampermonkey par ex.) où redémarrer le navigateur était indispensable pour rétablir le comportement normal.
A noter que, par défaut, chrome a une option qui lui permet de continuer à tourner même après l'avoir fermé (une option dont l'intitulé est du genre "Continue running background apps when Google Chrome is closed"). Et donc, dans ce cas, fermer et redémarrer chrome ne fait pas vraiment ce à quoi on s'attend, puisqu'il n'est pas vraiment arrêté. Tout ça pour dire que FF a peut-être le même comportement. Je n'utilise pas FF en temps normal, et donc je n'ai pas fouillé dans les options.
Merci de continuer à mettre à jour ton script, c'est pas facile d'en trouver un à jour. Y'a 50 FORKs du script ici, et pas un (sauf le tiens) est gardé à jour. PS: Tu pourrais activer les "Issues" sur ton Fork, tant qu'à utiliser le issue tracker de quelqu'un d'autre.
Je me suis dévoué quand j'ai vu que @devunt n'avait pas le temps de s'occuper des mises à jour. :) Je n'ai volontairement pas activé les issues sur mon fork pour garder les contacts centralisés ici, sur le repository d'origine. Mais il est vrai que devunt n'est plus passé ici depuis un certain temps. Et que l'extension, elle, n'est plus mise à jour du tout.
Salut!
C'est exactement ce que je pense, le "Multi-Process" (exécution non-synchronisée) cause des problèmes parce que dans Firefox il y a des endroits où plusieurs extensions peuvent modifier une requête/page (comme par exemple les Headers) et la première qui y touche gagne sur les autres. Ils ont corrigé ça à certains endroits mais pas partout. Il y a d'autres problèmes aussi; Firefox est en retard sur Chrome, et c'est long de faire corriger des bugs; ils travaillent surtout à rattraper Chrome hehe.
Pour ton fork, c'est correct si tu préfères utiliser le repo d'origine, tant qu'à être obligé de changer de nom etc. L'extension n'est même plus sur le site de Mozilla, lol. Il y en a une autre (https://addons.mozilla.org/en-US/firefox/addon/view-image/) mais elle souffre du même problème, c-a-d que l'auteur ne la garde pas tout à fait à jour. Elle ne fonctionne qu'à demie.
Enouka, merci d'être ici, c'est pratique ce bouton View Image! :-)
Fixes to ensure the original full-size image is used. The code in my fork is updated. Those using it don't have to do anything.
// @version 1.5.0.14
Latest version is below
Another variation of the layout has appeared.
// @version 1.5.0.15
Latest version is below
name of a style has changed
// @version 1.5.0.16
Long time no see...
Noticed today that our button wasn't there. Just a classname changed.
// @version 1.5.0.17
Latest version is below
@Procyon-b i think it broke again. please save us. 🙏
also you might as well set the script homepage to your fork. and the update url. you're the man.
@ftc2 you're lucky. I was able to reproduce only with my current cookies. Whenever I tried to trigger this layout variation with other cookies/TLDs the button was added.
I keep the original homepage because issues are here, but I've added the updateurl of my fork. Those who have added the script from that url are already updated automatically.
The fix is as usual just a classname change.
// @version 1.5.0.18
Latest version is below
awesome, thanks!
I keep the original homepage because issues are here, but I've added the updateurl of my fork. Those who have added the script from that url are already updated automatically.
@updateURL
is still missing from your fork though. it's in what you pasted above, but i think you forgot to add it to your repo.
@updateURL is still missing from your fork though. it's in what you pasted above, but i think you forgot to add it to your repo.
It isn't needed because the script is already located at the right place. Every userscripts managers I've tested (3 or 4) uses either the updateURL or the script installation location to check for updates. Am I missing something?
i had no idea! i thought updateURL
was needed for updates.
It's useful when you host the code on different servers and want to direct every update to one copy/server only.
Two new designs for the buttons are currently tested. Here is a new version to handle these cases
// ==UserScript==
// @name Google Search "View Image" Button
// @name:ru Google Search кнопка "Показать в полном размере"
// @name:sl Gumb "Ogled slike" na Google Slikah
// @name:uk Google Search кнопка "Показати зображення"
// @name:lt Google paieškos mygtukas "Rodyti vaizdą"
// @name:pl Przycisk "Pokaż obraz" w wyszukiwarce obrazów Google
// @name:ja Google 検索「画像を表示」ボタン
// @name:ko Google 검색 ‘이미지 보기’ 버튼
// @name:nl Google zoeken "Afbeelding bekijken" knop
// @name:sk Tlačidlo "Zobraziť obrázok" pre Google Search
// @name:tr Google Görseller "Resmi Görüntüle" butonu
// @namespace https://github.com/devunt/make-gis-great-again
// @icon https://raw.githubusercontent.com/devunt/make-gis-great-again/master/icons/icon.png
// @version 1.5.0.19
// @description This userscript adds "View Image" button to Google Image Search results.
// @description:ru Этот скрипт добавляет кнопку "Показать в полном размере" к результатам Google Image Search.
// @description:sl Ponovno prikaže gumb "Ogled slike" na Google Slikah.
// @description:uk Цей скрипт додає кнопку "Показати зображення" до результатів Google Image Search.
// @description:lt Šis vartotojo skriptas prideda mygtuką "Rodyti vaizdą" į Google vaizdo paieškos rezultatus.
// @description:pl Ten skrypt przywraca przycisk "Pokaż obraz" do wyszukiwarki obrazów Google.
// @description:ja この UserScript は Google 画像検索結果に「画像を表示」ボタンを追加します。
// @description:ko 이 유저스크립트는 Google 이미지 검색 결과에 ‘이미지 보기’ 버튼을 추가합니다.
// @description:nl Voegt de "Afbeelding bekijken" knop aan toe aan Google Afbeeldingen.
// @description:sk Toto rozšírenie pridáva tlačidlo "Zobraziť obrázok" do výsledkov vyhľadávania Google Search.
// @description:tr Bu betik Google Görseller arama sonuçlarına "Resmi Görüntüle" düğmesini ekler.
// @author Bae Junehyeon
// @run-at document-end
// @include http*://*.google.tld/search*tbm=isch*
// @include http*://*.google.tld/imgres*
// ==/UserScript==
const lang = {
ar: 'عرض الصورة',
cs: 'Zobrazit obrázek',
da: 'Vis billede',
de: 'Bild ansehen',
en: 'View image',
es: 'Ver imagen',
fi: 'Näytä kuva',
fr: 'Voir l\'image',
he: 'הצג תמונה', // also 'iw'
hu: 'Kép megtekintése',
it: 'Apri immagine',
iw: 'הצג תמונה', // same as 'he'
ja: '画像を表示',
ko: '이미지 보기',
lt: 'Rodyti vaizdą',
nl: 'Afbeelding bekijken',
no: 'Se bilde',
pl: 'Pokaż obraz',
pt: 'Ver imagem',
ru: 'Показать в полном размере',
se: 'Visa bild', // also 'sv'
sk: 'Zobraziť obrázok',
sl: 'Ogled slike',
sv: 'Visa bild', // same as 'se'
tr: 'Resmi Görüntüle',
uk: 'Показати зображення',
zh: '查看原图',
'zh-CN': '查看原图', // also 'zh'
},
srch = {
cs: 'Vyhledat podle obrázku',
da: 'Søg efter billede',
de: 'Zur "Bildersuche"',
en: 'Search by image',
es: 'Buscar por imagen',
fr: 'Recherche par image',
he: 'חפש לפי תמונה', // also 'iw'
hu: 'Keresés kép alapján',
it: 'Ricerca tramite immagine',
iw: 'חפש לפי תמונה', // same as 'he'
ja: '画像を検索',
ko: '이미지로 검색',
nl: 'Afbeelding zoeken',
no: 'Søk med bilde',
pl: 'Wyszukiwanie obrazem',
pt: 'Pesquisar por imagem',
ru: 'Поиск по картинке',
se: 'Fler storlekar', // also 'sv'
sk: 'Vyhľadať podľa obrázku',
sl: 'Iskanje s sliko',
sv: 'Fler storlekar', // same as 'se'
tr: 'Görselle Ara',
zh: '以图搜图',
};
const pgL=document.documentElement.lang;
const localizedViewImage = lang[pgL] || lang[pgL.split('-')[0]] || lang[navigator.language] || lang[navigator.language.split('-')[0]] || lang['en'];
const SBItxt = srch[pgL] || srch[pgL.split('-')[0]] || srch[navigator.language] || srch[navigator.language.split('-')[0]] || srch['en'];
var Btn_1, Btn_2;
var RE=new RegExp('^(?:'+location.origin+')?\/imgres[\?&]imgurl=([^&]*)');
var dataN;
document.querySelectorAll('script').forEach((s)=>{
let c=s.innerText;
if (c.startsWith('AF_initDataCallback') && c.length>100) {
dataN=s;
}
})
function addButton(node) {
if (node.nodeType === Node.ELEMENT_NODE) {
if (node.classList.contains('irc_ris') || node.classList.contains('Y6heUd') || node.classList.contains('BfYA2c') || node.classList.contains('irc_mi')) {
let container;
if (node.classList.contains('Y6heUd') || node.classList.contains('BfYA2c')) container = node;
else container = node.closest('.irc_c');
let inView = container.parentNode.style.display !== "none";
let similarImages = node.querySelectorAll('.rg_l');
if (!similarImages.length) {
let block = container.querySelector('div[jsname="ofUehf"]');
if (block) block.addEventListener('click', function(ev){
if (ev.target.classList.contains('rg_i')) updateLinkAfterClickOnSimilar(ev);
});
}
[].forEach.call(similarImages, (image) => {
image.addEventListener('click', updateLinkAfterClickOnSimilar);
});
let data=dataN.innerText.replace(/^AF_initDataCallback\((.*)\);$/s,"$1");
let findSrc, focus, tbnID, t;
try{
findSrc=((t=container.querySelector(':scope .irc_t .irc_mi, :scope .n3VNCb, :scope .r48jcc')) && t.src) || ((t=container.querySelector(':scope .irc_t .irc_mut')) && t.src);
focus=document.querySelector('.irc-s');
if (!focus) {
tbnID=container.parentNode.dataset['tbnid'];
if (tbnID) focus=document.querySelector('div[data-tbnid="'+tbnID+'"]');
}
if (badImg(findSrc) && focus) {
for (let k of focus.querySelectorAll('a')) {
if (RE.test(k.href)) {
findSrc=unescape(RegExp.$1);
break;
}
}
}
if (badImg(findSrc) && dataN) {
let u= new RegExp('"'+tbnID+'".*?\\[.*?\\[(".*?"),','s').exec(dataN.innerText);
if (u && u[1]) findSrc=unescape(JSON.parse(u[1]));
}
}catch(e){}
if (focus && inView && badImg(findSrc)) {
obsFocus.observe(focus,{
childList: false,
subtree: true,
attributes: true,
attributeFilter: [ "href", "src" ]
});
}
let thumbnail = node.querySelector('.irc_rimask.irc_rist');
let src = bigSrc[findSrc] || findSrc || unescape(thumbnail.querySelector('.rg_l').href.match(/imgurl=([^&]+)/)[1]);
let buttons = container.querySelector('.irc_but_r tr');
// new version
let nv=false;
if (!buttons) {
buttons = container.querySelector('.Qc8zh > .irc_ab');
nv=1;
}
if (!buttons) {
buttons = container.querySelector('.fwCBrd');
nv=2;
}
if (!buttons) {
buttons = container.querySelector('.kEwVtd, .QCk63e');
nv=3;
}
if (!buttons) {
buttons = container.querySelector('[jsname="St5Dhe"]');
nv=4;
}
let button = buttons.querySelector(nv? 'a.mgisga' : 'td.mgisga'),
pn=false;
if (button === null) {
let openButton = buttons.querySelector(nv ? (nv >= 3 ? 'a.ZsbmCf, a.J2oL9c, a.jAklOc, a.uZ49bd, a.wvfN0b' : 'a' ) : 'td');
button = openButton.cloneNode(true);
if ( (nv == 4) && (openButton.parentNode.childNodes.length == 1) ) {
openButton=openButton.parentNode;
button = openButton.cloneNode(true);
pn=true;
}
let sp=button.querySelector(nv ? ( nv >= 3 ? 'div span':'div span:nth-child(2)' ) : 'a span:nth-child(2)');
if (!sp && (nv == 4)) {
button.firstChild.firstChild.innerHTML='<span style="margin: 0 10px; color: var(--uv-styles-color-text-emphasis);"></span>';
sp=button.firstChild.firstChild.firstChild;
}
sp.innerText = localizedViewImage;
sp.style.padding='0';
// remove icon and style
try{sp.parentNode.removeChild(sp.previousElementSibling);}catch(e){}
if (nv==1) sp.className='';
let link = nv && !pn ? button : button.querySelector('a');
link.href = src;
if (!nv) link.className = '';
link.removeAttribute('data-cthref');
link.removeAttribute('jsaction');
link.removeAttribute('data-ved');
button.classList.remove('irc_lth');
button.classList.add('mgisga');
if (nv && button.classList.contains('irc_hol')) button.style='margin-left: 8px;';
if (nv >= 3) openButton.before(button);
else openButton.after(button);
// adding "Search by image"
let lnks = container.querySelector('.irc_b .irc_hd .irc_dsh');
let style = 'margin-left:1em', cls = 'o5rIVb SBIlnk dPO1Qe';
if (!lnks) {
lnks = (lnks=container.querySelector('.irc_ft, .yKbIbb, .Beeb4e')) && lnks.parentNode;
cls = cls.replace(/dPO1Qe/,'');
cls += ' irc_help PvkmDc So4Urb';
style = '';
}
if (lnks) {
let lnkSBI = document.createElement('a');
let RE=/.*[\?&](hl=[^&]+)/.exec(location.search); // catch last &hl=xx parameter
lnkSBI.setAttribute('hrefbase','/searchbyimage?'+(RE?RE[1]+'&':'')+'image_url=');
lnkSBI.setAttribute('target','_blank');
lnkSBI.setAttribute('class',cls);
lnkSBI.setAttribute('style',style);
lnkSBI.innerText= SBItxt;
lnks.appendChild(lnkSBI);
}
}
let link = nv ? button : button.querySelector('a');
link.href = src;
link = container.querySelector('.SBIlnk');
link.href = link.attributes.hrefbase.value + encodeURIComponent(src);
if (inView) {
Btn_1=button;
Btn_2=link;
}
}
}
}
function badImg(u) {
if (!u || u.startsWith('data:') || /^https?:\/\/[^\/]*?\.gstatic\.com\//.test(u)) {
return true;
}
}
function updButton(url,src) {
let u;
if ( ((u=RE.exec(url)) && (u=u[1])) || (u=src) ) {
u=unescape(u);
Btn_1.href=u;
Btn_2.href=Btn_2.attributes.hrefbase.value + encodeURIComponent(u);
}
}
var bigSrc={};
function updateLinkAfterClickOnSimilar({target:node}) {
let src = unescape(node.closest('.rg_l, a').href.match(/imgurl=([^&]+)/)[1]);
let i = node.src;
if (i) bigSrc[i]=src;
let container = node.closest('.irc_c');
let button = container.querySelector('.mgisga');
let link = button.querySelector('a');
if (!link) link = button;
link.href = src;
link = container.querySelector('.SBIlnk');
link.href = link.attributes.hrefbase.value + encodeURIComponent(src);
}
const observer = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
const addedNodes = mutation.addedNodes || [];
[].forEach.call(addedNodes, (newNode) => {
addButton(newNode);
});
});
});
observer.observe(document.body, {
childList: true,
subtree: true
});
var obsFocus = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
updButton(mutation.target.href, mutation.target.src);
});
});
addButton(document.body);
@Procyon-b script seems broken again(checked in FF and Opera), can you update it..?
Two new designs for the buttons are currently tested. Here is a new version to handle these cases
// ==UserScript== // @name Google Search "View Image" Button // @name:ru Google Search кнопка "Показать в полном размере" // @name:sl Gumb "Ogled slike" na Google Slikah // @name:uk Google Search кнопка "Показати зображення" // @name:lt Google paieškos mygtukas "Rodyti vaizdą" // @name:pl Przycisk "Pokaż obraz" w wyszukiwarce obrazów Google // @name:ja Google 検索「画像を表示」ボタン // @name:ko Google 검색 ‘이미지 보기’ 버튼 // @name:nl Google zoeken "Afbeelding bekijken" knop // @name:sk Tlačidlo "Zobraziť obrázok" pre Google Search // @name:tr Google Görseller "Resmi Görüntüle" butonu // @namespace https://github.com/devunt/make-gis-great-again // @icon https://raw.githubusercontent.com/devunt/make-gis-great-again/master/icons/icon.png // @version 1.5.0.19 // @description This userscript adds "View Image" button to Google Image Search results. // @description:ru Этот скрипт добавляет кнопку "Показать в полном размере" к результатам Google Image Search. // @description:sl Ponovno prikaže gumb "Ogled slike" na Google Slikah. // @description:uk Цей скрипт додає кнопку "Показати зображення" до результатів Google Image Search. // @description:lt Šis vartotojo skriptas prideda mygtuką "Rodyti vaizdą" į Google vaizdo paieškos rezultatus. // @description:pl Ten skrypt przywraca przycisk "Pokaż obraz" do wyszukiwarki obrazów Google. // @description:ja この UserScript は Google 画像検索結果に「画像を表示」ボタンを追加します。 // @description:ko 이 유저스크립트는 Google 이미지 검색 결과에 ‘이미지 보기’ 버튼을 추가합니다. // @description:nl Voegt de "Afbeelding bekijken" knop aan toe aan Google Afbeeldingen. // @description:sk Toto rozšírenie pridáva tlačidlo "Zobraziť obrázok" do výsledkov vyhľadávania Google Search. // @description:tr Bu betik Google Görseller arama sonuçlarına "Resmi Görüntüle" düğmesini ekler. // @author Bae Junehyeon // @run-at document-end // @include http*://*.google.tld/search*tbm=isch* // @include http*://*.google.tld/imgres* // ==/UserScript== const lang = { ar: 'عرض الصورة', cs: 'Zobrazit obrázek', da: 'Vis billede', de: 'Bild ansehen', en: 'View image', es: 'Ver imagen', fi: 'Näytä kuva', fr: 'Voir l\'image', he: 'הצג תמונה', // also 'iw' hu: 'Kép megtekintése', it: 'Apri immagine', iw: 'הצג תמונה', // same as 'he' ja: '画像を表示', ko: '이미지 보기', lt: 'Rodyti vaizdą', nl: 'Afbeelding bekijken', no: 'Se bilde', pl: 'Pokaż obraz', pt: 'Ver imagem', ru: 'Показать в полном размере', se: 'Visa bild', // also 'sv' sk: 'Zobraziť obrázok', sl: 'Ogled slike', sv: 'Visa bild', // same as 'se' tr: 'Resmi Görüntüle', uk: 'Показати зображення', zh: '查看原图', 'zh-CN': '查看原图', // also 'zh' }, srch = { cs: 'Vyhledat podle obrázku', da: 'Søg efter billede', de: 'Zur "Bildersuche"', en: 'Search by image', es: 'Buscar por imagen', fr: 'Recherche par image', he: 'חפש לפי תמונה', // also 'iw' hu: 'Keresés kép alapján', it: 'Ricerca tramite immagine', iw: 'חפש לפי תמונה', // same as 'he' ja: '画像を検索', ko: '이미지로 검색', nl: 'Afbeelding zoeken', no: 'Søk med bilde', pl: 'Wyszukiwanie obrazem', pt: 'Pesquisar por imagem', ru: 'Поиск по картинке', se: 'Fler storlekar', // also 'sv' sk: 'Vyhľadať podľa obrázku', sl: 'Iskanje s sliko', sv: 'Fler storlekar', // same as 'se' tr: 'Görselle Ara', zh: '以图搜图', }; const pgL=document.documentElement.lang; const localizedViewImage = lang[pgL] || lang[pgL.split('-')[0]] || lang[navigator.language] || lang[navigator.language.split('-')[0]] || lang['en']; const SBItxt = srch[pgL] || srch[pgL.split('-')[0]] || srch[navigator.language] || srch[navigator.language.split('-')[0]] || srch['en']; var Btn_1, Btn_2; var RE=new RegExp('^(?:'+location.origin+')?\/imgres[\?&]imgurl=([^&]*)'); var dataN; document.querySelectorAll('script').forEach((s)=>{ let c=s.innerText; if (c.startsWith('AF_initDataCallback') && c.length>100) { dataN=s; } }) function addButton(node) { if (node.nodeType === Node.ELEMENT_NODE) { if (node.classList.contains('irc_ris') || node.classList.contains('Y6heUd') || node.classList.contains('BfYA2c') || node.classList.contains('irc_mi')) { let container; if (node.classList.contains('Y6heUd') || node.classList.contains('BfYA2c')) container = node; else container = node.closest('.irc_c'); let inView = container.parentNode.style.display !== "none"; let similarImages = node.querySelectorAll('.rg_l'); if (!similarImages.length) { let block = container.querySelector('div[jsname="ofUehf"]'); if (block) block.addEventListener('click', function(ev){ if (ev.target.classList.contains('rg_i')) updateLinkAfterClickOnSimilar(ev); }); } [].forEach.call(similarImages, (image) => { image.addEventListener('click', updateLinkAfterClickOnSimilar); }); let data=dataN.innerText.replace(/^AF_initDataCallback\((.*)\);$/s,"$1"); let findSrc, focus, tbnID, t; try{ findSrc=((t=container.querySelector(':scope .irc_t .irc_mi, :scope .n3VNCb, :scope .r48jcc')) && t.src) || ((t=container.querySelector(':scope .irc_t .irc_mut')) && t.src); focus=document.querySelector('.irc-s'); if (!focus) { tbnID=container.parentNode.dataset['tbnid']; if (tbnID) focus=document.querySelector('div[data-tbnid="'+tbnID+'"]'); } if (badImg(findSrc) && focus) { for (let k of focus.querySelectorAll('a')) { if (RE.test(k.href)) { findSrc=unescape(RegExp.$1); break; } } } if (badImg(findSrc) && dataN) { let u= new RegExp('"'+tbnID+'".*?\\[.*?\\[(".*?"),','s').exec(dataN.innerText); if (u && u[1]) findSrc=unescape(JSON.parse(u[1])); } }catch(e){} if (focus && inView && badImg(findSrc)) { obsFocus.observe(focus,{ childList: false, subtree: true, attributes: true, attributeFilter: [ "href", "src" ] }); } let thumbnail = node.querySelector('.irc_rimask.irc_rist'); let src = bigSrc[findSrc] || findSrc || unescape(thumbnail.querySelector('.rg_l').href.match(/imgurl=([^&]+)/)[1]); let buttons = container.querySelector('.irc_but_r tr'); // new version let nv=false; if (!buttons) { buttons = container.querySelector('.Qc8zh > .irc_ab'); nv=1; } if (!buttons) { buttons = container.querySelector('.fwCBrd'); nv=2; } if (!buttons) { buttons = container.querySelector('.kEwVtd, .QCk63e'); nv=3; } if (!buttons) { buttons = container.querySelector('[jsname="St5Dhe"]'); nv=4; } let button = buttons.querySelector(nv? 'a.mgisga' : 'td.mgisga'), pn=false; if (button === null) { let openButton = buttons.querySelector(nv ? (nv >= 3 ? 'a.ZsbmCf, a.J2oL9c, a.jAklOc, a.uZ49bd, a.wvfN0b' : 'a' ) : 'td'); button = openButton.cloneNode(true); if ( (nv == 4) && (openButton.parentNode.childNodes.length == 1) ) { openButton=openButton.parentNode; button = openButton.cloneNode(true); pn=true; } let sp=button.querySelector(nv ? ( nv >= 3 ? 'div span':'div span:nth-child(2)' ) : 'a span:nth-child(2)'); if (!sp && (nv == 4)) { button.firstChild.firstChild.innerHTML='<span style="margin: 0 10px; color: var(--uv-styles-color-text-emphasis);"></span>'; sp=button.firstChild.firstChild.firstChild; } sp.innerText = localizedViewImage; sp.style.padding='0'; // remove icon and style try{sp.parentNode.removeChild(sp.previousElementSibling);}catch(e){} if (nv==1) sp.className=''; let link = nv && !pn ? button : button.querySelector('a'); link.href = src; if (!nv) link.className = ''; link.removeAttribute('data-cthref'); link.removeAttribute('jsaction'); link.removeAttribute('data-ved'); button.classList.remove('irc_lth'); button.classList.add('mgisga'); if (nv && button.classList.contains('irc_hol')) button.style='margin-left: 8px;'; if (nv >= 3) openButton.before(button); else openButton.after(button); // adding "Search by image" let lnks = container.querySelector('.irc_b .irc_hd .irc_dsh'); let style = 'margin-left:1em', cls = 'o5rIVb SBIlnk dPO1Qe'; if (!lnks) { lnks = (lnks=container.querySelector('.irc_ft, .yKbIbb, .Beeb4e')) && lnks.parentNode; cls = cls.replace(/dPO1Qe/,''); cls += ' irc_help PvkmDc So4Urb'; style = ''; } if (lnks) { let lnkSBI = document.createElement('a'); let RE=/.*[\?&](hl=[^&]+)/.exec(location.search); // catch last &hl=xx parameter lnkSBI.setAttribute('hrefbase','/searchbyimage?'+(RE?RE[1]+'&':'')+'image_url='); lnkSBI.setAttribute('target','_blank'); lnkSBI.setAttribute('class',cls); lnkSBI.setAttribute('style',style); lnkSBI.innerText= SBItxt; lnks.appendChild(lnkSBI); } } let link = nv ? button : button.querySelector('a'); link.href = src; link = container.querySelector('.SBIlnk'); link.href = link.attributes.hrefbase.value + encodeURIComponent(src); if (inView) { Btn_1=button; Btn_2=link; } } } } function badImg(u) { if (!u || u.startsWith('data:') || /^https?:\/\/[^\/]*?\.gstatic\.com\//.test(u)) { return true; } } function updButton(url,src) { let u; if ( ((u=RE.exec(url)) && (u=u[1])) || (u=src) ) { u=unescape(u); Btn_1.href=u; Btn_2.href=Btn_2.attributes.hrefbase.value + encodeURIComponent(u); } } var bigSrc={}; function updateLinkAfterClickOnSimilar({target:node}) { let src = unescape(node.closest('.rg_l, a').href.match(/imgurl=([^&]+)/)[1]); let i = node.src; if (i) bigSrc[i]=src; let container = node.closest('.irc_c'); let button = container.querySelector('.mgisga'); let link = button.querySelector('a'); if (!link) link = button; link.href = src; link = container.querySelector('.SBIlnk'); link.href = link.attributes.hrefbase.value + encodeURIComponent(src); } const observer = new MutationObserver((mutations) => { mutations.forEach((mutation) => { const addedNodes = mutation.addedNodes || []; [].forEach.call(addedNodes, (newNode) => { addButton(newNode); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); var obsFocus = new MutationObserver((mutations) => { mutations.forEach((mutation) => { updButton(mutation.target.href, mutation.target.src); }); }); addButton(document.body);
Can you also make this compatible for mobile version too?
This is the lastest version. It contains a small fix to display the "search by image link" on the side-panel.
I post this in a new thread to make it easier to locate for newcomers.
The code in my fork has been updated. Those still using this as a source for the userscript in tampermonkey will be updated automatically.
Here is the method to use it that way: Those who want to have the script automatically updated from my fork can use the "Raw" button on the script page. Tampermonkey detects that it is a userscript, and proposes to install it. And it will automatically be updated when a newer version appears.