# JavaScript Usage

This project minimizes JavaScript usage, preferring pure CSS solutions where possible (e.g., `<details>` elements for toggles). JavaScript is used only where necessary for payment integrations, real-time updates, and progressive enhancement.

## Philosophy

- Prefer pure HTML/CSS over JavaScript
- Use `<details>` elements for toggles instead of JS
- External SDKs loaded only when payment method is enabled
- No build step - vanilla JS only
- No jQuery - all vanilla JavaScript

## Static JavaScript Files

Located in `make_post_sell/static/js/`:

### qrcode.min.js
- QRious library for QR code generation
- Used by: Crypto checkout page
- Generates payment QR codes for XMR/DOGE addresses

### custom.js
- Markdown preview functionality
- Functions: `previewAjax()`, `sendPreview()`
- Uses fetch API for AJAX calls to `/markup-editor-preview`

### watch.js
- Watch mode continuous playback engine
- Used by: `product.j2` when shop has `watch_mode_enabled`
- Discovery ring with deterministic content traversal per shop
- Crossfade transitions between media (3s, 60 steps)
- Countdown overlay (7s) between items
- Queue management: add, remove, reorder
- Two-phase preload: JSON metadata fetch, then media buffering 30s before end
- Recently-played filtering via localStorage (4-hour expiry)
- Handles video, audio, and static content (PDFs, images)
- Autoplay toggle persisted in localStorage
- Ring state (position, direction, history) persisted in localStorage

### sandbox.js
- Client-side creative filter engine (IIFE, ~700 lines)
- Used by: `base.j2` when shop has `sandbox_mode` enabled
- 32 CSS filter presets across 7 categories (basic, warm, cool, dramatic, color, Instagram-style, SVG)
- 7 adjustment sliders (brightness, contrast, saturation, hue, blur, sepia, grayscale)
- Image export via canvas `toBlob()` (PNG)
- Video export via `MediaRecorder` + `captureStream(30fps)` (WebM)
- On-demand face detection via MediaPipe Face Mesh (468 landmarks, eye glow, face mask overlays)
- Upload-to-bucket: presigned POST to user's S3 bucket via `/u/sandbox/upload`
- localStorage persistence: preset, slider values, panel state, filter mode
- Exposes `window.sandboxReapply()` for watch.js SPA integration

### signals.js
- Anonymous page visit signal collector
- Used by: all product/content pages
- Collects presence (wall_clock, visible, active), scroll (depth, direction changes), and media playback signals
- Sends single JSON beacon (~300 bytes) via `navigator.sendBeacon()` on page unload
- No cookies, no IPs, no fingerprints — purely behavioral signals
- Viewport width sent for device class derivation (server-side)

### comments.js
- AJAX comment submission (progressive enhancement)
- Intercepts comment form POST, submits via `fetch()` with `X-Requested-With: XMLHttpRequest`
- Server returns JSON (HTTP 201) for AJAX requests
- Inserts new comment into DOM without page reload (preserves media playback)
- Falls back to normal POST + redirect without JS or on error

### player.js
- Pop-out media player with draggable window
- Prev/next navigation and keyboard shortcuts
- Auto-advance for images/PDFs (60s timer)
- Preloads adjacent media for instant switching
- Used by: `/random` and `/tv` endpoints

## Inline JavaScript by Template

### base.j2
**Purpose:** Theme switching (dark/light mode)

- Runs immediately in `<head>` to prevent flash of wrong theme
- Priority: localStorage > user preference > shop default
- Exposes `window.setTheme()` for programmatic use

### shop_settings.j2
**Purpose:** Settings page interactions

- Crypto wallets toggle (checkbox + localStorage)
- Theme preview for shop default theme radio buttons
- Note: Payment provider toggles use pure CSS `<details>` elements

### user_settings.j2
**Purpose:** User theme preference sync

- Syncs theme radio buttons with localStorage
- Updates localStorage on form submit

### cart_checkout.j2
**Purpose:** Payment processing

1. **PayPal SDK** (`paypal.Buttons()`)
   - Loads PayPal SDK from `paypal.com`
   - Creates orders via `POST /paypal/create-order`
   - Handles approval flow and form submission
   - Double-click protection flags

2. **Cancel Crypto Quote** (`cancelQuote()`)
   - Cancels pending crypto payment quotes
   - Uses fetch API with CSRF token

### crypto_checkout.j2
**Purpose:** Crypto payment monitoring

- QR code generation using QRious library
- Countdown timer for quote expiry
- Status polling via fetch API
- Copy-to-clipboard for address/amount
- Dynamic UI updates based on payment status
- Functions: `disableQuoteButtons()`, `removePaymentElements()`, `replaceButtonsWithInvoiceLink()`

### snippets/stripe.j2
**Purpose:** Stripe card form (macro `new_card()`)

- Loads Stripe.js SDK
- Creates Payment Element for card input
- Handles `stripe.confirmSetup()` flow
- Uses vanilla JS with `DOMContentLoaded`

### snippets/analytics.j2
**Purpose:** Analytics tracking (optional)

- Plausible Analytics (privacy-focused)
- Google Analytics (gtag.js)
- Only loaded if shop has configured analytics

### product.j2
**Purpose:** Inline video playback

- `playInline()` replaces thumbnail container with `<video>` element on click
- Used for preview playback on product pages without watch mode
- Loads `watch.js` when shop has `watch_mode_enabled`

### snippets/comments.j2
**Purpose:** Comment form

- Loads `comments.js` async for AJAX submission
- Uses `js-only` class pattern for elements requiring JS

### snippets/optional-javascript.j2
**Purpose:** Optional JS loading

- Loads custom.js async
- Used for markdown preview functionality

## External SDKs

| SDK | URL | Used For |
|-----|-----|----------|
| PayPal | `paypal.com/sdk/js` | PayPal button/checkout |
| Stripe | `js.stripe.com/v3/` | Card payment form |
| Plausible | Shop-configured domain | Privacy analytics |
| Google Analytics | `googletagmanager.com` | Google analytics |
| MediaPipe | `cdn.jsdelivr.net` | Face detection (sandbox mode, on-demand) |

## CSRF Protection

All fetch/AJAX calls include CSRF tokens:
- Header: `X-CSRF-Token`
- Value from: `{{ request.session.get_csrf_token() }}` or hidden input

## Progressive Enhancement

Pages work without JavaScript where possible:
- Payment provider toggles use `<details>` (pure CSS)
- Forms submit normally without JS
- JS enhances UX (copy buttons, QR codes, live previews)
- Comment forms POST normally without JS; AJAX submission preserves playback with JS
- Watch mode elements use `js-only` class (hidden via `<noscript>` stylesheet)
- Video thumbnails link directly to media without JS; inline playback with JS
