Fix form submission #129
@@ -20,7 +20,8 @@ document.addEventListener("pjax:success", function() {
|
|||||||
document.addEventListener("DOMContentLoaded", function() {
|
document.addEventListener("DOMContentLoaded", function() {
|
||||||
var pjax = new Pjax({
|
var pjax = new Pjax({
|
||||||
elements: [".js-Pjax"],
|
elements: [".js-Pjax"],
|
||||||
selectors: [".body"]
|
selectors: [".body", "title"],
|
||||||
|
cacheBust: true,
|
||||||
// currentUrlFullReload: true,
|
// currentUrlFullReload: true,
|
||||||
})
|
})
|
||||||
console.log("Pjax initialized.", pjax)
|
console.log("Pjax initialized.", pjax)
|
||||||
|
|||||||
138
example/forms.html
Normal file
138
example/forms.html
Normal file
@@ -0,0 +1,138 @@
|
|||||||
|
<!doctype html>
|
||||||
|
<html>
|
||||||
|
<head>
|
||||||
|
<meta charset="utf-8">
|
||||||
|
<title>Forms</title>
|
||||||
|
<script src="../pjax.js"></script>
|
||||||
|
<script src="example.js"></script>
|
||||||
|
</head>
|
||||||
|
<body>
|
||||||
|
<div class="body">
|
||||||
|
<h1>Forms</h1>
|
||||||
|
Hello. Try out the examples below and inspect the results in your browser's developer tools, or go to the <a href="index.html" class="js-Pjax">Index</a>.
|
||||||
|
|
||||||
|
<h3>GET form</h3>
|
||||||
|
|
||||||
|
<form action="" method="get" class="js-Pjax" id="get-form">
|
||||||
|
<label for="get-form-text">Text input:</label>
|
||||||
|
<input type="text" name="textInput" id="get-form-text" value="Foobar" />
|
||||||
|
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<label for="get-form-number">Number input:</label>
|
||||||
|
<input type="number" name="numberInput" id="get-form-number" value="1" />
|
||||||
|
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<label for="get-form-email">Email input:</label>
|
||||||
|
<input type="email" name="emailInput" id="get-form-email" value="example@example.com" />
|
||||||
|
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<label for="get-form-textarea">Textarea:</label>
|
||||||
|
<textarea name="textarea" id="get-form-textarea">This is some text</textarea>
|
||||||
|
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<fieldset>
|
||||||
|
<label for="get-form-radio-1">Radio input:</label>
|
||||||
|
<input type="radio" name="radioInput" value="radio-1" checked id="get-form-radio-1" />
|
||||||
|
|
||||||
|
<label for="get-form-radio-2">Radio input alt:</label>
|
||||||
|
<input type="radio" name="radioInput" value="radio-2" id="get-form-radio-2" />
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<label for="get-form-checkbox">Checkbox input:</label>
|
||||||
|
<input type="checkbox" name="checkboxInput" checked id="get-form-checkbox" />
|
||||||
|
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<label for="get-form-select">Select list:</label>
|
||||||
|
<select name="select" id="get-form-select">
|
||||||
|
<option>
|
||||||
|
Option 1
|
||||||
|
</option>
|
||||||
|
<option>
|
||||||
|
Option 2
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<input type="submit" value="Submit" />
|
||||||
|
</form>
|
||||||
|
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<h3>POST form</h3>
|
||||||
|
|
||||||
|
<form action="" method="post" class="js-Pjax" id="post-form">
|
||||||
|
<label for="post-form-text">Text input:</label>
|
||||||
|
<input type="text" name="textInput" id="post-form-text" value="Foobar" />
|
||||||
|
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<label for="post-form-number">Number input:</label>
|
||||||
|
<input type="number" name="numberInput" id="post-form-number" value="1" />
|
||||||
|
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<label for="post-form-email">Email input:</label>
|
||||||
|
<input type="email" name="emailInput" id="post-form-email" value="example@example.com" />
|
||||||
|
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<label for="post-form-textarea">Textarea:</label>
|
||||||
|
<textarea name="textarea" id="post-form-textarea">This is some text</textarea>
|
||||||
|
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<fieldset>
|
||||||
|
<label for="post-form-radio-1">Radio input:</label>
|
||||||
|
<input type="radio" name="radioInput" value="radio-1" checked id="post-form-radio-1" />
|
||||||
|
|
||||||
|
<label for="post-form-radio-2">Radio input alt:</label>
|
||||||
|
<input type="radio" name="radioInput" value="radio-2" id="post-form-radio-2" />
|
||||||
|
</fieldset>
|
||||||
|
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<label for="post-form-checkbox">Checkbox input:</label>
|
||||||
|
<input type="checkbox" name="checkboxInput" checked id="post-form-checkbox" />
|
||||||
|
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<label for="post-form-select">Select list:</label>
|
||||||
|
<select name="select" id="post-form-select">
|
||||||
|
<option>
|
||||||
|
Option 1
|
||||||
|
</option>
|
||||||
|
<option>
|
||||||
|
Option 2
|
||||||
|
</option>
|
||||||
|
</select>
|
||||||
|
|
||||||
|
<br />
|
||||||
|
<br />
|
||||||
|
|
||||||
|
<input type="submit" value="Submit" />
|
||||||
|
</form>
|
||||||
|
</div>
|
||||||
|
</body>
|
||||||
|
</html>
|
||||||
@@ -1,17 +1,22 @@
|
|||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta charset='utf-8'>
|
<meta charset="utf-8">
|
||||||
<title>Hello</title>
|
<title>Hello</title>
|
||||||
<script src='../pjax.js'></script>
|
<script src="../pjax.js"></script>
|
||||||
<script src='example.js'></script>
|
<script src="example.js"></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class='body'>
|
<div class="body">
|
||||||
<h1>Index</h1>
|
<h1>Index</h1>
|
||||||
Hello.
|
Hello.
|
||||||
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>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.
|
||||||
|
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta charset='utf-8'>
|
<meta charset="utf-8">
|
||||||
<title>Hello</title>
|
<title>Page 2</title>
|
||||||
<script src='../pjax.js'></script>
|
<script src="../pjax.js"></script>
|
||||||
<script src='example.js'></script>
|
<script src="example.js"></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class='body'>
|
<div class="body">
|
||||||
<h1>Page 2</h1>
|
<h1>Page 2</h1>
|
||||||
Hello. Go to <a href='index.html' class="js-Pjax">Index</a>.
|
Hello. Go to <a href="index.html" class="js-Pjax">Index</a>.
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -1,15 +1,15 @@
|
|||||||
<!doctype html>
|
<!doctype html>
|
||||||
<html>
|
<html>
|
||||||
<head>
|
<head>
|
||||||
<meta charset='utf-8'>
|
<meta charset="utf-8">
|
||||||
<title>Hello</title>
|
<title>Page 3</title>
|
||||||
<script src='../pjax.js'></script>
|
<script src="../pjax.js"></script>
|
||||||
<script src='example.js'></script>
|
<script src="example.js"></script>
|
||||||
</head>
|
</head>
|
||||||
<body>
|
<body>
|
||||||
<div class='body'>
|
<div class="body">
|
||||||
<h1>Page 3</h1>
|
<h1>Page 3</h1>
|
||||||
Hello. Go to <a href='index.html' class="js-Pjax">Index</a>.
|
Hello. Go to <a href="index.html" class="js-Pjax">Index</a>.
|
||||||
</div>
|
</div>
|
||||||
</body>
|
</body>
|
||||||
</html>
|
</html>
|
||||||
|
|||||||
@@ -11,7 +11,8 @@ var formAction = function(el, event) {
|
|||||||
// 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",
|
||||||
|
requestParams: []
|
||||||
}
|
}
|
||||||
|
|
||||||
// create a testable virtual link of the form action
|
// create a testable virtual link of the form action
|
||||||
@@ -44,24 +45,20 @@ var formAction = function(el, event) {
|
|||||||
|
|
||||||
event.preventDefault()
|
event.preventDefault()
|
||||||
|
|
||||||
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 || element.attributes.type.value !== "checkbox" && element.attributes.type.value !== "radio") || element.checked) {
|
||||||
paramObject.push({name: encodeURIComponent(element.name), value: encodeURIComponent(element.value)})
|
options.requestOptions.requestParams.push({
|
||||||
|
name: encodeURIComponent(element.name),
|
||||||
|
value: encodeURIComponent(element.value)
|
||||||
|
})
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
// Creating a getString
|
|
||||||
var paramsString = (paramObject.map(function(value) {return value.name + "=" + value.value})).join("&")
|
|
||||||
|
|
||||||
options.requestOptions.requestPayload = paramObject
|
|
||||||
options.requestOptions.requestPayloadString = paramsString
|
|
||||||
|
|
||||||
el.setAttribute(attrClick, "submit")
|
el.setAttribute(attrClick, "submit")
|
||||||
|
|
||||||
options.triggerElement = el
|
options.triggerElement = el
|
||||||
|
|||||||
@@ -1,7 +1,11 @@
|
|||||||
|
var updateQueryString = require("./util/update-query-string");
|
||||||
|
|
||||||
module.exports = function(location, options, callback) {
|
module.exports = function(location, options, callback) {
|
||||||
options = options || {}
|
options = options || {}
|
||||||
var requestMethod = options.requestMethod || "GET"
|
var queryString
|
||||||
var requestPayload = options.requestPayloadString || null
|
var requestMethod = (options.requestMethod || "GET").toUpperCase()
|
||||||
|
var requestParams = options.requestParams || null
|
||||||
|
var requestPayload = null
|
||||||
var request = new XMLHttpRequest()
|
var request = new XMLHttpRequest()
|
||||||
|
|
||||||
request.onreadystatechange = function() {
|
request.onreadystatechange = function() {
|
||||||
@@ -24,19 +28,40 @@ module.exports = function(location, options, callback) {
|
|||||||
callback(null, request)
|
callback(null, request)
|
||||||
}
|
}
|
||||||
|
|
||||||
// Add a timestamp as part of the query string if cache busting is enabled
|
// Prepare the request payload for forms, if available
|
||||||
if (this.options.cacheBust) {
|
if (requestParams && requestParams.length) {
|
||||||
location += (!/[?&]/.test(location) ? "?" : "&") + new Date().getTime()
|
// Build query string
|
||||||
|
queryString = (requestParams.map(function(param) {return param.name + "=" + param.value})).join("&")
|
||||||
|
|
||||||
|
switch (requestMethod) {
|
||||||
|
case "GET":
|
||||||
|
// Reset query string to avoid an issue with repeat submissions where checkboxes that were
|
||||||
|
// previously checked are incorrectly preserved
|
||||||
|
location = location.split("?")[0]
|
||||||
|
|
||||||
|
// Append new query string
|
||||||
|
location += "?" + queryString
|
||||||
|
break
|
||||||
|
|
||||||
|
case "POST":
|
||||||
|
// Send query string as request payload
|
||||||
|
requestPayload = queryString
|
||||||
|
break
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
request.open(requestMethod.toUpperCase(), location, true)
|
// Add a timestamp as part of the query string if cache busting is enabled
|
||||||
|
if (this.options.cacheBust) {
|
||||||
|
location = updateQueryString(location, "t", Date.now())
|
||||||
|
}
|
||||||
|
|
||||||
|
request.open(requestMethod, location, true)
|
||||||
request.timeout = options.timeout
|
request.timeout = options.timeout
|
||||||
request.setRequestHeader("X-Requested-With", "XMLHttpRequest")
|
request.setRequestHeader("X-Requested-With", "XMLHttpRequest")
|
||||||
request.setRequestHeader("X-PJAX", "true")
|
request.setRequestHeader("X-PJAX", "true")
|
||||||
|
|
||||||
// Add the request payload if available
|
// Send the proper header information for POST forms
|
||||||
if (options.requestPayloadString !== undefined && options.requestPayloadString !== "") {
|
if (requestPayload && requestMethod === "POST") {
|
||||||
// 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")
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|||||||
10
lib/util/update-query-string.js
Normal file
10
lib/util/update-query-string.js
Normal file
@@ -0,0 +1,10 @@
|
|||||||
|
module.exports = function(uri, key, value) {
|
||||||
|
var re = new RegExp("([?&])" + key + "=.*?(&|$)", "i")
|
||||||
|
var separator = uri.indexOf("?") !== -1 ? "&" : "?"
|
||||||
|
if (uri.match(re)) {
|
||||||
|
return uri.replace(re, "$1" + key + "=" + value + "$2")
|
||||||
|
}
|
||||||
|
else {
|
||||||
|
return uri + separator + key + "=" + value
|
||||||
|
}
|
||||||
|
}
|
||||||
Reference in New Issue
Block a user