var on = require("../events/on") var clone = require("../util/clone") var attrState = "data-pjax-state" var formAction = function(el, event) { if (isDefaultPrevented(event)) { return } // Since loadUrl modifies options and we may add our own modifications below, // clone it so the changes don't persist var options = clone(this.options) // Initialize requestOptions 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", options.requestOptions.requestUrl) var attrValue = checkIfShouldAbort(virtLinkElement, options) if (attrValue) { el.setAttribute(attrState, attrValue) return } event.preventDefault() if (el.enctype === "multipart/form-data") { options.requestOptions.formData = new FormData(el) } else { options.requestOptions.requestParams = parseFormElements(el) } el.setAttribute(attrState, "submit") options.triggerElement = el this.loadUrl(virtLinkElement.href, options) } function parseFormElements(el) { var requestParams = [] var formElements = el.elements for (var i = 0; i < formElements.length; i++) { var element = formElements[i] var tagName = element.tagName.toLowerCase() // jscs:disable disallowImplicitTypeConversion if (!!element.name && element.attributes !== undefined && tagName !== "button") { // jscs:enable disallowImplicitTypeConversion var type = element.attributes.type if ((!type || type.value !== "checkbox" && type.value !== "radio") || element.checked) { // Build array of values to submit var values = [] if (tagName === "select") { var opt for (var j = 0; j < element.options.length; j++) { opt = element.options[j] if (opt.selected && !opt.disabled) { values.push(opt.hasAttribute("value") ? opt.value : opt.text) } } } else { values.push(element.value) } for (var k = 0; k < values.length; k++) { requestParams.push({ name: encodeURIComponent(element.name), value: encodeURIComponent(values[k]) }) } } } } return requestParams } function checkIfShouldAbort(virtLinkElement, options) { // Ignore external links. if (virtLinkElement.protocol !== window.location.protocol || virtLinkElement.host !== window.location.host) { return "external" } // Ignore click if we are on an anchor on the same page if (virtLinkElement.hash && virtLinkElement.href.replace(virtLinkElement.hash, "") === window.location.href.replace(location.hash, "")) { return "anchor" } // Ignore empty anchor "foo.html#" if (virtLinkElement.href === window.location.href.split("#")[0] + "#") { return "anchor-empty" } // if declared as a full reload, just normally submit the form if (options.currentUrlFullReload && virtLinkElement.href === window.location.href.split("#")[0]) { return "reload" } } var isDefaultPrevented = function(event) { return event.defaultPrevented || event.returnValue === false } module.exports = function(el) { var that = this el.setAttribute(attrState, "") on(el, "submit", function(event) { formAction.call(that, el, event) }) }