Frame Interactions

Scripts on an html page inside the about frame plugin are able to interact with wiki using specific messages - see: - About Frame Integrations - Frame Height

Considering the interaction between the wiki the embeddded HTML page we have **two sides** involved: 1. **The embedded HTML page** inside the `<iframe>`. 2. **The Federated Wiki client**, which hosts and renders that `<iframe>` using the `frame` plugin. These two use `window.postMessage()` to communicate across the frame boundary.

# What Happens and When?

digraph FrameMessageFlow { rankdir=LR; node [shape=box style=rounded fontsize=12 fontname="Helvetica"]; subgraph cluster_parent { label="Federated Wiki (Parent)"; style=dashed; wikiClient [label="Wiki Client\n(Parent Window)"]; } subgraph cluster_frame { label="Embedded Frame (iframe)"; style=dashed; framePage [label="HTML Page\n(DOM Content Loaded)"]; listener [label="Message Listener:\nhandleFrameContext"]; } framePage -> wikiClient [label="postMessage: sendFrameContext", style=bold, color=blue]; wikiClient -> listener [label="postMessage: frameContext", style=dashed, color=green]; listener -> listener [label="Remove listener", style=dotted, color=gray]; }

Let's examine an interaction where the HTML page requests the frame context - that is information about the wiki-page the plugin is situated on.

# Step 1: Embedded Page Requests Context Info When the embedded page loads (`DOMContentLoaded`), it sends a message to its parent (the wiki client) saying:

window.parent.postMessage({ action: "sendFrameContext" }, "*")

* **Sender**: the page **inside** the frame. * **Recipient**: the **wiki** client (parent window). * **When**: as soon as the embedded frame's DOM is loaded. * **Why**: to ask the wiki client for context like the page title, item ID, origin, site, etc.

# Step 2: Wiki Replies with Frame Context The wiki client understands the message (`action: "sendFrameContext"`), and will respond with a message like:

{ action: "frameContext", pageKey, itemId, origin, site, slug, item, page: {title, story} }

* **Sender**: the **wiki client (parent window)**. * **Recipient**: the **embedded HTML page**. * **When**: after receiving the `sendFrameContext` request. * **Why**: to give the embedded page access to the context it needs to adapt its behavior to the hosting wiki page.

# Step 3: Embedded Page Handles the Context The embedded page has already set up a listener:

window.addEventListener("message", handleFrameContext)

So when the parent sends the `"frameContext"` message, the handler does the following: * Logs the message and its content. * Optionally does something with the page title, item IDs, or story content. * **Removes** the event listener so it doesn’t listen multiple times.

# Frame Context Code Here we see the code demo including all the parts. You can see it in action on the About Frame Integrations page.

#

window.addEventListener("message", handleFrameContext) function handleFrameContext ({data}) { console.log("message received", data) if (data.action == "frameContext") { window.removeEventListener( "message", handleFrameContext) const {pageKey, itemId, origin, site, slug, item, page: {title, story}} = data const items = story.reduce((acc, {type}) => { acc[type] = (acc[type]||0)+1 return acc }, {}) console.log({title, items}) } } window.addEventListener( "DOMContentLoaded", () => window.parent.postMessage({ action: "sendFrameContext" }, "*") )

It may not be apparant, but the frameContext message contains the full page-json (inclusing the journal), but not inforamtion about the current lineup.

# Feature Requests

- [ ] **Lineup Array**. We would like to be able to retrieve information about the current lineup.

Full access to the dynamicly displayed content is probably not a good idea for security reasons - but knowledge of the browsers displayed url - or rather an ordered array of lineup items containing `title,slug,domain` would be useful in a number of contexts where a tool wishes to interact with page-json found in the lineup.

# See