Skip to content

Commit 787df43

Browse files
committed
add instantclick
1 parent 346e31c commit 787df43

4 files changed

Lines changed: 109 additions & 4 deletions

File tree

app/javascript/application.js

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,4 +1,5 @@
1-
import '@hotwired/turbo-rails'
1+
import '@hotwired/turbo'
2+
import { encodeMethodIntoRequestBody } from '@hotwired/turbo-rails/app/javascript/turbo/fetch_requests'
23

34
import { createApp, reactive } from 'vue'
45
import TemplateBuilder from './template_builder/builder'
@@ -15,6 +16,10 @@ import SetOriginUrl from './elements/set_origin_url'
1516
import SetTimezone from './elements/set_timezone'
1617
import AutoresizeTextarea from './elements/autoresize_textarea'
1718

19+
import * as TurboInstantClick from './lib/turbo_instant_click'
20+
21+
TurboInstantClick.start()
22+
1823
document.addEventListener('turbo:before-cache', () => {
1924
window.flash?.remove()
2025
})
@@ -37,6 +42,8 @@ window.customElements.define('set-origin-url', SetOriginUrl)
3742
window.customElements.define('set-timezone', SetTimezone)
3843
window.customElements.define('autoresize-textarea', AutoresizeTextarea)
3944

45+
document.addEventListener('turbo:before-fetch-request', encodeMethodIntoRequestBody)
46+
4047
window.customElements.define('template-builder', class extends HTMLElement {
4148
connectedCallback () {
4249
this.appElem = document.createElement('div')
Lines changed: 98 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,98 @@
1+
const requestCache = new Map()
2+
const cacheTtl = 10 * 1000
3+
4+
function isPreloadable (linkElement) {
5+
const href = linkElement.getAttribute('href')
6+
7+
if (!href || href === '#' || linkElement.dataset.turbo === 'false' || linkElement.dataset.prefetch === 'false') {
8+
return
9+
}
10+
11+
if (linkElement.origin !== document.location.origin) {
12+
return
13+
}
14+
15+
if (!['http:', 'https:'].includes(linkElement.protocol)) {
16+
return
17+
}
18+
19+
if (linkElement.pathname + linkElement.search === document.location.pathname + document.location.search) {
20+
return
21+
}
22+
23+
if (linkElement.dataset.turboMethod && linkElement.dataset.turboMethod !== 'get') {
24+
return
25+
}
26+
27+
return true
28+
}
29+
30+
function mouseoverListener (event) {
31+
let linkElement
32+
33+
if (event.target.tagName === 'A') {
34+
linkElement = event.target
35+
} else {
36+
linkElement = event.target.closest('a')
37+
}
38+
39+
if (!linkElement) {
40+
return
41+
}
42+
43+
if (!isPreloadable(linkElement)) {
44+
return
45+
}
46+
47+
const url = linkElement.getAttribute('href')
48+
const loc = new URL(url, location.protocol + '//' + location.host)
49+
const absoluteUrl = loc.toString()
50+
51+
const cached = requestCache.get(absoluteUrl)
52+
53+
if (cached && cached.ttl > new Date()) {
54+
return
55+
}
56+
57+
const requestOptions = {
58+
credentials: 'same-origin',
59+
headers: { Accept: 'text/html, application/xhtml+xml', 'VND.PREFETCH': 'true' },
60+
method: 'GET',
61+
redirect: 'follow'
62+
}
63+
64+
if (linkElement.dataset.turboFrame && linkElement.dataset.turboFrame !== '_top') {
65+
requestOptions.headers['Turbo-Frame'] = linkElement.dataset.turboFrame
66+
} else if (linkElement.dataset.turboFrame !== '_top') {
67+
const turboFrame = linkElement.closest('turbo-frame')
68+
69+
if (turboFrame) {
70+
requestOptions.headers['Turbo-Frame'] = turboFrame.id
71+
}
72+
}
73+
74+
requestCache.set(absoluteUrl, { request: fetch(absoluteUrl, requestOptions), ttl: new Date(new Date().getTime() + cacheTtl) })
75+
}
76+
77+
function turboBeforeFetchRequest (event) {
78+
if (event.target.tagName !== 'FORM' && event.detail.fetchOptions.method === 'GET') {
79+
const cached = requestCache.get(event.detail.url.toString())
80+
81+
if (cached && cached.ttl > new Date()) {
82+
event.detail.response = cached.request
83+
}
84+
}
85+
86+
requestCache.clear()
87+
}
88+
89+
function start () {
90+
if (!window.turboInstantClickEnabled) {
91+
document.addEventListener('turbo:before-fetch-request', turboBeforeFetchRequest)
92+
document.addEventListener('mouseover', mouseoverListener, { capture: true, passive: true })
93+
}
94+
95+
window.turboInstantClickEnabled = true
96+
}
97+
98+
export { start }

package.json

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -7,6 +7,7 @@
77
"@babel/preset-env": "7.21.5",
88
"@babel/runtime": "7.21.5",
99
"@github/catalyst": "^2.0.0-beta",
10+
"@hotwired/turbo": "https://github.com/docusealco/turbo#main",
1011
"@hotwired/turbo-rails": "^7.3.0",
1112
"@rails/activestorage": "^7.0.0",
1213
"@tabler/icons-vue": "^2.20.0",

yarn.lock

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -988,10 +988,9 @@
988988
"@hotwired/turbo" "^7.3.0"
989989
"@rails/actioncable" "^7.0"
990990

991-
"@hotwired/turbo@^7.3.0":
991+
"@hotwired/turbo@^7.3.0", "@hotwired/turbo@https://github.com/docusealco/turbo#main":
992992
version "7.3.0"
993-
resolved "https://registry.yarnpkg.com/@hotwired/turbo/-/turbo-7.3.0.tgz#2226000fff1aabda9fd9587474565c9929dbf15d"
994-
integrity sha512-Dcu+NaSvHLT7EjrDrkEmH4qET2ZJZ5IcCWmNXxNQTBwlnE5tBZfN6WxZ842n5cHV52DH/AKNirbPBtcEXDLW4g==
993+
resolved "https://github.com/docusealco/turbo#64d286a14b0d11383719a9a09852a775863d621a"
995994

996995
"@humanwhocodes/config-array@^0.11.8":
997996
version "0.11.8"

0 commit comments

Comments
 (0)