instantclick: support updating head tags
only for meta and link (not stylesheet) tags
This commit is contained in:
parent
0d1dec9d55
commit
c60eaeb535
|
@ -17,6 +17,7 @@ var InstantClick = function(document, location) {
|
||||||
$title = false,
|
$title = false,
|
||||||
$mustRedirect = false,
|
$mustRedirect = false,
|
||||||
$body = false,
|
$body = false,
|
||||||
|
$head = false,
|
||||||
$timing = {},
|
$timing = {},
|
||||||
$isPreloading = false,
|
$isPreloading = false,
|
||||||
$isWaitingForCompletion = false,
|
$isWaitingForCompletion = false,
|
||||||
|
@ -125,12 +126,15 @@ var InstantClick = function(document, location) {
|
||||||
return returnValue
|
return returnValue
|
||||||
}
|
}
|
||||||
|
|
||||||
function changePage(title, body, newUrl, scrollY) {
|
function changePage(title, body, headCache, newUrl, scrollY) {
|
||||||
document.documentElement.replaceChild(body, document.body)
|
document.documentElement.replaceChild(body, document.body)
|
||||||
/* We cannot just use `document.body = doc.body`, it causes Safari (tested
|
/* We cannot just use `document.body = doc.body`, it causes Safari (tested
|
||||||
5.1, 6.0 and Mobile 7.0) to execute script tags directly.
|
5.1, 6.0 and Mobile 7.0) to execute script tags directly.
|
||||||
*/
|
*/
|
||||||
|
|
||||||
|
// updateHead
|
||||||
|
updateHead(headCache)
|
||||||
|
|
||||||
if (newUrl) {
|
if (newUrl) {
|
||||||
history.pushState(null, null, newUrl)
|
history.pushState(null, null, newUrl)
|
||||||
|
|
||||||
|
@ -190,6 +194,51 @@ var InstantClick = function(document, location) {
|
||||||
return html.replace(/<noscript[\s\S]+<\/noscript>/gi, '')
|
return html.replace(/<noscript[\s\S]+<\/noscript>/gi, '')
|
||||||
}
|
}
|
||||||
|
|
||||||
|
const stylesheetRegex = /stylesheet/
|
||||||
|
|
||||||
|
function loopHeadTags(head, callback) {
|
||||||
|
for (const i of head.children) {
|
||||||
|
let v
|
||||||
|
switch (i.tagName) {
|
||||||
|
case 'LINK':
|
||||||
|
const rel = i.getAttribute('rel') || ''
|
||||||
|
if (rel && !stylesheetRegex.test(rel)) {
|
||||||
|
v = rel
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
case 'META':
|
||||||
|
const name = i.getAttribute('name') || ''
|
||||||
|
const property = i.getAttribute('property') || ''
|
||||||
|
if (name || property) {
|
||||||
|
v = `${name}-${property}`
|
||||||
|
}
|
||||||
|
break;
|
||||||
|
}
|
||||||
|
|
||||||
|
if (v) {
|
||||||
|
callback(i, `${i.tagName}-${v}`)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
function makeHeadCache(head) {
|
||||||
|
const cache = {}
|
||||||
|
loopHeadTags(head, (i, key) => {
|
||||||
|
cache[key] = i.outerHTML
|
||||||
|
})
|
||||||
|
return cache
|
||||||
|
}
|
||||||
|
|
||||||
|
function updateHead(headCache) {
|
||||||
|
// console.log('update head', headCache)
|
||||||
|
loopHeadTags(document.head, (i, key) => {
|
||||||
|
const headTag = headCache[key]
|
||||||
|
if (headTag) {
|
||||||
|
i.outerHTML = headTag
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
|
||||||
|
|
||||||
////////// EVENT HANDLERS //////////
|
////////// EVENT HANDLERS //////////
|
||||||
|
|
||||||
|
@ -292,6 +341,7 @@ var InstantClick = function(document, location) {
|
||||||
doc.documentElement.innerHTML = removeNoscriptTags($xhr.responseText)
|
doc.documentElement.innerHTML = removeNoscriptTags($xhr.responseText)
|
||||||
$title = doc.title
|
$title = doc.title
|
||||||
$body = doc.body
|
$body = doc.body
|
||||||
|
$head = makeHeadCache(doc.head)
|
||||||
|
|
||||||
var alteredOnReceive = triggerPageEvent('receive', $url, $body, $title)
|
var alteredOnReceive = triggerPageEvent('receive', $url, $body, $title)
|
||||||
if (alteredOnReceive) {
|
if (alteredOnReceive) {
|
||||||
|
@ -304,9 +354,11 @@ var InstantClick = function(document, location) {
|
||||||
}
|
}
|
||||||
|
|
||||||
var urlWithoutHash = removeHash($url)
|
var urlWithoutHash = removeHash($url)
|
||||||
|
// console.log('set history 2', urlWithoutHash, $head)
|
||||||
$history[urlWithoutHash] = {
|
$history[urlWithoutHash] = {
|
||||||
body: $body,
|
body: $body,
|
||||||
title: $title,
|
title: $title,
|
||||||
|
head: $head,
|
||||||
scrollY: urlWithoutHash in $history ? $history[urlWithoutHash].scrollY : 0
|
scrollY: urlWithoutHash in $history ? $history[urlWithoutHash].scrollY : 0
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -493,7 +545,7 @@ var InstantClick = function(document, location) {
|
||||||
}
|
}
|
||||||
$history[$currentLocationWithoutHash].scrollY = pageYOffset
|
$history[$currentLocationWithoutHash].scrollY = pageYOffset
|
||||||
setPreloadingAsHalted()
|
setPreloadingAsHalted()
|
||||||
changePage($title, $body, $url)
|
changePage($title, $body, $head, $url)
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
@ -695,8 +747,10 @@ var InstantClick = function(document, location) {
|
||||||
$history[$currentLocationWithoutHash] = {
|
$history[$currentLocationWithoutHash] = {
|
||||||
body: document.body,
|
body: document.body,
|
||||||
title: document.title,
|
title: document.title,
|
||||||
|
head: makeHeadCache(document.head),
|
||||||
scrollY: pageYOffset
|
scrollY: pageYOffset
|
||||||
}
|
}
|
||||||
|
// console.log('set history 1', $currentLocationWithoutHash)
|
||||||
|
|
||||||
var elems = document.head.children,
|
var elems = document.head.children,
|
||||||
elem,
|
elem,
|
||||||
|
@ -736,7 +790,7 @@ var InstantClick = function(document, location) {
|
||||||
|
|
||||||
$history[$currentLocationWithoutHash].scrollY = pageYOffset
|
$history[$currentLocationWithoutHash].scrollY = pageYOffset
|
||||||
$currentLocationWithoutHash = loc
|
$currentLocationWithoutHash = loc
|
||||||
changePage($history[loc].title, $history[loc].body, false, $history[loc].scrollY)
|
changePage($history[loc].title, $history[loc].body, $history[loc].head, false, $history[loc].scrollY)
|
||||||
})
|
})
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -147,6 +147,9 @@
|
||||||
{{- /* InstantClick.js */}}
|
{{- /* InstantClick.js */}}
|
||||||
{{- if (.Param "EnableInstantClick") }}
|
{{- if (.Param "EnableInstantClick") }}
|
||||||
{{- $instantclick := resources.Get "js/instantclick.js" }}
|
{{- $instantclick := resources.Get "js/instantclick.js" }}
|
||||||
|
{{- if hugo.IsProduction }}
|
||||||
|
{{- $instantclick = minify $instantclick }}
|
||||||
|
{{- end }}
|
||||||
<script src="{{ $instantclick.RelPermalink }}" data-no-instant
|
<script src="{{ $instantclick.RelPermalink }}" data-no-instant
|
||||||
{{- if site.Params.assets.disableFingerprinting }}integrity="{{ $instantclick.Data.Integrity }}"{{- end }}
|
{{- if site.Params.assets.disableFingerprinting }}integrity="{{ $instantclick.Data.Integrity }}"{{- end }}
|
||||||
></script>
|
></script>
|
||||||
|
|
|
@ -30,7 +30,7 @@ function setPrefTheme(theme) {
|
||||||
|
|
||||||
const toggleThemeCallbacks = []
|
const toggleThemeCallbacks = []
|
||||||
toggleThemeCallbacks.push((isDark) => {
|
toggleThemeCallbacks.push((isDark) => {
|
||||||
// console.log('window toggle-theme')
|
// console.log('window toggle-theme 1')
|
||||||
if (isDark) {
|
if (isDark) {
|
||||||
setPrefTheme('light');
|
setPrefTheme('light');
|
||||||
} else {
|
} else {
|
||||||
|
@ -42,6 +42,7 @@ toggleThemeCallbacks.push((isDark) => {
|
||||||
// because window is never changed by InstantClick,
|
// because window is never changed by InstantClick,
|
||||||
// we add the listener to window to ensure the event is always received
|
// we add the listener to window to ensure the event is always received
|
||||||
window.addEventListener('toggle-theme', function() {
|
window.addEventListener('toggle-theme', function() {
|
||||||
|
// console.log('window toggle-theme')
|
||||||
const isDark = isDarkTheme()
|
const isDark = isDarkTheme()
|
||||||
toggleThemeCallbacks.forEach(callback => callback(isDark))
|
toggleThemeCallbacks.forEach(callback => callback(isDark))
|
||||||
});
|
});
|
||||||
|
|
Loading…
Reference in New Issue