turbograft 0.1.16 → 0.1.17

Sign up to get free protection for your applications and to get access to all the features.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA1:
3
- metadata.gz: 3a484dc5c71d248936bbac0a9dbf199f45677dd2
4
- data.tar.gz: 34a5ec53588bf5f1a22414d71f5c2a00d13bf27b
3
+ metadata.gz: f60fc04a714620e05aa698969d262fb5d73d14e0
4
+ data.tar.gz: f90a6eb06c5934f6df39f4effc4ec6cc7e630a00
5
5
  SHA512:
6
- metadata.gz: 2210ec33b3ee750852288282c80171af7ee1558551496c6b72695e6276ff23d7a5da64e78b19f97cb44cbdc49e9ea90eb23f22b2f156d6dee4454618097f8299
7
- data.tar.gz: 36db02f2045e1ae7d8f4fe24b97f244e822983c95f3bdf27ea3768a286de7338405846854763d5271cae610de7478f9529a5adb0a2dadffe46148695b1e8e028
6
+ metadata.gz: 3565f2df608377abec798bab1b4aeecbf554c93913c6554a150b659e0ff15a5059c5614a985b3a6f0b4b00bffe5f6bdf7deefac6b6c79901334375fc377b305a
7
+ data.tar.gz: 75fab37719b676e4b0b52c800ad472f097bb80d96c64a599e49057f9447ae1ef707b1c1ff3e97c2dc181d4be2b7c4fe32dd209bb45a937ff26ab26731e838370
data/README.md CHANGED
@@ -137,6 +137,20 @@ Examples of where this may be useful include:
137
137
 
138
138
  For the lazy developer in all of us, we can use the attribute `refresh-always` when we want to be sure we've absolutely replaced a certain element, if it exists. An example of such a node you may want to apply this might be an unread notification count -- always being sure to update it if it exists in the response.
139
139
 
140
+ ### tg-remote-noserialize
141
+
142
+ When serializing forms for tg-remote calls, turbograft will check to ensure inputs meet the following criteria:
143
+
144
+ - the input has a `name` attribute
145
+ - the input does not have the `disabled` attribute
146
+
147
+ and
148
+
149
+ - the input does not have the `tg-remote-noserialize` attribute
150
+ - no ancestor of the input has the `tg-remote-noserialize` attribute
151
+
152
+ The `tg-remote-noserialize` is useful in scenarios where a whole section of the page should be editable, i.e. not `disabled`, but should only conditionally be submitted to the server.
153
+
140
154
  ## Example App
141
155
 
142
156
  There is an example app that you can boot to play with TurboGraft. Open the console and network inspector and see it in action! This same app is also used in the TurboGraft browser testing suite.
@@ -17,11 +17,17 @@ Page.refresh = (options = {}, callback) ->
17
17
  location.href
18
18
 
19
19
  if options.response
20
- onlyKeys = options.onlyKeys || []
21
- exceptKeys = options.exceptKeys || []
22
- Turbolinks.loadPage null, options.response, true, callback, onlyKeys, exceptKeys
20
+ options.partialReplace = true
21
+ options.onLoadFunction = callback
22
+
23
+ xhr = options.response
24
+ delete options.response
25
+ Turbolinks.loadPage null, xhr, options
23
26
  else
24
- Turbolinks.visit newUrl, true, options.onlyKeys || [], -> callback?()
27
+ options.partialReplace = true
28
+ options.callback = callback if callback
29
+
30
+ Turbolinks.visit newUrl, options
25
31
 
26
32
  Page.open = ->
27
33
  window.open(arguments...)
@@ -90,7 +90,7 @@ class TurboGraft.Remote
90
90
  formData
91
91
 
92
92
  _iterateOverFormInputs: (form, callback) ->
93
- inputs = form.querySelectorAll("input:not([type='reset']):not([type='button']):not([type='submit']):not([type='image']), select, textarea")
93
+ inputs = @_enabledInputs(form)
94
94
  for input in inputs
95
95
  inputEnabled = !input.disabled
96
96
  radioOrCheck = (input.type == 'checkbox' || input.type == 'radio')
@@ -99,6 +99,22 @@ class TurboGraft.Remote
99
99
  if (radioOrCheck && input.checked) || !radioOrCheck
100
100
  callback(input)
101
101
 
102
+ _enabledInputs: (form) ->
103
+ selector = "input:not([type='reset']):not([type='button']):not([type='submit']):not([type='image']), select, textarea"
104
+ inputs = Array::slice.call(form.querySelectorAll(selector))
105
+ disabledNodes = Array::slice.call(form.querySelectorAll("[tg-remote-noserialize]"))
106
+
107
+ return inputs unless disabledNodes.length
108
+
109
+ disabledInputs = disabledNodes
110
+ for node in disabledNodes
111
+ disabledInputs = disabledInputs.concat(Array::slice.call(node.querySelectorAll(selector)))
112
+
113
+ enabledInputs = []
114
+ for input in inputs when disabledInputs.indexOf(input) < 0
115
+ enabledInputs.push(input)
116
+ enabledInputs
117
+
102
118
  onSuccess: (ev) ->
103
119
  @opts.success?()
104
120
 
@@ -66,16 +66,19 @@ class window.Turbolinks
66
66
  loadedAssets = null
67
67
  referer = null
68
68
 
69
- fetch = (url, partialReplace = false, replaceContents = [], callback) ->
69
+ fetch = (url, options = {}) ->
70
70
  return if pageChangePrevented(url)
71
71
  url = new ComponentUrl url
72
72
 
73
73
  rememberReferer()
74
74
 
75
- fetchReplacement url, partialReplace, ->
76
- resetScrollPosition() unless replaceContents.length
77
- callback?()
78
- , replaceContents
75
+ options.partialReplace ?= false
76
+ options.onlyKeys ?= []
77
+ options.onLoadFunction = ->
78
+ resetScrollPosition() unless options.onlyKeys.length
79
+ options.callback?()
80
+
81
+ fetchReplacement url, options
79
82
 
80
83
  @pushState: (state, title, url) ->
81
84
  window.history.pushState(state, title, url)
@@ -83,7 +86,7 @@ class window.Turbolinks
83
86
  @replaceState: (state, title, url) ->
84
87
  window.history.replaceState(state, title, url)
85
88
 
86
- fetchReplacement = (url, partialReplace, onLoadFunction, replaceContents) ->
89
+ fetchReplacement = (url, options) ->
87
90
  triggerEvent 'page:fetch', url: url.absolute
88
91
 
89
92
  xhr?.abort()
@@ -96,7 +99,7 @@ class window.Turbolinks
96
99
  if xhr.status >= 500
97
100
  document.location.href = url.absolute
98
101
  else
99
- Turbolinks.loadPage(url, xhr, partialReplace, onLoadFunction, replaceContents)
102
+ Turbolinks.loadPage(url, xhr, options)
100
103
 
101
104
  xhr.onloadend = -> xhr = null
102
105
  xhr.onerror = ->
@@ -106,33 +109,36 @@ class window.Turbolinks
106
109
 
107
110
  return
108
111
 
109
- @loadPage: (url, xhr, partialReplace = false, onLoadFunction = (->), replaceContents = [], replaceAllExcept = []) ->
112
+ @loadPage: (url, xhr, options = {}) ->
110
113
  triggerEvent 'page:receive'
114
+ options.updatePushState ?= true
111
115
 
112
- if doc = processResponse(xhr, partialReplace)
113
- reflectNewUrl url
114
- nodes = changePage(extractTitleAndBody(doc)..., partialReplace, replaceContents, replaceAllExcept)
115
- reflectRedirectedUrl(xhr)
116
+ if doc = processResponse(xhr, options.partialReplace)
117
+ reflectNewUrl url if options.updatePushState
118
+ nodes = changePage(extractTitleAndBody(doc)..., options)
119
+ reflectRedirectedUrl(xhr) if options.updatePushState
116
120
  triggerEvent 'page:load', nodes
117
- onLoadFunction?()
121
+ options.onLoadFunction?()
118
122
  else
119
123
  document.location.href = url.absolute
120
124
 
121
125
  return
122
126
 
123
- changePage = (title, body, csrfToken, runScripts, partialReplace, onlyKeys = [], exceptKeys = []) ->
127
+ changePage = (title, body, csrfToken, runScripts, options = {}) ->
124
128
  document.title = title if title
129
+ options.onlyKeys ?= []
130
+ options.exceptKeys ?= []
125
131
 
126
- if onlyKeys.length
127
- nodesToRefresh = [].concat(getNodesWithRefreshAlways(), getNodesMatchingRefreshKeys(onlyKeys))
132
+ if options.onlyKeys.length
133
+ nodesToRefresh = [].concat(getNodesWithRefreshAlways(), getNodesMatchingRefreshKeys(options.onlyKeys))
128
134
  nodes = refreshNodes(nodesToRefresh, body)
129
135
  setAutofocusElement() if anyAutofocusElement(nodes)
130
136
  return nodes
131
137
  else
132
138
  refreshNodes(getNodesWithRefreshAlways(), body)
133
139
  persistStaticElements(body)
134
- if exceptKeys.length
135
- refreshAllExceptWithKeys(exceptKeys, body)
140
+ if options.exceptKeys.length
141
+ refreshAllExceptWithKeys(options.exceptKeys, body)
136
142
  else
137
143
  deleteRefreshNeverNodes(body)
138
144
 
@@ -1,3 +1,3 @@
1
1
  module TurboGraft
2
- VERSION = '0.1.16'
2
+ VERSION = '0.1.17'
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.1.16
4
+ version: 0.1.17
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: 2015-03-12 00:00:00.000000000 Z
16
+ date: 2015-03-20 00:00:00.000000000 Z
17
17
  dependencies:
18
18
  - !ruby/object:Gem::Dependency
19
19
  name: coffee-rails
@@ -229,7 +229,6 @@ files:
229
229
  - lib/assets/javascripts/turbograft/page.coffee
230
230
  - lib/assets/javascripts/turbograft/remote.coffee
231
231
  - lib/assets/javascripts/turbograft/turbolinks.coffee
232
- - lib/turbograft.js
233
232
  - lib/turbograft.rb
234
233
  - lib/turbograft/cookies.rb
235
234
  - lib/turbograft/redirection.rb
data/lib/turbograft.js DELETED
@@ -1,978 +0,0 @@
1
- (function e(t,n,r){function s(o,u){if(!n[o]){if(!t[o]){var a=typeof require=="function"&&require;if(!u&&a)return a(o,!0);if(i)return i(o,!0);var f=new Error("Cannot find module '"+o+"'");throw f.code="MODULE_NOT_FOUND",f}var l=n[o]={exports:{}};t[o][0].call(l.exports,function(e){var n=t[o][1][e];return s(n?n:e)},l,l.exports,e,t,n,r)}return n[o].exports}var i=typeof require=="function"&&require;for(var o=0;o<r.length;o++)s(r[o]);return s})({1:[function(require,module,exports){
2
- window.Click = (function() {
3
- Click.installHandlerLast = function(event) {
4
- if (!event.defaultPrevented) {
5
- document.removeEventListener('click', Click.handle, false);
6
- return document.addEventListener('click', Click.handle, false);
7
- }
8
- };
9
-
10
- Click.handle = function(event) {
11
- return new Click(event);
12
- };
13
-
14
- function Click(event) {
15
- this.event = event;
16
- if (this.event.defaultPrevented) {
17
- return;
18
- }
19
- this._extractLink();
20
- if (this._validForTurbolinks()) {
21
- if (!this._pageChangePrevented()) {
22
- Turbolinks.visit(this.link.href);
23
- }
24
- this.event.preventDefault();
25
- }
26
- }
27
-
28
- Click.prototype._pageChangePrevented = function() {
29
- return !triggerEvent('page:before-change');
30
- };
31
-
32
- Click.prototype._extractLink = function() {
33
- var link;
34
- link = this.event.target;
35
- while (!(!link.parentNode || link.nodeName === 'A')) {
36
- link = link.parentNode;
37
- }
38
- if (link.nodeName === 'A' && link.href.length !== 0) {
39
- return this.link = new Link(link);
40
- }
41
- };
42
-
43
- Click.prototype._validForTurbolinks = function() {
44
- return (this.link != null) && !(this.link.shouldIgnore() || this._nonStandardClick());
45
- };
46
-
47
- Click.prototype._nonStandardClick = function() {
48
- return this.event.which > 1 || this.event.metaKey || this.event.ctrlKey || this.event.shiftKey || this.event.altKey;
49
- };
50
-
51
- return Click;
52
-
53
- })();
54
-
55
-
56
-
57
- },{}],2:[function(require,module,exports){
58
- window.ComponentUrl = (function() {
59
- function ComponentUrl(original) {
60
- this.original = original != null ? original : document.location.href;
61
- if (this.original.constructor === ComponentUrl) {
62
- return this.original;
63
- }
64
- this._parse();
65
- }
66
-
67
- ComponentUrl.prototype.withoutHash = function() {
68
- return this.href.replace(this.hash, '');
69
- };
70
-
71
- ComponentUrl.prototype.withoutHashForIE10compatibility = function() {
72
- return this.withoutHash();
73
- };
74
-
75
- ComponentUrl.prototype.hasNoHash = function() {
76
- return this.hash.length === 0;
77
- };
78
-
79
- ComponentUrl.prototype._parse = function() {
80
- var _ref;
81
- (this.link != null ? this.link : this.link = document.createElement('a')).href = this.original;
82
- _ref = this.link, this.href = _ref.href, this.protocol = _ref.protocol, this.host = _ref.host, this.hostname = _ref.hostname, this.port = _ref.port, this.pathname = _ref.pathname, this.search = _ref.search, this.hash = _ref.hash;
83
- this.origin = [this.protocol, '//', this.hostname].join('');
84
- if (this.port.length !== 0) {
85
- this.origin += ":" + this.port;
86
- }
87
- this.relative = [this.pathname, this.search, this.hash].join('');
88
- return this.absolute = this.href;
89
- };
90
-
91
- return ComponentUrl;
92
-
93
- })();
94
-
95
-
96
-
97
- },{}],3:[function(require,module,exports){
98
- window.CSRFToken = (function() {
99
- function CSRFToken() {}
100
-
101
- CSRFToken.get = function(doc) {
102
- var tag;
103
- if (doc == null) {
104
- doc = document;
105
- }
106
- return {
107
- node: tag = doc.querySelector('meta[name="csrf-token"]'),
108
- token: tag != null ? typeof tag.getAttribute === "function" ? tag.getAttribute('content') : void 0 : void 0
109
- };
110
- };
111
-
112
- CSRFToken.update = function(latest) {
113
- var current;
114
- current = this.get();
115
- if ((current.token != null) && (latest != null) && current.token !== latest) {
116
- return current.node.setAttribute('content', latest);
117
- }
118
- };
119
-
120
- return CSRFToken;
121
-
122
- })();
123
-
124
-
125
-
126
- },{}],4:[function(require,module,exports){
127
- var documentListenerForButtons, hasClass, nodeIsDisabled;
128
-
129
- window.TurboGraft = {
130
- handlers: {}
131
- };
132
-
133
- hasClass = function(node, search) {
134
- var className, _i, _len, _ref;
135
- _ref = node.classList;
136
- for (_i = 0, _len = _ref.length; _i < _len; _i++) {
137
- className = _ref[_i];
138
- if (className === search) {
139
- return true;
140
- }
141
- }
142
- return false;
143
- };
144
-
145
- nodeIsDisabled = function(node) {
146
- return node.getAttribute('disabled') || hasClass(node, 'disabled');
147
- };
148
-
149
- TurboGraft.handlers.partialGraftClickHandler = function(ev) {
150
- var href, keys, partialGraft, refresh, target;
151
- target = ev.target;
152
- partialGraft = target.getAttribute("partial-graft");
153
- if (partialGraft == null) {
154
- return;
155
- }
156
- ev.preventDefault();
157
- href = target.getAttribute("href");
158
- refresh = target.getAttribute("refresh");
159
- if (href == null) {
160
- throw "TurboGraft developer error: href is not defined on node " + target;
161
- }
162
- if (refresh == null) {
163
- throw "TurboGraft developer error: refresh is not defined on node " + target;
164
- }
165
- keys = refresh.trim().split(" ");
166
- return Page.refresh({
167
- url: href,
168
- onlyKeys: keys
169
- });
170
- };
171
-
172
- TurboGraft.handlers.remoteMethodHandler = function(ev) {
173
- var httpRequestType, httpUrl, onlyOnce, options, remote, target;
174
- target = ev.target;
175
- if (!target.getAttribute('remote-method')) {
176
- return;
177
- }
178
- ev.preventDefault();
179
- httpUrl = target.getAttribute('href');
180
- httpRequestType = target.getAttribute('remote-method');
181
- if (!httpRequestType) {
182
- throw "Turbograft developer error: You did not provide a request type for remote-method";
183
- }
184
- if (!httpUrl) {
185
- throw "Turbograft developer error: You did not provide a URL for remote-method";
186
- }
187
- if (onlyOnce = target.getAttribute("remote-once")) {
188
- target.removeAttribute("remote-once");
189
- target.removeAttribute("remote-method");
190
- }
191
- options = {
192
- httpRequestType: httpRequestType,
193
- httpUrl: httpUrl,
194
- fullRefresh: target.getAttribute('full-refresh') != null,
195
- refreshOnSuccess: target.getAttribute('refresh-on-success'),
196
- refreshOnError: target.getAttribute('refresh-on-error')
197
- };
198
- remote = new TurboGraft.Remote(options);
199
- };
200
-
201
- documentListenerForButtons = function(eventType, handler, useCapture) {
202
- if (useCapture == null) {
203
- useCapture = false;
204
- }
205
- return document.addEventListener(eventType, function(ev) {
206
- var target;
207
- target = ev.target;
208
- if (!(target.nodeName === "A" || target.nodeName === "BUTTON") || nodeIsDisabled(target)) {
209
- return;
210
- }
211
- return handler(ev);
212
- });
213
- };
214
-
215
- documentListenerForButtons('click', TurboGraft.handlers.partialGraftClickHandler, true);
216
-
217
- documentListenerForButtons('click', TurboGraft.handlers.remoteMethodHandler, true);
218
-
219
-
220
-
221
- },{}],5:[function(require,module,exports){
222
- var __hasProp = {}.hasOwnProperty,
223
- __extends = function(child, parent) { for (var key in parent) { if (__hasProp.call(parent, key)) child[key] = parent[key]; } function ctor() { this.constructor = child; } ctor.prototype = parent.prototype; child.prototype = new ctor(); child.__super__ = parent.prototype; return child; },
224
- __slice = [].slice;
225
-
226
- window.Link = (function(_super) {
227
- __extends(Link, _super);
228
-
229
- Link.HTML_EXTENSIONS = ['html'];
230
-
231
- Link.allowExtensions = function() {
232
- var extension, extensions, _i, _len;
233
- extensions = 1 <= arguments.length ? __slice.call(arguments, 0) : [];
234
- for (_i = 0, _len = extensions.length; _i < _len; _i++) {
235
- extension = extensions[_i];
236
- Link.HTML_EXTENSIONS.push(extension);
237
- }
238
- return Link.HTML_EXTENSIONS;
239
- };
240
-
241
- function Link(link) {
242
- this.link = link;
243
- if (this.link.constructor === Link) {
244
- return this.link;
245
- }
246
- this.original = this.link.href;
247
- Link.__super__.constructor.apply(this, arguments);
248
- }
249
-
250
- Link.prototype.shouldIgnore = function() {
251
- return this._crossOrigin() || this._anchored() || this._nonHtml() || this._optOut() || this._target();
252
- };
253
-
254
- Link.prototype._crossOrigin = function() {
255
- return this.origin !== (new ComponentUrl).origin;
256
- };
257
-
258
- Link.prototype._anchored = function() {
259
- var current;
260
- return ((this.hash && this.withoutHash()) === (current = new ComponentUrl).withoutHash()) || (this.href === current.href + '#');
261
- };
262
-
263
- Link.prototype._nonHtml = function() {
264
- return this.pathname.match(/\.[a-z]+$/g) && !this.pathname.match(new RegExp("\\.(?:" + (Link.HTML_EXTENSIONS.join('|')) + ")?$", 'g'));
265
- };
266
-
267
- Link.prototype._optOut = function() {
268
- var ignore, link;
269
- link = this.link;
270
- while (!(ignore || link === document || link === null)) {
271
- ignore = link.getAttribute('data-no-turbolink') != null;
272
- link = link.parentNode;
273
- }
274
- return ignore;
275
- };
276
-
277
- Link.prototype._target = function() {
278
- return this.link.target.length !== 0;
279
- };
280
-
281
- return Link;
282
-
283
- })(ComponentUrl);
284
-
285
-
286
-
287
- },{}],6:[function(require,module,exports){
288
- if (!window.Page) {
289
- window.Page = {};
290
- }
291
-
292
- Page.visit = function(url, opts) {
293
- if (opts == null) {
294
- opts = {};
295
- }
296
- if (opts.reload) {
297
- return window.location = url;
298
- } else {
299
- return Turbolinks.visit(url);
300
- }
301
- };
302
-
303
- Page.refresh = function(options, callback) {
304
- var newUrl, paramString;
305
- if (options == null) {
306
- options = {};
307
- }
308
- newUrl = options.url ? options.url : options.queryParams ? (paramString = $.param(options.queryParams), paramString ? paramString = "?" + paramString : void 0, location.pathname + paramString) : location.href;
309
- if (options.response) {
310
- return Turbolinks.loadPage(null, options.response, true, callback, options.onlyKeys || []);
311
- } else {
312
- return Turbolinks.visit(newUrl, true, options.onlyKeys || [], function() {
313
- return typeof callback === "function" ? callback() : void 0;
314
- });
315
- }
316
- };
317
-
318
- Page.open = function() {
319
- return window.open.apply(window, arguments);
320
- };
321
-
322
-
323
-
324
- },{}],7:[function(require,module,exports){
325
- window.PageCache = (function() {
326
- var simultaneousAdditionOffset, storage;
327
-
328
- storage = {};
329
-
330
- simultaneousAdditionOffset = 0;
331
-
332
- function PageCache(cacheSize) {
333
- this.cacheSize = cacheSize != null ? cacheSize : 10;
334
- storage = {};
335
- return this;
336
- }
337
-
338
- PageCache.prototype.get = function(key) {
339
- return storage[key];
340
- };
341
-
342
- PageCache.prototype.set = function(key, value) {
343
- if (typeof value !== "object") {
344
- throw "Developer error: You must store objects in this cache";
345
- }
346
- value['cachedAt'] = new Date().getTime() + (simultaneousAdditionOffset += 1);
347
- storage[key] = value;
348
- return this.constrain();
349
- };
350
-
351
- PageCache.prototype.clear = function() {
352
- return storage = {};
353
- };
354
-
355
- PageCache.prototype.setCacheSize = function(newSize) {
356
- if (/^[\d]+$/.test(newSize)) {
357
- this.cacheSize = parseInt(newSize, 10);
358
- return this.constrain();
359
- } else {
360
- throw "Developer error: Invalid parameter '" + newSize + "' for PageCache; must be integer";
361
- }
362
- };
363
-
364
- PageCache.prototype.constrain = function() {
365
- var cacheTimesRecentFirst, key, pageCacheKeys, _i, _len, _results;
366
- pageCacheKeys = Object.keys(storage);
367
- cacheTimesRecentFirst = pageCacheKeys.map((function(_this) {
368
- return function(url) {
369
- return storage[url].cachedAt;
370
- };
371
- })(this)).sort(function(a, b) {
372
- return b - a;
373
- });
374
- _results = [];
375
- for (_i = 0, _len = pageCacheKeys.length; _i < _len; _i++) {
376
- key = pageCacheKeys[_i];
377
- if (!(storage[key].cachedAt <= cacheTimesRecentFirst[this.cacheSize])) {
378
- continue;
379
- }
380
- triggerEvent('page:expire', storage[key]);
381
- _results.push(delete storage[key]);
382
- }
383
- return _results;
384
- };
385
-
386
- PageCache.prototype.length = function() {
387
- return Object.keys(storage).length;
388
- };
389
-
390
- return PageCache;
391
-
392
- })();
393
-
394
-
395
-
396
- },{}],8:[function(require,module,exports){
397
- TurboGraft.Remote = (function() {
398
- function Remote(opts, form) {
399
- var actualRequestType, formData, xhr;
400
- this.opts = opts;
401
- if (form) {
402
- formData = new FormData(form);
403
- } else {
404
- formData = new FormData();
405
- }
406
- actualRequestType = this.opts.httpRequestType.toLowerCase() === 'get' ? 'GET' : 'POST';
407
- formData.append("_method", this.opts.httpRequestType);
408
- if (this.opts.refreshOnSuccess) {
409
- this.refreshOnSuccess = this.opts.refreshOnSuccess.split(" ");
410
- }
411
- if (this.opts.refreshOnError) {
412
- this.refreshOnError = this.opts.refreshOnError.split(" ");
413
- }
414
- xhr = new XMLHttpRequest;
415
- xhr.open(actualRequestType, this.opts.httpUrl, true);
416
- xhr.setRequestHeader('Accept', 'text/html, application/xhtml+xml, application/xml');
417
- xhr.addEventListener('loadstart', function() {
418
- return triggerEvent('turbograft:remote:start', xhr);
419
- });
420
- xhr.addEventListener('error', this.onError);
421
- xhr.addEventListener('load', (function(_this) {
422
- return function(event) {
423
- if (xhr.status < 400) {
424
- return _this.onSuccess(event);
425
- } else {
426
- return _this.onError(event);
427
- }
428
- };
429
- })(this));
430
- xhr.addEventListener('loadend', function() {
431
- return triggerEvent('turbograft:remote:always', xhr);
432
- });
433
- xhr.send(formData);
434
- return xhr;
435
- }
436
-
437
- Remote.prototype.onSuccess = function(ev) {
438
- var redirect, xhr;
439
- xhr = ev.target;
440
- triggerEvent('turbograft:remote:success', xhr);
441
- if (redirect = xhr.getResponseHeader('X-Next-Redirect')) {
442
- Page.visit(redirect, {
443
- reload: true
444
- });
445
- return;
446
- }
447
- if (this.opts.fullRefresh) {
448
- return Page.refresh({
449
- onlyKeys: this.refreshOnSuccess
450
- });
451
- } else if (this.refreshOnSuccess) {
452
- return Page.refresh({
453
- response: xhr,
454
- onlyKeys: this.refreshOnSuccess
455
- });
456
- }
457
- };
458
-
459
- Remote.prototype.onError = function(ev) {
460
- var xhr;
461
- xhr = ev.target;
462
- triggerEvent('turbograft:remote:fail', xhr);
463
- if (this.refreshOnError) {
464
- return Page.refresh({
465
- response: xhr,
466
- onlyKeys: this.refreshOnError
467
- });
468
- } else {
469
- return triggerEvent('turbograft:remote:fail:unhandled', xhr);
470
- }
471
- };
472
-
473
- return Remote;
474
-
475
- })();
476
-
477
-
478
-
479
- },{}],9:[function(require,module,exports){
480
- var browserIsntBuggy, browserSupportsCustomEvents, browserSupportsPushState, browserSupportsTurbolinks, historyStateIsDefined, installDocumentReadyPageEventTriggers, installJqueryAjaxSuccessPageUpdateTrigger, popCookie, requestMethodIsSafe, xhr, _ref,
481
- __slice = [].slice,
482
- __indexOf = [].indexOf || function(item) { for (var i = 0, l = this.length; i < l; i++) { if (i in this && this[i] === item) return i; } return -1; };
483
-
484
- xhr = null;
485
-
486
- installDocumentReadyPageEventTriggers = function() {
487
- return document.addEventListener('DOMContentLoaded', (function() {
488
- triggerEvent('page:change');
489
- return triggerEvent('page:update');
490
- }), true);
491
- };
492
-
493
- installJqueryAjaxSuccessPageUpdateTrigger = function() {
494
- if (typeof jQuery !== 'undefined') {
495
- return jQuery(document).on('ajaxSuccess', function(event, xhr, settings) {
496
- if (!jQuery.trim(xhr.responseText)) {
497
- return;
498
- }
499
- return triggerEvent('page:update');
500
- });
501
- }
502
- };
503
-
504
- historyStateIsDefined = window.history.state !== void 0 || navigator.userAgent.match(/Firefox\/2[6|7]/);
505
-
506
- browserSupportsPushState = window.history && window.history.pushState && window.history.replaceState && historyStateIsDefined;
507
-
508
- browserIsntBuggy = !navigator.userAgent.match(/CriOS\//);
509
-
510
- window.triggerEvent = function(name, data) {
511
- var event;
512
- event = document.createEvent('Events');
513
- if (data) {
514
- event.data = data;
515
- }
516
- event.initEvent(name, true, true);
517
- return document.dispatchEvent(event);
518
- };
519
-
520
- popCookie = function(name) {
521
- var value, _ref;
522
- value = ((_ref = document.cookie.match(new RegExp(name + "=(\\w+)"))) != null ? _ref[1].toUpperCase() : void 0) || '';
523
- document.cookie = name + '=; expires=Thu, 01-Jan-70 00:00:01 GMT; path=/';
524
- return value;
525
- };
526
-
527
- requestMethodIsSafe = (_ref = popCookie('request_method')) === 'GET' || _ref === '';
528
-
529
- browserSupportsTurbolinks = browserSupportsPushState && browserIsntBuggy && requestMethodIsSafe;
530
-
531
- browserSupportsCustomEvents = document.addEventListener && document.createEvent;
532
-
533
- if (browserSupportsCustomEvents) {
534
- installDocumentReadyPageEventTriggers();
535
- installJqueryAjaxSuccessPageUpdateTrigger();
536
- }
537
-
538
- window.Turbolinks = (function() {
539
- var browserCompatibleDocumentParser, bypassOnLoadPopstate, changePage, createDocument, currentState, deleteRefreshNeverNodes, executeScriptTag, executeScriptTags, extractTitleAndBody, fetch, fetchHistory, fetchReplacement, installHistoryChangeHandler, loadedAssets, pageCache, pageChangePrevented, processResponse, recallScrollPosition, referer, reflectNewUrl, reflectRedirectedUrl, refreshNodesWithKeys, rememberReferer, removeNoscriptTags, resetScrollPosition, transitionCacheFor, usePageCache;
540
-
541
- function Turbolinks() {}
542
-
543
- createDocument = null;
544
-
545
- currentState = null;
546
-
547
- loadedAssets = null;
548
-
549
- referer = null;
550
-
551
- usePageCache = false;
552
-
553
- Turbolinks.pageCache = pageCache = new PageCache();
554
-
555
- fetch = function(url, partialReplace, replaceContents, callback) {
556
- var cachedPage;
557
- if (partialReplace == null) {
558
- partialReplace = false;
559
- }
560
- if (replaceContents == null) {
561
- replaceContents = [];
562
- }
563
- url = new ComponentUrl(url);
564
- rememberReferer();
565
- if (usePageCache) {
566
- Turbolinks.cacheCurrentPage();
567
- }
568
- if (usePageCache && (cachedPage = transitionCacheFor(url.absolute))) {
569
- fetchHistory(cachedPage);
570
- return fetchReplacement(url, partialReplace, null, replaceContents);
571
- } else {
572
- return fetchReplacement(url, partialReplace, function() {
573
- if (!replaceContents.length) {
574
- resetScrollPosition();
575
- }
576
- return typeof callback === "function" ? callback() : void 0;
577
- }, replaceContents);
578
- }
579
- };
580
-
581
- Turbolinks.pageCacheEnabled = function() {
582
- return usePageCache;
583
- };
584
-
585
- Turbolinks.usePageCache = function(status) {
586
- return usePageCache = status;
587
- };
588
-
589
- transitionCacheFor = function(url) {
590
- var cachedPage;
591
- cachedPage = pageCache.get(url);
592
- if (cachedPage && !cachedPage.transitionCacheDisabled) {
593
- return cachedPage;
594
- }
595
- };
596
-
597
- Turbolinks.pushState = function(state, title, url) {
598
- return window.history.pushState(state, title, url);
599
- };
600
-
601
- Turbolinks.replaceState = function(state, title, url) {
602
- return window.history.replaceState(state, title, url);
603
- };
604
-
605
- fetchReplacement = function(url, partialReplace, onLoadFunction, replaceContents) {
606
- triggerEvent('page:fetch', {
607
- url: url.absolute
608
- });
609
- if (xhr != null) {
610
- xhr.abort();
611
- }
612
- xhr = new XMLHttpRequest;
613
- xhr.open('GET', url.withoutHashForIE10compatibility(), true);
614
- xhr.setRequestHeader('Accept', 'text/html, application/xhtml+xml, application/xml');
615
- xhr.setRequestHeader('X-XHR-Referer', referer);
616
- xhr.onload = function() {
617
- if (xhr.status >= 500) {
618
- return document.location.href = url.absolute;
619
- } else {
620
- return Turbolinks.loadPage(url, xhr, partialReplace, onLoadFunction, replaceContents);
621
- }
622
- };
623
- xhr.onloadend = function() {
624
- return xhr = null;
625
- };
626
- xhr.onerror = function() {
627
- return document.location.href = url.absolute;
628
- };
629
- xhr.send();
630
- };
631
-
632
- Turbolinks.loadPage = function(url, xhr, partialReplace, onLoadFunction, replaceContents) {
633
- var doc, nodes;
634
- if (partialReplace == null) {
635
- partialReplace = false;
636
- }
637
- if (onLoadFunction == null) {
638
- onLoadFunction = (function() {});
639
- }
640
- if (replaceContents == null) {
641
- replaceContents = [];
642
- }
643
- triggerEvent('page:receive');
644
- if (doc = processResponse(xhr, partialReplace)) {
645
- reflectNewUrl(url);
646
- nodes = changePage.apply(null, __slice.call(extractTitleAndBody(doc)).concat([partialReplace], [replaceContents]));
647
- reflectRedirectedUrl(xhr);
648
- triggerEvent('page:load', nodes);
649
- if (typeof onLoadFunction === "function") {
650
- onLoadFunction();
651
- }
652
- } else {
653
- document.location.href = url.absolute;
654
- }
655
- };
656
-
657
- fetchHistory = function(cachedPage) {
658
- if (xhr != null) {
659
- xhr.abort();
660
- }
661
- changePage(cachedPage.title, cachedPage.body, false);
662
- recallScrollPosition(cachedPage);
663
- return triggerEvent('page:restore');
664
- };
665
-
666
- Turbolinks.cacheCurrentPage = function() {
667
- var currentStateUrl;
668
- currentStateUrl = new ComponentUrl(currentState.url);
669
- pageCache.set(currentStateUrl.absolute, {
670
- url: currentStateUrl.relative,
671
- body: document.body,
672
- title: document.title,
673
- positionY: window.pageYOffset,
674
- positionX: window.pageXOffset,
675
- transitionCacheDisabled: document.querySelector('[data-no-transition-cache]') != null
676
- });
677
- };
678
-
679
- changePage = function(title, body, csrfToken, runScripts, partialReplace, replaceContents) {
680
- if (replaceContents == null) {
681
- replaceContents = [];
682
- }
683
- if (title) {
684
- document.title = title;
685
- }
686
- if (replaceContents.length) {
687
- return refreshNodesWithKeys(replaceContents, body);
688
- } else {
689
- deleteRefreshNeverNodes(body);
690
- triggerEvent('page:before-replace');
691
- document.documentElement.replaceChild(body, document.body);
692
- if (csrfToken != null) {
693
- CSRFToken.update(csrfToken);
694
- }
695
- if (runScripts) {
696
- executeScriptTags();
697
- }
698
- currentState = window.history.state;
699
- triggerEvent('page:change');
700
- triggerEvent('page:update');
701
- }
702
- };
703
-
704
- deleteRefreshNeverNodes = function(body) {
705
- var node, _i, _len, _ref1;
706
- _ref1 = body.querySelectorAll('[refresh-never]');
707
- for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
708
- node = _ref1[_i];
709
- node.parentNode.removeChild(node);
710
- }
711
- };
712
-
713
- refreshNodesWithKeys = function(keys, body) {
714
- var allNodesToBeRefreshed, existingNode, key, newNode, node, nodeId, parentIsRefreshing, refreshedNodes, _i, _j, _k, _l, _len, _len1, _len2, _len3, _ref1, _ref2;
715
- allNodesToBeRefreshed = [];
716
- _ref1 = document.querySelectorAll("[refresh-always]");
717
- for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
718
- node = _ref1[_i];
719
- allNodesToBeRefreshed.push(node);
720
- }
721
- for (_j = 0, _len1 = keys.length; _j < _len1; _j++) {
722
- key = keys[_j];
723
- _ref2 = document.querySelectorAll("[refresh=" + key + "]");
724
- for (_k = 0, _len2 = _ref2.length; _k < _len2; _k++) {
725
- node = _ref2[_k];
726
- allNodesToBeRefreshed.push(node);
727
- }
728
- }
729
- triggerEvent('page:before-partial-replace', allNodesToBeRefreshed);
730
- parentIsRefreshing = function(node) {
731
- var potentialParent, _l, _len3;
732
- for (_l = 0, _len3 = allNodesToBeRefreshed.length; _l < _len3; _l++) {
733
- potentialParent = allNodesToBeRefreshed[_l];
734
- if (node !== potentialParent) {
735
- if (potentialParent.contains(node)) {
736
- return true;
737
- }
738
- }
739
- }
740
- return false;
741
- };
742
- refreshedNodes = [];
743
- for (_l = 0, _len3 = allNodesToBeRefreshed.length; _l < _len3; _l++) {
744
- existingNode = allNodesToBeRefreshed[_l];
745
- if (parentIsRefreshing(existingNode)) {
746
- continue;
747
- }
748
- if (!(nodeId = existingNode.getAttribute('id'))) {
749
- throw new Error("Turbolinks refresh: Refresh key elements must have an id.");
750
- }
751
- if (newNode = body.querySelector("#" + nodeId)) {
752
- existingNode.parentNode.replaceChild(newNode, existingNode);
753
- if (newNode.nodeName === 'SCRIPT' && newNode.getAttribute("data-turbolinks-eval") !== "false") {
754
- executeScriptTag(newNode);
755
- } else {
756
- refreshedNodes.push(newNode);
757
- }
758
- } else if (existingNode.getAttribute("refresh-always") === null) {
759
- existingNode.parentNode.removeChild(existingNode);
760
- }
761
- }
762
- return refreshedNodes;
763
- };
764
-
765
- executeScriptTags = function() {
766
- var script, scripts, _i, _len, _ref1;
767
- scripts = Array.prototype.slice.call(document.body.querySelectorAll('script:not([data-turbolinks-eval="false"])'));
768
- for (_i = 0, _len = scripts.length; _i < _len; _i++) {
769
- script = scripts[_i];
770
- if ((_ref1 = script.type) === '' || _ref1 === 'text/javascript') {
771
- executeScriptTag(script);
772
- }
773
- }
774
- };
775
-
776
- executeScriptTag = function(script) {
777
- var attr, copy, nextSibling, parentNode, _i, _len, _ref1;
778
- copy = document.createElement('script');
779
- _ref1 = script.attributes;
780
- for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
781
- attr = _ref1[_i];
782
- copy.setAttribute(attr.name, attr.value);
783
- }
784
- copy.appendChild(document.createTextNode(script.innerHTML));
785
- parentNode = script.parentNode, nextSibling = script.nextSibling;
786
- parentNode.removeChild(script);
787
- parentNode.insertBefore(copy, nextSibling);
788
- };
789
-
790
- removeNoscriptTags = function(node) {
791
- node.innerHTML = node.innerHTML.replace(/<noscript[\S\s]*?<\/noscript>/ig, '');
792
- return node;
793
- };
794
-
795
- reflectNewUrl = function(url) {
796
- if ((url = new ComponentUrl(url)).absolute !== referer) {
797
- Turbolinks.pushState({
798
- turbolinks: true,
799
- url: url.absolute
800
- }, '', url.absolute);
801
- }
802
- };
803
-
804
- reflectRedirectedUrl = function(xhr) {
805
- var location, preservedHash;
806
- if (location = xhr.getResponseHeader('X-XHR-Redirected-To')) {
807
- location = new ComponentUrl(location);
808
- preservedHash = location.hasNoHash() ? document.location.hash : '';
809
- Turbolinks.replaceState(currentState, '', location.href + preservedHash);
810
- }
811
- };
812
-
813
- rememberReferer = function() {
814
- return referer = document.location.href;
815
- };
816
-
817
- Turbolinks.rememberCurrentUrl = function() {
818
- return Turbolinks.replaceState({
819
- turbolinks: true,
820
- url: document.location.href
821
- }, '', document.location.href);
822
- };
823
-
824
- Turbolinks.rememberCurrentState = function() {
825
- return currentState = window.history.state;
826
- };
827
-
828
- recallScrollPosition = function(page) {
829
- return window.scrollTo(page.positionX, page.positionY);
830
- };
831
-
832
- resetScrollPosition = function() {
833
- if (document.location.hash) {
834
- return document.location.href = document.location.href;
835
- } else {
836
- return window.scrollTo(0, 0);
837
- }
838
- };
839
-
840
- pageChangePrevented = function() {
841
- return !triggerEvent('page:before-change');
842
- };
843
-
844
- processResponse = function(xhr, partial) {
845
- var assetsChanged, changed, clientOrServerError, doc, extractTrackAssets, intersection, validContent;
846
- if (partial == null) {
847
- partial = false;
848
- }
849
- clientOrServerError = function() {
850
- var _ref1;
851
- if (xhr.status === 422) {
852
- return false;
853
- }
854
- return (400 <= (_ref1 = xhr.status) && _ref1 < 600);
855
- };
856
- validContent = function() {
857
- return xhr.getResponseHeader('Content-Type').match(/^(?:text\/html|application\/xhtml\+xml|application\/xml)(?:;|$)/);
858
- };
859
- extractTrackAssets = function(doc) {
860
- var node, _i, _len, _ref1, _results;
861
- _ref1 = doc.head.childNodes;
862
- _results = [];
863
- for (_i = 0, _len = _ref1.length; _i < _len; _i++) {
864
- node = _ref1[_i];
865
- if ((typeof node.getAttribute === "function" ? node.getAttribute('data-turbolinks-track') : void 0) != null) {
866
- _results.push(node.getAttribute('src') || node.getAttribute('href'));
867
- }
868
- }
869
- return _results;
870
- };
871
- assetsChanged = function(doc) {
872
- var fetchedAssets;
873
- loadedAssets || (loadedAssets = extractTrackAssets(document));
874
- fetchedAssets = extractTrackAssets(doc);
875
- return fetchedAssets.length !== loadedAssets.length || intersection(fetchedAssets, loadedAssets).length !== loadedAssets.length;
876
- };
877
- intersection = function(a, b) {
878
- var value, _i, _len, _ref1, _results;
879
- if (a.length > b.length) {
880
- _ref1 = [b, a], a = _ref1[0], b = _ref1[1];
881
- }
882
- _results = [];
883
- for (_i = 0, _len = a.length; _i < _len; _i++) {
884
- value = a[_i];
885
- if (__indexOf.call(b, value) >= 0) {
886
- _results.push(value);
887
- }
888
- }
889
- return _results;
890
- };
891
- if (!clientOrServerError() && validContent()) {
892
- doc = createDocument(xhr.responseText);
893
- changed = assetsChanged(doc);
894
- if (doc && (!changed || partial)) {
895
- return doc;
896
- }
897
- }
898
- };
899
-
900
- extractTitleAndBody = function(doc) {
901
- var title;
902
- title = doc.querySelector('title');
903
- return [title != null ? title.textContent : void 0, removeNoscriptTags(doc.body), CSRFToken.get(doc).token, 'runScripts'];
904
- };
905
-
906
- installHistoryChangeHandler = function(event) {
907
- var cachedPage, _ref1;
908
- if ((_ref1 = event.state) != null ? _ref1.turbolinks : void 0) {
909
- if (cachedPage = pageCache.get((new ComponentUrl(event.state.url)).absolute)) {
910
- Turbolinks.cacheCurrentPage();
911
- return fetchHistory(cachedPage);
912
- } else {
913
- return Turbolinks.visit(event.target.location.href);
914
- }
915
- }
916
- };
917
-
918
- bypassOnLoadPopstate = function(fn) {
919
- return setTimeout(fn, 500);
920
- };
921
-
922
- browserCompatibleDocumentParser = function() {
923
- var createDocumentUsingDOM, createDocumentUsingParser, createDocumentUsingWrite, e, testDoc, _ref1;
924
- createDocumentUsingParser = function(html) {
925
- return (new DOMParser).parseFromString(html, 'text/html');
926
- };
927
- createDocumentUsingDOM = function(html) {
928
- var doc;
929
- doc = document.implementation.createHTMLDocument('');
930
- doc.documentElement.innerHTML = html;
931
- return doc;
932
- };
933
- createDocumentUsingWrite = function(html) {
934
- var doc;
935
- doc = document.implementation.createHTMLDocument('');
936
- doc.open('replace');
937
- doc.write(html);
938
- doc.close();
939
- return doc;
940
- };
941
- try {
942
- if (window.DOMParser) {
943
- testDoc = createDocumentUsingParser('<html><body><p>test');
944
- return createDocumentUsingParser;
945
- }
946
- } catch (_error) {
947
- e = _error;
948
- testDoc = createDocumentUsingDOM('<html><body><p>test');
949
- return createDocumentUsingDOM;
950
- } finally {
951
- if ((testDoc != null ? (_ref1 = testDoc.body) != null ? _ref1.childNodes.length : void 0 : void 0) !== 1) {
952
- return createDocumentUsingWrite;
953
- }
954
- }
955
- };
956
-
957
- if (browserSupportsTurbolinks) {
958
- Turbolinks.visit = fetch;
959
- Turbolinks.rememberCurrentUrl();
960
- Turbolinks.rememberCurrentState();
961
- createDocument = browserCompatibleDocumentParser();
962
- document.addEventListener('click', Click.installHandlerLast, true);
963
- bypassOnLoadPopstate(function() {
964
- return window.addEventListener('popstate', installHistoryChangeHandler, false);
965
- });
966
- } else {
967
- Turbolinks.visit = function(url) {
968
- return document.location.href = url;
969
- };
970
- }
971
-
972
- return Turbolinks;
973
-
974
- })();
975
-
976
-
977
-
978
- },{}]},{},[1,2,3,5,6,7,9,4,8]);