Important: This documentation covers Yarn 1 (Classic).
For Yarn 2+ docs and migration guide, see yarnpkg.com.

Package detail

@pageworks/pjax

Pageworks10MIT2.3.2TypeScript support: included

Turns any website into a SPA using Fetch and link prefetching.

pjax, pushstate, ajax, navigation, transition, animation, prefetcher, typescript, fetch

readme

Pjax

Pjax enables fast and easy AJAX navigation on any website using pushState and fetch. No more full page reloads, no more multiple HTTP request, and written entirely in TypeScript.

Installation

Download Pjax via NPM:

npm i --save @pageworks/pjax

Once the package is installed import the package:

import Pjax from '@pageworks/pjax';

Then it's as simple as starting a new instance:

new Pjax();

How Pjax Works

Pjax loads pages using the Fetch API and updates the browser's current URL using a window.pushState() all without reloading the page's layout or any resources (JavaScript, CSS, etc). Pjax listens for the onmouseenter event for links and prefetches the pages HTML. Dpending on what the user does determines Pjax's response. If the user clicks the link before the server responds Pjax will notice that the user wants the page and will switch out the content as soon as the server responds. Finally, if the user remains hovered and the server has already responded Pjax will cache the new pages HTML content and will wait until the user clicks the link or triggers the onmouseleave event causing Pjax to clear the cached HTML. When combining prefetching and the ability to swap out content without causing a full page reload results in very fast page load responses.

Under the hood Pjax is one HTTP request with a window.pushState().

What Pjax's All About

  • Multiple container support
  • Fully supports browser history (window popstates)
  • Automagically falls back to standard navigation for external pages
  • Automagically falls back to standard navigation for internal pages that do not have an appropriate DOM tree
  • Allows for modern CSS page transitions (animation) easily
  • Is very lightweight

Under the Hood

  • Pjax attempts to prefetch internal links for the fastest possible load time
  • Pjax renders new pages without reloading resources such as images, CSS, JavaScript, etc...
  • Checks that all defined parts can be replaced:
    • If the page doesn't meet the requirements Pjax will do nothing and standard navigation is used
    • If the page meets requirements Pjax swaps the DOM elements
  • Pjax updates the browser's current URL using pushState()

Documentation

Getting Started

Start by setting up the basic index.html file for your website.

<!doctype <!DOCTYPE html>
<html>
<head>
    <meta charset="utf-8" />
    <meta http-equiv="X-UA-Compatible" content="IE=edge">
    <title>Index | Pjax Testing</title>
    <meta name="viewport" content="width=device-width, initial-scale=1">
</head>
<body>
    <a href="index">Home</a>
    <main class="js-pjax-wrapper">
        <article class="js-pjax">
            <h1>Index Page</h1>
            <ul>
                <li><a href="index">Index</a></li>
                <li><a href="page-1">Page 1</a></li>
            </ul>
        </article>
    </main>
    <script src="main.js"></script>
</body>
</html>

In the main/application script for your project you can being using Pjax with the following:

import Pjax from '@pageworks/pjax';

const pjax = new Pjax({
    debug: true
});

Pjax Options

You can define custom Pjax options using the following:

Option Type Default
elements string a[href]
selectors string[] .js-pjax
history boolean true
cacheBust boolean false
debug boolean false
titleSwitch boolean true
customTransitions boolean false
customPreventionAttributes string[] []
importScripts boolean true
importCSS boolean true
scriptImportLocation HTMLElement document.head
requireCssBeforeComplete boolean false

elements is the base element users should click on to trigger a page transition.

selectors is an array of containers that Pjax should swap.

When history is true Pjax will use window.history.pushState() to manipulate the browsers history.

cacheBust will add a GET param to all request forcing the browser to perform the request instead of using a cached version of the page.

debug will tell Pjax to display all debug information.

titleSwitch when true will swap out the documents title during page transitions.

customTransitions when true Pjax won't actually switch out the content until the developers application sends a custom pjax:continue event.

customPreventionAttributes is an array of custom element attributes that Pjax will look for when attaching event listeners. The default prevention attribute that is prevent-pjax however you can define additional attributes. For example, if you are using a custom lightcase modal libary you could tell Pjax not to hijack the events attached to any element that has a valid href attribute when the element also has a lightcase attribute.

When importScripts is true Pjax will dynamically fetch and append all <script> elements. Elements with a valid src will be appended once, elements that contain JavaScript will be re-appended every time.

When importCSS is true Pjax will dynamically fetch and append custom <style> elements to the documents <head>. Only <link> elements labeled as rel="stylesheet" with a valid href attribute will be appended. Custom styles will only be appended once.

scriptImportLocation is the HTMLElement that the dynamically fetched <script> elements will be appended upon. Defaults to document.head.

When requireCssBeforeComplete is true Pjax will delay firing the pjax:complete event until all the CSS fetch request have been resolved.

Pjax Events

Pjax fires a handful of events on the document that you can listen for.

document.addEventListener('pjax:error', ()=>{ console.log('Event: pjax:error'); });
document.addEventListener('pjax:send', (e)=>{ console.log('Event: pjax:send', e); });
document.addEventListener('pjax:prefetch', ()=>{ console.log('Event: pjax:prefetch'); });
document.addEventListener('pjax:cancel', ()=>{ console.log('Event: pjax:cancel'); });
document.addEventListener('pjax:complete', ()=>{ console.log('Event: pjax:complete'); });
document.addEventListener('pjax:scriptContentLoaded', ()=>{ console.log('Event: pjax:scriptContentLoaded'); });

Pjax listens for a pjax:continue event on the document. This is only used when the customTransitions option is set to true. Pjax will NOT swap content until it receives this event.

The pjax:scriptContentLoaded will fire on the document when all the new scripts have been fetched and appended to the body.

Status Classes

Pjax sets two custom status classes on the document element that you can use in your CSS to style your page transitions. In the example below we set all elements to use the wait cursor while the dom-is-loading class is set. Once the pjax:complete or pjax:error events fire the dom-is-loading class is removed and the dom-is-loaded class is applied.

HTML.dom-is-loading *
{
    cursor: wait !important;
}

Static Methods

Pjax allows developers to manually trigger a page load by using the public static method Pjax.load(url)

changelog

2.3.2 - 2019-09-26

Fixed

  • Fixes: fixed incorrect null check when verifying the existence of the Content-Type header

2.3.1 - 2019-09-24

Fixed

  • Fixes: fails the document parse when the response doesn't have a Content-Type header

2.3.0 - 2019-08-26

Added

  • Adds: developers can enable the requireCssBeforeComplete flag to force Pjax to fetch and append all the CSS stylesheets before firing the pjax:complete event

2.2.1 - 2019-08-23

Fixed

  • Fixes: page transitions break on slow connections #16

2.2.0 - 2019-08-22

Added

  • Adds: new scriptImportLocation option allowing developers to choose where the dynamically fetched scripts are appended, defaults to document.head

Fixed

  • Fixes: updates readme
  • Fixes: inline script elements will be appended every time the page loads while scripts with a src attribute will only be fetched and appended once
  • Fixes: updates script fetch response tracking functionality
  • Fixes: cleaned up stylesheet fetch logic

2.1.3 - 2019-04-29

Fixed

  • Fixes: switches dependencies from @codewithkyle to @pageworks

2.1.3 - 2019-04-19

Fixed

  • Fixes: tracks the request ID and doesn't handle stale request
  • Fixes: no longer default handling aborted request types (this._request === null)

2.1.2 - 2019-04-16

Fixed

  • Fixes: sends Fetch with method: GET and the following headers: 'X-Requested-With': 'XMLHttpRequest' and 'X-Pjax': 'true'

2.1.1 - 2019-04-16

Fixed

  • Fixes: script loading bug when the current document and the incoming document don't match

2.1.0 - 2019-04-15

Adds:

  • Adds: pjax:scriptContentLoaded event that fires on the document when all scripts have been fetched and appended to the body

2.0.1 - 2019-04-15

Fixed

  • Fixes: updates CSS regex href matching to handle cases where developers use a hash/timestamp for cache busting
  • Fixes: updates script src regex matching to handle cases where developers use a hash/timestamp for cache busting

2.0.0 - 2019-04-07

Adds

  • Adds: swaps XHR request with Fetch
  • Adds: new importScripts option to Pjax
  • Adds: new importCSS option to Pjax
  • Adds: when importScripts is set to true (default) any script elements will be fetched and appended to the document.body
  • Adds: when importCSS is set to true (default) any CSS (in HEAD or via <link>) will be fetched and appended
  • Adds: public static load() method to trigger a manual page load

Removes

  • Removes: no longer calls lastChance() when the new document contains <script> elements
  • Removes: timeout option from Pjax since we can't abort fetch

1.3.0 - 2019-03-27

Adds

  • Adds: Pjax manages the HTML status classes that developers can use to manage page transitions/animations

Fixed

  • Fixes: switches dependencies to use the version provided by @codewithkyle

1.2.5 - 2019-03-24

Fixed

  • Fixes: updates StateManager to user the new static methods provided in the 1.0.1 update
  • Fixes: updates readme

1.2.4 - 2019-03-16

Fixed

  • Fixes: updates version number for Pjax console log

1.2.3 - 2019-03-16

Fixed

  • Fixes: bug that occures when a page is cached but the user triggers a popstate via touch gestures

1.2.2 - 2019-03-11

Adds

  • Adds: webpack and http-server
  • Adds: /testing directory
  • Adds: new npm run bundle script for running webpack
  • Adds: new npm run test script for compiling, bundling, and launching a static http server for testing features
  • Adds: basic demo page and testing content

1.2.1 - 2019-03-11

Fixed

  • Fixes: updates console logs for better debugging

1.2.0 - 2019-03-06

Adds

  • Adds: allows users to device an array of custom attributes to prevent Pjax event listeners from firing #39

Fixed

  • Fixes: updates IE check to use fuel-device-manager package

1.1.4 - 2019-01-01

Fixed

  • Fixes: switchSelectors method now verifies that the temporary document isn't null, if it is Pjax will have the browser load the page

1.1.3 - 2019-02-25

Fixed

  • Fixes: prefetching 404 page caching bug #36

1.1.2 - 2019-02-25

Fixed

  • Fixes: prefetching 302 redirect cache bug #36

1.1.1 - 2019-02-24

Fixed

  • Fixes: updates fuel-state-manager to use the official npm package version
  • Fixes: prefetching non-200 status links #36

1.1.0 - 2019-02-23

Adds

  • Adds: new StateManager class manages the windows history

Fixed

  • Fixes: updates global.d.ts
  • Fixes: cleans up if statements to adhere to coding standards
  • Fixes: updates functions and methods to follow TypeScript guidelines

Removed

  • Removes: browserify
  • Removes: all methods related to window history management

1.0.9 - 2019-01-19

Adds

  • Adds: When switching containers if a new page contians <script> elements the pjax will load the page using the native browser functionality #31

Fixed

  • Fixes: Switched prefent-defualt attribute to prevent-pjax in order to make make preventing pjax less confusing
  • Fixes: Switches the event for calling clearPrefetched to the correct mouse event type

1.0.8 - 2019-01-08

Fixed

  • Fixes: Fixes a bug where links with an empty target attribute would prevent default. Now we only prevent default if target="_blank" #29
  • Fixes: Fixes bug where pjax would break on IE 11 #30

1.0.7 - 2018-12-24

  • Fixes: Fixes this.cache.status bug for non-200 response status

1.0.6 - 2018-12-07

  • Fixes: Sets this.state.history to false by default
  • Fixes: Calls this.handlePushState() on init to replace the default browser history with our custom history #28

1.0.5 - 2018-11-22

  • Fixes: Switches mouseover and mouseout to mouseenter and mouseleave to fix the GET request spam bug #27

1.0.4 - 2018-10-26

  • Adds: Pjax can listen for pjax:continue so developers can use custom page transitions
  • Adds: Pjax custom event documenation
  • Adds: Pjax's pjax:send event is now a CustomEvent and e.details contains the event's triggering element in e.details.el
  • Fixes: Updates the file structure
  • Fixes: Bug where pjax:send wasn't always firing so front-end developers couldn't end their page transitions
  • Fixes: Big where the cacheBust option was always adding a ? to the request even when set to false

1.0.0 - 2018-10-16

  • Adds: XMLHttpRequest page transitions
  • Adds: Switches request to return a promise
  • Adds: Handles non-200 status pages
  • Adds: Better documentation
  • Adds: Updated readme
  • Adds: Prefetches links on mouseover event
  • Adds: Better 'Prevent Default' checks
  • Adds: Converted to Typescript
  • Adds: New changelog