您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Open google images in page instead of new tab
// ==UserScript== // @name Super google // @namespace http://tampermonkey.net/ // @version 0.2 // @description Open google images in page instead of new tab // @author Faris Hijazi // @include https://www.google.* // @include https://encrypted.google.com* // @grant GM_setValue // @grant GM_getValue // @grant unsafeWindow // @require http://code.jquery.com/jquery-latest.js // @require https://greasyfork.org/scripts/38996-faris-handy-webdev-javascript-functions/code/Faris%20Handy%20Webdev%20JavaScript%20functions.user.js // @run-at document-end // ==/UserScript== // @require https://github.com/buzamahmooza/Helpful-Web-Userscripts/raw/master/Handy%20AF%20functions%20Faris.user.js // noinspection ES6ConvertVarToLetConst var debug; if (typeof debug === 'undefined') { debug = false; } if (typeof log === 'undefined') { log = function (msg) { if (debug) console.log('Log:', msg); }; } const gImgSearchUrl = "https://encrypted.google.com/search?&hl=en&tbm=isch&q="; const AUTO_SAVE_UBL_SITES = false; const REPLACE_IMG_DATA = false; if (typeof GM === 'undefined') // PRE GM4 { GM = {}; // noinspection JSUnresolvedVariable GM.getValue = GM_getValue; // noinspection JSUnresolvedVariable GM.setValue = GM_setValue; } let storedSuccessfulUrlsSet = GM_getValue('unblocked sites of og images', new Set(['forumophilia.com'])); let ublSitesMap = GM_getValue('ublSitesMap', new Map([['forumphilia.com', '']])); let successfulUrlsSet = new Set(); if (typeof unsafeWindow === "undefined") { unsafeWindow = window; } window.addEventListener("keydown", onkeydown, true); // addToSet(storedSuccessfulUrlsSet, successfulUrlsSet); storedSuccessfulUrlsSet.forEach(function (e, i, a) { successfulUrlsSet.add(e); }); // log('Stored successfulUrlsSet:', storedSuccessfulUrlsSet); // log('successfulUrlsSet:', successfulUrlsSet); if (AUTO_SAVE_UBL_SITES) setInterval(storeSuccessfulUrlsSet, 5000); function updateSuccessfulUrlsSet() { qa('.display-original-image').forEach(function (elt, index, array) { let siteUrl = "" + getHostname(getGimgRUrl(elt)); if (/google\.com/.test(siteUrl)) siteUrl = getHostname(elt.getAttribute('rg_meta_ru')); if (/tumblr\.com/.test(siteUrl)) siteUrl = siteUrl.replace(/^\d*?\./); successfulUrlsSet.add(siteUrl); console.log('adding ubl site:', siteUrl); }); console.log('in updateSuccessfulUrlsSet:', Array.from(successfulUrlsSet)); return successfulUrlsSet; // returning just cuz it could be handy } function storeSuccessfulUrlsSet() { updateSuccessfulUrlsSet(); var merged = new Set(); var stored = GM_getValue('unblocked sites of og images'); addToSet(merged, successfulUrlsSet); addToSet(merged, stored); var diff = Array.from(successfulUrlsSet).filter(x => Array.from(stored).indexOf(x) < 0); console.log("Found unblocked site that isn't in the database:", diff); // successfulUrlsSet; // addToSet(successfulUrlsSet, storedSuccessfulUrlsSet); GM_setValue('unblocked sites of og images', Array.from(merged)); console.log('stored set:', GM_getValue('unblocked sites of og images')); // console.log('merged successfulUrlsSet:', Array.from(merged)); } function observeDocument(callback) { callback(document.body); new MutationObserver(function (mutations) { for (let i = 0; i < mutations.length; i++) { if (!mutations[i].addedNodes.length) continue; callback(mutations[i].target); } }).observe(document.body, { childList: true, subtree: true, attributes: false, characterData: false }); } function observePanel(callback) { new MutationObserver(function (mutations) { for (let i = 0; i < mutations.length; i++) { if (!mutations[i].addedNodes.length) continue; callback(mutations[i].target); } }).observe(ImagePanel.mainPanel, { childList: true, subtree: true, attributes: true, characterData: false }); } for (let elt of Array.from(getAllImgEls)) { createAndAddAttribute(elt, 'download-name', getGimgDescription(elt)); } let GIUtOST_MutOb = (window.MutationObserver) ? window.MutationObserver : window.WebKitMutationObserver; if (REPLACE_IMG_DATA) { replaceImgData(); observeDocument(replaceImgData); } if (GIUtOST_MutOb) { const GIUtOST_chgMon = new GIUtOST_MutOb(function (mutationSet) { mutationSet.forEach(function (mutation) { for (let i = 0; i < mutation.addedNodes.length; i++) { // noinspection EqualityComparisonWithCoercionJS if (mutation.addedNodes[i].nodeType == 1) GIUtOST_checkNode(mutation.addedNodes[i]); } }); }); // attach chgMon to document.body const opts = {childList: true, subtree: true}; GIUtOST_chgMon.observe(document.body, opts); } GIUtOST_checkNode(document.elements); function getAllImgEls() { return qa('img.rg_ic.rg_i'); } /**abbreviation for querySelectorAll()*/ function qa(selector) { let x = document.querySelectorAll(selector); return x ? x : null; } function q(selector) { let x = document.querySelector(selector); return x ? x : null; } // Google images function GIUtOST_checkNode(els) { clickLoadMoreImages(els); // showFullImageSiteURL(els); // var picBoxes = qa('[pic-not-found]'); if(picBoxes.length <= 0) return; // for(var i=0; i<picBoxes.length; i++) picBoxes[i] = picBoxes[i].parentNode.parentNode; // document.getElementsByClassName("rg_bx rg_di rg_el ivg-i"); // if (picBoxes.length > 0) deleteElements(picBoxes); } function getImageBlocks() { return qa('.rg_bx'); } function showFullImageSiteURL(els) { //siteAnchors try { if (els === null) return; var as = els.querySelectorAll('div.Q7Rsec'); // console.log("as.length:" +as.length); for (var i = 0; i < as.length; i++) { var a = as[i]; var getLocation = function (href) { var l = document.createElement("a"); l.href = href; return l.hostname; }; // if(a.classList.contains("ShowFullImageSiteURL")) break; // if(a.href.match("/null")) {console.log("match with null");break;} var host = getLocation(as[1].href); // siteSearchAnchor var ssa = document.createElement('a'); ssa.href = (GoogleImagesSearchURL + "site:" + (host)); // console.log("as["+i+"]: " +a.href); // console.log(i+"Ssa.href: "+ ssa.href); ssa.innerHTML = "site search[" + host + "]"; let span = document.createElement('span'); span.appendChild(ssa); a.parentNode.appendChild(span); a.classList.add("ShowFullImageSiteURL"); } } catch (Exception) { } } // working :) function clickLoadMoreImages(els) { var el = document.getElementById("smb"); if (!el) return; el.click(); // if(debug)console.log("Load more images"); } //[Google.com images] function getDataElement(imgN) { return imgN.parentNode.nextSibling; } function getDataText(imgN) { let data = "Not a main image, No data text available"; try { data = getDataElement(imgN).innerHTML; } catch (exception) { } // console.log('Data text:', data); return data; } function getGimgDescription(imgN) { let txt = getDataText(imgN); let title = extractFromText(txt, "ru"); let desc = extractFromText(txt, "s"); return title + "_" + desc; // desc.length > 1 ? desc : title; // choosing one of them (prioratizing the description over the title) } function getGimgTitle(imgN) { return extractImgData(imgN, 'pt'); } function getGimgRUrl(imgN) { return extractImgData(imgN, 'ru'); } function getGimgDimensions(imgN) { return extractImgData(imgN, 'ow') + 'x' + extractImgData(imgN, 'oh'); } function extractImgData(imgN, key) { return extractFromText(getDataText(imgN), key); } /** The fallback will be the value returned if no results were found. */ function extractFromText(txt, key, fallback) { let data = typeof fallback === undefined ? fallback : ("no image data found for key: '" + key + "'"); let regex = new RegExp('(?<="' + key + '":")(.+?)(?=")'); if (!txt) return data; let matches = txt.match(regex); data = (matches) ? matches[0] : data; return data; } if (false) window.onbeforeunload = function (e) { // on tab exit ublSites = new Set(ublSites, GM_getValue('unblocked sites of og images')); console.log('ublSites:', ublSites); GM_setValue('unblocked sites of og images', Array.from(ublSites)); var message = "Saving unblocked sites (confirmation).", e = e || window.event; // For IE and Firefox if (e) { e.returnValue = message; } // For Safari return message; }; // replaces the image description link text function replaceImgData(dataEls) { if (typeof dataEls === 'undefined') return; dataEls.querySelectorAll('.rg_meta').forEach(function (dataEl) { if (dataEl.classList.contains('rg_meta-modified')) return; try { let dataText = dataEl.innerHTML; // console.log('modifying meta data text:', dataText); let siteUrl = extractFromText(dataText, 'ru'); let description = extractFromText(dataText, 's'); let subTitle = extractFromText(dataText, 'st'); let imageAnchor = dataEl.previousSibling; createAndAddAttribute(imageAnchor, 'rg_meta_st', subTitle); createAndAddAttribute(imageAnchor, 'rg_meta_ru', siteUrl); let hostname = getHostname(siteUrl).replace('www.', ''); let siteSearchUrl = GoogleImagesSearchURL + "site:" + encodeURIComponent(hostname); dataEl.innerHTML = dataEl.innerHTML .replace(subTitle, 'site search: ' + hostname) // replace SubTitle text with site HOSTNAME .replace(siteUrl, siteSearchUrl) // replace title lin with site siteSearch link // .replace(description, HOSTNAME) ; dataEl.classList.add('rg_meta-modified'); } catch (exception) { console.error("Caught exception while changin rg_meta:", exception); } }); } function makeImageDescriptionsClickable() { ImagePanel.mainPanel.forEach(function (panel) { var description = panel.querySelector('div.irc_b.i8152.irc_mmc > div.i30053 > div > div.irc_it > div.irc_hd > div[dir="ltr"] > font > font'); description.addEventListener("click", function (e) { var search = gImgSearchUrl + this.innerHTML; window.open(search, "_blank"); }); }); } unsafeWindow.extractImgData = extractImgData; unsafeWindow.getGimgTitle = getGimgTitle; unsafeWindow.getGimgRUrl = getGimgRUrl; unsafeWindow.getGimgDescription = getGimgDescription; unsafeWindow.reverseImgSearch = reverseImgSearch; //[Google.com images] unsafeWindow.saveUblSites = function () { storeSuccessfulUrlsSet(); console.log('Site links of unblocked images "display-original-image"es:', Array.from(successfulUrlsSet)); }; function addToSet(mainSet, otherSet) { if (typeof mainSet === 'undefined' || typeof otherSet === 'undefined') return; try { // if(isIterable(otherSet) && isIterable(mainSet)) otherSet.forEach(function (elt, i, a) { if (typeof elt === 'string') { mainSet.add(elt); } }); } catch (exc) { } console.log('merged sets:', Array.from(mainSet)); return mainSet; } function reverseImgSearch(imageUrl) { window.open("https://encrypted.google.com/searchbyimage?&image_url=" + imageUrl, "_blank"); } /**Here's a vanilla js example to trigger any event: * <code> triggerEvent(targetElement, 'keyup', 13); // simulate mouse/enter key press</code>*/ function triggerEvent(el, type, keyCode) { // focus on the input element el.focus(); if ('createEvent' in document) { // modern browsers, IE9+ var e = document.createEvent('HTMLEvents'); e.keyCode = keyCode; e.initEvent(type, false, true); el.dispatchEvent(e); } else { // IE 8 var e = document.createEventObject(); e.keyCode = keyCode; e.eventType = type; el.fireEvent('on' + e.eventType, e); } } /* Understanding Google Images ###Image Boxes: Image boxes are contained in one parent element with the selector: `div#rg_s`. Every image box contains an `img`, and a `div` containing the data. Attributes |Selector| Notes --- | --- | --- **img** | *ClassName =*| **nicely** ###The Image Panel: There is one big panel containing 3 sub-panels, you only get to see one sub-panel at a time. Moving to the next image will rotate the 3 sub-panels, and you will visit each one as they rotate. * Main panel selector: `#irc_cc` * Sub-panels contain a `data-ved` attribute, only the active one will have data, the other 2 will be `null`. * Active sub-panel selector: `#irc_cc div.irc_t:not([data-ved="null"])` */ class ImageBox extends Element { }//TODO: class ImagePanel { constructor(element) { if (typeof element !== 'undefined') { this.element = element; } this.makeDescriptionClickable(); // this.relatedImagesDiv = {divElement: this.element,} } makeDescriptionClickable() { this.descriptionEl.addEventListener("click", function (e) { const search = gImgSearchUrl + this.innerHTML; window.open(search, "_blank"); }); } get isFocused() { return "translate3d(0px, 0px, 0px)".test(this.getAttribute('style')); } static get mainPanel() { const mainPanelEl = q("#irc_cc"); return mainPanelEl ? new ImagePanel(mainPanelEl) : false; } get titleAndDescriptionDiv() { this.element.querySelector('._cjj > .irc_it'); } /** * @returns {ElementTagNameMap[] | Element} */ get descriptionEl() { if (this.titleAndDescriptionDiv) this.titleAndDescriptionDiv.querySelector('div.irc_hd > div[dir="ltr"] > font > font, div.irc_hd > div[dir="ltr"]'); } get titleEl() { if (this.titleAndDescriptionDiv) this.titleAndDescriptionDiv.querySelector('span ~ a'); } get title() { return this.titleEl.innerHTML; } get subtitleEl() { if (this.titleAndDescriptionDiv) this.titleAndDescriptionDiv.querySelector('span a.irc_lth._ZR'); } get subtitle() { return this.subtitleEl.innerHTML; } /** * returns that small square at the bottom right (the focused one) * @returns {ElementTagNameMap[string] | Element} */ get focusedRelativeImage() { return this.element.querySelector('div.irc_rimask.irc_rist'); } get imageUrl() { this.focusedRelativeImage.querySelector('a').href; } get image() { return this.element.querySelector('img#irc_mi,img.irc_mut'); } /** * @returns {ElementTagNameMap[string] | Element} returns the panel that is currently in focus (there are 3 panels) */ static get focusedPanel() { var p = this.mainPanel ? this.mainPanel.querySelector('div.irc_c[style*="translate3d(0px, 0px, 0px)"]') : null; console.log('mainPanel:', p); return p; } // TODO: getters: // description // title // subtitle } function mainPanel() { const mainPanelEl = q("#irc_cc"); return mainPanelEl; } // hot-keys let KeyEvent; if (typeof KeyEvent === "undefined") { KeyEvent = { DOM_VK_SPACE: 32, DOM_VK_LEFT: 37, DOM_VK_UP: 38, DOM_VK_RIGHT: 39, DOM_VK_DOWN: 40, DOM_VK_A: 65, DOM_VK_D: 68, DOM_VK_P: 80, DOM_VK_Q: 81, DOM_VK_R: 82, DOM_VK_S: 83, DOM_VK_V: 86, DOM_VK_W: 87, DOM_VK_COMMA: 188, DOM_VK_DOT: 190, DOM_VK_NUMPAD1: 97, DOM_VK_NUMPAD2: 98, DOM_VK_NUMPAD3: 99, DOM_VK_NUMPAD4: 100, DOM_VK_NUMPAD_LEFT: 100, DOM_VK_NUMPAD5: 101, DOM_VK_NUMPAD6: 102, DOM_VK_NUMPAD_RIGHT: 102, DOM_VK_NUMPAD7: 103, DOM_VK_NUMPAD8: 104, DOM_VK_NUMPAD9: 105, DOM_VK_NUMPAD_DIVIDE: 106, DOM_VK_NUMPAD_MULTIPLY: 111, DOM_VK_NUMPAD_ENTER: 113, DOM_VK_F5: 116 }; } function onkeydown(b) { const a = (window.event) ? b.keyCode : b.which; /** @type {{CTRL_ONLY: boolean, SHIFT_ONLY: boolean, ALT_ONLY: boolean, NONE: boolean}} */ const ModifierKeys = { CTRL_ONLY: b.ctrlKey && !b.altKey && !b.shiftKey && !b.metaKey, SHIFT_ONLY: !b.ctrlKey && !b.altKey && b.shiftKey && !b.metaKey, ALT_ONLY: !b.ctrlKey && b.altKey && !b.shiftKey && !b.metaKey, NONE: !b.ctrlKey && !b.shiftKey && !b.altKey && !b.metaKey }; // if(b.ctrlKey && a == KeyEvent.DOM_VK_S) // { // if(i) // { // a = protected_createElement("a"); // a.href = i.src; // a.download = ""; // HTML5 // document.body.appendChild(a); // a.click(); // document.body.removeChild(a); // } // return; // } // if (b.altKey || b.metaKey || (b.ctrlKey && a != KeyEvent.DOM_VK_SPACE && a != KeyEvent.DOM_VK_F5 && a != KeyEvent.DOM_VK_R)) // { // return; // } // var by = Math.round(window.innerHeight * 0.10); const panel = mainPanel().querySelector('div.irc_c[style*="translate3d(0px, 0px, 0px)"]'); //ImagePanel.focusedPanel; // the active panel if (!panel) { console.error("SUBPANEL NOT FOUND!!"); return false; } const focusedRelatedImage = panel.querySelector('div.irc_rimask.irc_rist');//panel.focusedRelativeImage; const panelImage = panel.querySelector('img#irc_mi,img.irc_mut'); /** * @type {any | NodeListOf<Element>} * 0 - Visit * 1 - Save * 2 - View saved * 3 - Share */ const buttons = panel.querySelectorAll('.irc_but_r > tbody > tr a'); const visitPageButton = buttons[0]; const titleAndDescriptionDiv = panel.querySelector('._cjj > .irc_it'); const titleEl = titleAndDescriptionDiv.querySelector('span ~ a'); const subtitleEl = titleAndDescriptionDiv.querySelector('span a.irc_lth._ZR'); log("titleAndDescriptionDiv:", titleAndDescriptionDiv); if (!titleEl) console.error("Title element not found"); if (!subtitleEl) console.error("SubTitle element not found"); const title = titleEl.innerHTML; // panel.querySelector('a._ZR.irc_hol.i3724.irc_lth'); const subtitle = subtitleEl.innerHTML; // image drop-down panel: #irc_bg /**Goes to the previous main image*/ function previousImage() { // triggerEvent(q("#irc_bg"), "keyup", KeyEvent.DOM_VK_LEFT); q('#irc_la').click(); } /**Goes to the next main image*/ function nextImage() { // triggerEvent(q("#irc_bg"), "keyup", KeyEvent.DOM_VK_LEFT); q('#irc_ra').click(); } function lookupTitle() { const extractedTitleSearchText = (title.length < subtitle.length ? subtitle : title); // use the longer title openInTab(GoogleReverseImagesSearchURL + extractedTitleSearchText); } function siteSearch() { const hostname = getHostname(subtitleEl.href); console.log('Site search:', hostname); openInTab(siteSearchUrl(getHostname(subtitleEl.href))); } switch (a) { // Search by image/ site search case KeyEvent.DOM_VK_V: case KeyEvent.DOM_VK_NUMPAD1: const focusedRelatedImageUrl = focusedRelatedImage.querySelector('a').href; console.log('currentPanelImage', focusedRelatedImageUrl); if (typeof panelImage !== "undefined") { reverseImgSearch(focusedRelatedImageUrl); log("focusedRelatedImageUrl:", focusedRelatedImageUrl); } else console.error('Image not found', focusedRelatedImageUrl); break; // TODO: case KeyEvent.DOM_VK_NUMPAD4: nextImage(); break; case KeyEvent.DOM_VK_NUMPAD6: previousImage(); break; // Open related images (press the bottom right square in the corner) in new tab case KeyEvent.DOM_VK_NUMPAD3: const moreRelatedImagesLink = q('.irc_rismo.irc_rimask a'); if (typeof moreRelatedImagesLink !== 'undefined') openInTab(moreRelatedImagesLink.href); break; case KeyEvent.DOM_VK_NUMPAD5: if (ModifierKeys.NONE) { openInTab(focusedRelatedImage.querySelector('a').href); } else if (ModifierKeys.CTRL_ONLY) { download(focusedRelatedImage.querySelector('a').href, undefined, undefined, focusedRelatedImage); } break; // Previous related image case KeyEvent.DOM_VK_COMMA: case KeyEvent.DOM_VK_NUMPAD8: let previousElementSibling = focusedRelatedImage.previousElementSibling; (previousElementSibling) ? previousElementSibling.click() : previousImage(); break; // Next related image case KeyEvent.DOM_VK_DOT: case KeyEvent.DOM_VK_NUMPAD2: let nextElementSibling = focusedRelatedImage.nextElementSibling; (nextElementSibling && !nextElementSibling.classList.contains('irc_rismo')) ? nextElementSibling.click() : nextImage(); break; // lookup the images title. // Opens a new window with the search query as the image title case KeyEvent.DOM_VK_NUMPAD7: // I have options, I'll choose the best later const visitUrl = buttons[0].href; const visitTitleUrl = subtitleEl.href; console.log('Visit:', visitUrl); openInTab(visitUrl); break; //TODO: Search using title //TODO: Visit website/ GIMG Site.Search the website case KeyEvent.DOM_VK_NUMPAD9: if (ModifierKeys.NONE) { lookupTitle(); } else if (ModifierKeys.CTRL_ONLY) { // site search siteSearch(); } break; case KeyEvent.DOM_VK_S: siteSearch(); break; } } function openInTab(url) { window.open(url, "_blank"); } // data-cthref = /url?sa=i&rct=j&q=&esrc=s&source=images&cd=&ved=2ahUKEwjW84KFwbzZAhUvT98KHX4fA6UQjB16BAgAEAU&url=http%3A%2F%2Frwby.wikia.com%2Fwiki%2FFile%3ATEAM_PAJAMA_RWBY!.jpg&psig=AOvVaw2HgCMglmhtGPN4QfLzDi4P&ust=1519491410121543