Hover tooltip of image displaying alt attribute, original title and URL info.
当前为
// ==UserScript==
// @name Image Alt to Title
// @namespace myfonj
// @include *
// @grant none
// @version 1.1.1
// @run-at document-start
// @description Hover tooltip of image displaying alt attribute, original title and URL info.
// ==/UserScript==
/*
* https://greasyfork.org/en/scripts/418348/versions/new
*
* § Trivia:
* ¶ Hover tooltip displays content of nearest element's title attribute (@title).
* ¶ Alt attribute (@alt) is possible only at IMG element.
* ¶ IMG@alt is not displayed in tooltip.
* ¶ IMG cannot have children.
* ¶ @title is possible on any element, including IMG.
* ¶ IMG@src is also valuable.
*
* Goal:
* Display image alt attribute value in images hover tooltip, add valuable @SRC chunks.
*
* Details
* Pull @alt from image and set it so it is readable as @title tooltip
* so that produced title value will not obscure existing parent title
* that would be displayed otherwise. Also include image filename from @src,
* and additionally path or domain.
*
* Means
* Load (and error?) event listener constructing and setting title.
*
* Dangers
* Artificially altered alt or title after image load event will not be taken into account.
* Mitigate with mutationObserver?
*
* Process
* Draw the rest of the owl
*
*
* § Tastcases
*
* FROM:
* <a>
* <img>
* </a>
* TO:
* <a>
* <img title="Alt missing.">
* </a>
*
* FROM:
* <a>
* <img alt="">
* </a>
* TO:
* <a>
* <img alt="" title="Alt: ''">
* </a>
*
* FROM:
* <a>
* <img alt="░">
* </a>
* TO:
* <a>
* <img alt="░" title="Alt: ░">
* </a>
*
* FROM:
* <a>
* <img alt="░" title="▒">
* </a>
* TO:
* <a>
* <img title="Alt: ░, title: ▒">
* </a>
* FROM:
* <a title="▒">
* <img alt="░">
* </a>
* TO:
* <a>
* <img title="Alt: ░, title: ▒">
* </a>
*
* */
document.documentElement.addEventListener('load', altPic, true);
// document.documentElement.addEventListener('error', altPic, true);
/**
* @param {{target: HTMLImageElement}} event
*/
function altPic (event) {
const separator = '\n---\n';
try {
const img = event.target;
if (img.tagName != 'IMG') return
var desc = '';
const alt = img.getAttribute('alt');
const title = getClosestTitle(img);
switch (alt) {
case null:
desc = 'Alt completely missing!';
break;
case '':
desc = 'Alt: \'\'';
break;
default:
if( alt == title ) {
desc = 'Alt (=title): ';
} else {
desc = 'Alt: ';
}
desc += alt;
}
if (title && alt != title) {
desc += separator;
desc += 'Title: ' + title;
}
const descby = img.getAttribute('described-by');
if (descby) {
desc += separator;
desc += 'Described by: ' + descby;
}
desc += separator;
const srcURI = new URL(img.src, img.baseURI);
const slugRx = /[^/]+$/;
if (['https:', 'http:'].includes(srcURI.protocol)) {
desc += 'File: ' + srcURI.pathname.match(slugRx);
if (srcURI.search) {
desc += '\nParams: ' + srcURI.search;
}
if (document.location.hostname != srcURI.hostname) {
desc += '\nHost: ' + srcURI.hostname;
}
desc += '\nPath: ' + srcURI.pathname.replace(slugRx, '');
} else {
desc += 'Src: ' + img.src;
}
img.title = desc
} catch (e) {
// console.error(e);
}
}
/**
* @param {HTMLElement} el
*/
function getClosestTitle (el) {
var ret = [];
do {
if (el.title) {
return el.title;
}
} while ((el = el.parentElement) && el !== document.documentElement);
return ''
}