Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

update pjax lib [ci skip]

  • Loading branch information...
commit 468a146dbdf6ffe2bdfcd5c144337aeafea09e4a 1 parent 348cb55
@bbenezech bbenezech authored
Showing with 154 additions and 81 deletions.
  1. +154 −81 app/assets/javascripts/rails_admin/jquery.pjax.js
View
235 app/assets/javascripts/rails_admin/jquery.pjax.js
@@ -84,29 +84,6 @@ function handleClick(event, container, options) {
return false
}
-// Internal: Strips _pjax param from url
-//
-// url - String
-//
-// Returns String.
-function stripPjaxParam(url) {
- return url
- .replace(/\?_pjax=[^&]+&?/, '?')
- .replace(/_pjax=[^&]+&?/, '')
- .replace(/[\?&]$/, '')
-}
-
-// Internal: Parse URL components and returns a Locationish object.
-//
-// url - String URL
-//
-// Returns HTMLAnchorElement that acts like Location.
-function parseURL(url) {
- var a = document.createElement('a')
- a.href = url
- return a
-}
-
// Loads a URL with ajax, puts the response body inside a container,
// then pushState()'s the loaded URL.
@@ -139,8 +116,7 @@ var pjax = $.pjax = function( options ) {
// DEPRECATED: use options.target
if (!target && options.clickedElement) target = options.clickedElement[0]
- var url = options.url
- var hash = parseURL(url).hash
+ var hash = parseURL(options.url).hash
// DEPRECATED: Save references to original event callbacks. However,
// listening for custom pjax:* events is prefered.
@@ -167,8 +143,6 @@ var pjax = $.pjax = function( options ) {
var timeoutTimer
options.beforeSend = function(xhr, settings) {
- url = stripPjaxParam(settings.url)
-
if (settings.timeout > 0) {
timeoutTimer = setTimeout(function() {
if (fire('pjax:timeout', [xhr, options]))
@@ -212,71 +186,39 @@ var pjax = $.pjax = function( options ) {
}
options.error = function(xhr, textStatus, errorThrown) {
- var respUrl = xhr.getResponseHeader('X-PJAX-URL')
- if (respUrl) url = stripPjaxParam(respUrl)
+ var container = extractContainer("", xhr, options)
// DEPRECATED: Invoke original `error` handler
if (oldError) oldError.apply(this, arguments)
var allowed = fire('pjax:error', [xhr, textStatus, errorThrown, options])
if (textStatus !== 'abort' && allowed)
- window.location = url
+ window.location = container.url
}
options.success = function(data, status, xhr) {
- var respUrl = xhr.getResponseHeader('X-PJAX-URL')
- if (respUrl) url = stripPjaxParam(respUrl)
-
- var title, oldTitle = document.title
-
- if ( options.fragment ) {
- // If they specified a fragment, look for it in the response
- // and pull it out.
- var html = $('<html>').html(data)
- var $fragment = html.find(options.fragment)
- if ( $fragment.length ) {
- this.html($fragment.contents())
-
- // If there's a <title> tag in the response, use it as
- // the page's title. Otherwise, look for data-title and title attributes.
- title = html.find('title').text() || $fragment.attr('title') || $fragment.data('title')
- } else {
- return window.location = url
- }
- } else {
- // If we got no data or an entire web page, go directly
- // to the page and let normal error handling happen.
- if ( !$.trim(data) || /<html/i.test(data) )
- return window.location = url
-
- this.html(data)
+ var container = extractContainer(data, xhr, options)
- // If there's a <title> tag in the response, use it as
- // the page's title.
- title = this.find('title').remove().text()
+ if (!container.contents) {
+ window.location = container.url
+ return
}
- if ( title ) document.title = $.trim(title)
-
- var state = {
- url: url,
- pjax: this.selector,
+ pjax.state = {
+ id: options.id || uniqueId(),
+ url: container.url,
+ container: context.selector,
fragment: options.fragment,
timeout: options.timeout
}
+ if (container.title) document.title = container.title
+ context.html(container.contents)
+
if ( options.replace ) {
- pjax.active = true
- window.history.replaceState(state, document.title, url)
+ window.history.replaceState(pjax.state, container.title, container.url)
} else if ( options.push ) {
- // this extra replaceState before first push ensures good back
- // button behavior
- if ( !pjax.active ) {
- window.history.replaceState($.extend({}, state, {url:null}), oldTitle)
- pjax.active = true
- }
-
- window.history.pushState(state, document.title, url)
+ window.history.pushState(pjax.state, container.title, container.url)
}
// Google Analytics support
@@ -296,6 +238,21 @@ var pjax = $.pjax = function( options ) {
}
+ // Initialize pjax.state for the initial page load. Assume we're
+ // using the container and options of the link we're loading for the
+ // back button to the initial page. This ensures good back button
+ // behavior.
+ if (!pjax.state) {
+ pjax.state = {
+ id: uniqueId(),
+ url: window.location.href,
+ container: context.selector,
+ fragment: options.fragment,
+ timeout: options.timeout
+ }
+ window.history.replaceState(pjax.state, document.title)
+ }
+
// Cancel the current request if we're already pjaxing
var xhr = pjax.xhr
if ( xhr && xhr.readyState < 4) {
@@ -311,6 +268,39 @@ var pjax = $.pjax = function( options ) {
}
+// Internal: Generate unique id for state object.
+//
+// Use a timestamp instead of a counter since ids should still be
+// unique across page loads.
+//
+// Returns Number.
+function uniqueId() {
+ return (new Date).getTime()
+}
+
+// Internal: Strips _pjax param from url
+//
+// url - String
+//
+// Returns String.
+function stripPjaxParam(url) {
+ return url
+ .replace(/\?_pjax=[^&]+&?/, '?')
+ .replace(/_pjax=[^&]+&?/, '')
+ .replace(/[\?&]$/, '')
+}
+
+// Internal: Parse URL components and returns a Locationish object.
+//
+// url - String URL
+//
+// Returns HTMLAnchorElement that acts like Location.
+function parseURL(url) {
+ var a = document.createElement('a')
+ a.href = url
+ return a
+}
+
// Internal: Build options Object for arguments.
//
// For convenience the first parameter can be either the container or
@@ -370,6 +360,87 @@ function findContainerFor(container) {
}
}
+// Internal: Filter and find all elements matching the selector.
+//
+// Where $.fn.find only matches descendants, findAll will test all the
+// top level elements in the jQuery object as well.
+//
+// elems - jQuery object of Elements
+// selector - String selector to match
+//
+// Returns a jQuery object.
+function findAll(elems, selector) {
+ var results = $()
+ elems.each(function() {
+ if ($(this).is(selector))
+ results = results.add(this)
+ results = results.add(selector, this)
+ })
+ return results
+}
+
+// Internal: Extracts container and metadata from response.
+//
+// 1. Extracts X-PJAX-URL header if set
+// 2. Extracts inline <title> tags
+// 3. Builds response Element and extracts fragment if set
+//
+// data - String response data
+// xhr - XHR response
+// options - pjax options Object
+//
+// Returns an Object with url, title, and contents keys.
+function extractContainer(data, xhr, options) {
+ var obj = {}
+
+ // Prefer X-PJAX-URL header if it was set, otherwise fallback to
+ // using the original requested url.
+ obj.url = stripPjaxParam(xhr.getResponseHeader('X-PJAX-URL') || options.url)
+
+ // Attempt to parse response html into elements
+ var $data = $(data)
+
+ // If response data is empty, return fast
+ if ($data.length === 0)
+ return obj
+
+ // If there's a <title> tag in the response, use it as
+ // the page's title.
+ obj.title = findAll($data, 'title').last().text()
+
+ if (options.fragment) {
+ // If they specified a fragment, look for it in the response
+ // and pull it out.
+ var $fragment = findAll($data, options.fragment).first()
+
+ if ($fragment.length) {
+ obj.contents = $fragment.contents()
+
+ // If there's no title, look for data-title and title attributes
+ // on the fragment
+ if (!obj.title)
+ obj.title = $fragment.attr('title') || $fragment.data('title')
+ }
+
+ } else if (!/<html/i.test(data)) {
+ obj.contents = $data
+ }
+
+ // Clean up any <title> tags
+ if (obj.contents) {
+ // Remove any parent title elements
+ obj.contents = obj.contents.not('title')
+
+ // Then scrub any titles from their descendents
+ obj.contents.find('title').remove()
+ }
+
+ // Trim any whitespace off the title
+ if (obj.title) obj.title = $.trim(obj.title)
+
+ return obj
+}
+
pjax.defaults = {
timeout: 650,
@@ -400,18 +471,20 @@ $(window).bind('popstate', function(event){
var state = event.state
- if ( state && state.pjax ) {
- var container = state.pjax
- if ( $(container+'').length )
+ if (state && state.container) {
+ var container = $(state.container)
+ if (container.length) {
$.pjax({
- url: state.url || location.href,
- fragment: state.fragment,
+ id: state.id,
+ url: state.url,
container: container,
push: false,
+ fragment: state.fragment,
timeout: state.timeout
})
- else
+ } else {
window.location = location.href
+ }
}
})
@@ -467,4 +540,4 @@ if ( !$.support.pjax ) {
$.fn.pjax = function() { return this }
}
-})(jQuery);
+})(jQuery);
Please sign in to comment.
Something went wrong with that request. Please try again.