pjax_rails 0.2.2 → 0.3.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.
- data/lib/pjax.rb +25 -1
- data/vendor/assets/javascripts/jquery.pjax.js +176 -138
- metadata +2 -2
data/lib/pjax.rb
CHANGED
@@ -9,6 +9,11 @@ module Pjax
|
|
9
9
|
before_filter :set_pjax_url, :if => :pjax_request?
|
10
10
|
end
|
11
11
|
|
12
|
+
class Error < StandardError; end
|
13
|
+
class Unsupported < Error; end
|
14
|
+
|
15
|
+
rescue_from Pjax::Unsupported, :with => :pjax_unsupported
|
16
|
+
|
12
17
|
protected
|
13
18
|
def pjax_request?
|
14
19
|
env['HTTP_X_PJAX'].present?
|
@@ -23,9 +28,28 @@ module Pjax
|
|
23
28
|
request.headers['X-PJAX-Container']
|
24
29
|
end
|
25
30
|
|
31
|
+
def pjax_unsupported
|
32
|
+
head :not_acceptable
|
33
|
+
end
|
34
|
+
|
35
|
+
# Call in a before_filter or in an action to disable pjax on an action.
|
36
|
+
#
|
37
|
+
# Examples
|
38
|
+
#
|
39
|
+
# before_filter :prevent_pjax!
|
40
|
+
#
|
41
|
+
# def login
|
42
|
+
# prevent_pjax!
|
43
|
+
# # ...
|
44
|
+
# end
|
45
|
+
#
|
46
|
+
def prevent_pjax!
|
47
|
+
raise PjaxUnsupported if pjax_request?
|
48
|
+
end
|
49
|
+
|
26
50
|
def strip_pjax_param
|
27
51
|
params.delete(:_pjax)
|
28
|
-
request.env['QUERY_STRING'].sub
|
52
|
+
request.env['QUERY_STRING'] = request.env['QUERY_STRING'].sub(/_pjax=[^&]+&?/, '')
|
29
53
|
|
30
54
|
request.env.delete('rack.request.query_string')
|
31
55
|
request.env.delete('rack.request.query_hash')
|
@@ -23,7 +23,7 @@
|
|
23
23
|
// the options object.
|
24
24
|
//
|
25
25
|
// Returns the jQuery object
|
26
|
-
|
26
|
+
function fnPjax(container, options) {
|
27
27
|
return this.live('click.pjax', function(event){
|
28
28
|
handleClick(event, container, options)
|
29
29
|
})
|
@@ -82,12 +82,11 @@ function handleClick(event, container, options) {
|
|
82
82
|
fragment: null
|
83
83
|
}
|
84
84
|
|
85
|
-
|
85
|
+
pjax($.extend({}, defaults, options))
|
86
86
|
|
87
87
|
event.preventDefault()
|
88
88
|
}
|
89
89
|
|
90
|
-
|
91
90
|
// Loads a URL with ajax, puts the response body inside a container,
|
92
91
|
// then pushState()'s the loaded URL.
|
93
92
|
//
|
@@ -107,7 +106,7 @@ function handleClick(event, container, options) {
|
|
107
106
|
// console.log( xhr.readyState )
|
108
107
|
//
|
109
108
|
// Returns whatever $.ajax returns.
|
110
|
-
|
109
|
+
function pjax(options) {
|
111
110
|
options = $.extend(true, {}, $.ajaxSettings, pjax.defaults, options)
|
112
111
|
|
113
112
|
if ($.isFunction(options.url)) {
|
@@ -146,6 +145,12 @@ var pjax = $.pjax = function( options ) {
|
|
146
145
|
var timeoutTimer
|
147
146
|
|
148
147
|
options.beforeSend = function(xhr, settings) {
|
148
|
+
// No timeout for non-GET requests
|
149
|
+
// Its not safe to request the resource again with a fallback method.
|
150
|
+
if (settings.type !== 'GET') {
|
151
|
+
settings.timeout = 0
|
152
|
+
}
|
153
|
+
|
149
154
|
if (settings.timeout > 0) {
|
150
155
|
timeoutTimer = setTimeout(function() {
|
151
156
|
if (fire('pjax:timeout', [xhr, options]))
|
@@ -302,6 +307,121 @@ var pjax = $.pjax = function( options ) {
|
|
302
307
|
return pjax.xhr
|
303
308
|
}
|
304
309
|
|
310
|
+
// Public: Reload current page with pjax.
|
311
|
+
//
|
312
|
+
// Returns whatever $.pjax returns.
|
313
|
+
function pjaxReload(container, options) {
|
314
|
+
var defaults = {
|
315
|
+
url: window.location.href,
|
316
|
+
push: false,
|
317
|
+
replace: true,
|
318
|
+
scrollTo: false
|
319
|
+
}
|
320
|
+
|
321
|
+
return pjax($.extend(defaults, optionsFor(container, options)))
|
322
|
+
}
|
323
|
+
|
324
|
+
// popstate handler takes care of the back and forward buttons
|
325
|
+
//
|
326
|
+
// You probably shouldn't use pjax on pages with other pushState
|
327
|
+
// stuff yet.
|
328
|
+
function onPjaxPopstate(event) {
|
329
|
+
var state = event.state
|
330
|
+
|
331
|
+
if (state && state.container) {
|
332
|
+
var container = $(state.container)
|
333
|
+
if (container.length) {
|
334
|
+
var contents = cacheMapping[state.id]
|
335
|
+
|
336
|
+
if (pjax.state) {
|
337
|
+
// Since state ids always increase, we can deduce the history
|
338
|
+
// direction from the previous state.
|
339
|
+
var direction = pjax.state.id < state.id ? 'forward' : 'back'
|
340
|
+
|
341
|
+
// Cache current container before replacement and inform the
|
342
|
+
// cache which direction the history shifted.
|
343
|
+
cachePop(direction, pjax.state.id, container.clone().contents())
|
344
|
+
}
|
345
|
+
|
346
|
+
var popstateEvent = $.Event('pjax:popstate', {
|
347
|
+
state: state,
|
348
|
+
direction: direction
|
349
|
+
})
|
350
|
+
container.trigger(popstateEvent)
|
351
|
+
|
352
|
+
var options = {
|
353
|
+
id: state.id,
|
354
|
+
url: state.url,
|
355
|
+
container: container,
|
356
|
+
push: false,
|
357
|
+
fragment: state.fragment,
|
358
|
+
timeout: state.timeout,
|
359
|
+
scrollTo: false
|
360
|
+
}
|
361
|
+
|
362
|
+
if (contents) {
|
363
|
+
// pjax event is deprecated
|
364
|
+
$(document).trigger('pjax', [null, options])
|
365
|
+
container.trigger('pjax:start', [null, options])
|
366
|
+
// end.pjax event is deprecated
|
367
|
+
container.trigger('start.pjax', [null, options])
|
368
|
+
|
369
|
+
if (state.title) document.title = state.title
|
370
|
+
container.html(contents)
|
371
|
+
pjax.state = state
|
372
|
+
|
373
|
+
container.trigger('pjax:end', [null, options])
|
374
|
+
// end.pjax event is deprecated
|
375
|
+
container.trigger('end.pjax', [null, options])
|
376
|
+
} else {
|
377
|
+
pjax(options)
|
378
|
+
}
|
379
|
+
|
380
|
+
// Force reflow/relayout before the browser tries to restore the
|
381
|
+
// scroll position.
|
382
|
+
container[0].offsetHeight
|
383
|
+
} else {
|
384
|
+
window.location = location.href
|
385
|
+
}
|
386
|
+
}
|
387
|
+
}
|
388
|
+
|
389
|
+
// Fallback version of main pjax function for browsers that don't
|
390
|
+
// support pushState.
|
391
|
+
//
|
392
|
+
// Returns nothing since it retriggers a hard form submission.
|
393
|
+
function fallbackPjax(options) {
|
394
|
+
var url = $.isFunction(options.url) ? options.url() : options.url,
|
395
|
+
method = options.type ? options.type.toUpperCase() : 'GET'
|
396
|
+
|
397
|
+
var form = $('<form>', {
|
398
|
+
method: method === 'GET' ? 'GET' : 'POST',
|
399
|
+
action: url,
|
400
|
+
style: 'display:none'
|
401
|
+
})
|
402
|
+
|
403
|
+
if (method !== 'GET' && method !== 'POST') {
|
404
|
+
form.append($('<input>', {
|
405
|
+
type: 'hidden',
|
406
|
+
name: '_method',
|
407
|
+
value: method.toLowerCase()
|
408
|
+
}))
|
409
|
+
}
|
410
|
+
|
411
|
+
var data = options.data
|
412
|
+
if (typeof data === 'string') {
|
413
|
+
$.each(data.split('&'), function(index, value) {
|
414
|
+
var pair = value.split('=')
|
415
|
+
form.append($('<input>', {type: 'hidden', name: pair[0], value: pair[1]}))
|
416
|
+
})
|
417
|
+
} else if (typeof data === 'object') {
|
418
|
+
for (key in data)
|
419
|
+
form.append($('<input>', {type: 'hidden', name: key, value: data[key]}))
|
420
|
+
}
|
421
|
+
|
422
|
+
$(document.body).append(form)
|
423
|
+
form.submit()
|
424
|
+
}
|
305
425
|
|
306
426
|
// Internal: Generate unique id for state object.
|
307
427
|
//
|
@@ -476,35 +596,11 @@ function extractContainer(data, xhr, options) {
|
|
476
596
|
return obj
|
477
597
|
}
|
478
598
|
|
479
|
-
// Public: Reload current page with pjax.
|
480
|
-
//
|
481
|
-
// Returns whatever $.pjax returns.
|
482
|
-
pjax.reload = function(container, options) {
|
483
|
-
var defaults = {
|
484
|
-
url: window.location.href,
|
485
|
-
push: false,
|
486
|
-
replace: true,
|
487
|
-
scrollTo: false
|
488
|
-
}
|
489
|
-
|
490
|
-
return $.pjax($.extend(defaults, optionsFor(container, options)))
|
491
|
-
}
|
492
|
-
|
493
|
-
|
494
|
-
pjax.defaults = {
|
495
|
-
timeout: 650,
|
496
|
-
push: true,
|
497
|
-
replace: false,
|
498
|
-
type: 'GET',
|
499
|
-
dataType: 'html',
|
500
|
-
scrollTo: 0,
|
501
|
-
maxCacheLength: 20
|
502
|
-
}
|
503
|
-
|
504
599
|
// Internal: History DOM caching class.
|
505
600
|
var cacheMapping = {}
|
506
601
|
var cacheForwardStack = []
|
507
602
|
var cacheBackStack = []
|
603
|
+
|
508
604
|
// Push previous state id and container contents into the history
|
509
605
|
// cache. Should be called in conjunction with `pushState` to save the
|
510
606
|
// previous container contents.
|
@@ -526,6 +622,7 @@ function cachePush(id, value) {
|
|
526
622
|
while (cacheBackStack.length > pjax.defaults.maxCacheLength)
|
527
623
|
delete cacheMapping[cacheBackStack.shift()]
|
528
624
|
}
|
625
|
+
|
529
626
|
// Shifts cache from directional history cache. Should be
|
530
627
|
// called on `popstate` with the previous state id and container
|
531
628
|
// contents.
|
@@ -552,75 +649,54 @@ function cachePop(direction, id, value) {
|
|
552
649
|
delete cacheMapping[id]
|
553
650
|
}
|
554
651
|
|
555
|
-
|
556
|
-
// Export $.pjax.click
|
557
|
-
pjax.click = handleClick
|
558
|
-
|
559
|
-
|
560
|
-
// popstate handler takes care of the back and forward buttons
|
652
|
+
// Install pjax functions on $.pjax to enable pushState behavior.
|
561
653
|
//
|
562
|
-
//
|
563
|
-
//
|
564
|
-
|
565
|
-
|
566
|
-
|
567
|
-
|
568
|
-
|
569
|
-
|
570
|
-
|
571
|
-
|
572
|
-
|
573
|
-
|
574
|
-
|
575
|
-
|
576
|
-
|
577
|
-
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
|
582
|
-
|
583
|
-
|
584
|
-
direction: direction
|
585
|
-
})
|
586
|
-
container.trigger(popstateEvent)
|
587
|
-
|
588
|
-
var options = {
|
589
|
-
id: state.id,
|
590
|
-
url: state.url,
|
591
|
-
container: container,
|
592
|
-
push: false,
|
593
|
-
fragment: state.fragment,
|
594
|
-
timeout: state.timeout,
|
595
|
-
scrollTo: false
|
596
|
-
}
|
597
|
-
|
598
|
-
if (contents) {
|
599
|
-
// pjax event is deprecated
|
600
|
-
$(document).trigger('pjax', [null, options])
|
601
|
-
container.trigger('pjax:start', [null, options])
|
602
|
-
// end.pjax event is deprecated
|
603
|
-
container.trigger('start.pjax', [null, options])
|
604
|
-
|
605
|
-
if (state.title) document.title = state.title
|
606
|
-
container.html(contents)
|
607
|
-
pjax.state = state
|
608
|
-
|
609
|
-
container.trigger('pjax:end', [null, options])
|
610
|
-
// end.pjax event is deprecated
|
611
|
-
container.trigger('end.pjax', [null, options])
|
612
|
-
} else {
|
613
|
-
$.pjax(options)
|
614
|
-
}
|
615
|
-
|
616
|
-
// Force reflow/relayout before the browser tries to restore the
|
617
|
-
// scroll position.
|
618
|
-
container[0].offsetHeight
|
619
|
-
} else {
|
620
|
-
window.location = location.href
|
621
|
-
}
|
654
|
+
// Does nothing if already enabled.
|
655
|
+
//
|
656
|
+
// Examples
|
657
|
+
//
|
658
|
+
// $.pjax.enable()
|
659
|
+
//
|
660
|
+
// Returns nothing.
|
661
|
+
function enable() {
|
662
|
+
$.fn.pjax = fnPjax
|
663
|
+
$.pjax = pjax
|
664
|
+
$.pjax.enable = $.noop
|
665
|
+
$.pjax.disable = disable
|
666
|
+
$.pjax.click = handleClick
|
667
|
+
$.pjax.reload = pjaxReload
|
668
|
+
$.pjax.defaults = {
|
669
|
+
timeout: 650,
|
670
|
+
push: true,
|
671
|
+
replace: false,
|
672
|
+
type: 'GET',
|
673
|
+
dataType: 'html',
|
674
|
+
scrollTo: 0,
|
675
|
+
maxCacheLength: 20
|
622
676
|
}
|
623
|
-
|
677
|
+
$(window).bind('popstate.pjax', onPjaxPopstate)
|
678
|
+
}
|
679
|
+
|
680
|
+
// Disable pushState behavior.
|
681
|
+
//
|
682
|
+
// This is the case when a browser doesn't support pushState. It is
|
683
|
+
// sometimes useful to disable pushState for debugging on a modern
|
684
|
+
// browser.
|
685
|
+
//
|
686
|
+
// Examples
|
687
|
+
//
|
688
|
+
// $.pjax.disable()
|
689
|
+
//
|
690
|
+
// Returns nothing.
|
691
|
+
function disable() {
|
692
|
+
$.fn.pjax = function() { return this }
|
693
|
+
$.pjax = fallbackPjax
|
694
|
+
$.pjax.enable = enable
|
695
|
+
$.pjax.disable = $.noop
|
696
|
+
$.pjax.click = $.noop
|
697
|
+
$.pjax.reload = window.location.reload
|
698
|
+
$(window).unbind('popstate.pjax', onPjaxPopstate)
|
699
|
+
}
|
624
700
|
|
625
701
|
|
626
702
|
// Add the state property to jQuery's event object so we can use it in
|
@@ -628,50 +704,12 @@ $(window).bind('popstate', function(event){
|
|
628
704
|
if ( $.inArray('state', $.event.props) < 0 )
|
629
705
|
$.event.props.push('state')
|
630
706
|
|
631
|
-
|
632
|
-
// Is pjax supported by this browser?
|
707
|
+
// Is pjax supported by this browser?
|
633
708
|
$.support.pjax =
|
634
|
-
window.history && window.history.pushState && window.history.replaceState
|
709
|
+
window.history && window.history.pushState && window.history.replaceState &&
|
635
710
|
// pushState isn't reliable on iOS until 5.
|
636
|
-
|
637
|
-
|
638
|
-
// Fall back to normalcy for older browsers.
|
639
|
-
if ( !$.support.pjax ) {
|
640
|
-
$.pjax = function( options ) {
|
641
|
-
var url = $.isFunction(options.url) ? options.url() : options.url,
|
642
|
-
method = options.type ? options.type.toUpperCase() : 'GET'
|
643
|
-
|
644
|
-
var form = $('<form>', {
|
645
|
-
method: method === 'GET' ? 'GET' : 'POST',
|
646
|
-
action: url,
|
647
|
-
style: 'display:none'
|
648
|
-
})
|
649
|
-
|
650
|
-
if (method !== 'GET' && method !== 'POST') {
|
651
|
-
form.append($('<input>', {
|
652
|
-
type: 'hidden',
|
653
|
-
name: '_method',
|
654
|
-
value: method.toLowerCase()
|
655
|
-
}))
|
656
|
-
}
|
657
|
-
|
658
|
-
var data = options.data
|
659
|
-
if (typeof data === 'string') {
|
660
|
-
$.each(data.split('&'), function(index, value) {
|
661
|
-
var pair = value.split('=')
|
662
|
-
form.append($('<input>', {type: 'hidden', name: pair[0], value: pair[1]}))
|
663
|
-
})
|
664
|
-
} else if (typeof data === 'object') {
|
665
|
-
for (key in data)
|
666
|
-
form.append($('<input>', {type: 'hidden', name: key, value: data[key]}))
|
667
|
-
}
|
711
|
+
!navigator.userAgent.match(/((iPod|iPhone|iPad).+\bOS\s+[1-4]|WebApps\/.+CFNetwork)/)
|
668
712
|
|
669
|
-
|
670
|
-
form.submit()
|
671
|
-
}
|
672
|
-
$.pjax.click = $.noop
|
673
|
-
$.pjax.reload = window.location.reload
|
674
|
-
$.fn.pjax = function() { return this }
|
675
|
-
}
|
713
|
+
$.support.pjax ? enable() : disable()
|
676
714
|
|
677
715
|
})(jQuery);
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: pjax_rails
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.
|
4
|
+
version: 0.3.0
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-08-03 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: jquery-rails
|