make_post_sell/docs/JAVASCRIPT.md
russell@unturf.com 32a19a339c docs: add MPS-6 through MPS-9 tickets, architecture diagram, update JS docs
- MPS-6: referrer analytics (domain, query, trend line charts)
- MPS-7: sandbox mode creative filter system
- MPS-8: user S3 bucket + artifact storage
- MPS-9: shop S3 mirror bucket
- architecture.md: system diagram, request flow, data pipeline, S3 layout
- JAVASCRIPT.md: add sandbox.js, signals.js, MediaPipe SDK entries
- sandbox-mode.md: mark S3 upload as implemented
- mps-2.md: document referrer_domain + referrer_query columns

Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
2026-03-05 06:19:56 -05:00

177 lines
6.4 KiB
Markdown

# 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