diff --git a/index.js b/index.js index be13c30..4d6039d 100644 --- a/index.js +++ b/index.js @@ -27,7 +27,7 @@ var Pjax = function(options) { opt.url = st.state.url opt.title = st.state.title opt.history = false - + opt.requestOptions = {}; if (st.state.uid < this.lastUid) { opt.backward = true } @@ -55,6 +55,8 @@ Pjax.prototype = { attachLink: require("./lib/proto/attach-link.js"), + attachForm: require("./lib/proto/attach-form.js"), + forEachSelectors: function(cb, context, DOMcontext) { return require("./lib/foreach-selectors.js").bind(this)(this.options.selectors, cb, context, DOMcontext) }, @@ -151,7 +153,7 @@ Pjax.prototype = { trigger(document, "pjax:send", options); // Do the request - this.doRequest(href, function(html) { + this.doRequest(href, options.requestOptions, function(html) { // Fail if unable to load HTML via AJAX if (html === false) { trigger(document,"pjax:complete pjax:error", options) diff --git a/lib/eval-script.js b/lib/eval-script.js index d34436a..9591fd3 100644 --- a/lib/eval-script.js +++ b/lib/eval-script.js @@ -2,7 +2,7 @@ module.exports = function(el) { // console.log("going to execute script", el) var code = (el.text || el.textContent || el.innerHTML || "") - var head = document.querySelector("head") || document.documentElement + var parent = el.parentNode || document.querySelector("head") || document.documentElement var script = document.createElement("script") if (code.match("document.write")) { @@ -22,8 +22,11 @@ module.exports = function(el) { } // execute - head.insertBefore(script, head.firstChild) - head.removeChild(script) // avoid pollution + parent.appendChild(script); + // avoid pollution only in head or body tags + if (["head","body"].indexOf(parent.tagName.toLowerCase()) > 0) { + parent.removeChild(script) + } return true } diff --git a/lib/execute-scripts.js b/lib/execute-scripts.js index d6392b9..04ece08 100644 --- a/lib/execute-scripts.js +++ b/lib/execute-scripts.js @@ -4,6 +4,11 @@ var evalScript = require("./eval-script") // Needed since innerHTML does not run scripts module.exports = function(el) { // console.log("going to execute scripts for ", el) + + if (el.tagName.toLowerCase() === "script") { + evalScript(el); + } + forEachEls(el.querySelectorAll("script"), function(script) { if (!script.type || script.type.toLowerCase() === "text/javascript") { if (script.parentNode) { diff --git a/lib/proto/attach-form.js b/lib/proto/attach-form.js new file mode 100644 index 0000000..06fa447 --- /dev/null +++ b/lib/proto/attach-form.js @@ -0,0 +1,93 @@ +require("../polyfills/Function.prototype.bind") + +var on = require("../events/on") +var clone = require("../clone") + +var attrClick = "data-pjax-click-state" + +var formAction = function(el, event){ + + this.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', this.options.requestOptions.requestUrl); + + // Ignore external links. + if (virtLinkElement.protocol !== window.location.protocol || virtLinkElement.host !== window.location.host) { + el.setAttribute(attrClick, "external"); + return + } + + // Ignore click if we are on an anchor on the same page + if (virtLinkElement.pathname === window.location.pathname && virtLinkElement.hash.length > 0) { + el.setAttribute(attrClick, "anchor-present"); + return + } + + // Ignore empty anchor "foo.html#" + if (virtLinkElement.href === window.location.href.split("#")[0] + "#") { + el.setAttribute(attrClick, "anchor-empty") + return + } + + // if declared as a full reload, just normally submit the form + if ( this.options.currentUrlFullReload) { + el.setAttribute(attrClick, "reload"); + return; + } + + event.preventDefault() + + var paramObject = []; + for(var elementKey in el.elements) { + var element = el.elements[elementKey]; + if (!!element.name && element.attributes !== undefined && element.tagName.toLowerCase() !== 'button'){ + if ((element.attributes.type !== 'checkbox' && element.attributes.type !== 'radio') || element.checked) { + paramObject.push({ name: encodeURIComponent(element.name), value: encodeURIComponent(element.value)}); + } + } + } + + //Creating a getString + var paramsString = (paramObject.map(function(value){return value.name+"="+value.value;})).join('&'); + + this.options.requestOptions.requestPayload = paramObject; + this.options.requestOptions.requestPayloadString = paramsString; + + el.setAttribute(attrClick, "submit"); + + this.loadUrl(virtLinkElement.href, clone(this.options)) + +}; + +var isDefaultPrevented = function(event) { + return event.defaultPrevented || event.returnValue === false; +}; + + +module.exports = function(el) { + var that = this + + on(el, "submit", function(event) { + if (isDefaultPrevented(event)) { + return + } + + formAction.call(that, el, event) + }) + + on(el, "keyup", function(event) { + if (isDefaultPrevented(event)) { + return + } + + + if (event.keyCode == 13) { + formAction.call(that, el, event) + } + }.bind(this)) +} diff --git a/lib/proto/attach-link.js b/lib/proto/attach-link.js index 73e6986..b093f3a 100644 --- a/lib/proto/attach-link.js +++ b/lib/proto/attach-link.js @@ -51,7 +51,7 @@ var linkAction = function(el, event) { this.reload() return } - + this.options.requestOptions = this.options.requestOptions || {}; el.setAttribute(attrClick, "load") this.loadUrl(el.href, clone(this.options)) } diff --git a/lib/proto/parse-element.js b/lib/proto/parse-element.js index 736fdd7..af88ca3 100644 --- a/lib/proto/parse-element.js +++ b/lib/proto/parse-element.js @@ -7,8 +7,11 @@ module.exports = function(el) { } break - case "form": - throw "Pjax doesnt support