drowl_paragraphs_bs-1.x-dev/src/Plugin/Field/FieldWidget/DrowlParagraphsBsSettingsDefaultWidget.php
src/Plugin/Field/FieldWidget/DrowlParagraphsBsSettingsDefaultWidget.php
<?php
namespace Drupal\drowl_paragraphs_bs\Plugin\Field\FieldWidget;
use Drupal\Core\Config\ConfigFactoryInterface;
use Drupal\Core\Field\FieldDefinitionInterface;
use Drupal\Core\Field\FieldItemListInterface;
use Drupal\Core\Field\WidgetBase;
use Drupal\Core\Form\FormStateInterface;
use Drupal\Core\Plugin\ContainerFactoryPluginInterface;
use Symfony\Component\DependencyInjection\ContainerInterface;
/**
* Field widget "drowl_paragraphs_bs_settings_default".
*
* @FieldWidget(
* id = "drowl_paragraphs_bs_settings_default",
* label = @Translation("DROWL Paragraphs for Bootstrap settings default"),
* field_types = {
* "drowl_paragraphs_bs_settings",
* }
* )
*/
class DrowlParagraphsBsSettingsDefaultWidget extends WidgetBase implements ContainerFactoryPluginInterface {
/**
* The config factory.
*
* @var \Drupal\Core\Config\ConfigFactoryInterface
*/
protected $configFactory;
/**
* {@inheritdoc}
*/
public function __construct($plugin_id, $plugin_definition, FieldDefinitionInterface $field_definition, array $settings, array $third_party_settings, ConfigFactoryInterface $config_factory) {
parent::__construct($plugin_id, $plugin_definition, $field_definition, $settings, $third_party_settings);
$this->configFactory = $config_factory;
}
/**
* {@inheritdoc}
*/
public static function create(ContainerInterface $container, array $configuration, $plugin_id, $plugin_definition) {
return new static($plugin_id, $plugin_definition, $configuration['field_definition'], $configuration['settings'], $configuration['third_party_settings'], $container->get('config.factory'));
}
/**
* {@inheritdoc}
*/
public static function defaultSettings() {
return [
'open' => FALSE,
] + parent::defaultSettings();
}
/**
* {@inheritdoc}
*/
public function settingsForm(array $form, FormStateInterface $form_state) {
$element = parent::settingsForm($form, $form_state);
$element['open'] = [
'#type' => 'checkbox',
'#title' => $this->t('Display element open by default.'),
'#default_value' => $this->getSetting('open'),
];
return $element;
}
/**
* {@inheritdoc}
*/
public function settingsSummary() {
$summary = parent::settingsSummary();
if ($this->getSetting('open')) {
$summary[] = $this->t('Display element open by default.');
}
else {
$summary[] = $this->t('Display element closed by default.');
}
return $summary;
}
/**
* {@inheritdoc}
*/
public function formElement(FieldItemListInterface $items, $delta, array $element, array &$form, FormStateInterface $form_state) {
// $item is where the current saved values are stored.
$item = &$items[$delta];
// ===================================
// Styling group
// ===================================
$element['animations'] = [
'#type' => 'details',
'#title' => $this->t('Animations'),
'#group' => 'style',
'#group_name' => 'style',
'#description' => $this->t('<i class="fa fa-info-circle" aria-hidden="true"></i> <strong>Help:</strong> Set animations for this container, based on specific events.'),
];
$animations_allowed_count = 4;
for ($i = 1; $i <= $animations_allowed_count; $i++) {
$element['animations']['style_animation_' . $i] = [
'#type' => 'details',
'#title' => $this->t('Animation') . ' ' . $i,
];
$element['animations']['style_animation_' . $i]['style_animation_' . $i . '_events'] = [
'#type' => 'select',
'#title' => $this->t('Event trigger'),
'#options' => [
'enter-viewport' => $this->t('Entering the viewport'),
'leave-viewport' => $this->t('Leaving the viewport'),
'hover' => $this->t('Hover the element.'),
],
'#required' => FALSE,
'#multiple' => FALSE,
'#empty_option' => $this->t('- None -'),
'#default_value' => $item->{'style_animation_' . $i . '_events'} ?? '',
'#description' => '<ul>
<li><strong>' . $this->t('Entering the viewport') . ':</strong> ' . $this->t('Animates if the element enters the viewport (by scrolling).') . '</li>
<li><strong>' . $this->t('Leaving the viewport') . ':</strong> ' . $this->t('Animates if the element leaves the viewport (by scrolling).') . '</li>
<li><strong>' . $this->t('Hover the element') . ':</strong> ' . $this->t('Animation starts when entering the element with the cursor.') . '</li>
</ul>',
'#wrapper_attributes' => ['class' => 'form-item--style-animation-events'],
];
$element['animations']['style_animation_' . $i]['style_animation_' . $i . '_offset'] = [
'#type' => 'select',
'#title' => $this->t('Viewport animation event trigger offset'),
'#options' => [
'0' => '0',
'10' => $this->t('@percent% visible', ['@percent' => '10']),
'20' => $this->t('@percent% visible', ['@percent' => '20']),
'30' => $this->t('@percent% visible', ['@percent' => '30']),
'40' => $this->t('@percent% visible', ['@percent' => '40']),
'50' => $this->t('@percent% visible', ['@percent' => '50']),
'60' => $this->t('@percent% visible', ['@percent' => '60']),
'70' => $this->t('@percent% visible', ['@percent' => '70']),
'80' => $this->t('@percent% visible', ['@percent' => '80']),
'90' => $this->t('@percent% visible', ['@percent' => '90']),
'100' => $this->t('@percent% visible', ['@percent' => '100']),
],
'#default_value' => $item->{'style_animation_' . $i . '_offset'} ?: 0,
'#empty_option' => $this->t('- None -'),
'#empty_value' => 0,
'#required' => FALSE,
'#description' => $this->t('Entering the viewport') . '/' . $this->t('Leaving the viewport') . ': ' . $this->t('Offset for the animation to start if the element is visible for x %.'),
// @todo We'd need a selector to work on ancestor elements only:
// '#states' => [
// 'visible' => [
// 'select[name$="[style][animations][style_animation_' . $i . '][style_animation_' . $i . '_events]"]:first' => [
// 'value' => [
// 'enter-viewport',
// 'leave-viewport',
// ],
// ],
// ],
// ],.
'#wrapper_attributes' => ['class' => 'form-item--style-animation-offset'],
];
$element['animations']['style_animation_' . $i]['style_animation_' . $i . '_animation'] = [
'#type' => 'select',
'#title' => $this->t('Animation'),
'#options' => [
$this->t('Attention Seekers')->__toString() => [
'bounce' => $this->t('bounce'),
'flash' => $this->t('flash'),
'pulse' => $this->t('pulse'),
'rubberBand' => $this->t('rubberBand'),
'shake' => $this->t('shake'),
'swing' => $this->t('swing'),
'tada' => $this->t('tada'),
'wobble' => $this->t('wobble'),
'jello' => $this->t('jello'),
],
$this->t('Bouncing Entrances')->__toString() => [
'bounceIn' => $this->t('bounceIn'),
'bounceInDown' => $this->t('bounceInDown'),
'bounceInLeft' => $this->t('bounceInLeft'),
'bounceInRight' => $this->t('bounceInRight'),
'bounceInUp' => $this->t('bounceInUp'),
],
$this->t('Bouncing Exits')->__toString() => [
'bounceOut' => $this->t('bounceOut'),
'bounceOutDown' => $this->t('bounceOutDown'),
'bounceOutLeft' => $this->t('bounceOutLeft'),
'bounceOutRight' => $this->t('bounceOutRight'),
'bounceOutUp' => $this->t('bounceOutUp'),
],
$this->t('Fading Entrances')->__toString() => [
'fadeIn' => $this->t('fadeIn'),
'fadeInDown' => $this->t('fadeInDown'),
'fadeInDownBig' => $this->t('fadeInDownBig'),
'fadeInLeft' => $this->t('fadeInLeft'),
'fadeInLeftBig' => $this->t('fadeInLeftBig'),
'fadeInRight' => $this->t('fadeInRight'),
'fadeInRightBig' => $this->t('fadeInRightBig'),
'fadeInUp' => $this->t('fadeInUp'),
'fadeInUpBig' => $this->t('fadeInUpBig'),
],
$this->t('Fading Exits')->__toString() => [
'fadeOut' => $this->t('fadeOut'),
'fadeOutDown' => $this->t('fadeOutDown'),
'fadeOutDownBig' => $this->t('fadeOutDownBig'),
'fadeOutLeft' => $this->t('fadeOutLeft'),
'fadeOutLeftBig' => $this->t('fadeOutLeftBig'),
'fadeOutRight' => $this->t('fadeOutRight'),
'fadeOutRightBig' => $this->t('fadeOutRightBig'),
'fadeOutUp' => $this->t('fadeOutUp'),
'fadeOutUpBig' => $this->t('fadeOutUpBig'),
],
$this->t('Flippers')->__toString() => [
'flip' => $this->t('flip'),
'flipInX' => $this->t('flipInX'),
'flipInY' => $this->t('flipInY'),
'flipOutX' => $this->t('flipOutX'),
'flipOutY' => $this->t('flipOutY'),
],
$this->t('Lightspeed')->__toString() => [
'lightSpeedIn' => $this->t('lightSpeedIn'),
'lightSpeedOut' => $this->t('lightSpeedOut'),
],
$this->t('Rotating Entrances')->__toString() => [
'rotateIn' => $this->t('rotateIn'),
'rotateInDownLeft' => $this->t('rotateInDownLeft'),
'rotateInDownRight' => $this->t('rotateInDownRight'),
'rotateInUpLeft' => $this->t('rotateInUpLeft'),
'rotateInUpRight' => $this->t('rotateInUpRight'),
],
$this->t('Rotating Exits')->__toString() => [
'rotateOut' => $this->t('rotateOut'),
'rotateOutDownLeft' => $this->t('rotateOutDownLeft'),
'rotateOutDownRight' => $this->t('rotateOutDownRight'),
'rotateOutUpLeft' => $this->t('rotateOutUpLeft'),
'rotateOutUpRight' => $this->t('rotateOutUpRight'),
],
$this->t('Sliding Entrances')->__toString() => [
'slideInUp' => $this->t('slideInUp'),
'slideInDown' => $this->t('slideInDown'),
'slideInLeft' => $this->t('slideInLeft'),
'slideInRight' => $this->t('slideInRight'),
],
$this->t('Sliding Exits')->__toString() => [
'slideOutUp' => $this->t('slideOutUp'),
'slideOutDown' => $this->t('slideOutDown'),
'slideOutLeft' => $this->t('slideOutLeft'),
'slideOutRight' => $this->t('slideOutRight'),
],
$this->t('Zoom Entrances')->__toString() => [
'zoomIn' => $this->t('zoomIn'),
'zoomInDown' => $this->t('zoomInDown'),
'zoomInLeft' => $this->t('zoomInLeft'),
'zoomInRight' => $this->t('zoomInRight'),
'zoomInUp' => $this->t('zoomInUp'),
],
$this->t('Zoom Exits')->__toString() => [
'zoomOut' => $this->t('zoomOut'),
'zoomOutDown' => $this->t('zoomOutDown'),
'zoomOutLeft' => $this->t('zoomOutLeft'),
'zoomOutRight' => $this->t('zoomOutRight'),
'zoomOutUp' => $this->t('zoomOutUp'),
],
$this->t('Specials')->__toString() => [
'hinge' => $this->t('hinge'),
'jackInTheBox' => $this->t('jackInTheBox'),
'rollIn' => $this->t('rollIn'),
'rollOut' => $this->t('rollOut'),
],
],
'#required' => FALSE,
'#multiple' => FALSE,
'#empty_option' => $this->t('- None -'),
'#default_value' => $item->{'style_animation_' . $i . '_animation'} ?? '',
'#description' => $this->t('Choose the animation to run on the event.' . '<br><a style="margin-left:0" class="button" href="https://daneden.github.io/animate.css/" target="_balnk">' . $this->t('Preview') . '</a>'),
// @todo We'd need a selector to work on ancestor elements only:
// '#states' => [
// 'visible' => [
// 'select[name$="[style][animations][style_animation_' . $i . '][style_animation_' . $i . '_events]"]:first' => ['filled' => TRUE],
// ],
// ],.
'#wrapper_attributes' => ['class' => 'form-item--style-animation-animation'],
];
$element['animations']['style_animation_' . $i]['style_animation_' . $i . '_delay'] = [
'#title' => t('Animation start delay'),
'#type' => 'number',
'#min' => '0',
'#step' => '1',
'#default_value' => $item->{'style_animation_' . $i . '_delay'} ?: 0,
// Empty number is not allowed.
'#required' => TRUE,
'#field_suffix' => 'ms',
'#description' => $this->t('Delay the animation start. Value in milliseconds (1000ms = 1s).'),
// @todo We'd need a selector to work on ancestor elements only:
// '#states' => [
// 'visible' => [
// 'select[name$="[style][animations][style_animation_' . $i . '][style_animation_' . $i . '_events]"]:first' => ['filled' => TRUE],
// ],
// ],.
'#wrapper_attributes' => ['class' => 'form-item--style-animation-delay'],
];
$element['animations']['style_animation_' . $i]['style_animation_' . $i . '_transition_duration'] = [
'#title' => t('Duration'),
'#type' => 'number',
'#min' => '0',
'#step' => '1',
'#default_value' => $item->{'style_animation_' . $i . '_transition_duration'} ?: 0,
// Empty number is not allowed.
'#required' => TRUE,
'#field_suffix' => 'ms',
'#description' => $this->t('Duration of the animation transition. Value in milliseconds (1000ms = 1s). 0 = Default duration.'),
// @todo We'd need a selector to work on ancestor elements only:
// '#states' => [
// 'visible' => [
// 'select[name$="[style][animations][style_animation_' . $i . '][style_animation_' . $i . '_events]"]:first' => ['filled' => TRUE],
// ],
// ],.
'#wrapper_attributes' => ['class' => 'form-item--style-animation-transition-duration'],
];
}
// ===================================
// Expert settings group
// ===================================
$element['equal_height_group'] = [
'#title' => t('Equal height group'),
'#type' => 'textfield',
'#default_value' => $item->equal_height_group ?? '',
'#description' => $this->t('Enter the name (unique identifier) of the group of items which should have an equal height.'),
'#wrapper_attributes' => ['class' => 'form-item--layout-equal_height_group'],
];
$element['classes_additional'] = [
'#title' => t('Classes'),
'#type' => 'textfield',
'#default_value' => $item->classes_additional ?? '',
'#description' => $this->t('<strong>Experts:</strong> Enter classes seperated by space (set on the Paragraph).'),
'#wrapper_attributes' => ['class' => 'form-item--classes-additional'],
];
$element['id_attr'] = [
'#title' => t('ID'),
'#type' => 'textfield',
'#default_value' => $item->id_attr ?? '',
'#description' => $this->t('<strong>Experts:</strong> Enter an ID attribute (set on the Paragraph).'),
'#wrapper_attributes' => ['class' => 'form-item--id-attr'],
];
// If cardinality is 1, ensure a label is output for the field by wrapping
// it in a details element.
if ($this->fieldDefinition->getFieldStorageDefinition()
->getCardinality() == 1) {
$element += [
'#type' => 'details',
'#open' => $this->getSetting('open') ? TRUE : FALSE,
];
}
return $element;
}
/**
* {@inheritDoc}
*/
public function massageFormValues(array $values, array $form, FormStateInterface $form_state) {
// Turn the nested array structure into a flat key => value array.
$values_flat = [];
if (!empty($values)) {
foreach ($values as $delta => $field) {
$it = new \RecursiveIteratorIterator(new \RecursiveArrayIterator($field));
foreach ($it as $k => $v) {
$values_flat[$delta][$k] = $v;
}
}
}
return $values_flat;
}
}
