您需要先安装一个扩展,例如 篡改猴、Greasemonkey 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 暴力猴,之后才能安装此脚本。
您需要先安装一个扩展,例如 篡改猴 或 Userscripts ,之后才能安装此脚本。
您需要先安装一款用户脚本管理器扩展,例如 Tampermonkey,才能安装此脚本。
您需要先安装用户脚本管理器扩展后才能安装此脚本。
Hold mouse button over link to open it in new tab. Requires to release mouse to take effect due to popup restrictions.
// ==UserScript== // @name Hold to new tab // @description Hold mouse button over link to open it in new tab. Requires to release mouse to take effect due to popup restrictions. // @namespace util // @include * // @version 2016.2.15.18.05 // @grant none // @author Jakub Mareda aka MXXIV // @run-at document-start // ==/UserScript== // Timeout after mousedown when the new tab timeout should be started // this timeout is to prevent flickering when clicking links normally var startCoundownTimeout = null; var startCountdownTime = 100; //140; // the actual countdown before displaying the link var countdownTimeout = null; var countdownTime = 500; // Time when the mouse was pressed down var mouseDownTime = -1; // Target link var link = null; // progress bar object, initialized later var progressBar; function mouseDown(e) { // only left button if(e.button != 0) return; var el = e.target; //console.log("Mousedown"); while(el!=null) { if(el.tagName && el.tagName.toLowerCase()=="a") { link = el; //console.log("... link!"); startPreCountdown(e.clientX, e.clientY); return; } el = el.parentNode; } //console.log("... not a link."); } // Counts but doesn't display anything yet function startPreCountdown(x,y) { mouseDownTime = performance.now(); // add cancel listeners link.addEventListener("mouseout", failIfLeftButton); link.addEventListener("mouseup", failIfLeftButton); window.addEventListener("onunload", stopFail); // Don't use delay if delay is off if(startCountdownTime>0) { startCountdownTimeout = setTimeout(startCountdown, startCountdownTime, x, y); } else { startCountdown(x, y); } } // Starts displaying the loader function startCountdown(x,y) { progressBar.x = x; progressBar.y = y; progressBar.start(); countdownTimeout = setTimeout(stopExec, countdownTime); } // Stop and do the action function stopExec() { //console.log("Open in new tab: "+link.href); if(link.target!="_blank") { if(link.target) link.setAttribute("oldtarget", link.target); link.target = "_blank"; removeBlankOnClick(link); } //link.dispatchEvent(new MouseEvent("click")); stop(); } // stop and do nothing function stopFail() { //console.log("No action on "+link.href); stop(); } function failIfLeftButton(mouseEvent) { if(mouseEvent.button == 0) stopFail(); } function stop() { progressBar.stop(); clearTimeout(countdownTimeout); countdownTimeout = null; clearTimeout(startCountdownTimeout); startCountdownTimeout = null; // clear listeners link.removeEventListener("mouseout", failIfLeftButton); link.removeEventListener("mouseup", failIfLeftButton); window.removeEventListener("onunload", stopFail); } function calculateTimePercentage() { var dt = performance.now()-mouseDownTime; return (dt/(startCountdownTime+countdownTime))*100; } function Renderer(callback) { this.percents = 0; this.x = 0; this.y = 0; this.getPercents = callback; this.colorFull = "rgba(86,125,255,0.8)"; this.colorEmpty = "rgba(86,125,255,0.2)"; this.rendering = false; // cached callback this.renderLoop = this.renderLoop.bind(this); } Renderer.prototype = { init: function() { var div = this.div; if(!div) { var div = this.div = document.createElement("div"); div.style.position = "fixed"; div.style.width = "40px"; div.style.height = "6px"; div.style.fontSize = "0px"; div.innerHTML = "This div is used to render progress bar for New tab userscript."; div.style.display = "none"; document.body.appendChild(div); } return div; }, render: function() { var div = this.div?this.div:this.init(); div.style.top = (this.y-8)+"px"; // hardcoded half width div.style.left = (this.x-20)+"px"; var c = this.colorFull, c2 = this.colorEmpty; var perc = Math.round(this.percents)+""; div.style.background = "linear-gradient(to right, "+c+" 0%,"+c+" "+perc+"%,"+c2+" "+perc+"%,"+c2+" 100%)"; }, renderLoop: function() { if(this.rendering) { if(this.getPercents) this.percents = this.getPercents(); this.render(); requestAnimationFrame(this.renderLoop); } }, start: function() { this.rendering = true; (this.div ? this.div:this.init()).style.display = "block"; this.renderLoop(); }, stop: function() { this.rendering = false; if(this.div) this.div.style.display = "none"; } } progressBar = new Renderer(calculateTimePercentage); window.addEventListener("mousedown", mouseDown); function cancelEvent(e) { e.preventDefault(); console.log("Cancel ", e.type); window.removeEventListener(e.type, cancelEvent); return false; } function cancelNext(evtName) { window.addEventListener(evtName, cancelEvent); } /** remove target="_blank" - or set it to original value **/ function removeBlank(e) { // it must happen AFTER the click event does what it should setTimeout((()=>{ if(this.hasAttribute("oldtarget")) { this.setAttribute("target", this.getAttribute("oldtarget")); this.removeAttribute("oldtarget"); } else { this.removeAttribute("target"); } }).bind(this), 0); this.removeEventListener(e.type, removeBlank); } function removeBlankOnClick(link) { link.addEventListener("click", removeBlank); }
QingJ © 2025
镜像随时可能失效,请加Q群300939539或关注我们的公众号极客氢云获取最新地址