Skip to content

Instantly share code, notes, and snippets.

@AJolly
Last active August 7, 2024 07:38
Show Gist options
  • Save AJolly/b3d4f5374d8e76aa887a5aff29171969 to your computer and use it in GitHub Desktop.
Save AJolly/b3d4f5374d8e76aa887a5aff29171969 to your computer and use it in GitHub Desktop.
Enhances Kagi image search by opening the image's original webpage on shift-click or ctrl-shift-click, instead of just the image file
// ==UserScript==
// @name Kagi Image Search - Original Page Opener
// @namespace https://gist.github.com/AJolly
// @version 1.0
// @description Enhances Kagi image search by opening the image's original webpage on shift-click or ctrl-shift-click, instead of just the image file
// @match https://kagi.com/images*
// @grant none
// @author AJolly
// @license MIT
// @downloadURL https://gist.github.com/AJolly/b3d4f5374d8e76aa887a5aff29171969/raw/?cache-bust=111
// @updateURL https://gist.github.com/AJolly/b3d4f5374d8e76aa887a5aff29171969/raw/?cache-bust=111
// ==/UserScript==
(function() {
'use strict';
console.log('Kagi Image Search Link Modifier loaded');
function modifyImageLinks() {
const imageItems = document.querySelectorAll('div[class*="image_item"]');
console.log(`Found ${imageItems.length} image items`);
imageItems.forEach((item, index) => {
const link = item.querySelector('a[class*="_0_img_link_el"]');
const hostUrl = item.getAttribute('data-host_url');
if (link && hostUrl) {
const newLink = link.cloneNode(true);
link.parentNode.replaceChild(newLink, link);
newLink.addEventListener('click', function(event) {
if (event.shiftKey || (event.ctrlKey && event.shiftKey)) {
event.preventDefault();
event.stopPropagation();
window.open(hostUrl, '_blank');
}
});
newLink.href = hostUrl;
}
});
}
function waitForImages() {
return new Promise((resolve) => {
const checkImages = () => {
const imageItems = document.querySelectorAll('div[class*="image_item"]');
if (imageItems.length > 0) {
resolve();
} else {
setTimeout(checkImages, 500);
}
};
checkImages();
});
}
async function initialize() {
await waitForImages();
modifyImageLinks();
}
initialize();
const observer = new MutationObserver((mutations) => {
mutations.forEach((mutation) => {
if (mutation.type === 'childList') {
const addedNodes = mutation.addedNodes;
for (let node of addedNodes) {
if (node.nodeType === Node.ELEMENT_NODE && node.classList.contains('image_item')) {
modifyImageLinks();
break;
}
}
}
});
});
observer.observe(document.body, { childList: true, subtree: true });
})();
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment