turbograft 0.4.2 → 0.4.3
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- checksums.yaml +4 -4
- data/lib/assets/javascripts/turbograft/document.coffee +11 -0
- data/lib/assets/javascripts/turbograft/response.coffee +23 -0
- data/lib/assets/javascripts/turbograft/turbohead.coffee +1 -1
- data/lib/assets/javascripts/turbograft/turbolinks.coffee +42 -58
- data/lib/turbograft.rb +2 -4
- data/lib/turbograft/version.rb +1 -1
- metadata +6 -4
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 9334d30bbf9e86dd7baae353ac711bc9688f70ff
|
4
|
+
data.tar.gz: 92bc6bf6eb003c707d82b1b28d7b71bd67e59ada
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 6625a059b2940513077f90ab4e11645e807cd57a62074815ed36f89710d28c3702a0277a90c62f243a079a0cc042011f8845cacd077f7881db43e576d478e5dd
|
7
|
+
data.tar.gz: 02850cbe00f2c90a16a34fd2932fb458fe542f578b766e7b1709ff9c938a75d706c5b439639a6338d93be44c6e86a0d4d3a80af20ce0e9a8760b2b7544fc9f24
|
@@ -0,0 +1,11 @@
|
|
1
|
+
TurboGraft.Document =
|
2
|
+
create: (html) ->
|
3
|
+
if /<(html|body)/i.test(html)
|
4
|
+
doc = document.documentElement.cloneNode()
|
5
|
+
doc.innerHTML = html
|
6
|
+
else
|
7
|
+
doc = document.documentElement.cloneNode(true)
|
8
|
+
doc.querySelector('body').innerHTML = html
|
9
|
+
doc.head = doc.querySelector('head')
|
10
|
+
doc.body = doc.querySelector('body')
|
11
|
+
doc
|
@@ -0,0 +1,23 @@
|
|
1
|
+
class TurboGraft.Response
|
2
|
+
constructor: (@xhr) ->
|
3
|
+
|
4
|
+
valid: -> @hasRenderableHttpStatus() && @hasValidContent()
|
5
|
+
|
6
|
+
document: ->
|
7
|
+
if @valid()
|
8
|
+
TurboGraft.Document.create(@xhr.responseText)
|
9
|
+
|
10
|
+
hasRenderableHttpStatus: ->
|
11
|
+
return true if @xhr.status == 422 # we want to render form validations
|
12
|
+
!(400 <= @xhr.status < 600)
|
13
|
+
|
14
|
+
hasValidContent: ->
|
15
|
+
if contentType = @xhr.getResponseHeader('Content-Type')
|
16
|
+
contentType.match(/^(?:text\/html|application\/xhtml\+xml|application\/xml)(?:;|$)/)
|
17
|
+
else
|
18
|
+
throw new Error("Error encountered for XHR Response: #{this}")
|
19
|
+
|
20
|
+
toString: () ->
|
21
|
+
"URL: #{@xhr.responseURL}, " +
|
22
|
+
"ReadyState: #{@xhr.readyState}, " +
|
23
|
+
"Headers: #{@xhr.getAllResponseHeaders()}"
|
@@ -10,7 +10,7 @@ waitForCompleteDownloads = ->
|
|
10
10
|
scriptPromises[url]
|
11
11
|
Promise.all(loadingPromises)
|
12
12
|
|
13
|
-
class
|
13
|
+
class TurboGraft.TurboHead
|
14
14
|
constructor: (@activeDocument, @upstreamDocument) ->
|
15
15
|
@activeAssets = extractTrackedAssets(@activeDocument)
|
16
16
|
@upstreamAssets = extractTrackedAssets(@upstreamDocument)
|
@@ -1,14 +1,15 @@
|
|
1
1
|
xhr = null
|
2
|
+
activeDocument = document
|
2
3
|
|
3
4
|
installDocumentReadyPageEventTriggers = ->
|
4
|
-
|
5
|
+
activeDocument.addEventListener 'DOMContentLoaded', ( ->
|
5
6
|
triggerEvent 'page:change'
|
6
7
|
triggerEvent 'page:update'
|
7
8
|
), true
|
8
9
|
|
9
10
|
installJqueryAjaxSuccessPageUpdateTrigger = ->
|
10
11
|
if typeof jQuery isnt 'undefined'
|
11
|
-
jQuery(
|
12
|
+
jQuery(activeDocument).on 'ajaxSuccess', (event, xhr, settings) ->
|
12
13
|
return unless jQuery.trim xhr.responseText
|
13
14
|
triggerEvent 'page:update'
|
14
15
|
|
@@ -20,20 +21,20 @@ browserSupportsPushState =
|
|
20
21
|
window.history and window.history.pushState and window.history.replaceState and historyStateIsDefined
|
21
22
|
|
22
23
|
window.triggerEvent = (name, data) ->
|
23
|
-
event =
|
24
|
+
event = activeDocument.createEvent 'Events'
|
24
25
|
event.data = data if data
|
25
26
|
event.initEvent name, true, true
|
26
|
-
|
27
|
+
activeDocument.dispatchEvent event
|
27
28
|
|
28
29
|
window.triggerEventFor = (name, node, data) ->
|
29
|
-
event =
|
30
|
+
event = activeDocument.createEvent 'Events'
|
30
31
|
event.data = data if data
|
31
32
|
event.initEvent name, true, true
|
32
33
|
node.dispatchEvent event
|
33
34
|
|
34
35
|
popCookie = (name) ->
|
35
|
-
value =
|
36
|
-
|
36
|
+
value = activeDocument.cookie.match(new RegExp(name+"=(\\w+)"))?[1].toUpperCase() or ''
|
37
|
+
activeDocument.cookie = name + '=; expires=Thu, 01-Jan-70 00:00:01 GMT; path=/'
|
37
38
|
value
|
38
39
|
|
39
40
|
requestMethodIsSafe =
|
@@ -42,7 +43,7 @@ requestMethodIsSafe =
|
|
42
43
|
browserSupportsTurbolinks = browserSupportsPushState and requestMethodIsSafe
|
43
44
|
|
44
45
|
browserSupportsCustomEvents =
|
45
|
-
|
46
|
+
activeDocument.addEventListener and activeDocument.createEvent
|
46
47
|
|
47
48
|
if browserSupportsCustomEvents
|
48
49
|
installDocumentReadyPageEventTriggers()
|
@@ -61,7 +62,6 @@ removeNode = (node) ->
|
|
61
62
|
# TODO: clean up everything above me ^
|
62
63
|
# TODO: decide on the public API
|
63
64
|
class window.Turbolinks
|
64
|
-
createDocument = null
|
65
65
|
currentState = null
|
66
66
|
referer = null
|
67
67
|
|
@@ -80,8 +80,11 @@ class window.Turbolinks
|
|
80
80
|
fetchReplacement url, options
|
81
81
|
|
82
82
|
@fullPageNavigate: (url) ->
|
83
|
-
|
84
|
-
|
83
|
+
if url?
|
84
|
+
url = (new ComponentUrl(url)).absolute
|
85
|
+
triggerEvent('page:before-full-refresh', url: url)
|
86
|
+
activeDocument.location.href = url
|
87
|
+
return
|
85
88
|
|
86
89
|
@pushState: (state, title, url) ->
|
87
90
|
window.history.pushState(state, title, url)
|
@@ -89,6 +92,10 @@ class window.Turbolinks
|
|
89
92
|
@replaceState: (state, title, url) ->
|
90
93
|
window.history.replaceState(state, title, url)
|
91
94
|
|
95
|
+
@document: (documentToUse) ->
|
96
|
+
activeDocument = documentToUse if documentToUse
|
97
|
+
activeDocument
|
98
|
+
|
92
99
|
fetchReplacement = (url, options) ->
|
93
100
|
triggerEvent 'page:fetch', url: url.absolute
|
94
101
|
|
@@ -111,7 +118,7 @@ class window.Turbolinks
|
|
111
118
|
|
112
119
|
xhr.onload = ->
|
113
120
|
if xhr.status >= 500
|
114
|
-
Turbolinks.fullPageNavigate(url
|
121
|
+
Turbolinks.fullPageNavigate(url)
|
115
122
|
else
|
116
123
|
Turbolinks.loadPage(url, xhr, options)
|
117
124
|
xhr = null
|
@@ -121,7 +128,7 @@ class window.Turbolinks
|
|
121
128
|
if xhr.statusText == "abort"
|
122
129
|
xhr = null
|
123
130
|
return
|
124
|
-
Turbolinks.fullPageNavigate(url
|
131
|
+
Turbolinks.fullPageNavigate(url)
|
125
132
|
|
126
133
|
xhr.send()
|
127
134
|
|
@@ -130,21 +137,21 @@ class window.Turbolinks
|
|
130
137
|
@loadPage: (url, xhr, options = {}) ->
|
131
138
|
triggerEvent 'page:receive'
|
132
139
|
options.updatePushState ?= true
|
133
|
-
if upstreamDocument =
|
140
|
+
if upstreamDocument = new TurboGraft.Response(xhr).document()
|
134
141
|
if options.partialReplace
|
135
142
|
reflectNewUrl url if options.updatePushState
|
136
143
|
updateBody(upstreamDocument, xhr, options)
|
137
144
|
else
|
138
|
-
turbohead = new TurboHead(
|
145
|
+
turbohead = new TurboGraft.TurboHead(activeDocument, upstreamDocument)
|
139
146
|
if turbohead.hasAssetConflicts()
|
140
|
-
return Turbolinks.fullPageNavigate(url
|
147
|
+
return Turbolinks.fullPageNavigate(url)
|
141
148
|
reflectNewUrl url if options.updatePushState
|
142
149
|
turbohead.waitForAssets().then((result) ->
|
143
150
|
updateBody(upstreamDocument, xhr, options) unless result?.isCanceled
|
144
151
|
)
|
145
152
|
else
|
146
153
|
triggerEvent 'page:error', xhr
|
147
|
-
Turbolinks.fullPageNavigate(url
|
154
|
+
Turbolinks.fullPageNavigate(url)
|
148
155
|
|
149
156
|
updateBody = (upstreamDocument, xhr, options) ->
|
150
157
|
nodes = changePage(
|
@@ -159,7 +166,7 @@ class window.Turbolinks
|
|
159
166
|
triggerEvent 'page:load', nodes
|
160
167
|
|
161
168
|
changePage = (title, body, csrfToken, runScripts, options = {}) ->
|
162
|
-
|
169
|
+
activeDocument.title = title if title
|
163
170
|
options.onlyKeys ?= []
|
164
171
|
options.exceptKeys ?= []
|
165
172
|
|
@@ -177,7 +184,7 @@ class window.Turbolinks
|
|
177
184
|
deleteRefreshNeverNodes(body)
|
178
185
|
|
179
186
|
triggerEvent 'page:before-replace'
|
180
|
-
replaceNode(body,
|
187
|
+
replaceNode(body, activeDocument.body)
|
181
188
|
CSRFToken.update csrfToken if csrfToken?
|
182
189
|
setAutofocusElement()
|
183
190
|
executeScriptTags() if runScripts
|
@@ -190,14 +197,14 @@ class window.Turbolinks
|
|
190
197
|
getNodesMatchingRefreshKeys = (keys) ->
|
191
198
|
matchingNodes = []
|
192
199
|
for key in keys
|
193
|
-
for node in TurboGraft.querySelectorAllTGAttribute(
|
200
|
+
for node in TurboGraft.querySelectorAllTGAttribute(activeDocument, 'refresh', key)
|
194
201
|
matchingNodes.push(node)
|
195
202
|
|
196
203
|
return matchingNodes
|
197
204
|
|
198
205
|
getNodesWithRefreshAlways = ->
|
199
206
|
matchingNodes = []
|
200
|
-
for node in TurboGraft.querySelectorAllTGAttribute(
|
207
|
+
for node in TurboGraft.querySelectorAllTGAttribute(activeDocument, 'refresh-always')
|
201
208
|
matchingNodes.push(node)
|
202
209
|
|
203
210
|
return matchingNodes
|
@@ -210,8 +217,8 @@ class window.Turbolinks
|
|
210
217
|
false
|
211
218
|
|
212
219
|
setAutofocusElement = ->
|
213
|
-
autofocusElement = (list =
|
214
|
-
if autofocusElement and
|
220
|
+
autofocusElement = (list = activeDocument.querySelectorAll 'input[autofocus], textarea[autofocus]')[list.length - 1]
|
221
|
+
if autofocusElement and activeDocument.activeElement isnt autofocusElement
|
215
222
|
autofocusElement.focus()
|
216
223
|
|
217
224
|
deleteRefreshNeverNodes = (body) ->
|
@@ -260,7 +267,7 @@ class window.Turbolinks
|
|
260
267
|
persistStaticElements = (body) ->
|
261
268
|
allNodesToKeep = []
|
262
269
|
|
263
|
-
nodes = TurboGraft.querySelectorAllTGAttribute(
|
270
|
+
nodes = TurboGraft.querySelectorAllTGAttribute(activeDocument, 'tg-static')
|
264
271
|
allNodesToKeep.push(node) for node in nodes
|
265
272
|
|
266
273
|
keepNodes(body, allNodesToKeep)
|
@@ -270,22 +277,22 @@ class window.Turbolinks
|
|
270
277
|
allNodesToKeep = []
|
271
278
|
|
272
279
|
for key in keys
|
273
|
-
for node in TurboGraft.querySelectorAllTGAttribute(
|
280
|
+
for node in TurboGraft.querySelectorAllTGAttribute(activeDocument, 'refresh', key)
|
274
281
|
allNodesToKeep.push(node)
|
275
282
|
|
276
283
|
keepNodes(body, allNodesToKeep)
|
277
284
|
return
|
278
285
|
|
279
286
|
executeScriptTags = ->
|
280
|
-
scripts = Array::slice.call
|
287
|
+
scripts = Array::slice.call activeDocument.body.querySelectorAll 'script:not([data-turbolinks-eval="false"])'
|
281
288
|
for script in scripts when script.type in ['', 'text/javascript']
|
282
289
|
executeScriptTag(script)
|
283
290
|
return
|
284
291
|
|
285
292
|
executeScriptTag = (script) ->
|
286
|
-
copy =
|
293
|
+
copy = activeDocument.createElement 'script'
|
287
294
|
copy.setAttribute attr.name, attr.value for attr in script.attributes
|
288
|
-
copy.appendChild
|
295
|
+
copy.appendChild activeDocument.createTextNode script.innerHTML
|
289
296
|
{ parentNode, nextSibling } = script
|
290
297
|
parentNode.removeChild script
|
291
298
|
parentNode.insertBefore copy, nextSibling
|
@@ -303,16 +310,16 @@ class window.Turbolinks
|
|
303
310
|
reflectRedirectedUrl = (xhr) ->
|
304
311
|
if location = xhr.getResponseHeader 'X-XHR-Redirected-To'
|
305
312
|
location = new ComponentUrl location
|
306
|
-
preservedHash = if location.hasNoHash() then
|
313
|
+
preservedHash = if location.hasNoHash() then activeDocument.location.hash else ''
|
307
314
|
Turbolinks.replaceState currentState, '', location.href + preservedHash
|
308
315
|
|
309
316
|
return
|
310
317
|
|
311
318
|
rememberReferer = ->
|
312
|
-
referer =
|
319
|
+
referer = activeDocument.location.href
|
313
320
|
|
314
321
|
@rememberCurrentUrl: ->
|
315
|
-
Turbolinks.replaceState { turbolinks: true, url:
|
322
|
+
Turbolinks.replaceState { turbolinks: true, url: activeDocument.location.href }, '', activeDocument.location.href
|
316
323
|
|
317
324
|
@rememberCurrentState: ->
|
318
325
|
currentState = window.history.state
|
@@ -321,26 +328,14 @@ class window.Turbolinks
|
|
321
328
|
window.scrollTo page.positionX, page.positionY
|
322
329
|
|
323
330
|
resetScrollPosition = ->
|
324
|
-
if
|
325
|
-
|
331
|
+
if activeDocument.location.hash
|
332
|
+
activeDocument.location.href = activeDocument.location.href
|
326
333
|
else
|
327
334
|
window.scrollTo 0, 0
|
328
335
|
|
329
336
|
pageChangePrevented = (url) ->
|
330
337
|
!triggerEvent('page:before-change', url)
|
331
338
|
|
332
|
-
processResponse = (xhr) ->
|
333
|
-
clientOrServerError = ->
|
334
|
-
return false if xhr.status == 422 # we want to render form validations
|
335
|
-
400 <= xhr.status < 600
|
336
|
-
|
337
|
-
validContent = ->
|
338
|
-
xhr.getResponseHeader('Content-Type').match /^(?:text\/html|application\/xhtml\+xml|application\/xml)(?:;|$)/
|
339
|
-
|
340
|
-
if !clientOrServerError() && validContent()
|
341
|
-
upstreamDocument = createDocument(xhr.responseText)
|
342
|
-
return upstreamDocument
|
343
|
-
|
344
339
|
installHistoryChangeHandler = (event) ->
|
345
340
|
if event.state?.turbolinks
|
346
341
|
Turbolinks.visit event.target.location.href
|
@@ -350,26 +345,15 @@ class window.Turbolinks
|
|
350
345
|
bypassOnLoadPopstate = (fn) ->
|
351
346
|
setTimeout fn, 500
|
352
347
|
|
353
|
-
createDocument = (html) ->
|
354
|
-
if /<(html|body)/i.test(html)
|
355
|
-
doc = document.documentElement.cloneNode()
|
356
|
-
doc.innerHTML = html
|
357
|
-
else
|
358
|
-
doc = document.documentElement.cloneNode(true)
|
359
|
-
doc.querySelector('body').innerHTML = html
|
360
|
-
doc.head = doc.querySelector('head')
|
361
|
-
doc.body = doc.querySelector('body')
|
362
|
-
doc
|
363
|
-
|
364
348
|
if browserSupportsTurbolinks
|
365
349
|
@visit = fetch
|
366
350
|
@rememberCurrentUrl()
|
367
351
|
@rememberCurrentState()
|
368
352
|
|
369
|
-
|
353
|
+
activeDocument.addEventListener 'click', Click.installHandlerLast, true
|
370
354
|
|
371
355
|
bypassOnLoadPopstate ->
|
372
356
|
window.addEventListener 'popstate', installHistoryChangeHandler, false
|
373
357
|
|
374
358
|
else
|
375
|
-
@visit = (url) ->
|
359
|
+
@visit = (url) -> activeDocument.location.href = url
|
data/lib/turbograft.rb
CHANGED
@@ -35,10 +35,8 @@ module TurboGraft
|
|
35
35
|
end
|
36
36
|
|
37
37
|
ActiveSupport.on_load(:action_view) do
|
38
|
-
(ActionView::RoutingUrlFor rescue ActionView::Helpers::UrlHelper).
|
39
|
-
|
40
|
-
end
|
41
|
-
end unless RUBY_VERSION =~ /^1\.8/
|
38
|
+
(ActionView::RoutingUrlFor rescue ActionView::Helpers::UrlHelper).prepend(XHRUrlFor)
|
39
|
+
end
|
42
40
|
end
|
43
41
|
end
|
44
42
|
end
|
data/lib/turbograft/version.rb
CHANGED
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: turbograft
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.4.
|
4
|
+
version: 0.4.3
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kristian Plettenberg-Dussault
|
@@ -13,7 +13,7 @@ authors:
|
|
13
13
|
autorequire:
|
14
14
|
bindir: bin
|
15
15
|
cert_chain: []
|
16
|
-
date: 2016-
|
16
|
+
date: 2016-10-05 00:00:00.000000000 Z
|
17
17
|
dependencies:
|
18
18
|
- !ruby/object:Gem::Dependency
|
19
19
|
name: coffee-rails
|
@@ -224,10 +224,12 @@ files:
|
|
224
224
|
- lib/assets/javascripts/turbograft/click.coffee
|
225
225
|
- lib/assets/javascripts/turbograft/component_url.coffee
|
226
226
|
- lib/assets/javascripts/turbograft/csrf_token.coffee
|
227
|
+
- lib/assets/javascripts/turbograft/document.coffee
|
227
228
|
- lib/assets/javascripts/turbograft/initializers.coffee
|
228
229
|
- lib/assets/javascripts/turbograft/link.coffee
|
229
230
|
- lib/assets/javascripts/turbograft/page.coffee
|
230
231
|
- lib/assets/javascripts/turbograft/remote.coffee
|
232
|
+
- lib/assets/javascripts/turbograft/response.coffee
|
231
233
|
- lib/assets/javascripts/turbograft/turbohead.coffee
|
232
234
|
- lib/assets/javascripts/turbograft/turbolinks.coffee
|
233
235
|
- lib/turbograft.rb
|
@@ -247,9 +249,9 @@ require_paths:
|
|
247
249
|
- lib
|
248
250
|
required_ruby_version: !ruby/object:Gem::Requirement
|
249
251
|
requirements:
|
250
|
-
- - "
|
252
|
+
- - "~>"
|
251
253
|
- !ruby/object:Gem::Version
|
252
|
-
version: '
|
254
|
+
version: '2.1'
|
253
255
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
254
256
|
requirements:
|
255
257
|
- - ">="
|