Rasterex API/docs/components/files/page-selection

Page Selection

Navigate to a page from the host UI and listen for the corresponding selection result.

Overview

When a user clicks a page in your own page rail, send selectPage to the canvas. The payload can use either pageIndex or pageNumber, but page index is usually easier because it matches the pageList payload directly.

The canvas responds with selectPageResult, and the host should keep pageList as the source of truth for the final active-page state.

Quick Start

Send selectPage from the page click handler and listen for selectPageResult for confirmation.

Select by page index

viewerWindow.postMessage({
  type: 'selectPage',
  payload: { pageIndex: 2 }
}, '*');

Select by page number

viewerWindow.postMessage({
  type: 'selectPage',
  payload: { pageNumber: 3 }
}, '*');

Listen for selectPageResult

window.addEventListener('message', (event) => {
  if (event.data?.type !== 'selectPageResult') return;

  console.log(event.data.payload);
});

Complete Implementation

This example connects the page list UI to canvas navigation using page indexes.

function selectPage(pageIndex) {
  viewerWindow.postMessage({
    type: 'selectPage',
    payload: { pageIndex }
  }, '*');
}

window.addEventListener('message', (event) => {
  if (event.data?.type !== 'selectPageResult') return;
  console.log('Selection changed:', event.data.payload);
});
Complete Implementation

Complete HTML Example

Use this full standalone HTML document when you want a minimal host page for page selection.

html
<!doctype html>
<html lang="en">
<head>
  <meta charset="UTF-8" />
  <meta name="viewport" content="width=device-width, initial-scale=1.0" />
  <title>PDF Page Selection Demo</title>
  <style>
    body {
      margin: 0;
      font-family: Arial, sans-serif;
      background: #0b1220;
      color: #e5e7eb;
    }
    .app {
      display: grid;
      grid-template-columns: 320px 1fr;
      gap: 12px;
      min-height: 100vh;
      padding: 12px;
    }
    .panel {
      border: 1px solid #2f3b4f;
      border-radius: 12px;
      background: #111827;
      padding: 12px;
      display: grid;
      gap: 10px;
      align-content: start;
    }
    .stack {
      display: grid;
      gap: 8px;
    }
    .row {
      display: flex;
      gap: 8px;
      flex-wrap: wrap;
    }
    input, button, select {
      width: 100%;
      border: 1px solid #2f3b4f;
      border-radius: 8px;
      background: #0f172a;
      color: #e5e7eb;
      padding: 8px 10px;
      font: inherit;
      box-sizing: border-box;
    }
    button {
      width: auto;
      cursor: pointer;
    }
    .pages {
      display: grid;
      gap: 8px;
      max-height: 60vh;
      overflow: auto;
    }
    .page {
      border: 1px solid #2f3b4f;
      border-radius: 10px;
      background: #0d1728;
      padding: 8px;
      display: grid;
      gap: 8px;
    }
    .page.active {
      border-color: #22d3ee;
    }
    iframe {
      width: 100%;
      height: calc(100vh - 24px);
      border: 1px solid #2f3b4f;
      border-radius: 12px;
      background: #04101c;
    }
    img {
      max-width: 100%;
      height: auto;
      display: block;
      background: #fff;
      border-radius: 8px;
    }
    .meta {
      font-size: 12px;
      color: #9ca3af;
    }
  </style>
</head>
<body>
  <div class="app">
    <div class="panel">
      <div class="stack">
      <input id="viewerUrl" value="http://localhost:5173" />
      <input id="fileUrl" placeholder="Public PDF URL" />
      <div class="row">
        <button id="loadViewerBtn">Load Canvas</button>
        <button id="loadPdfBtn">Load PDF</button>
      </div>
      <div id="pages" class="pages"></div>
    </div>
    </div>
    <iframe id="viewerFrame" title="PDF Page Selection Demo Canvas"></iframe>
  </div>
  <script>
const viewerFrame = document.getElementById('viewerFrame');
const viewerUrlInput = document.getElementById('viewerUrl');
const fileUrlInput = document.getElementById('fileUrl');
const pagesEl = document.getElementById('pages');
let latestPageList = null;

function post(type, payload) {
  viewerFrame.contentWindow.postMessage({ type, payload }, '*');
}

function loadViewer() {
  viewerFrame.src = viewerUrlInput.value.trim();
}

function loadPdf() {
  post('view', {
    fileUrl: fileUrlInput.value.trim(),
    displayName: 'Demo User',
    username: 'demo.user',
    email: 'demo@example.com'
  });
}

window.addEventListener('message', (event) => {
  if (event.source !== viewerFrame.contentWindow) return;
  const data = event.data;
  if (!data || typeof data !== 'object') return;
  if (data.type === 'pageList') {
    latestPageList = data.payload;
    renderPages(data.payload.pages);
  }
  onViewerMessage(data);
});

function renderPages(pages) {
  if (!pagesEl) return;
  pagesEl.innerHTML = '';
  pages.forEach((page) => {
    const item = document.createElement('div');
    item.className = page.isSelected ? 'page active' : 'page';
    const actions = pageActions(page);
    item.innerHTML = [
      page.thumbnailDataUrl
        ? '<img src="' + page.thumbnailDataUrl + '" width="' + (page.thumbnailWidth || 120) + '" height="' + (page.thumbnailHeight || 160) + '" />'
        : '<div class="meta">No thumbnail data</div>',
      '<div><strong>' + (page.label || ('Page ' + (page.index + 1))) + '</strong></div>',
      '<div class="meta">' + (page.title || 'Default') + '</div>',
      actions
    ].join('');
    wirePageActions(item, page);
    pagesEl.appendChild(item);
  });
}

document.getElementById('loadViewerBtn').addEventListener('click', loadViewer);
document.getElementById('loadPdfBtn').addEventListener('click', loadPdf);

function pageActions() { return '<button data-action="select">Select</button>'; }
function wirePageActions(item, page) {
  item.querySelector('[data-action="select"]').addEventListener('click', () => {
    post('selectPage', { pageIndex: page.index });
  });
}
function onViewerMessage(data) {
  if (data.type === 'selectPageResult') {
    console.log('selectPageResult', data.payload);
  }
}
  </script>
</body>
</html>
Complete HTML Example

Live Preview

Open the focused demo to click page cards and watch selectPage and selectPageResult live.

File Page Selection Demo

Focused live demo for page selection.

Preview opens in a large modal for zoom-friendly review.