') + ')', 'gi'); if (regex.test(text)) { found = true; var frag = document.createDocumentFragment(); var parts = text.split(regex); parts.forEach(function(part, i) { if (i % 2 === 0) { frag.appendChild(document.createTextNode(part)); } else { var span = document.createElement('span'); span.className = 'userscript-highlight'; span.textContent = part; frag.appendChild(span); } }); node.parentNode.replaceChild(frag, node); } }); } else if (node.nodeType === 1 && node.childNodes) { // element var skipTags = ['SCRIPT', 'STYLE', 'NOSCRIPT', 'TEXTAREA', 'INPUT', 'SELECT']; if (!skipTags.includes(node.tagName)) { Array.from(node.childNodes).forEach(highlight); } } } highlight(document.body); // Re-highlight on dynamic content var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1 || node.nodeType === 3) highlight(node); }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Highlight Search Terms]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Strip utm_, fbclid, gclid, etc. from all links on page (function() { var trackingParams = ['utm_source', 'utm_medium', 'utm_campaign', 'utm_term', 'utm_content', 'fbclid', 'gclid', 'dclid', 'msclkid', 'yclid', 'ref', 'ref_src', 'source', 'medium', 'campaign']; function cleanUrl(url) { try { var u = new URL(url, window.location.origin); var changed = false; trackingParams.forEach(function(p) { if (u.searchParams.has(p)) { u.searchParams.delete(p); changed = true; } }); return changed ? u.toString() : url; } catch (e) { return url; } } function cleanLinks() { document.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } cleanLinks(); var observer = new MutationObserver(function(mutations) { mutations.forEach(function(m) { m.addedNodes.forEach(function(node) { if (node.nodeType === 1) { if (node.tagName === 'A') cleanLinks(); node.querySelectorAll('a[href]').forEach(function(a) { var clean = cleanUrl(a.href); if (clean !== a.href) a.href = clean; }); } }); }); }); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:Remove Tracking Parameters from Links]', __e); } })(); (function(){ try { var __m = "youtube.com"; var __re = new RegExp('^' + "youtube\\.com" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Auto-enable theater mode on YouTube (function() { function tryTheater() { var btn = document.querySelector('button[aria-label="Theater mode"], ytd-player #player button[title="Theater mode"]'); if (btn && !btn.classList.contains('activated')) { btn.click(); } } // Try immediately tryTheater(); // Try after navigation (SPA) var lastUrl = location.href; setInterval(function() { if (location.href !== lastUrl) { lastUrl = location.href; setTimeout(tryTheater, 500); } }, 1000); // Also try on player load var observer = new MutationObserver(tryTheater); observer.observe(document.body, { childList: true, subtree: true }); })(); } } catch(__e) { console.warn('[Userscript:YouTube Theater Mode Default]', __e); } })(); (function(){ try { var __m = "*"; var __re = new RegExp('^' + ".*" + ', 'i'); if (__m === '*' || __re.test(location.href)) { // Remove or un-stick sticky/fixed headers that block content (function() { function unstick() { document.querySelectorAll('header, nav, [role="banner"], .header, .navbar, .sticky, .fixed-top, [style*="position: fixed"], [style*="position:sticky"]').forEach(function(el) { if (el.style.position === 'fixed' || el.style.position === 'sticky' || getComputedStyle(el).position === 'fixed' || getComputedStyle(el).position === 'sticky') { el.style.position = 'static'; el.style.top = 'auto'; el.style.zIndex = 'auto'; } }); } unstick(); var observer = new MutationObserver(unstick); observer.observe(document.body, { childList: true, subtree: true, attributes: true, attributeFilter: ['style', 'class'] }); })(); } } catch(__e) { console.warn('[Userscript:Kill Sticky Headers]', __e); } })(); })(); GitHub - wolffe/fx-forms: A small contact-form plugin for ClassicPress. Build forms in the admin, drop them anywhere with a shortcode, and get notified by email. · GitHub
Skip to content

Latest commit

History

5 Commits

Folders and files

NameName
Last commit message
Last commit date

Repository files navigation

=== FX Forms ===
Contributors: butterflymedia
Tags: forms, contact form, classicpress
Requires at least: 5.3
Tested up to: 6.8
Requires PHP: 8.1
Stable tag: 2.1.0
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html
A small contact-form plugin for ClassicPress. Build forms in the admin, drop them anywhere with a shortcode, and get notified by email.
== Description ==
FX Forms is a minimal, no-frills form plugin built for ClassicPress (works on WordPress too). It does one thing well: lets you define forms in the admin and embed them in pages or posts. When a visitor submits, you get an email — no submissions are stored in the database.
* Custom post type "Forms" for managing form definitions
* Field types: text, full name, email, phone, number, URL, date, time, textarea, select, checkbox
* Full / half width fields, side-by-side via CSS Grid
* Per-field help text shown under each input
* Drag-and-drop field ordering (uses ClassicPress 2.7+ native SortableJS)
* Generic fields — pick any type and give it your own label
* Embed with `[fxform id=N]` shortcode
* Sends email on submit, supports multiple recipients (comma- or semicolon-separated)
* Sets `Reply-To` automatically when an email field is present
* Honeypot anti-spam field built in
* No submissions stored in the database
* No jQuery, no React, no build step — vanilla JS only
== Installation ==
1. Upload the plugin folder to `/wp-content/plugins/`.
2. Activate it in the Plugins menu.
3. Go to **FX Forms → Add New** and build your form.
4. Copy the shortcode shown above the title and paste it into any page or post.
== Frequently Asked Questions ==
= How do I embed a form? =
Each form has a shortcode shown at the top of the editor — `[fxform id=42]`. Paste it into any page or post.
= Where do submissions go? =
Straight to your email. Nothing is stored on the site.
= Can I send to multiple recipients? =
Yes — in the form's "Send to" field, separate addresses with commas or semicolons.
= Can replies go to the visitor? =
If your form has a field of type "Email" and the visitor fills it in, that address is automatically set as the `Reply-To` header on the notification email.
= What email placeholders are available? =
`{form_title}`, `{form_id}`, `{data}` (all fields), and any individual field id like `{email}` or `{message}`. For "Full Name" fields, `{your_name}` produces "First Last", and `{your_name_first}` / `{your_name_last}` work too.
== Changelog ==
= 2.1.0 =
* New: Global Settings page (FX Forms → Settings) — choose the sending method and configure the email log.
* New: SMTP2Go mailer — enter your API key and select SMTP2Go as the mailer to send via the SMTP2Go REST API instead of wp_mail. More mailer options can be added later.
* New: Email log — optionally store a copy of every sent email in a dedicated database table; configurable maximum entry count (default 1000); entries are pruned automatically; viewable and clearable from FX Forms → Email Log.
* New: Per-form CAPTCHA — enable a text verification code on any form to deter spam; stateless (no PHP sessions), challenge stored in a short-lived transient.
= 2.0.0 =
* Initial release as FX Forms.
* Procedural PHP 8.1+, vanilla JS, no jQuery, no React, no build step.
* Generic field builder: pick a type, give it your label.
* Field types include a composite "Full Name" (First / Last sub-inputs).
* Full / half width fields via CSS Grid.
* Per-field help text shown under each input.
* No submissions are stored — emailed only.
* Server-rendered shortcode, classic POST/redirect submit flow (no REST).
* Multiple notification recipients.
* Automatic Reply-To from a submitted email field.
* Built-in honeypot.

About

A small contact-form plugin for ClassicPress. Build forms in the admin, drop them anywhere with a shortcode, and get notified by email.

Topics

Resources

Stars

1 star

Watchers

0 watching

Forks

Releases

Used by

Contributors

Languages