turbograft 0.4.8 → 0.5.0
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/README.md +5 -4
- data/lib/assets/javascripts/turbograft/click.js +44 -0
- data/lib/assets/javascripts/turbograft/component_url.js +53 -0
- data/lib/assets/javascripts/turbograft/csrf_token.js +23 -0
- data/lib/assets/javascripts/turbograft/document.js +20 -0
- data/lib/assets/javascripts/turbograft/initializers.js +83 -0
- data/lib/assets/javascripts/turbograft/link.js +58 -0
- data/lib/assets/javascripts/turbograft/page.js +105 -0
- data/lib/assets/javascripts/turbograft/remote.js +248 -0
- data/lib/assets/javascripts/turbograft/response.js +48 -0
- data/lib/assets/javascripts/turbograft/turbohead.js +159 -0
- data/lib/assets/javascripts/turbograft/turbolinks.js +504 -0
- data/lib/assets/javascripts/turbograft.js +37 -0
- data/lib/turbograft/version.rb +1 -1
- metadata +27 -27
- data/lib/assets/javascripts/turbograft/click.coffee +0 -34
- data/lib/assets/javascripts/turbograft/component_url.coffee +0 -24
- data/lib/assets/javascripts/turbograft/csrf_token.coffee +0 -9
- data/lib/assets/javascripts/turbograft/document.coffee +0 -11
- data/lib/assets/javascripts/turbograft/initializers.coffee +0 -67
- data/lib/assets/javascripts/turbograft/link.coffee +0 -41
- data/lib/assets/javascripts/turbograft/page.coffee +0 -77
- data/lib/assets/javascripts/turbograft/remote.coffee +0 -179
- data/lib/assets/javascripts/turbograft/response.coffee +0 -31
- data/lib/assets/javascripts/turbograft/turbohead.coffee +0 -142
- data/lib/assets/javascripts/turbograft/turbolinks.coffee +0 -361
- data/lib/assets/javascripts/turbograft.coffee +0 -30
@@ -0,0 +1,37 @@
|
|
1
|
+
//= require_self
|
2
|
+
//= require_tree ./turbograft
|
3
|
+
|
4
|
+
if (window.TurboGraft == null) { window.TurboGraft = { handlers: {} }; }
|
5
|
+
|
6
|
+
TurboGraft.tgAttribute = function(attr) {
|
7
|
+
if (attr.slice(0, 3) === 'tg-') {
|
8
|
+
return `data-${attr}`;
|
9
|
+
} else {
|
10
|
+
return `data-tg-${attr}`;
|
11
|
+
}
|
12
|
+
};
|
13
|
+
|
14
|
+
TurboGraft.getTGAttribute = function(node, attr) {
|
15
|
+
const tgAttr = TurboGraft.tgAttribute(attr);
|
16
|
+
return node.getAttribute(tgAttr) || node.getAttribute(attr);
|
17
|
+
};
|
18
|
+
|
19
|
+
TurboGraft.removeTGAttribute = function(node, attr) {
|
20
|
+
const tgAttr = TurboGraft.tgAttribute(attr);
|
21
|
+
node.removeAttribute(tgAttr);
|
22
|
+
node.removeAttribute(attr);
|
23
|
+
};
|
24
|
+
|
25
|
+
TurboGraft.hasTGAttribute = function(node, attr) {
|
26
|
+
const tgAttr = TurboGraft.tgAttribute(attr);
|
27
|
+
return node.hasAttribute(tgAttr) || node.hasAttribute(attr);
|
28
|
+
};
|
29
|
+
|
30
|
+
TurboGraft.querySelectorAllTGAttribute = function(node, attr, value = null) {
|
31
|
+
const tgAttr = TurboGraft.tgAttribute(attr);
|
32
|
+
if (value) {
|
33
|
+
return node.querySelectorAll(`[${tgAttr}=${value}], [${attr}=${value}]`);
|
34
|
+
} else {
|
35
|
+
return node.querySelectorAll(`[${tgAttr}], [${attr}]`);
|
36
|
+
}
|
37
|
+
};
|
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
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- Kristian Plettenberg-Dussault
|
@@ -15,16 +15,16 @@ authors:
|
|
15
15
|
autorequire:
|
16
16
|
bindir: bin
|
17
17
|
cert_chain: []
|
18
|
-
date:
|
18
|
+
date: 2023-09-14 00:00:00.000000000 Z
|
19
19
|
dependencies:
|
20
20
|
- !ruby/object:Gem::Dependency
|
21
|
-
name:
|
21
|
+
name: bundler
|
22
22
|
requirement: !ruby/object:Gem::Requirement
|
23
23
|
requirements:
|
24
24
|
- - ">="
|
25
25
|
- !ruby/object:Gem::Version
|
26
26
|
version: '0'
|
27
|
-
type: :
|
27
|
+
type: :development
|
28
28
|
prerelease: false
|
29
29
|
version_requirements: !ruby/object:Gem::Requirement
|
30
30
|
requirements:
|
@@ -32,7 +32,7 @@ dependencies:
|
|
32
32
|
- !ruby/object:Gem::Version
|
33
33
|
version: '0'
|
34
34
|
- !ruby/object:Gem::Dependency
|
35
|
-
name:
|
35
|
+
name: rake
|
36
36
|
requirement: !ruby/object:Gem::Requirement
|
37
37
|
requirements:
|
38
38
|
- - ">="
|
@@ -46,7 +46,7 @@ dependencies:
|
|
46
46
|
- !ruby/object:Gem::Version
|
47
47
|
version: '0'
|
48
48
|
- !ruby/object:Gem::Dependency
|
49
|
-
name:
|
49
|
+
name: rails
|
50
50
|
requirement: !ruby/object:Gem::Requirement
|
51
51
|
requirements:
|
52
52
|
- - ">="
|
@@ -60,7 +60,7 @@ dependencies:
|
|
60
60
|
- !ruby/object:Gem::Version
|
61
61
|
version: '0'
|
62
62
|
- !ruby/object:Gem::Dependency
|
63
|
-
name: rails
|
63
|
+
name: jquery-rails
|
64
64
|
requirement: !ruby/object:Gem::Requirement
|
65
65
|
requirements:
|
66
66
|
- - ">="
|
@@ -74,7 +74,7 @@ dependencies:
|
|
74
74
|
- !ruby/object:Gem::Version
|
75
75
|
version: '0'
|
76
76
|
- !ruby/object:Gem::Dependency
|
77
|
-
name:
|
77
|
+
name: minitest-reporters
|
78
78
|
requirement: !ruby/object:Gem::Requirement
|
79
79
|
requirements:
|
80
80
|
- - ">="
|
@@ -88,7 +88,7 @@ dependencies:
|
|
88
88
|
- !ruby/object:Gem::Version
|
89
89
|
version: '0'
|
90
90
|
- !ruby/object:Gem::Dependency
|
91
|
-
name:
|
91
|
+
name: capybara
|
92
92
|
requirement: !ruby/object:Gem::Requirement
|
93
93
|
requirements:
|
94
94
|
- - ">="
|
@@ -102,7 +102,7 @@ dependencies:
|
|
102
102
|
- !ruby/object:Gem::Version
|
103
103
|
version: '0'
|
104
104
|
- !ruby/object:Gem::Dependency
|
105
|
-
name:
|
105
|
+
name: selenium-webdriver
|
106
106
|
requirement: !ruby/object:Gem::Requirement
|
107
107
|
requirements:
|
108
108
|
- - ">="
|
@@ -116,7 +116,7 @@ dependencies:
|
|
116
116
|
- !ruby/object:Gem::Version
|
117
117
|
version: '0'
|
118
118
|
- !ruby/object:Gem::Dependency
|
119
|
-
name:
|
119
|
+
name: teaspoon-mocha
|
120
120
|
requirement: !ruby/object:Gem::Requirement
|
121
121
|
requirements:
|
122
122
|
- - ">="
|
@@ -130,7 +130,7 @@ dependencies:
|
|
130
130
|
- !ruby/object:Gem::Version
|
131
131
|
version: '0'
|
132
132
|
- !ruby/object:Gem::Dependency
|
133
|
-
name:
|
133
|
+
name: sqlite3
|
134
134
|
requirement: !ruby/object:Gem::Requirement
|
135
135
|
requirements:
|
136
136
|
- - ">="
|
@@ -144,7 +144,7 @@ dependencies:
|
|
144
144
|
- !ruby/object:Gem::Version
|
145
145
|
version: '0'
|
146
146
|
- !ruby/object:Gem::Dependency
|
147
|
-
name:
|
147
|
+
name: thin
|
148
148
|
requirement: !ruby/object:Gem::Requirement
|
149
149
|
requirements:
|
150
150
|
- - ">="
|
@@ -158,7 +158,7 @@ dependencies:
|
|
158
158
|
- !ruby/object:Gem::Version
|
159
159
|
version: '0'
|
160
160
|
- !ruby/object:Gem::Dependency
|
161
|
-
name:
|
161
|
+
name: webrick
|
162
162
|
requirement: !ruby/object:Gem::Requirement
|
163
163
|
requirements:
|
164
164
|
- - ">="
|
@@ -224,18 +224,18 @@ extra_rdoc_files: []
|
|
224
224
|
files:
|
225
225
|
- MIT-LICENSE
|
226
226
|
- README.md
|
227
|
-
- lib/assets/javascripts/turbograft.
|
228
|
-
- lib/assets/javascripts/turbograft/click.
|
229
|
-
- lib/assets/javascripts/turbograft/component_url.
|
230
|
-
- lib/assets/javascripts/turbograft/csrf_token.
|
231
|
-
- lib/assets/javascripts/turbograft/document.
|
232
|
-
- lib/assets/javascripts/turbograft/initializers.
|
233
|
-
- lib/assets/javascripts/turbograft/link.
|
234
|
-
- lib/assets/javascripts/turbograft/page.
|
235
|
-
- lib/assets/javascripts/turbograft/remote.
|
236
|
-
- lib/assets/javascripts/turbograft/response.
|
237
|
-
- lib/assets/javascripts/turbograft/turbohead.
|
238
|
-
- lib/assets/javascripts/turbograft/turbolinks.
|
227
|
+
- lib/assets/javascripts/turbograft.js
|
228
|
+
- lib/assets/javascripts/turbograft/click.js
|
229
|
+
- lib/assets/javascripts/turbograft/component_url.js
|
230
|
+
- lib/assets/javascripts/turbograft/csrf_token.js
|
231
|
+
- lib/assets/javascripts/turbograft/document.js
|
232
|
+
- lib/assets/javascripts/turbograft/initializers.js
|
233
|
+
- lib/assets/javascripts/turbograft/link.js
|
234
|
+
- lib/assets/javascripts/turbograft/page.js
|
235
|
+
- lib/assets/javascripts/turbograft/remote.js
|
236
|
+
- lib/assets/javascripts/turbograft/response.js
|
237
|
+
- lib/assets/javascripts/turbograft/turbohead.js
|
238
|
+
- lib/assets/javascripts/turbograft/turbolinks.js
|
239
239
|
- lib/turbograft.rb
|
240
240
|
- lib/turbograft/cookies.rb
|
241
241
|
- lib/turbograft/redirection.rb
|
@@ -263,7 +263,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
263
263
|
- !ruby/object:Gem::Version
|
264
264
|
version: '0'
|
265
265
|
requirements: []
|
266
|
-
rubygems_version: 3.
|
266
|
+
rubygems_version: 3.4.19
|
267
267
|
signing_key:
|
268
268
|
specification_version: 4
|
269
269
|
summary: turbolinks with partial page replacement
|
@@ -1,34 +0,0 @@
|
|
1
|
-
# The Click class handles clicked links, verifying if Turbolinks should
|
2
|
-
# take control by inspecting both the event and the link. If it should,
|
3
|
-
# the page change process is initiated. If not, control is passed back
|
4
|
-
# to the browser for default functionality.
|
5
|
-
class window.Click
|
6
|
-
@installHandlerLast: (event) ->
|
7
|
-
unless event.defaultPrevented
|
8
|
-
document.removeEventListener 'click', Click.handle, false
|
9
|
-
document.addEventListener 'click', Click.handle, false
|
10
|
-
|
11
|
-
@handle: (event) ->
|
12
|
-
new Click event
|
13
|
-
|
14
|
-
constructor: (@event) ->
|
15
|
-
return if @event.defaultPrevented
|
16
|
-
@_extractLink()
|
17
|
-
if @_validForTurbolinks()
|
18
|
-
Turbolinks.visit @link.href
|
19
|
-
@event.preventDefault()
|
20
|
-
|
21
|
-
_extractLink: ->
|
22
|
-
link = @event.target
|
23
|
-
link = link.parentNode until !link.parentNode or link.nodeName is 'A'
|
24
|
-
@link = new Link(link) if link.nodeName is 'A' and link.href.length isnt 0
|
25
|
-
|
26
|
-
_validForTurbolinks: ->
|
27
|
-
@link? and not (@link.shouldIgnore() or @_nonStandardClick())
|
28
|
-
|
29
|
-
_nonStandardClick: ->
|
30
|
-
@event.which > 1 or
|
31
|
-
@event.metaKey or
|
32
|
-
@event.ctrlKey or
|
33
|
-
@event.shiftKey or
|
34
|
-
@event.altKey
|
@@ -1,24 +0,0 @@
|
|
1
|
-
# The ComponentUrl class converts a basic URL string into an object
|
2
|
-
# that behaves similarly to document.location.
|
3
|
-
#
|
4
|
-
# If an instance is created from a relative URL, the current document
|
5
|
-
# is used to fill in the missing attributes (protocol, host, port).
|
6
|
-
class window.ComponentUrl
|
7
|
-
constructor: (@original = document.location.href) ->
|
8
|
-
return @original if @original.constructor is ComponentUrl
|
9
|
-
@_parse()
|
10
|
-
|
11
|
-
withoutHash: -> @href.replace @hash, ''
|
12
|
-
|
13
|
-
# Intention revealing function alias
|
14
|
-
withoutHashForIE10compatibility: -> @withoutHash()
|
15
|
-
|
16
|
-
hasNoHash: -> @hash.length is 0
|
17
|
-
|
18
|
-
_parse: ->
|
19
|
-
(@link ?= document.createElement 'a').href = @original
|
20
|
-
{ @href, @protocol, @host, @hostname, @port, @pathname, @search, @hash } = @link
|
21
|
-
@origin = [@protocol, '//', @hostname].join ''
|
22
|
-
@origin += ":#{@port}" unless @port.length is 0
|
23
|
-
@relative = [@pathname, @search, @hash].join ''
|
24
|
-
@absolute = @href
|
@@ -1,9 +0,0 @@
|
|
1
|
-
class window.CSRFToken
|
2
|
-
@get: (doc = document) ->
|
3
|
-
node: tag = doc.querySelector 'meta[name="csrf-token"]'
|
4
|
-
token: tag?.getAttribute? 'content'
|
5
|
-
|
6
|
-
@update: (latest) ->
|
7
|
-
current = @get()
|
8
|
-
if current.token? and latest? and current.token isnt latest
|
9
|
-
current.node.setAttribute 'content', latest
|
@@ -1,11 +0,0 @@
|
|
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
|
@@ -1,67 +0,0 @@
|
|
1
|
-
hasClass = (node, search) ->
|
2
|
-
node.classList.contains(search)
|
3
|
-
|
4
|
-
nodeIsDisabled = (node) ->
|
5
|
-
node.getAttribute('disabled') || hasClass(node, 'disabled')
|
6
|
-
|
7
|
-
setupRemoteFromTarget = (target, httpRequestType, form = null) ->
|
8
|
-
httpUrl = target.getAttribute('href') || target.getAttribute('action')
|
9
|
-
|
10
|
-
throw new Error("Turbograft developer error: You did not provide a URL ('#{urlAttribute}' attribute) for data-tg-remote") unless httpUrl
|
11
|
-
|
12
|
-
if TurboGraft.getTGAttribute(target, "remote-once")
|
13
|
-
TurboGraft.removeTGAttribute(target, "remote-once")
|
14
|
-
TurboGraft.removeTGAttribute(target, "tg-remote")
|
15
|
-
|
16
|
-
options =
|
17
|
-
httpRequestType: httpRequestType
|
18
|
-
httpUrl: httpUrl
|
19
|
-
fullRefresh: TurboGraft.getTGAttribute(target, 'full-refresh')?
|
20
|
-
refreshOnSuccess: TurboGraft.getTGAttribute(target, 'refresh-on-success')
|
21
|
-
refreshOnSuccessExcept: TurboGraft.getTGAttribute(target, 'full-refresh-on-success-except')
|
22
|
-
refreshOnError: TurboGraft.getTGAttribute(target, 'refresh-on-error')
|
23
|
-
refreshOnErrorExcept: TurboGraft.getTGAttribute(target, 'full-refresh-on-error-except')
|
24
|
-
|
25
|
-
new TurboGraft.Remote(options, form, target)
|
26
|
-
|
27
|
-
TurboGraft.handlers.remoteMethodHandler = (ev) ->
|
28
|
-
target = ev.clickTarget
|
29
|
-
httpRequestType = TurboGraft.getTGAttribute(target, 'tg-remote')
|
30
|
-
|
31
|
-
return unless httpRequestType
|
32
|
-
ev.preventDefault()
|
33
|
-
|
34
|
-
remote = setupRemoteFromTarget(target, httpRequestType)
|
35
|
-
remote.submit()
|
36
|
-
return
|
37
|
-
|
38
|
-
TurboGraft.handlers.remoteFormHandler = (ev) ->
|
39
|
-
target = ev.target
|
40
|
-
method = target.getAttribute('method')
|
41
|
-
|
42
|
-
return unless TurboGraft.hasTGAttribute(target, 'tg-remote')
|
43
|
-
ev.preventDefault()
|
44
|
-
|
45
|
-
remote = setupRemoteFromTarget(target, method, target)
|
46
|
-
remote.submit()
|
47
|
-
return
|
48
|
-
|
49
|
-
documentListenerForButtons = (eventType, handler, useCapture = false) ->
|
50
|
-
document.addEventListener eventType, (ev) ->
|
51
|
-
target = ev.target
|
52
|
-
|
53
|
-
while target != document && target?
|
54
|
-
if target.nodeName == "A" || target.nodeName == "BUTTON"
|
55
|
-
isNodeDisabled = nodeIsDisabled(target)
|
56
|
-
ev.preventDefault() if isNodeDisabled
|
57
|
-
unless isNodeDisabled
|
58
|
-
ev.clickTarget = target
|
59
|
-
handler(ev)
|
60
|
-
return
|
61
|
-
|
62
|
-
target = target.parentNode
|
63
|
-
|
64
|
-
documentListenerForButtons('click', TurboGraft.handlers.remoteMethodHandler, true)
|
65
|
-
|
66
|
-
document.addEventListener "submit", (ev) ->
|
67
|
-
TurboGraft.handlers.remoteFormHandler(ev)
|
@@ -1,41 +0,0 @@
|
|
1
|
-
# The Link class derives from the ComponentUrl class, but is built from an
|
2
|
-
# existing link element. Provides verification functionality for Turbolinks
|
3
|
-
# to use in determining whether it should process the link when clicked.
|
4
|
-
class window.Link extends ComponentUrl
|
5
|
-
@HTML_EXTENSIONS: ['html']
|
6
|
-
|
7
|
-
@allowExtensions: (extensions...) ->
|
8
|
-
Link.HTML_EXTENSIONS.push extension for extension in extensions
|
9
|
-
Link.HTML_EXTENSIONS
|
10
|
-
|
11
|
-
constructor: (@link) ->
|
12
|
-
return @link if @link.constructor is Link
|
13
|
-
@original = @link.href
|
14
|
-
super
|
15
|
-
|
16
|
-
shouldIgnore: ->
|
17
|
-
@_crossOrigin() or
|
18
|
-
@_anchored() or
|
19
|
-
@_nonHtml() or
|
20
|
-
@_optOut() or
|
21
|
-
@_target()
|
22
|
-
|
23
|
-
_crossOrigin: ->
|
24
|
-
@origin isnt (new ComponentUrl).origin
|
25
|
-
|
26
|
-
_anchored: ->
|
27
|
-
((@hash and @withoutHash()) is (current = new ComponentUrl).withoutHash()) or
|
28
|
-
(@href is current.href + '#')
|
29
|
-
|
30
|
-
_nonHtml: ->
|
31
|
-
@pathname.match(/\.[a-z]+$/g) and not @pathname.match(new RegExp("\\.(?:#{Link.HTML_EXTENSIONS.join('|')})?$", 'g'))
|
32
|
-
|
33
|
-
_optOut: ->
|
34
|
-
link = @link
|
35
|
-
until ignore or link is document or link is null
|
36
|
-
ignore = link.getAttribute('data-no-turbolink')?
|
37
|
-
link = link.parentNode
|
38
|
-
ignore
|
39
|
-
|
40
|
-
_target: ->
|
41
|
-
@link.target.length isnt 0
|
@@ -1,77 +0,0 @@
|
|
1
|
-
window.Page = {} if !window.Page
|
2
|
-
|
3
|
-
Page.visit = (url, opts={}) ->
|
4
|
-
if opts.reload
|
5
|
-
window.location = url
|
6
|
-
else
|
7
|
-
Turbolinks.visit(url)
|
8
|
-
|
9
|
-
Page.refresh = (options = {}, callback) ->
|
10
|
-
newUrl = if options.url
|
11
|
-
options.url
|
12
|
-
else if options.queryParams
|
13
|
-
paramString = $.param(options.queryParams)
|
14
|
-
paramString = "?#{paramString}" if paramString
|
15
|
-
location.pathname + paramString
|
16
|
-
else
|
17
|
-
location.href
|
18
|
-
|
19
|
-
turboOptions = {
|
20
|
-
partialReplace: true,
|
21
|
-
exceptKeys: options.exceptKeys,
|
22
|
-
onlyKeys: options.onlyKeys,
|
23
|
-
updatePushState: options.updatePushState,
|
24
|
-
callback: callback
|
25
|
-
}
|
26
|
-
|
27
|
-
if xhr = options.response
|
28
|
-
Turbolinks.loadPage null, xhr, turboOptions
|
29
|
-
else
|
30
|
-
Turbolinks.visit newUrl, turboOptions
|
31
|
-
|
32
|
-
Page.open = ->
|
33
|
-
window.open(arguments...)
|
34
|
-
|
35
|
-
# Providing hooks for objects to set up destructors:
|
36
|
-
onReplaceCallbacks = []
|
37
|
-
|
38
|
-
# e.g., Page.onReplace(node, unbindListenersFnc)
|
39
|
-
# unbindListenersFnc will be called if the node in question is partially replaced
|
40
|
-
# or if a full replace occurs. It will be called only once
|
41
|
-
Page.onReplace = (node, callback) ->
|
42
|
-
throw new Error("Page.onReplace: Node and callback must both be specified") if !node || !callback
|
43
|
-
throw new Error("Page.onReplace: Callback must be a function") if !isFunction(callback)
|
44
|
-
onReplaceCallbacks.push({node, callback})
|
45
|
-
|
46
|
-
# option C from http://jsperf.com/alternative-isfunction-implementations
|
47
|
-
isFunction = (object) ->
|
48
|
-
!!(object && object.constructor && object.call && object.apply)
|
49
|
-
|
50
|
-
# roughly based on http://davidwalsh.name/check-parent-node (note, OP is incorrect)
|
51
|
-
contains = (parentNode, childNode) ->
|
52
|
-
if parentNode.contains
|
53
|
-
parentNode.contains(childNode)
|
54
|
-
else # old browser compatability
|
55
|
-
!!((parentNode == childNode) || (parentNode.compareDocumentPosition(childNode) & Node.DOCUMENT_POSITION_CONTAINED_BY))
|
56
|
-
|
57
|
-
document.addEventListener 'page:before-partial-replace', (event) ->
|
58
|
-
replacedNodes = event.data
|
59
|
-
|
60
|
-
unprocessedOnReplaceCallbacks = []
|
61
|
-
for entry in onReplaceCallbacks
|
62
|
-
fired = false
|
63
|
-
for replacedNode in replacedNodes
|
64
|
-
if contains(replacedNode, entry.node)
|
65
|
-
entry.callback()
|
66
|
-
fired = true
|
67
|
-
break
|
68
|
-
|
69
|
-
unless fired
|
70
|
-
unprocessedOnReplaceCallbacks.push(entry)
|
71
|
-
|
72
|
-
onReplaceCallbacks = unprocessedOnReplaceCallbacks
|
73
|
-
|
74
|
-
document.addEventListener 'page:before-replace', (event) ->
|
75
|
-
for entry in onReplaceCallbacks
|
76
|
-
entry.callback()
|
77
|
-
onReplaceCallbacks = []
|
@@ -1,179 +0,0 @@
|
|
1
|
-
class TurboGraft.Remote
|
2
|
-
constructor: (@opts, form, target) ->
|
3
|
-
|
4
|
-
@initiator = form || target
|
5
|
-
|
6
|
-
@actualRequestType = if @opts.httpRequestType?.toLowerCase() == 'get' then 'GET' else 'POST'
|
7
|
-
@useNativeEncoding = @opts.useNativeEncoding
|
8
|
-
|
9
|
-
@formData = @createPayload(form)
|
10
|
-
|
11
|
-
@refreshOnSuccess = @opts.refreshOnSuccess.split(" ") if @opts.refreshOnSuccess
|
12
|
-
@refreshOnSuccessExcept = @opts.refreshOnSuccessExcept.split(" ") if @opts.refreshOnSuccessExcept
|
13
|
-
@refreshOnError = @opts.refreshOnError.split(" ") if @opts.refreshOnError
|
14
|
-
@refreshOnErrorExcept = @opts.refreshOnErrorExcept.split(" ") if @opts.refreshOnErrorExcept
|
15
|
-
|
16
|
-
xhr = new XMLHttpRequest
|
17
|
-
if @actualRequestType == 'GET'
|
18
|
-
url = if @formData then @opts.httpUrl + "?#{@formData}" else @opts.httpUrl
|
19
|
-
xhr.open(@actualRequestType, url, true)
|
20
|
-
else
|
21
|
-
xhr.open(@actualRequestType, @opts.httpUrl, true)
|
22
|
-
xhr.setRequestHeader('X-Requested-With', 'XMLHttpRequest')
|
23
|
-
xhr.setRequestHeader('Accept', 'text/html, application/xhtml+xml, application/xml')
|
24
|
-
xhr.setRequestHeader("Content-Type", @contentType) if @contentType
|
25
|
-
xhr.setRequestHeader 'X-XHR-Referer', document.location.href
|
26
|
-
|
27
|
-
csrfToken = CSRFToken.get().token
|
28
|
-
xhr.setRequestHeader('X-CSRF-Token', csrfToken) if csrfToken
|
29
|
-
|
30
|
-
triggerEventFor('turbograft:remote:init', @initiator, {xhr: xhr, initiator: @initiator})
|
31
|
-
|
32
|
-
xhr.addEventListener 'loadstart', =>
|
33
|
-
triggerEventFor 'turbograft:remote:start', @initiator,
|
34
|
-
xhr: xhr
|
35
|
-
|
36
|
-
xhr.addEventListener 'error', @onError
|
37
|
-
xhr.addEventListener 'load', (event) =>
|
38
|
-
if xhr.status < 400
|
39
|
-
@onSuccess(event)
|
40
|
-
else
|
41
|
-
@onError(event)
|
42
|
-
|
43
|
-
xhr.addEventListener 'loadend', =>
|
44
|
-
@opts.done?()
|
45
|
-
triggerEventFor 'turbograft:remote:always', @initiator,
|
46
|
-
initiator: @initiator
|
47
|
-
xhr: xhr
|
48
|
-
|
49
|
-
@xhr = xhr
|
50
|
-
|
51
|
-
submit: ->
|
52
|
-
@xhr.send(@formData)
|
53
|
-
|
54
|
-
createPayload: (form) ->
|
55
|
-
if form
|
56
|
-
if @useNativeEncoding || form.querySelectorAll("[type='file'][name]").length > 0
|
57
|
-
formData = @nativeEncodeForm(form)
|
58
|
-
else # for much smaller payloads
|
59
|
-
formData = @uriEncodeForm(form)
|
60
|
-
else
|
61
|
-
formData = ''
|
62
|
-
|
63
|
-
if formData not instanceof FormData
|
64
|
-
@contentType = "application/x-www-form-urlencoded; charset=UTF-8"
|
65
|
-
formData = @formAppend(formData, "_method", @opts.httpRequestType) if formData.indexOf("_method") == -1 && @opts.httpRequestType && @actualRequestType != 'GET'
|
66
|
-
|
67
|
-
formData
|
68
|
-
|
69
|
-
formAppend: (uriEncoded, key, value) ->
|
70
|
-
uriEncoded += "&" if uriEncoded.length
|
71
|
-
uriEncoded += "#{encodeURIComponent(key)}=#{encodeURIComponent(value)}"
|
72
|
-
|
73
|
-
uriEncodeForm: (form) ->
|
74
|
-
formData = ""
|
75
|
-
@_iterateOverFormInputs form, (input) =>
|
76
|
-
formData = @formAppend(formData, input.name, input.value)
|
77
|
-
formData
|
78
|
-
|
79
|
-
formDataAppend: (formData, input) ->
|
80
|
-
if input.type == 'file'
|
81
|
-
for file in input.files
|
82
|
-
formData.append(input.name, file)
|
83
|
-
else
|
84
|
-
formData.append(input.name, input.value)
|
85
|
-
formData
|
86
|
-
|
87
|
-
nativeEncodeForm: (form) ->
|
88
|
-
formData = new FormData
|
89
|
-
@_iterateOverFormInputs form, (input) =>
|
90
|
-
formData = @formDataAppend(formData, input)
|
91
|
-
formData
|
92
|
-
|
93
|
-
_iterateOverFormInputs: (form, callback) ->
|
94
|
-
inputs = @_enabledInputs(form)
|
95
|
-
for input in inputs
|
96
|
-
inputEnabled = !input.disabled
|
97
|
-
radioOrCheck = (input.type == 'checkbox' || input.type == 'radio')
|
98
|
-
|
99
|
-
if inputEnabled && input.name
|
100
|
-
if (radioOrCheck && input.checked) || !radioOrCheck
|
101
|
-
callback(input)
|
102
|
-
|
103
|
-
_enabledInputs: (form) ->
|
104
|
-
selector = "input:not([type='reset']):not([type='button']):not([type='submit']):not([type='image']), select, textarea"
|
105
|
-
inputs = Array::slice.call(form.querySelectorAll(selector))
|
106
|
-
disabledNodes = Array::slice.call(TurboGraft.querySelectorAllTGAttribute(form, 'tg-remote-noserialize'))
|
107
|
-
|
108
|
-
return inputs unless disabledNodes.length
|
109
|
-
|
110
|
-
disabledInputs = disabledNodes
|
111
|
-
for node in disabledNodes
|
112
|
-
disabledInputs = disabledInputs.concat(Array::slice.call(node.querySelectorAll(selector)))
|
113
|
-
|
114
|
-
enabledInputs = []
|
115
|
-
for input in inputs when disabledInputs.indexOf(input) < 0
|
116
|
-
enabledInputs.push(input)
|
117
|
-
enabledInputs
|
118
|
-
|
119
|
-
onSuccess: (ev) =>
|
120
|
-
@opts.success?()
|
121
|
-
|
122
|
-
xhr = ev.target
|
123
|
-
triggerEventFor 'turbograft:remote:success', @initiator,
|
124
|
-
initiator: @initiator
|
125
|
-
xhr: xhr
|
126
|
-
|
127
|
-
if redirect = xhr.getResponseHeader('X-Next-Redirect')
|
128
|
-
Page.visit(redirect, reload: true)
|
129
|
-
return
|
130
|
-
|
131
|
-
unless TurboGraft.hasTGAttribute(@initiator, 'tg-remote-norefresh')
|
132
|
-
if @opts.fullRefresh && @refreshOnSuccess
|
133
|
-
Page.refresh(onlyKeys: @refreshOnSuccess)
|
134
|
-
else if @opts.fullRefresh
|
135
|
-
Page.refresh()
|
136
|
-
else if @refreshOnSuccess
|
137
|
-
Page.refresh(
|
138
|
-
response: xhr
|
139
|
-
onlyKeys: @refreshOnSuccess
|
140
|
-
)
|
141
|
-
else if @refreshOnSuccessExcept
|
142
|
-
Page.refresh(
|
143
|
-
response: xhr
|
144
|
-
exceptKeys: @refreshOnSuccessExcept
|
145
|
-
)
|
146
|
-
else
|
147
|
-
Page.refresh(
|
148
|
-
response: xhr
|
149
|
-
)
|
150
|
-
|
151
|
-
onError: (ev) =>
|
152
|
-
@opts.fail?()
|
153
|
-
|
154
|
-
xhr = ev.target
|
155
|
-
triggerEventFor 'turbograft:remote:fail', @initiator,
|
156
|
-
initiator: @initiator
|
157
|
-
xhr: xhr
|
158
|
-
|
159
|
-
if TurboGraft.hasTGAttribute(@initiator, 'tg-remote-norefresh')
|
160
|
-
triggerEventFor 'turbograft:remote:fail:unhandled', @initiator,
|
161
|
-
xhr: xhr
|
162
|
-
else
|
163
|
-
if @opts.fullRefresh && @refreshOnError
|
164
|
-
Page.refresh(onlyKeys: @refreshOnError)
|
165
|
-
else if @opts.fullRefresh
|
166
|
-
Page.refresh()
|
167
|
-
else if @refreshOnError
|
168
|
-
Page.refresh(
|
169
|
-
response: xhr
|
170
|
-
onlyKeys: @refreshOnError
|
171
|
-
)
|
172
|
-
else if @refreshOnErrorExcept
|
173
|
-
Page.refresh(
|
174
|
-
response: xhr
|
175
|
-
exceptKeys: @refreshOnErrorExcept
|
176
|
-
)
|
177
|
-
else
|
178
|
-
triggerEventFor 'turbograft:remote:fail:unhandled', @initiator,
|
179
|
-
xhr: xhr
|
@@ -1,31 +0,0 @@
|
|
1
|
-
class TurboGraft.Response
|
2
|
-
constructor: (@xhr, intendedURL) ->
|
3
|
-
if intendedURL && intendedURL.withoutHash() != @xhr.responseURL
|
4
|
-
redirectedTo = @xhr.responseURL
|
5
|
-
else
|
6
|
-
redirectedTo = @xhr.getResponseHeader('X-XHR-Redirected-To')
|
7
|
-
|
8
|
-
@finalURL = redirectedTo || intendedURL
|
9
|
-
|
10
|
-
valid: -> @hasRenderableHttpStatus() && @hasValidContent()
|
11
|
-
|
12
|
-
document: ->
|
13
|
-
if @valid()
|
14
|
-
TurboGraft.Document.create(@xhr.responseText)
|
15
|
-
|
16
|
-
hasRenderableHttpStatus: ->
|
17
|
-
return true if @xhr.status == 422 # we want to render form validations
|
18
|
-
!(400 <= @xhr.status < 600)
|
19
|
-
|
20
|
-
hasValidContent: ->
|
21
|
-
if contentType = @xhr.getResponseHeader('Content-Type')
|
22
|
-
contentType.match(/^(?:text\/html|application\/xhtml\+xml|application\/xml)(?:;|$)/)
|
23
|
-
else
|
24
|
-
throw new Error("Error encountered for XHR Response: #{this}")
|
25
|
-
|
26
|
-
toString: () ->
|
27
|
-
"URL: #{@xhr.responseURL}, " +
|
28
|
-
"ReadyState: #{@xhr.readyState}, " +
|
29
|
-
"Headers: #{@xhr.getAllResponseHeaders()}"
|
30
|
-
|
31
|
-
TurboGraft.location = () -> location.href
|