Last active
September 15, 2016 09:22
-
-
Save msaspence/6d8da471e8ec87f1ec40 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
"use strict"; | |
if (global.Turbolinks === undefined) { | |
throw "Missing Turbolinks dependency. TurboReact requires Turbolinks be included before it."; | |
} | |
var HTMLtoJSX = require("htmltojsx"); | |
var JSXTransformer = require("react-tools"); | |
var React = require("react"); | |
// Disable the Turbolinks page cache to prevent Tlinks from storing versions of | |
// pages with `react-id` attributes in them. When popping off the history, the | |
// `react-id` attributes cause React to treat the old page like a pre-rendered | |
// page and breaks diffing. | |
global.Turbolinks.pagesCached(0); | |
// `documentElement.replaceChild` must be called in the context of the | |
// `documentElement`. Keep a bound reference to use later. | |
var originalReplaceChild = | |
global.document.documentElement.replaceChild.bind( | |
global.document.documentElement); | |
var converter = new HTMLtoJSX({createClass: false}); | |
var TurboComponent = React.createClass({ | |
displayName: 'TurboReact', | |
componentDidMount: function() { | |
setTimeout(function() { | |
this.setProps({ | |
children: this.props.replacement | |
}); | |
}.bind(this),0); | |
}, | |
render: function() { | |
return this.props.children; | |
} | |
}); | |
var TurboReact = { | |
version: TURBO_REACT_VERSION, | |
applyDiff: function(replacementElement, targetElement) { | |
try { | |
var $root = $(targetElement).find('#turbo-react'); | |
var $children = $root.children(); | |
$children.appendTo(targetElement); | |
$root.remove(); | |
$(targetElement).find('[data-reactid]').removeAttr('data-reactid'); | |
var original = TurboReact.reactize(targetElement); | |
var replacement = TurboReact.reactize(replacementElement); | |
var body = React.createElement(TurboComponent, { replacement: replacement }, original); | |
React.render(body, targetElement); | |
} catch(e) { | |
// If any problem occurs when updating content, let Turbolinks replace | |
// the page normally. That means no transitions, but it also means no | |
// broken pages. | |
originalReplaceChild(replacementElement, targetElement); | |
throw e; | |
} | |
}, | |
reactize: function(element) { | |
var code = JSXTransformer.transform(converter.convert('<div id="turbo-react">'+element.innerHTML+'</div>')); | |
return eval(code); | |
} | |
}; | |
// Turbolinks calls `replaceChild` on the document element when an update should | |
// occur. Monkeypatch the method so Turbolinks can be used without modification. | |
global.document.documentElement.replaceChild = TurboReact.applyDiff; | |
// function applyBodyDiff() { | |
// TurboReact.applyDiff(document.body, document.body); | |
// global.document.removeEventListener("DOMContentLoaded", applyBodyDiff); | |
// // global.document.removeEventListener("page:fetch", applyBodyDiff); | |
// } | |
// | |
// global.document.addEventListener("DOMContentLoaded", applyBodyDiff); | |
// global.document.addEventListener("page:fetch", function() { | |
// console.log('applying body diff'); | |
// $('[data-reactid]').removeAttr('data-reactid'); | |
// applyBodyDiff(); | |
// console.log('applied body diff'); | |
// }); | |
// | |
// global.document.addEventListener("page:load", function() { | |
// console.log('new page loaded'); | |
// }); | |
module.exports = TurboReact; |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment