diff --git a/gis-vib.user.js b/gis-vib.user.js index 3212606..016fb68 100644 --- a/gis-vib.user.js +++ b/gis-vib.user.js @@ -12,7 +12,7 @@ // @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.8 +// @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. @@ -90,22 +90,52 @@ 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('irc_mi')) { - let container = node.closest('.irc_c'); + 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 findSrc; + + let data=dataN.innerText.replace(/^AF_initDataCallback\((.*)\);$/s,"$1"); + + let findSrc, focus, tbnID, t; try{ - findSrc=container.querySelector(':scope .irc_t .irc_mi').src || container.querySelector(':scope .irc_t .irc_mut').src; - let focus=document.querySelector('.irc-s'); - if (focus) { - let RE=new RegExp('^(?:'+location.origin+')?\/imgres[\?&]imgurl=([^&]*)'); + 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); @@ -113,31 +143,70 @@ function addButton(node) { } } } + + 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 = findSrc || unescape(thumbnail.querySelector('.rg_l').href.match(/imgurl=([^&]+)/)[1]); + 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=true; + 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; - let button = buttons.querySelector(nv? 'a.mgisga' : 'td.mgisga'); if (button === null) { - let openButton = buttons.querySelector(nv ? 'a' : 'td'); + let openButton = buttons.querySelector(nv ? (nv >= 3 ? 'a.ZsbmCf, a.J2oL9c, a.jAklOc, a.uZ49bd, a.wvfN0b' : 'a' ) : 'td'); button = openButton.cloneNode(true); - let sp=button.querySelector(nv ? 'div span:nth-child(2)' : 'a span:nth-child(2)'); + 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=''; + sp=button.firstChild.firstChild.firstChild; + } sp.innerText = localizedViewImage; + sp.style.padding='0'; // remove icon and style - sp.parentNode.removeChild(sp.previousElementSibling); - sp.className=''; + try{sp.parentNode.removeChild(sp.previousElementSibling);}catch(e){} + if (nv==1) sp.className=''; - let link = nv ? button : button.querySelector('a'); + let link = nv && !pn ? button : button.querySelector('a'); link.href = src; if (!nv) link.className = ''; link.removeAttribute('data-cthref'); @@ -148,36 +217,65 @@ function addButton(node) { button.classList.add('mgisga'); if (nv && button.classList.contains('irc_hol')) button.style='margin-left: 8px;'; - openButton.after(button); + 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'; + let style = 'margin-left:1em', cls = 'o5rIVb SBIlnk dPO1Qe'; + + if (!lnks) { - lnks = container.querySelector('.irc_ft').parentNode; - cls += ' irc_help'; + lnks = (lnks=container.querySelector('.irc_ft, .yKbIbb, .Beeb4e')) && lnks.parentNode; + cls = cls.replace(/dPO1Qe/,''); + cls += ' irc_help PvkmDc So4Urb'; style = ''; } - 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); + + 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').href.match(/imgurl=([^&]+)/)[1]); + 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'); @@ -202,4 +300,10 @@ observer.observe(document.body, { subtree: true }); +var obsFocus = new MutationObserver((mutations) => { + mutations.forEach((mutation) => { + updButton(mutation.target.href, mutation.target.src); + }); + }); + addButton(document.body);