// As documented on the reference below, turbolinks 5 does not treat a render // after a form submit by default, leaving the users to implement their own // solutions. // // https://github.com/turbolinks/turbolinks/issues/85#issuecomment-323446272 // // The code below imitates the behavior of turbolinks when treating regular GET // responses. Namely, it: // - Replaces only the body of the page // - It runs all script tags on the body of the new page // - It fires the turbolinks:load event // // This doesn't mean it does ALL what turbolinks does. For example, we don't // merge script tags from old and new page elements. // This also doesn't change the browser history or does any change to the URL. // The reason we don't do such things is simply that this gem is a solution to // render errors in forms, and usually we render the same page/form we had rendered // before the submit. var TurbolinksForm = function(){}; // Attach an event handler function for one or more events to the selected elements. // This method is inspired by JQuery on() and was created so that we could remove the dependency // on JQuery. // Ref: https://stackoverflow.com/questions/25248286/native-js-equivalent-to-jquery-delegation#answer-46595740 TurbolinksForm.on = function(eventHandlerOwner, event, delegateSelector, handler) { // handles call with 3 arguments if (!handler && delegateSelector) { handler = delegateSelector; delegateSelector = undefined; } $(eventHandlerOwner).on(event, function(e) { if (delegateSelector) { // goes up the dom tree searching for the delegate var currentTarget = e.target; while (currentTarget != null && currentTarget !== this && !currentTarget.matches(delegateSelector)) { currentTarget = currentTarget.parentElement; } // if delegate found, call the handler there if (currentTarget != null && currentTarget.matches(delegateSelector)) { handler.apply(currentTarget, arguments); } } // if there is no delegation, just call the handler directly else { handler.apply(eventHandlerOwner, arguments); } }); } TurbolinksForm.handleResponse = function(xhr, renderingError) { // parses response var newDom = new DOMParser().parseFromString(xhr.responseText, "text/html"); // Some browsers (PhantomJS and earlier versions of Firefox and IE) don't implement // parsing from string for "text/html" format. So we use an alternative method // described here: // https://developer.mozilla.org/en-US/Add-ons/Code_snippets/HTML_to_DOM#Parsing_Complete_HTML_to_DOM if (newDom == null) { newDom = document.implementation.createHTMLDocument("document"); newDom.documentElement.innerHTML = xhr.responseText; } if (newDom == null) { console.error("turbolinks-form was not able to parse response from server."); } // dispatches turbolinks event Turbolinks.dispatch('turbolinks:before-render', {data: {newBody: newDom.body}}); // console.log('before-render') // replaces whole head if rendering an error page. Useful when handling 500 error, since applications // usually have a whole different set of styles for this page. This is consistent with Turbolinks. if (renderingError) { // head replacement doesn't work the same way as body replacement. We must use the replaceChild() // function for it to work effectively document.documentElement.replaceChild(newDom.head, document.head); } // Removes/saves all script tags contents. // Most browsers don't run the new