Files
pjax/lib/proto/attach-form.js
BehindTheMath d6bf21ed22 Fix bugs and add tests (#145)
* Fix bug when checking if elements were parsed already

parse-element.js checks if the element was already parsed by
checking for the `data-pjax-click-state` attribute. However, this
attribute was not added until the link is clicked.

Originally, there was a separate attribute, `data-pjax-enabled`,
which tracked if the element was parsed already, but that was
changed in 9a86044.

This commit merges the attributes for mouse clicks and key presses
into one and adds that attribute when the element is initially
parsed.

* More bug fixes

* Fix documentation for currentUrlFullReload

* Ignore lines from coverage if they can't be tested

* Refactor attach-link and attach-form

* Fix and refactors tests

* Add tests

* Add TS definitions for options.requestOptions

* Code cleanup
2018-04-09 23:36:32 -04:00

95 lines
2.8 KiB
JavaScript

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",
requestParams: []
}
// 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()
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) {
options.requestOptions.requestParams.push({
name: encodeURIComponent(element.name),
value: encodeURIComponent(element.value)
})
}
}
}
el.setAttribute(attrState, "submit")
options.triggerElement = el
this.loadUrl(virtLinkElement.href, options)
}
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))
}