+
+
+
+
+```
+
+## Strategies
+
+### dom-order (default)
+
+Initializes iframes in DOM order (1st iframe first, then 2nd, then 3rd, etc.).
+
+```javascript
+initializeDoenetParentCoordinator({
+ strategy: "dom-order"
+});
+```
+
+### viewport-first
+
+Prioritizes visible iframes, initializing those in viewport first (sorted by DOM order), then initializes remaining iframes in DOM order.
+
+```javascript
+initializeDoenetParentCoordinator({
+ strategy: "viewport-first"
+});
+```
+
+Perfect for pages where users may scroll to see content - visible content initializes first for a responsive feel.
+
+**Note**: Visibility is detected using an IntersectionObserver with a rootMargin
+(default: 600px). Iframes are considered "visible" when they're within that margin
+of the viewport edges. This is configurable via `visibilityRootMargin`.
+
+## Script Placement
+
+The coordinator should be initialized before or immediately after creating iframes.
+This ensures the parent is listening for `DOENET_REGISTER` messages when child frames load.
+
+## How It Works
+
+1. **Child Registration**: When a child iframe with `data-doenet-enable-parent-coordination="true"` loads, it registers with the parent after `registrationDelayMs` (default: 100ms). Visibility changes are reported separately.
+
+2. **Initial Wait**: The parent waits `initialWaitMs` (default: 300ms) to collect registrations from all iframes. This ensures:
+ - All DOM positions are captured
+ - Selection logic can make informed decisions
+
+3. **Selective Permission**: The parent grants initialization permission to one iframe at a time based on strategy:
+ - **dom-order**: Next iframe in DOM order
+ - **viewport-first**: Visible iframe (by DOM order), or if none visible, next in DOM order
+
+4. **Serialized Rendering**: Each iframe waits for permission before rendering. Only one iframe renders at a time.
+
+5. **Continued Selection**: When an iframe completes, the parent selects and grants permission to the next iframe.
+
+## Configuration Options
+
+```javascript
+// Parent coordinator options
+initializeDoenetParentCoordinator({
+ // Initialization strategy (default: "dom-order")
+ strategy: "dom-order" | "viewport-first",
+
+ // Maximum time to wait for iframe to complete initialization (default: 30000ms)
+ // If exceeded, automatically proceeds to next iframe
+ timeoutMs: 30000,
+
+ // Time to wait for all iframes to register before granting (default: 300ms)
+ // Should be substantially larger (2-3x) than child registrationDelayMs
+ initialWaitMs: 300
+});
+
+// Child registration options (per iframe)
+// The source argument is optional; when omitted/undefined the DoenetML is read
+// from a
+
+
+
+
+
+
+
+
+
+
+
+
+
```
-in your webpage. Then you can call the globally-exported function `renderDoenetToContainer`, which expects
-a `
` element containing a `` as a child.
-
-For example
+### Multiple Documents in Separate Iframes
+**Parent page:**
```html
-
+
+
+
+```
-
+
```
-To pass attributes to the DoenetML react component, you may write them in kebob-case prefixed with `data-doenet`.
-For example,
+## API Reference
+
+### `renderDoenetViewerToContainer(container, doenetMLSource?, options?)`
+
+Renders a DoenetML viewer to a specific container element.
+
+**Parameters:**
+- `container`: DOM element to render into
+- `doenetMLSource`: (optional) DoenetML source code. If omitted, reads from `
+
+
```
+See [COORDINATION.md](./COORDINATION.md) for detailed documentation on cross-iframe coordination.
+
+### Coordination Strategies
+
+These are configured on the parent coordinator via `initializeDoenetParentCoordinator()`:
+
+- **`dom-order`** (default): Initialize iframes in DOM order
+- **`viewport-first`**: Prioritize visible iframes, then initialize remaining in DOM order
+
## Development
Run
@@ -57,6 +124,4 @@ Run
npm run dev
```
-to start a `vite` dev server that serves the test viewer and navigate to the indicated URL. By default
-`index.html` is served. You can instead navigate to `index-inline-worker.html` to view the same page but
-with the inlined version of the DoenetML web worker.
+to start a `vite` dev server that serves the test viewer and navigate to the indicated URL.
diff --git a/packages/standalone/iframe-child.html b/packages/standalone/iframe-child.html
new file mode 100644
index 000000000..cabd6d4d7
--- /dev/null
+++ b/packages/standalone/iframe-child.html
@@ -0,0 +1,36 @@
+
+
+
+
+
+
+ DoenetML Document
+
+
+
+
+ Test Purpose: Verify that DoenetML documents prioritize visible iframes
+ when using the "viewport-first" strategy.
+ Expected Behavior: Scroll down to see out-of-viewport iframes.
+ The visible iframe should initialize first, even if others registered earlier.
+ Open browser console to see initialization sequence.
+