SkillAgentSearch skills...

Pjax

Easily enable fast Ajax navigation on any website (using pushState + xhr)

Install / Use

/learn @MoOx/Pjax
About this skill

Quality Score

0/100

Supported Platforms

Universal

README

Pjax

Build Status.

Easily enable fast AJAX navigation on any website (using pushState() + XHR)

Pjax is a standalone JavaScript module that uses AJAX (XmlHttpRequest) and pushState() to deliver a fast browsing experience.

It allows you to completely transform the user experience of standard websites (server-side generated or static ones) to make users feel like they are browsing an app, especially for those with low bandwidth connections.

No more full page reloads. No more multiple HTTP requests.

Pjax does not rely on other libraries, like jQuery or similar. It is written entirely in vanilla JS.

Installation

  • You can link directly to the bundle:

    <script src="https://cdn.jsdelivr.net/npm/pjax@VERSION/pjax.js"></script>
    
  • Or the minified bundle:

    <script src="https://cdn.jsdelivr.net/npm/pjax@VERSION/pjax.min.js"></script>
    
  • You can also install Pjax from npm:

    npm install pjax
    

    Note: If you use this option, you will need to do one of the following:

    • Link a script tag to either pjax.js or pjax.min.js. E.g.:
    <script src="./node_modules/pjax/pjax.js"></script>
    
    • Use a bundler like Webpack. (index.js cannot be used in the browser without a bundler).
  • Or you can clone the repo and build the bundle from the source using npm:

    git clone https://github.com/MoOx/pjax.git
    cd pjax
    npm install
    npm run build
    

    and then link a script tag to either pjax.js or pjax.min.js. E.g.:

    <script src="./pjax.min.js"></script>
    

What Pjax Does

Under the hood, it's just ONE HTTP request with a pushState() call.

Pjax loads pages using AJAX and updates the browser's current URL using pushState() without reloading your page's layout or any resources (JS, CSS), giving a fast page load.

It works with all permalinks and can update all the parts of the page you want (including HTML metas, title, and navigation state).

In the case of browsers that don't support history.pushState(), Pjax gracefully degrades and does not do anything at all.

Additionally, Pjax:

  • Is not limited to one container, like jQuery-Pjax is.
  • Fully supports browser history (back and forward buttons).
  • Supports keyboard browsing.
  • Automatically falls back to standard navigation for external pages (thanks to Captain Obvious's help).
  • Automatically falls back to standard navigation for internal pages that do not have an appropriate DOM tree.
  • Allows for CSS transitions (animations) very easily.
  • Is only around 6kb (minified and gzipped).

How Pjax Works

  • It listens to every click on links you want (by default all of them).
  • When an internal link is clicked, Pjax fetches the page's HTML via AJAX.
  • Pjax renders the page's DOM tree (without loading any resources - images, CSS, JS, etc).
  • It checks that all defined parts can be replaced:
    • If the page doesn't meet the requirements, standard navigation is used.
    • If the page meets the requirements, Pjax does all defined DOM replacements.
  • Then it updates the browser's current URL using pushState().

Overview

Pjax is fully automatic. You don't need to change anything about your existing HTML, you just need to designate which elements on your page that you want to be replaced when your site is navigated.

Consider the following page.

<!DOCTYPE html>
<html>
<head>
  <!-- metas, title, styles, etc -->
  <title>My Cool Blog</title>
  <meta name="description" content="Welcome to My Cool Blog">
  <link href="/styles.css" rel="stylesheet">
</head>

<body>
  <header class="the-header">
    <nav>
      <a href="/" class="is-active">Home</a>
      <a href="/about">About</a>
      <a href="/contact">Contact</a>
    </nav>
  </header>

  <section class="the-content">
    <h1>My Cool Blog</h1>
    <p>
      Thanks for stopping by!

      <a href="/about">Click Here to find out more about me.</a>
    </p>
  </section>

  <aside class="the-sidebar">
    <h3>Recent Posts</h3>
    <!-- sidebar content -->
  </aside>

  <footer class="the-footer">
    &copy; My Cool Blog
  </footer>

  <script src="onDomReadystuff.js"></script>
  <script>
    // analytics
  </script>
</body>
</html>

We want Pjax to intercept the URL /about, and replace .the-content with the resulting content of the request.

It would also be nice if we could replace the <nav> to show that the /about link is active, as well as update our page meta and the <aside> sidebar.

So all in all we want to update the page title and meta, header, content area, and sidebar, without reloading styles or scripts.

We can easily do this by telling Pjax to listen on all a tags (which is the default) and use CSS selectors defined above (without forgetting minimal meta):

var pjax = new Pjax({
  selectors: [
    "title",
    "meta[name=description]",
    ".the-header",
    ".the-content",
    ".the-sidebar",
  ]
})

Now, when someone in a Pjax-compatible browser clicks an internal link on the page, the content of each of the selectors will be replaced with the specific content pieces found in the next page's content.

Magic! For real! There is no need to do anything server-side!

Differences with jQuery-pjax

  • No jQuery dependency.
  • Not limited to a container.
  • No server-side requirements.
  • Works for CommonJS environment (Webpack/Browserify), AMD (RequireJS) or even globally.
  • Allows page transitions with CSS animations.
  • Can be easily tweaked, since every method is public (and as a result, overridable).

Compatibility

Pjax only works with browsers that support the history.pushState() API. When the API isn't supported, Pjax goes into fallback mode (and it just does nothing).

To see if Pjax is actually supported by your browser, use Pjax.isSupported().

Usage

new Pjax()

Let's talk more about the most basic way to get started.

When instantiating Pjax, you can pass options into the constructor as an object:

var pjax = new Pjax({
  elements: "a", // default is "a[href], form[action]"
  selectors: ["title", ".the-header", ".the-content", ".the-sidebar"]
})

This will enable Pjax on all links, and designate the part to replace using CSS selectors "title", ".the-header", ".the-content", ".the-sidebar".

In some cases, you might want to only target some specific elements to apply Pjax behavior. In that case, you can do two different things:

  1. Use a custom CSS selector( such as "a.js-Pjax" or ".js-Pjax a", etc).
  2. Override Pjax.prototype.getElements.
    • Note: If doing this, make sure to return a NodeList.
// use case 1
var pjax = new Pjax({ elements: "a.js-Pjax" })
// use case 2
Pjax.prototype.getElements = function() {
  return document.getElementsByClassName(".js-Pjax")
}

var pjax = new Pjax()

loadUrl(href, [options])

With this method, you can manually trigger the loading of a URL:

var pjax = new Pjax()

// use case 1
pjax.loadUrl("/your-url")

// use case 2 (with options override)
pjax.loadUrl("/your-other-url", { timeout: 10 })

handleResponse(responseText, request, href, options)

This method takes the raw response, processes the URL, then calls pjax.loadContent() to actually load it into the DOM.

It is passed the following arguments:

  • responseText (string): This is the raw response text. This is equivalent to request.responseText.
  • request (XMLHttpRequest): This is the XHR object.
  • href (string): This is the URL that was passed to loadUrl().
  • options (object): This is an object with the options for this request. The structure basically matches the regular options object, with a few extra internal properties.

You can override this if you want to process the data before, or instead of, it being loaded into the DOM.

For example, if you want to check for a non-HTML response, you could do the following:

var pjax = new Pjax();

pjax._handleResponse = pjax.handleResponse;

pjax.handleResponse = function(responseText, request, href, options) {
  if (request.responseText.match("<html")) {
    pjax._handleResponse(responseText, request, href, options);
  } else {
    // handle non-HTML response here
  }
}

refresh([el])

Use this method to bind Pjax to children of a DOM element that didn't exist when Pjax was initialised e.g. content inserted dynamically by another library or script. If called with no arguments, Pjax will parse the entire document again to look for newly-inserted elements.

// Inside a callback or Promise that runs after new DOM content has been inserted
var newContent = document.querySelector(".new-content");

pjax.refresh(newContent);

reload()

A helper shortcut for window.location.reload(). Used to force a page reload.

pjax.reload()

Options

elements (String, default: "a[href], form[action]")

CSS selector(s) used to find links to apply Pjax to. If needing multiple specific selectors, separate them by a comma.

// Single element
var pjax = new Pjax({
  elements: ".ajax"
})
// Multiple elements
var pjax = new Pjax({
  elements: ".pjax, .ajax",
})

selectors (Array, default: ["title", ".js-Pjax"])

CSS selectors used to find which content to replace.

var pjax = new Pjax({
  selectors: [
    "title",
    "the-content",
  ]
})

If a query returns multiples items, it will just keep the index.

Example of what you can do:

<!DOCT

Related Skills

View on GitHub
GitHub Stars1.5k
CategoryDevelopment
Updated11d ago
Forks122

Languages

JavaScript

Security Score

100/100

Audited on Mar 21, 2026

No findings