turbolinks 1.2.0 → 1.3.0
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +27 -7
- data/lib/assets/javascripts/turbolinks.js.coffee +52 -52
- metadata +3 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 1263ec55bfcb3699eb35184773029a0f1366b9af
|
4
|
+
data.tar.gz: 25bd7c81bfc177362c28bef759e0da5c98ddb354
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 401359f94e306dbb1314e2dc1335b892124ce215b7e80289cfda10ba84c4ec09e064a6c1c0bc0f176bf9368db5bc3f36ede90549d7bd2a9d6d4094bfd0977bee
|
7
|
+
data.tar.gz: fab798e6aeeea6c25bb0a522c632ae1813c1e10459c7a626a2db568590104e10ba017eb58add3261c7b1255dbd9326ebd8ee74f48765c87ced3e39761333f639
|
data/README.md
CHANGED
@@ -27,21 +27,34 @@ Turbolinks is designed to be as light-weight as possible (so you won't think twi
|
|
27
27
|
Events
|
28
28
|
------
|
29
29
|
|
30
|
-
With Turbolinks pages will change without a full reload, so you can't rely on `DOMContentLoaded` or `jQuery.ready()` to trigger your code. Instead Turbolinks fires events on `document` to provide hooks into the lifecycle of the page
|
30
|
+
With Turbolinks pages will change without a full reload, so you can't rely on `DOMContentLoaded` or `jQuery.ready()` to trigger your code. Instead Turbolinks fires events on `document` to provide hooks into the lifecycle of the page.
|
31
31
|
|
32
|
-
|
32
|
+
***Load* a fresh version of a page from the server:**
|
33
|
+
* `page:before-change` a Turbolinks-enabled link has been clicked *(see below for more details)*
|
33
34
|
* `page:fetch` starting to fetch a new target page
|
34
35
|
* `page:receive` the page has been fetched from the server, but not yet parsed
|
35
36
|
* `page:change` the page has been parsed and changed to the new version
|
36
37
|
* `page:load` is fired at the end of the loading process.
|
37
38
|
|
38
|
-
|
39
|
+
Handlers bound to the `page:before-change` event may return `false`, which will cancel the Turbolinks process.
|
39
40
|
|
40
|
-
|
41
|
+
By default, Turbolinks caches 10 of these page loads. It listens to the [popstate](https://developer.mozilla.org/en-US/docs/DOM/Manipulating_the_browser_history#The_popstate_event) event and attempts to restore page state from the cache when it's triggered. When `popstate` is fired the following process happens:
|
42
|
+
|
43
|
+
***Restore* a cached page from the client-side cache:**
|
41
44
|
* `page:change` page has changed to the cached page.
|
42
45
|
* `page:restore` is fired at the end of restore process.
|
43
46
|
|
44
|
-
|
47
|
+
The number of pages Turbolinks caches can be configured to suit your application's needs:
|
48
|
+
|
49
|
+
```javascript
|
50
|
+
// View the current cache size
|
51
|
+
Turbolinks.pagesCached();
|
52
|
+
|
53
|
+
// Set the cache size
|
54
|
+
Turbolinks.pagesCached(20);
|
55
|
+
```
|
56
|
+
|
57
|
+
To implement a client-side spinner, you could listen for `page:fetch` to start it and `page:receive` to stop it.
|
45
58
|
|
46
59
|
document.addEventListener("page:fetch", startSpinner);
|
47
60
|
document.addEventListener("page:receive", stopSpinner);
|
@@ -98,7 +111,10 @@ Asset change detection
|
|
98
111
|
|
99
112
|
You can track certain assets, like application.js and application.css, that you want to ensure are always of the latest version inside a Turbolinks session. This is done by marking those asset links with data-turbolinks-track, like so:
|
100
113
|
|
101
|
-
|
114
|
+
```html
|
115
|
+
<link href="/assets/application-9bd64a86adb3cd9ab3b16e9dca67a33a.css" rel="stylesheet"
|
116
|
+
type="text/css" data-turbolinks-track>
|
117
|
+
```
|
102
118
|
|
103
119
|
If those assets change URLs (embed an md5 stamp to ensure this), the page will do a full reload instead of going through Turbolinks. This ensures that all Turbolinks sessions will always be running off your latest JavaScript and CSS.
|
104
120
|
|
@@ -108,7 +124,7 @@ When this happens, you'll technically be requesting the same page twice. Once th
|
|
108
124
|
Evaluating script tags
|
109
125
|
----------------------
|
110
126
|
|
111
|
-
Turbolinks will evaluate any script tags in pages it
|
127
|
+
Turbolinks will evaluate any script tags in pages it visits, if those tags do not have a type or if the type is text/javascript. All other script tags will be ignored.
|
112
128
|
|
113
129
|
As a rule of thumb when switching to Turbolinks, move all of your javascript tags inside the `head` and then work backwards, only moving javascript code back to the body if absolutely necessary. If you have any script tags in the body you do not want to be re-evaluated then you can set the `data-turbolinks-eval` attribute to `false`:
|
114
130
|
|
@@ -146,6 +162,10 @@ Installation
|
|
146
162
|
1. Add `//= require turbolinks` to your Javascript manifest file (usually found at `app/assets/javascripts/application.js`).
|
147
163
|
1. Restart your server and you're now using turbolinks!
|
148
164
|
|
165
|
+
Language Ports
|
166
|
+
--------------
|
167
|
+
|
168
|
+
* [Flask Turbolinks](https://github.com/lepture/flask-turbolinks) (Python Flask)
|
149
169
|
|
150
170
|
Credits
|
151
171
|
-------
|
@@ -1,20 +1,12 @@
|
|
1
|
-
|
1
|
+
cacheSize = 10
|
2
2
|
currentState = null
|
3
|
-
referer =
|
3
|
+
referer = null
|
4
4
|
loadedAssets = null
|
5
5
|
pageCache = {}
|
6
6
|
createDocument = null
|
7
7
|
requestMethod = document.cookie.match(/request_method=(\w+)/)?[1].toUpperCase() or ''
|
8
8
|
xhr = null
|
9
9
|
|
10
|
-
visit = (url) ->
|
11
|
-
if browserSupportsPushState && browserIsntBuggy
|
12
|
-
cacheCurrentPage()
|
13
|
-
reflectNewUrl url
|
14
|
-
fetchReplacement url
|
15
|
-
else
|
16
|
-
document.location.href = url
|
17
|
-
|
18
10
|
|
19
11
|
fetchReplacement = (url) ->
|
20
12
|
triggerEvent 'page:fetch'
|
@@ -31,7 +23,8 @@ fetchReplacement = (url) ->
|
|
31
23
|
xhr.onload = ->
|
32
24
|
triggerEvent 'page:receive'
|
33
25
|
|
34
|
-
if doc =
|
26
|
+
if doc = processResponse()
|
27
|
+
reflectNewUrl url
|
35
28
|
changePage extractTitleAndBody(doc)...
|
36
29
|
reflectRedirectedUrl()
|
37
30
|
if document.location.hash
|
@@ -39,6 +32,8 @@ fetchReplacement = (url) ->
|
|
39
32
|
else
|
40
33
|
resetScrollPosition()
|
41
34
|
triggerEvent 'page:load'
|
35
|
+
else
|
36
|
+
document.location.href = url
|
42
37
|
|
43
38
|
xhr.onloadend = -> xhr = null
|
44
39
|
xhr.onabort = -> rememberCurrentUrl()
|
@@ -46,21 +41,16 @@ fetchReplacement = (url) ->
|
|
46
41
|
|
47
42
|
xhr.send()
|
48
43
|
|
49
|
-
fetchHistory = (
|
44
|
+
fetchHistory = (position) ->
|
50
45
|
cacheCurrentPage()
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
|
55
|
-
|
56
|
-
triggerEvent 'page:restore'
|
57
|
-
else
|
58
|
-
fetchReplacement document.location.href
|
46
|
+
page = pageCache[position]
|
47
|
+
xhr?.abort()
|
48
|
+
changePage page.title, page.body
|
49
|
+
recallScrollPosition page
|
50
|
+
triggerEvent 'page:restore'
|
59
51
|
|
60
52
|
|
61
53
|
cacheCurrentPage = ->
|
62
|
-
rememberInitialPage()
|
63
|
-
|
64
54
|
pageCache[currentState.position] =
|
65
55
|
url: document.location.href,
|
66
56
|
body: document.body,
|
@@ -68,7 +58,10 @@ cacheCurrentPage = ->
|
|
68
58
|
positionY: window.pageYOffset,
|
69
59
|
positionX: window.pageXOffset
|
70
60
|
|
71
|
-
constrainPageCacheTo
|
61
|
+
constrainPageCacheTo cacheSize
|
62
|
+
|
63
|
+
pagesCached = (size = cacheSize) ->
|
64
|
+
cacheSize = parseInt(size) if /^[\d]+$/.test size
|
72
65
|
|
73
66
|
constrainPageCacheTo = (limit) ->
|
74
67
|
for own key, value of pageCache
|
@@ -101,8 +94,7 @@ removeNoscriptTags = ->
|
|
101
94
|
return
|
102
95
|
|
103
96
|
reflectNewUrl = (url) ->
|
104
|
-
if url isnt
|
105
|
-
referer = document.location.href
|
97
|
+
if url isnt referer
|
106
98
|
window.history.pushState { turbolinks: true, position: currentState.position + 1 }, '', url
|
107
99
|
|
108
100
|
reflectRedirectedUrl = ->
|
@@ -116,13 +108,6 @@ rememberCurrentUrl = ->
|
|
116
108
|
rememberCurrentState = ->
|
117
109
|
currentState = window.history.state
|
118
110
|
|
119
|
-
rememberInitialPage = ->
|
120
|
-
unless initialized
|
121
|
-
rememberCurrentUrl()
|
122
|
-
rememberCurrentState()
|
123
|
-
createDocument = browserCompatibleDocumentParser()
|
124
|
-
initialized = true
|
125
|
-
|
126
111
|
recallScrollPosition = (page) ->
|
127
112
|
window.scrollTo page.positionX, page.positionY
|
128
113
|
|
@@ -141,13 +126,15 @@ triggerEvent = (name) ->
|
|
141
126
|
event.initEvent name, true, true
|
142
127
|
document.dispatchEvent event
|
143
128
|
|
129
|
+
pageChangePrevented = ->
|
130
|
+
!triggerEvent 'page:before-change'
|
144
131
|
|
145
|
-
|
132
|
+
processResponse = ->
|
146
133
|
clientOrServerError = ->
|
147
134
|
400 <= xhr.status < 600
|
148
135
|
|
149
|
-
|
150
|
-
|
136
|
+
validContent = ->
|
137
|
+
xhr.getResponseHeader('Content-Type').match /^(?:text\/html|application\/xhtml\+xml|application\/xml)(?:;|$)/
|
151
138
|
|
152
139
|
extractTrackAssets = (doc) ->
|
153
140
|
(node.src || node.href) for node in doc.head.childNodes when node.getAttribute?('data-turbolinks-track')?
|
@@ -161,17 +148,10 @@ validateResponse = ->
|
|
161
148
|
[a, b] = [b, a] if a.length > b.length
|
162
149
|
value for value in a when value in b
|
163
150
|
|
164
|
-
if clientOrServerError()
|
165
|
-
|
166
|
-
|
167
|
-
|
168
|
-
window.location.replace url
|
169
|
-
false
|
170
|
-
else if invalidContent() or assetsChanged (doc = createDocument xhr.responseText)
|
171
|
-
window.location.reload()
|
172
|
-
false
|
173
|
-
else
|
174
|
-
doc
|
151
|
+
if not clientOrServerError() and validContent()
|
152
|
+
doc = createDocument xhr.responseText
|
153
|
+
if doc and !assetsChanged doc
|
154
|
+
return doc
|
175
155
|
|
176
156
|
extractTitleAndBody = (doc) ->
|
177
157
|
title = doc.querySelector 'title'
|
@@ -234,7 +214,7 @@ handleClick = (event) ->
|
|
234
214
|
unless event.defaultPrevented
|
235
215
|
link = extractLink event
|
236
216
|
if link.nodeName is 'A' and !ignoreClick(event, link)
|
237
|
-
visit link.href
|
217
|
+
visit link.href unless pageChangePrevented()
|
238
218
|
event.preventDefault()
|
239
219
|
|
240
220
|
|
@@ -269,11 +249,19 @@ nonStandardClick = (event) ->
|
|
269
249
|
ignoreClick = (event, link) ->
|
270
250
|
crossOriginLink(link) or anchoredLink(link) or nonHtmlLink(link) or noTurbolink(link) or targetLink(link) or nonStandardClick(event)
|
271
251
|
|
272
|
-
|
273
252
|
initializeTurbolinks = ->
|
253
|
+
rememberCurrentUrl()
|
254
|
+
rememberCurrentState()
|
255
|
+
createDocument = browserCompatibleDocumentParser()
|
274
256
|
document.addEventListener 'click', installClickHandlerLast, true
|
275
257
|
window.addEventListener 'popstate', (event) ->
|
276
|
-
|
258
|
+
state = event.state
|
259
|
+
|
260
|
+
if state?.turbolinks
|
261
|
+
if pageCache[state.position]
|
262
|
+
fetchHistory state.position
|
263
|
+
else
|
264
|
+
visit event.target.location.href
|
277
265
|
, false
|
278
266
|
|
279
267
|
browserSupportsPushState =
|
@@ -285,7 +273,19 @@ browserIsntBuggy =
|
|
285
273
|
requestMethodIsSafe =
|
286
274
|
requestMethod in ['GET','']
|
287
275
|
|
288
|
-
|
276
|
+
if browserSupportsPushState and browserIsntBuggy and requestMethodIsSafe
|
277
|
+
visit = (url) ->
|
278
|
+
referer = document.location.href
|
279
|
+
cacheCurrentPage()
|
280
|
+
fetchReplacement url
|
281
|
+
|
282
|
+
initializeTurbolinks()
|
283
|
+
else
|
284
|
+
visit = (url) ->
|
285
|
+
document.location.href = url
|
289
286
|
|
290
|
-
#
|
291
|
-
|
287
|
+
# Public API
|
288
|
+
# Turbolinks.visit(url)
|
289
|
+
# Turbolinks.pagesCached()
|
290
|
+
# Turbolinks.pagesCached(20)
|
291
|
+
@Turbolinks = { visit, pagesCached }
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: turbolinks
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: 1.3.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- David Heinemeier Hansson
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date: 2013-
|
11
|
+
date: 2013-07-11 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: coffee-rails
|
@@ -60,7 +60,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
60
60
|
version: '0'
|
61
61
|
requirements: []
|
62
62
|
rubyforge_project:
|
63
|
-
rubygems_version: 2.0.
|
63
|
+
rubygems_version: 2.0.3
|
64
64
|
signing_key:
|
65
65
|
specification_version: 4
|
66
66
|
summary: Turbolinks makes following links in your web application faster (use with
|