merge master in prod
This commit is contained in:
@@ -1,3 +1,124 @@
|
||||
# v4.1.1
|
||||
## 09/01/2020
|
||||
|
||||
1. [](#bugfix)
|
||||
* Key field should not escape the value
|
||||
|
||||
# v4.1.0
|
||||
## 07/29/2020
|
||||
|
||||
1. [](#new)
|
||||
* Support JSON based form submissions
|
||||
1. [](#improved)
|
||||
* Improved handling of error messages with more details + translation [#428](https://github.com/getgrav/grav-plugin-form/pull/428) [#429](https://github.com/getgrav/grav-plugin-form/pull/429)
|
||||
* Various improvements for nested form data in `data.html.twig` and `data.txt.twig`
|
||||
* Use `|length` rather than `|count` twig filter
|
||||
* Various language updates
|
||||
1. [](#bugfix)
|
||||
* Disabled the EXIF library for Dropzone for fixing the orientation as it was getting applied twice [#1923](https://github.com/getgrav/grav-plugin-admin/issues/1923)
|
||||
* Forked Dropzone fo fix issue with Resize + EXIF orientation [#1923](https://github.com/getgrav/grav-plugin-admin/issues/1923)
|
||||
|
||||
# v4.0.10
|
||||
## 06/08/2020
|
||||
|
||||
1. [](#improved)
|
||||
* Updated languages
|
||||
1. [](#bugfix)
|
||||
* Fixed redirect causing empty form on homepage forms with no action set
|
||||
|
||||
# v4.0.9
|
||||
## 06/03/2020
|
||||
|
||||
1. [](#bugfix)
|
||||
* Fixed bad `id` attribute on `checkbox` field [#421](https://github.com/getgrav/grav-plugin-form/issues/421)
|
||||
* Show the `description` span even for an empty description [#313](https://github.com/getgrav/grav-plugin-form/pull/313)
|
||||
|
||||
# v4.0.8
|
||||
## 04/30/2020
|
||||
|
||||
1. [](#bugfix)
|
||||
* Fixed issue with `force_bool` in `toggle` field to be more robust
|
||||
|
||||
# v4.0.7
|
||||
## 04/27/2020
|
||||
|
||||
1. [](#new)
|
||||
* Added ability to hide form fields in `data.html.twig` and `data.txt.twig` with `field.store: false`
|
||||
1. [](#improved)
|
||||
* Updated node dependencies
|
||||
* Added new `force_bool: true|false` option to `toggle` field to cast strings for use in BC situations
|
||||
1. [](#bugfix)
|
||||
* Fix markdown links in changelog [#415](https://github.com/getgrav/grav-plugin-form/pull/415)
|
||||
|
||||
# v4.0.6
|
||||
## 03/19/2020
|
||||
1. [](#new)
|
||||
* CHANGE: Form labels are now displayed in `raw` format so you can use HTML in them
|
||||
* Added support for `name` attribute on buttons [#411](https://github.com/getgrav/grav-plugin-form/issues/411)
|
||||
1. [](#improved)
|
||||
* Added support for `classes` option in `avatar` field
|
||||
* Recompiled JS with latest NPM libraries
|
||||
1. [](#bugfix)
|
||||
* Fixed password field outputting the contents to HTML (will now always be empty when loading the page)
|
||||
* Escape default output in `formdata.html.twig` [#384](https://github.com/getgrav/grav-plugin-form/issues/384)
|
||||
* Better JS rendering of captcha field scripts for VueJS template compatibility
|
||||
|
||||
# v4.0.5
|
||||
## 03/05/2020
|
||||
|
||||
1. [](#bugfix)
|
||||
* Fixed form actions that post to page anchors should not have current base_url added (e.g. `#contact-us`)
|
||||
* Fixed toggleable buttons no longer holding false state [#406](https://github.com/getgrav/grav-plugin-form/issues/406)
|
||||
|
||||
# v4.0.4
|
||||
## 02/25/2020
|
||||
|
||||
1. [](#bugfix)
|
||||
* Fix for `enctype` in multipart forms [#408](https://github.com/getgrav/grav-plugin-form/issues/408)
|
||||
|
||||
# v4.0.3
|
||||
## 02/11/2020
|
||||
|
||||
1. [](#new)
|
||||
* Pass phpstan level 1 tests
|
||||
|
||||
# v4.0.2
|
||||
## 02/03/2020
|
||||
|
||||
1. [](#improved)
|
||||
* Allow checkbox field to have custom value, default to 1
|
||||
1. [](#bugfix)
|
||||
* Fixed `toggle` field not working with `toggleable: true`
|
||||
* Fixed fatal error when form type is disabled
|
||||
|
||||
# v4.0.1
|
||||
## 01/02/2020
|
||||
|
||||
1. [](#improved)
|
||||
* Improve Grav 1.7 support by not using deprecated `$page->modular()` call
|
||||
* Use form scope if it is defined
|
||||
1. [](#bugfix)
|
||||
* Fixed bad HTML in select, radio, key, toggle, checkbox ad textarea when using tabindex attribute
|
||||
* Fixed bad looking `tabs` field with a single tab in admin
|
||||
|
||||
# v4.0.0
|
||||
## 11/06/2019
|
||||
|
||||
1. [](#new)
|
||||
* Added `tabindex` to global attributes of default field
|
||||
* Add ability to Sanitize SVGs on upload (Grav 1.7+ required)
|
||||
1. [](#improved)
|
||||
* Deprecate `select_optgroup` as `select` can handle optgroups now
|
||||
* Added missing tabindex checks
|
||||
* Refactored field inheritance to make things more reliable
|
||||
* Removed jQuery dependency for the reCaptcha field and VanillaJS-ified it instead
|
||||
* Removed a stray `dump()` command
|
||||
* Refactored the base `templates/forms/default` twig templates to make things more extensible
|
||||
* Added a new `templates/forms/layouts` set of twit templates to allow for easier customization
|
||||
1. [](#bugfix)
|
||||
* Fixed `Badly encoded JSON data` warning when uploading files [grav#2663](https://github.com/getgrav/grav/issues/2663)
|
||||
* Fixed a number of escaping issues [#368](https://github.com/getgrav/grav-plugin-form/issues/368)
|
||||
|
||||
# v3.0.9
|
||||
## 09/19/2019
|
||||
|
||||
@@ -14,7 +135,7 @@
|
||||
* Change form save action location to `user-data://` stream [#353](https://github.com/getgrav/grav-plugin-form/issues/353)
|
||||
* Updated `eu`, `fr` and `pl` language
|
||||
* Make `Form::initialize()` chainable
|
||||
* Added `folder` option to `save:` action with fallback
|
||||
* Added `folder` option to `save:` action with fallback
|
||||
1. [](#bugfix)
|
||||
* Fixed Submit & Redirect not working as expected [#355](https://github.com/getgrav/grav-plugin-form/issues/355)
|
||||
* Fixed oversensitive refresh prevention [#354](https://github.com/getgrav/grav-plugin-form/issues/354)
|
||||
|
||||
@@ -26,4 +26,12 @@ The Learn site has two pages describing how to use the Form Plugin:
|
||||
|
||||
# Using email
|
||||
|
||||
Note: when using email functionality in your forms, make sure you have configured the Email plugin correctly. In particular, make sure you configured the "Email from" and "Email to" email addresses in the Email plugin with your email address
|
||||
Note: when using email functionality in your forms, make sure you have configured the Email plugin correctly. In particular, make sure you configured the "Email from" and "Email to" email addresses in the Email plugin with your email address.
|
||||
|
||||
# NOTES:
|
||||
|
||||
As of version **Form version 4.0.6**, form labels are now being output with the `|raw` filter. If you wish to show HTML in your form label, ie `Root Folder <root>`, then you need to escape that in your form definition:
|
||||
|
||||
```yaml
|
||||
label: Root Folder <root>
|
||||
```
|
||||
|
||||
@@ -1,6 +1,6 @@
|
||||
import $ from 'jquery';
|
||||
import Dropzone from 'dropzone';
|
||||
import EXIF from 'exif-js';
|
||||
// import EXIF from 'exif-js';
|
||||
import {config, translations} from 'grav-form';
|
||||
|
||||
// translations
|
||||
@@ -28,7 +28,7 @@ const DropzoneMediaConfig = {
|
||||
previewTemplate: ''
|
||||
};
|
||||
|
||||
window.EXIF = EXIF;
|
||||
// window.EXIF = EXIF;
|
||||
|
||||
export default class FilesField {
|
||||
constructor({container = '.dropzone.files-upload', options = {}} = {}) {
|
||||
|
||||
Vendored
+9
-9
File diff suppressed because one or more lines are too long
File diff suppressed because one or more lines are too long
@@ -1,5 +1,7 @@
|
||||
name: Form
|
||||
version: 3.0.9
|
||||
slug: form
|
||||
type: plugin
|
||||
version: 4.1.1
|
||||
testing: false
|
||||
description: Enables the forms handling
|
||||
icon: check-square
|
||||
|
||||
@@ -11,6 +11,7 @@ use Grav\Common\Grav;
|
||||
use Grav\Common\Inflector;
|
||||
use Grav\Common\Language\Language;
|
||||
use Grav\Common\Page\Interfaces\PageInterface;
|
||||
use Grav\Common\Security;
|
||||
use Grav\Common\Uri;
|
||||
use Grav\Common\Utils;
|
||||
use Grav\Framework\Filesystem\Filesystem;
|
||||
@@ -35,7 +36,7 @@ use RocketTheme\Toolbox\ResourceLocator\UniformResourceLocator;
|
||||
* @property-read Data $data
|
||||
* @property-read array $files
|
||||
* @property-read Data $value
|
||||
* @property-read array $errors
|
||||
* @property array $errors
|
||||
* @property-read array $fields
|
||||
* @property-read Blueprint $blueprint
|
||||
* @property-read PageInterface $page
|
||||
@@ -133,7 +134,7 @@ class Form implements FormInterface, \ArrayAccess
|
||||
}
|
||||
|
||||
// If we're on a modular page, find the real page.
|
||||
while ($page && $page->modular()) {
|
||||
while ($page && $page->modularTwig()) {
|
||||
$header = $page->header();
|
||||
$header->never_cache_twig = true;
|
||||
$page = $page->parent();
|
||||
@@ -546,7 +547,11 @@ class Form implements FormInterface, \ArrayAccess
|
||||
// json_response
|
||||
return [
|
||||
'status' => 'error',
|
||||
'message' => sprintf($language->translate('PLUGIN_FORM.FILEUPLOAD_UNABLE_TO_UPLOAD', null, true), $filename, $this->upload_errors[$upload['file']['error']])
|
||||
'message' => sprintf(
|
||||
$language->translate('PLUGIN_FORM.FILEUPLOAD_UNABLE_TO_UPLOAD', null, true),
|
||||
$filename,
|
||||
$this->getFileUploadError($upload['file']['error'], $language)
|
||||
)
|
||||
];
|
||||
}
|
||||
|
||||
@@ -652,6 +657,11 @@ class Form implements FormInterface, \ArrayAccess
|
||||
$upload['file']['name'] = $filename;
|
||||
$upload['file']['path'] = $path;
|
||||
|
||||
// Special Sanitization for SVG
|
||||
if (method_exists('Grav\Common\Security', 'sanitizeSVG') && Utils::contains($mime, 'svg', false)) {
|
||||
Security::sanitizeSVG($upload['file']['tmp_name']);
|
||||
}
|
||||
|
||||
// We need to store the file into flash object or it will not be available upon save later on.
|
||||
$flash = $this->getFlash();
|
||||
$flash->setUrl($url)->setUser($grav['user'] ?? null);
|
||||
@@ -693,6 +703,54 @@ class Form implements FormInterface, \ArrayAccess
|
||||
exit;
|
||||
}
|
||||
|
||||
/**
|
||||
* Return an error message for a PHP file upload error code
|
||||
* https://www.php.net/manual/en/features.file-upload.errors.php
|
||||
*
|
||||
* @param int $error PHP file upload error code
|
||||
* @param Language|null $language
|
||||
* @return string File upload error message
|
||||
*/
|
||||
public function getFileUploadError(int $error, Language $language = null): string
|
||||
{
|
||||
if (!$language) {
|
||||
$grav = Grav::instance();
|
||||
|
||||
/** @var Language $language */
|
||||
$language = $grav['language'];
|
||||
}
|
||||
|
||||
switch ($error) {
|
||||
case UPLOAD_ERR_OK:
|
||||
$item = 'FILEUPLOAD_ERR_OK';
|
||||
break;
|
||||
case UPLOAD_ERR_INI_SIZE:
|
||||
$item = 'FILEUPLOAD_ERR_INI_SIZE';
|
||||
break;
|
||||
case UPLOAD_ERR_FORM_SIZE:
|
||||
$item = 'FILEUPLOAD_ERR_FORM_SIZE';
|
||||
break;
|
||||
case UPLOAD_ERR_PARTIAL:
|
||||
$item = 'FILEUPLOAD_ERR_PARTIAL';
|
||||
break;
|
||||
case UPLOAD_ERR_NO_FILE:
|
||||
$item = 'FILEUPLOAD_ERR_NO_FILE';
|
||||
break;
|
||||
case UPLOAD_ERR_NO_TMP_DIR:
|
||||
$item = 'FILEUPLOAD_ERR_NO_TMP_DIR';
|
||||
break;
|
||||
case UPLOAD_ERR_CANT_WRITE:
|
||||
$item = 'FILEUPLOAD_ERR_CANT_WRITE';
|
||||
break;
|
||||
case UPLOAD_ERR_EXTENSION:
|
||||
$item = 'FILEUPLOAD_ERR_EXTENSION';
|
||||
break;
|
||||
default:
|
||||
$item = 'FILEUPLOAD_ERR_UNKNOWN';
|
||||
}
|
||||
return $language->translate('PLUGIN_FORM.'.$item);
|
||||
}
|
||||
|
||||
/**
|
||||
* Removes a file from the flash object session, before it gets saved.
|
||||
*/
|
||||
@@ -854,7 +912,7 @@ class Form implements FormInterface, \ArrayAccess
|
||||
|
||||
/**
|
||||
* @return string
|
||||
* @deprecated 3.0 Use $this->getName() instead
|
||||
* @deprecated 3.0 Use $form->getName() instead
|
||||
*/
|
||||
public function name(): string
|
||||
{
|
||||
@@ -863,7 +921,7 @@ class Form implements FormInterface, \ArrayAccess
|
||||
|
||||
/**
|
||||
* @return array
|
||||
* @deprecated 3.0 Use $this->getFields() instead
|
||||
* @deprecated 3.0 Use $form->getFields() instead
|
||||
*/
|
||||
public function fields(): array
|
||||
{
|
||||
@@ -872,7 +930,7 @@ class Form implements FormInterface, \ArrayAccess
|
||||
|
||||
/**
|
||||
* @return PageInterface
|
||||
* @deprecated 3.0 Use $this->getPage() instead
|
||||
* @deprecated 3.0 Use $form->getPage() instead
|
||||
*/
|
||||
public function page(): PageInterface
|
||||
{
|
||||
@@ -882,7 +940,7 @@ class Form implements FormInterface, \ArrayAccess
|
||||
/**
|
||||
* Backwards compatibility
|
||||
*
|
||||
* @deprecated 3.0
|
||||
* @deprecated 3.0 Calling $form->filter() is not needed anymore (does nothing)
|
||||
*/
|
||||
public function filter(): void
|
||||
{
|
||||
@@ -995,7 +1053,7 @@ class Form implements FormInterface, \ArrayAccess
|
||||
|
||||
public function getPagePathFromToken($path)
|
||||
{
|
||||
return Utils::getPagePathFromToken($path, $this->page());
|
||||
return Utils::getPagePathFromToken($path, $this->getPage());
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
+36
-25
@@ -1,4 +1,5 @@
|
||||
<?php
|
||||
|
||||
namespace Grav\Plugin;
|
||||
|
||||
use Composer\Autoload\ClassLoader;
|
||||
@@ -19,6 +20,7 @@ use Grav\Framework\Route\Route;
|
||||
use Grav\Plugin\Form\Form;
|
||||
use Grav\Plugin\Form\Forms;
|
||||
use ReCaptcha\ReCaptcha;
|
||||
use ReCaptcha\RequestMethod\CurlPost;
|
||||
use RocketTheme\Toolbox\File\JsonFile;
|
||||
use RocketTheme\Toolbox\File\YamlFile;
|
||||
use RocketTheme\Toolbox\File\File;
|
||||
@@ -95,7 +97,7 @@ class FormPlugin extends Plugin
|
||||
public function onPluginsInitialized()
|
||||
{
|
||||
// Backwards compatibility for plugins that use forms.
|
||||
class_alias(Form::class, \Grav\Plugin\Form::class);
|
||||
class_alias(Form::class, 'Grav\Plugin\Form');
|
||||
|
||||
$this->grav['forms'] = function () {
|
||||
$forms = new Forms();
|
||||
@@ -156,7 +158,7 @@ class FormPlugin extends Plugin
|
||||
|
||||
// Force never_cache_twig if modular form (recursively up)
|
||||
$current = $page;
|
||||
while ($current && $current->modular()) {
|
||||
while ($current && $current->modularTwig()) {
|
||||
$header = $current->header();
|
||||
$header->never_cache_twig = true;
|
||||
|
||||
@@ -218,9 +220,9 @@ class FormPlugin extends Plugin
|
||||
// Enable form events if there's a POST
|
||||
if ($this->shouldProcessForm()) {
|
||||
$this->enable([
|
||||
'onFormProcessed' => ['onFormProcessed', 0],
|
||||
'onFormProcessed' => ['onFormProcessed', 0],
|
||||
'onFormValidationError' => ['onFormValidationError', 0],
|
||||
'onFormFieldTypes' => ['onFormFieldTypes', 0],
|
||||
'onFormFieldTypes' => ['onFormFieldTypes', 0],
|
||||
]);
|
||||
|
||||
/** @var Uri $uri */
|
||||
@@ -233,8 +235,9 @@ class FormPlugin extends Plugin
|
||||
if ($form instanceof Form) {
|
||||
// Post the form
|
||||
$isJson = $uri->extension() === 'json';
|
||||
$task = $uri->post('task') ?? $uri->param('task');
|
||||
|
||||
if ($isJson) {
|
||||
$task = $uri->post('task') ?? $uri->param('task');
|
||||
if ($task === 'store-state') {
|
||||
$this->json_response = $form->storeState();
|
||||
} elseif ($task === 'clear-state') {
|
||||
@@ -244,8 +247,9 @@ class FormPlugin extends Plugin
|
||||
} elseif ($task === 'file-upload' || $uri->post('__form-file-uploader__')) {
|
||||
$this->json_response = $form->uploadFiles();
|
||||
}
|
||||
} else {
|
||||
$task = $uri->post('task');
|
||||
}
|
||||
|
||||
if (empty($this->json_response)) {
|
||||
if ($task === 'clear-state') {
|
||||
$form->getFlash()->delete();
|
||||
$redirect = $form->getBlueprint()->get('form/clear_redirect_url') ?? $page->route();
|
||||
@@ -329,9 +333,9 @@ class FormPlugin extends Plugin
|
||||
new \Twig_SimpleFunction('forms', [$this, 'getForm'])
|
||||
);
|
||||
|
||||
$this->grav['twig']->twig()->getExtension('Twig_Extension_Core')->setEscaper('yaml', function($twig, $string, $charset) {
|
||||
$this->grav['twig']->twig()->getExtension('Twig_Extension_Core')->setEscaper('yaml', function ($twig, $string, $charset) {
|
||||
return Yaml::dump($string);
|
||||
}
|
||||
}
|
||||
);
|
||||
|
||||
}
|
||||
@@ -399,6 +403,9 @@ class FormPlugin extends Plugin
|
||||
$ip = Uri::ip();
|
||||
|
||||
$recaptcha = new ReCaptcha($secret);
|
||||
if (extension_loaded('curl')) {
|
||||
$recaptcha = new ReCaptcha($secret, new CurlPost());
|
||||
}
|
||||
|
||||
// get captcha version
|
||||
$captcha_version = $captcha_config['version'] ?? 2;
|
||||
@@ -427,13 +434,13 @@ class FormPlugin extends Plugin
|
||||
$type = $field['type'] ?? 'text';
|
||||
$field_message = $field['recaptcha_not_validated'] ?? null;
|
||||
if ($type === 'captcha' && $field_message) {
|
||||
$message = $field_message;
|
||||
$message = $field_message;
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
$this->grav->fireEvent('onFormValidationError', new Event([
|
||||
'form' => $form,
|
||||
'form' => $form,
|
||||
'message' => $message
|
||||
]));
|
||||
|
||||
@@ -448,16 +455,16 @@ class FormPlugin extends Plugin
|
||||
$label = $params['label'] ?? 'Timestamp';
|
||||
$format = $params['format'] ?? 'Y-m-d H:i:s';
|
||||
$blueprint = $form->value()->blueprints();
|
||||
$blueprint->set('form/fields/timestamp', ['name'=>'timestamp', 'label'=> $label, 'type'=>'hidden']);
|
||||
$blueprint->set('form/fields/timestamp', ['name' => 'timestamp', 'label' => $label, 'type' => 'hidden']);
|
||||
$now = new \DateTime('now');
|
||||
$date_string = $now->format($format);
|
||||
$form->setFields($blueprint->fields());
|
||||
$form->setData('timestamp',$date_string);
|
||||
$form->setData('timestamp', $date_string);
|
||||
break;
|
||||
case 'ip':
|
||||
$label = $params['label'] ?? 'User IP';
|
||||
$blueprint = $form->value()->blueprints();
|
||||
$blueprint->set('form/fields/ip', ['name'=>'ip', 'label'=> $label, 'type'=>'hidden']);
|
||||
$blueprint->set('form/fields/ip', ['name' => 'ip', 'label' => $label, 'type' => 'hidden']);
|
||||
$form->setFields($blueprint->fields());
|
||||
$form->setData('ip', Uri::ip());
|
||||
break;
|
||||
@@ -503,7 +510,7 @@ class FormPlugin extends Plugin
|
||||
if (!$route || $route[0] !== '/') {
|
||||
/** @var Uri $uri */
|
||||
$uri = $this->grav['uri'];
|
||||
$route = rtrim($uri->route(), '/'). '/' . ($route ?: '');
|
||||
$route = rtrim($uri->route(), '/') . '/' . ($route ?: '');
|
||||
}
|
||||
|
||||
/** @var Twig $twig */
|
||||
@@ -523,8 +530,8 @@ class FormPlugin extends Plugin
|
||||
break;
|
||||
case 'remember':
|
||||
foreach ($params as $remember_field) {
|
||||
$field_cookie = 'forms-'.$form['name'].'-'.$remember_field;
|
||||
setcookie($field_cookie, $form->value($remember_field), time()+60*60*24*60);
|
||||
$field_cookie = 'forms-' . $form['name'] . '-' . $remember_field;
|
||||
setcookie($field_cookie, $form->value($remember_field), time() + 60 * 60 * 24 * 60);
|
||||
}
|
||||
break;
|
||||
case 'upload':
|
||||
@@ -547,7 +554,7 @@ class FormPlugin extends Plugin
|
||||
throw new \RuntimeException('Form save: \'operation: add\' is only supported with a static filename');
|
||||
}
|
||||
|
||||
$filename = $prefix . $this->udate($format, $raw_format) . $postfix. $ext;
|
||||
$filename = $prefix . $this->udate($format, $raw_format) . $postfix . $ext;
|
||||
}
|
||||
|
||||
/** @var Twig $twig */
|
||||
@@ -562,7 +569,7 @@ class FormPlugin extends Plugin
|
||||
$locator = $this->grav['locator'];
|
||||
$path = $locator->findResource('user-data://', true);
|
||||
$dir = $path . DS . $folder;
|
||||
$fullFileName = $dir. DS . $filename;
|
||||
$fullFileName = $dir . DS . $filename;
|
||||
|
||||
if (!empty($params['raw']) || !empty($params['template'])) {
|
||||
// Save data as it comes from the form.
|
||||
@@ -673,7 +680,7 @@ class FormPlugin extends Plugin
|
||||
/**
|
||||
* Handle form validation error
|
||||
*
|
||||
* @param Event $event An event object
|
||||
* @param Event $event An event object
|
||||
* @throws \Exception
|
||||
*/
|
||||
public function onFormValidationError(Event $event)
|
||||
@@ -708,10 +715,14 @@ class FormPlugin extends Plugin
|
||||
* Add a form to the forms plugin
|
||||
*
|
||||
* @param string|null $page_route
|
||||
* @param FormInterface $form
|
||||
* @param FormInterface|null $form
|
||||
*/
|
||||
public function addForm(?string $page_route, FormInterface $form)
|
||||
public function addForm(?string $page_route, ?FormInterface $form)
|
||||
{
|
||||
if (null === $form) {
|
||||
return;
|
||||
}
|
||||
|
||||
$name = $form->getName();
|
||||
|
||||
if (!isset($this->forms[$page_route][$name])) {
|
||||
@@ -813,7 +824,7 @@ class FormPlugin extends Plugin
|
||||
'key' => [
|
||||
'input@' => false
|
||||
],
|
||||
'section' => [
|
||||
'section' => [
|
||||
'input@' => false
|
||||
],
|
||||
'spacer' => [
|
||||
@@ -915,7 +926,7 @@ class FormPlugin extends Plugin
|
||||
}
|
||||
|
||||
if (isset($form->refresh_prevention)) {
|
||||
$refresh_prevention = (bool) $form->refresh_prevention;
|
||||
$refresh_prevention = (bool)$form->refresh_prevention;
|
||||
} else {
|
||||
$refresh_prevention = $this->config->get('plugins.form.refresh_prevention', false);
|
||||
}
|
||||
@@ -1072,7 +1083,7 @@ class FormPlugin extends Plugin
|
||||
* Create unix timestamp for storing the data into the filesystem.
|
||||
*
|
||||
* @param string $format
|
||||
* @param bool $raw
|
||||
* @param bool $raw
|
||||
*
|
||||
* @return string
|
||||
*/
|
||||
|
||||
@@ -1,19 +1,19 @@
|
||||
'use strict';
|
||||
|
||||
var gulp = require('gulp'),
|
||||
util = require('util'),
|
||||
path = require('path'),
|
||||
immutable = require('immutable'),
|
||||
gulpWebpack = require('gulp-webpack'),
|
||||
webpack = require('webpack'),
|
||||
sourcemaps = require('gulp-sourcemaps'),
|
||||
exec = require('child_process').execSync,
|
||||
sass = require('gulp-sass'),
|
||||
cleancss = require('gulp-clean-css'),
|
||||
csscomb = require('gulp-csscomb'),
|
||||
rename = require('gulp-rename'),
|
||||
autoprefixer = require('gulp-autoprefixer'),
|
||||
pwd = exec('pwd').toString();
|
||||
var gulp = require('gulp');
|
||||
var util = require('util');
|
||||
var path = require('path');
|
||||
var immutable = require('immutable');
|
||||
var gulpWebpack = require('gulp-webpack');
|
||||
var webpack = require('webpack');
|
||||
var sourcemaps = require('gulp-sourcemaps');
|
||||
var exec = require('child_process').execSync;
|
||||
var sass = require('gulp-sass');
|
||||
var cleancss = require('gulp-clean-css');
|
||||
var csscomb = require('gulp-csscomb');
|
||||
var rename = require('gulp-rename');
|
||||
var autoprefixer = require('gulp-autoprefixer');
|
||||
var pwd = exec('pwd').toString();
|
||||
|
||||
// configure the paths
|
||||
var watch_dir = './scss/**/*.scss';
|
||||
@@ -24,23 +24,23 @@ var paths = {
|
||||
source: src_dir
|
||||
};
|
||||
|
||||
var plugins = {},
|
||||
base = immutable.fromJS(require('./webpack.conf.js')),
|
||||
options = {
|
||||
prod: base.mergeDeep({
|
||||
devtool: 'source-map',
|
||||
optimization: {minimize: true},
|
||||
plugins: [
|
||||
new webpack.DefinePlugin({
|
||||
'process.env': { NODE_ENV: '"production"' }
|
||||
}),
|
||||
new webpack.ProvidePlugin(plugins)
|
||||
],
|
||||
output: {
|
||||
filename: 'form.min.js'
|
||||
}
|
||||
})
|
||||
};
|
||||
var plugins = {};
|
||||
var base = immutable.fromJS(require('./webpack.conf.js'));
|
||||
var options = {
|
||||
prod: base.mergeDeep({
|
||||
devtool: 'source-map',
|
||||
optimization: {minimize: true},
|
||||
plugins: [
|
||||
new webpack.DefinePlugin({
|
||||
'process.env': { NODE_ENV: '"production"' }
|
||||
}),
|
||||
new webpack.ProvidePlugin(plugins)
|
||||
],
|
||||
output: {
|
||||
filename: 'form.min.js'
|
||||
}
|
||||
})
|
||||
};
|
||||
|
||||
// var compileJS = function(watch) {
|
||||
// var prodOpts = options.prod.set('watch', watch);
|
||||
@@ -65,7 +65,7 @@ var compileCSS = function() {
|
||||
suffix: '.min'
|
||||
}))
|
||||
.pipe(gulp.dest(dest_dir));
|
||||
}
|
||||
};
|
||||
|
||||
// gulp.task('js', function() {
|
||||
// compileJS(false);
|
||||
@@ -81,4 +81,4 @@ gulp.task('watch', function() {
|
||||
});
|
||||
|
||||
gulp.task('all', ['css']);
|
||||
gulp.task('default', ['all']);
|
||||
gulp.task('default', ['all']);
|
||||
|
||||
@@ -31,6 +31,15 @@ en:
|
||||
FILEUPLOAD_PREVENT_SELF: 'Cannot use "%s" outside of pages.'
|
||||
FILEUPLOAD_UNABLE_TO_UPLOAD: 'Unable to upload file %s: %s'
|
||||
FILEUPLOAD_UNABLE_TO_MOVE: 'Unable to move file %s to "%s"'
|
||||
FILEUPLOAD_ERR_OK: 'There is no error, the file uploaded with success'
|
||||
FILEUPLOAD_ERR_INI_SIZE: 'The uploaded file exceeds the max upload size'
|
||||
FILEUPLOAD_ERR_FORM_SIZE: 'The uploaded file exceeds the MAX_FILE_SIZE directive that was specified in the HTML'
|
||||
FILEUPLOAD_ERR_PARTIAL: 'The uploaded file was only partially uploaded'
|
||||
FILEUPLOAD_ERR_NO_FILE: 'No file was uploaded'
|
||||
FILEUPLOAD_ERR_NO_TMP_DIR: 'Missing a temporary folder'
|
||||
FILEUPLOAD_ERR_CANT_WRITE: 'Failed to write file to disk'
|
||||
FILEUPLOAD_ERR_EXTENSION: 'A PHP extension stopped the file upload'
|
||||
FILEUPLOAD_ERR_UNKNOWN: 'Unknown file upload error'
|
||||
DROPZONE_CANCEL_UPLOAD: 'Cancel upload'
|
||||
DROPZONE_CANCEL_UPLOAD_CONFIRMATION: 'Are you sure you want to cancel this upload?'
|
||||
DROPZONE_DEFAULT_MESSAGE: 'Drop your files here or <strong>click in this area</strong>'
|
||||
@@ -241,6 +250,7 @@ fr:
|
||||
NOT_VALIDATED: "Formulaire non validé. Un ou plusieurs champs obligatoires sont manquants."
|
||||
NONCE_NOT_VALIDATED: "Oups, un problème est survenu. Veuillez vérifier votre saisie et soumettre à nouveau le formulaire."
|
||||
FILES: "Fichiers chargés"
|
||||
FORM_ALREADY_SUBMITTED: "Le formulaire a déjà été envoyé."
|
||||
ALLOW_MULTIPLE: "Autoriser plus d'un fichier"
|
||||
ALLOW_MULTIPLE_HELP: "Permet la sélection de plusieurs fichiers pour chargement."
|
||||
DESTINATION: "Destination"
|
||||
@@ -436,6 +446,7 @@ hu:
|
||||
NOT_VALIDATED: "Érvénytelen az űrlap. Egy vagy több kötelező mező nincs kitöltve."
|
||||
NONCE_NOT_VALIDATED: "Upsz, van egy kis probléma, kérlek nézd át az űrlapot, majd küldd el újra."
|
||||
FILES: "Fájlok Feltöltése"
|
||||
FORM_ALREADY_SUBMITTED: "Ez az űrlap már el lett küldve."
|
||||
ALLOW_MULTIPLE: "Több fájl feltöltése"
|
||||
ALLOW_MULTIPLE_HELP: "Engedélyezi egyszerre több állomány feltöltését."
|
||||
DESTINATION: "Feltöltés Helye"
|
||||
@@ -443,6 +454,58 @@ hu:
|
||||
ACCEPT: "Engedélyezett MIME-típusok"
|
||||
ACCEPT_HELP: "A feltölthető állományok MIME-típusainak listája"
|
||||
ERROR_VALIDATING_CAPTCHA: "Hiba lépett fel a Captcha validálása során"
|
||||
DATA_SUMMARY: "Üzenet összesítő:"
|
||||
NO_FORM_DATA: "Űrlap adatok nem elérhetőek."
|
||||
RECAPTCHA: "reCAPTCHA"
|
||||
RECAPTCHA_VERSION: "Verzió"
|
||||
RECAPTCHA_VERSION_V2_CHECKBOX: "v2 - Kijelölőnégyzet"
|
||||
RECAPTCHA_VERSION_V2_INVISIBLE: "v2 - Láthatatlan"
|
||||
RECAPTCHA_VERSION_V3_LATEST: "v3 - Legutolsó"
|
||||
RECAPTCHA_THEME: "Téma"
|
||||
RECAPTCHA_THEME_LIGHT: "Világos téma"
|
||||
RECAPTCHA_THEME_DARK: "Sötét téma"
|
||||
RECAPTCHA_SITE_KEY: "Site kulcs"
|
||||
RECAPTCHA_SITE_KEY_HELP: "További információért látogass el ide a https://developers.google.com/recaptcha webhelyre."
|
||||
RECAPTCHA_SECRET_KEY: "Secret kulcs"
|
||||
RECAPTCHA_SECRET_KEY_HELP: "További információért látogass el ide a https://developers.google.com/recaptcha webhelyre."
|
||||
GENERAL: "Általános"
|
||||
USE_BUILT_IN_CSS: "Alapértelmezett CSS használata"
|
||||
USE_INLINE_CSS: "Beágyazott CSS használata"
|
||||
FILEUPLOAD_PREVENT_SELF: '"%s" nem használható oldalakon kívül.'
|
||||
FILEUPLOAD_UNABLE_TO_UPLOAD: 'Sikertelen fájlfeltöltés %s: %s'
|
||||
FILEUPLOAD_UNABLE_TO_MOVE: '%s áthelyezése sikertelen ide: "%s"'
|
||||
DROPZONE_CANCEL_UPLOAD: 'Feltöltés megszakítása'
|
||||
DROPZONE_CANCEL_UPLOAD_CONFIRMATION: 'Biztos megszakítsuk a feltöltést?'
|
||||
DROPZONE_DEFAULT_MESSAGE: 'Húzza a fájlokat ide vagy <strong>kattintson a területre</strong>'
|
||||
DROPZONE_FALLBACK_MESSAGE: 'A böngésző nem támogatja a drag and drop fájlfeltöltéseket.'
|
||||
DROPZONE_FALLBACK_TEXT: 'Kérjük használja a kompatibilitási űrlapot vagy a hagyományos fájfeltöltést.'
|
||||
DROPZONE_FILE_TOO_BIG: 'Túl nagy állomány ({{filesize}}MiB). Maximum fájlméret: {{maxFilesize}}MiB.'
|
||||
DROPZONE_INVALID_FILE_TYPE: "Ilyen típusú fájlok feltöltése nem megengedett."
|
||||
DROPZONE_MAX_FILES_EXCEEDED: "További fájlok feltöltése nem megengedett, elérte a maximumot."
|
||||
DROPZONE_REMOVE_FILE: "Fájl eltávolítása"
|
||||
DROPZONE_REMOVE_FILE_CONFIRMATION: 'Biztos az eltávolításban?'
|
||||
DROPZONE_RESPONSE_ERROR: "Szerver hiba, kód: {{statusCode}}."
|
||||
YES: "Igen"
|
||||
NO: "Nem"
|
||||
REFRESH_PREVENTION: "Újratöltési védelem"
|
||||
REFRESH_PREVENTION_HELP: "Az űrlap egyedi azonosítójának használata annak érdekében hogy az űrlap ne legyen újrafeldolgozva oldalfrissítés esetén."
|
||||
LIMIT: "Limit"
|
||||
LIMIT_HELP: "Az egy mezőben megadható fájlok maximális száma. (multiple required)"
|
||||
FILESIZE: "Maximum fájlméret"
|
||||
FILESIZE_HELP: "Maximum engedélyezett fájlméret (MB-ban), 0 = Rendszer alapértelmezés használata."
|
||||
AVOID_OVERWRITING: "Felülírás elkerülése"
|
||||
AVOID_OVERWRITING_HELP: "A már létező fájlok felülírásának elkerülése, dátum előtag hozzáadásával a fájlnévhez."
|
||||
RANDOM_NAME: "Véletlenszerű név"
|
||||
RANDOM_NAME_HELP: "Generáljon egy 15 karakter hosszú véletlenszerű nevet a feltöltött fájloknak."
|
||||
CLIENT_SIDE_VALIDATION: "Kliens oldali validáció"
|
||||
CLIENT_SIDE_VALIDATION_HELP: "Az űrlapok HTML5 kliens oldali validációt használnak alapértelmezésként, mint első védelmi vonal."
|
||||
INLINE_ERRORS: "Beágyazott hibaüzenetek"
|
||||
INLINE_ERRORS_HELP: "Beágyazott kontextuális űrlaphibák megjelenítése, hasznos ha a 'Kliens oldali validáció' ki van kapcsolva."
|
||||
RESOLUTION_MIN: "A(z) {{attr}} érték kisebb mint a minimum {{min}}px <br />"
|
||||
RESOLUTION_MAX: "A(z) {{attr}} érték nagyobb mint a maximum {{max}}px <br />"
|
||||
DESTINATION_NOT_SPECIFIED: "A feltöltés helye nincs megadva."
|
||||
INVALID_MIME_TYPE: "MIME-típus %s nem engedélyezett. Állomány: %s."
|
||||
INVALID_FILE_EXTENSION: "A(z) %s állomány kiterjesztése nem engedélyezett."
|
||||
|
||||
it:
|
||||
PLUGIN_FORM:
|
||||
|
||||
@@ -12,35 +12,34 @@
|
||||
"author": "Team Grav",
|
||||
"license": "MIT",
|
||||
"dependencies": {
|
||||
"dropzone": "^5.5.1",
|
||||
"dropzone": "getgrav/dropzone#master",
|
||||
"exif-js": "^2.3.0",
|
||||
"sortablejs": "^1.7.0"
|
||||
"sortablejs": "^1.10.2"
|
||||
},
|
||||
"devDependencies": {
|
||||
"babel-core": "^6.26.3",
|
||||
"babel-eslint": "^8.2.6",
|
||||
"babel-loader": "^7.1.5",
|
||||
"@babel/core": "^7.9.0",
|
||||
"@babel/preset-env": "^7.9.0",
|
||||
"babel-eslint": "^10.1.0",
|
||||
"babel-loader": "^8.1.0",
|
||||
"babel-polyfill": "^6.26.0",
|
||||
"babel-preset-es2015": "^6.24.1",
|
||||
"babel-preset-stage-3": "^6.24.1",
|
||||
"css-loader": "^1.0.0",
|
||||
"eslint": "^5.6.0",
|
||||
"eslint-loader": "^2.1.1",
|
||||
"css-loader": "^3.4.2",
|
||||
"eslint": "^6.8.0",
|
||||
"eslint-loader": "^3.0.4",
|
||||
"exports-loader": "^0.7.0",
|
||||
"gulp": "latest",
|
||||
"gulp-autoprefixer": "latest",
|
||||
"gulp-clean-css": "^3.10.0",
|
||||
"gulp-csscomb": "^3.0.8",
|
||||
"gulp-rename": "^1.4.0",
|
||||
"gulp-sass": "^4.0.1",
|
||||
"gulp-sourcemaps": "^2.6.4",
|
||||
"gulp": "^4.0.2",
|
||||
"gulp-autoprefixer": "^7.0.1",
|
||||
"gulp-clean-css": "^4.3.0",
|
||||
"gulp-csscomb": "^3.1.0",
|
||||
"gulp-rename": "^2.0.0",
|
||||
"gulp-sass": "^4.0.2",
|
||||
"gulp-sourcemaps": "^2.6.5",
|
||||
"gulp-webpack": "^1.5.0",
|
||||
"immutable": "^4.0.0-rc.12",
|
||||
"imports-loader": "^0.8.0",
|
||||
"json-loader": "^0.5.7",
|
||||
"style-loader": "^0.23.0",
|
||||
"uglifyjs-webpack-plugin": "^2.0.1",
|
||||
"webpack": "^4.19.1",
|
||||
"webpack-cli": "^3.1.0"
|
||||
"style-loader": "^1.1.3",
|
||||
"uglifyjs-webpack-plugin": "^2.2.0",
|
||||
"webpack": "^4.42.1",
|
||||
"webpack-cli": "^3.3.11"
|
||||
}
|
||||
}
|
||||
|
||||
@@ -2,41 +2,57 @@
|
||||
{% import _self as self %}
|
||||
|
||||
{% for index, field in fields %}
|
||||
{% set input = attribute(field, "input@") %}
|
||||
|
||||
{% if input is null or input == true %}
|
||||
|
||||
{% if form.value(scope ~ field.name) %}
|
||||
{% block field %}
|
||||
<div>
|
||||
{% block field_label %}
|
||||
<strong>{{ field.label|t|e }}</strong>:
|
||||
{% endblock %}
|
||||
|
||||
{% block field_value %}
|
||||
{% if field.type == 'checkboxes' %}
|
||||
<ul>
|
||||
{% set use_keys = field.use is defined and field.use == 'keys' %}
|
||||
{% for key,value in form.value(scope ~ field.name) %}
|
||||
{% set index = (use_keys ? key : value) %}
|
||||
<li>{{ field.options[index]|e }}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% elseif field.type == 'checkbox' %}
|
||||
{{ (form.value(scope ~ field.name) == 1) ? "GRAV.YES"|t|e : "GRAV.NO"|t|e }}
|
||||
{% elseif field.type == 'select' %}
|
||||
{{ field.options[form.value(scope ~ field.name)]|e }}
|
||||
{% else %}
|
||||
{{ string(form.value(scope ~ field.name))|nl2br }}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
{% endif %}
|
||||
{%- set show_field = attribute(field, "input@") ?? field.store ?? true %}
|
||||
{% if field.fields %}
|
||||
{%- set new_scope = field.nest_id ? scope ~ field.name ~ '.' : scope -%}
|
||||
{{- self.render_field(form, field.fields, new_scope) }}
|
||||
{% else %}
|
||||
{% if field.fields %}
|
||||
{% set new_scope = field.nest_id ? scope ~ field.name ~ '.' : scope %}
|
||||
{{ self.render_field(form, field.fields, new_scope) }}
|
||||
{% if show_field %}
|
||||
{%- set value = form.value(scope ~ (field.name ?? index)) -%}
|
||||
{% if value %}
|
||||
{% block field %}
|
||||
<div>
|
||||
{% block field_label %}
|
||||
<strong>{{ field.label|t|e }}</strong>:
|
||||
{% endblock %}
|
||||
|
||||
{% block field_value %}
|
||||
{% if field.type == 'checkboxes' %}
|
||||
<ul>
|
||||
{% set use_keys = field.use is defined and field.use == 'keys' %}
|
||||
{% for key,value in form.value(scope ~ field.name) %}
|
||||
{% set index = (use_keys ? key : value) %}
|
||||
<li>{{ field.options[index]|e }}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% elseif field.type == 'checkbox' %}
|
||||
{{ (form.value(scope ~ field.name) == 1) ? "GRAV.YES"|t|e : "GRAV.NO"|t|e }}
|
||||
{% elseif field.type == 'select' %}
|
||||
{{ field.options[form.value(scope ~ field.name)]|e }}
|
||||
{% else %}
|
||||
{% set value = form.value(scope ~ field.name) %}
|
||||
{% if value is iterable %}
|
||||
<ul>
|
||||
{% for val in value %}
|
||||
{% if val is iterable %}
|
||||
<ul>
|
||||
{% for v in val %}
|
||||
<li>{{ string(v)|e }}</li>
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% else %}
|
||||
<li>{{ string(val)|e }}</li>
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
</ul>
|
||||
{% else %}
|
||||
{{ string(value)|e|nl2br }}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
@@ -45,4 +61,3 @@
|
||||
{% import _self as macro %}
|
||||
|
||||
{{ macro.render_field(form, form.fields, '') }}
|
||||
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
{%- macro render_field(form, fields, scope) %}
|
||||
{%- import _self as self %}
|
||||
{%- for index, field in fields %}
|
||||
{%- set input = attribute(field, "input@") %}
|
||||
{%- if input is null or input == true %}
|
||||
{%- set value = form.value(scope ~ (field.name ?? index)) %}
|
||||
{{- scope ~ (field.name ?? index) }}: {{ string(value is iterable ? value|json_encode : value|escape('yaml')) ~ "\r\n" }}
|
||||
{%- else %}
|
||||
{%- if field.fields %}
|
||||
{%- set show_field = attribute(field, "input@") ?? field.store ?? true %}
|
||||
{%- if field.fields %}
|
||||
{%- set new_scope = field.nest_id ? scope ~ field.name ~ '.' : scope -%}
|
||||
{{- self.render_field(form, field.fields, new_scope) }}
|
||||
{%- else %}
|
||||
{%- if show_field %}
|
||||
{%- set value = form.value(scope ~ (field.name ?? index)) -%}
|
||||
{%- if value -%}
|
||||
{{- field.label }}: {{ string(value is iterable ? value|json_encode : value|e) ~ "\r\n" }}
|
||||
{%- endif -%}
|
||||
{%- endif %}
|
||||
{%- endif %}
|
||||
{%- endfor %}
|
||||
@@ -16,4 +18,4 @@
|
||||
{%- import _self as macro %}
|
||||
{%- autoescape false %}
|
||||
{{- macro.render_field(form, form.fields, '') ~ "\r\n" }}
|
||||
{%- endautoescape %}
|
||||
{%- endautoescape %}
|
||||
|
||||
@@ -1,4 +1,7 @@
|
||||
{% if not field.validate.ignore %}
|
||||
{% if not field.validate.ignore %}
|
||||
|
||||
{% use 'forms/layouts/field-variables.html.twig' %}
|
||||
{% block field_override_variables_before %}{% endblock %}
|
||||
|
||||
{% set field_name = (scope ~ field.name)|fieldName %}
|
||||
{% set vertical = field.style == 'vertical' %}
|
||||
@@ -7,11 +10,11 @@
|
||||
{% set toggleable = field.toggleable ?? false %}
|
||||
{% if toggleable %}
|
||||
{% set originalValue = originalValue is defined ? originalValue : value %}
|
||||
{% set toggleableChecked = originalValue is not null and originalValue is not empty %}
|
||||
{% set toggleableChecked = originalValue is not null %}
|
||||
{% elseif field.overridable %}
|
||||
{% set toggleable = true %}
|
||||
{% set default = form.getDefaultValue(field.name) ?? field.default %}
|
||||
{% set toggleableChecked = value != default %}
|
||||
{% set toggleableChecked = value is not null and value != default %}
|
||||
{% endif %}
|
||||
|
||||
{% set cookie_name = 'forms-' ~ form.name ~ '-' ~ field.name %}
|
||||
@@ -27,6 +30,12 @@
|
||||
{# DEPRECATED: Needed by old form fields; remove when backwards compatibility breaks are allowed #}
|
||||
{% set isDisabledToggleable = toggleable and not toggleableChecked %}
|
||||
|
||||
{% if toggleable %}
|
||||
{% set form_field_toggleable %}
|
||||
{% include 'forms/default/toggleable.html.twig' with {checked: toggleableChecked} %}
|
||||
{% endset %}
|
||||
{% endif %}
|
||||
|
||||
{% set errors = attribute(form.messages, field.name) %}
|
||||
{% set required = client_side_validation and field.validate.required in ['on', 'true', 1] %}
|
||||
{% set autofocus = (inline_errors == false) and field.autofocus in ['on', 'true', 1] %}
|
||||
@@ -35,105 +44,112 @@
|
||||
{% set autofocus = true %}
|
||||
{% endif %}
|
||||
|
||||
{% block field %}
|
||||
<div class="form-field {{ form_field_outer_classes }} {{ field.outerclasses }} {% if errors %} has-errors{% endif %} {% block outer_field_classes %}{% endblock %} {% if toggleable %} form-field-toggleable{% endif %}">
|
||||
{% block contents %}
|
||||
{% if field.label is not same as(false) and field.display_label is not same as(false) %}
|
||||
<div class="{{ form_field_outer_label_classes ?: 'form-label' }} {{ field.labelclasses }}">
|
||||
{% if toggleable %}
|
||||
{% include 'forms/default/toggleable.html.twig' with {field_name: field_name, field: field, checked: toggleableChecked} %}
|
||||
{% endif %}
|
||||
<label class="{{ form_field_label_classes ?: 'inline' }} {{ toggleable ? 'toggleable' }}" {% if field.id is defined %}for="{{ toggleable ? 'toggleable_' ~ field.name : field.id|e }}" {% endif %} >
|
||||
{% block label %}
|
||||
{% if field.help %}
|
||||
{% if field.markdown %}
|
||||
<span class="tooltip" data-asTooltip-position="w" title="{{ field.help|t|markdown(false)|e }}">{{ field.label|markdown(false)|default(field.name|capitalize)|t }}</span>
|
||||
{% else %}
|
||||
<span class="tooltip" data-asTooltip-position="w" title="{{ field.help|t|e }}">{{ field.label|default(field.name|capitalize)|t }}</span>
|
||||
{% endif %}
|
||||
{% else %}
|
||||
{% if field.markdown %}
|
||||
{{ field.label|markdown(false)|default(field.name|capitalize)|t }}
|
||||
{% else %}
|
||||
{{ field.label|default(field.name|capitalize)|t|e('html_attr') }}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% set embed_outer_field_classes %}
|
||||
{% block outer_field_classes %}{% endblock %}
|
||||
{% endset %}
|
||||
|
||||
{{ field.validate.required in ['on', 'true', 1] ? '<span class="required">*</span>' }}
|
||||
{% endblock %}
|
||||
</label>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="{{ form_field_outer_data_classes ?: 'form-data' }} {{ field.dataclasses }}"
|
||||
{% block global_attributes %}
|
||||
data-grav-field="{{ field.type }}"
|
||||
data-grav-disabled="{{ toggleable and toggleableChecked }}"
|
||||
data-grav-default="{{ field.default|json_encode()|e('html_attr') }}"
|
||||
{% endblock %}
|
||||
>
|
||||
{% block group %}
|
||||
{% block input %}
|
||||
<div class="{{ form_field_wrapper_classes ?: 'form-input-wrapper' }} {{ field.size }} {{ field.wrapper_classes }}">
|
||||
{% block prepend %}{% endblock prepend %}
|
||||
<input
|
||||
{# required attribute structures #}
|
||||
name="{{ (scope ~ field.name)|fieldName }}"
|
||||
value="{{ value|join(', ')|e('html_attr') }}"
|
||||
{# input attribute structures #}
|
||||
{% block input_attributes %}
|
||||
class="{{ form_field_input_classes }} {{ field.classes }} {{ field.size }}"
|
||||
{% if field.id is defined %}id="{{ field.id|e }}" {% endif %}
|
||||
{% if field.style is defined %}style="{{ field.style|e }}" {% endif %}
|
||||
{% if field.disabled or isDisabledToggleable %}disabled="disabled"{% endif %}
|
||||
{% if field.placeholder %}placeholder="{{ field.placeholder|t|e('html_attr') }}"{% endif %}
|
||||
{% if autofocus %}autofocus="autofocus"{% endif %}
|
||||
{% if field.novalidate in ['on', 'true', 1] %}novalidate="novalidate"{% endif %}
|
||||
{% if field.readonly in ['on', 'true', 1] %}readonly="readonly"{% endif %}
|
||||
{% if field.autocomplete is defined %}autocomplete="{{ field.autocomplete }}"{% endif %}
|
||||
{% if field.autocapitalize in ['off', 'characters', 'words', 'sentences'] %}autocapitalize="{{ field.autocapitalize }}"{% endif %}
|
||||
{% if field.inputmode in ['none', 'text', 'decimal', 'numeric', 'tel', 'search', 'email', 'url'] %}inputmode="{{ field.inputmode }}"{% endif %}
|
||||
{% if field.spellcheck in ['true', 'false'] %}spellcheck="{{ field.spellcheck }}"{% endif %}
|
||||
{# Field Classes #}
|
||||
{%- if errors %}{% set form_field_outer_core = form_field_outer_core ~ ' has-errors' %}{% endif -%}
|
||||
{%- if toggleable %}{% set form_field_outer_core = form_field_outer_core ~ ' form-field-toggleable' %}{% endif -%}
|
||||
|
||||
{% if field.attributes is defined %}
|
||||
{% for attribute in field.attributes %}
|
||||
{{ attribute.name }}="{{ attribute.value|e }}"
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% if required %}required="required"{% endif %}
|
||||
{% if field.validate.pattern %}pattern="{{ field.validate.pattern|e }}"{% endif %}
|
||||
{% if field.validate.message %}title="{{ field.validate.message|t|e }}"
|
||||
{% elseif field.title is defined %}title="{{ field.title|t|e }}" {% endif %}
|
||||
{% if field.datasets %}
|
||||
{% for datakey, datavalue in field.datasets %}
|
||||
data-{{ datakey }}="{{ datavalue|e('html_attr') }}"
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
/>
|
||||
{% block append %}{% endblock append %}
|
||||
{% if inline_errors and errors %}
|
||||
<div class="{{ form_errors_classes ?: 'form-errors' }}">
|
||||
<p class="form-message"><i class="fa fa-exclamation-circle"></i> {{ errors|first }}</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
{% if field.description %}
|
||||
<div class="form-extra-wrapper {{ field.wrapper_classes }}">
|
||||
<span class="form-description">
|
||||
{% if field.markdown %}
|
||||
{{ field.description|t|markdown(false)|raw }}
|
||||
{% else %}
|
||||
{{ field.description|t|raw }}
|
||||
{% endif %}
|
||||
</span>
|
||||
</div>
|
||||
{% endif %}
|
||||
{% set layout_form_field_outer_classes = field.outerclasses %}
|
||||
{% set layout_form_field_outer_classes = layout_form_field_outer_classes|trim ~ ' ' ~ form_field_outer_classes %}
|
||||
{% set layout_form_field_outer_classes = layout_form_field_outer_classes|trim ~ ' ' ~ embed_outer_field_classes %}
|
||||
|
||||
</div>
|
||||
{% endblock %}
|
||||
</div>
|
||||
{# Show Label logic #}
|
||||
{% set show_label = field.label is not same as(false) and field.display_label is not same as(false )%}
|
||||
|
||||
{# Label Classes #}
|
||||
{% set layout_form_field_outer_label_classes = ((form_field_outer_label_classes ?: 'form-label') ~ ' ' ~ field.labelclasses)|trim %}
|
||||
{% set layout_form_field_label_classes = (form_field_label_classes ?: 'inline')|trim %}
|
||||
{% set form_field_label_trim = toggleable ? 'toggleable' %}
|
||||
|
||||
{# Field Outer Data classes #}
|
||||
{% set layout_form_field_outer_data_classes = ((form_field_outer_data_classes ?: ' form-data') ~ ' ' ~ field.dataclasses)|trim %}
|
||||
|
||||
{# Field Wrapper classes #}
|
||||
{% set layout_form_field_wrapper_classes = ((form_field_wrapper_classes ?: ' form-input-wrapper') ~ ' ' ~ field.wrapper_classes)|trim %}
|
||||
|
||||
{# Field input classes #}
|
||||
{% if field|of_type('array') %}
|
||||
{% if field.classes %}
|
||||
{% set field = field|merge({'classes': field.classes ~ ' ' ~ block('field_input_classes')|trim }) %}
|
||||
{% else %}
|
||||
{% set field = field|merge({'classes': block('field_input_classes') }) %}
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% set layout_form_field_input_classes = (form_field_input_classes ~ ' ' ~ field.classes)|trim %}
|
||||
|
||||
{# Inline error classes #}
|
||||
{% set form_field_inline_error_classes = form_field_inline_error_classes ?: ' form-errors' %}
|
||||
|
||||
{# Field extra classes #}
|
||||
{% set form_field_extra_wrapper_classes = 'form-extra-wrapper ' ~ field.wrapper_classes %}
|
||||
|
||||
{# Field For #}
|
||||
{% set form_field_for = toggleable ? 'toggleable_' ~ field.name : field.id|e %}
|
||||
|
||||
{# Field Label #}
|
||||
{% set form_field_label = field.markdown ? field.label|markdown(false) : field.label %}
|
||||
{% set form_field_label = form_field_label|default(field.name|capitalize)|t %}
|
||||
|
||||
{# Field Help #}
|
||||
{% if field.help %}
|
||||
{% set form_field_help = field.markdown ? field.help|t|markdown(false)|e : field.help|t|e %}
|
||||
{% endif %}
|
||||
|
||||
{# Field Requied #}
|
||||
{% set form_field_required = field.validate.required in ['on', 'true', 1] ? true : false %}
|
||||
|
||||
{# Field Description #}
|
||||
{% set form_field_description = field.markdown ? field.description|t|markdown(false)|raw : field.description|t|raw %}
|
||||
|
||||
{% extends 'forms/layouts/field.html.twig' %}
|
||||
|
||||
{% block global_attributes %}
|
||||
data-grav-field="{{ field.type }}"
|
||||
data-grav-disabled="{{ toggleable and toggleableChecked }}"
|
||||
data-grav-default="{{ field.default|json_encode()|e('html_attr') }}"
|
||||
{% endblock %}
|
||||
|
||||
{% block input_attributes %}
|
||||
class="{{ layout_form_field_input_classes|trim }} {{ field.size }}"
|
||||
{% if field.id is defined %}id="{{ field.id|e }}" {% endif %}
|
||||
{% if field.style is defined %}style="{{ field.style|e }}" {% endif %}
|
||||
{% if field.disabled or isDisabledToggleable %}disabled="disabled"{% endif %}
|
||||
{% if field.placeholder %}placeholder="{{ field.placeholder|t|e('html_attr') }}"{% endif %}
|
||||
{% if autofocus %}autofocus="autofocus"{% endif %}
|
||||
{% if field.novalidate in ['on', 'true', 1] %}novalidate="novalidate"{% endif %}
|
||||
{% if field.readonly in ['on', 'true', 1] %}readonly="readonly"{% endif %}
|
||||
{% if field.autocomplete is defined %}autocomplete="{{ field.autocomplete }}"{% endif %}
|
||||
{% if field.autocapitalize in ['off', 'characters', 'words', 'sentences'] %}autocapitalize="{{ field.autocapitalize }}"{% endif %}
|
||||
{% if field.inputmode in ['none', 'text', 'decimal', 'numeric', 'tel', 'search', 'email', 'url'] %}inputmode="{{ field.inputmode }}"{% endif %}
|
||||
{% if field.tabindex %}tabindex="{{ field.tabindex }}"{% endif %}
|
||||
{% if field.spellcheck in ['true', 'false'] %}spellcheck="{{ field.spellcheck }}"{% endif %}
|
||||
{% if required %}required="required"{% endif %}
|
||||
{% if field.validate.pattern %}pattern="{{ field.validate.pattern|e }}"{% endif %}
|
||||
{% if field.validate.message %}title="{{ field.validate.message|t|e }}"
|
||||
{% elseif field.title is defined %}title="{{ field.title|t|e }}" {% endif %}
|
||||
|
||||
{# Support key/value and .name/.value styles #}
|
||||
{% if field.attributes is defined %}
|
||||
{% for key,attribute in field.attributes %}
|
||||
{% if attribute|of_type('array') %}
|
||||
{{ attribute.name }}="{{ attribute.value|e('html_attr') }}"
|
||||
{% else %}
|
||||
{{ key }}="{{ attribute|e('html_attr') }}"
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
|
||||
{# Support for Custom data attributes#}
|
||||
{% if field.datasets %}
|
||||
{% for key, attribute in field.datasets %}
|
||||
data-{{ key }}="{{ attribute|e('html_attr') }}"
|
||||
{% endfor %}
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
|
||||
|
||||
{% endif %}
|
||||
|
||||
@@ -6,10 +6,10 @@
|
||||
{% endif %}
|
||||
|
||||
{% set value = form ? form.value(field_name) : data.value(field_name) %}
|
||||
{% block field_open %}{% endblock %}
|
||||
{% block inner_markup_field_open %}{% endblock %}
|
||||
{% block field %}
|
||||
{% include ["forms/fields/#{field.type}/#{field.type}.html.twig", 'forms/fields/text/text.html.twig'] %}
|
||||
{% endblock %}
|
||||
{% block field_close %}{% endblock %}
|
||||
{% block inner_markup_field_close %}{% endblock %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
@@ -4,13 +4,16 @@
|
||||
|
||||
{% include 'partials/form-messages.html.twig' %}
|
||||
|
||||
{% set scope = scope ?: 'data.' %}
|
||||
{% set scope = scope ?: form.scope is defined ? form.scope : 'data.' %}
|
||||
{% set multipart = '' %}
|
||||
{% set blueprints = blueprints ?? form.blueprint() %}
|
||||
{% set method = form.method|upper|default('POST') %}
|
||||
{% set client_side_validation = form.client_side_validation is not null ? form.client_side_validation : config.plugins.form.client_side_validation|default(true) %}
|
||||
{% set inline_errors = form.inline_errors is not null ? form.inline_errors : config.plugins.form.inline_errors(false) %}
|
||||
|
||||
{% set data = data ?? form.data %}
|
||||
{% set context = context ?? data %}
|
||||
|
||||
{% for field in form.fields %}
|
||||
{% if (method == 'POST' and field.type == 'file') %}
|
||||
{% set multipart = ' enctype="multipart/form-data"' %}
|
||||
@@ -18,10 +21,10 @@
|
||||
{% endfor %}
|
||||
|
||||
{% set action = form.action ?: page.route ~ uri.params %}
|
||||
{% set action = action starts with 'http' ? action : base_url ~ action %}
|
||||
|
||||
{% set action = (action starts with 'http') or (action starts with '#') ? action : base_url ~ action %}
|
||||
{% set action = action|trim('/', 'right') %}
|
||||
{% if (action == base_url_relative) %}
|
||||
{% set action = base_url_relative ~ '/' ~ page.slug %}
|
||||
{% set action = base_url_relative ~ '/' %}
|
||||
{% endif %}
|
||||
|
||||
{% if form.keep_alive %}
|
||||
@@ -44,88 +47,129 @@
|
||||
window.GravForm.translations = Object.assign({}, window.GravForm.translations || {}, { PLUGIN_FORM: {} });
|
||||
", {'group': 'bottom', 'position': 'before'}) %}
|
||||
|
||||
<form name="{{ form.name }}"
|
||||
action="{{ action | trim('/', 'right') }}"
|
||||
method="{{ method }}"{{ multipart }}
|
||||
{% if form.id %}id="{{ form.id }}"{% endif %}
|
||||
{% block form_classes %}
|
||||
class="{{ form_outer_classes }} {{ form.classes }}"
|
||||
{% endblock %}
|
||||
{% if form.novalidate %}novalidate{% endif %}
|
||||
{% if form.keep_alive %}data-grav-keepalive="true"{% endif %}
|
||||
>
|
||||
{# Backwards Compatibility for block overrides #}
|
||||
{% set override_form_classes %}
|
||||
{% block form_classes -%}
|
||||
{{ form_outer_classes }} {{ form.classes }}
|
||||
{%- endblock %}
|
||||
{% endset %}
|
||||
|
||||
{% set override_inner_markup_fields_start %}
|
||||
{% block inner_markup_fields_start %}{% endblock %}
|
||||
{% endset %}
|
||||
|
||||
{% set data = data ?? form.data %}
|
||||
{% set context = context ?? data %}
|
||||
|
||||
{% block inner_markup_fields %}
|
||||
{% for field_name, field in form.fields %}
|
||||
{% set field_name = field.name ?? field_name %}
|
||||
{% if field_name and not field.validate.ignore %}
|
||||
{%- if field_name starts with '.' -%}
|
||||
{% set field_name = field_name[1:] %}
|
||||
{% set field = field|merge({ name: field_name }) %}
|
||||
{% endif %}
|
||||
|
||||
{% set value = form ? form.value(field_name) : data.value(field_name) %}
|
||||
{% block inner_markup_field_open %}{% endblock %}
|
||||
{% block process_field %}
|
||||
{% include "forms/fields/#{field.type}/#{field.type}.html.twig" ignore missing %}
|
||||
{% endblock %}
|
||||
{% block inner_markup_field_close %}{% endblock %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endblock %}
|
||||
|
||||
{% include "forms/fields/formname/formname.html.twig" %}
|
||||
{% include "forms/fields/formtask/formtask.html.twig" %}
|
||||
|
||||
{% set override_inner_markup_fields_end %}
|
||||
{% block inner_markup_fields_end %}{% endblock %}
|
||||
{% endset %}
|
||||
|
||||
{% set override_inner_markup_fields %}
|
||||
{% block inner_markup_fields %}
|
||||
{% for field_name, field in form.fields %}
|
||||
{% set field_name = field.name ?? field_name %}
|
||||
{% if field_name and not field.validate.ignore %}
|
||||
{%- if field_name starts with '.' -%}
|
||||
{% set field_name = field_name[1:] %}
|
||||
{% set field = field|merge({ name: field_name }) %}
|
||||
{% endif %}
|
||||
|
||||
{% set value = form ? form.value(field_name) : data.value(field_name) %}
|
||||
{% block inner_markup_field_open %}{% endblock %}
|
||||
{% block field %}
|
||||
{% include "forms/fields/#{field.type}/#{field.type}.html.twig" ignore missing %}
|
||||
{% endblock %}
|
||||
{% block inner_markup_field_close %}{% endblock %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% endblock %}
|
||||
{% endset %}
|
||||
|
||||
{% set override_inner_markup_buttons_start %}
|
||||
{% block inner_markup_buttons_start %}
|
||||
<div class="{{ form_button_outer_classes ?: 'buttons'}}">
|
||||
{% endblock %}
|
||||
{% endset %}
|
||||
|
||||
{% for button in form.buttons %}
|
||||
{% if button.outerclasses is defined %}<div class=" {{ button.outerclasses }}">{% endif %}
|
||||
{% if button.url %}
|
||||
<a href="{{ button.url starts with 'http' ? button.url : base_url ~ button.url }}">
|
||||
{% endif %}
|
||||
<button
|
||||
{% if button.id %}id="{{ button.id }}"{% endif %}
|
||||
{% block button_classes %}
|
||||
class="{{ form_button_classes ?: 'button' }} {{ button.classes }}"
|
||||
{% endblock %}
|
||||
{% if button.disabled %}disabled="disabled"{% endif %}
|
||||
|
||||
type="{{ button.type|default('submit') }}"
|
||||
|
||||
{% if button.task %}
|
||||
name="task" value="{{ button.task }}"
|
||||
{% endif %}
|
||||
>
|
||||
{% if button.html %}
|
||||
{{ button.value|t|default('Submit')|raw }}
|
||||
{% else %}
|
||||
{{ button.value|t|default('Submit') }}
|
||||
{% endif %}
|
||||
</button>
|
||||
{% if button.url %}
|
||||
</a>
|
||||
{% endif %}
|
||||
{% if button.outerclasses is defined %}</div>{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
{% set override_inner_markup_buttons_end %}
|
||||
{% block inner_markup_buttons_end %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
{% endset %}
|
||||
|
||||
{% include 'forms/fields/uniqueid/uniqueid.html.twig' %}
|
||||
{# Embed for HTML layout #}
|
||||
{% embed 'forms/layouts/form.html.twig' %}
|
||||
|
||||
{% block embed_form_core %}
|
||||
name="{{ form.name }}"
|
||||
action="{{ action }}"
|
||||
method="{{ method }}"{{ multipart|raw }}
|
||||
{% if form.id %}id="{{ form.id }}"{% endif %}
|
||||
{% if form.novalidate %}novalidate{% endif %}
|
||||
{% if form.keep_alive %}data-grav-keepalive="true"{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block embed_form_classes -%}
|
||||
class="{{ parent() }} {{ override_form_classes|trim }}"
|
||||
{%- endblock %}
|
||||
|
||||
{% block embed_fields %}
|
||||
{{ override_inner_markup_fields_start|raw }}
|
||||
{{ override_inner_markup_fields|raw }}
|
||||
|
||||
{% include "forms/fields/formname/formname.html.twig" %}
|
||||
{% include "forms/fields/formtask/formtask.html.twig" %}
|
||||
{% include 'forms/fields/uniqueid/uniqueid.html.twig' %}
|
||||
{{ nonce_field(form.getNonceAction() ?? 'form', form.getNonceName() ?? 'form-nonce')|raw }}
|
||||
|
||||
{{ override_inner_markup_fields_end|raw }}
|
||||
{% endblock %}
|
||||
|
||||
{% block embed_buttons %}
|
||||
{{ override_inner_markup_buttons_start|raw }}
|
||||
|
||||
{% for button in form.buttons %}
|
||||
{% if button.outerclasses is defined %}<div class="{{ button.outerclasses }}">{% endif %}
|
||||
|
||||
{% if button.url %}
|
||||
{% set button_url = button.url starts with 'http' ? button.url : base_url ~ button.url %}
|
||||
{% endif %}
|
||||
|
||||
{% embed 'forms/layouts/button.html.twig' %}
|
||||
{% block embed_button_core %}
|
||||
{% if button.id %}id="{{ button.id }}"{% endif %}
|
||||
{% if button.disabled %}disabled="disabled"{% endif %}
|
||||
{% if button.name %}
|
||||
name="{{ button.name }}"
|
||||
{% else %}
|
||||
{% if button.task %}name="task" value="{{ button.task }}"{% endif %}
|
||||
{% endif %}
|
||||
type="{{ button.type|default('submit') }}"
|
||||
{% endblock %}
|
||||
|
||||
{% block embed_button_classes %}
|
||||
{% block button_classes %}
|
||||
class="{{ form_button_classes ?: 'button' }} {{ button.classes }}"
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
|
||||
{% block embed_button_content -%}
|
||||
{%- set button_value = button.value|t|default('Submit') -%}
|
||||
{%- if button.html -%}
|
||||
{{- button_value|trim|raw -}}
|
||||
{%- else -%}
|
||||
{{- button_value|trim|e -}}
|
||||
{%- endif -%}
|
||||
{%- endblock %}
|
||||
|
||||
{% endembed %}
|
||||
|
||||
{% if button.outerclasses is defined %}</div>{% endif %}
|
||||
{% endfor %}
|
||||
|
||||
{{ override_inner_markup_buttons_end }}
|
||||
{% endblock %}
|
||||
|
||||
{% endembed %}
|
||||
|
||||
{{ nonce_field(form.getNonceAction() ?? 'form', form.getNonceName() ?? 'form-nonce')|raw }}
|
||||
</form>
|
||||
|
||||
{% if config.forms.dropzone.enabled %}
|
||||
<div id="dropzone-template" style="display:none;">
|
||||
|
||||
@@ -3,8 +3,8 @@
|
||||
{% block field %}
|
||||
{% set avatar = form.value('avatar') %}
|
||||
{% if avatar %}
|
||||
<label><img style="max-width:200px;" src="{{ base_url_simple ~ '/' ~ (avatar|first).path }}" /></label>
|
||||
<label class="{{ field.classes }}"><img class="{{ field.img_classes }}" style="max-width:200px;" src="{{ base_url_simple ~ '/' ~ (avatar|first).path }}" /></label>
|
||||
{% else %}
|
||||
<label><img src="https://www.gravatar.com/avatar/{{ form.value('email')|md5 }}?s=200" /></label>
|
||||
<label class="{{ field.classes }}"><img class="{{ field.img_classes }}" src="https://www.gravatar.com/avatar/{{ form.value('email')|md5 }}?s=200" /></label>
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
|
||||
@@ -10,11 +10,11 @@
|
||||
|
||||
{% block input %}
|
||||
{% if not site_key %}
|
||||
<script>console && console.error('site_key was not defined for form "{{ form.name }}" (Grav Form Plugin)')</script>
|
||||
<script type="application/javascript">console && console.error('site_key was not defined for form "{{ form.name }}" (Grav Form Plugin)')</script>
|
||||
{% elseif config.plugins.form.recaptcha.version == 3 %}
|
||||
{#{% do assets.addJs('https://www.google.com/recaptcha/api.js?render='~site_key) %}#}
|
||||
<script src='https://www.google.com/recaptcha/api.js?render={{ site_key }}&theme={{ theme }}'></script>
|
||||
<script>
|
||||
{% do assets.addJs('https://www.google.com/recaptcha/api.js?render='~site_key~'&theme=' ~ theme) %}
|
||||
{#<script src='https://www.google.com/recaptcha/api.js?render={{ site_key }}&theme={{ theme }}'></script>#}
|
||||
<script type="application/javascript">
|
||||
(document.querySelectorAll('form') || []).forEach(function(form, index) {
|
||||
var submit = function(event) {
|
||||
event.preventDefault();
|
||||
@@ -42,7 +42,7 @@
|
||||
});
|
||||
</script>
|
||||
{% elseif config.plugins.form.recaptcha.version == '2-invisible' %}
|
||||
<script>
|
||||
<script type="application/javascript">
|
||||
function captchaOnloadCallback_{{ formName }}() {
|
||||
var form = document.querySelector('form#{{ form.id }}');
|
||||
var submits = form.querySelectorAll('[type="submit"]') || [];
|
||||
@@ -75,7 +75,7 @@
|
||||
<script src="https://www.google.com/recaptcha/api.js?onload=captchaOnloadCallback_{{ formName }}&hl={{ grav.language.language }}&theme={{ theme }}"
|
||||
async defer></script>
|
||||
{% else %}
|
||||
<script>
|
||||
<script type="application/javascript">
|
||||
var captchaOnloadCallback_{{ formName }} = function captchaOnloadCallback_{{ formName }}() {
|
||||
grecaptcha.render('g-recaptcha-{{ formName }}', {
|
||||
'sitekey': "{{ site_key }}",
|
||||
|
||||
@@ -4,14 +4,14 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block input %}
|
||||
{% set id = field.id|default(field.name) ~ '-' ~ key %}
|
||||
{% set id = field.id|default(field.name)|hyphenize %}
|
||||
<div class="{{ form_field_wrapper_classes ?: 'form-input-wrapper' }} {{ field.size }} {{ field.wrapper_classes }}">
|
||||
<input
|
||||
{# required attribute structures #}
|
||||
name="{{ (scope ~ field.name)|fieldName }}"
|
||||
value="{{ value|join(', ') }}"
|
||||
value="{{ field.value ?? '1' }}"
|
||||
type="checkbox"
|
||||
{% if value == true %} checked="checked" {% endif %}
|
||||
{% if value == field.value ?? '1' %} checked="checked" {% endif %}
|
||||
|
||||
{# input attribute structures #}
|
||||
{% block input_attributes %}
|
||||
@@ -22,6 +22,7 @@
|
||||
{% if field.autofocus in ['on', 'true', 1] %}autofocus="autofocus"{% endif %}
|
||||
{% if field.novalidate in ['on', 'true', 1] %}novalidate="novalidate"{% endif %}
|
||||
{% if required %}required="required"{% endif %}
|
||||
{% if field.tabindex %}tabindex="{{ field.tabindex }}"{% endif %}
|
||||
{% endblock %}
|
||||
/>
|
||||
<label style="display:inline;" class="inline" for="{{ id|e }}">
|
||||
|
||||
@@ -15,7 +15,7 @@
|
||||
{% block input %}
|
||||
{% for key, text in field.options %}
|
||||
|
||||
{% set id = field.id|default(field.name) ~ '-' ~ key %}
|
||||
{% set id = field.id|default(field.name)|hyphenize ~ '-' ~ key %}
|
||||
{% set name = field.use == 'keys' ? key : id %}
|
||||
{% set val = field.use == 'keys' ? '1' : key %}
|
||||
{% set checked = (field.use == 'keys' ? value[key] : key in value) %}
|
||||
|
||||
@@ -4,7 +4,7 @@
|
||||
<div class="form-input-wrapper {{ field.size }}">
|
||||
<input
|
||||
type="text"
|
||||
value="{{ value|e('html_attr')|join(', ') }}"
|
||||
value="{{ value|join(', ') }}"
|
||||
data-key-observe="{{ (scope ~ field.name)|fieldName }}"
|
||||
{% block input_attributes %}
|
||||
{% if field.classes is defined %}class="{{ field.classes }}" {% endif %}
|
||||
@@ -16,6 +16,7 @@
|
||||
{% if field.novalidate in ['on', 'true', 1] %}novalidate="novalidate"{% endif %}
|
||||
{% if field.readonly in ['on', 'true', 1] %}readonly="readonly"{% endif %}
|
||||
{% if field.autocomplete in ['on', 'off'] %}autocomplete="{{ field.autocomplete }}"{% endif %}
|
||||
{% if field.tabindex %}tabindex="{{ field.tabindex }}"{% endif %}
|
||||
{% if field.validate.required in ['on', 'true', 1] %}required="required"{% endif %}
|
||||
{% if field.validate.pattern %}pattern="{{ field.validate.pattern }}"{% endif %}
|
||||
{% if field.validate.message %}title="{{ field.validate.message|e|t }}"
|
||||
@@ -23,4 +24,4 @@
|
||||
{% endblock %}
|
||||
/>
|
||||
</div>
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
|
||||
@@ -1,5 +1,7 @@
|
||||
{% extends "forms/field.html.twig" %}
|
||||
|
||||
{% set value = null %}
|
||||
|
||||
{% block input_attributes %}
|
||||
type="password"
|
||||
{{ parent() }}
|
||||
|
||||
@@ -16,6 +16,7 @@
|
||||
{% if key == value %}checked="checked" {% endif %}
|
||||
{% if field.disabled or isDisabledToggleable %}disabled="disabled"{% endif %}
|
||||
{% if required %}required="required"{% endif %}
|
||||
{% if field.tabindex %}tabindex="{{ field.tabindex }}"{% endif %}
|
||||
/>
|
||||
<label style="display: inline" class="inline" for="{{ id|e }}">{{ text|t|raw }}</label>
|
||||
</div>
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
{% if required %}required="required"{% endif %}
|
||||
{% if field.multiple in ['on', 'true', 1] %}multiple="multiple"{% endif %}
|
||||
{% if field.disabled or isDisabledToggleable %}disabled="disabled"{% endif %}
|
||||
{% if field.tabindex %}tabindex="{{ field.tabindex }}"{% endif %}
|
||||
{% if field.form %}form="{{ field.form }}"{% endif %}
|
||||
{% if field.key %}
|
||||
data-key-observe="{{ (scope ~ field.name)|fieldName }}"
|
||||
@@ -46,14 +47,15 @@
|
||||
{{ avalue|raw }}
|
||||
</option>
|
||||
{% elseif item_value is iterable %}
|
||||
<optgroup label="{{ key }}">
|
||||
{%for subkey, suboption in item_value %}
|
||||
{% set selected = field.selectize ? suboption : subkey %}
|
||||
{% set item_value = field.selectize and field.multiple ? suboption : subkey %}
|
||||
<option {% if subkey == value or (field.multiple and selected in value) %}selected="selected"{% endif %} value="{{ suboption }}">
|
||||
{{ suboption|t|raw }}
|
||||
</option>
|
||||
{% endfor %}
|
||||
{% set optgroup_label = item_value|keys|first %}
|
||||
<optgroup label="{{ optgroup_label }}">
|
||||
{% for subkey, suboption in field.options[key][optgroup_label] %}
|
||||
{% set selected = field.selectize ? suboption : subkey %}
|
||||
{% set item_value = field.selectize and field.multiple ? suboption : subkey %}
|
||||
<option {% if subkey == value or (field.multiple and selected in value) %}selected="selected"{% endif %} value="{{ suboption }}">
|
||||
{{ suboption|t|raw }}
|
||||
</option>
|
||||
{% endfor %}
|
||||
</optgroup>
|
||||
{% else %}
|
||||
{% set selected = field.selectize ? item_value : key %}
|
||||
|
||||
@@ -1,42 +1,2 @@
|
||||
{% extends "forms/field.html.twig" %}
|
||||
|
||||
{% block global_attributes %}
|
||||
data-grav-selectize="{{ (field.selectize is defined ? field.selectize : {})|json_encode()|e('html_attr') }}"
|
||||
{{ parent() }}
|
||||
{% endblock %}
|
||||
|
||||
{% block input %}
|
||||
<div class="{{ form_field_wrapper_classes ?: 'form-select-wrapper' }} {{ field.size }} {{ field.wrapper_classes }}">
|
||||
<select name="{{ (scope ~ field.name)|fieldName ~ (field.multiple ? '[]' : '') }}"
|
||||
class="{{ form_field_select_classes }} {{ field.classes }}"
|
||||
{% if field.id is defined %}id="{{ field.id|e }}" {% endif %}
|
||||
{% if field.style is defined %}style="{{ field.style|e }}" {% endif %}
|
||||
{% if field.disabled %}disabled="disabled"{% endif %}
|
||||
{% if field.autofocus in ['on', 'true', 1] %}autofocus="autofocus"{% endif %}
|
||||
{% if field.novalidate in ['on', 'true', 1] %}novalidate="novalidate"{% endif %}
|
||||
{% if required %}required="required"{% endif %}
|
||||
{% if field.multiple in ['on', 'true', 1] %}multiple="multiple"{% endif %}
|
||||
{% if field.disabled or isDisabledToggleable %}disabled="disabled"{% endif %}
|
||||
{% if field.form %}form="{{ field.form }}"{% endif %}
|
||||
{% if field.key %}
|
||||
data-key-observe="{{ (scope ~ field.name)|fieldName }}"
|
||||
{% endif %}
|
||||
>
|
||||
{% if field.placeholder %}<option value="" disabled selected>{{ field.placeholder|t|raw }}</option>{% endif %}
|
||||
|
||||
{% for key, optgroup in field.options %}
|
||||
{% set optgroup_label = optgroup|keys|first %}
|
||||
|
||||
<optgroup label="{{ optgroup_label }}">
|
||||
{%for subkey, suboption in field.options[key][optgroup_label] %}
|
||||
{% set selected = field.selectize ? suboption : subkey %}
|
||||
{% set item_value = field.selectize and field.multiple ? suboption : subkey %}
|
||||
<option {% if subkey == value or (field.multiple and selected in value) %}selected="selected"{% endif %} value="{{ suboption }}">
|
||||
{{ suboption|t|raw }}
|
||||
</option>
|
||||
{% endfor %}
|
||||
</optgroup>
|
||||
{% endfor %}
|
||||
</select>
|
||||
</div>
|
||||
{% endblock %}
|
||||
{# Deprecated Form 4.0: Just use `select` field #}
|
||||
{% extends "forms/fields/select/select.html.twig" %}
|
||||
|
||||
@@ -15,11 +15,11 @@
|
||||
{% set tabs = tabs|merge([tab]) %}
|
||||
{% endif %}
|
||||
{% endfor %}
|
||||
{% set count = tabs|count %}
|
||||
{% set count = tabs|length %}
|
||||
|
||||
{% if count == 0 %}
|
||||
{# Nothing to display #}
|
||||
{% elseif count == 1 %}
|
||||
{% elseif count == 1 and not admin %}
|
||||
{% for field in (tabs|first).fields %}
|
||||
{% if field.type %}
|
||||
{% set value = field.name ? (form ? form.value(field.name) : data.value(field.name)) : data.toArray %}
|
||||
@@ -52,10 +52,10 @@
|
||||
</div>
|
||||
<div class="tabs-content">
|
||||
{% embed 'forms/default/fields.html.twig' with {name: field.name, fields: field.fields} %}
|
||||
{% block field_open %}
|
||||
{% block inner_markup_field_open %}
|
||||
<div id="tab-{{ tabsKey ~ loop.index }}" class="tab__content {{ (storedTab == scope ~ field.name) or active == loop.index ? 'active' : '' }}">
|
||||
{% endblock %}
|
||||
{% block field_close %}
|
||||
{% block inner_markup_field_close %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
{% endembed %}
|
||||
|
||||
@@ -1,3 +1,7 @@
|
||||
{% if field.prepend or field.append or field.copy_to_clipboard %}
|
||||
{% set field = field|merge({'wrapper_classes': 'form-input-addon-wrapper'}) %}
|
||||
{% endif %}
|
||||
|
||||
{% extends "forms/field.html.twig" %}
|
||||
|
||||
{% block prepend %}
|
||||
@@ -19,7 +23,6 @@
|
||||
{% block append %}
|
||||
{% if field.copy_to_clipboard %}
|
||||
<div class="form-input-addon form-input-append copy-to-clipboard">
|
||||
{{ dump(field.copy_to_clipboard|t|raw) }}
|
||||
{% if field.copy_to_clipboard in ['0', '1'] %}
|
||||
<i class="fa fa-clipboard"></i>
|
||||
{% else %}
|
||||
@@ -33,9 +36,4 @@
|
||||
{% endif %}
|
||||
{% endblock %}
|
||||
|
||||
{% block input %}
|
||||
{% if field.prepend or field.append or field.copy_to_clipboard %}
|
||||
{% set field = field|merge({'wrapper_classes': 'form-input-addon-wrapper'}) %}
|
||||
{% endif %}
|
||||
{{ parent() }}
|
||||
{% endblock %}
|
||||
|
||||
|
||||
@@ -17,6 +17,7 @@
|
||||
{% if field.novalidate in ['on', 'true', 1] %}novalidate="novalidate"{% endif %}
|
||||
{% if field.readonly in ['on', 'true', 1] %}readonly="readonly"{% endif %}
|
||||
{% if field.autocomplete in ['on', 'off'] %}autocomplete="{{ field.autocomplete }}"{% endif %}
|
||||
{% if field.tabindex %}tabindex="{{ field.tabindex }}"{% endif %}
|
||||
{% if required %}required="required"{% endif %}
|
||||
{% if field.validate.pattern %}pattern="{{ field.validate.pattern }}"{% endif %}
|
||||
{% if field.validate.message %}title="{{ field.validate.message|t|e }}"{% endif %}
|
||||
|
||||
@@ -7,9 +7,6 @@
|
||||
|
||||
{% import _self as macro %}
|
||||
|
||||
{% set value = value ?? field.default %}
|
||||
{% set value = (value is same as(false) ? 0 : value) %}
|
||||
|
||||
{% set has_hidden = false %}
|
||||
{% for key, text in field.options %}
|
||||
{% if key is empty %}
|
||||
@@ -23,6 +20,12 @@
|
||||
{% endblock %}
|
||||
|
||||
{% block input %}
|
||||
{% set value = (value is same as(false) ? 0 : value) %}
|
||||
|
||||
{% if field.force_bool and get_type(value) == 'string'%}
|
||||
{% set value = true %}
|
||||
{% endif %}
|
||||
|
||||
|
||||
<div class="switch-toggle switch-grav {{ field.size }} switch-{{ field.options|length }} {{ field.classes }}">
|
||||
{% set maxLen = 0 %}
|
||||
@@ -55,6 +58,7 @@
|
||||
{% endif %}
|
||||
{% endif %}
|
||||
{% if field.validate.required in ['on', 'true', 1] %}required="required"{% endif %}
|
||||
{% if field.tabindex %}tabindex="{{ field.tabindex }}"{% endif %}
|
||||
/>
|
||||
<label for="{{ id }}">{{ (macro.spanToggle(translation, maxLen)|trim)|raw }}</label>
|
||||
{% endfor %}
|
||||
|
||||
@@ -1 +1 @@
|
||||
<a href="{{ url(value) }}" target="_blank"><i class="fa fa-link"></i>{{ value|e }}</a>
|
||||
<a href="{{ url(value) }}" target="_blank"><i class="fa fa-link"></i> {{ value|e }}</a>
|
||||
|
||||
@@ -0,0 +1,12 @@
|
||||
{% set button_tag %}
|
||||
<button
|
||||
{% block embed_button_core %}{% endblock %}
|
||||
{% block embed_button_classes %}{% endblock %}
|
||||
>{%- block embed_button_content -%}{%- endblock -%}</button>
|
||||
{% endset %}
|
||||
|
||||
{% if button_url %}
|
||||
<a href="{{ button_url|e }}">{{ button_tag|trim|raw }}</a>
|
||||
{% else %}
|
||||
{{ button_tag|trim|raw }}
|
||||
{% endif %}
|
||||
@@ -0,0 +1 @@
|
||||
{% block field_input_classes %}{% endblock %}
|
||||
@@ -0,0 +1,52 @@
|
||||
{% block field %}
|
||||
<div class="form-field {{ layout_form_field_outer_classes|trim -}} {{- form_field_outer_core|trim -}}">
|
||||
{% block contents %}
|
||||
{% if show_label %}
|
||||
<div class="{{- layout_form_field_outer_label_classes -}}">
|
||||
{{- form_field_toggleable -}}
|
||||
<label class="{{ layout_form_field_label_classes }}{{ form_field_label_trim }}" {% if field.id %}for="{{ form_field_for }}"{% endif %}>
|
||||
{%- block label -%}
|
||||
{%- if form_field_help -%}
|
||||
<span class="tooltip" data-tooltip="{{ form_field_help|e }}">{{ form_field_label|raw }}</span>
|
||||
{%- else -%}
|
||||
{{ form_field_label|raw }}
|
||||
{%- endif -%}
|
||||
{%- if form_field_required %}
|
||||
<span class="required">*</span>
|
||||
{%- endif -%}
|
||||
{%- endblock -%}
|
||||
</label>
|
||||
</div>
|
||||
{% endif %}
|
||||
<div class="{{ layout_form_field_outer_data_classes }}"
|
||||
{% block global_attributes %}{% endblock %}
|
||||
>
|
||||
{% block group %}
|
||||
{% block input %}
|
||||
<div class="{{ layout_form_field_wrapper_classes }} {{ field.size }}">
|
||||
{% block prepend %}{% endblock prepend %}
|
||||
<input
|
||||
name="{{ (scope ~ field.name)|fieldName }}"
|
||||
value="{{ value|join(', ')|e }}"
|
||||
{% block input_attributes %}{% endblock %}
|
||||
/>
|
||||
{% block append %}{% endblock append %}
|
||||
{% if inline_errors and errors %}
|
||||
<div class="{{ form_field_inline_error_classes }}">
|
||||
<p class="form-message"><i class="fa fa-exclamation-circle"></i> {{ errors|first|raw }}</p>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
{% endblock %}
|
||||
{% if field.description is defined %}
|
||||
<div class="{{ form_field_extra_wrapper_classes }}">
|
||||
<span class="form-description">
|
||||
{{ form_field_description|raw }}
|
||||
</span>
|
||||
</div>
|
||||
{% endif %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
</div>
|
||||
{% endblock %}
|
||||
@@ -0,0 +1,7 @@
|
||||
<form
|
||||
{% block embed_form_core %}{% endblock %}
|
||||
{% block embed_form_classes %}{% endblock %}
|
||||
>
|
||||
{% block embed_fields %}{% endblock %}
|
||||
{% block embed_buttons %}{% endblock %}
|
||||
</form>
|
||||
+2
-2
@@ -279,7 +279,7 @@ class ClassLoader
|
||||
*/
|
||||
public function setApcuPrefix($apcuPrefix)
|
||||
{
|
||||
$this->apcuPrefix = function_exists('apcu_fetch') && filter_var(ini_get('apc.enabled'), FILTER_VALIDATE_BOOLEAN) ? $apcuPrefix : null;
|
||||
$this->apcuPrefix = function_exists('apcu_fetch') && ini_get('apc.enabled') ? $apcuPrefix : null;
|
||||
}
|
||||
|
||||
/**
|
||||
@@ -377,7 +377,7 @@ class ClassLoader
|
||||
$subPath = $class;
|
||||
while (false !== $lastPos = strrpos($subPath, '\\')) {
|
||||
$subPath = substr($subPath, 0, $lastPos);
|
||||
$search = $subPath . '\\';
|
||||
$search = $subPath.'\\';
|
||||
if (isset($this->prefixDirsPsr4[$search])) {
|
||||
$pathEnd = DIRECTORY_SEPARATOR . substr($logicalPathPsr4, $lastPos + 1);
|
||||
foreach ($this->prefixDirsPsr4[$search] as $dir) {
|
||||
|
||||
@@ -1,7 +1,7 @@
|
||||
var webpack = require('webpack'),
|
||||
path = require('path'),
|
||||
UglifyJsPlugin = require('uglifyjs-webpack-plugin'),
|
||||
isProd = process.env.NODE_ENV === 'production' || process.env.NODE_ENV === 'production-wip';
|
||||
var webpack = require('webpack');
|
||||
var path = require('path');
|
||||
var UglifyJsPlugin = require('uglifyjs-webpack-plugin');
|
||||
var isProd = process.env.NODE_ENV === 'production' || process.env.NODE_ENV === 'production-wip';
|
||||
|
||||
module.exports = {
|
||||
entry: {
|
||||
@@ -57,7 +57,7 @@ module.exports = {
|
||||
loader: 'babel-loader',
|
||||
exclude: /node_modules/,
|
||||
query: {
|
||||
presets: ['es2015', 'stage-3']
|
||||
presets: ['@babel/preset-env']
|
||||
}
|
||||
}
|
||||
]
|
||||
|
||||
+3525
-2254
File diff suppressed because it is too large
Load Diff
Reference in New Issue
Block a user