rails-pjax 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- data/README.md +4 -4
- data/pjax_rails.gemspec +1 -1
- data/rails-pjax-0.0.1.gem +0 -0
- data/vendor/assets/javascripts/jquery.pjax.js +89 -298
- metadata +4 -3
data/README.md
CHANGED
@@ -29,7 +29,7 @@ The PJAX container has to be marked with data-pjax-container attribute, so for e
|
|
29
29
|
|
30
30
|
FIXME: Currently the layout is hardcoded to "application". Need to delegate that to the specific layout of the controller.
|
31
31
|
|
32
|
-
Examples for
|
32
|
+
Examples for redirect_pjax_to
|
33
33
|
-----------------------------
|
34
34
|
|
35
35
|
class ProjectsController < ApplicationController
|
@@ -44,19 +44,19 @@ Examples for redirect_to
|
|
44
44
|
|
45
45
|
def create
|
46
46
|
@project = Project.create params[:project]
|
47
|
-
|
47
|
+
redirect_pjax_to :show, @project
|
48
48
|
end
|
49
49
|
|
50
50
|
def update
|
51
51
|
@project.update_attributes params[:project]
|
52
|
-
|
52
|
+
redirect_pjax_to :show, @project
|
53
53
|
end
|
54
54
|
|
55
55
|
def destroy
|
56
56
|
@project.destroy
|
57
57
|
|
58
58
|
index # set the objects needed for rendering index
|
59
|
-
|
59
|
+
redirect_pjax_to :index
|
60
60
|
end
|
61
61
|
|
62
62
|
private
|
data/pjax_rails.gemspec
CHANGED
Binary file
|
@@ -24,8 +24,8 @@
|
|
24
24
|
//
|
25
25
|
// Returns the jQuery object
|
26
26
|
$.fn.pjax = function( container, options ) {
|
27
|
-
return this.live('click
|
28
|
-
handleClick(event, container, options)
|
27
|
+
return this.live('click', function(event){
|
28
|
+
return handleClick(event, container, options)
|
29
29
|
})
|
30
30
|
}
|
31
31
|
|
@@ -53,11 +53,7 @@ function handleClick(event, container, options) {
|
|
53
53
|
|
54
54
|
var link = event.currentTarget
|
55
55
|
|
56
|
-
// If current target isnt a link, try to find the first A descendant
|
57
56
|
if (link.tagName.toUpperCase() !== 'A')
|
58
|
-
link = $(link).find('a')[0]
|
59
|
-
|
60
|
-
if (!link)
|
61
57
|
throw "$.fn.pjax or $.pjax.click requires an anchor element"
|
62
58
|
|
63
59
|
// Middle click, cmd click, and ctrl click should open
|
@@ -85,6 +81,30 @@ function handleClick(event, container, options) {
|
|
85
81
|
$.pjax($.extend({}, defaults, options))
|
86
82
|
|
87
83
|
event.preventDefault()
|
84
|
+
return false
|
85
|
+
}
|
86
|
+
|
87
|
+
// Internal: Strips _pjax param from url
|
88
|
+
//
|
89
|
+
// url - String
|
90
|
+
//
|
91
|
+
// Returns String.
|
92
|
+
function stripPjaxParam(url) {
|
93
|
+
return url
|
94
|
+
.replace(/\?_pjax=[^&]+&?/, '?')
|
95
|
+
.replace(/_pjax=[^&]+&?/, '')
|
96
|
+
.replace(/[\?&]$/, '')
|
97
|
+
}
|
98
|
+
|
99
|
+
// Internal: Parse URL components and returns a Locationish object.
|
100
|
+
//
|
101
|
+
// url - String URL
|
102
|
+
//
|
103
|
+
// Returns HTMLAnchorElement that acts like Location.
|
104
|
+
function parseURL(url) {
|
105
|
+
var a = document.createElement('a')
|
106
|
+
a.href = url
|
107
|
+
return a
|
88
108
|
}
|
89
109
|
|
90
110
|
|
@@ -119,7 +139,8 @@ var pjax = $.pjax = function( options ) {
|
|
119
139
|
// DEPRECATED: use options.target
|
120
140
|
if (!target && options.clickedElement) target = options.clickedElement[0]
|
121
141
|
|
122
|
-
var
|
142
|
+
var url = options.url
|
143
|
+
var hash = parseURL(url).hash
|
123
144
|
|
124
145
|
// DEPRECATED: Save references to original event callbacks. However,
|
125
146
|
// listening for custom pjax:* events is prefered.
|
@@ -146,6 +167,8 @@ var pjax = $.pjax = function( options ) {
|
|
146
167
|
var timeoutTimer
|
147
168
|
|
148
169
|
options.beforeSend = function(xhr, settings) {
|
170
|
+
url = stripPjaxParam(settings.url)
|
171
|
+
|
149
172
|
if (settings.timeout > 0) {
|
150
173
|
timeoutTimer = setTimeout(function() {
|
151
174
|
if (fire('pjax:timeout', [xhr, options]))
|
@@ -169,18 +192,9 @@ var pjax = $.pjax = function( options ) {
|
|
169
192
|
|
170
193
|
if (!fire('pjax:beforeSend', [xhr, settings])) return false
|
171
194
|
|
172
|
-
if (options.push && !options.replace) {
|
173
|
-
// Cache current container element before replacing it
|
174
|
-
containerCache.push(pjax.state.id, context.clone(true, true).contents())
|
175
|
-
|
176
|
-
window.history.pushState(null, "", options.url)
|
177
|
-
}
|
178
|
-
|
179
195
|
fire('pjax:start', [xhr, options])
|
180
196
|
// start.pjax is deprecated
|
181
197
|
fire('start.pjax', [xhr, options])
|
182
|
-
|
183
|
-
fire('pjax:send', [xhr, settings])
|
184
198
|
}
|
185
199
|
|
186
200
|
options.complete = function(xhr, textStatus) {
|
@@ -198,42 +212,72 @@ var pjax = $.pjax = function( options ) {
|
|
198
212
|
}
|
199
213
|
|
200
214
|
options.error = function(xhr, textStatus, errorThrown) {
|
201
|
-
var
|
215
|
+
var respUrl = xhr.getResponseHeader('X-PJAX-URL')
|
216
|
+
if (respUrl) url = stripPjaxParam(respUrl)
|
202
217
|
|
203
218
|
// DEPRECATED: Invoke original `error` handler
|
204
219
|
if (oldError) oldError.apply(this, arguments)
|
205
220
|
|
206
221
|
var allowed = fire('pjax:error', [xhr, textStatus, errorThrown, options])
|
207
222
|
if (textStatus !== 'abort' && allowed)
|
208
|
-
window.location =
|
223
|
+
window.location = url
|
209
224
|
}
|
210
225
|
|
211
226
|
options.success = function(data, status, xhr) {
|
212
|
-
var
|
227
|
+
var respUrl = xhr.getResponseHeader('X-PJAX-URL')
|
228
|
+
if (respUrl) url = stripPjaxParam(respUrl)
|
229
|
+
|
230
|
+
var title, oldTitle = document.title
|
231
|
+
|
232
|
+
if ( options.fragment ) {
|
233
|
+
// If they specified a fragment, look for it in the response
|
234
|
+
// and pull it out.
|
235
|
+
var html = $('<html>').html(data)
|
236
|
+
var $fragment = html.find(options.fragment)
|
237
|
+
if ( $fragment.length ) {
|
238
|
+
this.html($fragment.contents())
|
239
|
+
|
240
|
+
// If there's a <title> tag in the response, use it as
|
241
|
+
// the page's title. Otherwise, look for data-title and title attributes.
|
242
|
+
title = html.find('title').text() || $fragment.attr('title') || $fragment.data('title')
|
243
|
+
} else {
|
244
|
+
return window.location = url
|
245
|
+
}
|
246
|
+
} else {
|
247
|
+
// If we got no data or an entire web page, go directly
|
248
|
+
// to the page and let normal error handling happen.
|
249
|
+
if ( !$.trim(data) || /<html/i.test(data) )
|
250
|
+
return window.location = url
|
251
|
+
|
252
|
+
this.html(data)
|
213
253
|
|
214
|
-
|
215
|
-
|
216
|
-
|
254
|
+
// If there's a <title> tag in the response, use it as
|
255
|
+
// the page's title.
|
256
|
+
title = this.find('title').remove().text()
|
217
257
|
}
|
218
258
|
|
219
|
-
|
220
|
-
|
221
|
-
|
222
|
-
|
259
|
+
if ( title ) document.title = $.trim(title)
|
260
|
+
|
261
|
+
var state = {
|
262
|
+
url: url,
|
263
|
+
pjax: this.selector,
|
223
264
|
fragment: options.fragment,
|
224
265
|
timeout: options.timeout
|
225
266
|
}
|
226
267
|
|
227
|
-
if (
|
228
|
-
|
229
|
-
|
230
|
-
|
231
|
-
|
232
|
-
|
268
|
+
if ( options.replace ) {
|
269
|
+
pjax.active = true
|
270
|
+
window.history.replaceState(state, document.title, url)
|
271
|
+
} else if ( options.push ) {
|
272
|
+
// this extra replaceState before first push ensures good back
|
273
|
+
// button behavior
|
274
|
+
if ( !pjax.active ) {
|
275
|
+
window.history.replaceState($.extend({}, state, {url:null}), oldTitle)
|
276
|
+
pjax.active = true
|
277
|
+
}
|
233
278
|
|
234
|
-
|
235
|
-
|
236
|
-
$(window).scrollTop(options.scrollTo)
|
279
|
+
window.history.pushState(state, document.title, url)
|
280
|
+
}
|
237
281
|
|
238
282
|
// Google Analytics support
|
239
283
|
if ( (options.replace || options.push) && window._gaq )
|
@@ -252,21 +296,6 @@ var pjax = $.pjax = function( options ) {
|
|
252
296
|
}
|
253
297
|
|
254
298
|
|
255
|
-
// Initialize pjax.state for the initial page load. Assume we're
|
256
|
-
// using the container and options of the link we're loading for the
|
257
|
-
// back button to the initial page. This ensures good back button
|
258
|
-
// behavior.
|
259
|
-
if (!pjax.state) {
|
260
|
-
pjax.state = {
|
261
|
-
id: uniqueId(),
|
262
|
-
url: window.location.href,
|
263
|
-
container: context.selector,
|
264
|
-
fragment: options.fragment,
|
265
|
-
timeout: options.timeout
|
266
|
-
}
|
267
|
-
window.history.replaceState(pjax.state, document.title)
|
268
|
-
}
|
269
|
-
|
270
299
|
// Cancel the current request if we're already pjaxing
|
271
300
|
var xhr = pjax.xhr
|
272
301
|
if ( xhr && xhr.readyState < 4) {
|
@@ -276,47 +305,12 @@ var pjax = $.pjax = function( options ) {
|
|
276
305
|
|
277
306
|
pjax.options = options
|
278
307
|
pjax.xhr = $.ajax(options)
|
279
|
-
|
280
|
-
// pjax event is deprecated
|
281
308
|
$(document).trigger('pjax', [pjax.xhr, options])
|
282
309
|
|
283
310
|
return pjax.xhr
|
284
311
|
}
|
285
312
|
|
286
313
|
|
287
|
-
// Internal: Generate unique id for state object.
|
288
|
-
//
|
289
|
-
// Use a timestamp instead of a counter since ids should still be
|
290
|
-
// unique across page loads.
|
291
|
-
//
|
292
|
-
// Returns Number.
|
293
|
-
function uniqueId() {
|
294
|
-
return (new Date).getTime()
|
295
|
-
}
|
296
|
-
|
297
|
-
// Internal: Strips _pjax param from url
|
298
|
-
//
|
299
|
-
// url - String
|
300
|
-
//
|
301
|
-
// Returns String.
|
302
|
-
function stripPjaxParam(url) {
|
303
|
-
return url
|
304
|
-
.replace(/\?_pjax=[^&]+&?/, '?')
|
305
|
-
.replace(/_pjax=[^&]+&?/, '')
|
306
|
-
.replace(/[\?&]$/, '')
|
307
|
-
}
|
308
|
-
|
309
|
-
// Internal: Parse URL components and returns a Locationish object.
|
310
|
-
//
|
311
|
-
// url - String URL
|
312
|
-
//
|
313
|
-
// Returns HTMLAnchorElement that acts like Location.
|
314
|
-
function parseURL(url) {
|
315
|
-
var a = document.createElement('a')
|
316
|
-
a.href = url
|
317
|
-
return a
|
318
|
-
}
|
319
|
-
|
320
314
|
// Internal: Build options Object for arguments.
|
321
315
|
//
|
322
316
|
// For convenience the first parameter can be either the container or
|
@@ -376,181 +370,15 @@ function findContainerFor(container) {
|
|
376
370
|
}
|
377
371
|
}
|
378
372
|
|
379
|
-
// Internal: Filter and find all elements matching the selector.
|
380
|
-
//
|
381
|
-
// Where $.fn.find only matches descendants, findAll will test all the
|
382
|
-
// top level elements in the jQuery object as well.
|
383
|
-
//
|
384
|
-
// elems - jQuery object of Elements
|
385
|
-
// selector - String selector to match
|
386
|
-
//
|
387
|
-
// Returns a jQuery object.
|
388
|
-
function findAll(elems, selector) {
|
389
|
-
var results = $()
|
390
|
-
elems.each(function() {
|
391
|
-
if ($(this).is(selector))
|
392
|
-
results = results.add(this)
|
393
|
-
results = results.add(selector, this)
|
394
|
-
})
|
395
|
-
return results
|
396
|
-
}
|
397
|
-
|
398
|
-
// Internal: Extracts container and metadata from response.
|
399
|
-
//
|
400
|
-
// 1. Extracts X-PJAX-URL header if set
|
401
|
-
// 2. Extracts inline <title> tags
|
402
|
-
// 3. Builds response Element and extracts fragment if set
|
403
|
-
//
|
404
|
-
// data - String response data
|
405
|
-
// xhr - XHR response
|
406
|
-
// options - pjax options Object
|
407
|
-
//
|
408
|
-
// Returns an Object with url, title, and contents keys.
|
409
|
-
function extractContainer(data, xhr, options) {
|
410
|
-
var obj = {}
|
411
|
-
|
412
|
-
// Prefer X-PJAX-URL header if it was set, otherwise fallback to
|
413
|
-
// using the original requested url.
|
414
|
-
obj.url = stripPjaxParam(xhr.getResponseHeader('X-PJAX-URL') || options.url)
|
415
|
-
|
416
|
-
// Attempt to parse response html into elements
|
417
|
-
var $data = $(data)
|
418
|
-
|
419
|
-
// If response data is empty, return fast
|
420
|
-
if ($data.length === 0)
|
421
|
-
return obj
|
422
|
-
|
423
|
-
// If there's a <title> tag in the response, use it as
|
424
|
-
// the page's title.
|
425
|
-
obj.title = findAll($data, 'title').last().text()
|
426
|
-
|
427
|
-
if (options.fragment) {
|
428
|
-
// If they specified a fragment, look for it in the response
|
429
|
-
// and pull it out.
|
430
|
-
var $fragment = findAll($data, options.fragment).first()
|
431
|
-
|
432
|
-
if ($fragment.length) {
|
433
|
-
obj.contents = $fragment.contents()
|
434
|
-
|
435
|
-
// If there's no title, look for data-title and title attributes
|
436
|
-
// on the fragment
|
437
|
-
if (!obj.title)
|
438
|
-
obj.title = $fragment.attr('title') || $fragment.data('title')
|
439
|
-
}
|
440
|
-
|
441
|
-
} else if (!/<html/i.test(data)) {
|
442
|
-
obj.contents = $data
|
443
|
-
}
|
444
|
-
|
445
|
-
// Clean up any <title> tags
|
446
|
-
if (obj.contents) {
|
447
|
-
// Remove any parent title elements
|
448
|
-
obj.contents = obj.contents.not('title')
|
449
|
-
|
450
|
-
// Then scrub any titles from their descendents
|
451
|
-
obj.contents.find('title').remove()
|
452
|
-
}
|
453
|
-
|
454
|
-
// Trim any whitespace off the title
|
455
|
-
if (obj.title) obj.title = $.trim(obj.title)
|
456
|
-
|
457
|
-
return obj
|
458
|
-
}
|
459
|
-
|
460
|
-
// Public: Reload current page with pjax.
|
461
|
-
//
|
462
|
-
// Returns whatever $.pjax returns.
|
463
|
-
pjax.reload = function(container, options) {
|
464
|
-
var defaults = {
|
465
|
-
url: window.location.href,
|
466
|
-
push: false,
|
467
|
-
replace: true,
|
468
|
-
scrollTo: false
|
469
|
-
}
|
470
|
-
|
471
|
-
return $.pjax($.extend(defaults, optionsFor(container, options)))
|
472
|
-
}
|
473
|
-
|
474
373
|
|
475
374
|
pjax.defaults = {
|
476
375
|
timeout: 650,
|
477
376
|
push: true,
|
478
377
|
replace: false,
|
479
378
|
type: 'GET',
|
480
|
-
dataType: 'html'
|
481
|
-
scrollTo: 0,
|
482
|
-
maxCacheLength: 20
|
379
|
+
dataType: 'html'
|
483
380
|
}
|
484
381
|
|
485
|
-
// Internal: History DOM caching class.
|
486
|
-
function Cache() {
|
487
|
-
this.mapping = {}
|
488
|
-
this.forwardStack = []
|
489
|
-
this.backStack = []
|
490
|
-
}
|
491
|
-
// Push previous state id and container contents into the history
|
492
|
-
// cache. Should be called in conjunction with `pushState` to save the
|
493
|
-
// previous container contents.
|
494
|
-
//
|
495
|
-
// id - State ID Number
|
496
|
-
// value - DOM Element to cache
|
497
|
-
//
|
498
|
-
// Returns nothing.
|
499
|
-
Cache.prototype.push = function(id, value) {
|
500
|
-
this.mapping[id] = value
|
501
|
-
this.backStack.push(id)
|
502
|
-
|
503
|
-
// Remove all entires in forward history stack after pushing
|
504
|
-
// a new page.
|
505
|
-
while (this.forwardStack.length)
|
506
|
-
delete this.mapping[this.forwardStack.shift()]
|
507
|
-
|
508
|
-
// Trim back history stack to max cache length.
|
509
|
-
while (this.backStack.length > pjax.defaults.maxCacheLength)
|
510
|
-
delete this.mapping[this.backStack.shift()]
|
511
|
-
}
|
512
|
-
// Retrieve cached DOM Element for state id.
|
513
|
-
//
|
514
|
-
// id - State ID Number
|
515
|
-
//
|
516
|
-
// Returns DOM Element(s) or undefined if cache miss.
|
517
|
-
Cache.prototype.get = function(id) {
|
518
|
-
return this.mapping[id]
|
519
|
-
}
|
520
|
-
// Shifts cache from forward history cache to back stack. Should be
|
521
|
-
// called on `popstate` with the previous state id and container
|
522
|
-
// contents.
|
523
|
-
//
|
524
|
-
// id - State ID Number
|
525
|
-
// value - DOM Element to cache
|
526
|
-
//
|
527
|
-
// Returns nothing.
|
528
|
-
Cache.prototype.forward = function(id, value) {
|
529
|
-
this.mapping[id] = value
|
530
|
-
this.backStack.push(id)
|
531
|
-
|
532
|
-
if (id = this.forwardStack.pop())
|
533
|
-
delete this.mapping[id]
|
534
|
-
}
|
535
|
-
// Shifts cache from back history cache to forward stack. Should be
|
536
|
-
// called on `popstate` with the previous state id and container
|
537
|
-
// contents.
|
538
|
-
//
|
539
|
-
// id - State ID Number
|
540
|
-
// value - DOM Element to cache
|
541
|
-
//
|
542
|
-
// Returns nothing.
|
543
|
-
Cache.prototype.back = function(id, value) {
|
544
|
-
this.mapping[id] = value
|
545
|
-
this.forwardStack.push(id)
|
546
|
-
|
547
|
-
if (id = this.backStack.pop())
|
548
|
-
delete this.mapping[id]
|
549
|
-
}
|
550
|
-
|
551
|
-
var containerCache = new Cache
|
552
|
-
|
553
|
-
|
554
382
|
// Export $.pjax.click
|
555
383
|
pjax.click = handleClick
|
556
384
|
|
@@ -572,54 +400,18 @@ $(window).bind('popstate', function(event){
|
|
572
400
|
|
573
401
|
var state = event.state
|
574
402
|
|
575
|
-
if (state && state.
|
576
|
-
var container =
|
577
|
-
if (container.length)
|
578
|
-
|
579
|
-
|
580
|
-
|
581
|
-
// Since state ids always increase, we can deduce the history
|
582
|
-
// direction from the previous state.
|
583
|
-
var direction = pjax.state.id < state.id ? 'forward' : 'back'
|
584
|
-
|
585
|
-
// Cache current container before replacement and inform the
|
586
|
-
// cache which direction the history shifted.
|
587
|
-
containerCache[direction](pjax.state.id, container.clone(true, true).contents())
|
588
|
-
}
|
589
|
-
|
590
|
-
var options = {
|
591
|
-
id: state.id,
|
592
|
-
url: state.url,
|
403
|
+
if ( state && state.pjax ) {
|
404
|
+
var container = state.pjax
|
405
|
+
if ( $(container+'').length )
|
406
|
+
$.pjax({
|
407
|
+
url: state.url || location.href,
|
408
|
+
fragment: state.fragment,
|
593
409
|
container: container,
|
594
410
|
push: false,
|
595
|
-
|
596
|
-
|
597
|
-
|
598
|
-
}
|
599
|
-
|
600
|
-
if (contents) {
|
601
|
-
// pjax event is deprecated
|
602
|
-
$(document).trigger('pjax', [null, options])
|
603
|
-
container.trigger('pjax:start', [null, options])
|
604
|
-
// end.pjax event is deprecated
|
605
|
-
container.trigger('start.pjax', [null, options])
|
606
|
-
|
607
|
-
container.html(contents)
|
608
|
-
pjax.state = state
|
609
|
-
|
610
|
-
container.trigger('pjax:end', [null, options])
|
611
|
-
// end.pjax event is deprecated
|
612
|
-
container.trigger('end.pjax', [null, options])
|
613
|
-
} else {
|
614
|
-
$.pjax(options)
|
615
|
-
}
|
616
|
-
|
617
|
-
// Force reflow/relayout before the browser tries to restore the
|
618
|
-
// scroll position.
|
619
|
-
container[0].offsetHeight
|
620
|
-
} else {
|
411
|
+
timeout: state.timeout
|
412
|
+
})
|
413
|
+
else
|
621
414
|
window.location = location.href
|
622
|
-
}
|
623
415
|
}
|
624
416
|
})
|
625
417
|
|
@@ -672,7 +464,6 @@ if ( !$.support.pjax ) {
|
|
672
464
|
form.submit()
|
673
465
|
}
|
674
466
|
$.pjax.click = $.noop
|
675
|
-
$.pjax.reload = window.location.reload
|
676
467
|
$.fn.pjax = function() { return this }
|
677
468
|
}
|
678
469
|
|
metadata
CHANGED
@@ -1,13 +1,13 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: rails-pjax
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
hash:
|
4
|
+
hash: 27
|
5
5
|
prerelease:
|
6
6
|
segments:
|
7
7
|
- 0
|
8
8
|
- 0
|
9
|
-
-
|
10
|
-
version: 0.0.
|
9
|
+
- 2
|
10
|
+
version: 0.0.2
|
11
11
|
platform: ruby
|
12
12
|
authors:
|
13
13
|
- Helioid (original David Heinemeier Hansson and PJAX by Chris Wanstrath)
|
@@ -42,6 +42,7 @@ extra_rdoc_files: []
|
|
42
42
|
files:
|
43
43
|
- ./pjax_rails.gemspec
|
44
44
|
- ./README.md
|
45
|
+
- ./rails-pjax-0.0.1.gem
|
45
46
|
- ./vendor/assets/javascripts/jquery.pjax.js
|
46
47
|
- ./lib/pjax_rails.rb
|
47
48
|
- ./lib/pjax.rb
|