joicomponents
Version:
Design patterns to build native web components
78 lines (70 loc) • 2.44 kB
HTML
<script>
const innerTemplate = `
<script src="https://unpkg.com/joievents@1.0.16/src/link-click-es6.js"></scrip` + `t>
<script src="https://unpkg.com/joievents@1.0.16/src/browse.js"></scrip` + `t>
<script>(function(){
window.addEventListener("browse", function(e){
e.preventDefault();
let event = {type: e.type, timeStamp: e.timeStamp, href: e.getHref()};
parent.postMessage(JSON.stringify({event}), "*");
}, true);
})();</scrip` + `t>`;
const outerTemplate = document.createElement("template");
outerTemplate.innerHTML = `
<style>
:host, iframe {
border: none;
margin: 0;
padding: 0;
}
:host{
overflow: visible;
display: inline-block;
}
iframe {
overflow: hidden;
height: 100%; /*initial value only, will be overwritten later*/
width: 100%; /*initial value only, will be overwritten later*/
}
</style>
<iframe sandbox="allow-scripts" scrolling="no" frameborder="0"></iframe>`;
class OverflowIframe extends HTMLElement {
constructor() {
super();
this.attachShadow({mode: "open"});
this.shadowRoot.appendChild(outerTemplate.content.cloneNode(true));
this._iframe = this.shadowRoot.children[1];
window.addEventListener("message", this.onMessage.bind(this))
}
static get observedAttributes() {
return ["srcdoc"];
}
attributeChangedCallback(name, oldValue, newValue) {
if (name === "srcdoc") {
const src = (newValue || "") + innerTemplate;
let blob = new Blob([src], {type: "text/html"});
this._iframe.setAttribute("src", URL.createObjectURL(blob));
}
}
onMessage(e) {
if (e.source !== this._iframe.contentWindow)
return;
const res = JSON.parse(e.data);
if (res.event)
this.dispatchEvent(new CustomEvent(res.event.type, {bubbles: true, composed: true, detail: {href: res.event.href}}));
}
}
customElements.define("overflow-iframe", OverflowIframe);
</script>
<h1>Hello world!</h1>
<hr>
<overflow-iframe srcdoc="<a href='//bbc.com'>bbc.com</a><hr><a href='//google.com'>google.com</a>"></overflow-iframe>
<script>
window.addEventListener("browse", function(e){
console.log("browsing to: ", e);
});
</script>
<!--
This code is untested. I have only done superficial tests from within devtools in Chrome.
The code should only work in Chrome, Safari, Firefox as template does not work in IE and Edge.
-->