-
Notifications
You must be signed in to change notification settings - Fork 1
/
x-react.js
93 lines (81 loc) · 2.3 KB
/
x-react.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
/** @jsx React.DOM */
(function(global) {
var XReact = React.createClass({
componentDidMount: function() {
// When anything change in the DOM subtree, we want to update the React
// version of the element
new MutationObserver(this.forceUpdate.bind(this)).observe(
this.props.element, {
childList: true,
attributes: true,
characterData: true,
subtree: true
}
);
},
render: function() {
return convertDOMToReact(this.props.element);
}
});
global.xreact = {
tags: {},
register: function(name, component){
// We register the react component internally
xreact.tags[name.toLowerCase()] = component;
xtag.register(name, {
lifecycle: {
created: function() {
// We render the special XReact component inside of the shadow
// root of the DOM node that was passed it.
React.renderComponent(
XReact({element: this}),
this.webkitCreateShadowRoot()
);
}
}
});
}
};
function convertDOMToReact(dom) {
// If it's a text node, we just return it as string
if (dom.nodeType === 3) {
return dom.textContent;
}
// Otherwise we find the React component associated to the DOM node. It can
// either be in React.DOM for standard HTML components or in xreact.tags for
// React elements we created
var tag = dom.tagName.toLowerCase();
return (React.DOM[tag] || xreact.tags[tag])(
convertAttributes(dom),
getChildren(dom).map(convertDOMToReact)
);
}
// Helper to get an array of all the children (including text) of a dom node
function getChildren(dom) {
var children = [];
var child = dom.firstChild;
while (child) {
children.push(child);
child = child.nextSibling;
}
return children;
}
// Helper to convert dom.attributes to an object React can read
function convertAttributes(dom) {
var result = {};
for (var i = 0; i < dom.attributes.length; i) {
var attribute = dom.attributes[i];
result[attribute.name] = attribute.value;
}
if (result.style) {
// Convert "font-size: 10px" to {'font-size': '10px'}
var style = {};
result.style.split(';').forEach(function(rule) {
var split = rule.split(':');
style[split[0]] = split[1];
});
result.style = style;
}
return result;
}
})(this);