From a5b51f34dfd9dce904c4887bc7d3dfd9857c70e1 Mon Sep 17 00:00:00 2001 From: Robin North Date: Wed, 21 Feb 2018 18:27:26 +0000 Subject: [PATCH] Fix GET form submission --- lib/proto/attach-form.js | 10 +++----- lib/send-request.js | 41 +++++++++++++++++++++++++-------- lib/util/update-query-string.js | 10 ++++++++ 3 files changed, 45 insertions(+), 16 deletions(-) create mode 100644 lib/util/update-query-string.js diff --git a/lib/proto/attach-form.js b/lib/proto/attach-form.js index 4f6ed82..43ac1a6 100644 --- a/lib/proto/attach-form.js +++ b/lib/proto/attach-form.js @@ -44,23 +44,19 @@ var formAction = function(el, event) { event.preventDefault() - var paramObject = [] + var params = [] for (var elementKey in el.elements) { var element = el.elements[elementKey] // jscs:disable disallowImplicitTypeConversion if (!!element.name && element.attributes !== undefined && element.tagName.toLowerCase() !== "button") { // jscs:enable disallowImplicitTypeConversion 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)}) + params.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 + options.requestOptions.requestParams = params el.setAttribute(attrClick, "submit") diff --git a/lib/send-request.js b/lib/send-request.js index 618f65b..58ce7fd 100644 --- a/lib/send-request.js +++ b/lib/send-request.js @@ -1,7 +1,10 @@ +var updateQueryString = require("./util/update-query-string"); + module.exports = function(location, options, callback) { options = options || {} - var requestMethod = options.requestMethod || "GET" - var requestPayload = options.requestPayloadString || null + var requestMethod = (options.requestMethod || "GET").toUpperCase() + var requestParams = options.requestParams || null + var requestPayload = null var request = new XMLHttpRequest() request.onreadystatechange = function() { @@ -24,19 +27,39 @@ module.exports = function(location, options, callback) { callback(null, request) } - // Add a timestamp as part of the query string if cache busting is enabled - if (this.options.cacheBust) { - location += (!/[?&]/.test(location) ? "?" : "&") + new Date().getTime() + // Prepare the request payload for forms, if available + if (requestParams && requestParams.length) { + 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] + + // Build new query string + requestParams.forEach(function(param) { + location = updateQueryString(location, param.name, param.value) + }); + break; + + case "POST": + // Build payload string + requestPayload = (requestParams.map(function(param) {return param.name + "=" + param.value})).join("&") + 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.setRequestHeader("X-Requested-With", "XMLHttpRequest") 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 + // Send the proper header information for POST forms + if (requestPayload && requestMethod === "POST") { request.setRequestHeader("Content-type", "application/x-www-form-urlencoded") } diff --git a/lib/util/update-query-string.js b/lib/util/update-query-string.js new file mode 100644 index 0000000..3635de0 --- /dev/null +++ b/lib/util/update-query-string.js @@ -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 + } +}