loadUrl enhancements
#134
26
README.md
26
README.md
@@ -124,9 +124,13 @@ To see if Pjax is actually supported by your browser, use `Pjax.isSupported()`.
|
|||||||
|
|
||||||
## Usage
|
## Usage
|
||||||
|
|
||||||
### `new Pjax()`
|
### Methods
|
||||||
|
|
||||||
Let's talk more about the most basic way to get started:
|
#### `new Pjax()`
|
||||||
|
|
||||||
|
Let's talk more about the most basic way to get started.
|
||||||
|
|
||||||
|
When instantiating `Pjax`, you can pass options in to the constructor as an object:
|
||||||
|
|
||||||
```js
|
```js
|
||||||
new Pjax({
|
new Pjax({
|
||||||
@@ -153,12 +157,24 @@ Pjax.prototype.getElements = function() {
|
|||||||
return document.getElementsByClassName(".js-Pjax")
|
return document.getElementsByClassName(".js-Pjax")
|
||||||
}
|
}
|
||||||
|
|
||||||
new Pjax({})
|
new Pjax()
|
||||||
```
|
```
|
||||||
|
|
||||||
When instantiating a `Pjax` object, you need to pass all options as an object:
|
#### `loadUrl(href, [options])`
|
||||||
|
|
||||||
#### Options
|
With this method, you can manually trigger loading of a URL:
|
||||||
|
|
||||||
|
```js
|
||||||
|
var pjax = new Pjax()
|
||||||
|
|
||||||
|
// use case 1 (without options override)
|
||||||
|
pjax.loadUrl("/your-url")
|
||||||
|
|
||||||
|
// use case 2 (with options override)
|
||||||
|
pjax.loadUrl("/your-other-url", {timeout: 10})
|
||||||
|
```
|
||||||
|
|
||||||
|
### Options
|
||||||
|
|
||||||
##### `elements` (String, default: `"a[href], form[action]"`)
|
##### `elements` (String, default: `"a[href], form[action]"`)
|
||||||
|
|
||||||
|
|||||||
@@ -1,4 +1,31 @@
|
|||||||
/* global Pjax */
|
/* global Pjax */
|
||||||
|
var pjax;
|
||||||
|
var initButtons = function() {
|
||||||
|
var buttons = document.querySelectorAll("button[data-manual-trigger]")
|
||||||
|
|
||||||
|
if (!buttons) {
|
||||||
|
return
|
||||||
|
}
|
||||||
|
|
||||||
|
// jshint -W083
|
||||||
|
for (var i = 0; i < buttons.length; i++) {
|
||||||
|
buttons[i].addEventListener("click", function(e) {
|
||||||
|
var el = e.currentTarget
|
||||||
|
|
||||||
|
if (el.getAttribute("data-manual-trigger-override") === "true") {
|
||||||
|
// Manually load URL with overridden Pjax instance options
|
||||||
|
pjax.loadUrl("/example/page2.html", {cacheBust: false})
|
||||||
|
}
|
||||||
|
else
|
||||||
|
{
|
||||||
|
// Manually load URL with current Pjax instance options
|
||||||
|
pjax.loadUrl("/example/page2.html")
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
// jshint +W083
|
||||||
|
}
|
||||||
|
|
||||||
console.log("Document initialized:", window.location.href)
|
console.log("Document initialized:", window.location.href)
|
||||||
|
|
||||||
document.addEventListener("pjax:send", function() {
|
document.addEventListener("pjax:send", function() {
|
||||||
@@ -15,14 +42,20 @@ document.addEventListener("pjax:error", function() {
|
|||||||
|
|
||||||
document.addEventListener("pjax:success", function() {
|
document.addEventListener("pjax:success", function() {
|
||||||
console.log("Event: pjax:success", arguments)
|
console.log("Event: pjax:success", arguments)
|
||||||
|
|
||||||
|
// Init page content
|
||||||
|
initButtons()
|
||||||
})
|
})
|
||||||
|
|
||||||
document.addEventListener("DOMContentLoaded", function() {
|
document.addEventListener("DOMContentLoaded", function() {
|
||||||
var pjax = new Pjax({
|
// Init Pjax instance
|
||||||
|
pjax = new Pjax({
|
||||||
elements: [".js-Pjax"],
|
elements: [".js-Pjax"],
|
||||||
selectors: [".body", "title"],
|
selectors: [".body", "title"],
|
||||||
cacheBust: true,
|
cacheBust: true
|
||||||
// currentUrlFullReload: true,
|
|
||||||
})
|
})
|
||||||
console.log("Pjax initialized.", pjax)
|
console.log("Pjax initialized.", pjax)
|
||||||
|
|
||||||
|
// Init page content
|
||||||
|
initButtons()
|
||||||
})
|
})
|
||||||
|
|||||||
@@ -13,6 +13,13 @@
|
|||||||
Go to <a href="page2.html" class="js-Pjax">Page 2</a> or <a href="page3.html" class="js-Pjax">Page 3</a> and view your console to see Pjax events.
|
Go to <a href="page2.html" class="js-Pjax">Page 2</a> or <a href="page3.html" class="js-Pjax">Page 3</a> and view your console to see Pjax events.
|
||||||
Clicking on <a href="index.html">this page</a> will just reload the page entirely.
|
Clicking on <a href="index.html">this page</a> will just reload the page entirely.
|
||||||
|
|
||||||
|
<h2>Manual URL loading</h2>
|
||||||
|
|
||||||
|
You can use Pjax's <i>loadUrl</i> method to manually load a URL. Click the buttons below to try it out!<br /><br />
|
||||||
|
|
||||||
|
<button data-manual-trigger>loadUrl with current options</button><br /><br />
|
||||||
|
<button data-manual-trigger data-manual-trigger-override="true">loadUrl with overridden options (no cache busting)</button>
|
||||||
|
|
||||||
<h2>Forms</h2>
|
<h2>Forms</h2>
|
||||||
|
|
||||||
You can submit GET or POST forms with Pjax! Go to the <a href="forms.html">form examples</a> to try it out.
|
You can submit GET or POST forms with Pjax! Go to the <a href="forms.html">form examples</a> to try it out.
|
||||||
|
|||||||
16
index.js
16
index.js
@@ -1,13 +1,15 @@
|
|||||||
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 parseOptions = require("./lib/parse-options.js")
|
||||||
var switches = require("./lib/switches")
|
var switches = require("./lib/switches")
|
||||||
var newUid = require("./lib/uniqueid.js")
|
var newUid = require("./lib/uniqueid.js")
|
||||||
|
|
||||||
var on = require("./lib/events/on.js")
|
var on = require("./lib/events/on.js")
|
||||||
var trigger = require("./lib/events/trigger.js")
|
var trigger = require("./lib/events/trigger.js")
|
||||||
|
|
||||||
|
var clone = require("./lib/util/clone.js")
|
||||||
var contains = require("./lib/util/contains.js")
|
var contains = require("./lib/util/contains.js")
|
||||||
|
var extend = require("./lib/util/extend.js")
|
||||||
var noop = require("./lib/util/noop")
|
var noop = require("./lib/util/noop")
|
||||||
|
|
||||||
var Pjax = function(options) {
|
var Pjax = function(options) {
|
||||||
@@ -17,8 +19,8 @@ var Pjax = function(options) {
|
|||||||
options: null
|
options: null
|
||||||
}
|
}
|
||||||
|
|
||||||
var parseOptions = require("./lib/proto/parse-options.js")
|
|
||||||
parseOptions.call(this,options)
|
this.options = parseOptions(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) {
|
||||||
@@ -35,7 +37,6 @@ 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.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
|
||||||
@@ -142,6 +143,10 @@ Pjax.prototype = {
|
|||||||
doRequest: require("./lib/send-request.js"),
|
doRequest: require("./lib/send-request.js"),
|
||||||
|
|
||||||
loadUrl: function(href, options) {
|
loadUrl: function(href, options) {
|
||||||
|
options = typeof options === "object" ?
|
||||||
|
extend({}, this.options, options) :
|
||||||
|
clone(this.options)
|
||||||
|
|
||||||
this.log("load href", href, options)
|
this.log("load href", href, options)
|
||||||
|
|
||||||
// Abort any previous request
|
// Abort any previous request
|
||||||
@@ -150,8 +155,7 @@ Pjax.prototype = {
|
|||||||
trigger(document, "pjax:send", options)
|
trigger(document, "pjax:send", options)
|
||||||
|
|
||||||
// Do the request
|
// Do the request
|
||||||
options.requestOptions.timeout = this.options.timeout
|
this.request = this.doRequest(href, options, function(html, request) {
|
||||||
this.request = this.doRequest(href, options.requestOptions, function(html, request) {
|
|
||||||
// Fail if unable to load HTML via AJAX
|
// Fail if unable to load HTML via AJAX
|
||||||
if (html === false) {
|
if (html === false) {
|
||||||
trigger(document, "pjax:complete pjax:error", options)
|
trigger(document, "pjax:complete pjax:error", options)
|
||||||
|
|||||||
@@ -1,6 +1,6 @@
|
|||||||
/* global _gaq: true, ga: true */
|
/* global _gaq: true, ga: true */
|
||||||
|
|
||||||
var defaultSwitches = require("../switches")
|
var defaultSwitches = require("./switches")
|
||||||
|
|
||||||
module.exports = function(options) {
|
module.exports = function(options) {
|
||||||
options = options || {}
|
options = options || {}
|
||||||
@@ -36,5 +36,5 @@ module.exports = function(options) {
|
|||||||
options.switches.body = defaultSwitches.switchElementsAlt
|
options.switches.body = defaultSwitches.switchElementsAlt
|
||||||
}
|
}
|
||||||
|
|
||||||
this.options = options
|
return options
|
||||||
}
|
}
|
||||||
@@ -1,5 +1,5 @@
|
|||||||
var on = require("../events/on")
|
var on = require("../events/on")
|
||||||
var clone = require("../clone")
|
var clone = require("../util/clone")
|
||||||
|
|
||||||
var attrClick = "data-pjax-click-state"
|
var attrClick = "data-pjax-click-state"
|
||||||
|
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
var on = require("../events/on")
|
var on = require("../events/on")
|
||||||
var clone = require("../clone")
|
var clone = require("../util/clone")
|
||||||
|
|
||||||
var attrClick = "data-pjax-click-state"
|
var attrClick = "data-pjax-click-state"
|
||||||
var attrKey = "data-pjax-keyup-state"
|
var attrKey = "data-pjax-keyup-state"
|
||||||
@@ -9,9 +9,6 @@ var linkAction = function(el, event) {
|
|||||||
// 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
|
|
||||||
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) {
|
||||||
el.setAttribute(attrClick, "modifier")
|
el.setAttribute(attrClick, "modifier")
|
||||||
|
|||||||
@@ -3,10 +3,12 @@ var updateQueryString = require("./util/update-query-string");
|
|||||||
module.exports = function(location, options, callback) {
|
module.exports = function(location, options, callback) {
|
||||||
options = options || {}
|
options = options || {}
|
||||||
var queryString
|
var queryString
|
||||||
var requestMethod = (options.requestMethod || "GET").toUpperCase()
|
var requestOptions = options.requestOptions || {}
|
||||||
var requestParams = options.requestParams || null
|
var requestMethod = (requestOptions.requestMethod || "GET").toUpperCase()
|
||||||
|
var requestParams = requestOptions.requestParams || null
|
||||||
var requestPayload = null
|
var requestPayload = null
|
||||||
var request = new XMLHttpRequest()
|
var request = new XMLHttpRequest()
|
||||||
|
var timeout = options.timeout || 0
|
||||||
|
|
||||||
request.onreadystatechange = function() {
|
request.onreadystatechange = function() {
|
||||||
if (request.readyState === 4) {
|
if (request.readyState === 4) {
|
||||||
@@ -51,12 +53,12 @@ module.exports = function(location, options, callback) {
|
|||||||
}
|
}
|
||||||
|
|
||||||
// Add a timestamp as part of the query string if cache busting is enabled
|
// Add a timestamp as part of the query string if cache busting is enabled
|
||||||
if (this.options.cacheBust) {
|
if (options.cacheBust) {
|
||||||
location = updateQueryString(location, "t", Date.now())
|
location = updateQueryString(location, "t", Date.now())
|
||||||
}
|
}
|
||||||
|
|
||||||
request.open(requestMethod, location, true)
|
request.open(requestMethod, location, true)
|
||||||
request.timeout = options.timeout
|
request.timeout = timeout
|
||||||
request.setRequestHeader("X-Requested-With", "XMLHttpRequest")
|
request.setRequestHeader("X-Requested-With", "XMLHttpRequest")
|
||||||
request.setRequestHeader("X-PJAX", "true")
|
request.setRequestHeader("X-PJAX", "true")
|
||||||
|
|
||||||
|
|||||||
21
lib/util/extend.js
Normal file
21
lib/util/extend.js
Normal file
@@ -0,0 +1,21 @@
|
|||||||
|
module.exports = function(target) {
|
||||||
|
if (target == null) {
|
||||||
|
return target
|
||||||
|
}
|
||||||
|
|
||||||
|
var to = Object(target)
|
||||||
|
|
||||||
|
for (var i = 1; i < arguments.length; i++) {
|
||||||
|
var source = arguments[i]
|
||||||
|
|
||||||
|
if (source != null) {
|
||||||
|
for (var key in source) {
|
||||||
|
// Avoid bugs when hasOwnProperty is shadowed
|
||||||
|
if (Object.prototype.hasOwnProperty.call(source, key)) {
|
||||||
|
to[key] = source[key]
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return to
|
||||||
|
}
|
||||||
@@ -1,17 +0,0 @@
|
|||||||
var tape = require("tape")
|
|
||||||
|
|
||||||
var clone = require("../../lib/clone")
|
|
||||||
|
|
||||||
tape("test clone method", function(t) {
|
|
||||||
var obj = {one: 1, two: 2}
|
|
||||||
var cloned = clone(obj)
|
|
||||||
|
|
||||||
t.notEqual(obj, cloned, "cloned object isn't the object")
|
|
||||||
|
|
||||||
t.same(obj, cloned, "cloned object have the same values than object")
|
|
||||||
|
|
||||||
cloned.tree = 3
|
|
||||||
t.notSame(obj, cloned, "modified cloned object haven't the same values than object")
|
|
||||||
|
|
||||||
t.end()
|
|
||||||
})
|
|
||||||
@@ -1,10 +1,10 @@
|
|||||||
var tape = require("tape")
|
var tape = require("tape")
|
||||||
|
|
||||||
var parseOptions = require("../../../lib/proto/parse-options.js")
|
var parseOptions = require("../../lib/parse-options.js")
|
||||||
tape("test parse initalization options function", function(t) {
|
tape("test parse initalization options function", function(t) {
|
||||||
t.test("- default options", function(t) {
|
t.test("- default options", function(t) {
|
||||||
var pjax = {}
|
var pjax = {}
|
||||||
parseOptions.call(pjax, {})
|
pjax.options = parseOptions({})
|
||||||
|
|
||||||
t.equal(pjax.options.elements, "a[href], form[action]")
|
t.equal(pjax.options.elements, "a[href], form[action]")
|
||||||
t.equal(pjax.options.selectors.length, 2, "selectors length")
|
t.equal(pjax.options.selectors.length, 2, "selectors length")
|
||||||
@@ -30,7 +30,7 @@ tape("test parse initalization options function", function(t) {
|
|||||||
// 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 pjax = {}
|
var pjax = {}
|
||||||
parseOptions.call(pjax, {analytics: "some string"})
|
pjax.options = parseOptions({analytics: "some string"})
|
||||||
|
|
||||||
t.deepEqual(typeof pjax.options.analytics, "function")
|
t.deepEqual(typeof pjax.options.analytics, "function")
|
||||||
t.end()
|
t.end()
|
||||||
@@ -39,7 +39,7 @@ tape("test parse initalization options function", function(t) {
|
|||||||
// verify that the value false for scrollTo is not squashed
|
// verify that the value false for scrollTo is not squashed
|
||||||
t.test("- scrollTo remains false", function(t) {
|
t.test("- scrollTo remains false", function(t) {
|
||||||
var pjax = {}
|
var pjax = {}
|
||||||
parseOptions.call(pjax, {scrollTo: false})
|
pjax.options = parseOptions({scrollTo: false})
|
||||||
|
|
||||||
t.deepEqual(pjax.options.scrollTo, false)
|
t.deepEqual(pjax.options.scrollTo, false)
|
||||||
t.end()
|
t.end()
|
||||||
@@ -18,12 +18,7 @@ tape("test xhr request", function(t) {
|
|||||||
var url = "https://httpbin.org/get"
|
var url = "https://httpbin.org/get"
|
||||||
|
|
||||||
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 r = sendRequest(url, {cacheBust: true}, function(result) {
|
||||||
options: {
|
|
||||||
cacheBust: true
|
|
||||||
}
|
|
||||||
})
|
|
||||||
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 {
|
||||||
result = JSON.parse(result)
|
result = JSON.parse(result)
|
||||||
@@ -36,12 +31,7 @@ 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 r = sendRequest(url, {}, function() {
|
||||||
options: {
|
|
||||||
cacheBust: false
|
|
||||||
}
|
|
||||||
})
|
|
||||||
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()
|
||||||
})
|
})
|
||||||
|
|||||||
17
tests/lib/util/clone.js
Normal file
17
tests/lib/util/clone.js
Normal file
@@ -0,0 +1,17 @@
|
|||||||
|
var tape = require("tape")
|
||||||
|
|
||||||
|
var clone = require("../../../lib/util/clone")
|
||||||
|
|
||||||
|
tape("test clone method", function(t) {
|
||||||
|
var obj = {one: 1, two: 2}
|
||||||
|
var cloned = clone(obj)
|
||||||
|
|
||||||
|
t.notEqual(obj, cloned, "cloned object isn't the original object")
|
||||||
|
|
||||||
|
t.same(obj, cloned, "cloned object has the same values as original object")
|
||||||
|
|
||||||
|
cloned.three = 3
|
||||||
|
t.notSame(obj, cloned, "modified cloned object doesn't have the same values as original object")
|
||||||
|
|
||||||
|
t.end()
|
||||||
|
})
|
||||||
16
tests/lib/util/extend.js
Normal file
16
tests/lib/util/extend.js
Normal file
@@ -0,0 +1,16 @@
|
|||||||
|
var tape = require("tape")
|
||||||
|
|
||||||
|
var extend = require("../../../lib/util/extend")
|
||||||
|
|
||||||
|
tape("test extend method", function(t) {
|
||||||
|
var obj = {one: 1, two: 2}
|
||||||
|
var extended = extend({}, obj, {two: "two", three: 3})
|
||||||
|
|
||||||
|
t.notEqual(obj, extended, "extended object isn't the original object")
|
||||||
|
|
||||||
|
t.notSame(obj, extended, "extended object doesn't have the same values as original object")
|
||||||
|
|
||||||
|
t.notSame(obj.two, extended.two, "extended object value overwrites value from original object")
|
||||||
|
|
||||||
|
t.end()
|
||||||
|
})
|
||||||
Reference in New Issue
Block a user