Developer documentation

Embed the UVa problem picker

Add a temporary, multi-select UVa problem picker to another application. The hosted picker uses https://uvaexplorer.algojudge.app/picker/ by default and returns the confirmed selection through a versioned postMessage protocol.

Recommended

React component

Install the typed wrapper:

npm install @algojudge/uva-explorer-react

The src property is optional. Omit it to use the hosted UVa Explorer automatically. Exchange the long-lived key on your server through POST /api/access/token, then pass only the returned one-hour token to React.

import { UvaProblemPicker } from "@algojudge/uva-explorer-react";

export function ProblemField() {
  return (
    <UvaProblemPicker
      language="en"
      problemNumbers={[100, 101]}
      accessToken={accessTokenFromYourServer}
      options={{ hideLangPicker: true, showAiPanel: true, showFilters: true, filtersMode: "summary" }}
      onConfirm={({ problemNumbers, problems }) => {
        console.log(problemNumbers, problems);
      }}
      style={{ width: "100%", height: 720, border: 0 }}
    />
  );
}
<UvaProblemPicker
  accessToken={shortLivedAccessToken}
  onConfirm={({ problemNumbers }) => console.log(problemNumbers)}
/>

Set src only when using a self-hosted Explorer. The component transfers accessToken in the iframe fragment; UVa Explorer consumes and removes it immediately. Never expose the long-lived access key to browser code.

No framework

iframe and postMessage

Validate both the Explorer origin and the iframe window before accepting messages.

<iframe id="uva-picker"
  src="https://uvaexplorer.algojudge.app/picker/">
</iframe>

<script>
const pickerUrl = "https://uvaexplorer.algojudge.app/picker/";
const accessToken = undefined; // Fetch this from your application server.
const pickerSrc = accessToken
  ? `${pickerUrl}#token=${encodeURIComponent(accessToken)}`
  : pickerUrl;
const pickerOrigin = new URL(pickerUrl).origin;
const picker = document.querySelector("#uva-picker");
picker.src = pickerSrc;

window.addEventListener("message", (event) => {
  if (event.origin !== pickerOrigin ||
      event.source !== picker.contentWindow) return;

  if (event.data?.type === "uva-explorer:ready") {
    picker.contentWindow.postMessage({
      type: "uva-explorer:init",
      version: 1,
      requestId: "contest-problems",
      language: "en",
      problemNumbers: [100, 101],
      options: { hideLangPicker: true, showAiPanel: true, showFilters: true, filtersMode: "summary" }
    }, pickerOrigin);
  }

  if (event.data?.type === "uva-explorer:confirm") {
    console.log(event.data.problemNumbers, event.data.problems);
  }
});
</script>

Your Content Security Policy must allow https://uvaexplorer.algojudge.app in frame-src.

Live example

Hosted picker

Connecting to the picker…