2 changed files with 194 additions and 1 deletions
@ -0,0 +1,178 @@ |
|||
const frameHtml = `<!doctype html> |
|||
<html> |
|||
<head> |
|||
<title>Frame</title> |
|||
<style> |
|||
html, body, iframe { |
|||
margin: 0; |
|||
padding: 0; |
|||
width: 100%; |
|||
height: 100%; |
|||
} |
|||
iframe { |
|||
border: none; |
|||
display: block; |
|||
} |
|||
html { |
|||
box-sizing: border-box; |
|||
} |
|||
*, *:before, *:after { |
|||
box-sizing: inherit; |
|||
} |
|||
</style> |
|||
</head> |
|||
<body> |
|||
${'<'}script type="module"> |
|||
let frame = undefined |
|||
addEventListener('message', event => { |
|||
let isNew = false |
|||
const d = event.data |
|||
if (Array.isArray(d) && d[0] === 'srcdoc') { |
|||
isNew = frame === undefined |
|||
if (isNew) { |
|||
frame = document.createElement('iframe') |
|||
frame.sandbox = "allow-scripts allow-top-navigation" |
|||
} |
|||
frame.srcdoc = d[1] |
|||
} else if (frame !== undefined) { |
|||
frame.postMessage(event.data) |
|||
} |
|||
if (isNew) { |
|||
document.body.appendChild(frame) |
|||
} |
|||
}) |
|||
${'</'}script> |
|||
</body> |
|||
</html>` |
|||
|
|||
export class FileGroupPage extends HTMLElement { |
|||
constructor() { |
|||
super() |
|||
this.attachShadow({mode: 'open'}) |
|||
this.csp = "default-src 'self' 'unsafe-inline' 'unsafe-eval'" |
|||
} |
|||
|
|||
connectedCallback() { |
|||
const style = document.createElement('style') |
|||
style.textContent = ` |
|||
:host { |
|||
display: grid; |
|||
grid-template-columns: 1fr; |
|||
grid-template-rows: 1fr; |
|||
grid-template-areas: "main"; |
|||
flex-direction: column; |
|||
align-items: stretch; |
|||
} |
|||
iframe { |
|||
border: none; |
|||
margin: 0; |
|||
padding: 0; |
|||
grid-area: main; |
|||
width: 100%; |
|||
} |
|||
:host(.editing) iframe.view { |
|||
display: none; |
|||
} |
|||
:host(.viewing) iframe.edit { |
|||
display: none; |
|||
} |
|||
` |
|||
this.shadowRoot.append(style) |
|||
this.initEditFrame() |
|||
this.initViewFrame() |
|||
this.editing = this.editing |
|||
} |
|||
|
|||
initEditFrame() { |
|||
const frame = document.createElement('iframe') |
|||
if (this.csp !== undefined) { |
|||
frame.sandbox = "allow-same-origin allow-scripts allow-top-navigation" |
|||
const url = new URL( |
|||
'/-/frame', location.href |
|||
) |
|||
url.searchParams.set('csp', this.csp) |
|||
url.searchParams.set('html', frameHtml) |
|||
frame.src = url.href |
|||
} else { |
|||
frame.sandbox = "allow-scripts allow-top-navigation" |
|||
frame.srcdoc = frameHtml |
|||
} |
|||
frame.addEventListener('load', () => { |
|||
this.displayEdit() |
|||
}) |
|||
this.editFrame = frame |
|||
this.shadowRoot.append(frame) |
|||
} |
|||
|
|||
initViewFrame() { |
|||
const frame = document.createElement('iframe') |
|||
if (this.csp !== undefined) { |
|||
frame.sandbox = "allow-same-origin allow-scripts allow-top-navigation" |
|||
const url = new URL( |
|||
'/-/frame', location.href |
|||
) |
|||
url.searchParams.set('csp', this.csp) |
|||
url.searchParams.set('html', frameHtml) |
|||
frame.src = url.href |
|||
} else { |
|||
frame.sandbox = "allow-scripts allow-top-navigation" |
|||
frame.srcdoc = frameHtml |
|||
} |
|||
frame.addEventListener('load', () => { |
|||
this.displayView() |
|||
}) |
|||
this.viewFrame = frame |
|||
this.shadowRoot.append(frame) |
|||
} |
|||
|
|||
displayView() { |
|||
let doc = 'view here' |
|||
const msg = ['srcdoc', doc] |
|||
this.viewFrame.contentWindow.postMessage( |
|||
msg, '*' |
|||
) |
|||
} |
|||
|
|||
displayEdit() { |
|||
let doc = 'edit here' |
|||
const msg = ['srcdoc', doc] |
|||
this.viewFrame.contentWindow.postMessage( |
|||
msg, '*' |
|||
) |
|||
} |
|||
|
|||
set body(value) { |
|||
try { |
|||
localStorage.setItem(this.path, value) |
|||
} catch (err) { |
|||
console.error(err) |
|||
} |
|||
} |
|||
|
|||
get body() { |
|||
try { |
|||
return localStorage.getItem(this.path) |
|||
} catch (err) { |
|||
console.error(err) |
|||
return '' |
|||
} |
|||
} |
|||
|
|||
set editing(value) { |
|||
this._editing = value |
|||
if (this.shadowRoot.host) { |
|||
const classes = this.shadowRoot.host.classList |
|||
if (this.editing) { |
|||
classes.add('editing') |
|||
classes.remove('viewing') |
|||
} else { |
|||
classes.add('viewing') |
|||
classes.remove('editing') |
|||
} |
|||
} |
|||
} |
|||
|
|||
get editing() { |
|||
return this._editing |
|||
} |
|||
} |
|||
Loading…
Reference in new issue