rails_admin 0.4.1 → 0.4.2

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.

Potentially problematic release.


This version of rails_admin might be problematic. Click here for more details.

data/README.md CHANGED
@@ -1,12 +1,14 @@
1
1
  # RailsAdmin
2
+ [![Gem Version](https://badge.fury.io/rb/rails_admin.png)][gem]
2
3
  [![Build Status](https://secure.travis-ci.org/sferik/rails_admin.png?branch=master)][travis]
3
4
  [![Dependency Status](https://gemnasium.com/sferik/rails_admin.png?travis)][gemnasium]
4
5
  [![Code Climate](https://codeclimate.com/badge.png)][codeclimate]
5
- [![Pledgie](https://www.pledgie.com/campaigns/15917.png)][pledgie]
6
+ [![Pledgie](http://www.pledgie.com/campaigns/15917.png)][pledgie]
6
7
  [![Flattr](http://api.flattr.com/button/flattr-badge-large.png)][flattr]
7
8
 
8
9
  RailsAdmin is a Rails engine that provides an easy-to-use interface for managing your data.
9
10
 
11
+ [gem]: https://rubygems.org/gems/rails_admin
10
12
  [travis]: http://travis-ci.org/sferik/rails_admin
11
13
  [gemnasium]: https://gemnasium.com/sferik/rails_admin
12
14
  [codeclimate]: https://codeclimate.com/github/sferik/rails_admin
@@ -4,28 +4,36 @@
4
4
 
5
5
  (function($){
6
6
 
7
- // When called on a link, fetches the href with ajax into the
8
- // container specified as the first parameter or with the data-pjax
9
- // attribute on the link itself.
7
+ // When called on a container with a selector, fetches the href with
8
+ // ajax into the container or with the data-pjax attribute on the link
9
+ // itself.
10
10
  //
11
11
  // Tries to make sure the back button and ctrl+click work the way
12
12
  // you'd expect.
13
13
  //
14
+ // Exported as $.fn.pjax
15
+ //
14
16
  // Accepts a jQuery ajax options object that may include these
15
17
  // pjax specific options:
16
18
  //
19
+ //
17
20
  // container - Where to stick the response body. Usually a String selector.
18
21
  // $(container).html(xhr.responseBody)
22
+ // (default: current jquery context)
19
23
  // push - Whether to pushState the URL. Defaults to true (of course).
20
24
  // replace - Want to use replaceState instead? That's cool.
21
25
  //
22
- // For convenience the first parameter can be either the container or
26
+ // For convenience the second parameter can be either the container or
23
27
  // the options object.
24
28
  //
25
29
  // Returns the jQuery object
26
- $.fn.pjax = function( container, options ) {
27
- return this.live('click.pjax', function(event){
28
- return handleClick(event, container, options)
30
+ function fnPjax(selector, container, options) {
31
+ var context = this
32
+ return this.on('click.pjax', selector, function(event) {
33
+ var opts = $.extend({}, optionsFor(container, options))
34
+ if (!opts.container)
35
+ opts.container = $(this).attr('data-pjax') || context
36
+ handleClick(event, opts)
29
37
  })
30
38
  }
31
39
 
@@ -38,16 +46,16 @@ $.fn.pjax = function( container, options ) {
38
46
  //
39
47
  // Examples
40
48
  //
41
- // $('a').live('click', $.pjax.click)
49
+ // $(document).on('click', 'a', $.pjax.click)
42
50
  // // is the same as
43
- // $('a').pjax()
51
+ // $(document).pjax('a')
44
52
  //
45
53
  // $(document).on('click', 'a', function(event) {
46
54
  // var container = $(this).closest('[data-pjax-container]')
47
- // return $.pjax.click(event, container)
55
+ // $.pjax.click(event, container)
48
56
  // })
49
57
  //
50
- // Returns false if pjax runs, otherwise nothing.
58
+ // Returns nothing.
51
59
  function handleClick(event, container, options) {
52
60
  options = optionsFor(container, options)
53
61
 
@@ -58,7 +66,7 @@ function handleClick(event, container, options) {
58
66
 
59
67
  // Middle click, cmd click, and ctrl click should open
60
68
  // links in a new tab as normal.
61
- if ( event.which > 1 || event.metaKey )
69
+ if ( event.which > 1 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey )
62
70
  return
63
71
 
64
72
  // Ignore cross origin links
@@ -66,24 +74,62 @@ function handleClick(event, container, options) {
66
74
  return
67
75
 
68
76
  // Ignore anchors on the same page
69
- if ( link.hash && link.href.replace(link.hash, '') ===
70
- location.href.replace(location.hash, '') )
77
+ if (link.hash && link.href.replace(link.hash, '') ===
78
+ location.href.replace(location.hash, ''))
79
+ return
80
+
81
+ // Ignore empty anchor "foo.html#"
82
+ if (link.href === location.href + '#')
71
83
  return
72
84
 
73
85
  var defaults = {
74
86
  url: link.href,
75
87
  container: $(link).attr('data-pjax'),
76
88
  target: link,
77
- clickedElement: $(link), // DEPRECATED: use target
78
89
  fragment: null
79
90
  }
80
91
 
81
- $.pjax($.extend({}, defaults, options))
92
+ pjax($.extend({}, defaults, options))
82
93
 
83
94
  event.preventDefault()
84
- return false
85
95
  }
86
96
 
97
+ // Public: pjax on form submit handler
98
+ //
99
+ // Exported as $.pjax.submit
100
+ //
101
+ // event - "click" jQuery.Event
102
+ // options - pjax options
103
+ //
104
+ // Examples
105
+ //
106
+ // $(document).on('submit', 'form', function(event) {
107
+ // var container = $(this).closest('[data-pjax-container]')
108
+ // $.pjax.submit(event, container)
109
+ // })
110
+ //
111
+ // Returns nothing.
112
+ function handleSubmit(event, container, options) {
113
+ options = optionsFor(container, options)
114
+
115
+ var form = event.currentTarget
116
+
117
+ if (form.tagName.toUpperCase() !== 'FORM')
118
+ throw "$.pjax.submit requires a form element"
119
+
120
+ var defaults = {
121
+ type: form.method,
122
+ url: form.action,
123
+ data: $(form).serializeArray(),
124
+ container: $(form).attr('data-pjax'),
125
+ target: form,
126
+ fragment: null
127
+ }
128
+
129
+ pjax($.extend({}, defaults, options))
130
+
131
+ event.preventDefault()
132
+ }
87
133
 
88
134
  // Loads a URL with ajax, puts the response body inside a container,
89
135
  // then pushState()'s the loaded URL.
@@ -104,7 +150,7 @@ function handleClick(event, container, options) {
104
150
  // console.log( xhr.readyState )
105
151
  //
106
152
  // Returns whatever $.ajax returns.
107
- var pjax = $.pjax = function( options ) {
153
+ function pjax(options) {
108
154
  options = $.extend(true, {}, $.ajaxSettings, pjax.defaults, options)
109
155
 
110
156
  if ($.isFunction(options.url)) {
@@ -113,18 +159,8 @@ var pjax = $.pjax = function( options ) {
113
159
 
114
160
  var target = options.target
115
161
 
116
- // DEPRECATED: use options.target
117
- if (!target && options.clickedElement) target = options.clickedElement[0]
118
-
119
162
  var hash = parseURL(options.url).hash
120
163
 
121
- // DEPRECATED: Save references to original event callbacks. However,
122
- // listening for custom pjax:* events is prefered.
123
- var oldBeforeSend = options.beforeSend,
124
- oldComplete = options.complete,
125
- oldSuccess = options.success,
126
- oldError = options.error
127
-
128
164
  var context = options.context = findContainerFor(options.container)
129
165
 
130
166
  // We want the browser to maintain two separate internal caches: one
@@ -143,13 +179,9 @@ var pjax = $.pjax = function( options ) {
143
179
  var timeoutTimer
144
180
 
145
181
  options.beforeSend = function(xhr, settings) {
146
- if (settings.timeout > 0) {
147
- timeoutTimer = setTimeout(function() {
148
- if (fire('pjax:timeout', [xhr, options]))
149
- xhr.abort('timeout')
150
- }, settings.timeout)
151
-
152
- // Clear timeout setting so jquerys internal timeout isn't invoked
182
+ // No timeout for non-GET requests
183
+ // Its not safe to request the resource again with a fallback method.
184
+ if (settings.type !== 'GET') {
153
185
  settings.timeout = 0
154
186
  }
155
187
 
@@ -158,68 +190,67 @@ var pjax = $.pjax = function( options ) {
158
190
 
159
191
  var result
160
192
 
161
- // DEPRECATED: Invoke original `beforeSend` handler
162
- if (oldBeforeSend) {
163
- result = oldBeforeSend.apply(this, arguments)
164
- if (result === false) return false
165
- }
193
+ if (!fire('pjax:beforeSend', [xhr, settings]))
194
+ return false
195
+
196
+ if (settings.timeout > 0) {
197
+ timeoutTimer = setTimeout(function() {
198
+ if (fire('pjax:timeout', [xhr, options]))
199
+ xhr.abort('timeout')
200
+ }, settings.timeout)
166
201
 
167
- if (!fire('pjax:beforeSend', [xhr, settings])) return false
202
+ // Clear timeout setting so jquerys internal timeout isn't invoked
203
+ settings.timeout = 0
204
+ }
168
205
 
169
- fire('pjax:start', [xhr, options])
170
- // start.pjax is deprecated
171
- fire('start.pjax', [xhr, options])
206
+ options.requestUrl = parseURL(settings.url).href
172
207
  }
173
208
 
174
209
  options.complete = function(xhr, textStatus) {
175
210
  if (timeoutTimer)
176
211
  clearTimeout(timeoutTimer)
177
212
 
178
- // DEPRECATED: Invoke original `complete` handler
179
- if (oldComplete) oldComplete.apply(this, arguments)
180
-
181
213
  fire('pjax:complete', [xhr, textStatus, options])
182
214
 
183
215
  fire('pjax:end', [xhr, options])
184
- // end.pjax is deprecated
185
- fire('end.pjax', [xhr, options])
186
216
  }
187
217
 
188
218
  options.error = function(xhr, textStatus, errorThrown) {
189
219
  var container = extractContainer("", xhr, options)
190
220
 
191
- // DEPRECATED: Invoke original `error` handler
192
- if (oldError) oldError.apply(this, arguments)
193
-
194
221
  var allowed = fire('pjax:error', [xhr, textStatus, errorThrown, options])
195
- if (textStatus !== 'abort' && allowed)
196
- window.location = container.url
222
+ if (options.type == 'GET' && textStatus !== 'abort' && allowed) {
223
+ locationReplace(container.url)
224
+ }
197
225
  }
198
226
 
199
227
  options.success = function(data, status, xhr) {
200
228
  var container = extractContainer(data, xhr, options)
201
229
 
202
230
  if (!container.contents) {
203
- window.location = container.url
231
+ locationReplace(container.url)
204
232
  return
205
233
  }
206
234
 
207
235
  pjax.state = {
208
236
  id: options.id || uniqueId(),
209
237
  url: container.url,
238
+ title: container.title,
210
239
  container: context.selector,
211
240
  fragment: options.fragment,
212
241
  timeout: options.timeout
213
242
  }
214
243
 
244
+ if (options.push || options.replace) {
245
+ window.history.replaceState(pjax.state, container.title, container.url)
246
+ }
247
+
215
248
  if (container.title) document.title = container.title
216
249
  context.html(container.contents)
217
250
 
218
- if ( options.replace ) {
219
- window.history.replaceState(pjax.state, container.title, container.url)
220
- } else if ( options.push ) {
221
- window.history.pushState(pjax.state, container.title, container.url)
222
- }
251
+ // Scroll to top by default
252
+ if (typeof options.scrollTo === 'number')
253
+ $(window).scrollTop(options.scrollTo)
223
254
 
224
255
  // Google Analytics support
225
256
  if ( (options.replace || options.push) && window._gaq )
@@ -228,12 +259,21 @@ var pjax = $.pjax = function( options ) {
228
259
  // If the URL has a hash in it, make sure the browser
229
260
  // knows to navigate to the hash.
230
261
  if ( hash !== '' ) {
231
- window.location.href = hash
262
+ // Avoid using simple hash set here. Will add another history
263
+ // entry. Replace the url with replaceState and scroll to target
264
+ // by hand.
265
+ //
266
+ // window.location.hash = hash
267
+ var url = parseURL(container.url)
268
+ url.hash = hash
269
+
270
+ pjax.state.url = url.href
271
+ window.history.replaceState(pjax.state, container.title, url.href)
272
+
273
+ var target = $(url.hash)
274
+ if (target.length) $(window).scrollTop(target.offset().top)
232
275
  }
233
276
 
234
- // DEPRECATED: Invoke original `success` handler
235
- if (oldSuccess) oldSuccess.apply(this, arguments)
236
-
237
277
  fire('pjax:success', [data, status, xhr, options])
238
278
  }
239
279
 
@@ -246,6 +286,7 @@ var pjax = $.pjax = function( options ) {
246
286
  pjax.state = {
247
287
  id: uniqueId(),
248
288
  url: window.location.href,
289
+ title: document.title,
249
290
  container: context.selector,
250
291
  fragment: options.fragment,
251
292
  timeout: options.timeout
@@ -261,12 +302,148 @@ var pjax = $.pjax = function( options ) {
261
302
  }
262
303
 
263
304
  pjax.options = options
264
- pjax.xhr = $.ajax(options)
265
- $(document).trigger('pjax', [pjax.xhr, options])
305
+ var xhr = pjax.xhr = $.ajax(options)
306
+
307
+ if (xhr.readyState > 0) {
308
+ if (options.push && !options.replace) {
309
+ // Cache current container element before replacing it
310
+ cachePush(pjax.state.id, context.clone().contents())
311
+
312
+ window.history.pushState(null, "", stripPjaxParam(options.requestUrl))
313
+ }
314
+
315
+ fire('pjax:start', [xhr, options])
316
+ fire('pjax:send', [xhr, options])
317
+ }
266
318
 
267
319
  return pjax.xhr
268
320
  }
269
321
 
322
+ // Public: Reload current page with pjax.
323
+ //
324
+ // Returns whatever $.pjax returns.
325
+ function pjaxReload(container, options) {
326
+ var defaults = {
327
+ url: window.location.href,
328
+ push: false,
329
+ replace: true,
330
+ scrollTo: false
331
+ }
332
+
333
+ return pjax($.extend(defaults, optionsFor(container, options)))
334
+ }
335
+
336
+ // Internal: Hard replace current state with url.
337
+ //
338
+ // Work for around WebKit
339
+ // https://bugs.webkit.org/show_bug.cgi?id=93506
340
+ //
341
+ // Returns nothing.
342
+ function locationReplace(url) {
343
+ window.history.replaceState(null, "", "#")
344
+ window.location.replace(url)
345
+ }
346
+
347
+ // popstate handler takes care of the back and forward buttons
348
+ //
349
+ // You probably shouldn't use pjax on pages with other pushState
350
+ // stuff yet.
351
+ function onPjaxPopstate(event) {
352
+ var state = event.state
353
+
354
+ if (state && state.container) {
355
+ var container = $(state.container)
356
+ if (container.length) {
357
+ var contents = cacheMapping[state.id]
358
+
359
+ if (pjax.state) {
360
+ // Since state ids always increase, we can deduce the history
361
+ // direction from the previous state.
362
+ var direction = pjax.state.id < state.id ? 'forward' : 'back'
363
+
364
+ // Cache current container before replacement and inform the
365
+ // cache which direction the history shifted.
366
+ cachePop(direction, pjax.state.id, container.clone().contents())
367
+ } else {
368
+ // Page was reloaded but we have an existing history entry.
369
+ // Set it to our initial state.
370
+ pjax.state = state;
371
+ return;
372
+ }
373
+
374
+ var popstateEvent = $.Event('pjax:popstate', {
375
+ state: state,
376
+ direction: direction
377
+ })
378
+ container.trigger(popstateEvent)
379
+
380
+ var options = {
381
+ id: state.id,
382
+ url: state.url,
383
+ container: container,
384
+ push: false,
385
+ fragment: state.fragment,
386
+ timeout: state.timeout,
387
+ scrollTo: false
388
+ }
389
+
390
+ if (contents) {
391
+ container.trigger('pjax:start', [null, options])
392
+
393
+ if (state.title) document.title = state.title
394
+ container.html(contents)
395
+ pjax.state = state
396
+
397
+ container.trigger('pjax:end', [null, options])
398
+ } else {
399
+ pjax(options)
400
+ }
401
+
402
+ // Force reflow/relayout before the browser tries to restore the
403
+ // scroll position.
404
+ container[0].offsetHeight
405
+ } else {
406
+ locationReplace(location.href)
407
+ }
408
+ }
409
+ }
410
+
411
+ // Fallback version of main pjax function for browsers that don't
412
+ // support pushState.
413
+ //
414
+ // Returns nothing since it retriggers a hard form submission.
415
+ function fallbackPjax(options) {
416
+ var url = $.isFunction(options.url) ? options.url() : options.url,
417
+ method = options.type ? options.type.toUpperCase() : 'GET'
418
+
419
+ var form = $('<form>', {
420
+ method: method === 'GET' ? 'GET' : 'POST',
421
+ action: url,
422
+ style: 'display:none'
423
+ })
424
+
425
+ if (method !== 'GET' && method !== 'POST') {
426
+ form.append($('<input>', {
427
+ type: 'hidden',
428
+ name: '_method',
429
+ value: method.toLowerCase()
430
+ }))
431
+ }
432
+
433
+ var data = options.data
434
+ if (typeof data === 'string') {
435
+ $.each(data.split('&'), function(index, value) {
436
+ var pair = value.split('=')
437
+ form.append($('<input>', {type: 'hidden', name: pair[0], value: pair[1]}))
438
+ })
439
+ } else if (typeof data === 'object') {
440
+ for (key in data)
441
+ form.append($('<input>', {type: 'hidden', name: key, value: data[key]}))
442
+ }
443
+
444
+ $(document.body).append(form)
445
+ form.submit()
446
+ }
270
447
 
271
448
  // Internal: Generate unique id for state object.
272
449
  //
@@ -370,13 +547,7 @@ function findContainerFor(container) {
370
547
  //
371
548
  // Returns a jQuery object.
372
549
  function findAll(elems, selector) {
373
- var results = $()
374
- elems.each(function() {
375
- if ($(this).is(selector))
376
- results = results.add(this)
377
- results = results.add(selector, this)
378
- })
379
- return results
550
+ return elems.filter(selector).add(elems.find(selector));
380
551
  }
381
552
 
382
553
  // Internal: Extracts container and metadata from response.
@@ -395,23 +566,32 @@ function extractContainer(data, xhr, options) {
395
566
 
396
567
  // Prefer X-PJAX-URL header if it was set, otherwise fallback to
397
568
  // using the original requested url.
398
- obj.url = stripPjaxParam(xhr.getResponseHeader('X-PJAX-URL') || options.url)
569
+ obj.url = stripPjaxParam(xhr.getResponseHeader('X-PJAX-URL') || options.requestUrl)
399
570
 
400
571
  // Attempt to parse response html into elements
401
- var $data = $(data)
572
+ if (/<html/i.test(data)) {
573
+ var $head = $(data.match(/<head[^>]*>([\s\S.]*)<\/head>/i)[0])
574
+ var $body = $(data.match(/<body[^>]*>([\s\S.]*)<\/body>/i)[0])
575
+ } else {
576
+ var $head = $body = $(data)
577
+ }
402
578
 
403
579
  // If response data is empty, return fast
404
- if ($data.length === 0)
580
+ if ($body.length === 0)
405
581
  return obj
406
582
 
407
- // If there's a <title> tag in the response, use it as
583
+ // If there's a <title> tag in the header, use it as
408
584
  // the page's title.
409
- obj.title = findAll($data, 'title').last().text()
585
+ obj.title = findAll($head, 'title').last().text()
410
586
 
411
587
  if (options.fragment) {
412
588
  // If they specified a fragment, look for it in the response
413
589
  // and pull it out.
414
- var $fragment = findAll($data, options.fragment).first()
590
+ if (options.fragment === 'body') {
591
+ var $fragment = $body
592
+ } else {
593
+ var $fragment = findAll($body, options.fragment).first()
594
+ }
415
595
 
416
596
  if ($fragment.length) {
417
597
  obj.contents = $fragment.contents()
@@ -423,7 +603,7 @@ function extractContainer(data, xhr, options) {
423
603
  }
424
604
 
425
605
  } else if (!/<html/i.test(data)) {
426
- obj.contents = $data
606
+ obj.contents = $body
427
607
  }
428
608
 
429
609
  // Clean up any <title> tags
@@ -441,52 +621,110 @@ function extractContainer(data, xhr, options) {
441
621
  return obj
442
622
  }
443
623
 
624
+ // Internal: History DOM caching class.
625
+ var cacheMapping = {}
626
+ var cacheForwardStack = []
627
+ var cacheBackStack = []
444
628
 
445
- pjax.defaults = {
446
- timeout: 650,
447
- push: true,
448
- replace: false,
449
- type: 'GET',
450
- dataType: 'html'
451
- }
629
+ // Push previous state id and container contents into the history
630
+ // cache. Should be called in conjunction with `pushState` to save the
631
+ // previous container contents.
632
+ //
633
+ // id - State ID Number
634
+ // value - DOM Element to cache
635
+ //
636
+ // Returns nothing.
637
+ function cachePush(id, value) {
638
+ cacheMapping[id] = value
639
+ cacheBackStack.push(id)
640
+
641
+ // Remove all entires in forward history stack after pushing
642
+ // a new page.
643
+ while (cacheForwardStack.length)
644
+ delete cacheMapping[cacheForwardStack.shift()]
452
645
 
453
- // Export $.pjax.click
454
- pjax.click = handleClick
646
+ // Trim back history stack to max cache length.
647
+ while (cacheBackStack.length > pjax.defaults.maxCacheLength)
648
+ delete cacheMapping[cacheBackStack.shift()]
649
+ }
455
650
 
651
+ // Shifts cache from directional history cache. Should be
652
+ // called on `popstate` with the previous state id and container
653
+ // contents.
654
+ //
655
+ // direction - "forward" or "back" String
656
+ // id - State ID Number
657
+ // value - DOM Element to cache
658
+ //
659
+ // Returns nothing.
660
+ function cachePop(direction, id, value) {
661
+ var pushStack, popStack
662
+ cacheMapping[id] = value
456
663
 
457
- // Used to detect initial (useless) popstate.
458
- // If history.state exists, assume browser isn't going to fire initial popstate.
459
- var popped = ('state' in window.history), initialURL = location.href
664
+ if (direction === 'forward') {
665
+ pushStack = cacheBackStack
666
+ popStack = cacheForwardStack
667
+ } else {
668
+ pushStack = cacheForwardStack
669
+ popStack = cacheBackStack
670
+ }
460
671
 
672
+ pushStack.push(id)
673
+ if (id = popStack.pop())
674
+ delete cacheMapping[id]
675
+ }
461
676
 
462
- // popstate handler takes care of the back and forward buttons
677
+ // Install pjax functions on $.pjax to enable pushState behavior.
463
678
  //
464
- // You probably shouldn't use pjax on pages with other pushState
465
- // stuff yet.
466
- $(window).bind('popstate', function(event){
467
- // Ignore inital popstate that some browsers fire on page load
468
- var initialPop = !popped && location.href == initialURL
469
- popped = true
470
- if ( initialPop ) return
679
+ // Does nothing if already enabled.
680
+ //
681
+ // Examples
682
+ //
683
+ // $.pjax.enable()
684
+ //
685
+ // Returns nothing.
686
+ function enable() {
687
+ $.fn.pjax = fnPjax
688
+ $.pjax = pjax
689
+ $.pjax.enable = $.noop
690
+ $.pjax.disable = disable
691
+ $.pjax.click = handleClick
692
+ $.pjax.submit = handleSubmit
693
+ $.pjax.reload = pjaxReload
694
+ $.pjax.defaults = {
695
+ timeout: 650,
696
+ push: true,
697
+ replace: false,
698
+ type: 'GET',
699
+ dataType: 'html',
700
+ scrollTo: 0,
701
+ maxCacheLength: 20
702
+ }
703
+ $(window).bind('popstate.pjax', onPjaxPopstate)
704
+ }
471
705
 
472
- var state = event.state
706
+ // Disable pushState behavior.
707
+ //
708
+ // This is the case when a browser doesn't support pushState. It is
709
+ // sometimes useful to disable pushState for debugging on a modern
710
+ // browser.
711
+ //
712
+ // Examples
713
+ //
714
+ // $.pjax.disable()
715
+ //
716
+ // Returns nothing.
717
+ function disable() {
718
+ $.fn.pjax = function() { return this }
719
+ $.pjax = fallbackPjax
720
+ $.pjax.enable = enable
721
+ $.pjax.disable = $.noop
722
+ $.pjax.click = $.noop
723
+ $.pjax.submit = $.noop
724
+ $.pjax.reload = function() { window.location.reload() }
473
725
 
474
- if (state && state.container) {
475
- var container = $(state.container)
476
- if (container.length) {
477
- $.pjax({
478
- id: state.id,
479
- url: state.url,
480
- container: container,
481
- push: false,
482
- fragment: state.fragment,
483
- timeout: state.timeout
484
- })
485
- } else {
486
- window.location = location.href
487
- }
488
- }
489
- })
726
+ $(window).unbind('popstate.pjax', onPjaxPopstate)
727
+ }
490
728
 
491
729
 
492
730
  // Add the state property to jQuery's event object so we can use it in
@@ -494,50 +732,12 @@ $(window).bind('popstate', function(event){
494
732
  if ( $.inArray('state', $.event.props) < 0 )
495
733
  $.event.props.push('state')
496
734
 
497
-
498
- // Is pjax supported by this browser?
735
+ // Is pjax supported by this browser?
499
736
  $.support.pjax =
500
- window.history && window.history.pushState && window.history.replaceState
737
+ window.history && window.history.pushState && window.history.replaceState &&
501
738
  // pushState isn't reliable on iOS until 5.
502
- && !navigator.userAgent.match(/((iPod|iPhone|iPad).+\bOS\s+[1-4]|WebApps\/.+CFNetwork)/)
503
-
504
-
505
- // Fall back to normalcy for older browsers.
506
- if ( !$.support.pjax ) {
507
- $.pjax = function( options ) {
508
- var url = $.isFunction(options.url) ? options.url() : options.url,
509
- method = options.type ? options.type.toUpperCase() : 'GET'
510
-
511
- var form = $('<form>', {
512
- method: method === 'GET' ? 'GET' : 'POST',
513
- action: url,
514
- style: 'display:none'
515
- })
516
-
517
- if (method !== 'GET' && method !== 'POST') {
518
- form.append($('<input>', {
519
- type: 'hidden',
520
- name: '_method',
521
- value: method.toLowerCase()
522
- }))
523
- }
524
-
525
- var data = options.data
526
- if (typeof data === 'string') {
527
- $.each(data.split('&'), function(index, value) {
528
- var pair = value.split('=')
529
- form.append($('<input>', {type: 'hidden', name: pair[0], value: pair[1]}))
530
- })
531
- } else if (typeof data === 'object') {
532
- for (key in data)
533
- form.append($('<input>', {type: 'hidden', name: key, value: data[key]}))
534
- }
739
+ !navigator.userAgent.match(/((iPod|iPhone|iPad).+\bOS\s+[1-4]|WebApps\/.+CFNetwork)/)
535
740
 
536
- $(document.body).append(form)
537
- form.submit()
538
- }
539
- $.pjax.click = $.noop
540
- $.fn.pjax = function() { return this }
541
- }
741
+ $.support.pjax ? enable() : disable()
542
742
 
543
- })(jQuery);
743
+ })(jQuery);