HTML · CSS · JavaScript ready

Build forms in HTML. Style them with CSS. Collect data with JavaScript.

Generate a document from your own web form, or use the isolated JavaScript mode in pasteToPrint for interactive calculations. Review the result, draw on the page, add shapes or images, then print or export PDF.

48 languages Browser-based workflow Human review Print and PDF
Generated document preview safe
FORM / 2026

Equipment inspection

HTML + CSS
Customer North Plant
Device Control panel A-17
Inspection result Passed without defects
Data collected by JavaScript · ready for review 1 / 1

Declared developer environment

Three web layers. One printable result.

Use JavaScript in your host application or in the editor’s isolated JavaScript mode. The editor keeps script source separately and produces a sanitized static document for printing.

HTML

Structure the printable form

Use semantic sections, headings, fields rendered as text, lists, tables, links and safe images to define the document.

CSS

Control the visual layout

Preserve colors, typography, spacing, borders, dimensions, flex, grid and page breaks through safe CSS inlining.

JavaScript

Collect data and calculate results

On your website, validate forms and collect values with FormData. In the editor, use the supported virtual DOM and events for calculations and document updates.

Host application workflow

From live form to reviewed document.

The example below runs on your own website and imports a static summary. Alternatively, import HTML with embedded scripts and explicitly start them in the editor’s JavaScript mode.

  1. 01

    Design the host form

    Create standard inputs, selects and validation rules in your own application.

  2. 02

    Collect and validate

    Validate the form before importing. FormData collects values; it does not perform validation. Validate requests again on your backend.

  3. 03

    Generate HTML and CSS

    Escape user values and map them into a printable semantic document.

  4. 04

    Hand off for review

    Send the summary through the SDK. The user can review, edit, draw, print or export PDF. Optional email scheduling is handled separately by your backend.

Support contract

A clear boundary for every layer.

Distinguish the host website, the isolated JavaScript editor and the static print output. Each environment supports different capabilities.

Layer Supported features Document behavior
HTML Text, sections, lists, tables and safe images; supported inputs, selects, textareas and buttons in the interactive JavaScript preview. Unsupported elements are removed. In the static output, form values become text or checkbox symbols and buttons are removed.
CSS Safe selectors, colors, fonts, alignment, spacing, borders, sizing, flex, grid and page breaks. Rules are converted to inline styles so they survive editing, printing and PDF output.
JS Host website: browser APIs such as FormData. Editor: a virtual DOM, calculations and supported input, change, click, keydown, keyup, focus, blur and submit events.
FormData · DOM · input · change · click · keydown · keyup · focus · blur · submit
Embedded classic scripts and selected inline event handlers are imported into separate script source. They run only after the user presses Run; printed pages and PDF contain the static result.
EMAIL The host example lets the user request delayed email delivery of the original generated summary. You must implement the scheduling endpoint and server queue in your own backend. The SDK does not send email; later editor changes are not included in this example’s email.

Host example with optional backend integration

Validate, escape, generate, import.

Run this example on your own website. It imports a static summary through the SDK. Email scheduling requires your own authenticated endpoint and queue; it sends the original summary after import is accepted, without waiting for subsequent editor changes.

HTML + CSS + JavaScript inspection-form.html
<form id="inspectionForm">
  <label>
    Customer
    <input name="customer" required>
  </label>
  <label>
    Device
    <input name="device" required>
  </label>
  <label>
    Result
    <select name="result" required>
      <option value="Passed">Passed</option>
      <option value="Defect found">Defect found</option>
    </select>
  </label>
  <label>
    <input type="checkbox" name="emailEnabled" value="yes">
    Send the result to my email
  </label>
  <label>
    Email
    <input name="email" type="email" autocomplete="email">
  </label>
  <label>
    Send after (minutes)
    <input name="delayMinutes" type="number"
      min="0" max="10080" value="60">
  </label>
  <button type="submit" data-pastetoprint-button>
    Create printable report
  </button>
</form>
<p id="formStatus" role="status" aria-live="polite"></p>

<script src="https://www.pastetoprint.com/assets/js/import-button.js?v=1.5.0"></script>
<script>
const escapeHtml = (value) => String(value).replace(
  /[&<>"']/g,
  (character) => ({
    '&': '&amp;',
    '<': '&lt;',
    '>': '&gt;',
    '"': '&quot;',
    "'": '&#39;'
  })[character]
);

const form = document.getElementById('inspectionForm');
const status = document.getElementById('formStatus');
const submitButton = form.querySelector('button[type="submit"]');
const emailEnabled = form.elements.namedItem('emailEnabled');
const emailField = form.elements.namedItem('email');
const delayField = form.elements.namedItem('delayMinutes');

function syncEmailFields() {
  for (const field of [emailField, delayField]) {
    field.disabled = !emailEnabled.checked;
    field.required = emailEnabled.checked;
  }
}
emailEnabled.addEventListener('change', syncEmailFields);
syncEmailFields();

form.addEventListener('submit', async (event) => {
    event.preventDefault();
    if (submitButton.disabled || !form.reportValidity()) return;
    status.textContent = '';
    submitButton.disabled = true;
    let importAccepted = false;

    try {

      // Names are unique here. Use FormData.getAll(name) for repeated fields.
      // Disabled fields and unchecked checkboxes are omitted by FormData.
      const data = Object.fromEntries(new FormData(event.currentTarget));

      const html = `
        <article class="report">
          <header>
            <span>INSPECTION REPORT</span>
            <h1>${escapeHtml(data.device)}</h1>
          </header>
          <section class="details">
            <p><small>Customer</small>
              <strong>${escapeHtml(data.customer)}</strong></p>
            <p><small>Result</small>
              <strong>${escapeHtml(data.result)}</strong></p>
          </section>
        </article>`;

      const css = `
        .report {
          padding: 18mm;
          border: 1px solid #cbd5e1;
          font-family: Arial;
        }
        .report header {
          padding: 18px;
          background: #173f8a;
          color: #ffffff;
        }
        .details {
          display: grid;
          grid-template-columns: repeat(2, minmax(0, 1fr));
          gap: 12px;
          margin-top: 18px;
        }
        .details p {
          padding: 12px;
          border: 1px solid #cbd5e1;
        }
        .details small,
        .details strong {
          display: block;
        }`;

      const title = `Inspection – ${data.device}`;

      await PasteToPrint.import({
        title,
        mode: 'replace',
        items: [{ kind: 'html', html, css }]
      });

      importAccepted = true;

      if (data.emailEnabled === 'yes') {
        const delayMinutes = Math.min(
          10080,
          Math.max(0, Number(data.delayMinutes) || 0)
        );
        const sendAt = new Date(
          Date.now() + delayMinutes * 60_000
        ).toISOString();

        // Implement this authenticated endpoint in your host backend.
        // Validate the recipient, delay and content again on the server.
        // Add a persistent queue to send even after the tab is closed.
        // This sends the ORIGINAL summary, not later changes in the editor.
        // Import acceptance does not mean editing or printing is complete.
        const response = await fetch('/api/form-deliveries', {
          method: 'POST',
          headers: { 'Content-Type': 'application/json' },
          body: JSON.stringify({
            recipient: data.email,
            sendAt,
            formData: {
              customer: data.customer,
              device: data.device,
              result: data.result
            },
            document: { title, html, css }
          })
        });

        if (!response.ok) {
          throw new Error('Email delivery could not be scheduled.');
        }
      }
      status.textContent = data.emailEnabled === 'yes'
        ? 'Report imported and original summary scheduled for email.'
        : 'Report imported. Continue reviewing it in pasteToPrint.';
    } catch (error) {
      status.textContent = (importAccepted
        ? 'Report imported, but email scheduling failed: '
        : 'Import failed: ') + error.message;
    } finally {
      submitButton.disabled = false;
    }
});
</script>

Repair and security

Tolerant input. Strict document boundary.

Common authoring mistakes are repaired where possible. Script execution requires an explicit user action in the isolated JavaScript mode; the print output is sanitized separately.

Automatic recovery

The browser repairs missing closing HTML tags and tolerates a missing final CSS semicolon or brace. Unreadable declarations are discarded individually.

Separate script source and static output

Classic embedded scripts are stored separately, and supported inline handlers become event listeners. External scripts, module scripts and unsupported handlers are skipped. The static print output excludes executable code; unsafe embeds and CSS are filtered.

Review before output

Send only data needed for the result. Obtain consent, verify the recipient and let the user cancel or reschedule a pending email.

Choose the smallest safe handoff

Use browser IMPORT for user-triggered HTML/CSS. Use PTDF Public Sessions or Document API v2 when the backend already has structured document data.

Developer-ready

Turn your next web form into a printable workflow.

Use JavaScript on your website or in the isolated editor, review the static HTML/CSS result and print or export PDF. Implement any scheduled email delivery in your own backend.