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. Private access uses the separate, optional accessKey property.

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

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

Set src only when using a self-hosted Explorer. The component transfers accessKey in the iframe fragment; UVa Explorer consumes and removes it immediately.

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 accessKey = undefined; // Optional private dataset key.
const pickerSrc = accessKey
  ? `${pickerUrl}#key=${encodeURIComponent(accessKey)}`
  : 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 }
    }, 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…