// ==UserScript== // @name 链接预览 // @name:en Link Previewer // @namespace https://greasyfork.org/zh-CN/users/1073-hzhbest // @version 1.1 // @description 鼠标指向链接标识图标预览链接网页 // @description:en Hovering to preview a link // @author hzhbest // @match *://*/* // @grant none // @license MIT // @downloadURL none // ==/UserScript== (function () { 'use strict'; const ixonimg = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAAA7DAAAOwwHHb6hkAAAAoUlEQVQ4y8XSyw3CMBAE0AekkHTBBZGkCa40QA9AOVADEkGiEJfCxZEsk+8F5mLZs7Mzay3/xmpm3Tm7v9DCeqHhDhdU3UORkHVKJAi4osEJj5RME1SxiZ64De444J2SRVbcRjdZslsUP7Efa6BH3DkHHHOD9UxxG8VlXjTUoExit2MRh0YI2MZzFGMjTIr7EtQTf/I1zmbBWoe4E7OS/Q4fA1sbIN+Dzp4AAAAASUVORK5CYIIAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="; const inonimg = "data:image/png;base64,iVBORw0KGgoAAAANSUhEUgAAABAAAAAQCAYAAAAf8/9hAAAACXBIWXMAATr4AAE6+AGeOBvEAAAA3klEQVQ4y83SPUpDURAF4M8YooUiIi7BQBaQ2lqirZjnVrIFCwsLDbbZgLoAO8FC7EJcgNgZUpvYTOByee/513hguDB3zpm5cy5/xOovOI0qgUZJ5FjDBbbxnF5s4hHjLPYz8jVmOFwmm0n3PdzhJXIreM06H6OP23y0LbyjVzJ2C8O8c51AGwOsB/kqyEd1m00FephiF5dfkZs1Vp0H8RQ3kS/iHJV6mmADJziLRe4kAkXlpwgsMI8Y4AEHP3nCPTohtMTbdwUKdCtq5+HQpEzgA09R0K5xa5p8tH+CT7aEK2vlnm2YAAAAAElFTkSuQmCCAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAAA=="; const loadimg = "data:image/png;base64,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"; const domainregex = /(?<=:\/\/)[^\/]+/; const minHgap = 20, minVgap = 10; // 小窗距鼠标位置的右、下最大距离:像素 var winWidth = 700, winHeight = 550; // 小窗宽、高:像素 const scale = 0.9; // 小窗内页面放大率:(0~1] const animationtime = 0.5; // 动画时长:秒 const iconsize = 20; // 图标放大后大小:像素 const icontrpr = 0.7; // 图标放大后不透明度:(0~1) const pre = "░░░░░░ "; // 拖动手柄前缀:字符串 const id = "__link__prev"; const css = ` /* 链接样式 */ a.___prevlink>img.___previcon { width: 16px !important; height: 16px !important; opacity: 0%; transition: opacity 0.5s ease-out, background 0s; position: absolute; display: inline-block !important; margin: 0 !important; } a.___prevlink.__pr { position: relative; } *:hover>a.___prevlink>img.___previcon { opacity: 30%; } a.___prevlink:hover>img.___previcon { opacity: ${icontrpr}; background: white; border: 1px solid #8d8d8db1; transition: opacity 0.5s linear; z-index: 10008; transform: scale(${iconsize / 16}); } a.___prevlink>img.___previcon:hover { background: #3e3ed3 !important; transition: background 1s !important; } a.__link__preved { outline: 3px solid #3e3ed3; } /* 小窗样式 */ div#__link__prev_win { opacity: 0; position: absolute; z-index: 10009; box-shadow: 1px 1px 7px 1px #717171; padding: 0; margin: 0; background-color: white; transition: ${animationtime}s ease; } div#__link__prev_win.__close { transition: 0s !important; display: none; } div#__link__prev_win.__loading { background: url(${loadimg}) no-repeat center center; background-color: #e7e7e7; } div#__link__prev_win.__link__visible { opacity: 1; transition: 0.2s !important; } div#__link__prev_win.visible .__link__prev_ifr { border: none; transform: scale(${scale}); } div#__link__prev_win.__ondrag { transition: 0s !important; opacity: 0.7; } /* 关闭按钮样式 */ @keyframes rotating_button { from { transform: rotate(0deg); } to { transform: rotate(360deg); } } div#__link__prev_win>.__link__clos_btn { position: absolute; top: -10px; right: -10px; z-index: 10010; line-height: 24px; width: 24px; height: 24px; color: white; font-family: Consolas; font-size: 11pt; text-align: center; background: #df2020; border: 1px solid black; border-radius: 50%; box-shadow: 1px 1px 5px #333; cursor: default; padding: 0 !important; margin: 0; } div#__link__prev_win>.__link__clos_btn.__loading { animation: 3s linear 0s infinite rotating_button; background: #d76565; } div#__link__prev_win>.__link__clos_btn.__loading:hover { animation: none; background: #df2020; } div#__link__prev_win>.__link__clos_btn:hover { outline: 3px solid #be3737a2; } div#__link__prev_win>.__link__clos_btn.__close { display: none; } /* 拖动手柄样式 */ div#__link__prev_win>div.__link__prev_han { position: absolute; top: -5px; left: 0px; z-index: 10010; color: #d7d7d7; height: 6px; width: 30px; border: 1px solid #242424; background: #3e3e3e; cursor: move; border-radius: 3px; overflow: hidden; max-width: ${winWidth}px; } div#__link__prev_win>div.__link__prev_han>* { display: inline-block; width: fit-content; } div#__link__prev_win>div.__link__prev_han:hover { color: #e0a52e; height: 20px; top: -20px; width: fit-content; } div#__link__prev_win.__ondrag>div.__link__prev_han { background: #6f6122; height: 50px; top: -20px; } div#__link__prev_win>.__link__prev_ttl { font-size: 14px; font-family: Arial; white-space: nowrap; } div#__link__prev_win>.__link__prev_btn { height: 18px; width: 18px; border: 1px solid #616161; color: #9a9276; font-size: 13px; position: absolute; right: 0; bottom: 0; z-index: 10011; background: #ccd0d3af; } div#__link__prev_win>.__link__prev_btn:hover { background: #2c96e24f; border-color: #2c96e2af; } div#__link__prev_win.__ondrag>.__link__prev_btn { height: 40px; width: 40px; } `; var previewwin, pre_ir, timer, linkprev, closebtn, draghand, titlebox, ondrag, rsbtn, rsdrag; addCSS(css, id); makeprevwin(); var site = location.host; document.addEventListener('mouseover', (evt) => { const t = evt.target; if (t.tagName == "A" && ispagelink(t)) { addIconTo([t]); } else { var links = getLinksInThreeLayer(t); addIconTo(links); } }); setTimeout(function () { // 延时设置监视器,若标题变化则重新加载 var watch = document.querySelector('title'); new (window.MutationObserver || window.WebKitMutationObserver)(function (mutations) { // console.log('标题变了', document.title); if (!document.querySelector("#" + id)) { addCSS(css, id); } if (!document.querySelector("#" + "__link__prev_win")) { makeprevwin(); } site = location.host; }).observe(watch, { childList: true, subtree: true, characterData: true }); }, 1000); function addIconTo(links) { var lnkl = links.length; var exl = 0; // console.log(lnkl); for (let i = 0; i < lnkl; i++) { const lnk = links[i]; if (lnk.classList.contains("___prevlink")) { continue; } lnk.classList.add("___prevlink"); if (window.getComputedStyle(lnk).position == "static") { lnk.classList.add("__pr"); } var lnkposit = getTrueSize(lnk); var textWidth = lnk.textContent.trim().length * parseInt(window.getComputedStyle(lnk).fontSize) textWidth = Math.min(lnkposit.w, textWidth); var img; img = creaElemIn('img', lnk); img.className = '___previcon'; img.style.bottom = '0.1em'; var adj = (lnkposit.r >= (4 + iconsize)) ? textWidth + 4 : Math.min(textWidth + 4, lnkposit.w - 5 - iconsize); img.style.left = adj + "px"; if (domainregex.exec(lnk.href)[0] !== site) { img.src = ixonimg; exl += 1; } else { img.src = inonimg; } img.addEventListener('mouseover', (evt) => { //clearTimeout(timer); setTimeout(() => { if (previewwin.classList.contains("__close")) { setWinPosit(evt.x, evt.y); } }, 1000); timer = setTimeout(previewlink, 1000, evt); }); img.addEventListener('mouseleave', () => { clearTimeout(timer); }); } //console.log("external link count:" + exl); window.addEventListener('mousedown', (e) => { var target = e.target; // 隐藏预览 if (isprevvisual() && !previewwin.contains(target)) { hidepreview(e); } }, true); } function makeprevwin() { previewwin = creaElemIn('div', document.body); previewwin.id = "__link__prev_win"; previewwin.style.width = '100px'; // 显示前小窗大小 previewwin.style.height = '100px'; previewwin.classList.add("__close"); draghand = creaElemIn('div', previewwin); draghand.classList.add("__link__prev_han"); draghand.innerHTML = pre; rsbtn = creaElemIn('div', previewwin); rsbtn.className = "__link__prev_btn"; rsbtn.innerHTML = "┘"; titlebox = creaElemIn('div', draghand); titlebox.className = "__link__prev_ttl"; pre_ir = creaElemIn('iframe', previewwin); pre_ir.className = "__link__prev_ifr"; pre_ir.style.border = 0; closebtn = creaElemIn('div', previewwin); closebtn.classList.add("__link__clos_btn"); closebtn.innerHTML = "X"; closebtn.addEventListener('click', hidepreview); ondrag = endrag(previewwin, { x: 'left', y: 'top' }, draghand); ondrag.hook('__drag_begin', () => { previewwin.classList.add("__ondrag"); }); ondrag.hook('__drag_end', () => { previewwin.classList.remove("__ondrag"); }); rsdrag = endrag(previewwin, { x: 'width', y: 'height' }, rsbtn); rsdrag.hook('__dragging', () => { if (!!rsdrag.position) { // 未开始拖动前该对象不存在,判断避免编译出错 winWidth = rsdrag.position._x; winHeight = rsdrag.position._y; setIfrWinSize(winWidth, winHeight); } }); rsdrag.hook('__drag_begin', () => { previewwin.classList.add("__ondrag"); }); rsdrag.hook('__drag_end', () => { previewwin.classList.remove("__ondrag"); }); } function previewlink(evt) { if (!!linkprev) { linkprev.classList.remove("__link__preved"); } linkprev = evt.target.parentNode; linkprev.classList.add("__link__preved"); pre_ir.src = linkprev.href; pre_ir.style.transform = "scale(" + scale + ")"; previewwin.classList.remove("__close"); previewwin.classList.add("__loading"); closebtn.classList.remove("__close"); closebtn.classList.add("__loading"); titlebox.innerHTML = linkprev.textContent; setTimeout(() => { previewwin.classList.add("__link__visible"); let l = Math.max(minHgap, Math.min(window.innerWidth - winWidth - minHgap, evt.x)); let t = Math.max(minVgap, Math.min(window.innerHeight - winHeight - minVgap, evt.y)); setWinPosit(l, t); setPrevWinSize(winWidth, winHeight); }, 100); pre_ir.onload = () => { closebtn.classList.remove("__loading"); previewwin.classList.remove("__loading"); }; } function setWinPosit(l, t) { // 根据屏幕位置设置网页位置 previewwin.style.left = l + window.scrollX + 'px'; previewwin.style.top = t + window.scrollY + 'px'; } function setPrevWinSize(w,h) { // 设置预览窗口大小 previewwin.style.width = w + 'px'; previewwin.style.height = h + 'px'; setIfrWinSize(w, h); } function setIfrWinSize(w, h) { // 根据放大率设置iframe窗口大小 var f = (1 - scale) / 2 * -1 / scale; pre_ir.width = w / scale; pre_ir.height = h / scale; pre_ir.style.marginLeft = (w * f) + 'px'; pre_ir.style.marginTop = (h * f) + 'px'; } function hidepreview(evt) { setPrevWinSize(100, 100); // 小窗缩小效果 pre_ir.src = ''; setWinPosit(evt.x, evt.y); // 在鼠标位置消失 previewwin.classList.remove('__link__visible'); linkprev.classList.remove('__link__preved'); closebtn.classList.add("__close"); setTimeout(() => { previewwin.classList.add("__close"); }, animationtime * 1000 + 10); } function isprevvisual() { return previewwin && previewwin.classList.contains('__link__visible'); } function getLinksInThreeLayer(elem) { var links = []; elem.childNodes.forEach(cnode => { if (ispagelink(cnode)) { links.push(cnode); } else { cnode.childNodes.forEach(ccnode => { if (ispagelink(ccnode)) { links.push(ccnode); } else { ccnode.childNodes.forEach(cccnode => { if (ispagelink(cccnode)) { links.push(cccnode); } }); } }); } }); return links; } function ispagelink(node) { // 若节点是A且指向实网址(非js非锚点)返回true if (node.tagName !== "A" || !node.href) { return false; } const h = node.href, l = location.href; if (h.indexOf('javascript:') == 0 || h.replace(l.split('#')[0], "").indexOf("#") == 0) { return false; } else { return true; } } function creaElemIn(tagname, destin) { //在 destin 内末尾创建元素 tagname let theElem = destin.appendChild(document.createElement(tagname)); return theElem; } function addCSS(css, cssid) { let stylenode = creaElemIn('style', document.getElementsByTagName('head')[0]); stylenode.textContent = css; stylenode.type = 'text/css'; stylenode.id = cssid || ''; } // 输入元素,返回对象{元素可见的宽、高、顶、左、一层父元素右侧余量} function getTrueSize(elem, posiz) { if (!posiz) { var p = elem.getBoundingClientRect(); posiz = { w: p.width, h: p.height, t: p.top, l: p.left, r: 0 }; } var pp = elem.parentNode.getBoundingClientRect(); if (posiz.r == 0) posiz.r = (pp.left + pp.width) - (posiz.l + posiz.w); // 父元素对当前元素的右侧余量 if (pp.width >= posiz.w && pp.height >= posiz.h && pp.top <= posiz.t && pp.left <= posiz.l) { return posiz; } else { return getTrueSize(elem.parentNode, { w: Math.min(posiz.w, pp.width), h: Math.min(posiz.h, pp.height), t: Math.max(posiz.t, pp.top), l: Math.max(posiz.l, pp.left), r: posiz.r }); } } // 对target拖动handle时,实现拖动的功能 // 输入:目标元素target,拖动位置参考系opt,拖动手柄handle // 输入opt:形如【{x:'right',y:'bottom'}】,或者width、height(右下角拖动) function endrag(target, opt, handle) { var p_x, p_y, isDragging; endrag = function (target, opt, handle) { return new endrag.proto(target, opt || {}, handle); } endrag.proto = function (target, opt, handle) { var self = this; this.target = target; this.style = target.style; this.handle = handle; var _x = opt.x !== 'right'; var _y = opt.y !== 'bottom'; this.x = opt.x; //_x ? 'left' : 'right'; this.y = opt.y; //_y ? 'top' : 'bottom'; // p_x = this.x; // p_y = this.y; this.xd = _x ? -1 : 1; this.yd = _y ? -1 : 1; this.computed_style = document.defaultView.getComputedStyle(target, ''); this.drag_begin = function (e) { self.__drag_begin(e); }; this.handle.addEventListener('mousedown', this.drag_begin, false); //only drag on handler this.dragging = function (e) { self.__dragging(e); }; document.addEventListener('mousemove', this.dragging, false); this.drag_end = function (e) { self.__drag_end(e); }; document.addEventListener('mouseup', this.drag_end, false); }; endrag.proto.prototype = { __drag_begin: function (e) { if (e.button == 0) { var _c = this.computed_style; this.isDragging = isDragging = true; this.position = { _x: parseFloat(_c[this.x]), _y: parseFloat(_c[this.y]), x: e.pageX, y: e.pageY }; e.preventDefault(); } }, __dragging: function (e) { if (!this.isDragging) return; var x = Math.floor(e.pageX), y = Math.floor(e.pageY), p = this.position; // prevent moving out of window var x_border = window.innerWidth - 40, y_border = window.innerHeight - 20; if (x - window.scrollX > x_border) x = window.scrollX + x_border; if (y - window.scrollY > y_border) y = window.scrollY + y_border; p._x = p._x + (p.x - x) * this.xd; p._y = p._y + (p.y - y) * this.yd; this.style[this.x] = p._x + 'px'; this.style[this.y] = p._y + 'px'; p.x = x; p.y = y; }, __drag_end: function (e) { if (e.button == 0) { if (this.isDragging) { this.isDragging = isDragging = false; } } }, hook: function (method, func) { if (typeof this[method] === 'function') { var o = this[method]; this[method] = function () { if (func.apply(this, arguments) === false) { return; } o.apply(this, arguments); }; } } }; return endrag(target, opt, handle); } })();