Skip to content

Instantly share code, notes, and snippets.

@msaspence
Last active September 15, 2016 09:22
Show Gist options
  • Save msaspence/6d8da471e8ec87f1ec40 to your computer and use it in GitHub Desktop.
Save msaspence/6d8da471e8ec87f1ec40 to your computer and use it in GitHub Desktop.
"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