UNPKG

pjax

Version:

Easily enable fast AJAX navigation on any website (using pushState + XHR)

140 lines (114 loc) 3.62 kB
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); }); };