From 2e4cc57e8f2cf6c0e2b78ae82c31aee2899cdd3d Mon Sep 17 00:00:00 2001 From: Matthias Schmidt Date: Mon, 7 Oct 2019 18:12:07 +0200 Subject: [PATCH] Add SuffixFormFieldContainer Close #3087 --- .../templates/__suffixFormFieldContainer.tpl | 57 ++++++ syncTemplates.json | 1 + .../templates/__suffixFormFieldContainer.tpl | 57 ++++++ .../Form/Builder/Container/SuffixFormField.js | 68 +++++++ .../SuffixFormFieldContainer.class.php | 171 ++++++++++++++++++ .../style/bootstrap/mixin/dropdownMenu.scss | 8 + 6 files changed, 362 insertions(+) create mode 100644 com.woltlab.wcf/templates/__suffixFormFieldContainer.tpl create mode 100644 wcfsetup/install/files/acp/templates/__suffixFormFieldContainer.tpl create mode 100644 wcfsetup/install/files/js/WoltLabSuite/Core/Form/Builder/Container/SuffixFormField.js create mode 100644 wcfsetup/install/files/lib/system/form/builder/container/SuffixFormFieldContainer.class.php diff --git a/com.woltlab.wcf/templates/__suffixFormFieldContainer.tpl b/com.woltlab.wcf/templates/__suffixFormFieldContainer.tpl new file mode 100644 index 0000000000..731d1c3a4e --- /dev/null +++ b/com.woltlab.wcf/templates/__suffixFormFieldContainer.tpl @@ -0,0 +1,57 @@ +
getField()->getClasses()|empty} class="{implode from=$element->getField()->getClasses() item='class' glue=' '}{$class}{/implode}"{/if}{* + *}{foreach from=$element->getField()->getAttributes() key='attributeName' item='attributeValue'} {$attributeName}="{$attributeValue}"{/foreach}{* + *}{if !$element->getField()->checkDependencies()} style="display: none;"{/if}{* +*}> +
{if $element->getLabel() !== null}{/if}
+
+
+ {@$element->getField()->getFieldHtml()} + + {if $element->getSuffixField() !== null && $element->getSuffixField()->isAvailable()} + {if !$element->suffixHasSelectableOptions()} + {if $element->getSuffixLabel() !== ''} + {@$element->getSuffixLabel()} + {/if} + {else} + + {@$element->getSelectedSuffixOption()[label]} + + + + + + {include file='__formFieldDependencies' field=$element->getSuffixField()} + {include file='__formFieldDataHandler' field=$element->getSuffixField()} + {/if} + {/if} +
+ + {if $element->getDescription() !== null} + {@$element->getDescription()} + {/if} + + {include file='__formFieldErrors' field=$element->getField()} + + {if $element->getSuffixField() !== null && $element->getSuffixField()->isAvailable()} + {foreach from=$element->getSuffixField()->getValidationErrors() item='validationError'} + {@$validationError->getHtml()} + {/foreach} + {/if} + + {include file='__formFieldDependencies' field=$element->getField()} + {include file='__formFieldDataHandler' field=$element->getField()} +
+
+ +{if $element->getSuffixField() !== null && $element->getSuffixField()->isAvailable() && !$element->getSuffixField()->isImmutable() && $element->suffixHasSelectableOptions()} + +{/if} diff --git a/syncTemplates.json b/syncTemplates.json index 24c8f421b2..11db7532e8 100644 --- a/syncTemplates.json +++ b/syncTemplates.json @@ -36,6 +36,7 @@ "__rowFormFieldContainer", "__singleMediaSelectionFormField", "__singleSelectionFormField", + "__suffixFormFieldContainer", "__tabFormContainer", "__tabMenuFormContainer", "__tabTabMenuFormContainer", diff --git a/wcfsetup/install/files/acp/templates/__suffixFormFieldContainer.tpl b/wcfsetup/install/files/acp/templates/__suffixFormFieldContainer.tpl new file mode 100644 index 0000000000..c6ea9e6356 --- /dev/null +++ b/wcfsetup/install/files/acp/templates/__suffixFormFieldContainer.tpl @@ -0,0 +1,57 @@ +
getField()->getClasses()|empty} class="{implode from=$element->getField()->getClasses() item='class' glue=' '}{$class}{/implode}"{/if}{* + *}{foreach from=$element->getField()->getAttributes() key='attributeName' item='attributeValue'} {$attributeName}="{$attributeValue}"{/foreach}{* + *}{if !$element->getField()->checkDependencies()} style="display: none;"{/if}{* +*}> +
{if $element->getLabel() !== null}{/if}
+
+
+ {@$element->getField()->getFieldHtml()} + + {if $element->getSuffixField() !== null && $element->getSuffixField()->isAvailable()} + {if !$element->suffixHasSelectableOptions()} + {if $element->getSuffixLabel() !== ''} + {@$element->getSuffixLabel()} + {/if} + {else} + + {@$element->getSelectedSuffixOption()[label]} + + + + + + {include file='__formFieldDependencies' field=$element->getSuffixField()} + {include file='__formFieldDataHandler' field=$element->getSuffixField()} + {/if} + {/if} +
+ + {if $element->getDescription() !== null} + {@$element->getDescription()} + {/if} + + {include file='__formFieldErrors' field=$element->getField()} + + {if $element->getSuffixField() !== null && $element->getSuffixField()->isAvailable()} + {foreach from=$element->getSuffixField()->getValidationErrors() item='validationError'} + {@$validationError->getHtml()} + {/foreach} + {/if} + + {include file='__formFieldDependencies' field=$element->getField()} + {include file='__formFieldDataHandler' field=$element->getField()} +
+
+ +{if $element->getSuffixField() !== null && $element->getSuffixField()->isAvailable() && !$element->getSuffixField()->isImmutable() && $element->suffixHasSelectableOptions()} + +{/if} diff --git a/wcfsetup/install/files/js/WoltLabSuite/Core/Form/Builder/Container/SuffixFormField.js b/wcfsetup/install/files/js/WoltLabSuite/Core/Form/Builder/Container/SuffixFormField.js new file mode 100644 index 0000000000..f945113615 --- /dev/null +++ b/wcfsetup/install/files/js/WoltLabSuite/Core/Form/Builder/Container/SuffixFormField.js @@ -0,0 +1,68 @@ +/** + * Handles the dropdowns of form fields with a suffix. + * + * @author Matthias Schmidt + * @copyright 2001-2019 WoltLab GmbH + * @license GNU Lesser General Public License + * @module WoltLabSuite/Core/Form/Builder/Container/SuffixFormField + * @since 5.2 + */ +define(['EventHandler', 'Ui/SimpleDropdown'], function(EventHandler, UiSimpleDropdown) { + "use strict"; + + /** + * @constructor + */ + function PrefixSuffixFormFieldContainer(formId, suffixFieldId) { + this._formId = formId; + + this._suffixField = elById(suffixFieldId); + this._suffixDropdownMenu = UiSimpleDropdown.getDropdownMenu(suffixFieldId + '_dropdown'); + this._suffixDropdownToggle = elByClass('dropdownToggle', UiSimpleDropdown.getDropdown(suffixFieldId + '_dropdown'))[0]; + + var listItems = this._suffixDropdownMenu.children; + for (var i = 0, length = listItems.length; i < length; i++) { + listItems[i].addEventListener('click', this._changeSuffixSelection.bind(this)); + } + + EventHandler.add('WoltLabSuite/Core/Form/Builder/Manager', 'afterUnregisterForm', this._destroyDropdown.bind(this)); + }; + PrefixSuffixFormFieldContainer.prototype = { + /** + * Handles changing the suffix selection. + * + * @param {Event} event + */ + _changeSuffixSelection: function(event) { + if (event.currentTarget.classList.contains('disabled')) { + return; + } + + var listItems = this._suffixDropdownMenu.children; + for (var i = 0, length = listItems.length; i < length; i++) { + if (listItems[i] === event.currentTarget) { + listItems[i].classList.add('active'); + } + else { + listItems[i].classList.remove('active'); + } + } + + this._suffixField.value = elData(event.currentTarget, 'value'); + this._suffixDropdownToggle.innerHTML = elData(event.currentTarget, 'label') + ' '; + }, + + /** + * Destorys the suffix dropdown if the parent form is unregistered. + * + * @param {object} data event data + */ + _destroyDropdown: function(data) { + if (data.formId === this._formId) { + UiSimpleDropdown.destroy(this._suffixDropdownMenu.id); + } + } + }; + + return PrefixSuffixFormFieldContainer; +}); diff --git a/wcfsetup/install/files/lib/system/form/builder/container/SuffixFormFieldContainer.class.php b/wcfsetup/install/files/lib/system/form/builder/container/SuffixFormFieldContainer.class.php new file mode 100644 index 0000000000..545aa3d0fb --- /dev/null +++ b/wcfsetup/install/files/lib/system/form/builder/container/SuffixFormFieldContainer.class.php @@ -0,0 +1,171 @@ + + * @package WoltLabSuite\Core\System\Form\Builder\Container + * @since 5.2 + */ +class SuffixFormFieldContainer extends FormContainer { + /** + * form field to which the suffix selection is added + * @var IFormField + */ + protected $field; + + /** + * selection form field containing the suffix options + * @var ISelectionFormField + */ + protected $suffixField; + + /** + * Sets the form field to which the suffix selection is added and returns this field. + * + * @param IFormField $formField + * @return $this + */ + public function field(IFormField $formField) { + if ($this->field !== null) { + throw new \BadMethodCallException('Field has already been set.'); + } + + $this->field = $formField; + $this->appendChild($formField); + + return $this; + } + + /** + * Returns the form field to which the suffix selection is added. + * + * @return IFormField + */ + public function getField() { + if ($this->field === null) { + throw new \BadMethodCallException('Field has not been set yet.'); + } + + return $this->field; + } + + /** + * @inheritDoc + */ + public function getHtml() { + return WCF::getTPL()->fetch('__suffixFormFieldContainer', 'wcf', [ + 'element' => $this + ]); + } + + /** + * Returns the intial option of the suffix selection dropdown. + * + * @return string + * @throws \BadMethodCallException if no suffix field is set or has no options + */ + public function getSelectedSuffixOption() { + if ($this->getSuffixField() === null) { + throw new \BadMethodCallException('There is no suffix field for which a label could be determined.'); + } + if (empty($this->getSuffixField()->getOptions())) { + throw new \BadMethodCallException('The suffix field has no options.'); + } + + foreach ($this->getSuffixField()->getNestedOptions() as $option) { + if ($this->getSuffixField()->getValue() === null) { + if ($option['isSelectable']) { + return $option; + } + } + else if ($option['value'] == $this->getSuffixField()->getValue()) { + return $option; + } + } + + throw new \RuntimeException('Cannot determine selected suffix option.'); + } + + /** + * Returns the selection form field containing the suffix options. + * + * @return ISelectionFormField + */ + public function getSuffixField() { + return $this->suffixField; + } + + /** + * Returns the label used for the suffix selection if the field has no selectable options + * or is immutable. + * + * @return string + */ + public function getSuffixLabel() { + if ($this->getSuffixField() === null) { + throw new \BadMethodCallException('There is no suffix field for which a label could be determined.'); + } + + if (empty($this->getSuffixField()->getOptions())) { + return ''; + } + + if (isset($this->getSuffixField()->getOptions()[$this->getSuffixField()->getValue()])) { + return $this->getSuffixField()->getOptions()[$this->getSuffixField()->getValue()]; + } + + return ''; + } + + /** + * Sets the selection form field containing the suffix options. + * + * @param ISelectionFormField $formField + * @return $this + * @throws \BadMethodCallException if no suffix field is set + */ + public function suffixField(ISelectionFormField $formField) { + if ($this->suffixField !== null) { + throw new \BadMethodCallException('Suffix field has already been set.'); + } + + $this->suffixField = $formField; + $this->appendChild($formField); + + return $this; + } + + /** + * Returns `true` if the suffix selection has any selectable options. + * + * @return bool + */ + public function suffixHasSelectableOptions() { + if ($this->getSuffixField() === null) { + return false; + } + + if ($this->getSuffixField() instanceof IImmutableFormField && $this->getSuffixField()->isImmutable()) { + return false; + } + + foreach ($this->getSuffixField()->getNestedOptions() as $option) { + if ($option['isSelectable']) { + return true; + } + } + + return false; + } +} diff --git a/wcfsetup/install/files/style/bootstrap/mixin/dropdownMenu.scss b/wcfsetup/install/files/style/bootstrap/mixin/dropdownMenu.scss index 77cfc6ae70..8b02bcbbc6 100644 --- a/wcfsetup/install/files/style/bootstrap/mixin/dropdownMenu.scss +++ b/wcfsetup/install/files/style/bootstrap/mixin/dropdownMenu.scss @@ -66,6 +66,14 @@ } } + &.disabled { + color: $wcfContentDimmedText; + + > span { + cursor: not-allowed !important; + } + } + > a, > span { clear: both; -- 2.20.1