Skip to content

Instantly share code, notes, and snippets.

@jjrv
Created May 24, 2020 11:29
Show Gist options
  • Star 0 You must be signed in to star a gist
  • Fork 0 You must be signed in to fork a gist
  • Save jjrv/258f781646a48f56044ef15fe766a478 to your computer and use it in GitHub Desktop.
Save jjrv/258f781646a48f56044ef15fe766a478 to your computer and use it in GitHub Desktop.
import { Widget } from '@phosphor/widgets';
import { ElementExt } from '@phosphor/domutils';
export class IframePanel extends Widget {
constructor(iframe?: HTMLIFrameElement | null) {
super({ node: IframePanel.createNode() });
if(!iframe) iframe = document.createElement('iframe');
this.iframe = iframe;
this.addClass('phosphor-iframe');
this.addClass('charto-panel');
this.updateTitle();
this.node.addEventListener('mouseover', this);
this.node.addEventListener('mouseout', this);
this.node.addEventListener('mouseup', this);
iframe.addEventListener('mouseover', this);
iframe.addEventListener('mouseout', this);
iframe.addEventListener('mouseup', this);
iframe.addEventListener('load', this);
iframe.classList.add('charto-content');
if(iframe.contentWindow) this.handleEvent(new Event('load'));
}
static createNode(): HTMLElement {
const node = document.createElement('div');
return(node);
}
handleEvent(event: Event) {
switch(event.type) {
case 'load':
this.iframe.contentWindow!.addEventListener('beforeunload', this);
break;
case 'beforeunload':
const uri = this.iframe.contentWindow!.location.href;
const interval = window.setInterval(() => {
if(this.iframe.contentWindow && this.iframe.contentWindow.location.href != uri) {
this.updateTitle();
// iframe.contentWindow.location.href = 'nonexistent.html';
// this.iframe.contentWindow.location.href = uri;
window.clearInterval(interval);
}
}, 1);
break;
case 'mouseover':
if(event.target == this.iframe) this.overFlags |= 1;
if(event.target == this.node) this.overFlags |= 2;
// Fallthru
case 'mouseup':
// Allow iframe to capture events if mouse enters
// without primary button pressed.
if(!((event as MouseEvent).buttons & 1)) {
if(this.overFlags) this.iframe.style.pointerEvents = 'auto';
}
break;
case 'mouseout':
if(event.target == this.iframe) this.overFlags &= ~1;
if(event.target == this.node) this.overFlags &= ~2;
if(!this.overFlags) this.iframe.style.pointerEvents = 'none';
break;
}
}
updateTitle(uri = '') {
if(!uri && this.iframe.contentWindow) uri = this.iframe.contentWindow.location.href;
const uriParts = uri.split('/');
this.title.label = uriParts[uriParts.length - 1];
this.title.caption = uri;
}
onAfterHide() {
// Using "display: none" could cause code misbehaviour inside iframe
// due to skipped rendering-related computation.
this.iframe.style.visibility = 'hidden';
}
onAfterShow() {
this.iframe.style.visibility = 'visible';
}
onResize(msg: Widget.ResizeMessage) {
// Move iframe over the content div. Unfortunately reparenting
// the iframe would cause it to reload.
const rect = this.node.getBoundingClientRect();
const box = ElementExt.boxSizing(this.node);
const ibox = ElementExt.boxSizing(this.iframe);
this.iframe.style.top = (rect.top + box.borderTop + box.paddingTop) + 'px';
this.iframe.style.left = (rect.left + box.borderLeft + box.paddingLeft) + 'px';
this.iframe.style.width = (rect.right - rect.left - box.horizontalSum - ibox.borderLeft - ibox.borderRight) + 'px';
this.iframe.style.height = (rect.bottom - rect.top - box.verticalSum - ibox.borderTop - ibox.borderBottom) + 'px';
}
iframe: HTMLIFrameElement;
overFlags = 0;
}
import * as monaco from 'monaco-editor';
import { Widget } from '@phosphor/widgets';
export class MonacoEditor extends Widget {
constructor(options?: monaco.editor.IEditorConstructionOptions, override?: monaco.editor.IEditorOverrideServices) {
super({ node: MonacoEditor.createNode() });
this.addClass('phosphor-monaco');
this.addClass('charto-panel');
this.editorDiv = document.createElement('div');
this.editorDiv.className = 'charto-content';
this.node.appendChild(this.editorDiv);
this.editor = monaco.editor.create(this.editorDiv, options, override);
this.editor.onDidChangeModel((event) => this.updateTitle(event.newModelUrl));
this.updateTitle();
}
static createNode(): HTMLElement {
const node = document.createElement('div');
return(node);
}
updateTitle(uri = this.editor.getModel().uri) {
const fullPath = uri.path;
const pathParts = fullPath.split('/');
this.title.label = pathParts[pathParts.length - 1];
this.title.caption = fullPath;
}
onResize(msg: Widget.ResizeMessage) {
this.editor.layout();
}
static api = monaco;
editorDiv: HTMLDivElement;
editor: monaco.editor.IStandaloneCodeEditor;
}
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment