class TextWithExpandCollapseButtonsFormatter in Formatter Suite 8
Formats text with expand/collapse buttons to show more/less.
Long text fields may have long text. When presented along with other content on the same page, the text can be overwhelming and make it hard to find the other content. This formatter temporarily shortens the long text to a specified height and adds an "Expand" button. Clicking the button expands the text display to full size, and adds a "Collapse" button. Clicking that button shortes the text again.
Plugin annotation
@FieldFormatter(
id = "formatter_suite_text_with_expand_collapse_buttons",
label = @Translation("Formatter Suite - Text with expand/collapse buttons"),
weight = 1000,
field_types = {
"text",
"text_long",
"text_with_summary",
"string_long"
}
)
Hierarchy
- class \Drupal\Component\Plugin\PluginBase implements DerivativeInspectionInterface, PluginInspectionInterface
- class \Drupal\Core\Plugin\PluginBase uses DependencySerializationTrait, MessengerTrait, StringTranslationTrait
- class \Drupal\Core\Field\PluginSettingsBase implements DependentPluginInterface, PluginSettingsInterface
- class \Drupal\Core\Field\FormatterBase implements FormatterInterface, ContainerFactoryPluginInterface
- class \Drupal\formatter_suite\Plugin\Field\FieldFormatter\TextWithExpandCollapseButtonsFormatter
- class \Drupal\Core\Field\FormatterBase implements FormatterInterface, ContainerFactoryPluginInterface
- class \Drupal\Core\Field\PluginSettingsBase implements DependentPluginInterface, PluginSettingsInterface
- class \Drupal\Core\Plugin\PluginBase uses DependencySerializationTrait, MessengerTrait, StringTranslationTrait
Expanded class hierarchy of TextWithExpandCollapseButtonsFormatter
File
- src/
Plugin/ Field/ FieldFormatter/ TextWithExpandCollapseButtonsFormatter.php, line 35
Namespace
Drupal\formatter_suite\Plugin\Field\FieldFormatterView source
class TextWithExpandCollapseButtonsFormatter extends FormatterBase {
/*---------------------------------------------------------------------
*
* Configuration.
*
*---------------------------------------------------------------------*/
/**
* {@inheritdoc}
*/
public static function defaultSettings() {
return [
'collapsedHeight' => '8em',
'expandButtonLabel' => t('Expand...'),
'collapseButtonLabel' => t('Collapse...'),
'animationDuration' => 500,
];
}
/**
* {@inheritdoc}
*/
public function settingsSummary() {
// Get current settings.
$collapsedHeight = $this
->getSetting('collapsedHeight');
$animationDuration = $this
->getSetting('animationDuration');
// Security: The animation duration is entered by an administrator.
// It should be a simple integer, with no other characters, HTML, or
// HTML entities.
//
// By parsing it as an integer, we ignore anything else and remove
// any security issues.
$animationDuration = intval($animationDuration);
// Security: The collapse height is entered by an administrator.
// It should be a number followed by CSS units, such as "px", "pt",
// or "em". It should not contain HTML or HTML entities.
//
// If integer parsing of the string yields a zero, then the string
// is assumed to be empty or invalid and collapsing is disabled.
// Otherwise the string is santized using an Html escape filter
// that escapes all HTML and HTML entities. If the admin enters these,
// the resulting string is not likely to work as a collapse height
// and the Javascript will not get a meaningful result, but it will
// still be safe.
$collapsedHeight = Html::escape($collapsedHeight);
$hasCollapseHeight = TRUE;
if (empty($collapsedHeight) === TRUE || $collapsedHeight === "0" || (int) $collapsedHeight === 0) {
$hasCollapseHeight = FALSE;
}
// Present.
$summary = parent::settingsSummary();
if ($hasCollapseHeight === FALSE) {
$summary[] = $this
->t('Disabled because no collapsed height set.');
}
else {
$summary[] = $this
->t('Shorten long text areas to @collapsedHeight.', [
'@collapsedHeight' => $collapsedHeight,
]);
if ($animationDuration > 0) {
$summary[] = $this
->t('Animate over @animationDuration milliseconds.', [
'@animationDuration' => $animationDuration,
]);
}
}
return $summary;
}
/*---------------------------------------------------------------------
*
* Settings form.
*
*---------------------------------------------------------------------*/
/**
* Returns a brief description of the formatter.
*
* @return string
* Returns a brief translated description of the formatter.
*/
protected function getDescription() {
return $this
->t('Present long text in a shortened area and include links to expand the text to full height, and collapse it back again.');
}
/**
* {@inheritdoc}
*/
public function settingsForm(array $form, FormStateInterface $formState) {
//
// Start with the parent form.
$elements = parent::settingsForm($form, $formState);
$elements['#attached'] = [
'library' => [
'formatter_suite/formatter_suite.settings',
],
];
// Add branding.
$elements = [];
$elements = Branding::addFieldFormatterBranding($elements);
$elements['#attached']['library'][] = 'formatter_suite/formatter_suite.fieldformatter';
$elements['description'] = [
'#type' => 'html_tag',
'#tag' => 'div',
'#value' => $this
->getDescription(),
'#weight' => -1000,
'#attributes' => [
'class' => [
'formatter_suite-settings-description',
],
],
];
// Add each of the values.
$elements['collapsedHeight'] = [
'#type' => 'textfield',
'#title' => $this
->t('Collapsed height'),
'#size' => 10,
'#default_value' => $this
->getSetting('collapsedHeight'),
'#description' => $this
->t("Text height when collapsed. Use CSS units (e.g. '200px', '40pt', '8em'). Empty or zero value disables."),
'#attributes' => [
'autocomplete' => 'off',
'autocapitalize' => 'none',
'spellcheck' => 'false',
'autocorrect' => 'off',
],
];
$elements['collapseButtonLabel'] = [
'#type' => 'textfield',
'#title' => $this
->t('Collapse link label'),
'#size' => 10,
'#maxlength' => 128,
'#default_value' => $this
->getSetting('collapseButtonLabel'),
];
$elements['expandButtonLabel'] = [
'#type' => 'textfield',
'#title' => $this
->t('Expand link label'),
'#size' => 10,
'#maxlength' => 128,
'#default_value' => $this
->getSetting('expandButtonLabel'),
];
$elements['animationDuration'] = [
'#type' => 'number',
'#title' => $this
->t('Animation duration'),
'#size' => 10,
'#default_value' => $this
->getSetting('animationDuration'),
'#description' => $this
->t('Animation time in milliseconds (e.g. 500 = 1/2 second). Empty or zero value disables animation.'),
];
return $elements;
}
/*---------------------------------------------------------------------
*
* View.
*
*---------------------------------------------------------------------*/
/**
* {@inheritdoc}
*/
public function viewElements(FieldItemListInterface $items, $langCode) {
//
// The $items array has a list of items to format. We need to return
// an array with identical indexing and corresponding render elements
// for those items.
if ($items
->isEmpty() === TRUE) {
return [];
}
// Get current settings.
$collapsedHeight = $this
->getSetting('collapsedHeight');
$animationDuration = $this
->getSetting('animationDuration');
$collapseButtonLabel = $this
->getSetting('collapseButtonLabel');
$expandButtonLabel = $this
->getSetting('expandButtonLabel');
// Security: The button labels are entered by an administrator.
// They may legitimately include HTML entities and minor HTML, but
// they should not include dangerous HTML. For instance, it is
// legitimate to include <span class="blah"> to style the label,
// or to include <img src="blah"> to add an icon image. However,
// it is not legitimate to add <style> or <script>.
//
// So, Xss::filterAdmin() is used here to get rid of the most
// dangerous HTML, like <style> and <script>.
//
// We'd like the admin-entered text to be translated, if a site
// is using that Drupal feature. However, simply calling t() will
// not quite work. Drupal.org builds translatable text tables by
// scanning the source code for calls to t() with literal strings.
// Since the admin-entered button label text here is not a literal
// string, it will not be found by that scan. This means it will
// not be in automatically-generated translation tables and t()
// will not necessarily do anything.
//
// Calling t() anyway will still do the translation table lookup.
// If a site has MANUALLY entered the text into their own translation
// tables, then translation will take place. Otherwise the text will
// be used as-is.
//
// We'd like to call $this->t() here to do the translation, but the
// various Drupal style checkers complain, even though this is a
// legitimate use. To avoid those complaints, we get the string
// translator from the StringTranslationTrait included in the
// FormatterBase parent class. Calling the translate() method
// directly dodges the style checkers.
$translator = $this
->getStringTranslation();
$collapseButtonLabel = $translator
->translate(Xss::filterAdmin($collapseButtonLabel));
$expandButtonLabel = $translator
->translate(Xss::filterAdmin($expandButtonLabel));
// Security: The animation duration is entered by an administrator.
// It should be a simple integer, with no other characters, HTML, or
// HTML entities.
//
// By parsing it as an integer, we ignore anything else and remove
// any security issues.
$animationDuration = intval($animationDuration);
// Security: The collapse height is entered by an administrator.
// It should be a number followed by CSS units, such as "px", "pt",
// or "em". It should not contain HTML or HTML entities.
//
// If integer parsing of the string yields a zero, then the string
// is assumed to be empty or invalid and collapsing is disabled.
// Otherwise the string is santized using an Html escape filter
// that escapes all HTML and HTML entities. If the admin enters these,
// the resulting string is not likely to work as a collapse height
// and the Javascript will not get a meaningful result, but it will
// still be safe.
$collapsedHeight = Html::escape($collapsedHeight);
$hasCollapsedHeight = TRUE;
if (empty($collapsedHeight) === TRUE || $collapsedHeight === "0" || (int) $collapsedHeight === 0) {
$hasCollapsedHeight = FALSE;
}
// If there is no collapsed height, show text full height.
$build = [];
if ($hasCollapsedHeight === FALSE) {
foreach ($items as $delta => $item) {
$build[$delta] = [
'#type' => 'processed_text',
'#text' => $item->value,
'#format' => $item->format,
'#langcode' => $item
->getLangcode(),
];
}
return $build;
}
// Nest the text, add buttons, and add a behavior script.
foreach ($items as $delta => $item) {
$build[$delta] = [
'#type' => 'container',
'#attributes' => [
'class' => [
'formatter_suite-text-with-expand-collapse-buttons',
],
],
'#attached' => [
'library' => [
'formatter_suite/formatter_suite.usage',
'formatter_suite/formatter_suite.text_with_expand_collapse_buttons',
],
],
'text' => [
'#type' => 'container',
'#attributes' => [
'class' => [
'formatter_suite-text',
],
'data-formatter_suite-collapsed-height' => $collapsedHeight,
'data-formatter_suite-animation-duration' => $animationDuration,
],
'processedtext' => [
'#type' => 'processed_text',
'#text' => $item->value,
'#format' => $item->format,
'#langcode' => $item
->getLangcode(),
],
],
'collapse' => [
'#type' => 'html_tag',
'#tag' => 'div',
'#value' => '<a href="#">' . $collapseButtonLabel . '</a>',
'#attributes' => [
'class' => [
'formatter_suite-text-collapse-button',
],
'style' => 'display: none',
],
],
'expand' => [
'#type' => 'html_tag',
'#tag' => 'div',
'#value' => '<a href="#">' . $expandButtonLabel . '</a>',
'#attributes' => [
'class' => [
'formatter_suite-text-expand-button',
],
'style' => 'display: none',
],
],
];
}
return $build;
}
}
Members
Name | Modifiers | Type | Description | Overrides |
---|---|---|---|---|
DependencySerializationTrait:: |
protected | property | An array of entity type IDs keyed by the property name of their storages. | |
DependencySerializationTrait:: |
protected | property | An array of service IDs keyed by property name used for serialization. | |
DependencySerializationTrait:: |
public | function | 1 | |
DependencySerializationTrait:: |
public | function | 2 | |
FormatterBase:: |
protected | property | The field definition. | |
FormatterBase:: |
protected | property | The label display setting. | |
FormatterBase:: |
protected | property |
The formatter settings. Overrides PluginSettingsBase:: |
|
FormatterBase:: |
protected | property | The view mode. | |
FormatterBase:: |
public static | function |
Creates an instance of the plugin. Overrides ContainerFactoryPluginInterface:: |
11 |
FormatterBase:: |
protected | function | Returns the value of a field setting. | |
FormatterBase:: |
protected | function | Returns the array of field settings. | |
FormatterBase:: |
public static | function |
Returns if the formatter can be used for the provided field. Overrides FormatterInterface:: |
14 |
FormatterBase:: |
public | function |
Allows formatters to load information for field values being displayed. Overrides FormatterInterface:: |
2 |
FormatterBase:: |
public | function |
Builds a renderable array for a fully themed field. Overrides FormatterInterface:: |
1 |
FormatterBase:: |
public | function |
Constructs a FormatterBase object. Overrides PluginBase:: |
11 |
MessengerTrait:: |
protected | property | The messenger. | 29 |
MessengerTrait:: |
public | function | Gets the messenger. | 29 |
MessengerTrait:: |
public | function | Sets the messenger. | |
PluginBase:: |
protected | property | Configuration information passed into the plugin. | 1 |
PluginBase:: |
protected | property | The plugin implementation definition. | 1 |
PluginBase:: |
protected | property | The plugin_id. | |
PluginBase:: |
constant | A string which is used to separate base plugin IDs from the derivative ID. | ||
PluginBase:: |
public | function |
Gets the base_plugin_id of the plugin instance. Overrides DerivativeInspectionInterface:: |
|
PluginBase:: |
public | function |
Gets the derivative_id of the plugin instance. Overrides DerivativeInspectionInterface:: |
|
PluginBase:: |
public | function |
Gets the definition of the plugin implementation. Overrides PluginInspectionInterface:: |
3 |
PluginBase:: |
public | function |
Gets the plugin_id of the plugin instance. Overrides PluginInspectionInterface:: |
|
PluginBase:: |
public | function | Determines if the plugin is configurable. | |
PluginSettingsBase:: |
protected | property | Whether default settings have been merged into the current $settings. | |
PluginSettingsBase:: |
protected | property | The plugin settings injected by third party modules. | |
PluginSettingsBase:: |
public | function |
Calculates dependencies for the configured plugin. Overrides DependentPluginInterface:: |
6 |
PluginSettingsBase:: |
public | function |
Returns the value of a setting, or its default value if absent. Overrides PluginSettingsInterface:: |
|
PluginSettingsBase:: |
public | function |
Returns the array of settings, including defaults for missing settings. Overrides PluginSettingsInterface:: |
|
PluginSettingsBase:: |
public | function |
Gets the list of third parties that store information. Overrides ThirdPartySettingsInterface:: |
|
PluginSettingsBase:: |
public | function |
Gets the value of a third-party setting. Overrides ThirdPartySettingsInterface:: |
|
PluginSettingsBase:: |
public | function |
Gets all third-party settings of a given module. Overrides ThirdPartySettingsInterface:: |
|
PluginSettingsBase:: |
protected | function | Merges default settings values into $settings. | |
PluginSettingsBase:: |
public | function |
Informs the plugin that some configuration it depends on will be deleted. Overrides PluginSettingsInterface:: |
3 |
PluginSettingsBase:: |
public | function |
Sets the value of a setting for the plugin. Overrides PluginSettingsInterface:: |
|
PluginSettingsBase:: |
public | function |
Sets the settings for the plugin. Overrides PluginSettingsInterface:: |
|
PluginSettingsBase:: |
public | function |
Sets the value of a third-party setting. Overrides ThirdPartySettingsInterface:: |
|
PluginSettingsBase:: |
public | function |
Unsets a third-party setting. Overrides ThirdPartySettingsInterface:: |
|
StringTranslationTrait:: |
protected | property | The string translation service. | 1 |
StringTranslationTrait:: |
protected | function | Formats a string containing a count of items. | |
StringTranslationTrait:: |
protected | function | Returns the number of plurals supported by a given language. | |
StringTranslationTrait:: |
protected | function | Gets the string translation service. | |
StringTranslationTrait:: |
public | function | Sets the string translation service to use. | 2 |
StringTranslationTrait:: |
protected | function | Translates a string to the current language or to a given language. | |
TextWithExpandCollapseButtonsFormatter:: |
public static | function |
Defines the default settings for this plugin. Overrides PluginSettingsBase:: |
|
TextWithExpandCollapseButtonsFormatter:: |
protected | function | Returns a brief description of the formatter. | |
TextWithExpandCollapseButtonsFormatter:: |
public | function |
Returns a form to configure settings for the formatter. Overrides FormatterBase:: |
|
TextWithExpandCollapseButtonsFormatter:: |
public | function |
Returns a short summary for the current formatter settings. Overrides FormatterBase:: |
|
TextWithExpandCollapseButtonsFormatter:: |
public | function |
Builds a renderable array for a field value. Overrides FormatterInterface:: |