Code cleanup (#120)
* Lots of code cleanup * Cleanup parse-options tests - Rename objects for clarity and inline unneeded objects - Remove unneeded tests - Use Object.keys().length instead of a custom function - Use typeof === "object" instead of a custom function that checks the prototype tree as well, since we don't expect anything but an object literal. * Remove old switchFallback code * Remove polyfill for Function.prototype.bind * Inline small functions * Add more documentation and tests for options.currentUrlFullReload Closes #17 * Update package.json
This commit was merged in pull request #120.
This commit is contained in:
240
README.md
240
README.md
@@ -2,18 +2,18 @@
|
|||||||
|
|
||||||
[](https://travis-ci.org/MoOx/pjax).
|
[](https://travis-ci.org/MoOx/pjax).
|
||||||
|
|
||||||
> Easily enable fast Ajax navigation on any website (using pushState + xhr)
|
> Easily enable fast AJAX navigation on any website (using pushState() + XHR)
|
||||||
|
|
||||||
Pjax is ~~a jQuery plugin~~ **a standalone JavaScript module** that uses
|
Pjax is ~~a jQuery plugin~~ **a standalone JavaScript module** that uses
|
||||||
ajax (XmlHttpRequest) and
|
AJAX (XmlHttpRequest) and
|
||||||
[pushState()](https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Manipulating_the_browser_history)
|
[pushState()](https://developer.mozilla.org/en-US/docs/Web/Guide/API/DOM/Manipulating_the_browser_history)
|
||||||
to deliver a fast browsing experience.
|
to deliver a fast browsing experience.
|
||||||
|
|
||||||
_It allow you to completely transform user experience of standard websites
|
_It allows you to completely transform the user experience of standard websites
|
||||||
(server side generated or static ones) to make them feel they browse an app.
|
(server-side generated or static ones) to make them feel like they are browsing an app,
|
||||||
Especially for user that have low bandwidth connection._
|
especially for users with low bandwidth connection._
|
||||||
|
|
||||||
**No more full page reload. No more lots of HTTP request.**
|
**No more full page reloads. No more multiple HTTP requests.**
|
||||||
|
|
||||||
## Demo
|
## Demo
|
||||||
|
|
||||||
@@ -21,7 +21,7 @@ Especially for user that have low bandwidth connection._
|
|||||||
|
|
||||||
## Installation
|
## Installation
|
||||||
|
|
||||||
- You can install pjax from **npm**:
|
- You can install Pjax from **npm**:
|
||||||
```shell
|
```shell
|
||||||
npm install pjax
|
npm install pjax
|
||||||
```
|
```
|
||||||
@@ -37,45 +37,47 @@ Especially for user that have low bandwidth connection._
|
|||||||
|
|
||||||
## No dependencies
|
## No dependencies
|
||||||
|
|
||||||
_There is nothing you need. No jQuery or something._
|
_Pjax does not rely on other libraries, like jQuery or similar. It is written entirely in vanilla JS._
|
||||||
|
|
||||||
## How Pjax works
|
## How Pjax works
|
||||||
|
|
||||||
Pjax loads page using ajax & updates the browser's current url using pushState without reloading your page's layout or any resources (js, css), giving a fast page load.
|
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.
|
||||||
_But under the hood, it's just ONE http request with a pushState() call._
|
|
||||||
Obviously, for [browsers that don't support pushState()](http://caniuse.com/#search=pushstate) Pjax fully degrades (yeah, it doesn't do anything at all).
|
|
||||||
|
|
||||||
It simply works with all permalinks & can update all parts of the page you
|
_But under the hood, it's just ONE HTTP request with a `pushState()` call._
|
||||||
want (including html metas, title, navigation state).
|
|
||||||
|
|
||||||
- It's not limited to one container, like jQuery-Pjax is,
|
Obviously, for [browsers that don't support `history.pushState()`](http://caniuse.com/#search=pushstate) Pjax gracefully degrades and does not do anything at all.
|
||||||
- It fully support browser history (back & forward buttons),
|
|
||||||
- It **will** support keyboard browsing (@todo),
|
It simply works with all permalinks and can update all parts of the page you
|
||||||
- Automatically fallback to classic navigation for externals pages (thanks to Capitain Obvious help),
|
want (including HTML metas, title, and navigation state).
|
||||||
- Automatically fallback to classic navigation for internals pages that will not have the appropriated DOM tree,
|
|
||||||
|
- It's not limited to one container, like jQuery-Pjax is.
|
||||||
|
- It fully supports browser history (back and forward buttons).
|
||||||
|
- It 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.
|
||||||
- You can add pretty cool CSS transitions (animations) very easily.
|
- You can add pretty cool CSS transitions (animations) very easily.
|
||||||
- It's around 3kb (minified & gzipped).
|
- It's around 4kb (minified and gzipped).
|
||||||
|
|
||||||
### Under the hood
|
### Under the hood
|
||||||
|
|
||||||
- It listen to every clicks on links _you want_ (by default all of them),
|
- It listens to every click on links _you want_ (by default all of them).
|
||||||
- When an internal link is clicked, Pjax grabs HTML from your server via ajax,
|
- When an internal link is clicked, Pjax grabs HTML from your server via AJAX.
|
||||||
- Pjax render pages DOM tree (without loading any resources - images, css, js...)
|
- Pjax renders the page's DOM tree (without loading any resources - images, CSS, JS...).
|
||||||
- It check if all defined parts can be replaced:
|
- It checks that all defined parts can be replaced:
|
||||||
- if page doesn't suit requirement, classic navigation used,
|
- If the page doesn't meet the requirements, standard navigation is used.
|
||||||
- if page suits requirement, Pjax does all defined DOM replacements
|
- If the page meets the requirements, Pjax does all defined DOM replacements.
|
||||||
- Then, it updates the browser's current url using pushState
|
- Then it updates the browser's current URL using `pushState()`.
|
||||||
|
|
||||||
## Overview
|
## Overview
|
||||||
|
|
||||||
Pjax is fully automatic. You won't need to setup anything on the existing HTML.
|
Pjax is fully automatic. You don't need to setup anything in the existing HTML.
|
||||||
You just need to designate some elements on your page that will be replaced when
|
You just need to designate some elements on your page that will be replaced when
|
||||||
you navigate your site.
|
you navigate your site.
|
||||||
|
|
||||||
Consider the following page.
|
Consider the following page.
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<!doctype html>
|
<!DOCTYPE html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<!-- metas, title, styles, ... -->
|
<!-- metas, title, styles, ... -->
|
||||||
@@ -93,7 +95,7 @@ Consider the following page.
|
|||||||
</html>
|
</html>
|
||||||
```
|
```
|
||||||
|
|
||||||
We want Pjax to grab the url `/blah` then replace `.my-Content` with whatever it gets back.
|
We want Pjax to intercept the URL `/blah`, and replace `.my-Content` with the results of the request.
|
||||||
Oh and the `<nav>` (that contains a status marker somewhere) can be updated too (or stay the same, as you wish).
|
Oh and the `<nav>` (that contains a status marker somewhere) can be updated too (or stay the same, as you wish).
|
||||||
And also the `<aside>` please.
|
And also the `<aside>` please.
|
||||||
So we want to update `[".my-Header", ".my-Content", ".my-Sidebar"]`, **without reloading styles nor scripts**.
|
So we want to update `[".my-Header", ".my-Content", ".my-Sidebar"]`, **without reloading styles nor scripts**.
|
||||||
@@ -104,23 +106,23 @@ We do this by telling Pjax to listen on `a` tags and use CSS selectors defined a
|
|||||||
new Pjax({ selectors: ["title", ".my-Header", ".my-Content", ".my-Sidebar"] })
|
new Pjax({ selectors: ["title", ".my-Header", ".my-Content", ".my-Sidebar"] })
|
||||||
```
|
```
|
||||||
|
|
||||||
Now when someone in a Pjax-compatible browser clicks "blah" the content of all selectors will be replaced with the one found in the "blah" content.
|
Now, when someone in a Pjax-compatible browser clicks "blah", the content of all selectors will be replaced with the one found in the "blah" content.
|
||||||
|
|
||||||
_Magic! For real!_ **There is completely no need to do anything on server side!**
|
_Magic! For real!_ **There is no need to do anything server-side!**
|
||||||
|
|
||||||
## Differences with [jQuery-pjax](https://github.com/defunkt/jquery-pjax)
|
## Differences with [jQuery-pjax](https://github.com/defunkt/jquery-pjax)
|
||||||
|
|
||||||
- No jQuery dependency,
|
- No jQuery dependency
|
||||||
- Not limited to a container,
|
- Not limited to a container
|
||||||
- No server side requirements,
|
- No server-side requirements
|
||||||
- Works for CommonJS environment (browserify), AMD (RequireJS) or even globally,
|
- Works for CommonJS environment (Webpack/Browserify), AMD (RequireJS) or even globally
|
||||||
- Allow page transition with CSS animations,
|
- Allow page transition with CSS animations
|
||||||
- Can be easily hacked since every method is public (so overridable)
|
- Can be easily tweaked, since every method is public (and as a result, overridable)
|
||||||
|
|
||||||
## Compatibility
|
## Compatibility
|
||||||
|
|
||||||
Pjax only works with [browsers that support the `history.pushState` API](http://caniuse.com/#search=pushstate).
|
Pjax only works with [browsers that support the `history.pushState()` API](http://caniuse.com/#search=pushstate).
|
||||||
When the API isn't supported Pjax goes into fallback mode (it just does nothing).
|
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()`.
|
To see if Pjax is actually supported by your browser, use `Pjax.isSupported()`.
|
||||||
|
|
||||||
@@ -137,13 +139,13 @@ new Pjax({
|
|||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
This will enable Pjax on all links and designate the part to replace using CSS selectors `"title", ".my-Header", ".my-Content", ".my-Sidebar"`.
|
This will enable Pjax on all links, and designate the part to replace using CSS selectors `"title", ".my-Header", ".my-Content", ".my-Sidebar"`.
|
||||||
|
|
||||||
For some reason, you might want to just target some elements to apply Pjax behavior.
|
For some reason, you might want to just target some elements to apply Pjax behavior.
|
||||||
In that case, you can 2 differents things:
|
In that case, you can do two different things:
|
||||||
|
|
||||||
- use a custom selector like "a.js-Pjax" or ".js-Pjax a" depending on what you want.
|
- Use a custom selector like "a.js-Pjax" or ".js-Pjax a" depending on what you want.
|
||||||
- override `Pjax.prototype.getElements` that just basically `querSelectorAll` the `elements` option. In this function you just need to return a `NodeList`.
|
- Override `Pjax.prototype.getElements` that just basically `querySelectorAll` the `elements` option. In this function you just need to return a `NodeList`.
|
||||||
|
|
||||||
```js
|
```js
|
||||||
// use case 1
|
// use case 1
|
||||||
@@ -158,17 +160,17 @@ Pjax.prototype.getElements = function() {
|
|||||||
new Pjax({})
|
new Pjax({})
|
||||||
```
|
```
|
||||||
|
|
||||||
When instanciating a `Pjax` object, you need to pass all options as an object:
|
When instantiating a `Pjax` object, you need to pass all options as an object:
|
||||||
|
|
||||||
#### Options
|
#### Options
|
||||||
|
|
||||||
##### `elements` (String, default "a[href], form[action]")
|
##### `elements` (String, default: `"a[href], form[action]"`)
|
||||||
|
|
||||||
CSS Selector to use to retrieve links to apply Pjax
|
CSS selector to use to retrieve links to apply Pjax to.
|
||||||
|
|
||||||
##### `selectors` (Array, default ["title", ".js-Pjax"])
|
##### `selectors` (Array, default: `["title", ".js-Pjax"]`)
|
||||||
|
|
||||||
CSS Selectors to replace. If a query returns multiples items, it will just keep the index.
|
CSS selectors to replace. If a query returns multiples items, it will just keep the index.
|
||||||
|
|
||||||
Example of what you can do:
|
Example of what you can do:
|
||||||
|
|
||||||
@@ -188,13 +190,13 @@ Example of what you can do:
|
|||||||
```
|
```
|
||||||
|
|
||||||
This example is correct and should work "as expected".
|
This example is correct and should work "as expected".
|
||||||
_If there is not the same amount of DOM element from current page and new page,
|
_If the current page and new page do not have the same amount of DOM elements,
|
||||||
the Pjax behavior will fallback to normal page load._
|
Pjax will fall back to normal page load._
|
||||||
|
|
||||||
##### `switches` (Object, default {})
|
##### `switches` (Object, default: `{}`)
|
||||||
|
|
||||||
Objects containing callbacks that can be used to switch old element with new element.
|
Objects containing callbacks that can be used to switch old elements with new elements.
|
||||||
Keys should be one of the defined selector.
|
Keys should be one of the defined selectors.
|
||||||
|
|
||||||
Examples:
|
Examples:
|
||||||
|
|
||||||
@@ -214,22 +216,22 @@ new Pjax({
|
|||||||
})
|
})
|
||||||
```
|
```
|
||||||
|
|
||||||
Callbacks are binded to Pjax instance itself to allow you to reuse it (ex: `this.onSwitch()`)
|
Callbacks are bound to Pjax instance itself to allow you to reuse it (ex: `this.onSwitch()`)
|
||||||
|
|
||||||
###### Existing switches callback
|
###### Existing switches callback
|
||||||
|
|
||||||
- `Pjax.switches.outerHTML`: default behavior, replace elements using outerHTML
|
- `Pjax.switches.outerHTML`: default behavior, replace elements using outerHTML
|
||||||
- `Pjax.switches.innerHTML`: replace elements using innerHTML & copy className too
|
- `Pjax.switches.innerHTML`: replace elements using innerHTML and copy className too
|
||||||
- `Pjax.switches.sideBySide`: smart replacement that allow you to have both elements in the same parent when you want to use CSS animations. Old elements are removed when all childs have been fully animated ([animationEnd](http://www.w3.org/TR/css3-animations/#animationend) event triggered)
|
- `Pjax.switches.sideBySide`: smart replacement that allows you to have both elements in the same parent when you want to use CSS animations. Old elements are removed when all children have been fully animated ([animationEnd](http://www.w3.org/TR/css3-animations/#animationend) event triggered)
|
||||||
|
|
||||||
###### Create a switch callback
|
###### Create a switch callback
|
||||||
|
|
||||||
Your function can do whatever you want, but you need to:
|
Your function can do whatever you want, but you need to:
|
||||||
|
|
||||||
- replace oldEl content by newEl content in some fashion
|
- replace `oldEl`'s content with `newEl`'s content in some fashion
|
||||||
- call `this.onSwitch()` to trigger attached callback.
|
- call `this.onSwitch()` to trigger the attached callback.
|
||||||
|
|
||||||
Here is the default behavior as example
|
Here is the default behavior as an example:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
function(oldEl, newEl, pjaxRequestOptions, switchesClasses) {
|
function(oldEl, newEl, pjaxRequestOptions, switchesClasses) {
|
||||||
@@ -238,10 +240,10 @@ function(oldEl, newEl, pjaxRequestOptions, switchesClasses) {
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
##### `switchesOptions` (Object, default {})
|
##### `switchesOptions` (Object, default: `{}`)
|
||||||
|
|
||||||
This are options that can be used during switch by switchers ( for now, only `Pjax.switches.sideBySide` use it).
|
These are options that can be used during switch by switchers (for now, only `Pjax.switches.sideBySide` uses it).
|
||||||
Very convenient when you use something like [Animate.css](https://github.com/daneden/animate.css)
|
This is very convenient when you use something like [Animate.css](https://github.com/daneden/animate.css)
|
||||||
with or without [WOW.js](https://github.com/matthieua/WOW).
|
with or without [WOW.js](https://github.com/matthieua/WOW).
|
||||||
|
|
||||||
```js
|
```js
|
||||||
@@ -278,7 +280,7 @@ new Pjax({
|
|||||||
_Note that remove class include `Animated--reverse` which is a simple way to not have
|
_Note that remove class include `Animated--reverse` which is a simple way to not have
|
||||||
to create duplicate transition for (slideIn + reverse => slideOut)._
|
to create duplicate transition for (slideIn + reverse => slideOut)._
|
||||||
|
|
||||||
The following CSS will be required to make something nice
|
The following CSS will be required to make something nice:
|
||||||
|
|
||||||
```css
|
```css
|
||||||
/*
|
/*
|
||||||
@@ -336,8 +338,7 @@ The following CSS will be required to make something nice
|
|||||||
}
|
}
|
||||||
```
|
```
|
||||||
|
|
||||||
To get understand this CSS, here is a HTML snippet
|
To give context to this CSS, here is an HTML snippet:
|
||||||
|
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<!doctype html>
|
<!doctype html>
|
||||||
@@ -365,75 +366,99 @@ To get understand this CSS, here is a HTML snippet
|
|||||||
</html>
|
</html>
|
||||||
```
|
```
|
||||||
|
|
||||||
##### `history` (Boolean, default true)
|
##### `history` (Boolean, default: `true`)
|
||||||
|
|
||||||
Enable pushState. Only disable if you are crazy.
|
Enable the use of `pushState()`. Disabling this will prevent Pjax from updating browser history.
|
||||||
Internaly, this option is used when `popstate` is used (to not pushState again).
|
However, there is almost no use case where you would want to do that.
|
||||||
You should forget that option.
|
|
||||||
|
|
||||||
##### `analytics` (Function|Boolean, default to a function that pushes `_gaq` `_trackPageview` or sends `ga` `pageview`
|
Internally, this option is used when a `popstate` event triggers Pjax (to not `pushState()` again).
|
||||||
|
|
||||||
|
##### `analytics` (Function|Boolean, default: a function that pushes `_gaq` `_trackPageview` or sends `ga` `pageview`
|
||||||
|
|
||||||
Function that allows you to add behavior for analytics. By default it tries to track
|
Function that allows you to add behavior for analytics. By default it tries to track
|
||||||
a pageview with Google Analytics.
|
a pageview with Google Analytics (if it exists on the page).
|
||||||
It's called every time a page is switched, even for history buttons.
|
It's called every time a page is switched, even for history navigation.
|
||||||
|
|
||||||
Set to `false` to disable this behavior.
|
Set to `false` to disable this behavior.
|
||||||
|
|
||||||
##### `scrollTo` (Integer, default to 0)
|
##### `scrollTo` (Integer, default: `0`)
|
||||||
|
|
||||||
Value (in px) to scrollTo when a page is switched.
|
Value (in px from the top of the page) to scroll to when a page is switched.
|
||||||
|
|
||||||
##### `scrollRestoration` (Boolean, default true)
|
##### `scrollRestoration` (Boolean, default: `true`)
|
||||||
|
|
||||||
When set to true, attempt to restore the scroll position when navigating backwards or forwards.
|
When set to true, attempt to restore the scroll position when navigating backwards or forwards.
|
||||||
|
|
||||||
##### `cacheBust` (Boolean, default true)
|
##### `cacheBust` (Boolean, default: `true`)
|
||||||
|
|
||||||
When set to true,
|
When set to true, append a timestamp query string segment to the requested URLs
|
||||||
append a timestamp query string segment to the requested URLs
|
|
||||||
in order to skip browser cache.
|
in order to skip browser cache.
|
||||||
|
|
||||||
##### `debug` (Boolean, default to false)
|
##### `debug` (Boolean, default: `false`)
|
||||||
|
|
||||||
Enable verbose mode & doesn't use fallback when there is an error.
|
Enables verbose mode. Useful to debug page layout differences.
|
||||||
Useful to debug page layout differences.
|
|
||||||
|
|
||||||
##### `currentUrlFullReload` (Boolean, default to false)
|
##### `currentUrlFullReload` (Boolean, default: `false`)
|
||||||
|
|
||||||
When set to true, clicking on a link that point the current url trigger a full page reload.
|
When set to true, clicking on a link that points to the current URL will trigger a full page reload.
|
||||||
|
|
||||||
##### `timeout` (Integer, default to 0)
|
The default is `false`, so clicking on such a link will do nothing.
|
||||||
|
If you want to add some custom behavior, add a click listener to the link,
|
||||||
|
and set `preventDefault` to true, to prevent Pjax from receiving the event.
|
||||||
|
|
||||||
|
Here is some sample code:
|
||||||
|
|
||||||
|
```js
|
||||||
|
var links = document.querySelectorAll(".js-Pjax");
|
||||||
|
|
||||||
|
for (var i = 0; i < links.length; i++) {
|
||||||
|
var el = links[i]
|
||||||
|
|
||||||
|
el.addEventListener("click", function(e) {
|
||||||
|
if (el.href === window.location.href.split("#")[0]) {
|
||||||
|
e.preventDefault();
|
||||||
|
console.log("Link to current page clicked");
|
||||||
|
// Custom code goes here.
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
```
|
||||||
|
|
||||||
|
(Note that if `cacheBust` is set to true, the code that checks if the href
|
||||||
|
is the same as the current page's URL will not work, due to the query string
|
||||||
|
appended to force a cache bust).
|
||||||
|
|
||||||
|
##### `timeout` (Integer, default: `0`)
|
||||||
|
|
||||||
The timeout in milliseconds for the XHR requests. Set to 0 to disable the timeout.
|
The timeout in milliseconds for the XHR requests. Set to 0 to disable the timeout.
|
||||||
|
|
||||||
### Events
|
### Events
|
||||||
|
|
||||||
Pjax fires a number of events regardless of how its invoked.
|
Pjax fires a number of events regardless of how it's invoked.
|
||||||
|
|
||||||
All events are fired from the _document_, not the link was clicked.
|
All events are fired from the _document_, not the link that was clicked.
|
||||||
|
|
||||||
#### Ajax related events
|
|
||||||
|
|
||||||
* `pjax:send` - Fired after the Pjax request begins.
|
* `pjax:send` - Fired after the Pjax request begins.
|
||||||
* `pjax:complete` - Fired after the Pjax request finishes.
|
* `pjax:complete` - Fired after the Pjax request finishes.
|
||||||
* `pjax:success` - Fired after the Pjax request succeeds.
|
* `pjax:success` - Fired after the Pjax request succeeds.
|
||||||
* `pjax:error` - Fired after the Pjax request fails. Returning false will prevent the the fallback redirect.
|
* `pjax:error` - Fired after the Pjax request fails.
|
||||||
|
|
||||||
`send` and `complete` are a good pair of events to use if you are implementing a loading indicator (eg: [topbar](http://buunguyen.github.io/topbar/))
|
`send` and `complete` are a good pair of events to use if you are implementing a loading indicator (eg: [topbar](http://buunguyen.github.io/topbar/))
|
||||||
|
|
||||||
```js
|
```js
|
||||||
$(document).on('pjax:send', topbar.show)
|
document.addEventListener('pjax:send', topbar.show)
|
||||||
$(document).on('pjax:complete', topbar.hide)
|
document.addEventListener('pjax:complete', topbar.hide)
|
||||||
```
|
```
|
||||||
|
|
||||||
#### Note about DOM ready state
|
#### Note about DOM ready state
|
||||||
|
|
||||||
Most of the time, you have code attached & related to the current DOM, that you only execute when page/dom is ready.
|
Most of the time, you will have code related to the current DOM that you only execute when the DOM is ready.
|
||||||
Since Pjax doesn't magically rexecute you previous code each time you load a page, you need to make a simple thing to rexecute appropriate code:
|
|
||||||
|
Since Pjax doesn't magically re-execute your previous code each time you load a page, you need to add some simple code to achieve this:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
function whenDOMReady() {
|
function whenDOMReady() {
|
||||||
// do you stuff
|
// do your stuff
|
||||||
}
|
}
|
||||||
|
|
||||||
whenDOMReady()
|
whenDOMReady()
|
||||||
@@ -443,17 +468,18 @@ new Pjax()
|
|||||||
document.addEventListener("pjax:success", whenDOMReady)
|
document.addEventListener("pjax:success", whenDOMReady)
|
||||||
```
|
```
|
||||||
|
|
||||||
_Note: Don't create the Pjax in the `whenDOMReady` function._
|
_Note: Don't create the Pjax instance in the `whenDOMReady` function._
|
||||||
|
|
||||||
For my concern & usage, I `js-Pjax`ify all body children, including stuff like navigation & footer (to get navigation state easily updated).
|
For my concern and usage, I `js-Pjax`-ify all body children, including stuff like navigation and footer (to get navigation state easily updated).
|
||||||
So attached behavior are rexecuted each time a page is loaded, like in the snippet above.
|
|
||||||
|
The attached behavior is re-executed each time a page is loaded, like in the snippet above.
|
||||||
|
|
||||||
If you want to just update a specific part (it's totally a good idea), you can just
|
If you want to just update a specific part (it's totally a good idea), you can just
|
||||||
add the DOM related code in a function & rexecute this function when "pjax:success" event is done.
|
add the DOM-related code in a function and re-execute this function when "pjax:success" event is fired.
|
||||||
|
|
||||||
```js
|
```js
|
||||||
// do your global stuff
|
// do your global stuff
|
||||||
//... dom ready blah blah
|
//... DOM ready blah blah
|
||||||
|
|
||||||
function whenContainerReady() {
|
function whenContainerReady() {
|
||||||
// do your container related stuff
|
// do your container related stuff
|
||||||
@@ -472,12 +498,12 @@ document.addEventListener("pjax:success", whenContainerReady)
|
|||||||
### Q: Disqus doesn't work anymore, how can I fix that ?
|
### Q: Disqus doesn't work anymore, how can I fix that ?
|
||||||
|
|
||||||
A: There is a few things you need to do:
|
A: There is a few things you need to do:
|
||||||
- wrap your disqus snippet into a dom element that you will add to the `selector`
|
- wrap your Disqus snippet into a DOM element that you will add to the `selector`
|
||||||
arra (or just wrap it with class="js-Pjax") & be sure to have a least the empty
|
property (or just wrap it with `class="js-Pjax"`) and be sure to have at least the empty
|
||||||
wrapper on each page (to avoid differences of DOM between pages)
|
wrapper on each page (to avoid differences of DOM between pages)
|
||||||
- edit your disqus snippet like the one below
|
- edit your Disqus snippet like the one below
|
||||||
|
|
||||||
#### Disqus snippet before pjax integration
|
#### Disqus snippet before Pjax integration
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<script>
|
<script>
|
||||||
@@ -495,8 +521,8 @@ wrapper on each page (to avoid differences of DOM between pages)
|
|||||||
#### Disqus snippet after Pjax integration
|
#### Disqus snippet after Pjax integration
|
||||||
|
|
||||||
```html
|
```html
|
||||||
<div class="js-Pjax"><!-- need to be here on every pjaxified page, even if empty -->
|
<div class="js-Pjax"><!-- needs to be here on every Pjax-ified page, even if empty -->
|
||||||
<!-- if (blah blah) { // eventual server side test to know wheter or not you include this script -->
|
<!-- if (blah blah) { // eventual server-side test to know whether or not you include this script -->
|
||||||
<script>
|
<script>
|
||||||
var disqus_shortname = 'YOURSHORTNAME'
|
var disqus_shortname = 'YOURSHORTNAME'
|
||||||
var disqus_identifier = 'PAGEID'
|
var disqus_identifier = 'PAGEID'
|
||||||
@@ -526,7 +552,7 @@ wrapper on each page (to avoid differences of DOM between pages)
|
|||||||
</div>
|
</div>
|
||||||
```
|
```
|
||||||
|
|
||||||
**Note: The thing you need to understand is that Pjax handle inline `<script>` only for container you are reloading.**
|
**Note: Pjax only handles inline `<script>` blocks for the container you are switching.**
|
||||||
|
|
||||||
---
|
---
|
||||||
|
|
||||||
@@ -540,7 +566,7 @@ Clone this repository and run `npm run example`, which will open the example app
|
|||||||
|
|
||||||
* ⇄ Pull requests and ★ Stars are always welcome.
|
* ⇄ Pull requests and ★ Stars are always welcome.
|
||||||
* For bugs and feature requests, please create an issue.
|
* For bugs and feature requests, please create an issue.
|
||||||
* Pull requests must be accompanied by passing automated tests (`$ npm test`).
|
* Pull requests must be accompanied by passing automated tests (`npm test`).
|
||||||
|
|
||||||
## [CHANGELOG](CHANGELOG.md)
|
## [CHANGELOG](CHANGELOG.md)
|
||||||
|
|
||||||
|
|||||||
65
index.js
65
index.js
@@ -1,19 +1,14 @@
|
|||||||
var clone = require("./lib/clone.js")
|
var clone = require("./lib/clone.js")
|
||||||
var executeScripts = require("./lib/execute-scripts.js")
|
var executeScripts = require("./lib/execute-scripts.js")
|
||||||
|
|
||||||
var forEachEls = require("./lib/foreach-els.js")
|
var forEachEls = require("./lib/foreach-els.js")
|
||||||
|
var switches = require("./lib/switches")
|
||||||
var newUid = require("./lib/uniqueid.js")
|
var newUid = require("./lib/uniqueid.js")
|
||||||
|
|
||||||
var noop = require("./lib/util/noop")
|
|
||||||
var contains = require("./lib/util/contains.js")
|
|
||||||
|
|
||||||
var on = require("./lib/events/on.js")
|
var on = require("./lib/events/on.js")
|
||||||
// var off = require("./lib/events/on.js")
|
|
||||||
var trigger = require("./lib/events/trigger.js")
|
var trigger = require("./lib/events/trigger.js")
|
||||||
|
|
||||||
var defaultSwitches = require("./lib/switches")
|
var contains = require("./lib/util/contains.js")
|
||||||
|
var noop = require("./lib/util/noop")
|
||||||
|
|
||||||
var Pjax = function(options) {
|
var Pjax = function(options) {
|
||||||
this.state = {
|
this.state = {
|
||||||
@@ -22,8 +17,8 @@ var Pjax = function(options) {
|
|||||||
options: null
|
options: null
|
||||||
}
|
}
|
||||||
|
|
||||||
var parseOptions = require("./lib/proto/parse-options.js");
|
var parseOptions = require("./lib/proto/parse-options.js")
|
||||||
parseOptions.apply(this,[options])
|
parseOptions.call(this,options)
|
||||||
this.log("Pjax options", this.options)
|
this.log("Pjax options", this.options)
|
||||||
|
|
||||||
if (this.options.scrollRestoration && "scrollRestoration" in history) {
|
if (this.options.scrollRestoration && "scrollRestoration" in history) {
|
||||||
@@ -40,7 +35,7 @@ var Pjax = function(options) {
|
|||||||
opt.url = st.state.url
|
opt.url = st.state.url
|
||||||
opt.title = st.state.title
|
opt.title = st.state.title
|
||||||
opt.history = false
|
opt.history = false
|
||||||
opt.requestOptions = {};
|
opt.requestOptions = {}
|
||||||
opt.scrollPos = st.state.scrollPos
|
opt.scrollPos = st.state.scrollPos
|
||||||
if (st.state.uid < this.lastUid) {
|
if (st.state.uid < this.lastUid) {
|
||||||
opt.backward = true
|
opt.backward = true
|
||||||
@@ -56,18 +51,27 @@ var Pjax = function(options) {
|
|||||||
}.bind(this))
|
}.bind(this))
|
||||||
}
|
}
|
||||||
|
|
||||||
Pjax.switches = defaultSwitches
|
Pjax.switches = switches
|
||||||
|
|
||||||
Pjax.prototype = {
|
Pjax.prototype = {
|
||||||
log: require("./lib/proto/log.js"),
|
log: require("./lib/proto/log.js"),
|
||||||
|
|
||||||
getElements: require("./lib/proto/get-elements.js"),
|
getElements: function(el) {
|
||||||
|
return el.querySelectorAll(this.options.elements)
|
||||||
|
},
|
||||||
|
|
||||||
parseDOM: require("./lib/proto/parse-dom.js"),
|
parseDOM: function(el) {
|
||||||
|
var parseElement = require("./lib/proto/parse-element")
|
||||||
|
forEachEls(this.getElements(el), parseElement, this)
|
||||||
|
},
|
||||||
|
|
||||||
refresh: require("./lib/proto/refresh.js"),
|
refresh: function(el) {
|
||||||
|
this.parseDOM(el || document)
|
||||||
|
},
|
||||||
|
|
||||||
reload: require("./lib/reload.js"),
|
reload: function() {
|
||||||
|
window.location.reload()
|
||||||
|
},
|
||||||
|
|
||||||
attachLink: require("./lib/proto/attach-link.js"),
|
attachLink: require("./lib/proto/attach-link.js"),
|
||||||
|
|
||||||
@@ -81,15 +85,6 @@ Pjax.prototype = {
|
|||||||
return require("./lib/switches-selectors.js").bind(this)(this.options.switches, this.options.switchesOptions, selectors, fromEl, toEl, options)
|
return require("./lib/switches-selectors.js").bind(this)(this.options.switches, this.options.switchesOptions, selectors, fromEl, toEl, options)
|
||||||
},
|
},
|
||||||
|
|
||||||
// too much problem with the code below
|
|
||||||
// + it’s too dangerous
|
|
||||||
// switchFallback: function(fromEl, toEl) {
|
|
||||||
// this.switchSelectors(["head", "body"], fromEl, toEl)
|
|
||||||
// // execute script when DOM is like it should be
|
|
||||||
// Pjax.executeScripts(document.querySelector("head"))
|
|
||||||
// Pjax.executeScripts(document.querySelector("body"))
|
|
||||||
// }
|
|
||||||
|
|
||||||
latestChance: function(href) {
|
latestChance: function(href) {
|
||||||
window.location = href
|
window.location = href
|
||||||
},
|
},
|
||||||
@@ -139,16 +134,7 @@ Pjax.prototype = {
|
|||||||
} catch (e) { }
|
} catch (e) { }
|
||||||
}
|
}
|
||||||
|
|
||||||
// try {
|
|
||||||
this.switchSelectors(this.options.selectors, tmpEl, document, options)
|
this.switchSelectors(this.options.selectors, tmpEl, document, options)
|
||||||
|
|
||||||
// }
|
|
||||||
// catch(e) {
|
|
||||||
// if (this.options.debug) {
|
|
||||||
// this.log("Pjax switch fail: ", e)
|
|
||||||
// }
|
|
||||||
// this.switchFallback(tmpEl, document)
|
|
||||||
// }
|
|
||||||
},
|
},
|
||||||
|
|
||||||
abortRequest: require("./lib/abort-request.js"),
|
abortRequest: require("./lib/abort-request.js"),
|
||||||
@@ -161,7 +147,7 @@ Pjax.prototype = {
|
|||||||
// Abort any previous request
|
// Abort any previous request
|
||||||
this.abortRequest(this.request)
|
this.abortRequest(this.request)
|
||||||
|
|
||||||
trigger(document, "pjax:send", options);
|
trigger(document, "pjax:send", options)
|
||||||
|
|
||||||
// Do the request
|
// Do the request
|
||||||
options.requestOptions.timeout = this.options.timeout
|
options.requestOptions.timeout = this.options.timeout
|
||||||
@@ -218,8 +204,7 @@ Pjax.prototype = {
|
|||||||
if (console && console.error) {
|
if (console && console.error) {
|
||||||
console.error("Pjax switch fail: ", e)
|
console.error("Pjax switch fail: ", e)
|
||||||
}
|
}
|
||||||
this.latestChance(href)
|
return this.latestChance(href)
|
||||||
return
|
|
||||||
}
|
}
|
||||||
else {
|
else {
|
||||||
throw e
|
throw e
|
||||||
@@ -236,7 +221,7 @@ Pjax.prototype = {
|
|||||||
// http://www.w3.org/html/wg/drafts/html/master/forms.html
|
// http://www.w3.org/html/wg/drafts/html/master/forms.html
|
||||||
var autofocusEl = Array.prototype.slice.call(document.querySelectorAll("[autofocus]")).pop()
|
var autofocusEl = Array.prototype.slice.call(document.querySelectorAll("[autofocus]")).pop()
|
||||||
if (autofocusEl && document.activeElement !== autofocusEl) {
|
if (autofocusEl && document.activeElement !== autofocusEl) {
|
||||||
autofocusEl.focus();
|
autofocusEl.focus()
|
||||||
}
|
}
|
||||||
|
|
||||||
// execute scripts when DOM have been completely updated
|
// execute scripts when DOM have been completely updated
|
||||||
@@ -304,7 +289,7 @@ Pjax.prototype = {
|
|||||||
} while (target)
|
} while (target)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
window.scrollTo(0, curtop);
|
window.scrollTo(0, curtop)
|
||||||
}
|
}
|
||||||
else if (state.options.scrollTo !== false) {
|
else if (state.options.scrollTo !== false) {
|
||||||
// Scroll page to top on new page load
|
// Scroll page to top on new page load
|
||||||
@@ -328,7 +313,7 @@ Pjax.prototype = {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
Pjax.isSupported = require("./lib/is-supported.js");
|
Pjax.isSupported = require("./lib/is-supported.js")
|
||||||
|
|
||||||
// arguably could do `if( require("./lib/is-supported.js")()) {` but that might be a little to simple
|
// arguably could do `if( require("./lib/is-supported.js")()) {` but that might be a little to simple
|
||||||
if (Pjax.isSupported()) {
|
if (Pjax.isSupported()) {
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
module.exports = function(obj) {
|
module.exports = function(obj) {
|
||||||
if (null === obj || "object" != typeof obj) {
|
if (null === obj || "object" !== typeof obj) {
|
||||||
return obj
|
return obj
|
||||||
}
|
}
|
||||||
var copy = obj.constructor()
|
var copy = obj.constructor()
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
module.exports = function(el) {
|
module.exports = function(el) {
|
||||||
var code = (el.text || el.textContent || el.innerHTML || "")
|
var code = (el.text || el.textContent || el.innerHTML || "")
|
||||||
var src = (el.src || "");
|
var src = (el.src || "")
|
||||||
var parent = el.parentNode || document.querySelector("head") || document.documentElement
|
var parent = el.parentNode || document.querySelector("head") || document.documentElement
|
||||||
var script = document.createElement("script")
|
var script = document.createElement("script")
|
||||||
|
|
||||||
@@ -13,12 +13,12 @@ module.exports = function(el) {
|
|||||||
|
|
||||||
script.type = "text/javascript"
|
script.type = "text/javascript"
|
||||||
|
|
||||||
if (src != "") {
|
if (src !== "") {
|
||||||
script.src = src;
|
script.src = src
|
||||||
script.async = false; // force synchronous loading of peripheral js
|
script.async = false // force synchronous loading of peripheral JS
|
||||||
}
|
}
|
||||||
|
|
||||||
if (code != "") {
|
if (code !== "") {
|
||||||
try {
|
try {
|
||||||
script.appendChild(document.createTextNode(code))
|
script.appendChild(document.createTextNode(code))
|
||||||
}
|
}
|
||||||
@@ -29,11 +29,11 @@ module.exports = function(el) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// execute
|
// execute
|
||||||
parent.appendChild(script);
|
parent.appendChild(script)
|
||||||
// avoid pollution only in head or body tags
|
// avoid pollution only in head or body tags
|
||||||
if (["head", "body"].indexOf(parent.tagName.toLowerCase()) > 0) {
|
if (["head", "body"].indexOf(parent.tagName.toLowerCase()) > 0) {
|
||||||
parent.removeChild(script)
|
parent.removeChild(script)
|
||||||
}
|
}
|
||||||
|
|
||||||
return true;
|
return true
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,7 +4,7 @@ module.exports = function(els, events, opts) {
|
|||||||
events = (typeof events === "string" ? events.split(" ") : events)
|
events = (typeof events === "string" ? events.split(" ") : events)
|
||||||
|
|
||||||
events.forEach(function(e) {
|
events.forEach(function(e) {
|
||||||
var event // = new CustomEvent(e) // doesn't everywhere yet
|
var event
|
||||||
event = document.createEvent("HTMLEvents")
|
event = document.createEvent("HTMLEvents")
|
||||||
event.initEvent(e, true, true)
|
event.initEvent(e, true, true)
|
||||||
event.eventName = e
|
event.eventName = e
|
||||||
@@ -17,8 +17,8 @@ module.exports = function(els, events, opts) {
|
|||||||
forEachEls(els, function(el) {
|
forEachEls(els, function(el) {
|
||||||
var domFix = false
|
var domFix = false
|
||||||
if (!el.parentNode && el !== document && el !== window) {
|
if (!el.parentNode && el !== document && el !== window) {
|
||||||
// THANKS YOU IE (9/10//11 concerned)
|
// THANK YOU IE (9/10/11)
|
||||||
// dispatchEvent doesn't work if element is not in the dom
|
// dispatchEvent doesn't work if the element is not in the DOM
|
||||||
domFix = true
|
domFix = true
|
||||||
document.body.appendChild(el)
|
document.body.appendChild(el)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -3,10 +3,8 @@ var evalScript = require("./eval-script")
|
|||||||
// Finds and executes scripts (used for newly added elements)
|
// Finds and executes scripts (used for newly added elements)
|
||||||
// Needed since innerHTML does not run scripts
|
// Needed since innerHTML does not run scripts
|
||||||
module.exports = function(el) {
|
module.exports = function(el) {
|
||||||
// console.log("going to execute scripts for ", el)
|
|
||||||
|
|
||||||
if (el.tagName.toLowerCase() === "script") {
|
if (el.tagName.toLowerCase() === "script") {
|
||||||
evalScript(el);
|
evalScript(el)
|
||||||
}
|
}
|
||||||
|
|
||||||
forEachEls(el.querySelectorAll("script"), function(script) {
|
forEachEls(el.querySelectorAll("script"), function(script) {
|
||||||
@@ -14,7 +12,7 @@ module.exports = function(el) {
|
|||||||
if (script.parentNode) {
|
if (script.parentNode) {
|
||||||
script.parentNode.removeChild(script)
|
script.parentNode.removeChild(script)
|
||||||
}
|
}
|
||||||
evalScript(script);
|
evalScript(script)
|
||||||
}
|
}
|
||||||
});
|
})
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -4,6 +4,6 @@ module.exports = function(els, fn, context) {
|
|||||||
if (els instanceof HTMLCollection || els instanceof NodeList || els instanceof Array) {
|
if (els instanceof HTMLCollection || els instanceof NodeList || els instanceof Array) {
|
||||||
return Array.prototype.forEach.call(els, fn, context)
|
return Array.prototype.forEach.call(els, fn, context)
|
||||||
}
|
}
|
||||||
// assume simple dom element
|
// assume simple DOM element
|
||||||
return fn.call(context, els)
|
return fn.call(context, els)
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,20 +0,0 @@
|
|||||||
if (!Function.prototype.bind) {
|
|
||||||
Function.prototype.bind = function(oThis) {
|
|
||||||
if (typeof this !== "function") {
|
|
||||||
// closest thing possible to the ECMAScript 5 internal IsCallable function
|
|
||||||
throw new TypeError("Function.prototype.bind - what is trying to be bound is not callable")
|
|
||||||
}
|
|
||||||
|
|
||||||
var aArgs = Array.prototype.slice.call(arguments, 1)
|
|
||||||
var that = this
|
|
||||||
var Fnoop = function() {}
|
|
||||||
var fBound = function() {
|
|
||||||
return that.apply(this instanceof Fnoop && oThis ? this : oThis, aArgs.concat(Array.prototype.slice.call(arguments)))
|
|
||||||
}
|
|
||||||
|
|
||||||
Fnoop.prototype = this.prototype
|
|
||||||
fBound.prototype = new Fnoop()
|
|
||||||
|
|
||||||
return fBound
|
|
||||||
}
|
|
||||||
}
|
|
||||||
@@ -1,5 +1,3 @@
|
|||||||
require("../polyfills/Function.prototype.bind")
|
|
||||||
|
|
||||||
var on = require("../events/on")
|
var on = require("../events/on")
|
||||||
var clone = require("../clone")
|
var clone = require("../clone")
|
||||||
|
|
||||||
@@ -8,27 +6,27 @@ var attrClick = "data-pjax-click-state"
|
|||||||
var formAction = function(el, event) {
|
var formAction = function(el, event) {
|
||||||
// Since loadUrl modifies options and we may add our own modifications below,
|
// Since loadUrl modifies options and we may add our own modifications below,
|
||||||
// clone it so the changes don't persist
|
// clone it so the changes don't persist
|
||||||
var options = clone(this.options);
|
var options = clone(this.options)
|
||||||
|
|
||||||
// Initialize requestOptions
|
// Initialize requestOptions
|
||||||
options.requestOptions = {
|
options.requestOptions = {
|
||||||
requestUrl: el.getAttribute("action") || window.location.href,
|
requestUrl: el.getAttribute("action") || window.location.href,
|
||||||
requestMethod: el.getAttribute("method") || "GET",
|
requestMethod: el.getAttribute("method") || "GET"
|
||||||
}
|
}
|
||||||
|
|
||||||
// create a testable virtual link of the form action
|
// create a testable virtual link of the form action
|
||||||
var virtLinkElement = document.createElement("a");
|
var virtLinkElement = document.createElement("a")
|
||||||
virtLinkElement.setAttribute("href", options.requestOptions.requestUrl);
|
virtLinkElement.setAttribute("href", options.requestOptions.requestUrl)
|
||||||
|
|
||||||
// Ignore external links.
|
// Ignore external links.
|
||||||
if (virtLinkElement.protocol !== window.location.protocol || virtLinkElement.host !== window.location.host) {
|
if (virtLinkElement.protocol !== window.location.protocol || virtLinkElement.host !== window.location.host) {
|
||||||
el.setAttribute(attrClick, "external");
|
el.setAttribute(attrClick, "external")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
// Ignore click if we are on an anchor on the same page
|
// Ignore click if we are on an anchor on the same page
|
||||||
if (virtLinkElement.pathname === window.location.pathname && virtLinkElement.hash.length > 0) {
|
if (virtLinkElement.pathname === window.location.pathname && virtLinkElement.hash.length > 0) {
|
||||||
el.setAttribute(attrClick, "anchor-present");
|
el.setAttribute(attrClick, "anchor-present")
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
@@ -40,41 +38,39 @@ var formAction = function(el, event) {
|
|||||||
|
|
||||||
// if declared as a full reload, just normally submit the form
|
// if declared as a full reload, just normally submit the form
|
||||||
if (options.currentUrlFullReload) {
|
if (options.currentUrlFullReload) {
|
||||||
el.setAttribute(attrClick, "reload");
|
el.setAttribute(attrClick, "reload")
|
||||||
return;
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
|
|
||||||
var paramObject = [];
|
var paramObject = []
|
||||||
for (var elementKey in el.elements) {
|
for (var elementKey in el.elements) {
|
||||||
var element = el.elements[elementKey];
|
var element = el.elements[elementKey]
|
||||||
// jscs:disable disallowImplicitTypeConversion
|
// jscs:disable disallowImplicitTypeConversion
|
||||||
if (!!element.name && element.attributes !== undefined && element.tagName.toLowerCase() !== "button") {
|
if (!!element.name && element.attributes !== undefined && element.tagName.toLowerCase() !== "button") {
|
||||||
// jscs:enable disallowImplicitTypeConversion
|
// jscs:enable disallowImplicitTypeConversion
|
||||||
if ((element.attributes.type !== "checkbox" && element.attributes.type !== "radio") || element.checked) {
|
if ((element.attributes.type !== "checkbox" && element.attributes.type !== "radio") || element.checked) {
|
||||||
paramObject.push({name: encodeURIComponent(element.name), value: encodeURIComponent(element.value)});
|
paramObject.push({name: encodeURIComponent(element.name), value: encodeURIComponent(element.value)})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creating a getString
|
// Creating a getString
|
||||||
var paramsString = (paramObject.map(function(value) {return value.name + "=" + value.value;})).join("&");
|
var paramsString = (paramObject.map(function(value) {return value.name + "=" + value.value})).join("&")
|
||||||
|
|
||||||
options.requestOptions.requestPayload = paramObject;
|
options.requestOptions.requestPayload = paramObject
|
||||||
options.requestOptions.requestPayloadString = paramsString;
|
options.requestOptions.requestPayloadString = paramsString
|
||||||
|
|
||||||
el.setAttribute(attrClick, "submit");
|
el.setAttribute(attrClick, "submit")
|
||||||
|
|
||||||
|
options.triggerElement = el
|
||||||
options.triggerElement = el;
|
this.loadUrl(virtLinkElement.href, options)
|
||||||
this.loadUrl(virtLinkElement.href, options);
|
}
|
||||||
};
|
|
||||||
|
|
||||||
var isDefaultPrevented = function(event) {
|
var isDefaultPrevented = function(event) {
|
||||||
return event.defaultPrevented || event.returnValue === false;
|
return event.defaultPrevented || event.returnValue === false
|
||||||
};
|
}
|
||||||
|
|
||||||
|
|
||||||
module.exports = function(el) {
|
module.exports = function(el) {
|
||||||
var that = this
|
var that = this
|
||||||
@@ -92,8 +88,7 @@ module.exports = function(el) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
|
if (event.keyCode === 13) {
|
||||||
if (event.keyCode == 13) {
|
|
||||||
formAction.call(that, el, event)
|
formAction.call(that, el, event)
|
||||||
}
|
}
|
||||||
}.bind(this))
|
}.bind(this))
|
||||||
|
|||||||
@@ -1,5 +1,3 @@
|
|||||||
require("../polyfills/Function.prototype.bind")
|
|
||||||
|
|
||||||
var on = require("../events/on")
|
var on = require("../events/on")
|
||||||
var clone = require("../clone")
|
var clone = require("../clone")
|
||||||
|
|
||||||
@@ -9,10 +7,10 @@ var attrKey = "data-pjax-keyup-state"
|
|||||||
var linkAction = function(el, event) {
|
var linkAction = function(el, event) {
|
||||||
// Since loadUrl modifies options and we may add our own modifications below,
|
// Since loadUrl modifies options and we may add our own modifications below,
|
||||||
// clone it so the changes don't persist
|
// clone it so the changes don't persist
|
||||||
var options = clone(this.options);
|
var options = clone(this.options)
|
||||||
|
|
||||||
// Initialize requestOptions since loadUrl expects it to be an object
|
// Initialize requestOptions since loadUrl expects it to be an object
|
||||||
options.requestOptions = {};
|
options.requestOptions = {}
|
||||||
|
|
||||||
// Don’t break browser special behavior on links (like page in new window)
|
// Don’t break browser special behavior on links (like page in new window)
|
||||||
if (event.which > 1 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) {
|
if (event.which > 1 || event.metaKey || event.ctrlKey || event.shiftKey || event.altKey) {
|
||||||
@@ -66,7 +64,7 @@ var linkAction = function(el, event) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
var isDefaultPrevented = function(event) {
|
var isDefaultPrevented = function(event) {
|
||||||
return event.defaultPrevented || event.returnValue === false;
|
return event.defaultPrevented || event.returnValue === false
|
||||||
}
|
}
|
||||||
|
|
||||||
module.exports = function(el) {
|
module.exports = function(el) {
|
||||||
@@ -91,7 +89,7 @@ module.exports = function(el) {
|
|||||||
return
|
return
|
||||||
}
|
}
|
||||||
|
|
||||||
if (event.keyCode == 13) {
|
if (event.keyCode === 13) {
|
||||||
linkAction.call(that, el, event)
|
linkAction.call(that, el, event)
|
||||||
}
|
}
|
||||||
}.bind(this))
|
}.bind(this))
|
||||||
|
|||||||
@@ -1,3 +0,0 @@
|
|||||||
module.exports = function(el) {
|
|
||||||
return el.querySelectorAll(this.options.elements)
|
|
||||||
}
|
|
||||||
@@ -1,11 +1,11 @@
|
|||||||
module.exports = function() {
|
module.exports = function() {
|
||||||
if (this.options.debug && console) {
|
if (this.options.debug && console) {
|
||||||
if (typeof console.log === "function") {
|
if (typeof console.log === "function") {
|
||||||
console.log.apply(console, arguments);
|
console.log.apply(console, arguments)
|
||||||
}
|
}
|
||||||
// ie is weird
|
// IE is weird
|
||||||
else if (console.log) {
|
else if (console.log) {
|
||||||
console.log(arguments);
|
console.log(arguments)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,7 +0,0 @@
|
|||||||
var forEachEls = require("../foreach-els")
|
|
||||||
|
|
||||||
var parseElement = require("./parse-element")
|
|
||||||
|
|
||||||
module.exports = function(el) {
|
|
||||||
forEachEls(this.getElements(el), parseElement, this)
|
|
||||||
}
|
|
||||||
@@ -3,6 +3,7 @@
|
|||||||
var defaultSwitches = require("../switches")
|
var defaultSwitches = require("../switches")
|
||||||
|
|
||||||
module.exports = function(options) {
|
module.exports = function(options) {
|
||||||
|
options = options || {}
|
||||||
options.elements = options.elements || "a[href], form[action]"
|
options.elements = options.elements || "a[href], form[action]"
|
||||||
options.selectors = options.selectors || ["title", ".js-Pjax"]
|
options.selectors = options.selectors || ["title", ".js-Pjax"]
|
||||||
options.switches = options.switches || {}
|
options.switches = options.switches || {}
|
||||||
@@ -18,16 +19,16 @@ module.exports = function(options) {
|
|||||||
ga("send", "pageview", {page: location.pathname, title: document.title})
|
ga("send", "pageview", {page: location.pathname, title: document.title})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
options.scrollTo = (typeof options.scrollTo === "undefined") ? 0 : options.scrollTo;
|
options.scrollTo = (typeof options.scrollTo === "undefined") ? 0 : options.scrollTo
|
||||||
options.scrollRestoration = (typeof options.scrollRestoration !== "undefined") ? options.scrollRestoration : true
|
options.scrollRestoration = (typeof options.scrollRestoration !== "undefined") ? options.scrollRestoration : true
|
||||||
options.cacheBust = (typeof options.cacheBust === "undefined") ? true : options.cacheBust
|
options.cacheBust = (typeof options.cacheBust === "undefined") ? true : options.cacheBust
|
||||||
options.debug = options.debug || false
|
options.debug = options.debug || false
|
||||||
options.timeout = options.timeout || 0
|
options.timeout = options.timeout || 0
|
||||||
|
options.currentUrlFullReload = (typeof options.currentUrlFullReload === "undefined") ? false : options.currentUrlFullReload
|
||||||
|
|
||||||
// we can’t replace body.outerHTML or head.outerHTML
|
// We can’t replace body.outerHTML or head.outerHTML.
|
||||||
// it create a bug where new body or new head are created in the dom
|
// It creates a bug where a new body or head are created in the DOM.
|
||||||
// if you set head.outerHTML, a new body tag is appended, so the dom get 2 body
|
// If you set head.outerHTML, a new body tag is appended, so the DOM has 2 body nodes, and vice versa
|
||||||
// & it break the switchFallback which replace head & body
|
|
||||||
if (!options.switches.head) {
|
if (!options.switches.head) {
|
||||||
options.switches.head = defaultSwitches.switchElementsAlt
|
options.switches.head = defaultSwitches.switchElementsAlt
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,3 +0,0 @@
|
|||||||
module.exports = function(el) {
|
|
||||||
this.parseDOM(el || document)
|
|
||||||
}
|
|
||||||
@@ -1,3 +0,0 @@
|
|||||||
module.exports = function() {
|
|
||||||
window.location.reload()
|
|
||||||
}
|
|
||||||
@@ -1,7 +1,7 @@
|
|||||||
module.exports = function(location, options, callback) {
|
module.exports = function(location, options, callback) {
|
||||||
options = options || {};
|
options = options || {}
|
||||||
var requestMethod = options.requestMethod || "GET";
|
var requestMethod = options.requestMethod || "GET"
|
||||||
var requestPayload = options.requestPayloadString || null;
|
var requestPayload = options.requestPayloadString || null
|
||||||
var request = new XMLHttpRequest()
|
var request = new XMLHttpRequest()
|
||||||
|
|
||||||
request.onreadystatechange = function() {
|
request.onreadystatechange = function() {
|
||||||
@@ -35,9 +35,9 @@ module.exports = function(location, options, callback) {
|
|||||||
request.setRequestHeader("X-PJAX", "true")
|
request.setRequestHeader("X-PJAX", "true")
|
||||||
|
|
||||||
// Add the request payload if available
|
// Add the request payload if available
|
||||||
if (options.requestPayloadString != undefined && options.requestPayloadString != "") {
|
if (options.requestPayloadString !== undefined && options.requestPayloadString !== "") {
|
||||||
// Send the proper header information along with the request
|
// Send the proper header information along with the request
|
||||||
request.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
|
request.setRequestHeader("Content-type", "application/x-www-form-urlencoded")
|
||||||
}
|
}
|
||||||
|
|
||||||
request.send(requestPayload)
|
request.send(requestPayload)
|
||||||
|
|||||||
@@ -3,7 +3,7 @@ var forEachEls = require("./foreach-els")
|
|||||||
var defaultSwitches = require("./switches")
|
var defaultSwitches = require("./switches")
|
||||||
|
|
||||||
module.exports = function(switches, switchesOptions, selectors, fromEl, toEl, options) {
|
module.exports = function(switches, switchesOptions, selectors, fromEl, toEl, options) {
|
||||||
var switchesQueue = [];
|
var switchesQueue = []
|
||||||
|
|
||||||
selectors.forEach(function(selector) {
|
selectors.forEach(function(selector) {
|
||||||
var newEls = fromEl.querySelectorAll(selector)
|
var newEls = fromEl.querySelectorAll(selector)
|
||||||
@@ -12,12 +12,6 @@ module.exports = function(switches, switchesOptions, selectors, fromEl, toEl, op
|
|||||||
this.log("Pjax switch", selector, newEls, oldEls)
|
this.log("Pjax switch", selector, newEls, oldEls)
|
||||||
}
|
}
|
||||||
if (newEls.length !== oldEls.length) {
|
if (newEls.length !== oldEls.length) {
|
||||||
// forEachEls(newEls, function(el) {
|
|
||||||
// this.log("newEl", el, el.outerHTML)
|
|
||||||
// }, this)
|
|
||||||
// forEachEls(oldEls, function(el) {
|
|
||||||
// this.log("oldEl", el, el.outerHTML)
|
|
||||||
// }, this)
|
|
||||||
throw "DOM doesn’t look the same on new loaded page: ’" + selector + "’ - new " + newEls.length + ", old " + oldEls.length
|
throw "DOM doesn’t look the same on new loaded page: ’" + selector + "’ - new " + newEls.length + ", old " + oldEls.length
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
@@ -1,7 +1,4 @@
|
|||||||
var on = require("./events/on.js")
|
var on = require("./events/on.js")
|
||||||
// var off = require("./lib/events/on.js")
|
|
||||||
// var trigger = require("./lib/events/trigger.js")
|
|
||||||
|
|
||||||
|
|
||||||
module.exports = {
|
module.exports = {
|
||||||
outerHTML: function(oldEl, newEl) {
|
outerHTML: function(oldEl, newEl) {
|
||||||
@@ -20,7 +17,7 @@ module.exports = {
|
|||||||
|
|
||||||
// Copy attributes from the new element to the old one
|
// Copy attributes from the new element to the old one
|
||||||
if (newEl.hasAttributes()) {
|
if (newEl.hasAttributes()) {
|
||||||
var attrs = newEl.attributes;
|
var attrs = newEl.attributes
|
||||||
for (var i = 0; i < attrs.length; i++) {
|
for (var i = 0; i < attrs.length; i++) {
|
||||||
oldEl.attributes.setNamedItem(attrs[i].cloneNode())
|
oldEl.attributes.setNamedItem(attrs[i].cloneNode())
|
||||||
}
|
}
|
||||||
@@ -34,13 +31,10 @@ module.exports = {
|
|||||||
var elsToRemove = []
|
var elsToRemove = []
|
||||||
var elsToAdd = []
|
var elsToAdd = []
|
||||||
var fragToAppend = document.createDocumentFragment()
|
var fragToAppend = document.createDocumentFragment()
|
||||||
// height transition are shitty on safari
|
|
||||||
// so commented for now (until I found something ?)
|
|
||||||
// var relevantHeight = 0
|
|
||||||
var animationEventNames = "animationend webkitAnimationEnd MSAnimationEnd oanimationend"
|
var animationEventNames = "animationend webkitAnimationEnd MSAnimationEnd oanimationend"
|
||||||
var animatedElsNumber = 0
|
var animatedElsNumber = 0
|
||||||
var sexyAnimationEnd = function(e) {
|
var sexyAnimationEnd = function(e) {
|
||||||
if (e.target != e.currentTarget) {
|
if (e.target !== e.currentTarget) {
|
||||||
// end triggered by an animation on a child
|
// end triggered by an animation on a child
|
||||||
return
|
return
|
||||||
}
|
}
|
||||||
@@ -58,28 +52,16 @@ module.exports = {
|
|||||||
elsToAdd.forEach(function(el) {
|
elsToAdd.forEach(function(el) {
|
||||||
el.className = el.className.replace(el.getAttribute("data-pjax-classes"), "")
|
el.className = el.className.replace(el.getAttribute("data-pjax-classes"), "")
|
||||||
el.removeAttribute("data-pjax-classes")
|
el.removeAttribute("data-pjax-classes")
|
||||||
// Pjax.off(el, animationEventNames, sexyAnimationEnd, true)
|
|
||||||
})
|
})
|
||||||
|
|
||||||
elsToAdd = null // free memory
|
elsToAdd = null // free memory
|
||||||
elsToRemove = null // free memory
|
elsToRemove = null // free memory
|
||||||
|
|
||||||
// assume the height is now useless (avoid bug since there is overflow hidden on the parent)
|
|
||||||
// oldEl.style.height = "auto"
|
|
||||||
|
|
||||||
// this is to trigger some repaint (example: picturefill)
|
// this is to trigger some repaint (example: picturefill)
|
||||||
this.onSwitch()
|
this.onSwitch()
|
||||||
// Pjax.trigger(window, "scroll")
|
|
||||||
}
|
}
|
||||||
}.bind(this)
|
}.bind(this)
|
||||||
|
|
||||||
// Force height to be able to trigger css animation
|
|
||||||
// here we get the relevant height
|
|
||||||
// oldEl.parentNode.appendChild(newEl)
|
|
||||||
// relevantHeight = newEl.getBoundingClientRect().height
|
|
||||||
// oldEl.parentNode.removeChild(newEl)
|
|
||||||
// oldEl.style.height = oldEl.getBoundingClientRect().height + "px"
|
|
||||||
|
|
||||||
switchOptions = switchOptions || {}
|
switchOptions = switchOptions || {}
|
||||||
|
|
||||||
forEach.call(oldEl.childNodes, function(el) {
|
forEach.call(oldEl.childNodes, function(el) {
|
||||||
@@ -123,7 +105,5 @@ module.exports = {
|
|||||||
// pass all className of the parent
|
// pass all className of the parent
|
||||||
oldEl.className = newEl.className
|
oldEl.className = newEl.className
|
||||||
oldEl.appendChild(fragToAppend)
|
oldEl.appendChild(fragToAppend)
|
||||||
|
|
||||||
// oldEl.style.height = relevantHeight + "px"
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,11 +1,10 @@
|
|||||||
{
|
{
|
||||||
"name": "pjax",
|
"name": "pjax",
|
||||||
"version": "0.2.4",
|
"version": "0.2.4",
|
||||||
"description": "Easily enable fast Ajax navigation on any website (using pushState + xhr)",
|
"description": "Easily enable fast AJAX navigation on any website (using pushState + XHR)",
|
||||||
"keywords": [
|
"keywords": [
|
||||||
"pjax",
|
"pjax",
|
||||||
"push",
|
"pushstate",
|
||||||
"state",
|
|
||||||
"ajax",
|
"ajax",
|
||||||
"navigation",
|
"navigation",
|
||||||
"transition",
|
"transition",
|
||||||
@@ -13,6 +12,10 @@
|
|||||||
],
|
],
|
||||||
"repository": "https://github.com/MoOx/pjax.git",
|
"repository": "https://github.com/MoOx/pjax.git",
|
||||||
"author": "Maxime Thirouin",
|
"author": "Maxime Thirouin",
|
||||||
|
"contributors": [
|
||||||
|
"BehindTheMath",
|
||||||
|
"Robin North (http://robinnorth.co.uk)"
|
||||||
|
],
|
||||||
"license": "MIT",
|
"license": "MIT",
|
||||||
"main": "index.js",
|
"main": "index.js",
|
||||||
"files": [
|
"files": [
|
||||||
|
|||||||
@@ -18,8 +18,8 @@ if (!("responseURL" in XMLHttpRequest.prototype)) {
|
|||||||
tape("test aborting xhr request", function(t) {
|
tape("test aborting xhr request", function(t) {
|
||||||
var requestCacheBust = sendRequest.bind({
|
var requestCacheBust = sendRequest.bind({
|
||||||
options: {
|
options: {
|
||||||
cacheBust: true,
|
cacheBust: true
|
||||||
},
|
}
|
||||||
})
|
})
|
||||||
|
|
||||||
t.test("- pending request is aborted", function(t) {
|
t.test("- pending request is aborted", function(t) {
|
||||||
|
|||||||
@@ -7,8 +7,7 @@ var trigger = require("../../lib/events/trigger")
|
|||||||
var el = document.createElement("div")
|
var el = document.createElement("div")
|
||||||
var el2 = document.createElement("span")
|
var el2 = document.createElement("span")
|
||||||
var els = [el, el2]
|
var els = [el, el2]
|
||||||
// var eventType2 = "resize"
|
|
||||||
// var eventsType = "click resize"
|
|
||||||
var classCb = function() {
|
var classCb = function() {
|
||||||
this.className += "on"
|
this.className += "on"
|
||||||
}
|
}
|
||||||
@@ -92,14 +91,14 @@ tape("test events on/off/trigger for multiple elements, multiple events", functi
|
|||||||
})
|
})
|
||||||
|
|
||||||
tape("test events on top level elements", function(t) {
|
tape("test events on top level elements", function(t) {
|
||||||
var el = document;
|
var el = document
|
||||||
|
|
||||||
el.className = ""
|
el.className = ""
|
||||||
on(el, "click", classCb)
|
on(el, "click", classCb)
|
||||||
trigger(el, "click")
|
trigger(el, "click")
|
||||||
t.equal(el.className, "on", "attached callback has been fired properly on document")
|
t.equal(el.className, "on", "attached callback has been fired properly on document")
|
||||||
|
|
||||||
el = window;
|
el = window
|
||||||
|
|
||||||
el.className = ""
|
el.className = ""
|
||||||
// With jsdom, the default this is global, not window, so we need to explicitly bind to window.
|
// With jsdom, the default this is global, not window, so we need to explicitly bind to window.
|
||||||
|
|||||||
@@ -80,17 +80,16 @@ tape("test attach form preventDefaulted events", function(t) {
|
|||||||
tape("test options are not modified by attachForm", function(t) {
|
tape("test options are not modified by attachForm", function(t) {
|
||||||
var form = document.createElement("form")
|
var form = document.createElement("form")
|
||||||
var options = {foo: "bar"}
|
var options = {foo: "bar"}
|
||||||
var loadUrl = () => {}
|
var loadUrl = function() {}
|
||||||
|
|
||||||
attachForm.call({options, loadUrl}, form)
|
attachForm.call({options: options, loadUrl: loadUrl}, form)
|
||||||
|
|
||||||
var internalUri = window.location.protocol + "//" + window.location.host + window.location.pathname + window.location.search
|
form.action = window.location.protocol + "//" + window.location.host + window.location.pathname + window.location.search
|
||||||
form.action = internalUri
|
|
||||||
form.method = "GET"
|
form.method = "GET"
|
||||||
trigger(form, "submit")
|
trigger(form, "submit")
|
||||||
|
|
||||||
t.equal(1, Object.keys(options).length, "options object that is passed in should not be modified")
|
t.equal(1, Object.keys(options).length, "options object that is passed in should not be modified")
|
||||||
t.equal("bar", options.foo, "options object that is passed in should not be modified")
|
t.equal("bar", options.foo, "options object that is passed in should not be modified")
|
||||||
|
|
||||||
t.end();
|
t.end()
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -79,17 +79,16 @@ tape("test attach link preventDefaulted events", function(t) {
|
|||||||
tape("test options are not modified by attachLink", function(t) {
|
tape("test options are not modified by attachLink", function(t) {
|
||||||
var a = document.createElement("a")
|
var a = document.createElement("a")
|
||||||
var options = {foo: "bar"}
|
var options = {foo: "bar"}
|
||||||
var loadUrl = () => {};
|
var loadUrl = function() {}
|
||||||
|
|
||||||
attachLink.call({options, loadUrl}, a)
|
attachLink.call({options: options, loadUrl: loadUrl}, a)
|
||||||
|
|
||||||
var internalUri = window.location.protocol + "//" + window.location.host + window.location.pathname + window.location.search
|
a.href = window.location.protocol + "//" + window.location.host + window.location.pathname + window.location.search
|
||||||
a.href = internalUri
|
|
||||||
|
|
||||||
trigger(a, "click")
|
trigger(a, "click")
|
||||||
|
|
||||||
t.equal(1, Object.keys(options).length, "options object that is passed in should not be modified")
|
t.equal(1, Object.keys(options).length, "options object that is passed in should not be modified")
|
||||||
t.equal("bar", options.foo, "options object that is passed in should not be modified")
|
t.equal("bar", options.foo, "options object that is passed in should not be modified")
|
||||||
|
|
||||||
t.end();
|
t.end()
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -2,72 +2,48 @@ var tape = require("tape")
|
|||||||
|
|
||||||
var parseOptions = require("../../../lib/proto/parse-options.js")
|
var parseOptions = require("../../../lib/proto/parse-options.js")
|
||||||
tape("test parse initalization options function", function(t) {
|
tape("test parse initalization options function", function(t) {
|
||||||
// via http://stackoverflow.com/questions/1173549/how-to-determine-if-an-object-is-an-object-literal-in-javascript
|
|
||||||
function isObjLiteral(_obj) {
|
|
||||||
var _test = _obj;
|
|
||||||
return (typeof _obj !== "object" || _obj === null ?
|
|
||||||
false :
|
|
||||||
(
|
|
||||||
(function() {
|
|
||||||
while (!false) {
|
|
||||||
if (Object.getPrototypeOf(_test = Object.getPrototypeOf(_test)) === null) {
|
|
||||||
break;
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return Object.getPrototypeOf(_obj) === _test;
|
|
||||||
})()
|
|
||||||
)
|
|
||||||
);
|
|
||||||
}
|
|
||||||
|
|
||||||
function enumerableKeys(_obj) {
|
|
||||||
var c = 0;
|
|
||||||
for (var n in _obj) {
|
|
||||||
n = n;
|
|
||||||
c++;
|
|
||||||
}
|
|
||||||
return c;
|
|
||||||
}
|
|
||||||
|
|
||||||
t.test("- default options", function(t) {
|
t.test("- default options", function(t) {
|
||||||
var body1 = {};
|
var pjax = {}
|
||||||
var options1 = {};
|
parseOptions.call(pjax, {})
|
||||||
parseOptions.apply(body1, [options1]);
|
|
||||||
|
|
||||||
t.equal(body1.options.elements, "a[href], form[action]");
|
t.equal(pjax.options.elements, "a[href], form[action]")
|
||||||
t.equal(body1.options.selectors.length, 2, "selectors length");
|
t.equal(pjax.options.selectors.length, 2, "selectors length")
|
||||||
t.equal(body1.options.selectors[0], "title");
|
t.equal(pjax.options.selectors[0], "title")
|
||||||
t.equal(body1.options.selectors[1], ".js-Pjax");
|
t.equal(pjax.options.selectors[1], ".js-Pjax")
|
||||||
t.equal(isObjLiteral(body1.options.switches), true);
|
|
||||||
t.equal(enumerableKeys(body1.options.switches), 2);// head and body
|
t.equal(typeof pjax.options.switches, "object")
|
||||||
t.equal(isObjLiteral(body1.options.switchesOptions), true);
|
t.equal(Object.keys(pjax.options.switches).length, 2)// head and body
|
||||||
t.equal(enumerableKeys(body1.options.switchesOptions), 0);
|
|
||||||
t.equal(body1.options.history, true);
|
t.equal(typeof pjax.options.switchesOptions, "object")
|
||||||
t.equal(typeof body1.options.analytics, "function");
|
t.equal(Object.keys(pjax.options.switchesOptions).length, 0)
|
||||||
t.equal(body1.options.scrollTo, 0);
|
|
||||||
t.equal(body1.options.scrollRestoration, true);
|
t.equal(pjax.options.history, true)
|
||||||
t.equal(body1.options.cacheBust, true);
|
t.equal(typeof pjax.options.analytics, "function")
|
||||||
t.equal(body1.options.debug, false);
|
t.equal(pjax.options.scrollTo, 0)
|
||||||
t.end();
|
t.equal(pjax.options.scrollRestoration, true)
|
||||||
});
|
t.equal(pjax.options.cacheBust, true)
|
||||||
|
t.equal(pjax.options.debug, false)
|
||||||
|
t.equal(pjax.options.currentUrlFullReload, false)
|
||||||
|
t.end()
|
||||||
|
})
|
||||||
|
|
||||||
// verify analytics always ends up as a function even when passed not a function
|
// verify analytics always ends up as a function even when passed not a function
|
||||||
t.test("- analytics is a function", function(t) {
|
t.test("- analytics is a function", function(t) {
|
||||||
var body2 = {};
|
var pjax = {}
|
||||||
var options2 = {analytics: "some string"};
|
parseOptions.call(pjax, {analytics: "some string"})
|
||||||
parseOptions.apply(body2, [options2]);
|
|
||||||
|
t.deepEqual(typeof pjax.options.analytics, "function")
|
||||||
|
t.end()
|
||||||
|
})
|
||||||
|
|
||||||
|
// verify that the value false for scrollTo is not squashed
|
||||||
|
t.test("- scrollTo remains false", function(t) {
|
||||||
|
var pjax = {}
|
||||||
|
parseOptions.call(pjax, {scrollTo: false})
|
||||||
|
|
||||||
|
t.deepEqual(pjax.options.scrollTo, false)
|
||||||
|
t.end()
|
||||||
|
})
|
||||||
|
|
||||||
t.deepEqual(typeof body2.options.analytics, "function");
|
|
||||||
t.end();
|
|
||||||
});
|
|
||||||
// verify that the value false for scrollTo is not squashed
|
|
||||||
t.test("- scrollTo remains false", function(t) {
|
|
||||||
var body3 = {};
|
|
||||||
var options3 = {scrollTo: false};
|
|
||||||
parseOptions.apply(body3, [options3]);
|
|
||||||
|
|
||||||
t.deepEqual(body3.options.scrollTo, false);
|
|
||||||
t.end();
|
|
||||||
});
|
|
||||||
t.end()
|
t.end()
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -20,9 +20,9 @@ tape("test xhr request", function(t) {
|
|||||||
t.test("- request is made, gets a result, and is cache-busted", function(t) {
|
t.test("- request is made, gets a result, and is cache-busted", function(t) {
|
||||||
var requestCacheBust = sendRequest.bind({
|
var requestCacheBust = sendRequest.bind({
|
||||||
options: {
|
options: {
|
||||||
cacheBust: true,
|
cacheBust: true
|
||||||
},
|
}
|
||||||
});
|
})
|
||||||
var r = requestCacheBust(url, {}, function(result) {
|
var r = requestCacheBust(url, {}, function(result) {
|
||||||
t.equal(r.responseURL.indexOf("?"), url.length, "XHR URL is cache-busted when configured to be")
|
t.equal(r.responseURL.indexOf("?"), url.length, "XHR URL is cache-busted when configured to be")
|
||||||
try {
|
try {
|
||||||
@@ -38,9 +38,9 @@ tape("test xhr request", function(t) {
|
|||||||
t.test("- request is not cache-busted when configured not to be", function(t) {
|
t.test("- request is not cache-busted when configured not to be", function(t) {
|
||||||
var requestNoCacheBust = sendRequest.bind({
|
var requestNoCacheBust = sendRequest.bind({
|
||||||
options: {
|
options: {
|
||||||
cacheBust: false,
|
cacheBust: false
|
||||||
},
|
}
|
||||||
});
|
})
|
||||||
var r = requestNoCacheBust(url, {}, function() {
|
var r = requestNoCacheBust(url, {}, function() {
|
||||||
t.equal(r.responseURL, url, "XHR URL is left untouched")
|
t.equal(r.responseURL, url, "XHR URL is left untouched")
|
||||||
t.end()
|
t.end()
|
||||||
|
|||||||
Reference in New Issue
Block a user