|
| 1 | +With the release of [Obsidian v0.15.0](https://obsidian.md/changelog/2022-06-14-desktop-v0.15.0/), the pop-out windows feature was added to the desktop version of Obsidian. |
| 2 | + |
| 3 | +For most plugins, this feature should work out-of-the-box. However, some things work differently when your plugin renders things in pop-out windows. |
| 4 | + |
| 5 | +Most importantly, pop-out windows come with a complete different set of globals. Each pop-out window introduces its own `Window` object, `Document` object, and fresh copies of all global constructors (like `HTMLElement` and `MouseEvent`). |
| 6 | + |
| 7 | +This means that some of the things you previously had assumed to be global and use only _a single_ definition, will now only work in the main window. Here are some examples: |
| 8 | + |
| 9 | +```ts |
| 10 | +let myElement: HTMLElement = ...; |
| 11 | + |
| 12 | +// This will always append to the main window |
| 13 | +document.body.appendChild(myElement); |
| 14 | + |
| 15 | +// This will actually be false if element is in a pop-out window |
| 16 | +if (myElement instanceof HTMLElement) { |
| 17 | + |
| 18 | +} |
| 19 | + |
| 20 | +element.on('click', '.my-css-class', (event) => { |
| 21 | + // This will be false if the event is triggered in a pop-out window |
| 22 | + if (event instanceof MouseEvent) { |
| 23 | + |
| 24 | + } |
| 25 | +} |
| 26 | +``` |
| 27 | +
|
| 28 | +The Obsidian API includes various helper function and accessors to better support pop-out windows: |
| 29 | +
|
| 30 | +- A global `activeWindow` and `activeDocument` variable, which always points to the current focused window and its document. |
| 31 | +- An `element.win` and `element.doc` getter, which respectively point to the `Window` and `Document` objects that the element belongs to. |
| 32 | +- A function for performing cross-window compatible `instanceof` checks. Use `element.instanceOf(HTMLElement)` and `event.instanceOf(MouseEvent)`, instead of `element instanceof HTMLElement` and `event instanceof MouseEvent`. |
| 33 | +- `HTMLElement.onWindowMigrated(callback)` which hooks a callback on the element for when it is inserted into a different window than it originally was in. This can be used for complex renderers like canvases to re-initialize the rendering context. |
| 34 | +
|
| 35 | +Using these APIs, the previous example would look like this: |
| 36 | +
|
| 37 | +```ts |
| 38 | +let myElement: HTMLElement = ...; |
| 39 | + |
| 40 | +// Bad: myElement would be added to the currently focused document, which is not necessarily the one you want |
| 41 | +activeDocument.body.appendChild(myElement); |
| 42 | +// Good: This will append myElement to the same window as someElement |
| 43 | +someElement.doc.body.appendChild(myElement); |
| 44 | + |
| 45 | +// This will work correctly in pop-out windows |
| 46 | +if (myElement.instanceOf(HTMLElement)) { |
| 47 | + |
| 48 | +} |
| 49 | + |
| 50 | +element.on('click', '.my-css-class', (event) => { |
| 51 | + // This will work correctly in pop-out windows |
| 52 | + if (event.instanceOf(MouseEvent)) { |
| 53 | + |
| 54 | + } |
| 55 | +} |
| 56 | +``` |
0 commit comments