0

I am embedding some HTML content inside a webpage and I want it to be isolated from outside CSS. My users are able to create HTML content dynamically and these pages can contain some simple JS. I've been trying to run these JS inside a shadow root. Since the JS is created dynamicaly when the user creates the page I need a way to make it possible to run the code inside the shadowroot. I'm adding content as follows:

const header = document.createElement('header');
const shadowRoot = document.createElement('body')
shadowRoot.innerHTML = pageContent


var script = document.createElement('script')
script.textContent = `document.querySelectorAll('#ii0b7a'); document.createElement(........`  
shadowRoot.appendChild(script)

header.attachShadow({
 mode: 'open'
}).appendChild(shadowRoot)

document.getElementById('div-box-one').appendChild(header)

So far so good, but the code won't run correctly, because the script is accessing the document elements and not the shadowRoot. So I should first access shadowroot and then I'll be able to access the elements inside it. To do so, i'm wrapping the js code inside a function and renaming document variable like this:

(function(document) {
    // code here
}(document.getElementById('shadow_root').shadowRoot));

But this approach is not working correctly, because in some case I have to use the function "document.createElement" which will then throw an error.

My question is: How can I rename document variable only when needed. For example

document.querySelectorAll('#') = document.getElementById('shadow_root').shadowRoot.querySelectorAll('#')

document.createElement = document.createElement

I know it is almost impossible to use libraries inside shadowRoot and iframe is another solution, but iframe brings me other problems with it. (shadow-dom library)

Is it possible to achieve what I want renaming somehow the document variable?

Gabriel G
  • 97
  • 12
  • Does this answer your question? https://stackoverflow.com/questions/53698654/how-to-execute-javascript-in-shadow-dom-web-components – Dan Mullin May 03 '21 at 18:08
  • No. The script is running correctly. The problem is that inside the script elements are accessed using document.querySelector and so on. This will not find elements inside shadowRoot, thats why I am renaming document variable. – Gabriel G May 03 '21 at 18:13
  • Can you add a working snippet... Because you are doing weird code.. You add elements to body, and then you move elements to header.. Where is header? If it was in body originally it was removed bij pageContent – Danny '365CSI' Engelman May 03 '21 at 18:23
  • working codepen example: https://codepen.io/gabgran/pen/NWdQoMb See how the node list echoes on console and the error shows only when trying to createElement – Gabriel G May 03 '21 at 18:34

1 Answers1

0

So I've came up with the following solution:

function documentParse() {
   var element = document.getElementById('shadow_root').shadowRoot
   element.createElement = function createElement(type) {
      return document.createElement(type)
   }
   element.head = document.head
   return element
}

script.textContent = `(function(document) {
 //script source text
}(documentParse()));`

....

Wrapping the script in this way will bring every search on document to the scope of elements inside the shadowroot dom.

Gabriel G
  • 97
  • 12