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,
|
||||
$mustRedirect = false,
|
||||
$body = false,
|
||||
$head = false,
|
||||
$timing = {},
|
||||
$isPreloading = false,
|
||||
$isWaitingForCompletion = false,
|
||||
|
@ -125,12 +126,15 @@ var InstantClick = function(document, location) {
|
|||
return returnValue
|
||||
}
|
||||
|
||||
function changePage(title, body, newUrl, scrollY) {
|
||||
function changePage(title, body, headCache, newUrl, scrollY) {
|
||||
document.documentElement.replaceChild(body, document.body)
|
||||
/* 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.
|
||||
*/
|
||||
|
||||
// updateHead
|
||||
updateHead(headCache)
|
||||
|
||||
if (newUrl) {
|
||||
history.pushState(null, null, newUrl)
|
||||
|
||||
|
@ -190,6 +194,51 @@ var InstantClick = function(document, location) {
|
|||
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 //////////
|
||||
|
||||
|
@ -292,6 +341,7 @@ var InstantClick = function(document, location) {
|
|||
doc.documentElement.innerHTML = removeNoscriptTags($xhr.responseText)
|
||||
$title = doc.title
|
||||
$body = doc.body
|
||||
$head = makeHeadCache(doc.head)
|
||||
|
||||
var alteredOnReceive = triggerPageEvent('receive', $url, $body, $title)
|
||||
if (alteredOnReceive) {
|
||||
|
@ -304,9 +354,11 @@ var InstantClick = function(document, location) {
|
|||
}
|
||||
|
||||
var urlWithoutHash = removeHash($url)
|
||||
// console.log('set history 2', urlWithoutHash, $head)
|
||||
$history[urlWithoutHash] = {
|
||||
body: $body,
|
||||
title: $title,
|
||||
head: $head,
|
||||
scrollY: urlWithoutHash in $history ? $history[urlWithoutHash].scrollY : 0
|
||||
}
|
||||
|
||||
|
@ -493,7 +545,7 @@ var InstantClick = function(document, location) {
|
|||
}
|
||||
$history[$currentLocationWithoutHash].scrollY = pageYOffset
|
||||
setPreloadingAsHalted()
|
||||
changePage($title, $body, $url)
|
||||
changePage($title, $body, $head, $url)
|
||||
}
|
||||
|
||||
|
||||
|
@ -695,8 +747,10 @@ var InstantClick = function(document, location) {
|
|||
$history[$currentLocationWithoutHash] = {
|
||||
body: document.body,
|
||||
title: document.title,
|
||||
head: makeHeadCache(document.head),
|
||||
scrollY: pageYOffset
|
||||
}
|
||||
// console.log('set history 1', $currentLocationWithoutHash)
|
||||
|
||||
var elems = document.head.children,
|
||||
elem,
|
||||
|
@ -736,7 +790,7 @@ var InstantClick = function(document, location) {
|
|||
|
||||
$history[$currentLocationWithoutHash].scrollY = pageYOffset
|
||||
$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 */}}
|
||||
{{- if (.Param "EnableInstantClick") }}
|
||||
{{- $instantclick := resources.Get "js/instantclick.js" }}
|
||||
{{- if hugo.IsProduction }}
|
||||
{{- $instantclick = minify $instantclick }}
|
||||
{{- end }}
|
||||
<script src="{{ $instantclick.RelPermalink }}" data-no-instant
|
||||
{{- if site.Params.assets.disableFingerprinting }}integrity="{{ $instantclick.Data.Integrity }}"{{- end }}
|
||||
></script>
|
||||
|
|
|
@ -30,7 +30,7 @@ function setPrefTheme(theme) {
|
|||
|
||||
const toggleThemeCallbacks = []
|
||||
toggleThemeCallbacks.push((isDark) => {
|
||||
// console.log('window toggle-theme')
|
||||
// console.log('window toggle-theme 1')
|
||||
if (isDark) {
|
||||
setPrefTheme('light');
|
||||
} else {
|
||||
|
@ -42,6 +42,7 @@ toggleThemeCallbacks.push((isDark) => {
|
|||
// because window is never changed by InstantClick,
|
||||
// we add the listener to window to ensure the event is always received
|
||||
window.addEventListener('toggle-theme', function() {
|
||||
// console.log('window toggle-theme')
|
||||
const isDark = isDarkTheme()
|
||||
toggleThemeCallbacks.forEach(callback => callback(isDark))
|
||||
});
|
||||
|
|
Loading…
Reference in New Issue