优雅的 alert()

把警示窗改为显示在页面右上角,显示几秒后会自动关闭。用鼠标点按窗口会立即关闭,并把内容拷贝到系统剪贴簿。

目前为 2020-02-03 提交的版本。查看 最新版本

// ==UserScript==
// @name         elegant alert()
// @name:zh-CN   优雅的 alert()
// @name:zh-TW   優雅的 alert()
// @description:en     Customized alert box at the top right corner, auto close in a few seconds. Click on the alert box will close it immediately and copy the alert message to clipboard.
// @description:zh-CN  把警示窗改为显示在页面右上角,显示几秒后会自动关闭。用鼠标点按窗口会立即关闭,并把内容拷贝到系统剪贴簿。
// @description:zh-TW  把警示窗改為顯示在頁面右上角,顯示幾秒後會自動關閉。用滑鼠點按窗口會立即關閉,並把內容複製到系統剪貼簿。
// @namespace    https://greasyfork.org/zh-TW/users/393133-evan-tseng
// @author       Evan Tseng
// @version      1.03
// @include      http://*
// @include      https://*
// @run-at       document-start
// @grant        none
// @description Customized alert box at the top right corner, auto close in a few seconds. Click on the alert box will close it immediately and copy the alert message to clipboard.
// ==/UserScript==

(async function() {
	'use strict';

	const boxFont = '400 14pt Helvetica',
		  boxFontColor = '#220',
		  boxColor = 'rgba(240,240,210,.85)',
		  boxHoverColor = 'rgba(255,255,230,.85)',
		  popBgColor = '#F00',
		  countdownColor1 = 'rgba(0,0,255,.12)',
		  countdownColor2 = 'rgba(80,0,255,.12)',
		  duration = "12000";

	var alertWrap = null;
	const ElegantAlertBox = function(msg){
		if(!alertWrap) {
			const css = '@media screen and (min-width: 200px) { .elegantAlertBoxWrapper { max-width: 75%; right:5mm } }'+
				  '@media screen and (min-width: 800px) { .elegantAlertBoxWrapper { max-width: 400px; right:10mm} }'+
				  '.elegantAlertBoxWrapper { position:fixed; top:8mm; text-align:right; z-index:2147483647; -webkit-user-select:none; user-select:none }'+
				  '.elegantAlertBoxWrapper>div { float:right; clear: right; position:relative; font:'+ boxFont +'; line-height:1.4; color:'+ boxFontColor +'; background:'+ popBgColor +'; max-height:0; padding:2px 2mm; margin-bottom:1.5mm; overflow:scroll; border-radius:5px; opacity:0; cursor:pointer; box-shadow:inset 0 0 0 1px rgba(255,255,255,.8), 0 1px 2mm rgba(0,0,0,.7); backdrop-filter:blur(2px); -webkit-backdrop-filter:blur(2px); }'+
				  '.elegantAlertBoxWrapper>div>.eaBar { position: absolute; left:0; top:0; width:100%; height:100%; background:'+ countdownColor1 +'; border-radius: 3px }'+
				  '.elegantAlertBoxWrapper>.eaNormal { background:'+ boxColor +'; opacity:1; max-height:4.7em; transition:max-height 0s, opacity 0s, background .2s 0s }'+
				  '.elegantAlertBoxWrapper>.eaNormal>.eaBar, .elegantAlertBoxWrapper>.eaClose>.eaBar { background: '+ countdownColor2 +'; width:0; transition:' + duration + 'ms linear}'+
				  '.elegantAlertBoxWrapper>.eaClose { background:'+ boxColor +'; opacity:0; max-height:0; padding:0 2mm; margin:0; transition: .6s }'+
				  '.elegantAlertBoxWrapper>.eaNormal:hover { background:'+ boxHoverColor +'; z-index:2; box-shadow:inset 0 0 0 1px rgba(255,255,255,.8), 0 1px 2mm rgba(0,0,0,.8); transition: .1s }'+
				  '.elegantAlertBoxWrapper>.eaNormal:active { box-shadow:0 0 0 1px #777, inset 0 1px 2px #555 }',
				  cssStyle = document.createElement('style');
			if(cssStyle.styleSheet)	cssStyle.styleSheet.cssText = css;
			else	cssStyle.appendChild(document.createTextNode(css));
			document.querySelector('head').appendChild(cssStyle);

			alertWrap = document.createElement('div');
			alertWrap.setAttribute("class", "elegantAlertBoxWrapper");
			document.body.appendChild(alertWrap);
		}

		this.exist = true;
		this.createBox = function(text){
			var box = this,
				alBox = document.createElement('div');
			alBox.innerHTML = '<div class="eaBar"></div>' + text;
			alBox.onclick = function(){
				window.Clipboard.copy(text);
				box.close();
			};
			return alBox;
		};
		this.show = function(){
			var box = this;
			setTimeout(function(){
				box.elm.setAttribute("class", "eaNormal");
				setTimeout(function(){
					if(box.exist)	box.close();
				}, duration);
			},60);
		};
		this.close = function(){
			var box = this;
			box.elm.setAttribute("class", "eaClose");
			setTimeout(function(){
				if(box.exist) {
					alertWrap.removeChild(box.elm);
					box.exist = false;
				}
			}, 1000);
		};
		this.elm = this.createBox(msg);
		alertWrap.appendChild(this.elm);
		this.show();
		return this.elm;
	};

	window.Clipboard = (function(window, document, navigator) {
		var textArea, copy;
		function isOS() {
			return navigator.userAgent.match(/ipad|iphone/i);
		}
		function createTextArea(text) {
			textArea = document.createElement('textArea');
			textArea.value = text;
			document.body.appendChild(textArea);
		}
		function selectText() {
			var range,
				selection;
			if (isOS()) {
				range = document.createRange();
				range.selectNodeContents(textArea);
				selection = window.getSelection();
				selection.removeAllRanges();
				selection.addRange(range);
				textArea.setSelectionRange(0, -1);
			} else {
				textArea.select();
			}
		}
		function copyToClipboard() {
			document.execCommand('copy');
			document.body.removeChild(textArea);
		}
		copy = function(text) {
			createTextArea(text);
			selectText();
			copyToClipboard();
		};
		return {
			copy: copy
		};
	})(window, document, navigator);

	window.alert = async function(message){
		if(document.body) {
			var alertBox = new ElegantAlertBox(message);
		}
		else {
			setTimeout(function(){
				window.alert(message);
			}, 500);
		}
	};

})();