instantclick - ajax无刷新预加载页面
html
代码
<script src="路径/instantclick.js" data-no-instant></script>
<script data-no-instant>InstantClick.init();</script>
instantclick
代码
var InstantClick = function(document, location) {
var currentLocationWithoutHash
var urlToPreload
var preloadTimer
var pHistory = {}
var p = {}
var useBlacklist = true
var preloadOnMousedown
var delayBeforePreload
var listeners = {
change: []
}
function removeHash(url) {
var index = url.indexOf('#') if (index == -1) {
return url
}
return url.substr(0, index)
}
function getLinkTarget(target) {
while (target.nodeName != 'A') {
target = target.parentNode
}
return target
}
function triggerPageEvent(type) {
for (var i = 0; i < listeners[type].length; i++) {
listeners[type][i]()
}
}
function changePage(title, body) {
var doc = document.implementation.createHTMLDocument('') doc.documentElement.innerHTML = body document.documentElement.replaceChild(doc.body, document.body) var elem = document.createElement('i') elem.innerHTML = title document.title = elem.textContent
}
function mousedown(e) {
preload(getLinkTarget(e.target).href)
}
function mouseover(e) {
var a = getLinkTarget(e.target) a.addEventListener('mouseout', mouseout) if (!delayBeforePreload) {
preload(a.href)
} else {
urlToPreload = a.href preloadTimer = setTimeout(preload, delayBeforePreload)
}
}
function click(e) {
if (e.which > 1 || e.metaKey || e.ctrlKey) {
return
}
e.preventDefault() display(getLinkTarget(e.target).href)
}
function mouseout() {
if (preloadTimer) {
clearTimeout(preloadTimer) preloadTimer = false
return
}
if (!p.isPreloading || (p.isPreloading && p.isWaitingForCompletion)) {
return
}
p.xhr.abort() p.isPreloading = false p.isWaitingForCompletion = false
}
function readystatechange(e) {
if (p.xhr.readyState < 4) {
return
}
if (p.xhr.status == 0) {
return
}
p.timing.ready = +new Date - p.timing.start
var text = p.xhr.responseText
var titleIndex = text.indexOf('<title') if (titleIndex > -1) {
p.title = text.substr(text.indexOf('>', titleIndex) + 1) p.title = p.title.substr(0, p.title.indexOf('</title'))
}
var bodyIndex = text.indexOf('<body') if (bodyIndex > -1) {
p.body = text.substr(bodyIndex) var closingIndex = p.body.indexOf('</body') if (closingIndex > -1) {
p.body = p.body.substr(0, closingIndex)
}
var urlWithoutHash = removeHash(p.url) pHistory[urlWithoutHash] = {
body: p.body,
title: p.title,
scrollY: urlWithoutHash in pHistory ? pHistory[urlWithoutHash].scrollY : 0
}
} else {
p.hasBody = false
}
if (p.isWaitingForCompletion) {
p.isWaitingForCompletion = false display(p.url)
}
}
function instantanize(isInitializing) {
var as = document.getElementsByTagName('a'),
a, domain = location.protocol + '//' + location.host
for (var i = as.length - 1; i >= 0; i--) {
a = as[i]
if (a.target || a.hasAttribute('download') || a.href.indexOf(domain + '/') != 0 || a.href.indexOf('#') > -1 && removeHash(a.href) == currentLocationWithoutHash || (useBlacklist ? a.hasAttribute('data-no-instant') : !a.hasAttribute('data-instant'))) {
continue
}
if (preloadOnMousedown) {
a.addEventListener('mousedown', mousedown)
} else {
a.addEventListener('mouseover', mouseover)
}
a.addEventListener('click', click)
}
if (!isInitializing) {
var scripts = document.getElementsByTagName('script'),
script, copy, parentNode, nextSibling
for (i = 0, j = scripts.length; i < j; i++) {
script = scripts[i]
if (script.hasAttribute('data-no-instant')) {
continue
}
copy = document.createElement('script') if (script.src) {
copy.src = script.src
}
if (script.innerHTML) {
copy.innerHTML = script.innerHTML
}
parentNode = script.parentNode nextSibling = script.nextSibling parentNode.removeChild(script) parentNode.insertBefore(copy, nextSibling)
}
}
triggerPageEvent('change')
}
function preload(url) {
if (!preloadOnMousedown && 'display' in p.timing && +new Date - (p.timing.start + p.timing.display) < 100) {
return
}
if (preloadTimer) {
clearTimeout(preloadTimer) preloadTimer = false
}
if (!url) {
url = urlToPreload
}
if ((p.isPreloading && url == p.url) || (p.isPreloading && p.isWaitingForCompletion)) {
return
}
p.isPreloading = true p.isWaitingForCompletion = false p.url = url p.body = false p.hasBody = true p.timing = {}
p.timing.start = +new Date p.xhr.open('GET', url) p.xhr.send()
}
function display(url) {
if (!('display' in p.timing)) {
p.timing.display = +new Date - p.timing.start
}
if (preloadTimer) {
if (p.url && p.url != url) {
location.href = url
return
}
preload(url) p.isWaitingForCompletion = true
return
}
if (!p.isPreloading || (p.isPreloading && p.isWaitingForCompletion)) {
location.href = url
return
}
if (!p.hasBody) {
location.href = p.url
return
}
if (!p.body) {
p.isWaitingForCompletion = true
return
}
pHistory[currentLocationWithoutHash].scrollY = pageYOffset p.isPreloading = false p.isWaitingForCompletion = false changePage(p.title, p.body) var hashIndex = p.url.indexOf('#') var hashElem = hashIndex > -1 && document.getElementById(p.url.substr(hashIndex + 1)) var offset = 0
if (p.url != location.href && hashElem) {
for (; hashElem.offsetParent; hashElem = hashElem.offsetParent) {
offset += hashElem.offsetTop
}
}
scrollTo(0, offset) history.pushState(null, null, p.url) currentLocationWithoutHash = removeHash(location.href) instantanize()
}
var supported = 'pushState' in history
function init() {
if (!supported) {
triggerPageEvent('change') return
}
if (currentLocationWithoutHash) {
return
}
for (var i = 0; i < arguments.length; i++) {
var arg = arguments[i]
if (arg === true) {
useBlacklist = false
} else if (arg == 'mousedown') {
preloadOnMousedown = true
} else if (typeof arg == 'number') {
delayBeforePreload = arg
}
}
currentLocationWithoutHash = removeHash(location.href) pHistory[currentLocationWithoutHash] = {
body: document.body.outerHTML,
title: document.title,
scrollY: pageYOffset
}
p.xhr = new XMLHttpRequest() p.xhr.addEventListener('readystatechange', readystatechange) p.url = false p.body = false p.hasBody = true p.title = false p.isPreloading = false p.isWaitingForCompletion = false p.timing = {}
instantanize(true) addEventListener('popstate', function() {
var loc = removeHash(location.href) if (loc == currentLocationWithoutHash) {
return
}
if (!(loc in pHistory)) {
location.href = location.href
return
}
pHistory[currentLocationWithoutHash].scrollY = pageYOffset currentLocationWithoutHash = loc changePage(pHistory[loc].title, pHistory[loc].body) scrollTo(0, pHistory[loc].scrollY) instantanize()
})
}
function on(type, listener) {
listeners[type].push(listener)
}
function debug() {
return {
currentLocationWithoutHash: currentLocationWithoutHash,
p: p,
pHistory: pHistory,
supported: supported,
useBlacklist: useBlacklist
}
}
return {
supported: supported,
init: init,
on: on,
debug: debug
}
}(document, location);
参考自 百度