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 = [] for (var elementKey in el.elements) { if (Number.isNaN(Number(elementKey))) { continue; } var element = el.elements[elementKey] 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 i = 0; i < element.options.length; i++) { opt = element.options[i] if (opt.selected) { values.push(opt.value || opt.text) } } } else { values.push(element.value) } for (var j = 0; j < values.length; j++) { requestParams.push({ name: encodeURIComponent(element.name), value: encodeURIComponent(values[j]) }) } } } } 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) }) on(el, "keyup", function(event) { if (event.keyCode === 13) { formAction.call(that, el, event) } }.bind(this)) }