From 683e2451972b1ac3207731f0363994b1b91aaa0a Mon Sep 17 00:00:00 2001 From: Ellpeck Date: Tue, 29 Mar 2022 13:18:25 +0200 Subject: [PATCH] split up the code into multiple files --- esbuild.config.mjs | 7 +- main.ts | 371 -------------------------------------------- src/main.ts | 51 ++++++ src/settings-tab.ts | 157 +++++++++++++++++++ src/settings.ts | 47 ++++++ src/view.ts | 123 +++++++++++++++ 6 files changed, 382 insertions(+), 374 deletions(-) delete mode 100644 main.ts create mode 100644 src/main.ts create mode 100644 src/settings-tab.ts create mode 100644 src/settings.ts create mode 100644 src/view.ts diff --git a/esbuild.config.mjs b/esbuild.config.mjs index f1fe201..a54797c 100644 --- a/esbuild.config.mjs +++ b/esbuild.config.mjs @@ -3,7 +3,7 @@ import process from "process"; import builtins from 'builtin-modules' const banner = -`/* + `/* THIS IS A GENERATED/BUNDLED FILE BY ESBUILD if you want to view the source, please visit the github repository of this plugin */ @@ -15,7 +15,7 @@ esbuild.build({ banner: { js: banner, }, - entryPoints: ['main.ts'], + entryPoints: ['src/main.ts'], bundle: true, external: [ 'obsidian', @@ -41,7 +41,8 @@ esbuild.build({ '@codemirror/text', '@codemirror/tooltip', '@codemirror/view', - ...builtins], + ...builtins + ], format: 'cjs', watch: !prod, target: 'es2016', diff --git a/main.ts b/main.ts deleted file mode 100644 index 7bc7aec..0000000 --- a/main.ts +++ /dev/null @@ -1,371 +0,0 @@ -import { App, ButtonComponent, DropdownComponent, ItemView, Plugin, PluginSettingTab, Setting, WorkspaceLeaf, Platform, Menu } from "obsidian"; - -const defaultSettings: CustomFramesSettings = { - frames: [], - padding: 5 -}; -const presets: Record = { - "obsidian": { - url: "https://forum.obsidian.md/", - displayName: "Obsidian Forum", - icon: "edit", - hideOnMobile: true, - minimumWidth: 367, - customCss: "" - }, - "keep": { - url: "https://keep.google.com", - displayName: "Google Keep", - icon: "files", - hideOnMobile: true, - minimumWidth: 370, - customCss: `/* hide the menu bar and the "Keep" text */ -.PvRhvb-qAWA2, .gb_2d.gb_Zc { - display: none !important; -}` - }, - "notion": { - url: "https://www.notion.so/", - displayName: "Notion", - icon: "box", - hideOnMobile: true, - minimumWidth: 400, - customCss: "" - } -}; - -interface CustomFramesSettings { - frames: CustomFrame[]; - padding: number; -} - -interface CustomFrame { - url: string; - displayName: string; - icon: string; - hideOnMobile: boolean; - minimumWidth: number; - customCss: string; -} - -export default class CustomFramesPlugin extends Plugin { - - settings: CustomFramesSettings; - - async onload(): Promise { - await this.loadSettings(); - - for (let frame of this.settings.frames) { - if (!frame.url || !frame.displayName) - continue; - let name = `custom-frames-${frame.displayName.toLowerCase().replace(/\s/g, "-")}`; - if (Platform.isMobileApp && frame.hideOnMobile) { - console.log(`Skipping frame ${name} which is hidden on mobile`); - continue; - } - try { - console.log(`Registering frame ${name} for URL ${frame.url}`); - - this.registerView(name, l => new CustomFrameView(l, this.settings, frame, name)); - this.addCommand({ - id: `open-${name}`, - name: `Open ${frame.displayName}`, - callback: () => this.openLeaf(name), - }); - } catch { - console.error(`Couldn't register frame ${name}, is there already one with the same name?`); - } - } - - this.addSettingTab(new CustomFramesSettingTab(this.app, this)); - } - - async loadSettings() { - this.settings = Object.assign({}, defaultSettings, await this.loadData()); - } - - async saveSettings() { - await this.saveData(this.settings); - } - - private async openLeaf(name: string): Promise { - if (!this.app.workspace.getLeavesOfType(name).length) - await this.app.workspace.getRightLeaf(false).setViewState({ type: name }); - this.app.workspace.revealLeaf(this.app.workspace.getLeavesOfType(name)[0]); - } -} - -class CustomFrameView extends ItemView { - - private readonly settings: CustomFramesSettings; - private readonly data: CustomFrame; - private readonly name: string; - private frame: HTMLIFrameElement | any; - - constructor(leaf: WorkspaceLeaf, settings: CustomFramesSettings, data: CustomFrame, name: string) { - super(leaf); - this.settings = settings; - this.data = data; - this.name = name; - - this.addAction("refresh-cw", "Refresh", () => this.refresh()); - this.addAction("home", "Return to original page", () => this.return()); - this.addAction("arrow-left", "Go back", () => this.goBack()); - this.addAction("arrow-right", "Go forward", () => this.goForward()); - } - - onload(): void { - this.contentEl.empty(); - this.contentEl.addClass("custom-frames-view"); - - if (Platform.isDesktopApp) { - this.frame = document.createElement("webview"); - this.frame.setAttribute("allowpopups", ""); - this.frame.addEventListener("dom-ready", () => { - this.frame.insertCSS(this.data.customCss); - - if (this.data.minimumWidth) { - let parent = this.contentEl.closest(".workspace-split.mod-horizontal"); - if (parent) { - let minWidth = `${this.data.minimumWidth + 2 * this.settings.padding}px`; - if (parent.style.width < minWidth) - parent.style.width = minWidth; - } - } - }); - } - else { - this.frame = document.createElement("iframe"); - this.frame.setAttribute("sandbox", "allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts allow-top-navigation-by-user-activation"); - this.frame.setAttribute("allow", "encrypted-media; fullscreen; oversized-images; picture-in-picture; sync-xhr; geolocation;"); - } - this.frame.addClass("custom-frames-frame"); - this.frame.setAttribute("style", `padding: ${this.settings.padding}px`); - this.frame.setAttribute("src", this.data.url); - this.contentEl.appendChild(this.frame); - } - - onHeaderMenu(menu: Menu): void { - super.onHeaderMenu(menu); - menu.addItem(i => { - i.setTitle("Refresh"); - i.setIcon("refresh-cw"); - i.onClick(() => this.refresh()); - }); - menu.addItem(i => { - i.setTitle("Return to original page"); - i.setIcon("home"); - i.onClick(() => this.return()); - }); - menu.addItem(i => { - i.setTitle("Go back"); - i.setIcon("arrow-left"); - i.onClick(() => this.goBack()); - }); - menu.addItem(i => { - i.setTitle("Go forward"); - i.setIcon("arrow-right"); - i.onClick(() => this.goForward()); - }); - } - - getViewType(): string { - return this.name; - } - - getDisplayText(): string { - return this.data.displayName; - } - - getIcon(): string { - return this.data.icon ? `lucide-${this.data.icon}` : "documents"; - } - - private refresh(): void { - if (this.frame instanceof HTMLIFrameElement) { - this.frame.contentWindow.location.reload(); - } else { - this.frame.reload(); - } - } - - private return(): void { - if (this.frame instanceof HTMLIFrameElement) { - this.frame.contentWindow.open(this.data.url); - } else { - this.frame.loadURL(this.data.url); - } - } - - private goBack(): void { - if (this.frame instanceof HTMLIFrameElement) { - this.frame.contentWindow.history.back(); - } - else { - this.frame.goBack(); - } - } - - private goForward() { - if (this.frame instanceof HTMLIFrameElement) { - this.frame.contentWindow.history.forward(); - } - else { - this.frame.goForward(); - } - } -} - -class CustomFramesSettingTab extends PluginSettingTab { - - plugin: CustomFramesPlugin; - - constructor(app: App, plugin: CustomFramesPlugin) { - super(app, plugin); - this.plugin = plugin; - } - - display(): void { - this.containerEl.empty(); - this.containerEl.createEl("h2", { text: "Custom Frames Settings" }); - this.containerEl.createEl("p", { text: "Note that Obsidian has to be restarted or reloaded for most of these settings to take effect.", cls: "mod-warning" }); - - new Setting(this.containerEl) - .setName("Frame Padding") - .setDesc("The padding that should be left around the inside of custom frame panes, in pixels.") - .addText(t => { - t.inputEl.type = "number"; - t.setValue(String(this.plugin.settings.padding)); - t.onChange(async v => { - this.plugin.settings.padding = v.length ? Number(v) : defaultSettings.padding; - await this.plugin.saveSettings(); - }); - }); - - for (let frame of this.plugin.settings.frames) { - let heading = this.containerEl.createEl("h3", { text: frame.displayName || "Unnamed Frame" }); - - new Setting(this.containerEl) - .setName("Display Name") - .setDesc("The display name that this frame should have.") - .addText(t => { - t.setValue(frame.displayName); - t.onChange(async v => { - frame.displayName = v; - heading.setText(frame.displayName || "Unnamed Frame"); - await this.plugin.saveSettings(); - }); - }); - new Setting(this.containerEl) - .setName("Icon") - .setDesc(createFragment(f => { - f.createSpan({ text: "The icon that this frame's pane should have. The names of any " }); - f.createEl("a", { text: "Lucide icons", href: "https://lucide.dev/" }); - f.createSpan({ text: " can be used." }); - })) - .addText(t => { - t.setValue(frame.icon); - t.onChange(async v => { - frame.icon = v; - await this.plugin.saveSettings(); - }); - }); - new Setting(this.containerEl) - .setName("URL") - .setDesc("The URL that should be opened in this frame.") - .addText(t => { - t.setValue(frame.url); - t.onChange(async v => { - frame.url = v; - await this.plugin.saveSettings(); - }); - }); - new Setting(this.containerEl) - .setName("Disable on Mobile") - .setDesc("Custom Frames is a lot more restricted on mobile devices and doesn't allow for the same types of content to be displayed. If a frame doesn't work as expected on mobile, it can be disabled.") - .addToggle(t => { - t.setValue(frame.hideOnMobile); - t.onChange(async v => { - frame.hideOnMobile = v; - await this.plugin.saveSettings(); - }); - }); - new Setting(this.containerEl) - .setName("Minimum Width") - .setDesc(createFragment(f => { - f.createSpan({ text: "The width that this frame's pane should be adjusted to automatically if it is lower. Set to 0 to disable." }); - f.createEl("br"); - f.createEl("em", { text: "Note that this is only applied on Desktop." }); - })) - .addText(t => { - t.inputEl.type = "number"; - t.setValue(String(frame.minimumWidth)); - t.onChange(async v => { - frame.minimumWidth = v.length ? Number(v) : 0; - await this.plugin.saveSettings(); - }); - }); - new Setting(this.containerEl) - .setName("Additional CSS") - .setDesc(createFragment(f => { - f.createSpan({ text: "A snippet of additional CSS that should be applied to this frame." }); - f.createEl("br"); - f.createEl("em", { text: "Note that this is only applied on Desktop." }); - })) - .addTextArea(t => { - t.inputEl.rows = 5; - t.inputEl.cols = 50; - t.setValue(frame.customCss); - t.onChange(async v => { - frame.customCss = v; - await this.plugin.saveSettings(); - }); - }); - - new ButtonComponent(this.containerEl) - .setButtonText("Remove Frame") - .onClick(async () => { - this.plugin.settings.frames.remove(frame); - await this.plugin.saveSettings(); - this.display(); - }); - } - - this.containerEl.createEl("hr"); - let info = this.containerEl.createEl("p", { text: "Create a new frame, either from a preset shipped with the plugin, or a custom one that you can edit yourself. Each frame's pane can be opened using the \"Custom Frames: Open\" command." }); - info.createEl("br"); - info.createSpan({ text: "Note that Obsidian has to be restarted or reloaded to activate a newly added frame.", cls: "mod-warning" }); - - let addDiv = this.containerEl.createDiv(); - addDiv.addClass("custom-frames-add"); - let dropdown = new DropdownComponent(addDiv); - dropdown.addOption("new", "Custom"); - for (let key of Object.keys(presets)) - dropdown.addOption(key, presets[key].displayName); - new ButtonComponent(addDiv) - .setButtonText("Add Frame") - .onClick(async () => { - let option = dropdown.getValue(); - if (option == "new") { - this.plugin.settings.frames.push({ - url: "", - displayName: "New Frame", - icon: "", - minimumWidth: 0, - customCss: "", - hideOnMobile: true - }); - } - else { - this.plugin.settings.frames.push(presets[option]); - } - await this.plugin.saveSettings(); - this.display(); - }); - - this.containerEl.createEl("hr"); - this.containerEl.createEl("p", { text: "If you like this plugin and want to support its development, you can do so through my website by clicking this fancy image!" }); - this.containerEl.createEl("a", { href: "https://ellpeck.de/support" }) - .createEl("img", { attr: { src: "https://ellpeck.de/res/generalsupport.png" }, cls: "custom-frames-support" }); - } -} \ No newline at end of file diff --git a/src/main.ts b/src/main.ts new file mode 100644 index 0000000..e9b3b18 --- /dev/null +++ b/src/main.ts @@ -0,0 +1,51 @@ +import { Plugin, Platform } from "obsidian"; +import { CustomFramesSettings, defaultSettings } from "./settings"; +import { CustomFramesSettingTab } from "./settings-tab"; +import { CustomFrameView } from "./view"; + +export default class CustomFramesPlugin extends Plugin { + + settings: CustomFramesSettings; + + async onload(): Promise { + await this.loadSettings(); + + for (let frame of this.settings.frames) { + if (!frame.url || !frame.displayName) + continue; + let name = `custom-frames-${frame.displayName.toLowerCase().replace(/\s/g, "-")}`; + if (Platform.isMobileApp && frame.hideOnMobile) { + console.log(`Skipping frame ${name} which is hidden on mobile`); + continue; + } + try { + console.log(`Registering frame ${name} for URL ${frame.url}`); + + this.registerView(name, l => new CustomFrameView(l, this.settings, frame, name)); + this.addCommand({ + id: `open-${name}`, + name: `Open ${frame.displayName}`, + callback: () => this.openLeaf(name), + }); + } catch { + console.error(`Couldn't register frame ${name}, is there already one with the same name?`); + } + } + + this.addSettingTab(new CustomFramesSettingTab(this.app, this)); + } + + async loadSettings() { + this.settings = Object.assign({}, defaultSettings, await this.loadData()); + } + + async saveSettings() { + await this.saveData(this.settings); + } + + private async openLeaf(name: string): Promise { + if (!this.app.workspace.getLeavesOfType(name).length) + await this.app.workspace.getRightLeaf(false).setViewState({ type: name }); + this.app.workspace.revealLeaf(this.app.workspace.getLeavesOfType(name)[0]); + } +} \ No newline at end of file diff --git a/src/settings-tab.ts b/src/settings-tab.ts new file mode 100644 index 0000000..e2448ca --- /dev/null +++ b/src/settings-tab.ts @@ -0,0 +1,157 @@ +import { App, ButtonComponent, DropdownComponent, PluginSettingTab, Setting } from "obsidian"; +import { defaultSettings, presets } from "./settings"; +import CustomFramesPlugin from "./main"; + +export class CustomFramesSettingTab extends PluginSettingTab { + + plugin: CustomFramesPlugin; + + constructor(app: App, plugin: CustomFramesPlugin) { + super(app, plugin); + this.plugin = plugin; + } + + display(): void { + this.containerEl.empty(); + this.containerEl.createEl("h2", { text: "Custom Frames Settings" }); + this.containerEl.createEl("p", { text: "Note that Obsidian has to be restarted or reloaded for most of these settings to take effect.", cls: "mod-warning" }); + + new Setting(this.containerEl) + .setName("Frame Padding") + .setDesc("The padding that should be left around the inside of custom frame panes, in pixels.") + .addText(t => { + t.inputEl.type = "number"; + t.setValue(String(this.plugin.settings.padding)); + t.onChange(async v => { + this.plugin.settings.padding = v.length ? Number(v) : defaultSettings.padding; + await this.plugin.saveSettings(); + }); + }); + + for (let frame of this.plugin.settings.frames) { + let heading = this.containerEl.createEl("h3", { text: frame.displayName || "Unnamed Frame" }); + + new Setting(this.containerEl) + .setName("Display Name") + .setDesc("The display name that this frame should have.") + .addText(t => { + t.setValue(frame.displayName); + t.onChange(async v => { + frame.displayName = v; + heading.setText(frame.displayName || "Unnamed Frame"); + await this.plugin.saveSettings(); + }); + }); + new Setting(this.containerEl) + .setName("Icon") + .setDesc(createFragment(f => { + f.createSpan({ text: "The icon that this frame's pane should have. The names of any " }); + f.createEl("a", { text: "Lucide icons", href: "https://lucide.dev/" }); + f.createSpan({ text: " can be used." }); + })) + .addText(t => { + t.setValue(frame.icon); + t.onChange(async v => { + frame.icon = v; + await this.plugin.saveSettings(); + }); + }); + new Setting(this.containerEl) + .setName("URL") + .setDesc("The URL that should be opened in this frame.") + .addText(t => { + t.setValue(frame.url); + t.onChange(async v => { + frame.url = v; + await this.plugin.saveSettings(); + }); + }); + new Setting(this.containerEl) + .setName("Disable on Mobile") + .setDesc("Custom Frames is a lot more restricted on mobile devices and doesn't allow for the same types of content to be displayed. If a frame doesn't work as expected on mobile, it can be disabled.") + .addToggle(t => { + t.setValue(frame.hideOnMobile); + t.onChange(async v => { + frame.hideOnMobile = v; + await this.plugin.saveSettings(); + }); + }); + new Setting(this.containerEl) + .setName("Minimum Width") + .setDesc(createFragment(f => { + f.createSpan({ text: "The width that this frame's pane should be adjusted to automatically if it is lower. Set to 0 to disable." }); + f.createEl("br"); + f.createEl("em", { text: "Note that this is only applied on Desktop." }); + })) + .addText(t => { + t.inputEl.type = "number"; + t.setValue(String(frame.minimumWidth)); + t.onChange(async v => { + frame.minimumWidth = v.length ? Number(v) : 0; + await this.plugin.saveSettings(); + }); + }); + new Setting(this.containerEl) + .setName("Additional CSS") + .setDesc(createFragment(f => { + f.createSpan({ text: "A snippet of additional CSS that should be applied to this frame." }); + f.createEl("br"); + f.createEl("em", { text: "Note that this is only applied on Desktop." }); + })) + .addTextArea(t => { + t.inputEl.rows = 5; + t.inputEl.cols = 50; + t.setValue(frame.customCss); + t.onChange(async v => { + frame.customCss = v; + await this.plugin.saveSettings(); + }); + }); + + new ButtonComponent(this.containerEl) + .setButtonText("Remove Frame") + .onClick(async () => { + this.plugin.settings.frames.remove(frame); + await this.plugin.saveSettings(); + this.display(); + }); + } + + this.containerEl.createEl("hr"); + let info = this.containerEl.createEl("p", { text: "Create a new frame, either from a preset shipped with the plugin, or a custom one that you can edit yourself. Each frame's pane can be opened using the \"Custom Frames: Open\" command." }); + info.createEl("br"); + info.createSpan({ text: "Note that Obsidian has to be restarted or reloaded to activate a newly added frame.", cls: "mod-warning" }); + + let addDiv = this.containerEl.createDiv(); + addDiv.addClass("custom-frames-add"); + let dropdown = new DropdownComponent(addDiv); + dropdown.addOption("new", "Custom"); + for (let key of Object.keys(presets)) + dropdown.addOption(key, presets[key].displayName); + new ButtonComponent(addDiv) + .setButtonText("Add Frame") + .onClick(async () => { + let option = dropdown.getValue(); + if (option == "new") { + this.plugin.settings.frames.push({ + url: "", + displayName: "New Frame", + icon: "", + minimumWidth: 0, + customCss: "", + hideOnMobile: true + }); + } + else { + this.plugin.settings.frames.push(presets[option]); + } + await this.plugin.saveSettings(); + this.display(); + }); + + this.containerEl.createEl("hr"); + this.containerEl.createEl("p", { text: "If you like this plugin and want to support its development, you can do so through my website by clicking this fancy image!" }); + this.containerEl.createEl("a", { href: "https://ellpeck.de/support" }) + .createEl("img", { attr: { src: "https://ellpeck.de/res/generalsupport.png" }, cls: "custom-frames-support" }); + } +} \ No newline at end of file diff --git a/src/settings.ts b/src/settings.ts new file mode 100644 index 0000000..d8297a8 --- /dev/null +++ b/src/settings.ts @@ -0,0 +1,47 @@ +export const defaultSettings: CustomFramesSettings = { + frames: [], + padding: 5 +}; +export const presets: Record = { + "obsidian": { + url: "https://forum.obsidian.md/", + displayName: "Obsidian Forum", + icon: "edit", + hideOnMobile: true, + minimumWidth: 367, + customCss: "" + }, + "keep": { + url: "https://keep.google.com", + displayName: "Google Keep", + icon: "files", + hideOnMobile: true, + minimumWidth: 370, + customCss: `/* hide the menu bar and the "Keep" text */ +.PvRhvb-qAWA2, .gb_2d.gb_Zc { + display: none !important; +}` + }, + "notion": { + url: "https://www.notion.so/", + displayName: "Notion", + icon: "box", + hideOnMobile: true, + minimumWidth: 400, + customCss: "" + } +}; + +export interface CustomFramesSettings { + frames: CustomFrame[]; + padding: number; +} + +export interface CustomFrame { + url: string; + displayName: string; + icon: string; + hideOnMobile: boolean; + minimumWidth: number; + customCss: string; +} \ No newline at end of file diff --git a/src/view.ts b/src/view.ts new file mode 100644 index 0000000..1b0e5c6 --- /dev/null +++ b/src/view.ts @@ -0,0 +1,123 @@ +import { ItemView, WorkspaceLeaf, Platform, Menu } from "obsidian"; +import { CustomFrame, CustomFramesSettings } from "./settings"; + +export class CustomFrameView extends ItemView { + + private readonly settings: CustomFramesSettings; + private readonly data: CustomFrame; + private readonly name: string; + private frame: HTMLIFrameElement | any; + + constructor(leaf: WorkspaceLeaf, settings: CustomFramesSettings, data: CustomFrame, name: string) { + super(leaf); + this.settings = settings; + this.data = data; + this.name = name; + + this.addAction("refresh-cw", "Refresh", () => this.refresh()); + this.addAction("home", "Return to original page", () => this.return()); + this.addAction("arrow-left", "Go back", () => this.goBack()); + this.addAction("arrow-right", "Go forward", () => this.goForward()); + } + + onload(): void { + this.contentEl.empty(); + this.contentEl.addClass("custom-frames-view"); + + if (Platform.isDesktopApp) { + this.frame = document.createElement("webview"); + this.frame.setAttribute("allowpopups", ""); + this.frame.addEventListener("dom-ready", () => { + this.frame.insertCSS(this.data.customCss); + + if (this.data.minimumWidth) { + let parent = this.contentEl.closest(".workspace-split.mod-horizontal"); + if (parent) { + let minWidth = `${this.data.minimumWidth + 2 * this.settings.padding}px`; + if (parent.style.width < minWidth) + parent.style.width = minWidth; + } + } + }); + } + else { + this.frame = document.createElement("iframe"); + this.frame.setAttribute("sandbox", "allow-forms allow-modals allow-popups allow-presentation allow-same-origin allow-scripts allow-top-navigation-by-user-activation"); + this.frame.setAttribute("allow", "encrypted-media; fullscreen; oversized-images; picture-in-picture; sync-xhr; geolocation;"); + } + this.frame.addClass("custom-frames-frame"); + this.frame.setAttribute("style", `padding: ${this.settings.padding}px`); + this.frame.setAttribute("src", this.data.url); + this.contentEl.appendChild(this.frame); + } + + onHeaderMenu(menu: Menu): void { + super.onHeaderMenu(menu); + menu.addItem(i => { + i.setTitle("Refresh"); + i.setIcon("refresh-cw"); + i.onClick(() => this.refresh()); + }); + menu.addItem(i => { + i.setTitle("Return to original page"); + i.setIcon("home"); + i.onClick(() => this.return()); + }); + menu.addItem(i => { + i.setTitle("Go back"); + i.setIcon("arrow-left"); + i.onClick(() => this.goBack()); + }); + menu.addItem(i => { + i.setTitle("Go forward"); + i.setIcon("arrow-right"); + i.onClick(() => this.goForward()); + }); + } + + getViewType(): string { + return this.name; + } + + getDisplayText(): string { + return this.data.displayName; + } + + getIcon(): string { + return this.data.icon ? `lucide-${this.data.icon}` : "documents"; + } + + private refresh(): void { + if (this.frame instanceof HTMLIFrameElement) { + this.frame.contentWindow.location.reload(); + } else { + this.frame.reload(); + } + } + + private return(): void { + if (this.frame instanceof HTMLIFrameElement) { + this.frame.contentWindow.open(this.data.url); + } else { + this.frame.loadURL(this.data.url); + } + } + + private goBack(): void { + if (this.frame instanceof HTMLIFrameElement) { + this.frame.contentWindow.history.back(); + } + else { + this.frame.goBack(); + } + } + + private goForward() { + if (this.frame instanceof HTMLIFrameElement) { + this.frame.contentWindow.history.forward(); + } + else { + this.frame.goForward(); + } + } +} \ No newline at end of file