Top Related Projects
Classic version of Turbolinks. Now deprecated in favor of Turbolinks 5.
Classic version of Turbolinks. Now deprecated in favor of Turbolinks 5.
The speed of a single-page web application without having to write any JavaScript
A full-stack framework for Laravel that takes the pain out of building dynamic UIs.
A rugged, minimal framework for composing JavaScript behavior in your markup.
A collection of composable behaviors for your Stimulus Controllers
Quick Overview
The jquery-pjax
library is a jQuery plugin that enables PJAX (Pushstate-based Ajax) functionality, allowing for smooth and efficient page transitions without a full page reload. It provides a way to load content from the server via Ajax and update the current page's URL, creating a seamless user experience.
Pros
- Improved User Experience: PJAX enables faster page loads and a more responsive website, as only the necessary content is loaded, rather than the entire page.
- Reduced Server Load: By only loading the required content, the server's workload is reduced, leading to better overall performance.
- Easier Bookmarking and Sharing: PJAX-enabled pages can be bookmarked and shared with the correct URL, as the URL is updated with each page transition.
- Progressive Enhancement: The library gracefully degrades, providing a standard page load experience for browsers that do not support PJAX.
Cons
- Complexity: Integrating PJAX into an existing website can be more complex than a traditional page load approach, requiring additional setup and configuration.
- Potential Compatibility Issues: PJAX may not work seamlessly with all server-side frameworks and content management systems, requiring additional customization.
- Debugging Challenges: Troubleshooting issues related to PJAX can be more challenging, as the behavior is different from a standard page load.
- Limited Functionality: PJAX is primarily focused on page transitions and may not provide the same level of functionality as a full-featured single-page application (SPA) framework.
Code Examples
Here are a few examples of how to use the jquery-pjax
library:
- Basic PJAX Setup:
$(document).pjax('a', '#pjax-container');
This code sets up PJAX to automatically handle clicks on all <a>
tags, loading the content into the element with the ID #pjax-container
.
- Handling PJAX Events:
$(document).on('pjax:send', function() {
// Show a loading indicator
$('#loading-indicator').show();
});
$(document).on('pjax:complete', function() {
// Hide the loading indicator
$('#loading-indicator').hide();
});
This code demonstrates how to listen for the pjax:send
and pjax:complete
events, which can be used to show and hide a loading indicator during the PJAX request.
- Manually Triggering a PJAX Request:
$.pjax({
url: '/new-page',
container: '#pjax-container'
});
This code shows how to manually trigger a PJAX request, specifying the URL and the container element to update.
- Handling PJAX Errors:
$(document).on('pjax:error', function(xhr, textStatus, error) {
// Handle PJAX errors
console.error('PJAX error:', error);
});
This code demonstrates how to listen for the pjax:error
event, which is triggered when a PJAX request encounters an error.
Getting Started
To get started with jquery-pjax
, follow these steps:
- Include the jQuery library and the
jquery-pjax
plugin in your HTML file:
<script src="https://code.jquery.com/jquery-3.6.0.min.js"></script>
<script src="https://cdnjs.cloudflare.com/ajax/libs/jquery.pjax/2.0.1/jquery.pjax.min.js"></script>
- Set up PJAX on your page by selecting the links and the container element to update:
$(document).pjax('a', '#pjax-container');
- (Optional) Handle PJAX events, such as showing and hiding a loading indicator:
$(document).on('pjax:send', function() {
$('#loading-indicator').show();
});
$(document).on('pjax:complete', function() {
$('#loading-indicator
Competitor Comparisons
Classic version of Turbolinks. Now deprecated in favor of Turbolinks 5.
Pros of Turbolinks Classic
- Works with any backend framework, not limited to Ruby on Rails
- Automatically handles browser history and URL changes
- Supports progress bar for page loads
Cons of Turbolinks Classic
- Can interfere with JavaScript events and DOM manipulation
- Requires more configuration for complex applications
- May cause issues with third-party JavaScript libraries
Code Comparison
Turbolinks Classic:
// No need for explicit initialization
document.addEventListener("turbolinks:load", function() {
// Your code here
});
jQuery-pjax:
$(document).pjax('a', '#pjax-container')
$(document).on('pjax:end', function() {
// Your code here
});
Key Differences
- Turbolinks Classic replaces the entire
<body>
by default, while jQuery-pjax allows for partial page updates - Turbolinks Classic uses the History API directly, whereas jQuery-pjax relies on jQuery for AJAX and history management
- jQuery-pjax requires explicit initialization and container specification, while Turbolinks Classic works globally by default
Use Cases
- Turbolinks Classic: Ideal for Ruby on Rails applications or projects seeking a drop-in solution for faster page loads
- jQuery-pjax: Better suited for applications requiring fine-grained control over partial page updates or those already using jQuery extensively
Both libraries aim to improve perceived page load times and create a smoother user experience in web applications. The choice between them depends on specific project requirements and existing technology stack.
Classic version of Turbolinks. Now deprecated in favor of Turbolinks 5.
Pros of Turbolinks Classic
- Works with any backend framework, not limited to Ruby on Rails
- Automatically handles browser history and URL changes
- Supports progress bar for page loads
Cons of Turbolinks Classic
- Can interfere with JavaScript events and DOM manipulation
- Requires more configuration for complex applications
- May cause issues with third-party JavaScript libraries
Code Comparison
Turbolinks Classic:
// No need for explicit initialization
document.addEventListener("turbolinks:load", function() {
// Your code here
});
jQuery-pjax:
$(document).pjax('a', '#pjax-container')
$(document).on('pjax:end', function() {
// Your code here
});
Key Differences
- Turbolinks Classic replaces the entire
<body>
by default, while jQuery-pjax allows for partial page updates - Turbolinks Classic uses the History API directly, whereas jQuery-pjax relies on jQuery for AJAX and history management
- jQuery-pjax requires explicit initialization and container specification, while Turbolinks Classic works globally by default
Use Cases
- Turbolinks Classic: Ideal for Ruby on Rails applications or projects seeking a drop-in solution for faster page loads
- jQuery-pjax: Better suited for applications requiring fine-grained control over partial page updates or those already using jQuery extensively
Both libraries aim to improve perceived page load times and create a smoother user experience in web applications. The choice between them depends on specific project requirements and existing technology stack.
The speed of a single-page web application without having to write any JavaScript
Pros of Turbo
- Framework-agnostic and doesn't require jQuery, making it more versatile and lightweight
- Offers more advanced features like lazy-loading and form handling out of the box
- Actively maintained with regular updates and improvements
Cons of Turbo
- Steeper learning curve due to more complex API and concepts
- May require more setup and configuration for optimal performance
- Potentially overkill for simpler projects that don't need all its features
Code Comparison
Turbo:
import { Turbo } from "@hotwired/turbo-rails"
Turbo.start()
jQuery-pjax:
$(document).pjax('a', '#pjax-container')
Key Differences
- Turbo is a more modern and comprehensive solution for building responsive web applications
- jQuery-pjax is simpler and easier to implement for basic AJAX navigation
- Turbo offers a wider range of features and better performance, but may be more complex to set up
- jQuery-pjax relies on jQuery, while Turbo is framework-independent
Use Cases
- Choose Turbo for larger, more complex applications that require advanced features and performance optimizations
- Opt for jQuery-pjax in smaller projects or when working with existing jQuery-based codebases for quick AJAX navigation implementation
A full-stack framework for Laravel that takes the pain out of building dynamic UIs.
Pros of Livewire
- Full-stack framework with server-side rendering, offering more comprehensive functionality
- Seamless integration with Laravel, providing a cohesive development experience
- Real-time updates without writing JavaScript, simplifying development
Cons of Livewire
- Steeper learning curve due to its more complex architecture
- Potentially higher server load as more processing occurs on the backend
Code Comparison
Livewire component:
class SearchUsers extends Component
{
public $search = '';
public function render()
{
return view('livewire.search-users', [
'users' => User::where('name', 'like', "%{$this->search}%")->get(),
]);
}
}
jQuery-pjax usage:
$(document).pjax('a', '#pjax-container')
$(document).on('submit', 'form', function(event) {
$.pjax.submit(event, '#pjax-container')
})
Summary
Livewire offers a more comprehensive solution for building dynamic interfaces, particularly within the Laravel ecosystem. It provides real-time updates and server-side rendering without the need for custom JavaScript. However, it may have a steeper learning curve and potentially higher server load compared to the simpler, client-side approach of jQuery-pjax. The choice between the two depends on the project's requirements, the development team's expertise, and the desired level of integration with the backend framework.
A rugged, minimal framework for composing JavaScript behavior in your markup.
Pros of Alpine
- Lightweight and minimal, with no dependencies
- More modern approach to reactive JavaScript
- Broader functionality beyond just AJAX navigation
Cons of Alpine
- Steeper learning curve for developers used to jQuery
- Less focused on specific PJAX functionality
- Potentially overkill for simple AJAX navigation needs
Code Comparison
Alpine:
<div x-data="{ open: false }">
<button @click="open = true">Open</button>
<div x-show="open">Content</div>
</div>
jquery-pjax:
$(document).pjax('a', '#pjax-container')
Key Differences
- Alpine is a more comprehensive framework for building interactive UIs, while jquery-pjax focuses specifically on AJAX-powered navigation
- Alpine uses a declarative syntax directly in HTML, whereas jquery-pjax relies on jQuery selectors and method calls
- Alpine offers more flexibility for complex interactions, but jquery-pjax provides a simpler solution for its specific use case
Use Cases
- Choose Alpine for modern, reactive web applications with various interactive elements
- Opt for jquery-pjax when you need a straightforward solution for AJAX navigation in jQuery-based projects
Community and Maintenance
- Alpine has a growing, active community and regular updates
- jquery-pjax, while stable, has less frequent updates and a more mature but potentially smaller user base
A collection of composable behaviors for your Stimulus Controllers
Pros of stimulus-use
- Built for modern JavaScript frameworks, specifically Stimulus
- Offers a wider range of utilities and behaviors beyond just PJAX
- Actively maintained with regular updates and community support
Cons of stimulus-use
- Requires Stimulus framework, limiting its use in non-Stimulus projects
- Steeper learning curve for developers not familiar with Stimulus
- May introduce unnecessary complexity for simple PJAX-like functionality
Code Comparison
stimulus-use example:
import { useIntersection } from 'stimulus-use'
export default class extends Controller {
connect() {
useIntersection(this)
}
appear(entry) {
// Handle element appearance
}
}
jquery-pjax example:
$(document).pjax('a', '#pjax-container')
$(document).on('pjax:success', function() {
// Handle successful PJAX load
})
Summary
stimulus-use is a modern, feature-rich library built for Stimulus, offering a wide range of utilities beyond PJAX. It's actively maintained but requires the Stimulus framework. jquery-pjax, on the other hand, is a simpler, more focused library for PJAX functionality, compatible with jQuery-based projects. The choice between the two depends on the project's framework, complexity requirements, and desired features.
Convert
designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual CopilotREADME
pjax = pushState + ajax
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.
pjax works by fetching HTML from your server via ajax and replacing the content of a container element on your page with the loaded HTML. It then updates the current URL in the browser using pushState. This results in faster page navigation for two reasons:
- No page resources (JS, CSS) get re-executed or re-applied;
- If the server is configured for pjax, it can render only partial page contents and thus avoid the potentially costly full layout render.
Status of this project
jquery-pjax is largely unmaintained at this point. It might continue to receive important bug fixes, but its feature set is frozen and it's unlikely that it will get new features or enhancements.
Installation
pjax depends on jQuery 1.8 or higher.
npm
$ npm install jquery-pjax
standalone script
Download and include jquery.pjax.js
in your web page:
curl -LO https://raw.github.com/defunkt/jquery-pjax/master/jquery.pjax.js
Usage
$.fn.pjax
The simplest and most common use of pjax looks like this:
$(document).pjax('a', '#pjax-container')
This will enable pjax on all links on the page and designate the container as #pjax-container
.
If you are migrating an existing site, you probably don't want to enable pjax
everywhere just yet. Instead of using a global selector like a
, try annotating
pjaxable links with data-pjax
, then use 'a[data-pjax]'
as your selector. Or,
try this selector that matches any <a data-pjax href=>
links inside a <div data-pjax>
container:
$(document).pjax('[data-pjax] a, a[data-pjax]', '#pjax-container')
Server-side configuration
Ideally, your server should detect pjax requests by looking at the special
X-PJAX
HTTP header, and render only the HTML meant to replace the contents of
the container element (#pjax-container
in our example) without the rest of
the page layout. Here is an example of how this might be done in Ruby on Rails:
def index
if request.headers['X-PJAX']
render :layout => false
end
end
If you'd like a more automatic solution than pjax for Rails check out Turbolinks.
Check if there is a pjax plugin for your favorite server framework.
Also check out RailsCasts #294: Playing with PJAX.
Arguments
The synopsis for the $.fn.pjax
function is:
$(document).pjax(selector, [container], options)
selector
is a string to be used for click event delegation.container
is a string selector that uniquely identifies the pjax container.options
is an object with keys described below.
pjax options
key | default | description |
---|---|---|
timeout | 650 | ajax timeout in milliseconds after which a full refresh is forced |
push | true | use pushState to add a browser history entry upon navigation |
replace | false | replace URL without adding browser history entry |
maxCacheLength | 20 | maximum cache size for previous container contents |
version | a string or function returning the current pjax version | |
scrollTo | 0 | vertical position to scroll to after navigation. To avoid changing scroll position, pass false . |
type | "GET" | see $.ajax |
dataType | "html" | see $.ajax |
container | CSS selector for the element where content should be replaced | |
url | link.href | a string or function that returns the URL for the ajax request |
target | link | eventually the relatedTarget value for pjax events |
fragment | CSS selector for the fragment to extract from ajax response |
You can change the defaults globally by writing to the $.pjax.defaults
object:
$.pjax.defaults.timeout = 1200
$.pjax.click
This is a lower level function used by $.fn.pjax
itself. It allows you to get a little more control over the pjax event handling.
This example uses the current click context to set an ancestor element as the container:
if ($.support.pjax) {
$(document).on('click', 'a[data-pjax]', function(event) {
var container = $(this).closest('[data-pjax-container]')
var containerSelector = '#' + container.id
$.pjax.click(event, {container: containerSelector})
})
}
NOTE Use the explicit $.support.pjax
guard. We aren't using $.fn.pjax
so we should avoid binding this event handler unless the browser is actually going to use pjax.
$.pjax.submit
Submits a form via pjax.
$(document).on('submit', 'form[data-pjax]', function(event) {
$.pjax.submit(event, '#pjax-container')
})
$.pjax.reload
Initiates a request for the current URL to the server using pjax mechanism and replaces the container with the response. Does not add a browser history entry.
$.pjax.reload('#pjax-container', options)
$.pjax
Manual pjax invocation. Used mainly when you want to start a pjax request in a handler that didn't originate from a click. If you can get access to a click event
, consider $.pjax.click(event)
instead.
function applyFilters() {
var url = urlForFilters()
$.pjax({url: url, container: '#pjax-container'})
}
Events
All pjax events except pjax:click
& pjax:clicked
are fired from the pjax
container element.
event | cancel | arguments | notes |
---|---|---|---|
event lifecycle upon following a pjaxed link | |||
pjax:click |
âï¸ | options |
fires from a link that got activated; cancel to prevent pjax |
pjax:beforeSend |
âï¸ | xhr, options |
can set XHR headers |
pjax:start |
xhr, options |
||
pjax:send |
xhr, options |
||
pjax:clicked |
options |
fires after pjax has started from a link that got clicked | |
pjax:beforeReplace |
contents, options |
before replacing HTML with content loaded from the server | |
pjax:success |
data, status, xhr, options |
after replacing HTML content loaded from the server | |
pjax:timeout |
âï¸ | xhr, options |
fires after options.timeout ; will hard refresh unless canceled |
pjax:error |
âï¸ | xhr, textStatus, error, options |
on ajax error; will hard refresh unless canceled |
pjax:complete |
xhr, textStatus, options |
always fires after ajax, regardless of result | |
pjax:end |
xhr, options |
||
event lifecycle on browser Back/Forward navigation | |||
pjax:popstate |
event direction property: "back"/"forward" |
||
pjax:start |
null, options |
before replacing content | |
pjax:beforeReplace |
contents, options |
right before replacing HTML with content from cache | |
pjax:end |
null, options |
after replacing content |
pjax:send
& pjax:complete
are a good pair of events to use if you are implementing a
loading indicator. They'll only be triggered if an actual XHR request is made,
not if the content is loaded from cache:
$(document).on('pjax:send', function() {
$('#loading').show()
})
$(document).on('pjax:complete', function() {
$('#loading').hide()
})
An example of canceling a pjax:timeout
event would be to disable the fallback
timeout behavior if a spinner is being shown:
$(document).on('pjax:timeout', function(event) {
// Prevent default timeout redirection behavior
event.preventDefault()
})
Advanced configuration
Reinitializing plugins/widget on new page content
The whole point of pjax is that it fetches and inserts new content without
refreshing the page. However, other jQuery plugins or libraries that are set to
react on page loaded event (such as DOMContentLoaded
) will not pick up on
these changes. Therefore, it's usually a good idea to configure these plugins to
reinitialize in the scope of the updated page content. This can be done like so:
$(document).on('ready pjax:end', function(event) {
$(event.target).initializeMyPlugin()
})
This will make $.fn.initializeMyPlugin()
be called at the document level on
normal page load, and on the container level after any pjax navigation (either
after clicking on a link or going Back in the browser).
Response types that force a reload
By default, pjax will force a full reload of the page if it receives one of the following responses from the server:
-
Page content that includes
<html>
whenfragment
selector wasn't explicitly configured. Pjax presumes that the server's response hasn't been properly configured for pjax. Iffragment
pjax option is given, pjax will extract the content based on that selector. -
Page content that is blank. Pjax assumes that the server is unable to deliver proper pjax contents.
-
HTTP response code that is 4xx or 5xx, indicating some server error.
Affecting the browser URL
If the server needs to affect the URL which will appear in the browser URL after
pjax navigation (like HTTP redirects work for normal requests), it can set the
X-PJAX-URL
header:
def index
request.headers['X-PJAX-URL'] = "http://example.com/hello"
end
Layout Reloading
Layouts can be forced to do a hard reload when assets or html changes.
First set the initial layout version in your header with a custom meta tag.
<meta http-equiv="x-pjax-version" content="v123">
Then from the server side, set the X-PJAX-Version
header to the same.
if request.headers['X-PJAX']
response.headers['X-PJAX-Version'] = "v123"
end
Deploying a deploy, bumping the version constant to force clients to do a full reload the next request getting the new layout and assets.
Top Related Projects
Classic version of Turbolinks. Now deprecated in favor of Turbolinks 5.
Classic version of Turbolinks. Now deprecated in favor of Turbolinks 5.
The speed of a single-page web application without having to write any JavaScript
A full-stack framework for Laravel that takes the pain out of building dynamic UIs.
A rugged, minimal framework for composing JavaScript behavior in your markup.
A collection of composable behaviors for your Stimulus Controllers
Convert
designs to code with AI
Introducing Visual Copilot: A new AI model to turn Figma designs to high quality code using your components.
Try Visual Copilot