Compare commits

...

25 Commits
0.2.3 ... dev

Author SHA1 Message Date
BehindTheMath
0916c74171 Merge pull request #93 from BehindTheMath/bugfix/add-switchElementsAlt
Add switchElementsAlt() to the default switches

Fixes #83.
2017-12-20 15:58:29 -05:00
Behind The Math
0781f820ee Add switchElementsAlt() to the default switches
Fixes #83.
2017-12-19 15:56:48 -05:00
Maxime Thirouin
a7b584c469 Add direct download link
Ref #57
2017-12-19 14:11:55 +01:00
Oskar
be5d58d550 Asynchronous switch functions (Make sure the DOM is parsed after switching) (#79)
* Make sure the DOM is parsed after switching

* Fix reload-link in the example
2017-12-19 13:58:22 +01:00
Bradley B Smith
1e40a0d70b Send the X-PJAX header with request (#80)
Make it more compatible with the jQuery PJAX and lets the server choose to optimize the response. Sending the list of selectors would be nice, too.
2017-12-19 13:56:30 +01:00
BehindTheMath
75eddfcab6 Add default switches to Pjax.switches (#92)
Fixes #68 and reverts #74
2017-12-19 13:49:26 +01:00
Maxime Thirouin
352e7114b6 Bye codesponsor 😢 2017-12-04 14:53:01 +01:00
markusfluer
af57adaafb Fixed #77 Fails on Internet Explorer 2017-11-02 13:02:17 +01:00
markusfluer
09f14fc86c Added evaluation of remote script tags 2017-11-02 12:51:36 +01:00
markusfluer
b17457f5a2 Fixed tests for request.js 2017-09-18 14:23:44 +02:00
markusfluer
86e5a2281a Added support do do a push-state ajax request with forms 2017-09-18 14:13:45 +02:00
Maxime Thirouin
109e78347f Update README.md 2017-09-14 21:45:39 +02:00
Markus Flür
cb3b6b8a5d Merge pull request #81 from CPTechnikVX/patch-1
Fix bug on IE11 preventing from ajax page refresh
2017-07-20 15:34:50 +02:00
CPTechnikVX
6dffeba21a Fix bug on IE11 preventing from ajax page refresh
It used to be fixed a long time ago, but was perhaps merged away...
2016-11-28 15:39:14 +01:00
Dale
acdd87ef3d README: Modified switches sidebySide example so it doesn't result in a undefined Type Error. (#74) 2016-09-27 07:07:28 +02:00
Maxime Thirouin
917c6f6bcb 0.2.4 2016-07-11 07:11:39 +02:00
Bart Nagel
b201b96a37 Polyfill XHR.responseURL so tests pass in old Safari (#73)
This property is only used in the tests. It doesn't exist in Safari 8
and before, so where it's not available this patch polyfills it,
allowing the test to continue.
2016-07-11 06:55:47 +02:00
Maxime Thirouin
eff7cfd452 Merge pull request #67 from compressed/refresh
Update refresh and handle attributes without values
2016-06-28 07:17:43 +02:00
Bart Nagel
7976f06043 Added: cacheBust option (#71)
* Refactor request test to allow further tests to be added

* Make cache-busting optional

Closes #70
2016-06-28 06:46:14 +02:00
Maxime Thirouin
ee530f4c0a 0.2.3 (bower) 2016-05-03 09:23:50 +02:00
Christopher Brickley
bf71894395 fix(attributes): for attributes without a value, add only the attribute
Some attributes, such as `itemscope` have no corresponding value. This
change allows them to still be set.
2016-04-19 12:15:39 -04:00
Christopher Brickley
beaa21fb3a fix(refresh): use this.parseDOM for refresh
Fix for issue mentioned in #36
2016-04-19 12:13:14 -04:00
Maxime Thirouin
b96b0f41a7 Merge pull request #66 from christophwolff/patch-1
Fix bracket in switches example
2016-04-05 17:20:49 +02:00
Christoph Wolff
6e113b2d06 Fix bracket in switches example 2016-04-05 16:40:52 +02:00
Maxime Thirouin
46912e6797 More logical npm publish (testling don't like to be spawn or something) 2016-03-24 13:34:11 +01:00
21 changed files with 355 additions and 67 deletions

View File

@@ -1,3 +1,13 @@
# 0.2.4 - 2016-06-28
- Fixed: ``refresh`` should now work (use `this.parseDOM` for refresh)
([#67](https://github.com/MoOx/pjax/pull/67) - @compressed)
- Fixed: Some attributes, such as `itemscope` have no corresponding value.
This change allows them to still be set.
([#67](https://github.com/MoOx/pjax/pull/67) - @compressed)
- Added: ``cacheBust`` option
([#71](https://github.com/MoOx/pjax/pull/71) - @tremby)
# 0.2.3 - 2016-03-24 # 0.2.3 - 2016-03-24
- Fixed: ``currentUrlFullReload`` option now works - Fixed: ``currentUrlFullReload`` option now works

View File

@@ -15,11 +15,26 @@ Especially for user that have low bandwidth connection._
**No more full page reload. No more lots of HTTP request.** **No more full page reload. No more lots of HTTP request.**
## Demo ## Demo
[You can see this running on my website](http://moox.io), with sexy CSS animations when switching pages. [You can see this running on my website](http://moox.io), with sexy CSS animations when switching pages.
## Installation
You can install pjax from **npm**
```shell
$ npm install pjax
```
Pjax can obviously be downloaded directly.
[https://unpkg.com/pjax/pjax.js](https://unpkg.com/pjax/pjax.js)
## No dependencies
_There is nothing you need. No jQuery or something._
## 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 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.
@@ -98,26 +113,6 @@ _Magic! For real!_ **There is completely no need to do anything on server side!*
- 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 hacked since every method is public (so overridable)
## Installation
You can install pjax from **npm**
```shell
$ npm install pjax
```
Or using **bower**
```shell
$ bower install pjax
```
Pjax can obviously be downloaded directly.
## No dependencies
_There is nothing you need. No jQuery or something._
## 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).
@@ -273,6 +268,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
@@ -381,6 +377,12 @@ It's called every time a page is switched, even for history buttons.
Value (in px) to scrollTo when a page is switched. Value (in px) to scrollTo when a page is switched.
##### `cacheBust` (Boolean, default true)
When set to true,
append a timestamp query string segment to the requested URLs
in order to skip browser cache.
##### `debug` (Boolean, default to false) ##### `debug` (Boolean, default to false)
Enable verbose mode & doesn't use fallback when there is an error. Enable verbose mode & doesn't use fallback when there is an error.

View File

@@ -1,6 +1,6 @@
{ {
"name": "pjax", "name": "pjax",
"version": "0.2.2", "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",

View File

@@ -19,7 +19,8 @@ document.addEventListener("pjax:success", function() {
document.addEventListener("DOMContentLoaded", function() { document.addEventListener("DOMContentLoaded", function() {
var pjax = new Pjax({ var pjax = new Pjax({
selectors: [".body"], elements: [".js-Pjax"],
selectors: [".body"]
// currentUrlFullReload: true, // currentUrlFullReload: true,
}) })
console.log("Pjax initialized.", pjax) console.log("Pjax initialized.", pjax)

View File

@@ -10,7 +10,7 @@
<div class='body'> <div class='body'>
<h1>Index</h1> <h1>Index</h1>
Hello. Hello.
Go to <a href='page2.html'>Page 2</a> and view your console to see Pjax events. Go to <a href='page2.html' class="js-Pjax">Page 2</a> and view your console to see Pjax events.
Clicking on <a href='index.html'>this page</a> will just reload the page entierly. Clicking on <a href='index.html'>this page</a> will just reload the page entierly.
</div> </div>
</body> </body>

View File

@@ -9,7 +9,7 @@
<body> <body>
<div class='body'> <div class='body'>
<h1>Page 2</h1> <h1>Page 2</h1>
Hello. Go to <a href='index.html'>Index</a>. Hello. Go to <a href='index.html' class="js-Pjax">Index</a>.
</div> </div>
</body> </body>
</html> </html>

View File

@@ -9,6 +9,8 @@ var on = require("./lib/events/on.js")
// var off = 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 Pjax = function(options) { var Pjax = function(options) {
this.firstrun = true this.firstrun = true
@@ -27,7 +29,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 = {};
if (st.state.uid < this.lastUid) { if (st.state.uid < this.lastUid) {
opt.backward = true opt.backward = true
} }
@@ -42,6 +44,8 @@ var Pjax = function(options) {
}.bind(this)) }.bind(this))
} }
Pjax.switches = defaultSwitches
Pjax.prototype = { Pjax.prototype = {
log: require("./lib/proto/log.js"), log: require("./lib/proto/log.js"),
@@ -55,6 +59,8 @@ Pjax.prototype = {
attachLink: require("./lib/proto/attach-link.js"), attachLink: require("./lib/proto/attach-link.js"),
attachForm: require("./lib/proto/attach-form.js"),
forEachSelectors: function(cb, context, DOMcontext) { forEachSelectors: function(cb, context, DOMcontext) {
return require("./lib/foreach-selectors.js").bind(this)(this.options.selectors, cb, context, DOMcontext) return require("./lib/foreach-selectors.js").bind(this)(this.options.selectors, cb, context, DOMcontext)
}, },
@@ -77,11 +83,12 @@ Pjax.prototype = {
}, },
onSwitch: function() { onSwitch: function() {
this.parseDOM(document)
trigger(window, "resize scroll") trigger(window, "resize scroll")
}, },
loadContent: function(html, options) { loadContent: function(html, options) {
var tmpEl = document.implementation.createHTMLDocument() var tmpEl = document.implementation.createHTMLDocument("pjax")
// parse HTML attributes to copy them // parse HTML attributes to copy them
// since we are forced to use documentElement.innerHTML (outerHTML can't be used for <html>) // since we are forced to use documentElement.innerHTML (outerHTML can't be used for <html>)
@@ -94,7 +101,12 @@ Pjax.prototype = {
matches.shift() matches.shift()
matches.forEach(function(htmlAttrib) { matches.forEach(function(htmlAttrib) {
var attr = htmlAttrib.trim().split("=") var attr = htmlAttrib.trim().split("=")
if (attr.length === 1) {
tmpEl.documentElement.setAttribute(attr[0], true)
}
else {
tmpEl.documentElement.setAttribute(attr[0], attr[1].slice(1, -1)) tmpEl.documentElement.setAttribute(attr[0], attr[1].slice(1, -1))
}
}) })
} }
} }
@@ -146,7 +158,7 @@ Pjax.prototype = {
trigger(document, "pjax:send", options); trigger(document, "pjax:send", options);
// Do the request // Do the request
this.doRequest(href, function(html) { this.doRequest(href, options.requestOptions, function(html) {
// 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)

View File

@@ -2,7 +2,8 @@ module.exports = function(el) {
// console.log("going to execute script", el) // console.log("going to execute script", el)
var code = (el.text || el.textContent || el.innerHTML || "") var code = (el.text || el.textContent || el.innerHTML || "")
var head = document.querySelector("head") || document.documentElement var src = (el.src || "");
var parent = el.parentNode || document.querySelector("head") || document.documentElement
var script = document.createElement("script") var script = document.createElement("script")
if (code.match("document.write")) { if (code.match("document.write")) {
@@ -13,6 +14,14 @@ module.exports = function(el) {
} }
script.type = "text/javascript" script.type = "text/javascript"
if (src != "") {
script.src = src;
script.onload = function() { document.dispatchEvent((new Event("pjax:complete"))); }
script.async = false; // force asynchronous loading of peripheral js
}
if (code != "") {
try { try {
script.appendChild(document.createTextNode(code)) script.appendChild(document.createTextNode(code))
} }
@@ -20,10 +29,14 @@ module.exports = function(el) {
// old IEs have funky script nodes // old IEs have funky script nodes
script.text = code script.text = code
} }
}
// execute // execute
head.insertBefore(script, head.firstChild) parent.appendChild(script);
head.removeChild(script) // avoid pollution // avoid pollution only in head or body tags
if (["head","body"].indexOf(parent.tagName.toLowerCase()) > 0) {
return true parent.removeChild(script)
}
return true;
} }

View File

@@ -4,12 +4,17 @@ var evalScript = require("./eval-script")
// 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) // console.log("going to execute scripts for ", el)
if (el.tagName.toLowerCase() === "script") {
evalScript(el);
}
forEachEls(el.querySelectorAll("script"), function(script) { forEachEls(el.querySelectorAll("script"), function(script) {
if (!script.type || script.type.toLowerCase() === "text/javascript") { if (!script.type || script.type.toLowerCase() === "text/javascript") {
if (script.parentNode) { if (script.parentNode) {
script.parentNode.removeChild(script) script.parentNode.removeChild(script)
} }
evalScript(script) evalScript(script);
} }
}) });
} }

93
lib/proto/attach-form.js Normal file
View File

@@ -0,0 +1,93 @@
require("../polyfills/Function.prototype.bind")
var on = require("../events/on")
var clone = require("../clone")
var attrClick = "data-pjax-click-state"
var formAction = function(el, event){
this.options.requestOptions = {
requestUrl : el.getAttribute('action') || window.location.href,
requestMethod : el.getAttribute('method') || 'GET',
}
//create a testable virtual link of the form action
var virtLinkElement = document.createElement('a');
virtLinkElement.setAttribute('href', this.options.requestOptions.requestUrl);
// Ignore external links.
if (virtLinkElement.protocol !== window.location.protocol || virtLinkElement.host !== window.location.host) {
el.setAttribute(attrClick, "external");
return
}
// Ignore click if we are on an anchor on the same page
if (virtLinkElement.pathname === window.location.pathname && virtLinkElement.hash.length > 0) {
el.setAttribute(attrClick, "anchor-present");
return
}
// Ignore empty anchor "foo.html#"
if (virtLinkElement.href === window.location.href.split("#")[0] + "#") {
el.setAttribute(attrClick, "anchor-empty")
return
}
// if declared as a full reload, just normally submit the form
if ( this.options.currentUrlFullReload) {
el.setAttribute(attrClick, "reload");
return;
}
event.preventDefault()
var paramObject = [];
for(var elementKey in el.elements) {
var element = el.elements[elementKey];
if (!!element.name && element.attributes !== undefined && element.tagName.toLowerCase() !== 'button'){
if ((element.attributes.type !== 'checkbox' && element.attributes.type !== 'radio') || element.checked) {
paramObject.push({ name: encodeURIComponent(element.name), value: encodeURIComponent(element.value)});
}
}
}
//Creating a getString
var paramsString = (paramObject.map(function(value){return value.name+"="+value.value;})).join('&');
this.options.requestOptions.requestPayload = paramObject;
this.options.requestOptions.requestPayloadString = paramsString;
el.setAttribute(attrClick, "submit");
this.loadUrl(virtLinkElement.href, clone(this.options))
};
var isDefaultPrevented = function(event) {
return event.defaultPrevented || event.returnValue === false;
};
module.exports = function(el) {
var that = this
on(el, "submit", function(event) {
if (isDefaultPrevented(event)) {
return
}
formAction.call(that, el, event)
})
on(el, "keyup", function(event) {
if (isDefaultPrevented(event)) {
return
}
if (event.keyCode == 13) {
formAction.call(that, el, event)
}
}.bind(this))
}

View File

@@ -51,7 +51,7 @@ var linkAction = function(el, event) {
this.reload() this.reload()
return return
} }
this.options.requestOptions = this.options.requestOptions || {};
el.setAttribute(attrClick, "load") el.setAttribute(attrClick, "load")
this.loadUrl(el.href, clone(this.options)) this.loadUrl(el.href, clone(this.options))
} }

View File

@@ -8,7 +8,10 @@ module.exports = function(el) {
break break
case "form": case "form":
throw "Pjax doesnt support <form> yet." // only attach link if el does not already have link attached
if (!el.hasAttribute('data-pjax-click-state')) {
this.attachForm(el)
}
break break
default: default:

View File

@@ -1,5 +1,7 @@
/* global _gaq: true, ga: true */ /* global _gaq: true, ga: true */
var defaultSwitches = require("../switches")
module.exports = function(options){ module.exports = function(options){
this.options = options this.options = options
this.options.elements = this.options.elements || "a[href], form[action]" this.options.elements = this.options.elements || "a[href], form[action]"
@@ -19,6 +21,7 @@ module.exports = function(options){
} }
} }
this.options.scrollTo = (typeof this.options.scrollTo === 'undefined') ? 0 : this.options.scrollTo; this.options.scrollTo = (typeof this.options.scrollTo === 'undefined') ? 0 : this.options.scrollTo;
this.options.cacheBust = (typeof this.options.cacheBust === 'undefined') ? true : this.options.cacheBust
this.options.debug = this.options.debug || false this.options.debug = this.options.debug || false
// we cant replace body.outerHTML or head.outerHTML // we cant replace body.outerHTML or head.outerHTML
@@ -26,10 +29,10 @@ module.exports = function(options){
// 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 get 2 body
// & it break the switchFallback which replace head & body // & it break the switchFallback which replace head & body
if (!this.options.switches.head) { if (!this.options.switches.head) {
this.options.switches.head = this.switchElementsAlt this.options.switches.head = defaultSwitches.switchElementsAlt
} }
if (!this.options.switches.body) { if (!this.options.switches.body) {
this.options.switches.body = this.switchElementsAlt this.options.switches.body = defaultSwitches.switchElementsAlt
} }
if (typeof options.analytics !== "function") { if (typeof options.analytics !== "function") {
options.analytics = function() {} options.analytics = function() {}

View File

@@ -1,6 +1,3 @@
var parseDom = require("./parse-dom")
module.exports = function(el) { module.exports = function(el) {
parseDom(el || document) this.parseDOM(el || document)
} }

View File

@@ -1,4 +1,7 @@
module.exports = function(location, callback) { module.exports = function(location, options, callback) {
options = options || {};
var requestMethod = options.requestMethod || "GET";
var requestPayload = options.requestPayloadString || null;
var request = new XMLHttpRequest() var request = new XMLHttpRequest()
request.onreadystatechange = function() { request.onreadystatechange = function() {
@@ -12,8 +15,22 @@ module.exports = function(location, callback) {
} }
} }
request.open("GET", location + (!/[?&]/.test(location) ? "?" : "&") + (new Date().getTime()), true) // Add a timestamp as part of the query string if cache busting is enabled
if (this.options.cacheBust) {
location += (!/[?&]/.test(location) ? "?" : "&") + new Date().getTime()
}
request.open(requestMethod.toUpperCase(), location, true)
request.setRequestHeader("X-Requested-With", "XMLHttpRequest") request.setRequestHeader("X-Requested-With", "XMLHttpRequest")
request.send(null) request.setRequestHeader("X-PJAX", "true")
// Add the request payload if available
if (options.requestPayloadString != undefined && options.requestPayloadString != "") {
// Send the proper header information along with the request
request.setRequestHeader("Content-type", "application/x-www-form-urlencoded");
}
request.send(requestPayload)
return request return request
} }

View File

@@ -15,6 +15,20 @@ module.exports = {
this.onSwitch() this.onSwitch()
}, },
switchElementsAlt: function(oldEl, newEl) {
oldEl.innerHTML = newEl.innerHTML
// Copy attributes from the new element to the old one
if (newEl.hasAttributes()) {
const attrs = newEl.attributes;
for (var i = 0; i < attrs.length; i++) {
oldEl.attributes.setNamedItem(attrs[i])
}
}
this.onSwitch()
},
sideBySide: function(oldEl, newEl, options, switchOptions) { sideBySide: function(oldEl, newEl, options, switchOptions) {
var forEach = Array.prototype.forEach var forEach = Array.prototype.forEach
var elsToRemove = [] var elsToRemove = []

View File

@@ -1,6 +1,6 @@
{ {
"name": "pjax", "name": "pjax",
"version": "0.2.3", "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",
@@ -26,6 +26,7 @@
"jscs": "^1.6.2", "jscs": "^1.6.2",
"jshint": "^2.5.6", "jshint": "^2.5.6",
"npmpub": "^3.1.0", "npmpub": "^3.1.0",
"opn-cli": "^3.1.0",
"serve": "1.4.0", "serve": "1.4.0",
"tape": "^3.0.0", "tape": "^3.0.0",
"testling": "^1.6.1" "testling": "^1.6.1"
@@ -33,13 +34,15 @@
"scripts": { "scripts": {
"lint": "jscs **/*.js && jshint . --exclude-path .gitignore", "lint": "jscs **/*.js && jshint . --exclude-path .gitignore",
"standalone": "browserify index.js --standalone Pjax > pjax.js", "standalone": "browserify index.js --standalone Pjax > pjax.js",
"build-debug": "browserify index.js --debug --standalone Pjax > pjax.js",
"tests": "testling", "tests": "testling",
"test": "npm run lint && npm run standalone && npm run tests", "test": "npm run lint && npm run standalone && npm run tests",
"test--html": "testling --html > tests/scripts/index.html", "test--html": "testling --html > tests/scripts/index.html",
"coverage": "browserify -t coverify tests/**/*.js | testling | coverify", "coverage": "browserify -t coverify tests/**/*.js | testling | coverify",
"example": "echo '\n==> Open http://localhost:3000/example in your browser.'; serve .", "example": "opn http://localhost:3000/example/; serve .",
"prepublish": "npm run standalone", "prepublish": "npm run standalone",
"release": "npm test && npmpub --skip-test" "#release": "testling does not work in a process launch by npm... :facepalm:",
"release": "echo \"npmpub --skip-test --dry && npm test && npmpub --skip-test --skip-cleanup\""
}, },
"testling": { "testling": {
"files": "tests/**/*.js", "files": "tests/**/*.js",

View File

@@ -0,0 +1,78 @@
var tape = require("tape")
var on = require("../../../lib/events/on")
var trigger = require("../../../lib/events/trigger")
var attachForm = require("../../../lib/proto/attach-form")
var form = document.createElement("form")
var attr = "data-pjax-click-state"
var preventDefault = function(e) { e.preventDefault() }
tape("test attach form prototype method", function(t) {
t.plan(7)
attachForm.call({
options: {},
reload: function() {
t.equal(form.getAttribute(attr), "reload", "triggering a simple reload will just submit the form")
},
loadUrl: function() {
t.equal(form.getAttribute(attr), "submit", "triggering a post to the next page")
}
}, form)
var internalUri = window.location.protocol + "//" + window.location.host + window.location.pathname + window.location.search
form.action = "http://external.com/"
trigger(form, "submit")
t.equal(form.getAttribute(attr), "external", "external url stop behavior")
form.action = internalUri + "#anchor"
trigger(form, "submit")
t.equal(form.getAttribute(attr), "anchor-present", "internal anchor stop behavior")
window.location.hash = "#anchor"
form.action = internalUri + "#another-anchor"
trigger(form, "submit")
t.notEqual(form.getAttribute(attr), "anchor", "differents anchors stop behavior")
window.location.hash = ""
form.action = internalUri + "#"
trigger(form, "submit")
t.equal(form.getAttribute(attr), "anchor-empty", "empty anchor stop behavior")
form.action = internalUri
trigger(form, "submit")
// see reload defined above
form.action = window.location.protocol + "//" + window.location.host + "/internal"
form.method = 'POST'
trigger(form, "submit")
// see post defined above
form.action = window.location.protocol + "//" + window.location.host + "/internal"
form.method = 'GET'
trigger(form, "submit")
// see post defined above
t.end()
})
tape("test attach form preventDefaulted events", function(t) {
var callbacked = false
var form = document.createElement("form")
attachForm.call({
options: {},
loadUrl: function() {
callbacked = true
}
}, form)
form.action = "#"
on(form, "submit", preventDefault)
trigger(form, "submit")
t.equal(callbacked, false, "events that are preventDefaulted should not fire callback")
t.end()
})

View File

@@ -1,17 +1,21 @@
var tape = require("tape") var tape = require("tape")
var parseElement = require("../../../lib/proto/parse-element") var parseElement = require("../../../lib/proto/parse-element")
var protoMock = {attachLink: function() { return true}} var protoMock = {
attachLink: function() { return true },
attachForm: function() { return true }
}
tape("test parse element prototype method", function(t) { tape("test parse element prototype method", function(t) {
t.doesNotThrow(function() { t.doesNotThrow(function() {
var a = document.createElement("a") var a = document.createElement("a")
parseElement.call(protoMock, a) parseElement.call(protoMock, a)
}, "<a> element can be parsed") }, "<a> element can be parsed")
t.throws(function() { t.doesNotThrow(function() {
var form = document.createElement("form") var form = document.createElement("form")
parseElement.call(protoMock, form) parseElement.call(protoMock, form)
}, "<form> cannot be used (for now)") }, "<form> element can be parsed")
t.end() t.end()
}) })

View File

@@ -46,6 +46,7 @@ tape("test parse initalization options function", function(t) {
t.deepEqual(typeof body_1.options.analytics,"function"); t.deepEqual(typeof body_1.options.analytics,"function");
t.deepEqual(body_1.options.scrollTo,0); t.deepEqual(body_1.options.scrollTo,0);
t.deepEqual(body_1.options.cacheBust,true);
t.deepEqual(body_1.options.debug,false); t.deepEqual(body_1.options.debug,false);
t.end(); t.end();
}); });

View File

@@ -2,8 +2,27 @@ var tape = require("tape")
var request = require("../../lib/request.js") var request = require("../../lib/request.js")
// Polyfill responseURL property into XMLHttpRequest if it doesn't exist,
// just for the purposes of this test
// This polyfill is not complete; it won't show the updated location if a
// redirection occurred, but it's fine for our purposes.
if (!('responseURL' in XMLHttpRequest.prototype)) {
var nativeOpen = XMLHttpRequest.prototype.open
XMLHttpRequest.prototype.open = function (method, url) {
this.responseURL = url
return nativeOpen.apply(this, arguments)
}
}
tape("test xhr request", function(t) { tape("test xhr request", function(t) {
request("https://api.github.com/", function(result) { t.test("- request is made, gets a result, and is cache-busted", function(t) {
var requestCacheBust = request.bind({
options: {
cacheBust: true,
},
});
var r = requestCacheBust("https://api.github.com/", {}, function(result) {
t.equal(r.responseURL.indexOf("?"), 23, "XHR URL is cache-busted when configured to be")
try { try {
result = JSON.parse(result) result = JSON.parse(result)
} }
@@ -14,3 +33,16 @@ tape("test xhr request", function(t) {
t.end() t.end()
}) })
}) })
t.test("- request is not cache-busted when configured not to be", function(t) {
var requestNoCacheBust = request.bind({
options: {
cacheBust: false,
},
});
var r = requestNoCacheBust("https://api.github.com/", {}, function() {
t.equal(r.responseURL, "https://api.github.com/", "XHR URL is left untouched")
t.end()
})
})
t.end()
})