Skip to content

Instantly share code, notes, and snippets.

@ner00
Forked from bijij/viewimage.user.js
Last active June 15, 2024 15:11
Show Gist options
  • Save ner00/ec9ae47e202b8e99f19be44a5af6baf3 to your computer and use it in GitHub Desktop.
Save ner00/ec9ae47e202b8e99f19be44a5af6baf3 to your computer and use it in GitHub Desktop.
Userscript version of the View Image extension
// ==UserScript==
// @name View Image
// @namespace https://github.com/bijij/ViewImage
// @version 3.7.0.15
// @description Re-implements the Google Images' "View Image" and "Search by Image" buttons.
// @author Joshua B
// @icon data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAADAAAAAwCAYAAABXAvmHAAAFdElEQVRoge2YX2xTVRzHv7ejc8BGmuAYwQXHgxmEIDVqIiEmHULUxIcaffShE2YMgdjBgwRM4HHu5ZpofGDorfpAjA8j0ZjxZxbcwERZWOKTPhjGxv51W9vb293/5/hw1/Z299ze27WgJPs2be89f379/M45v3N+t8C61rWuJ1qcW0X6zIkIR8FTRQ5TVQUIASi1KgvfBa3c02J5qX7r1z+U/cZi7F2K1e2Kt7byognrIvHcCZw+f8TBu4EFr997K2L89U8yPwg2eBl/eR3LCbvI4gKj7yoHVtm42HkaI00HmPYCzEJD4jfs+BMbD00yO7nBVyd/fQY6T2Nk+xHXeuYMEGMpDACNezIAKB4O7ag4vaXRZ5fbtWiS8oKyWbVsb23gfMG7OgBTLkI07skgKAZ6Z29tG2c0dLdssItThHS5tevYtZNvyKTDyEsY2H0KI22V4QGXINZ/bbcNHQU4riv46tRNT2s1KP3RUYHMz8VINuuAL8AMfdzs4GXGgNWl8H70Ssd7LHhRxMBua9kQTSqSAO5h5uLA41M63iOQuVkLvvMURrYfBlGzMOVFxpJ1qoIDj34WrJGfjZGcBT+6Am9IM4kNLTt7/diosIQerYrwooiBzl6Mbj8McwV++NOXuv3aYe9CBRUWnumypaxRdvhLnacw2vYaE97PMLIdWNPB5E/peI9AUiX4ERd4vzgeQVzfGFgNv9ZlY5fHNlo//RZ9IzIzNVUOr9QGD/jaRuvjyIErQzfTWan7s53vY7TNGnldmnaFN/JT0LMPoGUnoIsT0LMTTLvsk/hWWzk14bqCXbN1OYmPnBmLccGNgqkvJ4b71j7yBT32g+x634sJoue76gEP+N6FXJ971qQbfS/XLa/6z1OJWuVykK2egfocZPFv8hcMwu3/onvT215t3/s8FzG5QNKOdPnkZr/ZaP0V/y4fTS/j/IJEoye/XY57tV+QgCWJYtH2ZslHOu29jdJ7kZA5dsgV6sPkmY6ljT8KqRyFKFPklikfF6Swp13HhVN1mQHTMAepnuGNsUiMVa8adHCC+ymktCZAAaRyFMtmYDAupEO1/nbN6bT+R4SnylSEyvfxVbaN77l2tmxkj944J0znU2FCCbTmO1BaEyAEmM+SDo08JXgSeiyAmtJp424kyunzcRhZ9Ev7cDndGFKonowlL4QAoGf4bCwlL8byulLcmbXm25BbBagGsJCn0ZNChXigzEs/DhR6UddUUPs9EoYpCVSdQb+0D1fVdhBK8DA/H+IMOXns+icRUV/mlxTRBmHZ0lvuQG4VIMoUokL54x7xUGk42Q5UAAesoG2AKlD5fqhfeh5X1fYioE50TEpzYYWoyVlpobjGqQ2DgkJrsWYilaNQa4gHn8lc+TlgmuCJPBHuz+3FkPoM6MqrIMXQcF98CJMSJnxBevNt5LcKSGVJh+oSD14P9T4PspLE24diDyanYpcyu3BTexqAWuxS3os6rBRLbBUmhmEQEYHpd6LHL87HvvxgW8KbwtMBd205+EsCQAL4u9quFXQFwLmyEgOlDKzSE1nVM/C45fV0+79O5qiPbdTnDNQ3na5WlSaB6YCicWhqLHX7nhwMH7v+QgUzzmy11vxVnLsWFh+8XtqFDIXZzsUBoClode2T9uMu9ywPLNlaUNtnZTH3IpeOZW23XIW8bRJN88cAAKQaBzL5wHhoMwn3SfsxpLYDSLvAOAgqQ7HuqVsdBVpGAQBNs90gSob5XynTAUkO9J6b2Jsc3bQDCFQPXS24s750rW0egRHMokF7k/kM7Rqdr/DRCAlQnmsMhLlgwNqvPH1xNnCU0NWoziUGACAURKOgijlOG9A93vuzr3+r17WudT1h+hcMcjsg9ZBlWQAAAABJRU5ErkJggg==
// @run-at document-end
// @match *://*.google.com/search*tbm=isch*
// @match *://*.google.ad/search*tbm=isch*
// @match *://*.google.ae/search*tbm=isch*
// @match *://*.google.com.af/search*tbm=isch*
// @match *://*.google.com.ag/search*tbm=isch*
// @match *://*.google.com.ai/search*tbm=isch*
// @match *://*.google.al/search*tbm=isch*
// @match *://*.google.am/search*tbm=isch*
// @match *://*.google.co.ao/search*tbm=isch*
// @match *://*.google.com.ar/search*tbm=isch*
// @match *://*.google.as/search*tbm=isch*
// @match *://*.google.at/search*tbm=isch*
// @match *://*.google.com.au/search*tbm=isch*
// @match *://*.google.az/search*tbm=isch*
// @match *://*.google.ba/search*tbm=isch*
// @match *://*.google.com.bd/search*tbm=isch*
// @match *://*.google.be/search*tbm=isch*
// @match *://*.google.bf/search*tbm=isch*
// @match *://*.google.bg/search*tbm=isch*
// @match *://*.google.com.bh/search*tbm=isch*
// @match *://*.google.bi/search*tbm=isch*
// @match *://*.google.bj/search*tbm=isch*
// @match *://*.google.com.bn/search*tbm=isch*
// @match *://*.google.com.bo/search*tbm=isch*
// @match *://*.google.com.br/search*tbm=isch*
// @match *://*.google.bs/search*tbm=isch*
// @match *://*.google.bt/search*tbm=isch*
// @match *://*.google.co.bw/search*tbm=isch*
// @match *://*.google.by/search*tbm=isch*
// @match *://*.google.com.bz/search*tbm=isch*
// @match *://*.google.ca/search*tbm=isch*
// @match *://*.google.cd/search*tbm=isch*
// @match *://*.google.cf/search*tbm=isch*
// @match *://*.google.cg/search*tbm=isch*
// @match *://*.google.ch/search*tbm=isch*
// @match *://*.google.ci/search*tbm=isch*
// @match *://*.google.co.ck/search*tbm=isch*
// @match *://*.google.cl/search*tbm=isch*
// @match *://*.google.cm/search*tbm=isch*
// @match *://*.google.cn/search*tbm=isch*
// @match *://*.google.com.co/search*tbm=isch*
// @match *://*.google.co.cr/search*tbm=isch*
// @match *://*.google.com.cu/search*tbm=isch*
// @match *://*.google.cv/search*tbm=isch*
// @match *://*.google.com.cy/search*tbm=isch*
// @match *://*.google.cz/search*tbm=isch*
// @match *://*.google.de/search*tbm=isch*
// @match *://*.google.dj/search*tbm=isch*
// @match *://*.google.dk/search*tbm=isch*
// @match *://*.google.dm/search*tbm=isch*
// @match *://*.google.com.do/search*tbm=isch*
// @match *://*.google.dz/search*tbm=isch*
// @match *://*.google.com.ec/search*tbm=isch*
// @match *://*.google.ee/search*tbm=isch*
// @match *://*.google.com.eg/search*tbm=isch*
// @match *://*.google.es/search*tbm=isch*
// @match *://*.google.com.et/search*tbm=isch*
// @match *://*.google.fi/search*tbm=isch*
// @match *://*.google.com.fj/search*tbm=isch*
// @match *://*.google.fm/search*tbm=isch*
// @match *://*.google.fr/search*tbm=isch*
// @match *://*.google.ga/search*tbm=isch*
// @match *://*.google.ge/search*tbm=isch*
// @match *://*.google.gg/search*tbm=isch*
// @match *://*.google.com.gh/search*tbm=isch*
// @match *://*.google.com.gi/search*tbm=isch*
// @match *://*.google.gl/search*tbm=isch*
// @match *://*.google.gm/search*tbm=isch*
// @match *://*.google.gr/search*tbm=isch*
// @match *://*.google.com.gt/search*tbm=isch*
// @match *://*.google.gy/search*tbm=isch*
// @match *://*.google.hk/search*tbm=isch*
// @match *://*.google.com.hk/search*tbm=isch*
// @match *://*.google.hn/search*tbm=isch*
// @match *://*.google.hr/search*tbm=isch*
// @match *://*.google.ht/search*tbm=isch*
// @match *://*.google.hu/search*tbm=isch*
// @match *://*.google.co.id/search*tbm=isch*
// @match *://*.google.ie/search*tbm=isch*
// @match *://*.google.co.il/search*tbm=isch*
// @match *://*.google.im/search*tbm=isch*
// @match *://*.google.co.in/search*tbm=isch*
// @match *://*.google.iq/search*tbm=isch*
// @match *://*.google.is/search*tbm=isch*
// @match *://*.google.it/search*tbm=isch*
// @match *://*.google.je/search*tbm=isch*
// @match *://*.google.com.jm/search*tbm=isch*
// @match *://*.google.jo/search*tbm=isch*
// @match *://*.google.jp/search*tbm=isch*
// @match *://*.google.co.jp/search*tbm=isch*
// @match *://*.google.co.ke/search*tbm=isch*
// @match *://*.google.com.kh/search*tbm=isch*
// @match *://*.google.ki/search*tbm=isch*
// @match *://*.google.kg/search*tbm=isch*
// @match *://*.google.co.kr/search*tbm=isch*
// @match *://*.google.com.kw/search*tbm=isch*
// @match *://*.google.kz/search*tbm=isch*
// @match *://*.google.la/search*tbm=isch*
// @match *://*.google.com.lb/search*tbm=isch*
// @match *://*.google.li/search*tbm=isch*
// @match *://*.google.lk/search*tbm=isch*
// @match *://*.google.co.ls/search*tbm=isch*
// @match *://*.google.lt/search*tbm=isch*
// @match *://*.google.lu/search*tbm=isch*
// @match *://*.google.lv/search*tbm=isch*
// @match *://*.google.com.ly/search*tbm=isch*
// @match *://*.google.co.ma/search*tbm=isch*
// @match *://*.google.md/search*tbm=isch*
// @match *://*.google.me/search*tbm=isch*
// @match *://*.google.mg/search*tbm=isch*
// @match *://*.google.mk/search*tbm=isch*
// @match *://*.google.ml/search*tbm=isch*
// @match *://*.google.com.mm/search*tbm=isch*
// @match *://*.google.mn/search*tbm=isch*
// @match *://*.google.ms/search*tbm=isch*
// @match *://*.google.com.mt/search*tbm=isch*
// @match *://*.google.mu/search*tbm=isch*
// @match *://*.google.mv/search*tbm=isch*
// @match *://*.google.mw/search*tbm=isch*
// @match *://*.google.com.mx/search*tbm=isch*
// @match *://*.google.com.my/search*tbm=isch*
// @match *://*.google.co.mz/search*tbm=isch*
// @match *://*.google.com.na/search*tbm=isch*
// @match *://*.google.com.ng/search*tbm=isch*
// @match *://*.google.com.ni/search*tbm=isch*
// @match *://*.google.ne/search*tbm=isch*
// @match *://*.google.nl/search*tbm=isch*
// @match *://*.google.no/search*tbm=isch*
// @match *://*.google.com.np/search*tbm=isch*
// @match *://*.google.nr/search*tbm=isch*
// @match *://*.google.nu/search*tbm=isch*
// @match *://*.google.co.nz/search*tbm=isch*
// @match *://*.google.com.om/search*tbm=isch*
// @match *://*.google.com.pa/search*tbm=isch*
// @match *://*.google.com.pe/search*tbm=isch*
// @match *://*.google.com.pg/search*tbm=isch*
// @match *://*.google.com.ph/search*tbm=isch*
// @match *://*.google.com.pk/search*tbm=isch*
// @match *://*.google.pl/search*tbm=isch*
// @match *://*.google.pn/search*tbm=isch*
// @match *://*.google.com.pr/search*tbm=isch*
// @match *://*.google.ps/search*tbm=isch*
// @match *://*.google.pt/search*tbm=isch*
// @match *://*.google.com.py/search*tbm=isch*
// @match *://*.google.com.qa/search*tbm=isch*
// @match *://*.google.ro/search*tbm=isch*
// @match *://*.google.ru/search*tbm=isch*
// @match *://*.google.rw/search*tbm=isch*
// @match *://*.google.com.sa/search*tbm=isch*
// @match *://*.google.com.sb/search*tbm=isch*
// @match *://*.google.sc/search*tbm=isch*
// @match *://*.google.se/search*tbm=isch*
// @match *://*.google.com.sg/search*tbm=isch*
// @match *://*.google.sh/search*tbm=isch*
// @match *://*.google.si/search*tbm=isch*
// @match *://*.google.sk/search*tbm=isch*
// @match *://*.google.com.sl/search*tbm=isch*
// @match *://*.google.sn/search*tbm=isch*
// @match *://*.google.so/search*tbm=isch*
// @match *://*.google.sm/search*tbm=isch*
// @match *://*.google.sr/search*tbm=isch*
// @match *://*.google.st/search*tbm=isch*
// @match *://*.google.com.sv/search*tbm=isch*
// @match *://*.google.td/search*tbm=isch*
// @match *://*.google.tg/search*tbm=isch*
// @match *://*.google.co.th/search*tbm=isch*
// @match *://*.google.com.tj/search*tbm=isch*
// @match *://*.google.tl/search*tbm=isch*
// @match *://*.google.tm/search*tbm=isch*
// @match *://*.google.tn/search*tbm=isch*
// @match *://*.google.to/search*tbm=isch*
// @match *://*.google.com.tr/search*tbm=isch*
// @match *://*.google.tt/search*tbm=isch*
// @match *://*.google.com.tw/search*tbm=isch*
// @match *://*.google.co.tz/search*tbm=isch*
// @match *://*.google.com.ua/search*tbm=isch*
// @match *://*.google.co.ug/search*tbm=isch*
// @match *://*.google.co.uk/search*tbm=isch*
// @match *://*.google.com.uy/search*tbm=isch*
// @match *://*.google.co.uz/search*tbm=isch*
// @match *://*.google.com.vc/search*tbm=isch*
// @match *://*.google.co.ve/search*tbm=isch*
// @match *://*.google.vg/search*tbm=isch*
// @match *://*.google.co.vi/search*tbm=isch*
// @match *://*.google.com.vn/search*tbm=isch*
// @match *://*.google.vu/search*tbm=isch*
// @match *://*.google.ws/search*tbm=isch*
// @match *://*.google.rs/search*tbm=isch*
// @match *://*.google.co.za/search*tbm=isch*
// @match *://*.google.co.zm/search*tbm=isch*
// @match *://*.google.co.zw/search*tbm=isch*
// @match *://*.google.cat/search*tbm=isch*
// @match *://*.google.com/search*udm=2*
// @match *://*.google.ad/search*udm=2*
// @match *://*.google.ae/search*udm=2*
// @match *://*.google.com.af/search*udm=2*
// @match *://*.google.com.ag/search*udm=2*
// @match *://*.google.com.ai/search*udm=2*
// @match *://*.google.al/search*udm=2*
// @match *://*.google.am/search*udm=2*
// @match *://*.google.co.ao/search*udm=2*
// @match *://*.google.com.ar/search*udm=2*
// @match *://*.google.as/search*udm=2*
// @match *://*.google.at/search*udm=2*
// @match *://*.google.com.au/search*udm=2*
// @match *://*.google.az/search*udm=2*
// @match *://*.google.ba/search*udm=2*
// @match *://*.google.com.bd/search*udm=2*
// @match *://*.google.be/search*udm=2*
// @match *://*.google.bf/search*udm=2*
// @match *://*.google.bg/search*udm=2*
// @match *://*.google.com.bh/search*udm=2*
// @match *://*.google.bi/search*udm=2*
// @match *://*.google.bj/search*udm=2*
// @match *://*.google.com.bn/search*udm=2*
// @match *://*.google.com.bo/search*udm=2*
// @match *://*.google.com.br/search*udm=2*
// @match *://*.google.bs/search*udm=2*
// @match *://*.google.bt/search*udm=2*
// @match *://*.google.co.bw/search*udm=2*
// @match *://*.google.by/search*udm=2*
// @match *://*.google.com.bz/search*udm=2*
// @match *://*.google.ca/search*udm=2*
// @match *://*.google.cd/search*udm=2*
// @match *://*.google.cf/search*udm=2*
// @match *://*.google.cg/search*udm=2*
// @match *://*.google.ch/search*udm=2*
// @match *://*.google.ci/search*udm=2*
// @match *://*.google.co.ck/search*udm=2*
// @match *://*.google.cl/search*udm=2*
// @match *://*.google.cm/search*udm=2*
// @match *://*.google.cn/search*udm=2*
// @match *://*.google.com.co/search*udm=2*
// @match *://*.google.co.cr/search*udm=2*
// @match *://*.google.com.cu/search*udm=2*
// @match *://*.google.cv/search*udm=2*
// @match *://*.google.com.cy/search*udm=2*
// @match *://*.google.cz/search*udm=2*
// @match *://*.google.de/search*udm=2*
// @match *://*.google.dj/search*udm=2*
// @match *://*.google.dk/search*udm=2*
// @match *://*.google.dm/search*udm=2*
// @match *://*.google.com.do/search*udm=2*
// @match *://*.google.dz/search*udm=2*
// @match *://*.google.com.ec/search*udm=2*
// @match *://*.google.ee/search*udm=2*
// @match *://*.google.com.eg/search*udm=2*
// @match *://*.google.es/search*udm=2*
// @match *://*.google.com.et/search*udm=2*
// @match *://*.google.fi/search*udm=2*
// @match *://*.google.com.fj/search*udm=2*
// @match *://*.google.fm/search*udm=2*
// @match *://*.google.fr/search*udm=2*
// @match *://*.google.ga/search*udm=2*
// @match *://*.google.ge/search*udm=2*
// @match *://*.google.gg/search*udm=2*
// @match *://*.google.com.gh/search*udm=2*
// @match *://*.google.com.gi/search*udm=2*
// @match *://*.google.gl/search*udm=2*
// @match *://*.google.gm/search*udm=2*
// @match *://*.google.gr/search*udm=2*
// @match *://*.google.com.gt/search*udm=2*
// @match *://*.google.gy/search*udm=2*
// @match *://*.google.hk/search*udm=2*
// @match *://*.google.com.hk/search*udm=2*
// @match *://*.google.hn/search*udm=2*
// @match *://*.google.hr/search*udm=2*
// @match *://*.google.ht/search*udm=2*
// @match *://*.google.hu/search*udm=2*
// @match *://*.google.co.id/search*udm=2*
// @match *://*.google.ie/search*udm=2*
// @match *://*.google.co.il/search*udm=2*
// @match *://*.google.im/search*udm=2*
// @match *://*.google.co.in/search*udm=2*
// @match *://*.google.iq/search*udm=2*
// @match *://*.google.is/search*udm=2*
// @match *://*.google.it/search*udm=2*
// @match *://*.google.je/search*udm=2*
// @match *://*.google.com.jm/search*udm=2*
// @match *://*.google.jo/search*udm=2*
// @match *://*.google.jp/search*udm=2*
// @match *://*.google.co.jp/search*udm=2*
// @match *://*.google.co.ke/search*udm=2*
// @match *://*.google.com.kh/search*udm=2*
// @match *://*.google.ki/search*udm=2*
// @match *://*.google.kg/search*udm=2*
// @match *://*.google.co.kr/search*udm=2*
// @match *://*.google.com.kw/search*udm=2*
// @match *://*.google.kz/search*udm=2*
// @match *://*.google.la/search*udm=2*
// @match *://*.google.com.lb/search*udm=2*
// @match *://*.google.li/search*udm=2*
// @match *://*.google.lk/search*udm=2*
// @match *://*.google.co.ls/search*udm=2*
// @match *://*.google.lt/search*udm=2*
// @match *://*.google.lu/search*udm=2*
// @match *://*.google.lv/search*udm=2*
// @match *://*.google.com.ly/search*udm=2*
// @match *://*.google.co.ma/search*udm=2*
// @match *://*.google.md/search*udm=2*
// @match *://*.google.me/search*udm=2*
// @match *://*.google.mg/search*udm=2*
// @match *://*.google.mk/search*udm=2*
// @match *://*.google.ml/search*udm=2*
// @match *://*.google.com.mm/search*udm=2*
// @match *://*.google.mn/search*udm=2*
// @match *://*.google.ms/search*udm=2*
// @match *://*.google.com.mt/search*udm=2*
// @match *://*.google.mu/search*udm=2*
// @match *://*.google.mv/search*udm=2*
// @match *://*.google.mw/search*udm=2*
// @match *://*.google.com.mx/search*udm=2*
// @match *://*.google.com.my/search*udm=2*
// @match *://*.google.co.mz/search*udm=2*
// @match *://*.google.com.na/search*udm=2*
// @match *://*.google.com.ng/search*udm=2*
// @match *://*.google.com.ni/search*udm=2*
// @match *://*.google.ne/search*udm=2*
// @match *://*.google.nl/search*udm=2*
// @match *://*.google.no/search*udm=2*
// @match *://*.google.com.np/search*udm=2*
// @match *://*.google.nr/search*udm=2*
// @match *://*.google.nu/search*udm=2*
// @match *://*.google.co.nz/search*udm=2*
// @match *://*.google.com.om/search*udm=2*
// @match *://*.google.com.pa/search*udm=2*
// @match *://*.google.com.pe/search*udm=2*
// @match *://*.google.com.pg/search*udm=2*
// @match *://*.google.com.ph/search*udm=2*
// @match *://*.google.com.pk/search*udm=2*
// @match *://*.google.pl/search*udm=2*
// @match *://*.google.pn/search*udm=2*
// @match *://*.google.com.pr/search*udm=2*
// @match *://*.google.ps/search*udm=2*
// @match *://*.google.pt/search*udm=2*
// @match *://*.google.com.py/search*udm=2*
// @match *://*.google.com.qa/search*udm=2*
// @match *://*.google.ro/search*udm=2*
// @match *://*.google.ru/search*udm=2*
// @match *://*.google.rw/search*udm=2*
// @match *://*.google.com.sa/search*udm=2*
// @match *://*.google.com.sb/search*udm=2*
// @match *://*.google.sc/search*udm=2*
// @match *://*.google.se/search*udm=2*
// @match *://*.google.com.sg/search*udm=2*
// @match *://*.google.sh/search*udm=2*
// @match *://*.google.si/search*udm=2*
// @match *://*.google.sk/search*udm=2*
// @match *://*.google.com.sl/search*udm=2*
// @match *://*.google.sn/search*udm=2*
// @match *://*.google.so/search*udm=2*
// @match *://*.google.sm/search*udm=2*
// @match *://*.google.sr/search*udm=2*
// @match *://*.google.st/search*udm=2*
// @match *://*.google.com.sv/search*udm=2*
// @match *://*.google.td/search*udm=2*
// @match *://*.google.tg/search*udm=2*
// @match *://*.google.co.th/search*udm=2*
// @match *://*.google.com.tj/search*udm=2*
// @match *://*.google.tl/search*udm=2*
// @match *://*.google.tm/search*udm=2*
// @match *://*.google.tn/search*udm=2*
// @match *://*.google.to/search*udm=2*
// @match *://*.google.com.tr/search*udm=2*
// @match *://*.google.tt/search*udm=2*
// @match *://*.google.com.tw/search*udm=2*
// @match *://*.google.co.tz/search*udm=2*
// @match *://*.google.com.ua/search*udm=2*
// @match *://*.google.co.ug/search*udm=2*
// @match *://*.google.co.uk/search*udm=2*
// @match *://*.google.com.uy/search*udm=2*
// @match *://*.google.co.uz/search*udm=2*
// @match *://*.google.com.vc/search*udm=2*
// @match *://*.google.co.ve/search*udm=2*
// @match *://*.google.vg/search*udm=2*
// @match *://*.google.co.vi/search*udm=2*
// @match *://*.google.com.vn/search*udm=2*
// @match *://*.google.vu/search*udm=2*
// @match *://*.google.ws/search*udm=2*
// @match *://*.google.rs/search*udm=2*
// @match *://*.google.co.za/search*udm=2*
// @match *://*.google.co.zm/search*udm=2*
// @match *://*.google.co.zw/search*udm=2*
// @match *://*.google.cat/search*udm=2*
// @match *://*.google.com/imgres*
// @match *://*.google.ad/imgres*
// @match *://*.google.ae/imgres*
// @match *://*.google.com.af/imgres*
// @match *://*.google.com.ag/imgres*
// @match *://*.google.com.ai/imgres*
// @match *://*.google.al/imgres*
// @match *://*.google.am/imgres*
// @match *://*.google.co.ao/imgres*
// @match *://*.google.com.ar/imgres*
// @match *://*.google.as/imgres*
// @match *://*.google.at/imgres*
// @match *://*.google.com.au/imgres*
// @match *://*.google.az/imgres*
// @match *://*.google.ba/imgres*
// @match *://*.google.com.bd/imgres*
// @match *://*.google.be/imgres*
// @match *://*.google.bf/imgres*
// @match *://*.google.bg/imgres*
// @match *://*.google.com.bh/imgres*
// @match *://*.google.bi/imgres*
// @match *://*.google.bj/imgres*
// @match *://*.google.com.bn/imgres*
// @match *://*.google.com.bo/imgres*
// @match *://*.google.com.br/imgres*
// @match *://*.google.bs/imgres*
// @match *://*.google.bt/imgres*
// @match *://*.google.co.bw/imgres*
// @match *://*.google.by/imgres*
// @match *://*.google.com.bz/imgres*
// @match *://*.google.ca/imgres*
// @match *://*.google.cd/imgres*
// @match *://*.google.cf/imgres*
// @match *://*.google.cg/imgres*
// @match *://*.google.ch/imgres*
// @match *://*.google.ci/imgres*
// @match *://*.google.co.ck/imgres*
// @match *://*.google.cl/imgres*
// @match *://*.google.cm/imgres*
// @match *://*.google.cn/imgres*
// @match *://*.google.com.co/imgres*
// @match *://*.google.co.cr/imgres*
// @match *://*.google.com.cu/imgres*
// @match *://*.google.cv/imgres*
// @match *://*.google.com.cy/imgres*
// @match *://*.google.cz/imgres*
// @match *://*.google.de/imgres*
// @match *://*.google.dj/imgres*
// @match *://*.google.dk/imgres*
// @match *://*.google.dm/imgres*
// @match *://*.google.com.do/imgres*
// @match *://*.google.dz/imgres*
// @match *://*.google.com.ec/imgres*
// @match *://*.google.ee/imgres*
// @match *://*.google.com.eg/imgres*
// @match *://*.google.es/imgres*
// @match *://*.google.com.et/imgres*
// @match *://*.google.fi/imgres*
// @match *://*.google.com.fj/imgres*
// @match *://*.google.fm/imgres*
// @match *://*.google.fr/imgres*
// @match *://*.google.ga/imgres*
// @match *://*.google.ge/imgres*
// @match *://*.google.gg/imgres*
// @match *://*.google.com.gh/imgres*
// @match *://*.google.com.gi/imgres*
// @match *://*.google.gl/imgres*
// @match *://*.google.gm/imgres*
// @match *://*.google.gr/imgres*
// @match *://*.google.com.gt/imgres*
// @match *://*.google.gy/imgres*
// @match *://*.google.hk/imgres*
// @match *://*.google.com.hk/imgres*
// @match *://*.google.hn/imgres*
// @match *://*.google.hr/imgres*
// @match *://*.google.ht/imgres*
// @match *://*.google.hu/imgres*
// @match *://*.google.co.id/imgres*
// @match *://*.google.ie/imgres*
// @match *://*.google.co.il/imgres*
// @match *://*.google.im/imgres*
// @match *://*.google.co.in/imgres*
// @match *://*.google.iq/imgres*
// @match *://*.google.is/imgres*
// @match *://*.google.it/imgres*
// @match *://*.google.je/imgres*
// @match *://*.google.com.jm/imgres*
// @match *://*.google.jo/imgres*
// @match *://*.google.jp/imgres*
// @match *://*.google.co.jp/imgres*
// @match *://*.google.co.ke/imgres*
// @match *://*.google.com.kh/imgres*
// @match *://*.google.ki/imgres*
// @match *://*.google.kg/imgres*
// @match *://*.google.co.kr/imgres*
// @match *://*.google.com.kw/imgres*
// @match *://*.google.kz/imgres*
// @match *://*.google.la/imgres*
// @match *://*.google.com.lb/imgres*
// @match *://*.google.li/imgres*
// @match *://*.google.lk/imgres*
// @match *://*.google.co.ls/imgres*
// @match *://*.google.lt/imgres*
// @match *://*.google.lu/imgres*
// @match *://*.google.lv/imgres*
// @match *://*.google.com.ly/imgres*
// @match *://*.google.co.ma/imgres*
// @match *://*.google.md/imgres*
// @match *://*.google.me/imgres*
// @match *://*.google.mg/imgres*
// @match *://*.google.mk/imgres*
// @match *://*.google.ml/imgres*
// @match *://*.google.com.mm/imgres*
// @match *://*.google.mn/imgres*
// @match *://*.google.ms/imgres*
// @match *://*.google.com.mt/imgres*
// @match *://*.google.mu/imgres*
// @match *://*.google.mv/imgres*
// @match *://*.google.mw/imgres*
// @match *://*.google.com.mx/imgres*
// @match *://*.google.com.my/imgres*
// @match *://*.google.co.mz/imgres*
// @match *://*.google.com.na/imgres*
// @match *://*.google.com.ng/imgres*
// @match *://*.google.com.ni/imgres*
// @match *://*.google.ne/imgres*
// @match *://*.google.nl/imgres*
// @match *://*.google.no/imgres*
// @match *://*.google.com.np/imgres*
// @match *://*.google.nr/imgres*
// @match *://*.google.nu/imgres*
// @match *://*.google.co.nz/imgres*
// @match *://*.google.com.om/imgres*
// @match *://*.google.com.pa/imgres*
// @match *://*.google.com.pe/imgres*
// @match *://*.google.com.pg/imgres*
// @match *://*.google.com.ph/imgres*
// @match *://*.google.com.pk/imgres*
// @match *://*.google.pl/imgres*
// @match *://*.google.pn/imgres*
// @match *://*.google.com.pr/imgres*
// @match *://*.google.ps/imgres*
// @match *://*.google.pt/imgres*
// @match *://*.google.com.py/imgres*
// @match *://*.google.com.qa/imgres*
// @match *://*.google.ro/imgres*
// @match *://*.google.ru/imgres*
// @match *://*.google.rw/imgres*
// @match *://*.google.com.sa/imgres*
// @match *://*.google.com.sb/imgres*
// @match *://*.google.sc/imgres*
// @match *://*.google.se/imgres*
// @match *://*.google.com.sg/imgres*
// @match *://*.google.sh/imgres*
// @match *://*.google.si/imgres*
// @match *://*.google.sk/imgres*
// @match *://*.google.com.sl/imgres*
// @match *://*.google.sn/imgres*
// @match *://*.google.so/imgres*
// @match *://*.google.sm/imgres*
// @match *://*.google.sr/imgres*
// @match *://*.google.st/imgres*
// @match *://*.google.com.sv/imgres*
// @match *://*.google.td/imgres*
// @match *://*.google.tg/imgres*
// @match *://*.google.co.th/imgres*
// @match *://*.google.com.tj/imgres*
// @match *://*.google.tl/imgres*
// @match *://*.google.tm/imgres*
// @match *://*.google.tn/imgres*
// @match *://*.google.to/imgres*
// @match *://*.google.com.tr/imgres*
// @match *://*.google.tt/imgres*
// @match *://*.google.com.tw/imgres*
// @match *://*.google.co.tz/imgres*
// @match *://*.google.com.ua/imgres*
// @match *://*.google.co.ug/imgres*
// @match *://*.google.co.uk/imgres*
// @match *://*.google.com.uy/imgres*
// @match *://*.google.co.uz/imgres*
// @match *://*.google.com.vc/imgres*
// @match *://*.google.co.ve/imgres*
// @match *://*.google.vg/imgres*
// @match *://*.google.co.vi/imgres*
// @match *://*.google.com.vn/imgres*
// @match *://*.google.vu/imgres*
// @match *://*.google.ws/imgres*
// @match *://*.google.rs/imgres*
// @match *://*.google.co.za/imgres*
// @match *://*.google.co.zm/imgres*
// @match *://*.google.co.zw/imgres*
// @match *://*.google.cat/imgres*
// @updateURL https://gist.github.com/ner00/ec9ae47e202b8e99f19be44a5af6baf3/raw/viewimage.user.js
// @downloadURL https://gist.github.com/ner00/ec9ae47e202b8e99f19be44a5af6baf3/raw/viewimage.user.js
// ==/UserScript==
'use strict';
const DEBUG = false;
const SearchImgBtn = true;
const VERSIONS = {
FEB18: 'FEB18',
JUL19: 'JUL19',
OCT19: 'OCT19'
};
var images = new Object();
// Finds the div which contains all required elements
function getContainer(node) {
var container, version;
[
['.irc_c[style*="visibility: visible;"][style*="transform: translate3d(0px, 0px, 0px);"]', VERSIONS.FEB18],
['.irc_c[data-ved]', VERSIONS.JUL19],
['.tvh9oe', VERSIONS.OCT19],
['.EIehLd', VERSIONS.OCT19], // Actually 2024, but let's stick with it for simplicity
['.fHE6De', VERSIONS.OCT19] // Actually 2024, but let's stick with it for simplicity
].forEach(element => {
if (node.closest(element[0])) {
[container, version] = [node.closest(element[0]), element[1]];
}
});
return [container, version];
}
// Finds and deletes all extension related elements.
function clearExtElements(container) {
// Remove previously generated elements
var oldExtensionElements = container.querySelectorAll('.vi_ext_addon');
for (var element of oldExtensionElements) {
element.remove();
}
}
// Returns the image URL
function findImageURL(container, version) {
var image = null;
switch (version) {
case VERSIONS.FEB18:
image = container.querySelector('img[src]#irc_mi, img[alt^="Image result"][src]:not([src^="https://encrypted-tbn"]).irc_mut, img[src].irc_mi');
break;
case VERSIONS.JUL19:
var iframe = container.querySelector('iframe.irc_ifr');
if (!iframe)
return findImageURL(container, VERSIONS.FEB18);
image = iframe.contentDocument.querySelector('img#irc_mi');
break;
case VERSIONS.OCT19:
//image = container.querySelector('img[src].n3VNCb, img[src].r48jcc');
image = container.querySelector('img[src][style][jsaction]'); // Testing a dynamic approach to finding the class name
if (image.src in images) {
return images[image.src];
}
}
// Override url for images using base64 embeds
if (image === null || image.src === '' || image.src.startsWith('data')) {
var thumbnail = document.querySelector('img[name="' + container.dataset.itemId + '"]');
if (thumbnail === null) {
// If no thumbnail found, try getting image from URL
var url = new URL(window.location);
var imgLink = url.searchParams.get('imgurl');
if (imgLink) {
return imgLink;
}
} else {
var meta = thumbnail.closest('.rg_bx').querySelector('.rg_meta');
var metadata = JSON.parse(meta.innerHTML);
return metadata.ou;
}
}
// If the above doesn't work, use the link in related images to find it
if (image === null || image.src === '' || image.src.startsWith('data')) {
var target_image = container.querySelector('img.target_image');
if (target_image) {
var link = target_image.closest('a');
if (link) {
// Some extensions replace google image links with their original links
if (link.href.match(/^[a-z]+:\/\/(?:www\.)?google\.[^/]*\/imgres\?/)) {
var link_url = new URL(link.href);
var new_imgLink = link_url.searchParams.get('imgurl');
if (new_imgLink) {
return new_imgLink;
}
} else {
return link.href;
}
}
}
}
if (image) {
return image.src;
}
}
function addViewImageButton(container, imageURL, version) {
// get the visit buttonm
var visitButton, vbClassName;
switch (version) {
case VERSIONS.FEB18:
visitButton = container.querySelector('td > a.irc_vpl[href]').parentElement;
break;
case VERSIONS.JUL19:
visitButton = container.querySelector('a.irc_hol[href]');
break;
case VERSIONS.OCT19:
// Testing a dynamic approach to finding the class name
try {
vbClassName = document.querySelector('img[src][style][jsaction]').parentElement.parentElement.parentElement.nextSibling.nextSibling.querySelector('div a span').parentElement.parentElement.className.split(" ")[0]; // Desktop
} catch (error) {
if (DEBUG)
console.log('ViewImage: vbClassName not found!');
}
if (!vbClassName) { vbClassName = document.querySelector('img[src][style][jsaction]').parentElement.parentElement.nextSibling.nextSibling.querySelector('div a span').parentElement.parentElement.className.split(" ")[0]; } // Mobile
visitButton = container.querySelector('.ZsbmCf[href], a.J2oL9c, a.jAklOc, a.uZ49bd, a.e0XTue, a.kWgFk, a.j7ZI7c, a.'+vbClassName);
break;
}
// Create the view image button
var viewImageButton = visitButton.cloneNode(true);
viewImageButton.classList.add('vi_ext_addon');
// Set the view image button url
var viewImageLink;
switch (version) {
case VERSIONS.FEB18:
viewImageLink = viewImageButton.querySelector('a');
break;
default:
viewImageLink = viewImageButton;
}
viewImageLink.href = imageURL;
if (version == VERSIONS.OCT19) {
viewImageLink.removeAttribute('jsaction');
}
// Set additional options
viewImageLink.setAttribute('target', '_blank');
// Set the view image button text
var viewImageButtonText;
switch (version) {
case VERSIONS.FEB18:
viewImageButtonText = viewImageButton.querySelector('.Tl8XHc');
break;
case VERSIONS.JUL19:
viewImageButtonText = viewImageButton.querySelector('.irc_ho');
break;
case VERSIONS.OCT19:
viewImageButtonText = viewImageButton.querySelector('.pM4Snf, .KSvtLc, .Pw5kW, .q7UPLe, .K8E1Be, .pFBf7b, span');
break;
}
viewImageButtonText.innerText = 'View image';
// Place the view image button
visitButton.parentElement.insertBefore(viewImageButton, visitButton);
visitButton.parentElement.insertBefore(visitButton, viewImageButton);
}
function addSearchImageButton(container, imageURL, version) {
var link, vbClassName;
switch (version) {
case VERSIONS.FEB18:
link = container.querySelector('.irc_dsh > a.irc_hol');
break;
case VERSIONS.JUL19:
link = container.querySelector('.irc_ft > a.irc_help');
break;
case VERSIONS.OCT19:
// Testing a dynamic approach to finding the class name
try {
vbClassName = document.querySelector('img[src][style][jsaction]').parentElement.parentElement.parentElement.nextSibling.nextSibling.querySelector('div a span').parentElement.parentElement.className.split(" ")[0]; // Desktop
} catch (error) {
if (DEBUG)
console.log('ViewImage: vbClassName not found!');
}
if (!vbClassName) { vbClassName = document.querySelector('img[src][style][jsaction]').parentElement.parentElement.nextSibling.nextSibling.querySelector('div a span').parentElement.parentElement.className.split(" ")[0]; } // Mobile
link = container.querySelector('.PvkmDc, .qnLx5b, .zSA7pe, .uZ49bd, .e0XTue, .kWgFk, .j7ZI7c, .'+vbClassName);
break;
}
// Create the search by image button
var searchImageButton = link.cloneNode(true);
searchImageButton.classList.add('vi_ext_addon');
// Set the more sizes button text
var searchImageButtonText;
switch (version) {
case VERSIONS.FEB18:
searchImageButtonText = container.querySelector('.irc_ho');
break;
case VERSIONS.JUL19:
searchImageButtonText = searchImageButton.querySelector('span');
break;
case VERSIONS.OCT19:
searchImageButtonText = searchImageButton.querySelector('span');
break;
}
searchImageButtonText.innerText = '';
var lensButton = document.createElement("img");
lensButton.style.marginTop = "5px";
lensButton.style.width = "23px";
lensButton.src = "https://fonts.gstatic.com/s/i/productlogos/lens_2023q2/v2/192px.svg";
lensButton.alt = "Search by image";
searchImageButtonText.appendChild(lensButton);
// Set the search by image button url
searchImageButton.href = 'https://lens.google.com/uploadbyurl?url=' + encodeURIComponent(imageURL);
// Set additional options
if (true) {
searchImageButton.setAttribute('target', '_blank');
}
// Place the more sizes button
link.parentElement.insertBefore(searchImageButton, link);
link.parentElement.insertBefore(link, searchImageButton);
}
// Adds links to an object
function addLinks(node) {
if (DEBUG)
console.log('ViewImage: Trying to add links to node: ', node);
// Find the container
var [container, version] = getContainer(node);
// Return if no container was found
if (!container) {
if (DEBUG)
console.log('ViewImage: Adding links failed, container was not found.');
return;
}
if (DEBUG)
console.log('ViewImage: Assuming site version: ', version);
// Clear any old extension elements
clearExtElements(container);
// Find the image url
var imageURL = findImageURL(container, version);
// Return if image was not found
if (!imageURL) {
if (DEBUG)
console.log('ViewImage: Adding links failed, image was not found.');
return;
}
addViewImageButton(container, imageURL, version);
if (SearchImgBtn)
addSearchImageButton(container, imageURL, version);
}
function parseDataSource(array) {
var meta = array[31][0][12][2];
for (var i = 0; i < meta.length; i++) {
try {
images[meta[i][1][2][0]] = meta[i][1][3][0];
} catch (error) {
if (DEBUG)
console.log('ViewImage: Skipping image');
}
}
}
function parseDataSource1() {
const start_search = /AF_initDataCallback\({key:\s'ds:1',\sisError:\s{2}false\s,\shash:\s'\d+',\sdata:/;
const end_search = ', sideChannel: {}});</script>';
var match = document.documentElement.innerHTML.match(start_search);
var start_index = match.index + match[0].length;
var end_index = start_index + document.documentElement.innerHTML.slice(start_index).indexOf(end_search);
parseDataSource(JSON.parse(document.documentElement.innerHTML.slice(start_index, end_index)));
}
function parseDataSource2() {
const start_search = /AF_initDataCallback\({key:\s'ds:2',\sisError:\s{2}false\s,\shash:\s'\d+',\sdata:function(){return\s/;
const end_search = '}});</script>';
var match = document.documentElement.innerHTML.match(start_search);
var start_index = match.index + match[0].length;
var end_index = start_index + document.documentElement.innerHTML.slice(start_index).indexOf(end_search);
parseDataSource(JSON.parse(document.documentElement.innerHTML.slice(start_index, end_index)));
}
// Check if source holds array of images
try {
if (document.documentElement.innerHTML.indexOf('key: \'ds:1\'') != -1) {
if (DEBUG)
console.log('ViewImage: Attempting to parse data source 1.');
parseDataSource1();
} else if (document.documentElement.innerHTML.indexOf('key: \'ds:2\'') != -1) {
if (DEBUG)
console.log('ViewImage: Attempting to parse data source 2.');
parseDataSource2();
} else {
throw 'Could not determine data source type.';
}
if (DEBUG)
console.log('ViewImage: Successfully created source images array.');
} catch (error) {
if (DEBUG) {
console.log('ViewImage: Failed to create source images array.');
console.error(error);
}
}
// Define the mutation observers
var observer = new MutationObserver(function (mutations) {
if (DEBUG)
console.log('ViewImage: Mutations detected: ', mutations);
var node, imgClassName;
imgClassName = document.querySelector('img[src][style][jsaction]').className.split(" ")[0]; // Testing a dynamic approach to finding the class name
for (var mutation of mutations) {
if (mutation.addedNodes && mutation.addedNodes.length > 0) {
for (node of mutation.addedNodes) {
if (node.classList) {
// Check for new image nodes
//if (['irc_mi', 'irc_mut', 'irc_ris', 'n3VNCb', 'r48jcc'].some(className => node.classList.contains(className))) {
if ([imgClassName].some(className => node.classList.contains(className))) {
addLinks(node);
}
}
}
}
//if (mutation.target.classList && mutation.target.classList.contains('n3VNCb', 'r48jcc')) {
if (mutation.target.classList && mutation.target.classList.contains(imgClassName)) {
node = mutation.target.closest('.tvh9oe');
if (!node.hasAttribute('aria-hidden')) {
addLinks(node);
}
}
}
});
// Start adding links
if (DEBUG)
console.log('ViewImage: Initialising observer...');
observer.observe(document.body, {
childList: true,
subtree: true,
attributes: true
});
// inject CSS into document
if (DEBUG)
console.log('ViewImage: Injecting CSS...');
var customStyle = document.createElement('style');
customStyle.innerText = `
.irc_dsh>.irc_hol.vi_ext_addon,
.irc_ft>.irc_help.vi_ext_addon,
.PvkmDc.vi_ext_addon,
.qnLx5b.vi_ext_addon
{
margin: 0 4pt!important
}
.irc_hol.vi_ext_addon
{
flex-grow:0!important
}
/*
.uZ49bd[href^="https://lens.google.com/uploadbyurl"] {
margin-left: 4px;
}
*/
.ZsbmCf.vi_ext_addon{
flex-grow:0
}`;
document.head.appendChild(customStyle);
@ner00
Copy link
Author

ner00 commented May 6, 2024

@gioxx Absolutely, I was able to reproduce the issue. I'm on Firefox, Tampermonkey and Win10
While @E-Bosher 's regex is still sound and covers that search url too, the matter of fact is that in practice it doesn't work in that case for whatever reason, so I decided to revert back to the long list of @match for the time being.

Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment