=== Ajebang Form and Survey Builder ===
Contributors: ajebang
Tags: form, survey, poll, form builder, shortcode
Requires at least: 5.8
Tested up to: 7.0
Requires PHP: 7.4
Stable tag: 1.9.1
License: GPLv2 or later
License URI: https://www.gnu.org/licenses/gpl-2.0.html
Author URI: https://ajebang.com

Build forms and surveys with a drag-and-drop builder, show aggregated results, set deadlines, and place them anywhere with shortcodes.

== Description ==

Ajebang Form and Survey Builder is a lightweight form and survey builder. You create a form in the admin
area by dragging fields into place, then publish it with a shortcode or share the
standalone link the plugin generates for it. Visitors can respond without logging
in or creating an account.

Every form is one of two types:

* **Form** — collects responses. Administrators see the number of submissions but
  not the content of individual answers.
* **Survey** — collects responses and shows aggregated statistics: the count and
  percentage for each choice, averages for number fields, and so on. Visitors see
  the results after they respond.

= Features =

* Drag-and-drop builder with eight field types: text, textarea, email, number,
  dropdown, radio, checkbox and date
* Draft and published states. A new form starts as a draft, so nothing appears on
  your site until you are ready
* Response deadline. Forms accept answers indefinitely by default. After the
  deadline the server refuses new submissions and shows a closing notice; surveys
  can keep displaying their results
* Featured image, shown above the form and as the thumbnail in listings
* Related links, listed underneath the form
* Standalone page for every form at an address such as `/aj-form/survey/12/`, so
  you can share a link without embedding a shortcode anywhere
* Repeat-response limiting per form, by browser cookie or by cookie and IP address
* Submission modes: a submit button, automatic submission once every field is
  filled, or per-question submission where answering one question immediately
  turns that question into its result
* Works without JavaScript. Submissions use AJAX when they can and fall back to a
  normal form post when they cannot
* Translation ready. Every string is internationalised, so translations arrive
  through translate.wordpress.org in any language the community contributes

= Shortcodes =

Place a form in a post or page:

`[aj_form id="123"]`

Turn individual parts on or off:

`[aj_form id="123" title="0" image="0" description="0" deadline="0" links="0"]`

Choose the heading level for the form title. The default is `h2`, which sits above
the `h3` used for question titles:

`[aj_form id="123" title_tag="h1"]`

Output a single question, counting from 1. This is useful when you want to spread
the questions of one form across a longer article:

`[aj_form id="123" sno="2"]`

The display defaults depend on `sno`. Without it you get everything: title, image,
description, deadline notice and related links. With it you get the question on its
own, because repeating the title and the deadline next to every question would be
noise. Writing an attribute yourself always wins over either default.

List your published surveys as cards, each linking to its standalone page:

`[aj_form_list]`

`[aj_form_list]` accepts `type="survey|form|all"`, `ids="3,5"`, `limit="10"`,
`orderby="date|title|deadline"`, `order="desc|asc"`, `excerpt="1"`, `words="25"`,
`count="1"`, `deadline="1"`, `status="1"` and `image="1"`.

The Shortcodes tab under Ajebang Forms → Settings documents every attribute, with copy
ready examples for the forms on your own site.

= Permissions =

Creating forms and viewing statistics requires the `manage_options` capability, so
only administrators can do it. Submitting a response requires nothing at all —
anonymous visitors can take part.

= Data storage =

Responses are not stored as posts. The plugin creates two of its own tables:

* `{prefix}aj_form_forms` — form definitions
* `{prefix}aj_form_submissions` — submitted responses

Deactivating or deleting the plugin leaves both tables in place, so your responses
survive an uninstall.

= A note on repeat responses =

Because the plugin accepts anonymous submissions, repeat responses cannot be
blocked completely. Cookies can be cleared or sidestepped with a private window,
and IP addresses are shared in offices and on mobile networks, where blocking by IP
would turn away genuine participants. Treat the setting as protection against
accidental double submissions and page reloads rather than as a guarantee.

== Installation ==

1. Upload the plugin through Plugins → Add New → Upload Plugin, or copy the
   `ajebang-form-survey-builder` folder into `wp-content/plugins/`.
2. Activate it. The plugin creates its two database tables on activation.
3. Go to Ajebang Forms → Add New to build your first form.
4. Copy the shortcode from the form list, or share the standalone link shown on the
   edit screen.

== Frequently Asked Questions ==

= Do visitors need an account to respond? =

No. Anyone can submit a response without logging in. Only administrators can create
forms and read the statistics.

= What happens to my responses if I delete the plugin? =

They stay. The plugin has no uninstall routine and never drops its tables, so
reinstalling brings your forms and responses back exactly as they were.

= The standalone links return "page not found". =

Visit Settings → Permalinks once to let WordPress rebuild its rewrite rules. If
your site uses the plain permalink structure, the plugin falls back to addresses
in the form `?aj_form_view=12` instead.

= Can I show only one question of a form? =

Yes, with the `sno` attribute: `[aj_form id="1" sno="2"]` renders the second
question by itself. Validation, submission and results are all scoped to that
question, and the answers are still recorded against the original form.

= I use a full page cache. Does that cause problems? =

The plugin is built for it. Anonymous submissions do not rely on a nonce, because a
cached page eventually serves an expired one and would lock every visitor out. After
the page loads, the plugin fetches the real participation state and corrects the
screen, so a cached "not yet answered" view does not let someone respond twice.

= Where do I report a problem? =

Email ajebang@ajebang.com or visit https://ajebang.com.

== Changelog ==

= 1.9.1 =
* The virtual post cached for a shortcut page is now removed from the post cache
  when the request ends, so nothing the plugin writes outlives the request on
  sites running a persistent object cache.

= 1.9.0 =
* Renamed the plugin to "Ajebang Form and Survey Builder". The former name combined
  a two-letter initialism with a generic term and was not distinctive enough for the
  plugin directory. The text domain, the plugin folder and the main file follow the
  new slug, `ajebang-form-survey-builder`.
* The form builder's initial data is attached with `wp_add_inline_script()` instead
  of a `<script>` tag written into the page.
* The `the_title` filter callback escapes the title it returns. A filter callback's
  return value is output by WordPress without any escaping of its own.
* Dropped `load_plugin_textdomain()` and the bundled `.po`/`.mo` files. Translations
  for a plugin hosted on wordpress.org come from translate.wordpress.org through the
  standard update system, so neither is needed.

= 1.8.8 =
* Removed the `Plugin URI` header. It pointed at the same address as `Author URI`,
  which wordpress.org rejects on upload — the two describe different things and
  neither is required. `Author URI` is the accurate one here; wordpress.org
  provides the plugin's own page.

= 1.8.7 =
* The current URL is now derived from a sanitised `REQUEST_URI`. It is passed
  through `esc_url_raw()` rather than `sanitize_text_field()`, which strips `%xx`
  sequences and would mangle any address containing non-ASCII characters.
* Documented the deliberate deviations that Plugin Check reports, as `phpcs:ignore`
  comments with their reasons: anonymous submissions do not carry a nonce, input is
  sanitised after decoding rather than before, and the custom tables are reached
  with direct `$wpdb` calls. No change in behaviour — 100 warnings down to 1.

= 1.8.6 =
* Fixed choice display counts not saving. On any form where a count had never been
  set, the builder was not sending the changed values at all, so the screen said
  "Form saved" while the numbers stayed the same. The empty count list arrived as a
  JSON array rather than an object, and the values keyed by choice name were dropped
  during serialisation. Existing forms work from this version on, with no migration.
* Plugin Check fixes: the number in the "N responses deleted" notice is now escaped
  at the point of output, and a `translators:` comment was moved onto the line
  directly above its gettext call. No change in behaviour.
* The readme and the plugin header description are now in English.

= 1.8.5 =
* Reversed the display defaults for `sno`. `[aj_form id="1" sno="1"]` now renders the
  question on its own, without the title, featured image, description, deadline
  notice or related links. The attribute exists to drop a question into the middle of
  an article, where repeating all of that was in the way. A whole form, with no `sno`,
  still shows everything as before.
* Added the `deadline` attribute, which turns the "you can respond until…" notice on
  and off. The notice on a closed form always appears, since it explains why there is
  no form to fill in.
* Writing an attribute yourself beats either default, for example
  `[aj_form id="1" sno="1" deadline="1"]`.

= 1.8.4 =
* Added a Shortcodes tab to the settings screen. It lists every attribute of both
  shortcodes with its values, default and description, adds examples for common
  situations, and notes which options belong to the form rather than the shortcode.
  At the bottom it lists the forms on your site with copy ready shortcodes and links.

= 1.8.3 =
* The standalone page now hands its featured image to the theme, supplying it as the
  WordPress featured image, so the theme draws its usual header banner instead of
  leaving the image stranded below the content.
* Settings → General → standalone page → featured image is now a choice of three:
  leave it to the theme (default), print it in the content, or hide it. Values saved
  in 1.8.2 carry over to the first and third options respectively.

= 1.8.2 =
* Fixed the empty title area on standalone pages. Themes render an
  `<h1 class="entry-title">` slot, which stayed blank because the post is virtual.
  The plugin now fills that slot through the `the_title` filter, leaving other titles
  on the page, such as navigation items, untouched.
* Printing the title inside the content is now off by default, since the fix above
  fills the theme's own title area and leaving both on shows the title twice. The
  option remains under Settings → General for themes with no title area at all.
* Added a setting for whether the standalone page shows the featured image. Listings
  keep using it as a thumbnail either way.

= 1.8.1 =
* Fixed the missing form title on standalone pages. The shortcode suppressed the
  title on the assumption that the theme would draw it, which left a page with no
  title on themes that do not. The title is now printed as an `h1` by default and can
  be turned off under Settings → General.
* Added featured images. Pick one from the media library per form and it appears
  above the form and as the thumbnail in listings. Turn it off with `image="0"`.
* Question titles are now `<h3>` elements rather than labels, which were not headings
  as far as document structure was concerned. The hierarchy runs form title (`h2`, or
  `h1` on a standalone page) then question title (`h3`), and result cards match. The
  wrapper changed from `<p>` to `<div>`, because a paragraph cannot contain a heading
  and browsers break the markup apart.
* Fixed choice labels rendering in bold. A `font-weight` rule meant for field titles
  was catching them too.
* Accessibility: single inputs are tied to their control with `label for`, and radio
  and checkbox groups are tied to their question title with `role="group"` and
  `aria-labelledby`.

= 1.8.0 =
* Added the `[aj_form_list]` shortcode, which shows published surveys as cards with
  the title, an excerpt, the response count, the deadline and an open or closed badge.
  Open surveys sort above closed ones and each card links to its standalone page.
* Added display attributes `title`, `description` and `links` to `[aj_form]`. All
  default to on. Titles are printed by default from this version, so add `title="0"`
  if your post already has one.
* Added the `sno` attribute for rendering a single question. Validation, submission
  and results are scoped to that question; everything else behaves as before.
* Added related links, a per-form list shown underneath the form.
* Added a response deadline. Forms run indefinitely by default. After the deadline the
  server refuses submissions and shows a notice, and surveys can go on showing their
  results.
* Added drafts. A draft form renders nothing, stays out of listings, and returns 404
  on its standalone link; administrators see it with a notice. New forms start as
  drafts. Existing forms all stay published.
* Added standalone links. Every form has its own page at `/aj-form/{type}/{id}/`. The
  base is configurable, and sites using plain permalinks fall back to
  `?aj_form_view=12`.
* Added a Korean translation.
* No database schema change. The new options all live in the existing settings column.

= 1.7.4 =
* Fixed the mangled plugin description in the plugins list, caused by the Korean text
  in the plugin file and readme having been saved in the wrong encoding.
* Removed a UTF-8 byte order mark from the head of the plugin file. Those three bytes
  were sent before any header, which could make `setcookie()` and `wp_safe_redirect()`
  fail with "headers already sent".

= 1.7.3 =
* Fixed "This form has expired. Please reload the page and try again." blocking every
  submission. The nonce baked into a cached page expires after 24 hours while the page
  cache lives longer, so all visitors were posting a dead nonce. Logged out visitors
  are no longer asked for one, since without a session it carries no CSRF protection
  anyway, and the nonce for logged in users is refreshed as the page loads.

= 1.7.2 =
* Fixed nobody being able to take part on a cached page. Once a participant's screen
  was cached, every later visitor received the results view with no form. The state
  correction now works in both directions and can bring the form back.

= 1.7.1 =
* Dark theme support. Hard-coded light colours on the front end — bar backgrounds,
  inputs, choice boxes, notices — were replaced with neutral values that follow the
  theme, fixing bar backgrounds that glowed white on dark themes.

= 1.7.0 =
* Page cache support. A full page cache could serve the "not yet answered" screen and
  allow a repeat response. The plugin now fetches the real state after the page loads,
  corrects the screen, and refreshes an expired nonce at the same time.
* Repeat limiting by IP is stronger: a previous response is found by IP even when the
  cookie is gone.
* Added an option for showing the response count per question.
* Added survey defaults to the global settings, so new forms start with the options
  you prefer.
* Split the settings and form edit screens into tabs.

= 1.6.0 =
* Improved the survey results layout. Each question is a card with its response count
  beside the title, which fixes the missing boundaries between questions.
* Added an option for showing the total response count.
* Added per-question submission. Answering one question turns that question into its
  result immediately and leaves the rest alone.
* Added deleting all responses, from the form list and the responses screen. The form
  definition is kept.
* Added the global settings screen at Ajebang Forms → Settings.
* Added adjustable display counts per choice. Turn it on in the global settings and
  the builder lets you set the number shown for each option. Turn it off and stored
  values are ignored, leaving the real response counts.

= 1.5.0 =
* Added repeat-response limiting, per form: none, browser cookie, or cookie and IP.
  The default is cookie. A visitor who has already taken part sees the results.
* Added an option to hide the submit button and send the form automatically once every
  field is filled. Visitors without JavaScript still see the button.
* Added internationalisation: a `Domain Path` header, `load_plugin_textdomain()` and a
  bundled POT file. Translations were not being loaded before this.
* Improved string extraction with more `translators:` comments and `_n()` for counts.

= 1.4.0 =
* Added a per-form option for whether a thank-you message appears after submission.
  With it off, the results appear straight away.
* Added the settings column used to store per-form options. Existing rows fall back to
  the default of showing the message.

= 1.3.2 =
* Tidied the plugin header: added `Requires at least`, `Requires PHP` and the licence
  fields, and updated `Tested up to`.

= 1.3.1 =
* Improved the survey results layout by putting each choice label on its own line with
  the bar and figures below it, which fixes long labels overlapping in narrow columns.
* Removed the fixed width from the results screen.

= 1.3.0 =
* Added AJAX submission on the front end. The page is not left behind, and surveys turn
  into their results in place. Browsers without JavaScript fall back to a normal post.
* Fixed submissions redirecting to the home page. A form posting to itself made the
  redirect target impossible to work out.
* Added server-side validation of required fields, including checkbox groups.
* Added Preview to the admin form list, matching the front end with submission disabled.

= 1.2.1 =
* Fixed a permission error when administrators opened View Statistics or
  View Submissions.

= 1.2.0 =
* Added a description field, shown above the form controls.
* Added collapsing and expanding of individual fields in the builder.
* Improved radio and checkbox styling on the front end.

= 1.1.0 =
* Added form types. Surveys show aggregated statistics.

= 1.0.0 =
* First release.

== Upgrade Notice ==

= 1.8.6 =
Fixes choice display counts silently failing to save. Upgrade if you use that option.
