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.
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.”
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.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With