turbograft 0.4.1 → 0.4.2

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 CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 908ca189eb5f9c51f6e061d844528bde62953db6
4
- data.tar.gz: 2b6f48a3f32d885e7d23ce33cd1f5fbdb2d2a6a2
3
+ metadata.gz: 1e699e8c4097b50cf1a8530b545dc15b0a285a5b
4
+ data.tar.gz: 60db5ecf8f5dc92ba320b3c88cfc97485255a953
5
5
  SHA512:
6
- metadata.gz: 5bc193a959af440b4af8312deea19d8356ac11a640d2d8189e7f9cb6fe10debb5f245033f6eff715287b85f4d665ea989eb6118e583e91e6111052ac3b03ba28
7
- data.tar.gz: 922997e629e3d77b3c6a2024273524149d8d5fceedb3d01d6c00d559eda8e8cf6ac3adacaa8bb49ac6b03180676d6a65650d5ceba61abf1ad4dd5761342678f7
6
+ metadata.gz: 9fd21cae920d11a5a6d755ed19e39fd50c6b0185e4bdbfcfb6e34485b90d810d15cc8a0f3a74b1eda351658f2b1983ebc3de5b1c986d89411c916cd02309c5ed
7
+ data.tar.gz: c0795f45590c5cea04be07a6aa0f91715fa22f3b3c0f19196e96c4179be0e89eb10e0cc33ffecc10288de3341f1d438d5542880112240fde4ab0da700d0d269a
data/README.md CHANGED
@@ -28,6 +28,9 @@ Turbograft was built with simplicity in mind. It intends to offer the smallest a
28
28
  * Replace `//= require turbolinks` with `//= require turbograft` in _app/assets/javascripts/application.js_
29
29
  * Run `bundle install`
30
30
 
31
+ ## Dependencies
32
+
33
+ Turbograft requires a browser that supports [`Promise`](https://developer.mozilla.org/en/docs/Web/JavaScript/Reference/Global_Objects/Promise), or a polyfill (e.g., [core-js](https://github.com/zloirock/core-js).)
31
34
 
32
35
  ## Usage
33
36
 
@@ -2,6 +2,14 @@ TRACKED_ASSET_SELECTOR = '[data-turbolinks-track]'
2
2
  TRACKED_ATTRIBUTE_NAME = 'turbolinksTrack'
3
3
  ANONYMOUS_TRACK_VALUE = 'true'
4
4
 
5
+ scriptPromises = {}
6
+ resolvePreviousRequest = null
7
+
8
+ waitForCompleteDownloads = ->
9
+ loadingPromises = Object.keys(scriptPromises).map (url) ->
10
+ scriptPromises[url]
11
+ Promise.all(loadingPromises)
12
+
5
13
  class window.TurboHead
6
14
  constructor: (@activeDocument, @upstreamDocument) ->
7
15
  @activeAssets = extractTrackedAssets(@activeDocument)
@@ -14,6 +22,12 @@ class window.TurboHead
14
22
  .filter(attributeMatches('nodeName', 'LINK'))
15
23
  .filter(noAttributeMatchesIn('href', @activeAssets))
16
24
 
25
+ @_testAPI: {
26
+ reset: ->
27
+ scriptPromises = {}
28
+ resolvePreviousRequest = null
29
+ }
30
+
17
31
  hasChangedAnonymousAssets: () ->
18
32
  anonymousUpstreamAssets = @upstreamAssets
19
33
  .filter(datasetMatches(TRACKED_ATTRIBUTE_NAME, ANONYMOUS_TRACK_VALUE))
@@ -39,9 +53,20 @@ class window.TurboHead
39
53
  hasAssetConflicts: () ->
40
54
  @hasNamedAssetConflicts() || @hasChangedAnonymousAssets()
41
55
 
42
- insertNewAssets: (callback) ->
56
+ waitForAssets: () ->
57
+ resolvePreviousRequest?(isCanceled: true)
58
+
59
+ new Promise((resolve) =>
60
+ resolvePreviousRequest = resolve
61
+ waitForCompleteDownloads()
62
+ .then(@_insertNewAssets)
63
+ .then(waitForCompleteDownloads)
64
+ .then(resolve)
65
+ )
66
+
67
+ _insertNewAssets: () =>
43
68
  updateLinkTags(@activeDocument, @newLinks)
44
- updateScriptTags(@activeDocument, @newScripts, callback)
69
+ updateScriptTags(@activeDocument, @newScripts)
45
70
 
46
71
  extractTrackedAssets = (doc) ->
47
72
  [].slice.call(doc.querySelectorAll(TRACKED_ASSET_SELECTOR))
@@ -76,37 +101,37 @@ noDatasetMatchesIn = (attribute, collection) ->
76
101
  updateLinkTags = (activeDocument, newLinks) ->
77
102
  # style tag load events don't work in all browsers
78
103
  # as such we just hope they load ¯\_(ツ)_/¯
79
- newLinks.forEach((linkNode) -> insertLinkTask(activeDocument, linkNode)())
80
-
81
- updateScriptTags = (activeDocument, newScripts, callback) ->
82
- asyncSeries(
83
- newScripts.map((scriptNode) -> insertScriptTask(activeDocument, scriptNode)),
84
- callback
104
+ newLinks.forEach((linkNode) ->
105
+ newNode = linkNode.cloneNode()
106
+ activeDocument.head.appendChild(newNode)
107
+ triggerEvent("page:after-link-inserted", newNode)
85
108
  )
86
109
 
87
- asyncSeries = (tasks, callback) ->
88
- return callback() if tasks.length == 0
89
- task = tasks.shift()
90
- task(-> asyncSeries(tasks, callback))
110
+ updateScriptTags = (activeDocument, newScripts) ->
111
+ promise = Promise.resolve()
112
+ newScripts.forEach (scriptNode) ->
113
+ promise = promise.then(-> insertScript(activeDocument, scriptNode))
114
+ promise
115
+
116
+ insertScript = (activeDocument, scriptNode) ->
117
+ url = scriptNode.src
118
+ if scriptPromises[url]
119
+ return scriptPromises[url]
91
120
 
92
- insertScriptTask = (activeDocument, scriptNode) ->
93
- # We need to clone script tags in order to ensure that the browser executes them.
121
+ # Clone script tags to guarantee browser execution.
94
122
  newNode = activeDocument.createElement('SCRIPT')
95
123
  newNode.setAttribute(attr.name, attr.value) for attr in scriptNode.attributes
96
124
  newNode.appendChild(activeDocument.createTextNode(scriptNode.innerHTML))
97
- insertAssetTask(activeDocument, newNode, 'script')
98
125
 
99
- insertLinkTask = (activeDocument, node) ->
100
- insertAssetTask(activeDocument, node.cloneNode(), 'link')
101
-
102
- insertAssetTask = (activeDocument, newNode, name) ->
103
- (done) ->
126
+ scriptPromises[url] = new Promise((resolve) ->
104
127
  onAssetEvent = (event) ->
105
- triggerEvent("page:#{name}-error", event) if event.type == 'error'
128
+ triggerEvent("page:#script-error", event) if event.type == 'error'
106
129
  newNode.removeEventListener('load', onAssetEvent)
107
130
  newNode.removeEventListener('error', onAssetEvent)
108
- done() if typeof done == 'function'
131
+ resolve()
132
+
109
133
  newNode.addEventListener('load', onAssetEvent)
110
134
  newNode.addEventListener('error', onAssetEvent)
111
135
  activeDocument.head.appendChild(newNode)
112
- triggerEvent("page:after-#{name}-inserted", newNode)
136
+ triggerEvent("page:after-script-inserted", newNode)
137
+ )
@@ -139,7 +139,9 @@ class window.Turbolinks
139
139
  if turbohead.hasAssetConflicts()
140
140
  return Turbolinks.fullPageNavigate(url.absolute)
141
141
  reflectNewUrl url if options.updatePushState
142
- turbohead.insertNewAssets(-> updateBody(upstreamDocument, xhr, options))
142
+ turbohead.waitForAssets().then((result) ->
143
+ updateBody(upstreamDocument, xhr, options) unless result?.isCanceled
144
+ )
143
145
  else
144
146
  triggerEvent 'page:error', xhr
145
147
  Turbolinks.fullPageNavigate(url.absolute) if url?
@@ -303,6 +305,7 @@ class window.Turbolinks
303
305
  location = new ComponentUrl location
304
306
  preservedHash = if location.hasNoHash() then document.location.hash else ''
305
307
  Turbolinks.replaceState currentState, '', location.href + preservedHash
308
+
306
309
  return
307
310
 
308
311
  rememberReferer = ->
@@ -1,3 +1,3 @@
1
1
  module TurboGraft
2
- VERSION = '0.4.1'
2
+ VERSION = '0.4.2'
3
3
  end
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.1
4
+ version: 0.4.2
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-09-06 00:00:00.000000000 Z
16
+ date: 2016-09-22 00:00:00.000000000 Z
17
17
  dependencies:
18
18
  - !ruby/object:Gem::Dependency
19
19
  name: coffee-rails