Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Shadow DOM: is it possible to encapsulate JS?

I'm trying to find a way to encapsulate Javascript without using iframes. Ideally, I'd like a way to load external HTML components (widgets) on a parent page, without the two-step loading process, which comes with using iframes (first the host page loads, and only then does the iframe content is loaded).

Is it possible to accomplish that with some of the new web components technologies - shadow DOM / templates / imports? I was able to come close with adding HTML to shadow DOM and encapsulating CSS, but couldn't confirm whether it's possible to get a separate document for the component's javascript execution.

like image 999
Sasha Avatar asked Feb 14 '15 16:02

Sasha


2 Answers

Web-components, being used through HTML imports, encapsulate both Shadow DOM HTML and related script.

To narrow the terminology, let’s consider we have a Polymer component core-ajax. Here is the code. As you might see, it does not provide any HTML markup at all, encapsulating the script only.

Once imported on the host webpage as:

<link 
  rel="import"
  href="https://www.polymer-project.org/components/core-ajax/core-ajax.html"> 

this component provides an ability to perform AJAX calls without any javascript coding:

<core-ajax
  auto
  url="http://gdata.youtube.com/feeds/api/videos/"
  params='{"alt":"json", "q":"chrome"}'
  handleAs="json"
  response='{{response}}'
</core-ajax>

The above will load (since auto attribute is set) the content of the specified URL and put the response into bound response variable. Another way to communicate with this component is to supply handler instead of binding template variable to response:

  - response='{{response}}'
  + on-core-response="{{handleResponse}}"

One might implement handleResponse function in the page’s javascript and that’s it.

UPD Although currently there is no ability to distinguish main document and one used by shadow DOM, this feature is being discussed for almost three years in w3c mailgroups. The discussion is far from conclusion, though, even in aspects like “whether we never entirely enable them in author space.”

like image 146
Aleksei Matiushkin Avatar answered Sep 23 '22 04:09

Aleksei Matiushkin


This isn't related to the shadow dom, but it is related to encapsulating components entirely using javascript: https://benfrain.com/sandbox-local-htmlcss-code-snippets-inside-iframe-style-guidespattern-libraries/

Basically you create an iframe node and inject css and javascript into it:

var newIframe = document.createElement('iframe')
newIframe.contentWindow.document.open('text/html', 'replace')
var content = '<!DOCTYPE html><html><head>'+CSS+'</head><body>'+HTML+JS+'</body></html>'
newIframe.contentWindow.document.write(content)
newIframe.contentWindow.document.close()

To completely isolate the javascript from accessing its parent page, I believe you can modify the parent page's document.domain with some kind of randomly generated domain so that, to the new iframe, the parent page will look like its in a different domain and has no way of changing its domain to match. This would come with all the usual security constraints. Then you can safely talk to the child iframe via postmessage.

Theoretically you could also implement some communication to automatically resize the iframe element depending on its content, simulating a non-iframe element in-flow.

This is something I want to experiment with in the future, but haven't tried out yet.

like image 30
B T Avatar answered Sep 22 '22 04:09

B T