{"id":15434524,"url":"https://github.com/paperstrike/pjax","last_synced_at":"2025-04-19T18:09:54.516Z","repository":{"id":37112187,"uuid":"368879165","full_name":"PaperStrike/Pjax","owner":"PaperStrike","description":"Easily enable fast AJAX navigation (Fetch + pushState)","archived":false,"fork":false,"pushed_at":"2023-05-03T14:58:27.000Z","size":1476,"stargazers_count":25,"open_issues_count":12,"forks_count":3,"subscribers_count":2,"default_branch":"main","last_synced_at":"2025-04-09T21:41:03.311Z","etag":null,"topics":["ajax","fetch","navigation","pjax","pushstate","transition","typescript"],"latest_commit_sha":null,"homepage":"","language":"TypeScript","has_issues":true,"has_wiki":null,"has_pages":null,"mirror_url":null,"source_name":null,"license":"mit","status":null,"scm":"git","pull_requests_enabled":true,"icon_url":"https://github.com/PaperStrike.png","metadata":{"files":{"readme":"README.md","changelog":"CHANGELOG.md","contributing":".github/CONTRIBUTING.md","funding":".github/FUNDING.yml","license":"LICENSE","code_of_conduct":".github/CODE_OF_CONDUCT.md","threat_model":null,"audit":null,"citation":null,"codeowners":null,"security":".github/SECURITY.md","support":null,"governance":null,"roadmap":null,"authors":"AUTHORS","dei":null,"publiccode":null,"codemeta":null},"funding":{"github":null,"patreon":null,"open_collective":null,"ko_fi":null,"tidelift":null,"community_bridge":null,"liberapay":"PaperStrike","issuehunt":null,"otechie":null,"custom":null}},"created_at":"2021-05-19T13:28:57.000Z","updated_at":"2024-11-18T20:46:05.000Z","dependencies_parsed_at":"2024-06-20T22:08:07.073Z","dependency_job_id":null,"html_url":"https://github.com/PaperStrike/Pjax","commit_stats":{"total_commits":254,"total_committers":5,"mean_commits":50.8,"dds":0.547244094488189,"last_synced_commit":"728a62bafdea54373b35001836a2b538f9c8eb23"},"previous_names":[],"tags_count":19,"template":false,"template_full_name":null,"repository_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PaperStrike%2FPjax","tags_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PaperStrike%2FPjax/tags","releases_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PaperStrike%2FPjax/releases","manifests_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories/PaperStrike%2FPjax/manifests","owner_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners/PaperStrike","download_url":"https://codeload.github.com/PaperStrike/Pjax/tar.gz/refs/heads/main","host":{"name":"GitHub","url":"https://github.com","kind":"github","repositories_count":249759083,"owners_count":21321656,"icon_url":"https://github.com/github.png","version":null,"created_at":"2022-05-30T11:31:42.601Z","updated_at":"2022-07-04T15:15:14.044Z","host_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub","repositories_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repositories","repository_names_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/repository_names","owners_url":"https://repos.ecosyste.ms/api/v1/hosts/GitHub/owners"}},"keywords":["ajax","fetch","navigation","pjax","pushstate","transition","typescript"],"created_at":"2024-10-01T18:39:48.958Z","updated_at":"2025-04-19T18:09:54.481Z","avatar_url":"https://github.com/PaperStrike.png","language":"TypeScript","funding_links":["https://liberapay.com/PaperStrike"],"categories":[],"sub_categories":[],"readme":"\u003cdiv align=\"end\"\u003e\u003csub\u003e\n  ENGLISH,\n  \u003ca title=\"Simplified Chinese\" href=\"README.zh-Hans.md\"\u003e简体中文\u003c/a\u003e\n\u003c/sub\u003e\u003c/div\u003e\n\n# ES6+ Pjax\n\n[![Build Status](https://github.com/PaperStrike/Pjax/actions/workflows/test.yml/badge.svg)](https://github.com/PaperStrike/Pjax/actions/workflows/test.yml)\n[![npm Package](https://img.shields.io/npm/v/@sliphua/pjax?logo=npm)](https://www.npmjs.com/package/@sliphua/pjax \"@sliphua/pjax\")\n[![Compressed Minified Size](https://img.badgesize.io/https:/cdn.jsdelivr.net/npm/@sliphua/pjax@latest/dist/pjax.esm.min.js?compression=brotli\u0026label=minzipped\u0026color=ff69b4)](#pick-a-script-in-dist-folder \"dist/pjax.esm.min.js, Brotli compressed\")\n\nEasily enable fast AJAX navigation ([Fetch](https://developer.mozilla.org/en-US/docs/Web/API/Fetch_API) + [pushState](https://developer.mozilla.org/en-US/docs/Web/API/History_API/Working_with_the_History_API)).\n\nPjax aims to deliver _app-like_ browsing experiences. No more full page reloads, no more multiple HTTP requests. It does not rely on other libraries, like jQuery or similar. Written in pure TS, transpiled by [Babel](https://babel.dev/) and [Rollup](https://rollupjs.org/).\n\nA maintained, modern, and smaller version of [MoOx/pjax](https://github.com/MoOx/pjax).\n\n---\n\n🐿️ Jump to [Usage](#usage), [Options](#options), [Status](#status), [Q\u0026A][q-a], or [Contributing Guide][contributing].\n\n## Installation\n\n### Choose a source\n\n#### jsDelivr\n\nVisit [https://www.jsdelivr.com/package/npm/@sliphua/pjax](https://www.jsdelivr.com/package/npm/@sliphua/pjax).\n\n#### npm\n\nInstall package [@sliphua/pjax](https://www.npmjs.com/package/@sliphua/pjax):\n\n```shell\nnpm install @sliphua/pjax\n```\n\n#### Git\n\nClone this repo and install:\n\n```shell\ngit clone https://github.com/PaperStrike/Pjax.git\ncd Pjax\nnpm install\n```\n\n### Pick a script in `dist` folder\n\nEach script file has a related `.map` file, known as the [source map](https://developer.mozilla.org/en-US/docs/Tools/Debugger/How_to/Use_a_source_map), for debugging. Browsers won't fetch them without DevTools opened, so it won't affect your users' experiences. For more information, click the link to find out.\n\n#### To declare globally\n\nLink to `pjax.js` or `pjax.min.js` in a separate `\u003cscript\u003e` tag as:\n\n```html\n\u003cscript src=\"./dist/pjax.js\"\u003e\u003c/script\u003e\n```\n\n#### To import as ES module\n\nImport the default value from `pjax.esm.js` or `pjax.esm.min.js` as:\n\n```js\nimport Pjax from './dist/pjax.esm.js';\n```\n\n## What Pjax Does\n\n_In short, ONE fetch with a `pushState` call._\n\nPjax fetches the new content, updates the URL, switches parts of your page, executes newly added scripts and scroll to the right position _without_ refreshing the whole thing.\n\n## How Pjax Works\n\n1. Listen to simple redirections.\n2. Fetch the target page via `fetch`.\n3. Update current URL using `pushState`.\n4. Render the DOM tree using [`DOMParser`](https://developer.mozilla.org/en-US/docs/Web/API/DOMParser).\n5. Check if defined selectors select the same amount of elements in current DOM and the new DOM.\n    - If no, Pjax uses standard navigation.\n    - If yes, Pjax switches the elements in index order.\n6. Execute all newly-added or targeted scripts in document order.\n7. Scroll to the defined position.\n\n## Overview\n\nJust designate the elements that differs between navigations.\n_Pjax handles all the rest things._\n\nConsider the following page:\n\n```html\n\u003c!DOCTYPE html\u003e\n\u003chtml lang=\"\"\u003e\n\u003chead\u003e\n  \u003ctitle\u003eMy Cool Blog\u003c/title\u003e\n  \u003cmeta name=\"description\" content=\"Welcome to My Cool Blog\"\u003e\n  \u003clink href=\"/styles.css\" rel=\"stylesheet\"\u003e\n\u003c/head\u003e\n\n\u003cbody\u003e\n\u003cheader class=\"header\"\u003e\n  \u003cnav\u003e\n    \u003ca href=\"/\" class=\"is-active\"\u003eHome\u003c/a\u003e\n    \u003ca href=\"/about\"\u003eAbout\u003c/a\u003e\n    \u003ca href=\"/contact\"\u003eContact\u003c/a\u003e\n  \u003c/nav\u003e\n\u003c/header\u003e\n\n\u003csection class=\"content\"\u003e\n  \u003ch1\u003eMy Cool Blog\u003c/h1\u003e\n  \u003cp\u003e\n    Thanks for stopping by!\n\n    \u003ca href=\"/about\"\u003eClick Here to find out more about me.\u003c/a\u003e\n  \u003c/p\u003e\n\u003c/section\u003e\n\n\u003caside class=\"sidebar\"\u003e\n  \u003ch3\u003eRecent Posts\u003c/h3\u003e\n  \u003c!-- sidebar content --\u003e\n\u003c/aside\u003e\n\n\u003cfooter class=\"footer\"\u003e\n  \u0026copy; My Cool Blog\n\u003c/footer\u003e\n\n\u003cscript src=\"onDomReady.js\"\u003e\u003c/script\u003e\n\u003c/body\u003e\n\u003c/html\u003e\n```\n\nWe want Pjax to intercept the URL `/about`, and replace `.content` with the resulting content of the request.\n\nBesides, we would like to replace the `\u003cnav\u003e` to show the active `/about` link, as well as update our page meta and the `\u003caside\u003e` sidebar.\n\nSo all in all we want to update the page title and meta, header, content area, and sidebar, **without reloading styles or scripts**.\n\nWe can easily achieve this by telling Pjax to use such CSS selectors:\n\n```js\nconst pjax = new Pjax({\n  selectors: [\n    'title',\n    'meta[name=description]',\n    '.header',\n    '.content',\n    '.sidebar',\n  ],\n});\n```\n\nNow, when someone in a compatible browser clicks a link, the content selected above will switch to the specific content pieces found in the next page.\n\n_Magic! For real!_ **Nothing server-side!**\n\n## Compatibility\n\nBrowser | Supported versions | Release date\n:------ | :----------------: | -----------:\nChrome  | 66+                | Apr 17, 2018\nEdge    | 79+                | Jan 15, 2020\nFirefox | 60+                | May 9, 2018\nOpera   | 53+                | May 10, 2018\nSafari  | 12.2+              | Jul 22, 2019\n\n## Usage\n\nMethod | Parameters | Return Value\n------ | ---------- | ------------\n[Pjax.constructor](#constructor) | options?: **Partial\\\u003c[Options](#options)\\\u003e** | **Pjax**\n[load](#load) | requestInfo: **[RequestInfo][type-request-info]**, overrideOptions?: **Partial\\\u003c[Options](#options)\\\u003e** | **Promise\\\u003cvoid\\\u003e**\n[weakLoad](#weakload) | requestInfo: **[RequestInfo][type-request-info]**, overrideOptions?: **Partial\\\u003c[Options](#options)\\\u003e** | **Promise\\\u003cvoid\\\u003e**\n[switchDOM](#switchdom) | requestInfo: ****[RequestInfo][type-request-info]****, overrideOptions?: **Partial\\\u003c[Options](#options)\\\u003e** | **Promise\\\u003cvoid\\\u003e**\n[preparePage](#preparepage) | switchesResult: **[SwitchesResult](#type-switchesresult) \u0026#124; null**, overrideOptions?: **Partial\\\u003c[Options](#options)\\\u003e** | **Promise\\\u003cvoid\\\u003e**\n[Pjax.reload](#reload) | / | **void**\n\n[type-request-info]: https://fetch.spec.whatwg.org/#requestinfo\n\n### constructor\n\nThe most basic way to get started.\n\nWhen instantiating `Pjax`, you can pass options into the constructor as an object:\n\n```js\nconst pjax = new Pjax({\n  selectors: [\n    'title',\n    '.header',\n    '.content',\n    '.sidebar',\n  ],\n});\n```\n\nThis will enable Pjax on all links and forms, and designate the part to replace using CSS selectors `'title'`, `'.header'`, `'.content'`, and `'.sidebar'`.\n\nTo disable the default Pjax trigger, set [`defaultTrigger`](#defaulttrigger) option to `false`.\n\n### load\n\nA call to this method aborts the current Pjax action (if any), and navigates to the target resource in Pjax way.\n\nAny error other than `AbortError` leads to the normal navigation (by `window.location.assign`). Note that `AbortError` happens on fetch timeout, too.\n\n```js\nconst pjax = new Pjax();\n\n// use case 1\npjax.load('/your-url').catch(() =\u003e {});\n\n// use case 2 (with options override)\npjax.load('/your-url', { timeout: 200 }).catch(() =\u003e {});\n\n// use case 3 (with further action)\npjax.load('/your-url')\n  .then(() =\u003e {\n    onSuccess();\n  })\n  .catch(() =\u003e {\n    onAbort();\n  });\n\n// use case 4 (with formed Request object)\nconst requestToSend = new Request('/your-url', {\n  method: 'POST',\n  body: 'example',\n});\npjax.load(requestToSend);\n\n// use case X, mix brakets above together\n```\n\n### weakLoad\n\nThis method behaves almost the same as [`load`](#load), except that it throws regardless of the error's type.\n\nUseful when you need to handle all the errors on your own.\n\n```js\nconst pjax = new Pjax();\n\n// use case\npjax.weakLoad('/your-url')\n  .then(() =\u003e {\n    onSuccess();\n  })\n  .catch((e) =\u003e {\n    onError(e);\n  });\n```\n\n### switchDOM\n\nThis method accepts the URL string or the [Request][mdn-request-api] object to fetch. The response should contain the target document.\n\nIt returns a promise that resolves when all the following steps have done:\n\n1. Call `pushState` to update the URL.\n2. Transform elements selected by [`selectors`](#selectors) with switches defined in [`switches`](#switches).\n3. Set _focusCleared_ to `true` if previous step has cleared the page focus, otherwise, `false`.\n4. Call and await [`preparePage`](#preparepage) with a new [SwitchesResult](#type-switchesresult) that contains _focusCleared_.\n\n### preparePage\n\nThis method accepts a nullable [SwitchesResult](#type-switchesresult).\n\nIt returns a promise that resolves when all the following steps have done:\n\n1. Focus the first [`autofocus`](https://developer.mozilla.org/en-US/docs/Web/HTML/Global_attributes/autofocus) if `focusCleared` (in the given switches result) evaluates to `true`.\n2. Execute all newly-loaded and targeted scripts in document order.\n3. Wait until the blocking scripts got executed (e.g., inline scripts).\n4. Scroll to the position given by [`scrollTo`](#scrollto) option.\n\n#### Type SwitchesResult\n\n```ts\ninterface SwitchesResult {\n  focusCleared: boolean\n}\n```\n\n### reload\n\nA helper shortcut for `window.location.reload`, a static member of Pjax.\n\n```js\nPjax.reload();\n```\n\n## Options\n\nName | Type | Default Value\n---- | ---- | ----\n[defaultTrigger](#defaulttrigger) | **boolean \u0026#124; [TriggerOptions](#type-TriggerOptions)** | `true`\n[selectors](#selectors) | **string\\[\\]** | `['title', '.pjax']`\n[switches](#switches) | **Record\u003cstring, [Switch](#type-switch)\u003e** | `{}`\n[scripts](#scripts) | **string** | `script[data-pjax]`\n[scrollTo](#scrollto) | **number \u0026#124; \\[number, number\\] \u0026#124; boolean** | `true`\n[scrollRestoration](#scrollrestoration) | **boolean** | `true`\n[cache](#cache) | **[RequestCache][mdn-request-cache-api]** | `'default'`\n[timeout](#timeout) | **number** | `0`\n[hooks](#hooks) | **[Hooks](#type-hooks)** | `{}`\n\n### defaultTrigger\n\nWhen set to `false` or an object with `enable: false`, disable the default Pjax trigger.\n\nThe default trigger alters these redirections:\n\n- Activations of `\u003ca\u003e` and `\u003carea\u003e` that targets a link within the same origin.\n- Submissions of `\u003cform\u003e` that redirects to a link within the same origin.\n\nDisable when you only need Pjax in some specific moments. E.g.,\n\n```js\n// Set `defaultTrigger` to `false`.\nconst pjax = new Pjax({ defaultTrigger: false });\n\n// Use `load` on your demand.\ndocument.addEventListener('example', (event) =\u003e {\n  if (!needsPjax) return;\n  event.preventDefault();\n  pjax.load('/bingo');\n});\n```\n\nUse the `exclude` sub-option to disable the trigger only for specific elements:\n\n```js\nconst pjax = new Pjax({\n  defaultTrigger: {\n    exclude: 'a[data-no-pjax]',\n  },\n});\n```\n\n#### Type TriggerOptions\n\n```ts\ninterface TriggerOptions {\n  enable?: boolean,\n  exclude?: string,\n}\n```\n\n### selectors\n\nCSS selector list used to target contents to replace. E.g.,\n\n```js\nconst pjax = new Pjax({\n  selectors: [\n    'title',\n    '.content',\n  ],\n});\n```\n\nIf a query returns multiples items, it will just keep the index.\n\nEvery selector, in the current page and new page, must select the same amount of DOM elements. Otherwise, Pjax will fall back into normal page load.\n\n### switches\n\nThis contains callbacks (of type [Switch](#type-switch)) used to switch old elements with new elements.\n\nThe object keys should match one of the defined selectors (from the [`selectors`](#selectors) option).\n\nExamples:\n\n```js\nconst pjax = new Pjax({\n  selectors: ['title', '.Navbar', '.pjax'],\n  switches: {\n    // default behavior\n    'title': Pjax.switches.default,\n    '.content': async (oldEle, newEle) =\u003e {\n      // How you deal with the two elements.\n    },\n    '.pjax': Pjax.switches.innerText,\n  },\n});\n```\n\n#### Type Switch\n\n```ts\ntype Switch\u003cT extends Element = Element\u003e = (oldEle: T, newEle: T) =\u003e (Promise\u003cvoid\u003e | void);\n```\n\nWhen it returns a promise, Pjax recognizes when the switch has done. Newly added scripts execute and labeled scripts re-execute after all switches finishes.\n\n#### Existing Switch Callbacks\n\n- `Pjax.switches.default` —\n  The default behavior, same as `Pjax.switches.replaceWith`.\n- `Pjax.switches.innerHTML` —\n  Replace HTML contents by using [`Element.innerHTML`](https://developer.mozilla.org/en-US/docs/Web/API/Element/innerHTML).\n- `Pjax.switches.textContent` —\n  Replace all text by using [`Node.textContent`](https://developer.mozilla.org/en-US/docs/Web/API/Node/textContent).\n- `Pjax.switches.innerText` —\n  Replace readable text by using [`HTMLElement.innerText`](https://developer.mozilla.org/en-US/docs/Web/API/HTMLElement/innerText).\n- `Pjax.switches.attributes` —\n  Rewrite all attributes, leaving inner HTML untouched.\n- `Pjax.switches.replaceWith` —\n  Replace elements by using [`ChildNode.replaceWith`](https://developer.mozilla.org/en-US/docs/Web/API/ChildNode/replaceWith).\n\n#### Creating a Switch Callback\n\nYour callback function can do whatever you want. But remember to keep the amount of the elements selected by the [`selectors`](#selectors) option remain the same.\n\nIn the example below, `.current` class marks the only switching element, so that the switch elements' amount won't change. Before the returned promise resolves, Pjax will neither execute the script elements nor scroll the page.\n\n```js\nconst pjax = new Pjax({\n  selectors: ['.sidebar.current'],\n});\n\nconst customSwitch = (oldEle, newEle) =\u003e {\n  oldEle.classList.remove('current');\n  newEle.classList.add('current');\n  oldEle.after(newEle);\n\n  return new Promise((resolve) =\u003e {\n    // Assume there's animations start right after inserting to DOM.\n    newEle.addEventListener('animationend', () =\u003e {\n      oldEle.remove();\n      resolve();\n    }, { once: true });\n  });\n};\n```\n\n**NOTE:** _Pjax waits for the switches, but moves on to the next navigation, and forgets the previous one, on matter whether finished or not. Workarounds that try to block user actions may not work as well as hoped, because the user can always use the \"back\" button, and Pjax always reacts to it._\n\n### scripts\n\nCSS selector used to target **extra** `\u003cscript\u003e` to execute after a page switch. For multiple selectors, separate them by a comma. Use the empty string to target nothing. Like:\n\n```js\n// Single selector\nconst pjax = new Pjax({\n  scripts: 'script.pjax',\n});\n```\n\n```js\n// Multiple selectors\nconst pjax = new Pjax({\n  scripts: 'script.pjax, script.analytics',\n});\n```\n\n```js\n// Only execute new scripts\nconst pjax = new Pjax({\n  scripts: '',\n});\n```\n\n**NOTE:** _Pjax always executes the newly added scripts in a page switch. You don't have to mark them here._\n\n### scrollTo\n\nWhen set to a number, this represents the vertical value (in px from the top of the page) to scroll to after a page switch.\n\nWhen set to an array of 2 numbers (\\[x, y\\]), this contains the horizontal and vertical values to scroll to after a page switch.\n\nSet this to `true` to make Pjax decide the scroll position. Pjax will try to act as the browsers' default behavior. For example, scroll the element into view when hash changing to its id, scroll to page left top when navigating to a new page without a valid hash.\n\nSet this to `false` to disable all scrolling by Pjax.\n\n**NOTE:** _This does not affect the scroll restoration defined below._\n\n### scrollRestoration\n\nWhen set to `true`, Pjax attempts to restore the page scroll status when navigating backward or forward.\n\n### cache\n\nThis contains the cache mode of Pjax requests, which shares the same available values with [`Request.cache`][mdn-request-cache-api].\n\n### timeout\n\nThe time in _milliseconds_ to abort the fetch requests. Set to `0` to disable.\n\n### hooks\n\nThis option defines hooks (each of type [Hook](#type-hook)) for modifying the [_request_][mdn-request-api] sent, the [_response_][mdn-response-api] received, the [_document_][mdn-document-api] parsed and the [_switchResult_](#type-switchesresult) created in Pjax. An example for adding a custom header for Pjax requests:\n\n```js\nconst pjax = new Pjax({\n  hooks: {\n    request: (request) =\u003e {\n      request.headers.set('My-Custom-Header', 'ready');\n    },\n  },\n});\n```\n\n#### Type Hook\n\nA function that returns `undefined`, the hooked input, or a promise resolving to one of them.\n\n```ts\ntype Hook\u003cT\u003e = (input: T) =\u003e T | void | Promise\u003cT | void\u003e;\n```\n\n#### Type Hooks\n\n```ts\ninterface Hooks {\n  request?: Hook\u003cRequest\u003e;\n  response?: Hook\u003cResponse\u003e;\n  document?: Hook\u003cDocument\u003e;\n  switchesResult?: Hook\u003cSwitchesResult\u003e;\n}\n```\n\n## Status\n\nAccessible by calling on the Pjax instance.\n\nName | Type | Default Value\n---- | ---- | ----\n[location](#location) | **[URL][mdn-url-api]** | `new URL(window.location.href)`\n[abortController](#abortcontroller) | **[AbortController][mdn-abortcontroller-api] \u0026#124; null** | `null`\n\n### location\n\nThe last location recognized by Pjax.\n\n### abortController\n\nThe abort controller that can abort the Pjax handling navigation. When Pjax handles nothing, `null`.\n\nFor example, to abort Pjax on certain events:\n\n```js\nconst pjax = new Pjax();\n\ndocument.addEventListener('example', () =\u003e {\n  pjax.abortController?.abort();\n});\n```\n\n## Events\n\nWhen calling Pjax, Pjax may fire a number of events.\n\nAll events fire from the _document_, not the clicked anchor nor the caller function. You can get more detail of the event via `event.detail`.\n\nAn ordered list showing the types of these events, and the moment they happen:\n\n1. `pjax:send` event when Pjax sends the request.\n2. `pjax:receive` event when Pjax receives the response.\n3. Pjax switches the DOM. See [`switchDOM`](#switchdom) method for details.\n4. `pjax:error` event if any error happens to previous steps.\n5. `pjax:complete` event when previous steps finish.\n6. `pjax:success` event if previous steps finish without any error.\n\nIf you use a loading indicator (e.g. [topbar](https://buunguyen.github.io/topbar/)), a pair of `send` and `complete` events may suit you well.\n\n```js\ndocument.addEventListener('pjax:send', topbar.show);\ndocument.addEventListener('pjax:complete', topbar.hide);\n```\n\n## HTTP Headers\n\nPjax uses several custom headers when it sends HTTP requests.\n\n- `X-Requested-With: Fetch`\n- `X-PJAX: true`\n- `X-PJAX-Selectors` —\n  A serialized JSON array of selectors, taken from [`selectors`](#selectors). You can use this to send back only the elements that Pjax will use to switch, instead of sending the whole page. Note that you may need to deserialize this on the server (Such as by using `JSON.parse`)\n\n## DOM Ready State\n\nMost of the time, you will have code related to the current DOM that you only execute when the DOM became ready.\n\nSince Pjax doesn't trigger the standard DOM ready events, you'll need to add code to re-trigger the DOM ready code. For example:\n\n```js\nfunction whenDOMReady() {\n  // do your stuff\n}\n\ndocument.addEventListener('DOMContentLoaded', whenDOMReady);\n\nconst pjax = new Pjax();\n\ndocument.addEventListener('pjax:success', whenDOMReady);\n```\n\n**NOTE:** _Don't instantiate Pjax in the `whenDOMReady` function._\n\n## [Q\u0026A][q-a]\n\n## [CONTRIBUTING][contributing]\n\n## [CHANGELOG](CHANGELOG.md)\n\n## [LICENSE](LICENSE)\n\n[mdn-document-api]: https://developer.mozilla.org/en-US/docs/Web/API/Document\n[mdn-request-api]: https://developer.mozilla.org/en-US/docs/Web/API/Request\n[mdn-request-cache-api]: https://developer.mozilla.org/en-US/docs/Web/API/Request/cache\n[mdn-response-api]: https://developer.mozilla.org/en-US/docs/Web/API/Response\n[mdn-url-api]: https://developer.mozilla.org/en-US/docs/Web/API/URL\n[mdn-abortcontroller-api]: https://developer.mozilla.org/en-US/docs/Web/API/AbortController\n\n[q-a]: https://github.com/PaperStrike/Pjax/discussions/categories/q-a\n[contributing]: https://github.com/PaperStrike/Pjax/blob/main/.github/CONTRIBUTING.md\n","project_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpaperstrike%2Fpjax","html_url":"https://awesome.ecosyste.ms/projects/github.com%2Fpaperstrike%2Fpjax","lists_url":"https://awesome.ecosyste.ms/api/v1/projects/github.com%2Fpaperstrike%2Fpjax/lists"}