本文来源于网络,不知道转了多少手了,亲测可用,但似乎TangStyle与之不兼容,多多少少会出现问题。且用了Pjax后代码高亮的效果显示不出来了,直呼用不起,还是删除了这个功能。本文把操作方式记录下来。


一、在Emlog当前主题的header.php引用jquery.js,并在<body>标签前加上下述代码:

<!--pjax无刷新-->
<script type="text/javascript" src="<?php echo TEMPLATE_URL; ?>pjax.js"></script>
<div class="pjax_loading"></div>
<script>
$(document).pjax('a[target!=_blank]', '#main', {fragment:'#main', timeout:8000});
$(document).on('pjax:send', function() { //pjax链接点击后显示加载动画;
$(".pjax_loading").css("display", "block");
});
$(document).on('pjax:complete', function() { //pjax链接加载完成后隐藏加载动画;
$(".pjax_loading").css("display", "none");
pajx_loadDuodsuo();
});
function pajx_loadDuodsuo(){
var dus=$(".ds-thread");
if($(dus).length==1){
var el = document.createElement('div');
el.setAttribute('data-thread-key',$(dus).attr("data-thread-key"));//必选参数
el.setAttribute('data-url',$(dus).attr("data-url"));
DUOSHUO.EmbedThread(el);
$(dus).html(el);
}
}
</script>


二、在Emlog当前主题的footer.php模板的body标签</body>标签前加上下述代码:

<script>
$(document).pjax('a[target!=_blank]', '#contentleft', {fragment:'#contentleft', timeout:8000});
</script>


三.增加css到sytle.css后侧[2019.5.18]

.pjax_loading{position: fixed;top: 0;left: 0;z-index: 999999;display: none;width: 100%;height: 100%;background-color: #2C3E50;opacity: 0.88;background: url('data:image/svg+xml;base64,PCEtLSBCeSBTYW0gSGVyYmVydCAoQHNoZXJiKSwgZm9yIGV2ZXJ5b25lLiBNb3JlIEAgaHR0cDovL2dvby5nbC83QUp6YkwgLS0+CjwhLS0gVG9kbzogYWRkIGVhc2luZyAtLT4KPHN2ZyB3aWR0aD0iNTciIGhlaWdodD0iNTciIHZpZXdCb3g9IjAgMCA1NyA1NyIgeG1sbnM9Imh0dHA6Ly93d3cudzMub3JnLzIwMDAvc3ZnIiBzdHJva2U9IiNmZmYiPgogICAgPGcgZmlsbD0ibm9uZSIgZmlsbC1ydWxlPSJldmVub2RkIj4KICAgICAgICA8ZyB0cmFuc2Zvcm09InRyYW5zbGF0ZSgxIDEpIiBzdHJva2Utd2lkdGg9IjIiPgogICAgICAgICAgICA8Y2lyY2xlIGN4PSI1IiBjeT0iNTAiIHI9IjUiPgogICAgICAgICAgICAgICAgPGFuaW1hdGUgYXR0cmlidXRlTmFtZT0iY3kiCiAgICAgICAgICAgICAgICAgICAgIGJlZ2luPSIwcyIgZHVyPSIyLjJzIgogICAgICAgICAgICAgICAgICAgICB2YWx1ZXM9IjUwOzU7NTA7NTAiCiAgICAgICAgICAgICAgICAgICAgIGNhbGNNb2RlPSJsaW5lYXIiCiAgICAgICAgICAgICAgICAgICAgIHJlcGVhdENvdW50PSJpbmRlZmluaXRlIiAvPgogICAgICAgICAgICAgICAgPGFuaW1hdGUgYXR0cmlidXRlTmFtZT0iY3giCiAgICAgICAgICAgICAgICAgICAgIGJlZ2luPSIwcyIgZHVyPSIyLjJzIgogICAgICAgICAgICAgICAgICAgICB2YWx1ZXM9IjU7Mjc7NDk7NSIKICAgICAgICAgICAgICAgICAgICAgY2FsY01vZGU9ImxpbmVhciIKICAgICAgICAgICAgICAgICAgICAgcmVwZWF0Q291bnQ9ImluZGVmaW5pdGUiIC8+CiAgICAgICAgICAgIDwvY2lyY2xlPgogICAgICAgICAgICA8Y2lyY2xlIGN4PSIyNyIgY3k9IjUiIHI9IjUiPgogICAgICAgICAgICAgICAgPGFuaW1hdGUgYXR0cmlidXRlTmFtZT0iY3kiCiAgICAgICAgICAgICAgICAgICAgIGJlZ2luPSIwcyIgZHVyPSIyLjJzIgogICAgICAgICAgICAgICAgICAgICBmcm9tPSI1IiB0bz0iNSIKICAgICAgICAgICAgICAgICAgICAgdmFsdWVzPSI1OzUwOzUwOzUiCiAgICAgICAgICAgICAgICAgICAgIGNhbGNNb2RlPSJsaW5lYXIiCiAgICAgICAgICAgICAgICAgICAgIHJlcGVhdENvdW50PSJpbmRlZmluaXRlIiAvPgogICAgICAgICAgICAgICAgPGFuaW1hdGUgYXR0cmlidXRlTmFtZT0iY3giCiAgICAgICAgICAgICAgICAgICAgIGJlZ2luPSIwcyIgZHVyPSIyLjJzIgogICAgICAgICAgICAgICAgICAgICBmcm9tPSIyNyIgdG89IjI3IgogICAgICAgICAgICAgICAgICAgICB2YWx1ZXM9IjI3OzQ5OzU7MjciCiAgICAgICAgICAgICAgICAgICAgIGNhbGNNb2RlPSJsaW5lYXIiCiAgICAgICAgICAgICAgICAgICAgIHJlcGVhdENvdW50PSJpbmRlZmluaXRlIiAvPgogICAgICAgICAgICA8L2NpcmNsZT4KICAgICAgICAgICAgPGNpcmNsZSBjeD0iNDkiIGN5PSI1MCIgcj0iNSI+CiAgICAgICAgICAgICAgICA8YW5pbWF0ZSBhdHRyaWJ1dGVOYW1lPSJjeSIKICAgICAgICAgICAgICAgICAgICAgYmVnaW49IjBzIiBkdXI9IjIuMnMiCiAgICAgICAgICAgICAgICAgICAgIHZhbHVlcz0iNTA7NTA7NTs1MCIKICAgICAgICAgICAgICAgICAgICAgY2FsY01vZGU9ImxpbmVhciIKICAgICAgICAgICAgICAgICAgICAgcmVwZWF0Q291bnQ9ImluZGVmaW5pdGUiIC8+CiAgICAgICAgICAgICAgICA8YW5pbWF0ZSBhdHRyaWJ1dGVOYW1lPSJjeCIKICAgICAgICAgICAgICAgICAgICAgZnJvbT0iNDkiIHRvPSI0OSIKICAgICAgICAgICAgICAgICAgICAgYmVnaW49IjBzIiBkdXI9IjIuMnMiCiAgICAgICAgICAgICAgICAgICAgIHZhbHVlcz0iNDk7NTsyNzs0OSIKICAgICAgICAgICAgICAgICAgICAgY2FsY01vZGU9ImxpbmVhciIKICAgICAgICAgICAgICAgICAgICAgcmVwZWF0Q291bnQ9ImluZGVmaW5pdGUiIC8+CiAgICAgICAgICAgIDwvY2lyY2xlPgogICAgICAgIDwvZz4KICAgIDwvZz4KPC9zdmc+') #2C3E50 50% 50% no-repeat;}


附:1.jquery.js最新1.9版本,把他以PHP保存在当前模板根目录;

// jquery.pjax.js
// copyright chris wanstrath
// https://github.com/defunkt/jquery-pjax

(function($){
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)
  })
}

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: 8000,
push: true,
replace: false,
type: 'GET',
dataType: 'html',
scrollTo: 0,
maxCacheLength: 200,
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);