Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with HTTPS or Subversion.

Download ZIP

Loading…

Update jquery.pjax to version 1.8.0 #2797

Merged
merged 3 commits into from

2 participants

@tengyifei

Library downloaded from original Github repository
Source: https://codeload.github.com/defunkt/jquery-pjax/zip/v1.8.0
Watch: 414
Star: 8553
Fork: 871

@petecooper

Thanks, @tengyifei - all good. Merging and closing.

@petecooper petecooper merged commit 9827009 into cdnjs:master
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment
Commits on Mar 10, 2014
  1. @tengyifei

    Update pjax to 1.8.0

    tengyifei authored
  2. @tengyifei

    Update pjax to 1.8.0

    tengyifei authored
  3. @tengyifei

    Update pjax to 1.8.0

    tengyifei authored
This page is out of date. Refresh to see the latest.
View
839 ajax/libs/jquery.pjax/1.8.0/jquery.pjax.js
@@ -0,0 +1,839 @@
+// jquery.pjax.js
+// copyright chris wanstrath
+// https://github.com/defunkt/jquery-pjax
+
+(function($){
+
+// When called on a container with a selector, fetches the href with
+// ajax into the container or with the data-pjax attribute on the link
+// itself.
+//
+// Tries to make sure the back button and ctrl+click work the way
+// you'd expect.
+//
+// Exported as $.fn.pjax
+//
+// Accepts a jQuery ajax options object that may include these
+// pjax specific options:
+//
+//
+// container - Where to stick the response body. Usually a String selector.
+// $(container).html(xhr.responseBody)
+// (default: current jquery context)
+// push - Whether to pushState the URL. Defaults to true (of course).
+// replace - Want to use replaceState instead? That's cool.
+//
+// For convenience the second parameter can be either the container or
+// the options object.
+//
+// Returns the jQuery object
+function fnPjax(selector, container, options) {
+ var context = this
+ return this.on('click.pjax', selector, function(event) {
+ var opts = $.extend({}, optionsFor(container, options))
+ if (!opts.container)
+ opts.container = $(this).attr('data-pjax') || context
+ handleClick(event, opts)
+ })
+}
+
+// Public: pjax on click handler
+//
+// Exported as $.pjax.click.
+//
+// event - "click" jQuery.Event
+// options - pjax options
+//
+// Examples
+//
+// $(document).on('click', 'a', $.pjax.click)
+// // is the same as
+// $(document).pjax('a')
+//
+// $(document).on('click', 'a', function(event) {
+// var container = $(this).closest('[data-pjax-container]')
+// $.pjax.click(event, container)
+// })
+//
+// Returns nothing.
+function handleClick(event, container, options) {
+ options = optionsFor(container, options)
+
+ var link = event.currentTarget
+
+ if (link.tagName.toUpperCase() !== 'A')
+ throw "$.fn.pjax or $.pjax.click requires an anchor element"
+
+ // Middle click, cmd click, and ctrl click should open
+ // links in a new tab as normal.
+ if ( event.which > 1 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey )
+ return
+
+ // Ignore cross origin links
+ if ( location.protocol !== link.protocol || location.hostname !== link.hostname )
+ return
+
+ // Ignore anchors on the same page
+ if (link.hash && link.href.replace(link.hash, '') ===
+ location.href.replace(location.hash, ''))
+ return
+
+ // Ignore empty anchor "foo.html#"
+ if (link.href === location.href + '#')
+ return
+
+ var defaults = {
+ url: link.href,
+ container: $(link).attr('data-pjax'),
+ target: link
+ }
+
+ var opts = $.extend({}, defaults, options)
+ var clickEvent = $.Event('pjax:click')
+ $(link).trigger(clickEvent, [opts])
+
+ if (!clickEvent.isDefaultPrevented()) {
+ pjax(opts)
+ event.preventDefault()
+ $(link).trigger('pjax:clicked', [opts])
+ }
+}
+
+// Public: pjax on form submit handler
+//
+// Exported as $.pjax.submit
+//
+// event - "click" jQuery.Event
+// options - pjax options
+//
+// Examples
+//
+// $(document).on('submit', 'form', function(event) {
+// var container = $(this).closest('[data-pjax-container]')
+// $.pjax.submit(event, container)
+// })
+//
+// Returns nothing.
+function handleSubmit(event, container, options) {
+ options = optionsFor(container, options)
+
+ var form = event.currentTarget
+
+ if (form.tagName.toUpperCase() !== 'FORM')
+ throw "$.pjax.submit requires a form element"
+
+ var defaults = {
+ type: form.method.toUpperCase(),
+ url: form.action,
+ data: $(form).serializeArray(),
+ container: $(form).attr('data-pjax'),
+ target: form
+ }
+
+ pjax($.extend({}, defaults, options))
+
+ event.preventDefault()
+}
+
+// Loads a URL with ajax, puts the response body inside a container,
+// then pushState()'s the loaded URL.
+//
+// Works just like $.ajax in that it accepts a jQuery ajax
+// settings object (with keys like url, type, data, etc).
+//
+// Accepts these extra keys:
+//
+// container - Where to stick the response body.
+// $(container).html(xhr.responseBody)
+// push - Whether to pushState the URL. Defaults to true (of course).
+// replace - Want to use replaceState instead? That's cool.
+//
+// Use it just like $.ajax:
+//
+// var xhr = $.pjax({ url: this.href, container: '#main' })
+// console.log( xhr.readyState )
+//
+// Returns whatever $.ajax returns.
+function pjax(options) {
+ options = $.extend(true, {}, $.ajaxSettings, pjax.defaults, options)
+
+ if ($.isFunction(options.url)) {
+ options.url = options.url()
+ }
+
+ var target = options.target
+
+ var hash = parseURL(options.url).hash
+
+ var context = options.context = findContainerFor(options.container)
+
+ // We want the browser to maintain two separate internal caches: one
+ // for pjax'd partial page loads and one for normal page loads.
+ // Without adding this secret parameter, some browsers will often
+ // confuse the two.
+ if (!options.data) options.data = {}
+ options.data._pjax = context.selector
+
+ function fire(type, args) {
+ var event = $.Event(type, { relatedTarget: target })
+ context.trigger(event, args)
+ return !event.isDefaultPrevented()
+ }
+
+ var timeoutTimer
+
+ options.beforeSend = function(xhr, settings) {
+ // No timeout for non-GET requests
+ // Its not safe to request the resource again with a fallback method.
+ if (settings.type !== 'GET') {
+ settings.timeout = 0
+ }
+
+ xhr.setRequestHeader('X-PJAX', 'true')
+ xhr.setRequestHeader('X-PJAX-Container', context.selector)
+
+ if (!fire('pjax:beforeSend', [xhr, settings]))
+ return false
+
+ if (settings.timeout > 0) {
+ timeoutTimer = setTimeout(function() {
+ if (fire('pjax:timeout', [xhr, options]))
+ xhr.abort('timeout')
+ }, settings.timeout)
+
+ // Clear timeout setting so jquerys internal timeout isn't invoked
+ settings.timeout = 0
+ }
+
+ options.requestUrl = parseURL(settings.url).href
+ }
+
+ options.complete = function(xhr, textStatus) {
+ if (timeoutTimer)
+ clearTimeout(timeoutTimer)
+
+ fire('pjax:complete', [xhr, textStatus, options])
+
+ fire('pjax:end', [xhr, options])
+ }
+
+ options.error = function(xhr, textStatus, errorThrown) {
+ var container = extractContainer("", xhr, options)
+
+ var allowed = fire('pjax:error', [xhr, textStatus, errorThrown, options])
+ if (options.type == 'GET' && textStatus !== 'abort' && allowed) {
+ locationReplace(container.url)
+ }
+ }
+
+ options.success = function(data, status, xhr) {
+ // If $.pjax.defaults.version is a function, invoke it first.
+ // Otherwise it can be a static string.
+ var currentVersion = (typeof $.pjax.defaults.version === 'function') ?
+ $.pjax.defaults.version() :
+ $.pjax.defaults.version
+
+ var latestVersion = xhr.getResponseHeader('X-PJAX-Version')
+
+ var container = extractContainer(data, xhr, options)
+
+ // If there is a layout version mismatch, hard load the new url
+ if (currentVersion && latestVersion && currentVersion !== latestVersion) {
+ locationReplace(container.url)
+ return
+ }
+
+ // If the new response is missing a body, hard load the page
+ if (!container.contents) {
+ locationReplace(container.url)
+ return
+ }
+
+ pjax.state = {
+ id: options.id || uniqueId(),
+ url: container.url,
+ title: container.title,
+ container: context.selector,
+ fragment: options.fragment,
+ timeout: options.timeout
+ }
+
+ if (options.push || options.replace) {
+ window.history.replaceState(pjax.state, container.title, container.url)
+ }
+
+ // Clear out any focused controls before inserting new page contents.
+ document.activeElement.blur()
+
+ if (container.title) document.title = container.title
+ context.html(container.contents)
+
+ // FF bug: Won't autofocus fields that are inserted via JS.
+ // This behavior is incorrect. So if theres no current focus, autofocus
+ // the last field.
+ //
+ // http://www.w3.org/html/wg/drafts/html/master/forms.html
+ var autofocusEl = context.find('input[autofocus], textarea[autofocus]').last()[0]
+ if (autofocusEl && document.activeElement !== autofocusEl) {
+ autofocusEl.focus();
+ }
+
+ executeScriptTags(container.scripts)
+
+ // Scroll to top by default
+ if (typeof options.scrollTo === 'number')
+ $(window).scrollTop(options.scrollTo)
+
+ // If the URL has a hash in it, make sure the browser
+ // knows to navigate to the hash.
+ if ( hash !== '' ) {
+ // Avoid using simple hash set here. Will add another history
+ // entry. Replace the url with replaceState and scroll to target
+ // by hand.
+ //
+ // window.location.hash = hash
+ var url = parseURL(container.url)
+ url.hash = hash
+
+ pjax.state.url = url.href
+ window.history.replaceState(pjax.state, container.title, url.href)
+
+ var target = $(url.hash)
+ if (target.length) $(window).scrollTop(target.offset().top)
+ }
+
+ fire('pjax:success', [data, status, xhr, 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,
+ title: document.title,
+ 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) {
+ xhr.onreadystatechange = $.noop
+ xhr.abort()
+ }
+
+ pjax.options = options
+ var xhr = pjax.xhr = $.ajax(options)
+
+ if (xhr.readyState > 0) {
+ if (options.push && !options.replace) {
+ // Cache current container element before replacing it
+ cachePush(pjax.state.id, context.clone().contents())
+
+ window.history.pushState(null, "", stripPjaxParam(options.requestUrl))
+ }
+
+ fire('pjax:start', [xhr, options])
+ fire('pjax:send', [xhr, options])
+ }
+
+ return pjax.xhr
+}
+
+// Public: Reload current page with pjax.
+//
+// Returns whatever $.pjax returns.
+function pjaxReload(container, options) {
+ var defaults = {
+ url: window.location.href,
+ push: false,
+ replace: true,
+ scrollTo: false
+ }
+
+ return pjax($.extend(defaults, optionsFor(container, options)))
+}
+
+// Internal: Hard replace current state with url.
+//
+// Work for around WebKit
+// https://bugs.webkit.org/show_bug.cgi?id=93506
+//
+// Returns nothing.
+function locationReplace(url) {
+ window.history.replaceState(null, "", "#")
+ window.location.replace(url)
+}
+
+
+var initialPop = true
+var initialURL = window.location.href
+var initialState = window.history.state
+
+// Initialize $.pjax.state if possible
+// Happens when reloading a page and coming forward from a different
+// session history.
+if (initialState && initialState.container) {
+ pjax.state = initialState
+}
+
+// Non-webkit browsers don't fire an initial popstate event
+if ('state' in window.history) {
+ initialPop = false
+}
+
+// popstate handler takes care of the back and forward buttons
+//
+// You probably shouldn't use pjax on pages with other pushState
+// stuff yet.
+function onPjaxPopstate(event) {
+ var state = event.state
+
+ if (state && state.container) {
+ // When coming forward from a separate history session, will get an
+ // initial pop with a state we are already at. Skip reloading the current
+ // page.
+ if (initialPop && initialURL == state.url) return
+
+ // If popping back to the same state, just skip.
+ // Could be clicking back from hashchange rather than a pushState.
+ if (pjax.state.id === state.id) return
+
+ var container = $(state.container)
+ if (container.length) {
+ var direction, contents = cacheMapping[state.id]
+
+ if (pjax.state) {
+ // Since state ids always increase, we can deduce the history
+ // direction from the previous state.
+ direction = pjax.state.id < state.id ? 'forward' : 'back'
+
+ // Cache current container before replacement and inform the
+ // cache which direction the history shifted.
+ cachePop(direction, pjax.state.id, container.clone().contents())
+ }
+
+ var popstateEvent = $.Event('pjax:popstate', {
+ state: state,
+ direction: direction
+ })
+ container.trigger(popstateEvent)
+
+ var options = {
+ id: state.id,
+ url: state.url,
+ container: container,
+ push: false,
+ fragment: state.fragment,
+ timeout: state.timeout,
+ scrollTo: false
+ }
+
+ if (contents) {
+ container.trigger('pjax:start', [null, options])
+
+ if (state.title) document.title = state.title
+ container.html(contents)
+ pjax.state = state
+
+ container.trigger('pjax:end', [null, options])
+ } else {
+ pjax(options)
+ }
+
+ // Force reflow/relayout before the browser tries to restore the
+ // scroll position.
+ container[0].offsetHeight
+ } else {
+ locationReplace(location.href)
+ }
+ }
+ initialPop = false
+}
+
+// Fallback version of main pjax function for browsers that don't
+// support pushState.
+//
+// Returns nothing since it retriggers a hard form submission.
+function fallbackPjax(options) {
+ var url = $.isFunction(options.url) ? options.url() : options.url,
+ method = options.type ? options.type.toUpperCase() : 'GET'
+
+ var form = $('<form>', {
+ method: method === 'GET' ? 'GET' : 'POST',
+ action: url,
+ style: 'display:none'
+ })
+
+ if (method !== 'GET' && method !== 'POST') {
+ form.append($('<input>', {
+ type: 'hidden',
+ name: '_method',
+ value: method.toLowerCase()
+ }))
+ }
+
+ var data = options.data
+ if (typeof data === 'string') {
+ $.each(data.split('&'), function(index, value) {
+ var pair = value.split('=')
+ form.append($('<input>', {type: 'hidden', name: pair[0], value: pair[1]}))
+ })
+ } else if (typeof data === 'object') {
+ for (key in data)
+ form.append($('<input>', {type: 'hidden', name: key, value: data[key]}))
+ }
+
+ $(document.body).append(form)
+ form.submit()
+}
+
+// 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
+// the options object.
+//
+// Examples
+//
+// optionsFor('#container')
+// // => {container: '#container'}
+//
+// optionsFor('#container', {push: true})
+// // => {container: '#container', push: true}
+//
+// optionsFor({container: '#container', push: true})
+// // => {container: '#container', push: true}
+//
+// Returns options Object.
+function optionsFor(container, options) {
+ // Both container and options
+ if ( container && options )
+ options.container = container
+
+ // First argument is options Object
+ else if ( $.isPlainObject(container) )
+ options = container
+
+ // Only container
+ else
+ options = {container: container}
+
+ // Find and validate container
+ if (options.container)
+ options.container = findContainerFor(options.container)
+
+ return options
+}
+
+// Internal: Find container element for a variety of inputs.
+//
+// Because we can't persist elements using the history API, we must be
+// able to find a String selector that will consistently find the Element.
+//
+// container - A selector String, jQuery object, or DOM Element.
+//
+// Returns a jQuery object whose context is `document` and has a selector.
+function findContainerFor(container) {
+ container = $(container)
+
+ if ( !container.length ) {
+ throw "no pjax container for " + container.selector
+ } else if ( container.selector !== '' && container.context === document ) {
+ return container
+ } else if ( container.attr('id') ) {
+ return $('#' + container.attr('id'))
+ } else {
+ throw "cant get selector for pjax 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) {
+ return elems.filter(selector).add(elems.find(selector));
+}
+
+function parseHTML(html) {
+ return $.parseHTML(html, document, true)
+}
+
+// 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.requestUrl)
+
+ // Attempt to parse response html into elements
+ if (/<html/i.test(data)) {
+ var $head = $(parseHTML(data.match(/<head[^>]*>([\s\S.]*)<\/head>/i)[0]))
+ var $body = $(parseHTML(data.match(/<body[^>]*>([\s\S.]*)<\/body>/i)[0]))
+ } else {
+ var $head = $body = $(parseHTML(data))
+ }
+
+ // If response data is empty, return fast
+ if ($body.length === 0)
+ return obj
+
+ // If there's a <title> tag in the header, use it as
+ // the page's title.
+ obj.title = findAll($head, 'title').last().text()
+
+ if (options.fragment) {
+ // If they specified a fragment, look for it in the response
+ // and pull it out.
+ if (options.fragment === 'body') {
+ var $fragment = $body
+ } else {
+ var $fragment = findAll($body, 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 = $body
+ }
+
+ // Clean up any <title> tags
+ if (obj.contents) {
+ // Remove any parent title elements
+ obj.contents = obj.contents.not(function() { return $(this).is('title') })
+
+ // Then scrub any titles from their descendants
+ obj.contents.find('title').remove()
+
+ // Gather all script[src] elements
+ obj.scripts = findAll(obj.contents, 'script[src]').remove()
+ obj.contents = obj.contents.not(obj.scripts)
+ }
+
+ // Trim any whitespace off the title
+ if (obj.title) obj.title = $.trim(obj.title)
+
+ return obj
+}
+
+// Load an execute scripts using standard script request.
+//
+// Avoids jQuery's traditional $.getScript which does a XHR request and
+// globalEval.
+//
+// scripts - jQuery object of script Elements
+//
+// Returns nothing.
+function executeScriptTags(scripts) {
+ if (!scripts) return
+
+ var existingScripts = $('script[src]')
+
+ scripts.each(function() {
+ var src = this.src
+ var matchedScripts = existingScripts.filter(function() {
+ return this.src === src
+ })
+ if (matchedScripts.length) return
+
+ var script = document.createElement('script')
+ script.type = $(this).attr('type')
+ script.src = $(this).attr('src')
+ document.head.appendChild(script)
+ })
+}
+
+// Internal: History DOM caching class.
+var cacheMapping = {}
+var cacheForwardStack = []
+var cacheBackStack = []
+
+// Push previous state id and container contents into the history
+// cache. Should be called in conjunction with `pushState` to save the
+// previous container contents.
+//
+// id - State ID Number
+// value - DOM Element to cache
+//
+// Returns nothing.
+function cachePush(id, value) {
+ cacheMapping[id] = value
+ cacheBackStack.push(id)
+
+ // Remove all entires in forward history stack after pushing
+ // a new page.
+ while (cacheForwardStack.length)
+ delete cacheMapping[cacheForwardStack.shift()]
+
+ // Trim back history stack to max cache length.
+ while (cacheBackStack.length > pjax.defaults.maxCacheLength)
+ delete cacheMapping[cacheBackStack.shift()]
+}
+
+// Shifts cache from directional history cache. Should be
+// called on `popstate` with the previous state id and container
+// contents.
+//
+// direction - "forward" or "back" String
+// id - State ID Number
+// value - DOM Element to cache
+//
+// Returns nothing.
+function cachePop(direction, id, value) {
+ var pushStack, popStack
+ cacheMapping[id] = value
+
+ if (direction === 'forward') {
+ pushStack = cacheBackStack
+ popStack = cacheForwardStack
+ } else {
+ pushStack = cacheForwardStack
+ popStack = cacheBackStack
+ }
+
+ pushStack.push(id)
+ if (id = popStack.pop())
+ delete cacheMapping[id]
+}
+
+// Public: Find version identifier for the initial page load.
+//
+// Returns String version or undefined.
+function findVersion() {
+ return $('meta').filter(function() {
+ var name = $(this).attr('http-equiv')
+ return name && name.toUpperCase() === 'X-PJAX-VERSION'
+ }).attr('content')
+}
+
+// Install pjax functions on $.pjax to enable pushState behavior.
+//
+// Does nothing if already enabled.
+//
+// Examples
+//
+// $.pjax.enable()
+//
+// Returns nothing.
+function enable() {
+ $.fn.pjax = fnPjax
+ $.pjax = pjax
+ $.pjax.enable = $.noop
+ $.pjax.disable = disable
+ $.pjax.click = handleClick
+ $.pjax.submit = handleSubmit
+ $.pjax.reload = pjaxReload
+ $.pjax.defaults = {
+ timeout: 650,
+ push: true,
+ replace: false,
+ type: 'GET',
+ dataType: 'html',
+ scrollTo: 0,
+ maxCacheLength: 20,
+ version: findVersion
+ }
+ $(window).on('popstate.pjax', onPjaxPopstate)
+}
+
+// Disable pushState behavior.
+//
+// This is the case when a browser doesn't support pushState. It is
+// sometimes useful to disable pushState for debugging on a modern
+// browser.
+//
+// Examples
+//
+// $.pjax.disable()
+//
+// Returns nothing.
+function disable() {
+ $.fn.pjax = function() { return this }
+ $.pjax = fallbackPjax
+ $.pjax.enable = enable
+ $.pjax.disable = $.noop
+ $.pjax.click = $.noop
+ $.pjax.submit = $.noop
+ $.pjax.reload = function() { window.location.reload() }
+
+ $(window).off('popstate.pjax', onPjaxPopstate)
+}
+
+
+// Add the state property to jQuery's event object so we can use it in
+// $(window).bind('popstate')
+if ( $.inArray('state', $.event.props) < 0 )
+ $.event.props.push('state')
+
+// Is pjax supported by this browser?
+$.support.pjax =
+ window.history && window.history.pushState && window.history.replaceState &&
+ // pushState isn't reliable on iOS until 5.
+ !navigator.userAgent.match(/((iPod|iPhone|iPad).+\bOS\s+[1-4]|WebApps\/.+CFNetwork)/)
+
+$.support.pjax ? enable() : disable()
+
+})(jQuery);
View
5 ajax/libs/jquery.pjax/1.8.0/jquery.pjax.min.js
@@ -0,0 +1,5 @@
+// jquery.pjax.js 1.7.0
+// copyright chris wanstrath
+// https://github.com/defunkt/jquery-pjax
+
+!function(a){function b(b,d,e){var f=this;return this.on("click.pjax",b,function(b){var g=a.extend({},p(d,e));g.container||(g.container=a(this).attr("data-pjax")||f),c(b,g)})}function c(b,c,d){d=p(c,d);var f=b.currentTarget;if("A"!==f.tagName.toUpperCase())throw"$.fn.pjax or $.pjax.click requires an anchor element";if(!(b.which>1||b.metaKey||b.ctrlKey||b.shiftKey||b.altKey||location.protocol!==f.protocol||location.hostname!==f.hostname||f.hash&&f.href.replace(f.hash,"")===location.href.replace(location.hash,"")||f.href===location.href+"#")){var g={url:f.href,container:a(f).attr("data-pjax"),target:f},h=a.extend({},g,d),i=a.Event("pjax:click");a(f).trigger(i,[h]),i.isDefaultPrevented()||(e(h),b.preventDefault(),a(f).trigger("pjax:clicked",[h]))}}function d(b,c,d){d=p(c,d);var f=b.currentTarget;if("FORM"!==f.tagName.toUpperCase())throw"$.pjax.submit requires a form element";var g={type:f.method.toUpperCase(),url:f.action,data:a(f).serializeArray(),container:a(f).attr("data-pjax"),target:f};e(a.extend({},g,d)),b.preventDefault()}function e(b){function h(b,d){var e=a.Event(b,{relatedTarget:c});return f.trigger(e,d),!e.isDefaultPrevented()}b=a.extend(!0,{},a.ajaxSettings,e.defaults,b),a.isFunction(b.url)&&(b.url=b.url());var c=b.target,d=o(b.url).hash,f=b.context=q(b.container);b.data||(b.data={}),b.data._pjax=f.selector;var i;b.beforeSend=function(a,c){return"GET"!==c.type&&(c.timeout=0),a.setRequestHeader("X-PJAX","true"),a.setRequestHeader("X-PJAX-Container",f.selector),h("pjax:beforeSend",[a,c])?(c.timeout>0&&(i=setTimeout(function(){h("pjax:timeout",[a,b])&&a.abort("timeout")},c.timeout),c.timeout=0),b.requestUrl=o(c.url).href,void 0):!1},b.complete=function(a,c){i&&clearTimeout(i),h("pjax:complete",[a,c,b]),h("pjax:end",[a,b])},b.error=function(a,c,d){var e=t("",a,b),f=h("pjax:error",[a,c,d,b]);"GET"==b.type&&"abort"!==c&&f&&g(e.url)},b.success=function(c,i,j){var k="function"==typeof a.pjax.defaults.version?a.pjax.defaults.version():a.pjax.defaults.version,l=j.getResponseHeader("X-PJAX-Version"),n=t(c,j,b);if(k&&l&&k!==l)return g(n.url),void 0;if(!n.contents)return g(n.url),void 0;e.state={id:b.id||m(),url:n.url,title:n.title,container:f.selector,fragment:b.fragment,timeout:b.timeout},(b.push||b.replace)&&window.history.replaceState(e.state,n.title,n.url),document.activeElement.blur(),n.title&&(document.title=n.title),f.html(n.contents);var p=f.find("input[autofocus], textarea[autofocus]").last()[0];if(p&&document.activeElement!==p&&p.focus(),u(n.scripts),"number"==typeof b.scrollTo&&a(window).scrollTop(b.scrollTo),""!==d){var q=o(n.url);q.hash=d,e.state.url=q.href,window.history.replaceState(e.state,n.title,q.href);var r=a(q.hash);r.length&&a(window).scrollTop(r.offset().top)}h("pjax:success",[c,i,j,b])},e.state||(e.state={id:m(),url:window.location.href,title:document.title,container:f.selector,fragment:b.fragment,timeout:b.timeout},window.history.replaceState(e.state,document.title));var j=e.xhr;j&&j.readyState<4&&(j.onreadystatechange=a.noop,j.abort()),e.options=b;var j=e.xhr=a.ajax(b);return j.readyState>0&&(b.push&&!b.replace&&(y(e.state.id,f.clone().contents()),window.history.pushState(null,"",n(b.requestUrl))),h("pjax:start",[j,b]),h("pjax:send",[j,b])),e.xhr}function f(b,c){var d={url:window.location.href,push:!1,replace:!0,scrollTo:!1};return e(a.extend(d,p(b,c)))}function g(a){window.history.replaceState(null,"","#"),window.location.replace(a)}function k(b){var c=b.state;if(c&&c.container){if(h&&i==c.url)return;if(e.state.id===c.id)return;var d=a(c.container);if(d.length){var f,j=v[c.id];e.state&&(f=e.state.id<c.id?"forward":"back",z(f,e.state.id,d.clone().contents()));var k=a.Event("pjax:popstate",{state:c,direction:f});d.trigger(k);var l={id:c.id,url:c.url,container:d,push:!1,fragment:c.fragment,timeout:c.timeout,scrollTo:!1};j?(d.trigger("pjax:start",[null,l]),c.title&&(document.title=c.title),d.html(j),e.state=c,d.trigger("pjax:end",[null,l])):e(l),d[0].offsetHeight}else g(location.href)}h=!1}function l(b){var c=a.isFunction(b.url)?b.url():b.url,d=b.type?b.type.toUpperCase():"GET",e=a("<form>",{method:"GET"===d?"GET":"POST",action:c,style:"display:none"});"GET"!==d&&"POST"!==d&&e.append(a("<input>",{type:"hidden",name:"_method",value:d.toLowerCase()}));var f=b.data;if("string"==typeof f)a.each(f.split("&"),function(b,c){var d=c.split("=");e.append(a("<input>",{type:"hidden",name:d[0],value:d[1]}))});else if("object"==typeof f)for(key in f)e.append(a("<input>",{type:"hidden",name:key,value:f[key]}));a(document.body).append(e),e.submit()}function m(){return(new Date).getTime()}function n(a){return a.replace(/\?_pjax=[^&]+&?/,"?").replace(/_pjax=[^&]+&?/,"").replace(/[\?&]$/,"")}function o(a){var b=document.createElement("a");return b.href=a,b}function p(b,c){return b&&c?c.container=b:c=a.isPlainObject(b)?b:{container:b},c.container&&(c.container=q(c.container)),c}function q(b){if(b=a(b),b.length){if(""!==b.selector&&b.context===document)return b;if(b.attr("id"))return a("#"+b.attr("id"));throw"cant get selector for pjax container!"}throw"no pjax container for "+b.selector}function r(a,b){return a.filter(b).add(a.find(b))}function s(b){return a.parseHTML(b,document,!0)}function t(b,c,d){var e={};if(e.url=n(c.getResponseHeader("X-PJAX-URL")||d.requestUrl),/<html/i.test(b))var f=a(s(b.match(/<head[^>]*>([\s\S.]*)<\/head>/i)[0])),g=a(s(b.match(/<body[^>]*>([\s\S.]*)<\/body>/i)[0]));else var f=g=a(s(b));if(0===g.length)return e;if(e.title=r(f,"title").last().text(),d.fragment){if("body"===d.fragment)var h=g;else var h=r(g,d.fragment).first();h.length&&(e.contents=h.contents(),e.title||(e.title=h.attr("title")||h.data("title")))}else/<html/i.test(b)||(e.contents=g);return e.contents&&(e.contents=e.contents.not(function(){return a(this).is("title")}),e.contents.find("title").remove(),e.scripts=r(e.contents,"script[src]").remove(),e.contents=e.contents.not(e.scripts)),e.title&&(e.title=a.trim(e.title)),e}function u(b){if(b){var c=a("script[src]");b.each(function(){var b=this.src,d=c.filter(function(){return this.src===b});if(!d.length){var e=document.createElement("script");e.type=a(this).attr("type"),e.src=a(this).attr("src"),document.head.appendChild(e)}})}}function y(a,b){for(v[a]=b,x.push(a);w.length;)delete v[w.shift()];for(;x.length>e.defaults.maxCacheLength;)delete v[x.shift()]}function z(a,b,c){var d,e;v[b]=c,"forward"===a?(d=x,e=w):(d=w,e=x),d.push(b),(b=e.pop())&&delete v[b]}function A(){return a("meta").filter(function(){var b=a(this).attr("http-equiv");return b&&"X-PJAX-VERSION"===b.toUpperCase()}).attr("content")}function B(){a.fn.pjax=b,a.pjax=e,a.pjax.enable=a.noop,a.pjax.disable=C,a.pjax.click=c,a.pjax.submit=d,a.pjax.reload=f,a.pjax.defaults={timeout:650,push:!0,replace:!1,type:"GET",dataType:"html",scrollTo:0,maxCacheLength:20,version:A},a(window).on("popstate.pjax",k)}function C(){a.fn.pjax=function(){return this},a.pjax=l,a.pjax.enable=B,a.pjax.disable=a.noop,a.pjax.click=a.noop,a.pjax.submit=a.noop,a.pjax.reload=function(){window.location.reload()},a(window).off("popstate.pjax",k)}var h=!0,i=window.location.href,j=window.history.state;j&&j.container&&(e.state=j),"state"in window.history&&(h=!1);var v={},w=[],x=[];a.inArray("state",a.event.props)<0&&a.event.props.push("state"),a.support.pjax=window.history&&window.history.pushState&&window.history.replaceState&&!navigator.userAgent.match(/((iPod|iPhone|iPad).+\bOS\s+[1-4]|WebApps\/.+CFNetwork)/),a.support.pjax?B():C()}(jQuery);
View
2  ajax/libs/jquery.pjax/package.json
@@ -1,7 +1,7 @@
{
"name": "jquery.pjax",
"filename": "jquery.pjax.min.js",
- "version": "1.7.0",
+ "version": "1.8.0",
"description": "pjax is a jQuery plugin that uses ajax and pushState to deliver a fast browsing experience with real permalinks, page titles, and a working back button.",
"homepage": "https://github.com/defunkt/jquery-pjax",
"keywords": [
Something went wrong with that request. Please try again.