pjax_rails 0.2.2 → 0.3.0
Sign up to get free protection for your applications and to get access to all the features.
- 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
|