pjax_rails 0.4.0 → 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 +5 -5
- data/lib/pjax.rb +9 -4
- data/vendor/assets/javascripts/jquery.pjax.js +219 -154
- metadata +21 -27
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
|
-
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
2
|
+
SHA256:
|
3
|
+
metadata.gz: e64970b670dfdbc7ccfbdfeba5c68017592043da6a44dfca4bf802f38488d992
|
4
|
+
data.tar.gz: 3086bae93e9e83e8205d1f69890abe1e0ff75a99377601feb2661f83a2f275d7
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: cdb57cac74960ca7a13a480866417c960a96e462ea216e5821d0ac696bd5b539f99e30bf930b57c143af75bb176266d9292a0b684d31e7189e5cb8934d1d11b5
|
7
|
+
data.tar.gz: 6368084ddad6e1ea125b884aff74108f7ae4c418384a5d9137c5607175db33a826a3f199b1f812a65c7b79d469764cfd16e775d8cb666170b0a1868a017848fc
|
data/lib/pjax.rb
CHANGED
@@ -7,8 +7,13 @@ module Pjax
|
|
7
7
|
|
8
8
|
rescue_from Pjax::Unsupported, :with => :pjax_unsupported
|
9
9
|
|
10
|
-
|
11
|
-
|
10
|
+
if respond_to? :before_action
|
11
|
+
before_action :strip_pjax_param, :if => :pjax_request?
|
12
|
+
before_action :set_pjax_url, :if => :pjax_request?
|
13
|
+
else
|
14
|
+
before_filter :strip_pjax_param, :if => :pjax_request?
|
15
|
+
before_filter :set_pjax_url, :if => :pjax_request?
|
16
|
+
end
|
12
17
|
end
|
13
18
|
|
14
19
|
class Error < StandardError; end
|
@@ -32,11 +37,11 @@ module Pjax
|
|
32
37
|
head :not_acceptable
|
33
38
|
end
|
34
39
|
|
35
|
-
# Call in a
|
40
|
+
# Call in a before_action or in an action to disable pjax on an action.
|
36
41
|
#
|
37
42
|
# Examples
|
38
43
|
#
|
39
|
-
#
|
44
|
+
# before_action :prevent_pjax!
|
40
45
|
#
|
41
46
|
# def login
|
42
47
|
# prevent_pjax!
|
@@ -1,6 +1,8 @@
|
|
1
|
-
|
2
|
-
|
3
|
-
|
1
|
+
/*!
|
2
|
+
* Copyright 2012, Chris Wanstrath
|
3
|
+
* Released under the MIT License
|
4
|
+
* https://github.com/defunkt/jquery-pjax
|
5
|
+
*/
|
4
6
|
|
5
7
|
(function($){
|
6
8
|
|
@@ -17,9 +19,7 @@
|
|
17
19
|
// pjax specific options:
|
18
20
|
//
|
19
21
|
//
|
20
|
-
// container -
|
21
|
-
// $(container).html(xhr.responseBody)
|
22
|
-
// (default: current jquery context)
|
22
|
+
// container - String selector for the element where to place the response body.
|
23
23
|
// push - Whether to pushState the URL. Defaults to true (of course).
|
24
24
|
// replace - Want to use replaceState instead? That's cool.
|
25
25
|
//
|
@@ -28,11 +28,13 @@
|
|
28
28
|
//
|
29
29
|
// Returns the jQuery object
|
30
30
|
function fnPjax(selector, container, options) {
|
31
|
-
|
31
|
+
options = optionsFor(container, options)
|
32
32
|
return this.on('click.pjax', selector, function(event) {
|
33
|
-
var opts =
|
34
|
-
if (!opts.container)
|
35
|
-
opts
|
33
|
+
var opts = options
|
34
|
+
if (!opts.container) {
|
35
|
+
opts = $.extend({}, options)
|
36
|
+
opts.container = $(this).attr('data-pjax')
|
37
|
+
}
|
36
38
|
handleClick(event, opts)
|
37
39
|
})
|
38
40
|
}
|
@@ -50,16 +52,12 @@ function fnPjax(selector, container, options) {
|
|
50
52
|
// // is the same as
|
51
53
|
// $(document).pjax('a')
|
52
54
|
//
|
53
|
-
// $(document).on('click', 'a', function(event) {
|
54
|
-
// var container = $(this).closest('[data-pjax-container]')
|
55
|
-
// $.pjax.click(event, container)
|
56
|
-
// })
|
57
|
-
//
|
58
55
|
// Returns nothing.
|
59
56
|
function handleClick(event, container, options) {
|
60
57
|
options = optionsFor(container, options)
|
61
58
|
|
62
59
|
var link = event.currentTarget
|
60
|
+
var $link = $(link)
|
63
61
|
|
64
62
|
if (link.tagName.toUpperCase() !== 'A')
|
65
63
|
throw "$.fn.pjax or $.pjax.click requires an anchor element"
|
@@ -73,28 +71,28 @@ function handleClick(event, container, options) {
|
|
73
71
|
if ( location.protocol !== link.protocol || location.hostname !== link.hostname )
|
74
72
|
return
|
75
73
|
|
76
|
-
// Ignore
|
77
|
-
if (
|
78
|
-
location.href.replace(location.hash, ''))
|
74
|
+
// Ignore case when a hash is being tacked on the current URL
|
75
|
+
if ( link.href.indexOf('#') > -1 && stripHash(link) == stripHash(location) )
|
79
76
|
return
|
80
77
|
|
81
|
-
// Ignore
|
82
|
-
if (
|
78
|
+
// Ignore event with default prevented
|
79
|
+
if (event.isDefaultPrevented())
|
83
80
|
return
|
84
81
|
|
85
82
|
var defaults = {
|
86
83
|
url: link.href,
|
87
|
-
container: $
|
84
|
+
container: $link.attr('data-pjax'),
|
88
85
|
target: link
|
89
86
|
}
|
90
87
|
|
91
88
|
var opts = $.extend({}, defaults, options)
|
92
89
|
var clickEvent = $.Event('pjax:click')
|
93
|
-
$
|
90
|
+
$link.trigger(clickEvent, [opts])
|
94
91
|
|
95
92
|
if (!clickEvent.isDefaultPrevented()) {
|
96
93
|
pjax(opts)
|
97
94
|
event.preventDefault()
|
95
|
+
$link.trigger('pjax:clicked', [opts])
|
98
96
|
}
|
99
97
|
}
|
100
98
|
|
@@ -108,8 +106,7 @@ function handleClick(event, container, options) {
|
|
108
106
|
// Examples
|
109
107
|
//
|
110
108
|
// $(document).on('submit', 'form', function(event) {
|
111
|
-
//
|
112
|
-
// $.pjax.submit(event, container)
|
109
|
+
// $.pjax.submit(event, '[data-pjax-container]')
|
113
110
|
// })
|
114
111
|
//
|
115
112
|
// Returns nothing.
|
@@ -117,18 +114,32 @@ function handleSubmit(event, container, options) {
|
|
117
114
|
options = optionsFor(container, options)
|
118
115
|
|
119
116
|
var form = event.currentTarget
|
117
|
+
var $form = $(form)
|
120
118
|
|
121
119
|
if (form.tagName.toUpperCase() !== 'FORM')
|
122
120
|
throw "$.pjax.submit requires a form element"
|
123
121
|
|
124
122
|
var defaults = {
|
125
|
-
type: form.method.toUpperCase(),
|
126
|
-
url: form.action,
|
127
|
-
|
128
|
-
container: $(form).attr('data-pjax'),
|
123
|
+
type: ($form.attr('method') || 'GET').toUpperCase(),
|
124
|
+
url: $form.attr('action'),
|
125
|
+
container: $form.attr('data-pjax'),
|
129
126
|
target: form
|
130
127
|
}
|
131
128
|
|
129
|
+
if (defaults.type !== 'GET' && window.FormData !== undefined) {
|
130
|
+
defaults.data = new FormData(form)
|
131
|
+
defaults.processData = false
|
132
|
+
defaults.contentType = false
|
133
|
+
} else {
|
134
|
+
// Can't handle file uploads, exit
|
135
|
+
if ($form.find(':file').length) {
|
136
|
+
return
|
137
|
+
}
|
138
|
+
|
139
|
+
// Fallback to manually serializing the fields
|
140
|
+
defaults.data = $form.serializeArray()
|
141
|
+
}
|
142
|
+
|
132
143
|
pjax($.extend({}, defaults, options))
|
133
144
|
|
134
145
|
event.preventDefault()
|
@@ -142,8 +153,7 @@ function handleSubmit(event, container, options) {
|
|
142
153
|
//
|
143
154
|
// Accepts these extra keys:
|
144
155
|
//
|
145
|
-
// container -
|
146
|
-
// $(container).html(xhr.responseBody)
|
156
|
+
// container - String selector for where to stick the response body.
|
147
157
|
// push - Whether to pushState the URL. Defaults to true (of course).
|
148
158
|
// replace - Want to use replaceState instead? That's cool.
|
149
159
|
//
|
@@ -160,21 +170,32 @@ function pjax(options) {
|
|
160
170
|
options.url = options.url()
|
161
171
|
}
|
162
172
|
|
163
|
-
var target = options.target
|
164
|
-
|
165
173
|
var hash = parseURL(options.url).hash
|
166
174
|
|
167
|
-
var
|
175
|
+
var containerType = $.type(options.container)
|
176
|
+
if (containerType !== 'string') {
|
177
|
+
throw "expected string value for 'container' option; got " + containerType
|
178
|
+
}
|
179
|
+
var context = options.context = $(options.container)
|
180
|
+
if (!context.length) {
|
181
|
+
throw "the container selector '" + options.container + "' did not match anything"
|
182
|
+
}
|
168
183
|
|
169
184
|
// We want the browser to maintain two separate internal caches: one
|
170
185
|
// for pjax'd partial page loads and one for normal page loads.
|
171
186
|
// Without adding this secret parameter, some browsers will often
|
172
187
|
// confuse the two.
|
173
188
|
if (!options.data) options.data = {}
|
174
|
-
options.data
|
189
|
+
if ($.isArray(options.data)) {
|
190
|
+
options.data.push({name: '_pjax', value: options.container})
|
191
|
+
} else {
|
192
|
+
options.data._pjax = options.container
|
193
|
+
}
|
175
194
|
|
176
|
-
function fire(type, args) {
|
177
|
-
|
195
|
+
function fire(type, args, props) {
|
196
|
+
if (!props) props = {}
|
197
|
+
props.relatedTarget = options.target
|
198
|
+
var event = $.Event(type, props)
|
178
199
|
context.trigger(event, args)
|
179
200
|
return !event.isDefaultPrevented()
|
180
201
|
}
|
@@ -189,7 +210,7 @@ function pjax(options) {
|
|
189
210
|
}
|
190
211
|
|
191
212
|
xhr.setRequestHeader('X-PJAX', 'true')
|
192
|
-
xhr.setRequestHeader('X-PJAX-Container',
|
213
|
+
xhr.setRequestHeader('X-PJAX-Container', options.container)
|
193
214
|
|
194
215
|
if (!fire('pjax:beforeSend', [xhr, settings]))
|
195
216
|
return false
|
@@ -204,7 +225,9 @@ function pjax(options) {
|
|
204
225
|
settings.timeout = 0
|
205
226
|
}
|
206
227
|
|
207
|
-
|
228
|
+
var url = parseURL(settings.url)
|
229
|
+
if (hash) url.hash = hash
|
230
|
+
options.requestUrl = stripInternalParams(url)
|
208
231
|
}
|
209
232
|
|
210
233
|
options.complete = function(xhr, textStatus) {
|
@@ -226,9 +249,11 @@ function pjax(options) {
|
|
226
249
|
}
|
227
250
|
|
228
251
|
options.success = function(data, status, xhr) {
|
252
|
+
var previousState = pjax.state
|
253
|
+
|
229
254
|
// If $.pjax.defaults.version is a function, invoke it first.
|
230
255
|
// Otherwise it can be a static string.
|
231
|
-
var currentVersion =
|
256
|
+
var currentVersion = typeof $.pjax.defaults.version === 'function' ?
|
232
257
|
$.pjax.defaults.version() :
|
233
258
|
$.pjax.defaults.version
|
234
259
|
|
@@ -236,6 +261,12 @@ function pjax(options) {
|
|
236
261
|
|
237
262
|
var container = extractContainer(data, xhr, options)
|
238
263
|
|
264
|
+
var url = parseURL(container.url)
|
265
|
+
if (hash) {
|
266
|
+
url.hash = hash
|
267
|
+
container.url = url.href
|
268
|
+
}
|
269
|
+
|
239
270
|
// If there is a layout version mismatch, hard load the new url
|
240
271
|
if (currentVersion && latestVersion && currentVersion !== latestVersion) {
|
241
272
|
locationReplace(container.url)
|
@@ -252,7 +283,7 @@ function pjax(options) {
|
|
252
283
|
id: options.id || uniqueId(),
|
253
284
|
url: container.url,
|
254
285
|
title: container.title,
|
255
|
-
container:
|
286
|
+
container: options.container,
|
256
287
|
fragment: options.fragment,
|
257
288
|
timeout: options.timeout
|
258
289
|
}
|
@@ -261,10 +292,22 @@ function pjax(options) {
|
|
261
292
|
window.history.replaceState(pjax.state, container.title, container.url)
|
262
293
|
}
|
263
294
|
|
295
|
+
// Only blur the focus if the focused element is within the container.
|
296
|
+
var blurFocus = $.contains(context, document.activeElement)
|
297
|
+
|
264
298
|
// Clear out any focused controls before inserting new page contents.
|
265
|
-
|
299
|
+
if (blurFocus) {
|
300
|
+
try {
|
301
|
+
document.activeElement.blur()
|
302
|
+
} catch (e) { /* ignore */ }
|
303
|
+
}
|
266
304
|
|
267
305
|
if (container.title) document.title = container.title
|
306
|
+
|
307
|
+
fire('pjax:beforeReplace', [container.contents, options], {
|
308
|
+
state: pjax.state,
|
309
|
+
previousState: previousState
|
310
|
+
})
|
268
311
|
context.html(container.contents)
|
269
312
|
|
270
313
|
// FF bug: Won't autofocus fields that are inserted via JS.
|
@@ -274,33 +317,22 @@ function pjax(options) {
|
|
274
317
|
// http://www.w3.org/html/wg/drafts/html/master/forms.html
|
275
318
|
var autofocusEl = context.find('input[autofocus], textarea[autofocus]').last()[0]
|
276
319
|
if (autofocusEl && document.activeElement !== autofocusEl) {
|
277
|
-
autofocusEl.focus()
|
320
|
+
autofocusEl.focus()
|
278
321
|
}
|
279
322
|
|
280
323
|
executeScriptTags(container.scripts)
|
281
324
|
|
282
|
-
|
283
|
-
if (typeof options.scrollTo === 'number')
|
284
|
-
$(window).scrollTop(options.scrollTo)
|
285
|
-
|
286
|
-
// If the URL has a hash in it, make sure the browser
|
287
|
-
// knows to navigate to the hash.
|
288
|
-
if ( hash !== '' ) {
|
289
|
-
// Avoid using simple hash set here. Will add another history
|
290
|
-
// entry. Replace the url with replaceState and scroll to target
|
291
|
-
// by hand.
|
292
|
-
//
|
293
|
-
// window.location.hash = hash
|
294
|
-
var url = parseURL(container.url)
|
295
|
-
url.hash = hash
|
296
|
-
|
297
|
-
pjax.state.url = url.href
|
298
|
-
window.history.replaceState(pjax.state, container.title, url.href)
|
325
|
+
var scrollTo = options.scrollTo
|
299
326
|
|
300
|
-
|
301
|
-
|
327
|
+
// Ensure browser scrolls to the element referenced by the URL anchor
|
328
|
+
if (hash) {
|
329
|
+
var name = decodeURIComponent(hash.slice(1))
|
330
|
+
var target = document.getElementById(name) || document.getElementsByName(name)[0]
|
331
|
+
if (target) scrollTo = $(target).offset().top
|
302
332
|
}
|
303
333
|
|
334
|
+
if (typeof scrollTo == 'number') $(window).scrollTop(scrollTo)
|
335
|
+
|
304
336
|
fire('pjax:success', [data, status, xhr, options])
|
305
337
|
}
|
306
338
|
|
@@ -314,7 +346,7 @@ function pjax(options) {
|
|
314
346
|
id: uniqueId(),
|
315
347
|
url: window.location.href,
|
316
348
|
title: document.title,
|
317
|
-
container:
|
349
|
+
container: options.container,
|
318
350
|
fragment: options.fragment,
|
319
351
|
timeout: options.timeout
|
320
352
|
}
|
@@ -322,11 +354,7 @@ function pjax(options) {
|
|
322
354
|
}
|
323
355
|
|
324
356
|
// Cancel the current request if we're already pjaxing
|
325
|
-
|
326
|
-
if ( xhr && xhr.readyState < 4) {
|
327
|
-
xhr.onreadystatechange = $.noop
|
328
|
-
xhr.abort()
|
329
|
-
}
|
357
|
+
abortXHR(pjax.xhr)
|
330
358
|
|
331
359
|
pjax.options = options
|
332
360
|
var xhr = pjax.xhr = $.ajax(options)
|
@@ -334,9 +362,9 @@ function pjax(options) {
|
|
334
362
|
if (xhr.readyState > 0) {
|
335
363
|
if (options.push && !options.replace) {
|
336
364
|
// Cache current container element before replacing it
|
337
|
-
cachePush(pjax.state.id,
|
365
|
+
cachePush(pjax.state.id, [options.container, cloneContents(context)])
|
338
366
|
|
339
|
-
window.history.pushState(null, "",
|
367
|
+
window.history.pushState(null, "", options.requestUrl)
|
340
368
|
}
|
341
369
|
|
342
370
|
fire('pjax:start', [xhr, options])
|
@@ -367,7 +395,7 @@ function pjaxReload(container, options) {
|
|
367
395
|
//
|
368
396
|
// Returns nothing.
|
369
397
|
function locationReplace(url) {
|
370
|
-
window.history.replaceState(null, "",
|
398
|
+
window.history.replaceState(null, "", pjax.state.url)
|
371
399
|
window.location.replace(url)
|
372
400
|
}
|
373
401
|
|
@@ -393,7 +421,15 @@ if ('state' in window.history) {
|
|
393
421
|
// You probably shouldn't use pjax on pages with other pushState
|
394
422
|
// stuff yet.
|
395
423
|
function onPjaxPopstate(event) {
|
424
|
+
|
425
|
+
// Hitting back or forward should override any pending PJAX request.
|
426
|
+
if (!initialPop) {
|
427
|
+
abortXHR(pjax.xhr)
|
428
|
+
}
|
429
|
+
|
430
|
+
var previousState = pjax.state
|
396
431
|
var state = event.state
|
432
|
+
var direction
|
397
433
|
|
398
434
|
if (state && state.container) {
|
399
435
|
// When coming forward from a separate history session, will get an
|
@@ -401,22 +437,24 @@ function onPjaxPopstate(event) {
|
|
401
437
|
// page.
|
402
438
|
if (initialPop && initialURL == state.url) return
|
403
439
|
|
404
|
-
|
405
|
-
|
406
|
-
|
440
|
+
if (previousState) {
|
441
|
+
// If popping back to the same state, just skip.
|
442
|
+
// Could be clicking back from hashchange rather than a pushState.
|
443
|
+
if (previousState.id === state.id) return
|
407
444
|
|
408
|
-
|
409
|
-
|
410
|
-
|
445
|
+
// Since state IDs always increase, we can deduce the navigation direction
|
446
|
+
direction = previousState.id < state.id ? 'forward' : 'back'
|
447
|
+
}
|
411
448
|
|
412
|
-
|
413
|
-
|
414
|
-
|
415
|
-
direction = pjax.state.id < state.id ? 'forward' : 'back'
|
449
|
+
var cache = cacheMapping[state.id] || []
|
450
|
+
var containerSelector = cache[0] || state.container
|
451
|
+
var container = $(containerSelector), contents = cache[1]
|
416
452
|
|
453
|
+
if (container.length) {
|
454
|
+
if (previousState) {
|
417
455
|
// Cache current container before replacement and inform the
|
418
456
|
// cache which direction the history shifted.
|
419
|
-
cachePop(direction,
|
457
|
+
cachePop(direction, previousState.id, [containerSelector, cloneContents(container)])
|
420
458
|
}
|
421
459
|
|
422
460
|
var popstateEvent = $.Event('pjax:popstate', {
|
@@ -428,7 +466,7 @@ function onPjaxPopstate(event) {
|
|
428
466
|
var options = {
|
429
467
|
id: state.id,
|
430
468
|
url: state.url,
|
431
|
-
container:
|
469
|
+
container: containerSelector,
|
432
470
|
push: false,
|
433
471
|
fragment: state.fragment,
|
434
472
|
timeout: state.timeout,
|
@@ -438,9 +476,14 @@ function onPjaxPopstate(event) {
|
|
438
476
|
if (contents) {
|
439
477
|
container.trigger('pjax:start', [null, options])
|
440
478
|
|
479
|
+
pjax.state = state
|
441
480
|
if (state.title) document.title = state.title
|
481
|
+
var beforeReplaceEvent = $.Event('pjax:beforeReplace', {
|
482
|
+
state: state,
|
483
|
+
previousState: previousState
|
484
|
+
})
|
485
|
+
container.trigger(beforeReplaceEvent, [contents, options])
|
442
486
|
container.html(contents)
|
443
|
-
pjax.state = state
|
444
487
|
|
445
488
|
container.trigger('pjax:end', [null, options])
|
446
489
|
} else {
|
@@ -449,7 +492,7 @@ function onPjaxPopstate(event) {
|
|
449
492
|
|
450
493
|
// Force reflow/relayout before the browser tries to restore the
|
451
494
|
// scroll position.
|
452
|
-
container[0].offsetHeight
|
495
|
+
container[0].offsetHeight // eslint-disable-line no-unused-expressions
|
453
496
|
} else {
|
454
497
|
locationReplace(location.href)
|
455
498
|
}
|
@@ -485,7 +528,12 @@ function fallbackPjax(options) {
|
|
485
528
|
var pair = value.split('=')
|
486
529
|
form.append($('<input>', {type: 'hidden', name: pair[0], value: pair[1]}))
|
487
530
|
})
|
531
|
+
} else if ($.isArray(data)) {
|
532
|
+
$.each(data, function(index, value) {
|
533
|
+
form.append($('<input>', {type: 'hidden', name: value.name, value: value.value}))
|
534
|
+
})
|
488
535
|
} else if (typeof data === 'object') {
|
536
|
+
var key
|
489
537
|
for (key in data)
|
490
538
|
form.append($('<input>', {type: 'hidden', name: key, value: data[key]}))
|
491
539
|
}
|
@@ -494,6 +542,15 @@ function fallbackPjax(options) {
|
|
494
542
|
form.submit()
|
495
543
|
}
|
496
544
|
|
545
|
+
// Internal: Abort an XmlHttpRequest if it hasn't been completed,
|
546
|
+
// also removing its event handlers.
|
547
|
+
function abortXHR(xhr) {
|
548
|
+
if ( xhr && xhr.readyState < 4) {
|
549
|
+
xhr.onreadystatechange = $.noop
|
550
|
+
xhr.abort()
|
551
|
+
}
|
552
|
+
}
|
553
|
+
|
497
554
|
// Internal: Generate unique id for state object.
|
498
555
|
//
|
499
556
|
// Use a timestamp instead of a counter since ids should still be
|
@@ -504,16 +561,22 @@ function uniqueId() {
|
|
504
561
|
return (new Date).getTime()
|
505
562
|
}
|
506
563
|
|
507
|
-
|
508
|
-
|
509
|
-
//
|
564
|
+
function cloneContents(container) {
|
565
|
+
var cloned = container.clone()
|
566
|
+
// Unmark script tags as already being eval'd so they can get executed again
|
567
|
+
// when restored from cache. HAXX: Uses jQuery internal method.
|
568
|
+
cloned.find('script').each(function(){
|
569
|
+
if (!this.src) $._data(this, 'globalEval', false)
|
570
|
+
})
|
571
|
+
return cloned.contents()
|
572
|
+
}
|
573
|
+
|
574
|
+
// Internal: Strip internal query params from parsed URL.
|
510
575
|
//
|
511
|
-
// Returns String.
|
512
|
-
function
|
513
|
-
|
514
|
-
|
515
|
-
.replace(/_pjax=[^&]+&?/, '')
|
516
|
-
.replace(/[\?&]$/, '')
|
576
|
+
// Returns sanitized url.href String.
|
577
|
+
function stripInternalParams(url) {
|
578
|
+
url.search = url.search.replace(/([?&])(_pjax|_)=[^&]*/g, '').replace(/^&/, '')
|
579
|
+
return url.href.replace(/\?($|#)/, '$1')
|
517
580
|
}
|
518
581
|
|
519
582
|
// Internal: Parse URL components and returns a Locationish object.
|
@@ -527,6 +590,16 @@ function parseURL(url) {
|
|
527
590
|
return a
|
528
591
|
}
|
529
592
|
|
593
|
+
// Internal: Return the `href` component of given URL object with the hash
|
594
|
+
// portion removed.
|
595
|
+
//
|
596
|
+
// location - Location or HTMLAnchorElement
|
597
|
+
//
|
598
|
+
// Returns String
|
599
|
+
function stripHash(location) {
|
600
|
+
return location.href.replace(/#.*/, '')
|
601
|
+
}
|
602
|
+
|
530
603
|
// Internal: Build options Object for arguments.
|
531
604
|
//
|
532
605
|
// For convenience the first parameter can be either the container or
|
@@ -545,44 +618,14 @@ function parseURL(url) {
|
|
545
618
|
//
|
546
619
|
// Returns options Object.
|
547
620
|
function optionsFor(container, options) {
|
548
|
-
|
549
|
-
|
621
|
+
if (container && options) {
|
622
|
+
options = $.extend({}, options)
|
550
623
|
options.container = container
|
551
|
-
|
552
|
-
|
553
|
-
else if ( $.isPlainObject(container) )
|
554
|
-
options = container
|
555
|
-
|
556
|
-
// Only container
|
557
|
-
else
|
558
|
-
options = {container: container}
|
559
|
-
|
560
|
-
// Find and validate container
|
561
|
-
if (options.container)
|
562
|
-
options.container = findContainerFor(options.container)
|
563
|
-
|
564
|
-
return options
|
565
|
-
}
|
566
|
-
|
567
|
-
// Internal: Find container element for a variety of inputs.
|
568
|
-
//
|
569
|
-
// Because we can't persist elements using the history API, we must be
|
570
|
-
// able to find a String selector that will consistently find the Element.
|
571
|
-
//
|
572
|
-
// container - A selector String, jQuery object, or DOM Element.
|
573
|
-
//
|
574
|
-
// Returns a jQuery object whose context is `document` and has a selector.
|
575
|
-
function findContainerFor(container) {
|
576
|
-
container = $(container)
|
577
|
-
|
578
|
-
if ( !container.length ) {
|
579
|
-
throw "no pjax container for " + container.selector
|
580
|
-
} else if ( container.selector !== '' && container.context === document ) {
|
624
|
+
return options
|
625
|
+
} else if ($.isPlainObject(container)) {
|
581
626
|
return container
|
582
|
-
} else if ( container.attr('id') ) {
|
583
|
-
return $('#' + container.attr('id'))
|
584
627
|
} else {
|
585
|
-
|
628
|
+
return {container: container}
|
586
629
|
}
|
587
630
|
}
|
588
631
|
|
@@ -596,7 +639,7 @@ function findContainerFor(container) {
|
|
596
639
|
//
|
597
640
|
// Returns a jQuery object.
|
598
641
|
function findAll(elems, selector) {
|
599
|
-
return elems.filter(selector).add(elems.find(selector))
|
642
|
+
return elems.filter(selector).add(elems.find(selector))
|
600
643
|
}
|
601
644
|
|
602
645
|
function parseHTML(html) {
|
@@ -615,18 +658,21 @@ function parseHTML(html) {
|
|
615
658
|
//
|
616
659
|
// Returns an Object with url, title, and contents keys.
|
617
660
|
function extractContainer(data, xhr, options) {
|
618
|
-
var obj = {}
|
661
|
+
var obj = {}, fullDocument = /<html/i.test(data)
|
619
662
|
|
620
663
|
// Prefer X-PJAX-URL header if it was set, otherwise fallback to
|
621
664
|
// using the original requested url.
|
622
|
-
|
665
|
+
var serverUrl = xhr.getResponseHeader('X-PJAX-URL')
|
666
|
+
obj.url = serverUrl ? stripInternalParams(parseURL(serverUrl)) : options.requestUrl
|
623
667
|
|
668
|
+
var $head, $body
|
624
669
|
// Attempt to parse response html into elements
|
625
|
-
if (
|
626
|
-
|
627
|
-
var
|
670
|
+
if (fullDocument) {
|
671
|
+
$body = $(parseHTML(data.match(/<body[^>]*>([\s\S.]*)<\/body>/i)[0]))
|
672
|
+
var head = data.match(/<head[^>]*>([\s\S.]*)<\/head>/i)
|
673
|
+
$head = head != null ? $(parseHTML(head[0])) : $body
|
628
674
|
} else {
|
629
|
-
|
675
|
+
$head = $body = $(parseHTML(data))
|
630
676
|
}
|
631
677
|
|
632
678
|
// If response data is empty, return fast
|
@@ -638,16 +684,15 @@ function extractContainer(data, xhr, options) {
|
|
638
684
|
obj.title = findAll($head, 'title').last().text()
|
639
685
|
|
640
686
|
if (options.fragment) {
|
687
|
+
var $fragment = $body
|
641
688
|
// If they specified a fragment, look for it in the response
|
642
689
|
// and pull it out.
|
643
|
-
if (options.fragment
|
644
|
-
|
645
|
-
} else {
|
646
|
-
var $fragment = findAll($body, options.fragment).first()
|
690
|
+
if (options.fragment !== 'body') {
|
691
|
+
$fragment = findAll($fragment, options.fragment).first()
|
647
692
|
}
|
648
693
|
|
649
694
|
if ($fragment.length) {
|
650
|
-
obj.contents = $fragment.contents()
|
695
|
+
obj.contents = options.fragment === 'body' ? $fragment : $fragment.contents()
|
651
696
|
|
652
697
|
// If there's no title, look for data-title and title attributes
|
653
698
|
// on the fragment
|
@@ -655,7 +700,7 @@ function extractContainer(data, xhr, options) {
|
|
655
700
|
obj.title = $fragment.attr('title') || $fragment.data('title')
|
656
701
|
}
|
657
702
|
|
658
|
-
} else if (
|
703
|
+
} else if (!fullDocument) {
|
659
704
|
obj.contents = $body
|
660
705
|
}
|
661
706
|
|
@@ -699,7 +744,8 @@ function executeScriptTags(scripts) {
|
|
699
744
|
if (matchedScripts.length) return
|
700
745
|
|
701
746
|
var script = document.createElement('script')
|
702
|
-
|
747
|
+
var type = $(this).attr('type')
|
748
|
+
if (type) script.type = type
|
703
749
|
script.src = $(this).attr('src')
|
704
750
|
document.head.appendChild(script)
|
705
751
|
})
|
@@ -722,14 +768,11 @@ function cachePush(id, value) {
|
|
722
768
|
cacheMapping[id] = value
|
723
769
|
cacheBackStack.push(id)
|
724
770
|
|
725
|
-
// Remove all
|
726
|
-
|
727
|
-
while (cacheForwardStack.length)
|
728
|
-
delete cacheMapping[cacheForwardStack.shift()]
|
771
|
+
// Remove all entries in forward history stack after pushing a new page.
|
772
|
+
trimCacheStack(cacheForwardStack, 0)
|
729
773
|
|
730
774
|
// Trim back history stack to max cache length.
|
731
|
-
|
732
|
-
delete cacheMapping[cacheBackStack.shift()]
|
775
|
+
trimCacheStack(cacheBackStack, pjax.defaults.maxCacheLength)
|
733
776
|
}
|
734
777
|
|
735
778
|
// Shifts cache from directional history cache. Should be
|
@@ -754,8 +797,23 @@ function cachePop(direction, id, value) {
|
|
754
797
|
}
|
755
798
|
|
756
799
|
pushStack.push(id)
|
757
|
-
|
758
|
-
|
800
|
+
id = popStack.pop()
|
801
|
+
if (id) delete cacheMapping[id]
|
802
|
+
|
803
|
+
// Trim whichever stack we just pushed to to max cache length.
|
804
|
+
trimCacheStack(pushStack, pjax.defaults.maxCacheLength)
|
805
|
+
}
|
806
|
+
|
807
|
+
// Trim a cache stack (either cacheBackStack or cacheForwardStack) to be no
|
808
|
+
// longer than the specified length, deleting cached DOM elements as necessary.
|
809
|
+
//
|
810
|
+
// stack - Array of state IDs
|
811
|
+
// length - Maximum length to trim to
|
812
|
+
//
|
813
|
+
// Returns nothing.
|
814
|
+
function trimCacheStack(stack, length) {
|
815
|
+
while (stack.length > length)
|
816
|
+
delete cacheMapping[stack.shift()]
|
759
817
|
}
|
760
818
|
|
761
819
|
// Public: Find version identifier for the initial page load.
|
@@ -824,15 +882,22 @@ function disable() {
|
|
824
882
|
|
825
883
|
// Add the state property to jQuery's event object so we can use it in
|
826
884
|
// $(window).bind('popstate')
|
827
|
-
if ( $.inArray('state', $.event.props) < 0
|
885
|
+
if ($.event.props && $.inArray('state', $.event.props) < 0) {
|
828
886
|
$.event.props.push('state')
|
887
|
+
} else if (!('state' in $.Event.prototype)) {
|
888
|
+
$.event.addProp('state')
|
889
|
+
}
|
829
890
|
|
830
891
|
// Is pjax supported by this browser?
|
831
892
|
$.support.pjax =
|
832
893
|
window.history && window.history.pushState && window.history.replaceState &&
|
833
894
|
// pushState isn't reliable on iOS until 5.
|
834
|
-
!navigator.userAgent.match(/((iPod|iPhone|iPad).+\bOS\s+[1-4]|WebApps\/.+CFNetwork)/)
|
895
|
+
!navigator.userAgent.match(/((iPod|iPhone|iPad).+\bOS\s+[1-4]\D|WebApps\/.+CFNetwork)/)
|
835
896
|
|
836
|
-
$.support.pjax
|
897
|
+
if ($.support.pjax) {
|
898
|
+
enable()
|
899
|
+
} else {
|
900
|
+
disable()
|
901
|
+
}
|
837
902
|
|
838
|
-
})(jQuery)
|
903
|
+
})(jQuery)
|
metadata
CHANGED
@@ -1,103 +1,97 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pjax_rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.5.0
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- David Heinemeier Hansson (PJAX by Chris Wanstrath)
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2018-11-27 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: railties
|
15
15
|
requirement: !ruby/object:Gem::Requirement
|
16
16
|
requirements:
|
17
|
-
- -
|
17
|
+
- - ">="
|
18
18
|
- !ruby/object:Gem::Version
|
19
19
|
version: '3.2'
|
20
|
-
- - <
|
21
|
-
- !ruby/object:Gem::Version
|
22
|
-
version: '5.0'
|
23
20
|
type: :runtime
|
24
21
|
prerelease: false
|
25
22
|
version_requirements: !ruby/object:Gem::Requirement
|
26
23
|
requirements:
|
27
|
-
- -
|
24
|
+
- - ">="
|
28
25
|
- !ruby/object:Gem::Version
|
29
26
|
version: '3.2'
|
30
|
-
- - <
|
31
|
-
- !ruby/object:Gem::Version
|
32
|
-
version: '5.0'
|
33
27
|
- !ruby/object:Gem::Dependency
|
34
28
|
name: jquery-rails
|
35
29
|
requirement: !ruby/object:Gem::Requirement
|
36
30
|
requirements:
|
37
|
-
- -
|
31
|
+
- - ">="
|
38
32
|
- !ruby/object:Gem::Version
|
39
33
|
version: '0'
|
40
34
|
type: :runtime
|
41
35
|
prerelease: false
|
42
36
|
version_requirements: !ruby/object:Gem::Requirement
|
43
37
|
requirements:
|
44
|
-
- -
|
38
|
+
- - ">="
|
45
39
|
- !ruby/object:Gem::Version
|
46
40
|
version: '0'
|
47
41
|
- !ruby/object:Gem::Dependency
|
48
42
|
name: rake
|
49
43
|
requirement: !ruby/object:Gem::Requirement
|
50
44
|
requirements:
|
51
|
-
- -
|
45
|
+
- - ">="
|
52
46
|
- !ruby/object:Gem::Version
|
53
47
|
version: '0'
|
54
48
|
type: :development
|
55
49
|
prerelease: false
|
56
50
|
version_requirements: !ruby/object:Gem::Requirement
|
57
51
|
requirements:
|
58
|
-
- -
|
52
|
+
- - ">="
|
59
53
|
- !ruby/object:Gem::Version
|
60
54
|
version: '0'
|
61
55
|
- !ruby/object:Gem::Dependency
|
62
56
|
name: rails
|
63
57
|
requirement: !ruby/object:Gem::Requirement
|
64
58
|
requirements:
|
65
|
-
- -
|
59
|
+
- - ">="
|
66
60
|
- !ruby/object:Gem::Version
|
67
61
|
version: '0'
|
68
62
|
type: :development
|
69
63
|
prerelease: false
|
70
64
|
version_requirements: !ruby/object:Gem::Requirement
|
71
65
|
requirements:
|
72
|
-
- -
|
66
|
+
- - ">="
|
73
67
|
- !ruby/object:Gem::Version
|
74
68
|
version: '0'
|
75
69
|
- !ruby/object:Gem::Dependency
|
76
70
|
name: capybara
|
77
71
|
requirement: !ruby/object:Gem::Requirement
|
78
72
|
requirements:
|
79
|
-
- -
|
73
|
+
- - ">="
|
80
74
|
- !ruby/object:Gem::Version
|
81
75
|
version: '0'
|
82
76
|
type: :development
|
83
77
|
prerelease: false
|
84
78
|
version_requirements: !ruby/object:Gem::Requirement
|
85
79
|
requirements:
|
86
|
-
- -
|
80
|
+
- - ">="
|
87
81
|
- !ruby/object:Gem::Version
|
88
82
|
version: '0'
|
89
83
|
- !ruby/object:Gem::Dependency
|
90
84
|
name: poltergeist
|
91
85
|
requirement: !ruby/object:Gem::Requirement
|
92
86
|
requirements:
|
93
|
-
- -
|
87
|
+
- - ">="
|
94
88
|
- !ruby/object:Gem::Version
|
95
89
|
version: '0'
|
96
90
|
type: :development
|
97
91
|
prerelease: false
|
98
92
|
version_requirements: !ruby/object:Gem::Requirement
|
99
93
|
requirements:
|
100
|
-
- -
|
94
|
+
- - ">="
|
101
95
|
- !ruby/object:Gem::Version
|
102
96
|
version: '0'
|
103
97
|
description:
|
@@ -109,8 +103,9 @@ files:
|
|
109
103
|
- lib/pjax.rb
|
110
104
|
- lib/pjax_rails.rb
|
111
105
|
- vendor/assets/javascripts/jquery.pjax.js
|
112
|
-
homepage:
|
113
|
-
licenses:
|
106
|
+
homepage: https://github.com/rails/pjax_rails
|
107
|
+
licenses:
|
108
|
+
- MIT
|
114
109
|
metadata: {}
|
115
110
|
post_install_message:
|
116
111
|
rdoc_options: []
|
@@ -118,19 +113,18 @@ require_paths:
|
|
118
113
|
- lib
|
119
114
|
required_ruby_version: !ruby/object:Gem::Requirement
|
120
115
|
requirements:
|
121
|
-
- -
|
116
|
+
- - ">="
|
122
117
|
- !ruby/object:Gem::Version
|
123
118
|
version: '0'
|
124
119
|
required_rubygems_version: !ruby/object:Gem::Requirement
|
125
120
|
requirements:
|
126
|
-
- -
|
121
|
+
- - ">="
|
127
122
|
- !ruby/object:Gem::Version
|
128
123
|
version: '0'
|
129
124
|
requirements: []
|
130
125
|
rubyforge_project:
|
131
|
-
rubygems_version: 2.
|
126
|
+
rubygems_version: 2.7.6
|
132
127
|
signing_key:
|
133
128
|
specification_version: 4
|
134
|
-
summary: PJAX integration for Rails 3.
|
129
|
+
summary: PJAX integration for Rails 3.2+
|
135
130
|
test_files: []
|
136
|
-
has_rdoc:
|