Switch re-frame-trace to render into Shadow DOM

I tried to render re-frame-trace into a Shadow DOM which worked, but I
ran out of time to get click handlers to work. This is the working point
that I got up to.

Relates to https://github.com/Day8/re-frame-trace/issues/44
This commit is contained in:
Daniel Compton 2017-10-20 14:02:32 +13:00
parent 586de69894
commit bab881ee75
2 changed files with 73 additions and 24 deletions

View File

@ -393,34 +393,49 @@
:subvis [subvis/render-subvis traces
[:div.panel-content-scrollable]])]]]))})))
(defn panel-div []
(let [id "--re-frame-trace--"
panel (.getElementById js/document id)]
(if panel
panel
(let [new-panel (.createElement js/document "div")]
(.setAttribute new-panel "id" id)
(.appendChild (.-body js/document) new-panel)
(js/window.focus new-panel)
new-panel))))
(defn panel-shadow
"Attaches the panel to the dom and returns the shadow root for rendering.
(defn inject-styles []
Creates a re-frame-trace div on the body of the document
and attaches a shadow root, returning the root.
Returns an existing shadow root if one exists."
[]
(let [id "--re-frame-trace--root"]
(if-let [panel (.getElementById js/document id)]
(.-shadowRoot panel)
(let [new-panel (.createElement js/document "div")
_ (.setAttribute new-panel "id" id)
_ (.appendChild (.-body js/document) new-panel)
shadow (.attachShadow new-panel (clj->js {:mode "open"}))]
(js/window.focus new-panel)
shadow))))
(defn tracing-div
"Returns a div inside the shadow-root that can be used for rendering into with React/Reagent.
Creates it if it does not exist."
[shadow-root]
(let [id "--re-frame-trace--"]
(if-let [div (.querySelector shadow-root (str "#" id))]
div
(let [new-div (.createElement js/document "div")]
(.setAttribute new-div "id" id)
(.appendChild shadow-root new-div)
new-div))))
(defn inject-styles [shadow-root]
(let [id "--re-frame-trace-styles--"
styles-el (.getElementById js/document id)
styles-el (.querySelector shadow-root (str "#" id))
new-styles-el (.createElement js/document "style")
new-styles styles/panel-styles]
(.setAttribute new-styles-el "id" id)
(-> new-styles-el
(.-innerHTML)
(set! new-styles))
(set! (.-innerHTML new-styles-el) new-styles)
(if styles-el
(-> styles-el
(.-parentNode)
(.replaceChild new-styles-el styles-el))
(let []
(.appendChild (.-head js/document) new-styles-el)
new-styles-el))))
(.replaceChild (.-parentNode styles-el) new-styles-el styles-el)
(.appendChild shadow-root new-styles-el))
styles-el))
(defn inject-devtools! []
(inject-styles)
(r/render [devtools] (panel-div)))
(let [shadow-root (panel-shadow)
div (tracing-div shadow-root)]
(inject-styles shadow-root)
(r/render [devtools] div)))

View File

@ -0,0 +1,34 @@
<html>
<head></head>
<body>
<style>
html, body {
font-family: Segoe UI, Roboto, sans-serif;
font-size: 14px;
font-weight: 400;
color: rgba(68, 68, 68, 1.0);
letter-spacing: 0.002em;
height: 100%;
margin: 0px;
padding: 0px;
}
</style>
<!--<div style="all: unset" id="hostElement"></div>-->
<script>
// Create shadow DOM
var host = document.createElement("div");
host.setAttribute("id", "hostElement");
host.setAttribute("style", "all: initial");
document.body.appendChild(host);
var shadow = document.querySelector('#hostElement')
.attachShadow({mode: 'open'});
// Add some text to shadow DOM
shadow.innerHTML = '<span>Here is some new text</span>';
// Add some CSS to make the text red
shadow.innerHTML += '<style>span { color: red; }</style>';
</script>
</body>
</html>