1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
<!DOCTYPE html>
<html lang="en" prefix="twitter: https://api.twitter.com/ og: http://ogp.me/ns#">
<head>
<meta charset="utf-8"/>
</head>
<body>
<a href="http://www.w3school.com.cn/tags/att_a_target.asp" target="_blank">Test Url</a>
</body>
<script>
var urlToPreload;
var mouseoverTimer;
var lastTouchTimestamp;
var prefetcher=document.createElement('link');

if(prefetcher.relList&&prefetcher.relList.supports&&prefetcher.relList.supports('prefetch')){
	prefetcher.rel='prefetch';
	document.head.appendChild(prefetcher);
	const eventListenersOptions={
		capture:true,
		passive:true,
	}
	document.addEventListener('touchstart',touchstartListener,eventListenersOptions);
	document.addEventListener('mouseover',mouseoverListener,eventListenersOptions);
}

function touchstartListener(event){
	lastTouchTimestamp=performance.now();
	const linkElement=event.target.closest('a');
	if(!linkElement){
		return;
	}
	if(!isPreloadable(linkElement)){
		return;
	}
	const eventListenersOptions={
		passive:true
	};
	linkElement.addEventListener('touchcancel',touchendAndTouchcancelListener,eventListenersOptions);
	linkElement.addEventListener('touchend',touchendAndTouchcancelListener,eventListenersOptions);
	urlToPreload=linkElement.href;
	prefetcher.href=linkElement.href;
}

function touchendAndTouchcancelListener(){
	urlToPreload=undefined;
	prefetcher.removeAttribute('href');
}

function mouseoverListener(event){
	if(1100>performance.now()-lastTouchTimestamp){
		return;
	}
	const linkElement=event.target.closest('a');
	if(!linkElement){
		return;
	}
	if(!isPreloadable(linkElement)){
		return;
	}
	linkElement.addEventListener('mouseout',mouseoutListener,{
		passive:true
	})
	urlToPreload=linkElement.href;
	mouseoverTimer=setTimeout(function(){
		prefetcher.href=linkElement.href;
		mouseoverTimer=undefined;
	},65)
}

function mouseoutListener(event){
	if(event.relatedTarget&&event.target.closest('a')==event.relatedTarget.closest('a')){
		return;
	}
	if(mouseoverTimer){
		clearTimeout(mouseoverTimer);
		mouseoverTimer=undefined;
	}else{
		urlToPreload=undefined;
		prefetcher.removeAttribute('href');
	}
}

function isPreloadable(linkElement){
	if(urlToPreload==linkElement.href){
		return;
	}
	const urlObject=new URL(linkElement.href);
	if((!'instantAllowQueryString'in document.body.dataset)&&urlObject.search&&!('instant'in linkElement.dataset)){
		return;
	}
	if(urlObject.hash&&urlObject.pathname+urlObject.search==location.pathname+location.search){
		return;
	}
	if('noInstant'in linkElement.dataset){
		return;
	}
	return true;
}
</script>
</html>