Greasy Fork

Greasy Fork is available in English.

check the links is visitable or not

检查超链接是否有效

当前为 2015-08-21 提交的版本,查看 最新版本

// ==UserScript==
// @name    check the links is visitable or not
// @author  burningall
// @description 检查超链接是否有效
// @version     2015.8.22
// @include     *
// @grant       GM_registerMenuCommand
// @grant		GM_xmlhttpRequest
// @run-at      document-start
// @compatible  chrome  推荐
// @compatible  firefox  不推荐
// @license     The MIT License (MIT); http://opensource.org/licenses/MIT
// @supportURL      http://www.burningall.com
// @contributionURL [email protected]|alipay.com
// @namespace http://greasyfork.icu/zh-CN/users/3400-axetroy
// ==/UserScript==			

(function(document){
var config = {
	"autoLoad":true,//脚本开始加载,是否自动ajax。(不建议为true,大量ajax会影响性能,甚至假死)
	"rules": /[a-zA-z]+:\/\/[^\s]*/img
};

function Ob(target,config,fn){
    var MutationObserver = window.MutationObserver || window.WebKitMutationObserver || window.MozMutationObserver;
    var observer = new MutationObserver(function(mutations){
            mutations.forEach(function(mutation) {
                    fn.call(target);
            });
        });
    observer.observe(target, config);
}

function addEvent(obj, type, fn){
	return obj.addEventListener ?
			obj.addEventListener(type, function(e){
				var ev = window.event ? window.event : (e ? e : null);
				if( fn.call(obj,ev)===false ){
					e.cancelBubble = true;//阻止冒泡
					e.preventDefault();//chrome,firefox下阻止默认事件
				}
			}, false)
			 :
			obj.attachEvent('on' + type, function(e){
				ev.target = ev.target || ev.srcElement;
				if(fn.call(obj,ev)===false ){
					e.cancelBubble = true;//阻止冒泡
					return false;//阻止默认事件,针对IE8
				}
			});
}

function visible(obj) {
    var pos = obj.getBoundingClientRect();
    if (document.documentElement.getBoundingClientRect) {
        var w = document.documentElement.clientWidth;
        var h = document.documentElement.clientHeight;
        var jugg = pos.top > h || pos.bottom < 0 || pos.left > w || pos.right < 0;
        if (jugg === true) {
            //不可视
            return false;
        } else {
            //可视
            return true;
        }
    }
}

function check(urlLink,a,secFn,failFn){
	a.setAttribute("checking",true);
	GM_xmlhttpRequest({
	  method: "GET",
	  url: urlLink,
	  onerror: function(response ){
	  	failFn(a);
	  },
	  onreadystatechange:function(response){
	  	if(response.readyState==4){
	  		var status = response.status+'';
	  		if( status.charAt(0)=="4" || status.charAt(0)=="5" ){//4XX,5XX错误
	  			failFn(a);
	  		}else{
	  			secFn(a);
	  		}
	  	}
	  }
	});
}

function init(){
	/**
	 * 不考虑:
	 * <a href="javascript:;"></a>	||	<a href="javascript:void(0);"></a>
	 * <a href="#"></a>
	 */
	var link = document.querySelectorAll('a[href]:not([href^="javascript"]):not([href$="#"]):not([checking]):not([visited])');
	var inViewPort = [];
	var a;
	for(var i=0;i<link.length;i++){
		a = link[i];
		if( visible(a) ){
			inViewPort.push(a);
		}
	}
	// console.log( inViewPort.length );
	if( inViewPort.length>300 ){
		return;
	}
	for( var j=0;j<inViewPort.length;j++ ){
		a = inViewPort[j];
		//已访问过,并且成功,则跳过
		if( a.getAttribute('visited') && a.getAttribute('visited')=="true" ){
			continue;
		}
		check(a.href,a,function(a){
			//请求成功
			// a.style.cssText = "background:rgba(22, 189, 96, 0.75) !important; text-decoration:none !important;";
			a.setAttribute('visited',"true");
			a.removeAttribute('checking');
		},function(a){
			//请求失败
			a.style.cssText = "background:red; text-decoration:line-through;";
			a.setAttribute('visited',"false");
			a.removeAttribute('checking');
		});
	}
}

addEvent(document,'mouseover',function(e){
	var target = e.target || e.srcElement;
	if( target.tagName == "A" && config.rules.test(target.href) ){
		if( target.getAttribute('visited')==="true" ){
			return;
		}
		check(target.href,target,function(target){
			//加载成功
			// target.style.cssText = "background:rgba(22, 189, 96, 0.75) !important; text-decoration:none !important;";
			if( target.getAttribute('visited') && target.getAttribute('visited')=="false" ){
				target.style.cssText = "background:none; text-decoration:none;";
			}
			target.setAttribute('visited',"true");
			target.removeAttribute('checking');
		},function(){
			//加载失败
			target.style.cssText = "background:red; text-decoration:line-through;";
			target.setAttribute('visited',"false");
			target.removeAttribute('checking');
		});
	}
});

addEvent(window,'scroll',function(){
	init();
});

addEvent(window,'DOMContentLoaded',function(){
	if( config.autoLoad === true ){
		init();
		new Ob(document.documentElement,{
			"childList":true,
			"subtree":true
		},function(){
			init();
		});
	}
});

//注册菜单
GM_registerMenuCommand("检查全部链接", init);
})(document);